waitable/
lib.rs

1//! This crate consists of a single struct, [`Waitable`] that holds a value
2//! which can be get, set and waited upon.
3
4use parking_lot::{Condvar, Mutex};
5
6/// A waitable variable
7///
8/// This struct is essentially the `Mutex` and `Condvar` tuple documented in
9/// [`parking_lot::Condvar`], presented in an easy-to-use form.
10///
11/// [`parking_lot::Condvar`]: `parking_lot::Condvar#examples`
12#[derive(Debug)]
13pub struct Waitable<T> {
14	value: Mutex<T>,
15	condvar: Condvar,
16}
17
18impl<T> Waitable<T> {
19	/// Create a new waitable variable
20	///
21	/// # Examples
22	///
23	/// ```
24	/// use waitable::Waitable;
25	///
26	/// let w = Waitable::new(0);
27	/// ```
28	pub fn new(value: T) -> Self {
29		Self {
30			value: Mutex::new(value),
31			condvar: Condvar::new(),
32		}
33	}
34
35	/// Sets the value of the waitable
36	///
37	/// This function wakes up ([`notify_all`]) all waiters so that they may
38	/// check their waiting conditions and return if appropriate.
39	///
40	/// [`notify_all`]: parking_lot::Condvar::notify_all
41	pub fn set(&self, value: T) {
42		let mut vg = self.value.lock();
43		*vg = value;
44		self.condvar.notify_all();
45	}
46
47	/// Waits until a condition is satisfied
48	///
49	/// This function will block the current thread until the predicate
50	/// specified by `cond` returns `true` on the current value of the
51	/// Waitable.
52	///
53	/// If `cond` initially returns `true`, no blocking is done.
54	pub fn wait_cond<F: Fn(&T) -> bool>(&self, cond: F) {
55		let mut vg = self.value.lock();
56		while !cond(&*vg) {
57			self.condvar.wait(&mut vg);
58		}
59	}
60}
61
62impl<T: Copy> Waitable<T> {
63	/// Gets the value in the waitable
64	pub fn get(&self) -> T {
65		*self.value.lock()
66	}
67}
68
69impl<T: PartialEq> Waitable<T> {
70	/// Waits until the value of the waitable equals a certain value
71	///
72	/// This function is essentially equivalent to
73	/// `wait_cond(|val| val == value)`
74	pub fn wait(&self, value: &T) {
75		let mut vg = self.value.lock();
76		while &*vg != value {
77			self.condvar.wait(&mut vg);
78		}
79	}
80}
81
82impl<T: Default> Default for Waitable<T> {
83	/// Constructs a waitable containing the default value of the inner type
84	fn default() -> Self {
85		Self::new(T::default())
86	}
87}