Editor's note — this example was created before Rust 1.0 and the specific types have changed or been removed since then. The general question and concept remains valid.
I have spawned a thread with an infinite loop and timer inside.
thread::spawn(|| {
let mut timer = Timer::new().unwrap();
let periodic = timer.periodic(Duration::milliseconds(200));
loop {
periodic.recv();
// Do my work here
}
});
After a time based on some conditions, I need to terminate this thread from another part of my program. In other words, I want to exit from the infinite loop. How can I do this correctly? Additionally, how could I to suspend this thread and resume it later?
I tried to use a global unsafe flag to break the loop, but I think this solution does not look nice.
For both terminating and suspending a thread you can use channels.
Terminated externally
On each iteration of a worker loop, we check if someone notified us through a channel. If yes or if the other end of the channel has gone out of scope we break the loop.
Suspending and resuming
We use
recv()
which suspends the thread until something arrives on the channel. In order to resume the thread, you need to send something through the channel; the unit value()
in this case. If the transmitting end of the channel is dropped,recv()
will returnErr(())
- we use this to exit the loop.Other tools
Channels are the easiest and the most natural (IMO) way to do these tasks, but not the most efficient one. There are other concurrency primitives which you can find in the
std::sync
module. They belong to a lower level than channels but can be more efficient in particular tasks.The ideal solution would be a
Condvar
. You can usewait_timeout
in thestd::sync module
, as pointed out by @Vladimir Matveev.This is the example from the documentation: