2.6 KiB
runloop
This crate provides a cancelable RunLoop
to simplify writing non-blocking
polling threads.
Usage
The closure passed to RunLoop::new()
or RunLoop::new_with_timeout()
will be
called once and is executed in the newly spawned thread. It should periodically
check, via the given callback argument named alive
in the below examples,
whether the runloop was requested to terminate.
RunLoop::alive()
allows the owning thread to check whether the runloop is
still alive. This can be useful for debugging (e.g. assertions) or early
returns on failure in the passed closure.
RunLoop::cancel()
will request the runloop to terminate. If the runloop is
still active it will join the thread and block. If the runloop already
terminated on its own this will be a no-op.
Example: An endless runloop
A runloop does not have to terminate on its own, it can wait until the
cancel()
method is called.
// This runloop runs until we stop it.
let rloop = RunLoop::new(|alive| {
while alive() { /* endless loop */ }
})?;
// Loop a few times.
thread::sleep_ms(500);
assert!(rloop.alive());
// This will cause `alive()` to return false
// and block until the thread was joined.
rloop.cancel();
Example: A runloop with a timeout
Creating a runloop via new_with_timeout()
ensures that alive()
returns
false
after the given duration.
// This runloop will time out after 10ms.
let rloop = RunLoop::new_with_timeout(|alive| {
while alive() { /* endless loop */ }
}, 10)?;
// Wait for the timeout.
while rloop.alive() { /* loop */ }
// This won't block anymore, it's a no-op.
// The runloop has already terminated.
rloop.cancel();
Example: A runloop with channels
As a runloop will run the given closure in a newly spawned thread it requires channels and similar utilities to communicate back to the owning thread.
let (tx, rx) = channel();
// This runloop will send a lot of numbers.
let rloop = RunLoop::new(move |alive| {
let mut counter = 0u64;
while alive() {
tx.send(counter).unwrap();
counter += 1;
}
})?;
// Wait until we receive a specific number.
while rx.recv().unwrap() < 50 { /* loop */ }
// We've seen enough.
rloop.cancel();
License
runloop
is distributed under the terms of the Mozilla Public License, v. 2.0.
See LICENSE for details.