# `minuteurs` A very lightweight crate to give users control as fine grained as possible over threads' execution over time at a minimal cost. # Deadlines A `Deadline` allow users to block a thread's execution until a certain amount of time passed since the creation of the deadline unless the deadline already expired. It comes in two flavors: * `Deadline::once()` returns a `Deadline` that can be triggered only once meaning that once such a deadline expires, it can never block anymore. * `Deadline::repeat()` returns a `Deadline` that can be triggered multiple times. In this case, if too much time have passed between two `Deadline::wait()` calls, it will try to catch up. ## Examples ### Basic example ```rust use std::time::{Duration, Instant}; use minuteurs::Deadline; // Create a new deadline of 1 second. let mut deadline = Deadline::once(Duration::from_secs(1)); let mut now = Instant::now(); // This sleep represents some heavy computation. std::thread::sleep(Duration::from_millis(750)); // Blocks the thread if less than 1 second have passed since the deadline's creation. deadline.wait(); // Until this point, at least 1 second have passed no matter what happened // between the creation and the wait. let elapsed = now.elapsed(); assert!(elapsed > Duration::from_secs(1)); println!("elapsed: {elapsed:?}"); ``` Possible output: ``` elapsed: 1.00010838s ``` ### Using a deadline to synchronize multiple threads ```rust use std::time::{Duration, Instant}; use minuteurs::Deadline; // Create a repeatable deadline of 1 second. let mut deadline = Deadline::repeat(Duration::from_secs(1)); let now = Instant::now(); // Spawn two threads with the same deadline. // They should prints approximatively every 1s. let thread1 = std::thread::spawn(move || { for _ in 0..5 { deadline.wait(); let elapsed = now.elapsed(); println!("thread1 ticked at {elapsed:?}",) } }); let thread2 = std::thread::spawn(move || { for _ in 0..5 { deadline.wait(); let elapsed = now.elapsed(); println!("thread2 ticked at {elapsed:?}",) } }); // Obligatory clean up. let _ = thread1.join(); let _ = thread2.join(); ``` Possible output: ``` thread2 ticked at 1.000112249s thread1 ticked at 1.000112289s thread2 ticked at 2.000107337s thread1 ticked at 2.0001086s thread2 ticked at 3.000101815s thread1 ticked at 3.000641802s thread1 ticked at 4.000100891s thread2 ticked at 4.000100911s thread2 ticked at 5.000106159s thread1 ticked at 5.000112471s ``` # Timer A `Timer` differs from a repeatable `Deadline` in that a timer is specifically build to synchronize multiple threads on periodic events and are more precise and better optimized. Usually, the timer runs in a loop in its own thread, while the watchers are passed in another threads. The timer ticks periodically and notifies one or more watchers of the tick. ## Example ```rust use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; use std::time::{Duration, Instant}; use minuteurs::Timer; // Create a timer that ticks every seconds and get a watcher from it. let mut timer = Timer::new(Duration::from_secs(1)); let mut watcher1 = timer.watcher(); // Watchers are clonable and cloned ones are associated to the orignal watcher's timer. // The timer will then notify the watcher2 as well. let mut watcher2 = watcher1.clone(); let now = Instant::now(); let stop = Arc::new(AtomicBool::default()); // Spawn two threads. // They should prints approximatively every 1s. let stop_clone = Arc::clone(&stop); let thread1 = std::thread::spawn(move || { while !stop_clone.load(Ordering::SeqCst) { if watcher1.has_ticked() { let elapsed = now.elapsed(); println!("thread1 ticked at {elapsed:?}",) } } }); let stop_clone = Arc::clone(&stop); let thread2 = std::thread::spawn(move || { while !stop_clone.load(Ordering::SeqCst) { if watcher2.has_ticked() { let elapsed = now.elapsed(); println!("thread2 ticked at {elapsed:?}",) } } }); for _ in 0..5 { timer.tick(); } stop.store(true, Ordering::SeqCst); // Obligatory clean up. let _ = thread1.join(); let _ = thread2.join(); ``` Possible output: ```text thread1 ticked at 1.00087579s thread2 ticked at 1.000878295s thread1 ticked at 2.000870603s thread2 ticked at 2.000873087s thread2 ticked at 3.000875413s thread1 ticked at 3.000876254s thread2 ticked at 4.000874293s thread1 ticked at 4.000875034s thread2 ticked at 5.000874695s thread1 ticked at 5.000875316s ``` # License Licensed under the terms of MIT license. See [LICENSE](LICENSE) for details.