88 lines
2.6 KiB
Markdown
88 lines
2.6 KiB
Markdown
# runloop [](https://crates.io/crates/runloop) [](https://travis-ci.org/ttaubert/rust-runloop) [](LICENSE)
|
|
|
|
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.
|
|
|
|
```rust
|
|
// 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.
|
|
|
|
```rust
|
|
// 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.
|
|
|
|
```rust
|
|
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](LICENSE) for details.
|