future_bool/
lib.rs

1use std::sync::{
2    atomic::{AtomicBool, Ordering},
3    Arc,
4};
5use tokio::sync::Notify;
6
7/// A bool one can `await` the changes.
8#[derive(Clone)]
9pub struct FutureBool {
10    notify_true: Arc<Notify>,
11    notify_false: Arc<Notify>,
12    inner: Arc<AtomicBool>,
13}
14
15impl FutureBool {
16    /// Creates a new `FutureBool` with some initial value.
17    pub fn new(val: bool) -> Self {
18        Self {
19            notify_true: Arc::new(Notify::new()),
20            notify_false: Arc::new(Notify::new()),
21            inner: Arc::new(AtomicBool::new(val)),
22        }
23    }
24
25    /// Sets the `bool` value to `true`.
26    pub fn set(&self) {
27        self.inner.store(true, Ordering::Release);
28        self.notify_true.notify_waiters();
29    }
30
31    /// Sets the `bool` value to `false`.
32    pub fn unset(&self) {
33        self.inner.store(false, Ordering::Release);
34        self.notify_false.notify_waiters();
35    }
36
37    /// Returns the new value when it has changed.
38    pub async fn wait_change(&self) -> bool {
39        let val = self.inner.load(Ordering::Acquire);
40        if val {
41            self.notify_false.notified().await;
42        } else {
43            self.notify_true.notified().await;
44        }
45        !val
46    }
47
48    /// If the value is `true`, returns immidiately, otherwise waits until it's `true`.
49    pub async fn wait_true(&self) {
50        let val = self.inner.load(Ordering::Acquire);
51        if !val {
52            self.notify_true.notified().await;
53        }
54    }
55
56    /// If the value is `false`, returns immidiately, otherwise waits until it's `false`.
57    pub async fn wait_false(&self) {
58        let val = self.inner.load(Ordering::Acquire);
59        if val {
60            self.notify_false.notified().await;
61        }
62    }
63}