#thread #timeout #polling #non-blocking #optional #cancelable

runloop

Cancelable non-blocking polling threads (with optional timeouts)

1 unstable release

Uses old Rust 2015

0.1.0 Sep 16, 2017

#735 in Concurrency

Download history 18095/week @ 2023-11-20 13673/week @ 2023-11-27 14912/week @ 2023-12-04 13754/week @ 2023-12-11 9063/week @ 2023-12-18 3030/week @ 2023-12-25 11591/week @ 2024-01-01 13241/week @ 2024-01-08 15262/week @ 2024-01-15 15023/week @ 2024-01-22 20547/week @ 2024-01-29 11036/week @ 2024-02-05 22695/week @ 2024-02-12 19262/week @ 2024-02-19 26770/week @ 2024-02-26 25490/week @ 2024-03-04

94,429 downloads per month
Used in 7 crates (2 directly)

MPL-2.0 license

9KB
115 lines

runloop Crates.io Build Status 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.

// 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.

No runtime deps