tokio_condvar/
lib.rs

1use tokio::sync::{MutexGuard, Notify, RwLock, RwLockReadGuard, RwLockWriteGuard};
2
3#[cfg(feature = "parking_lot")]
4pub mod parking_lot;
5
6#[derive(Default)]
7pub struct Condvar {
8    inner: Notify,
9}
10
11impl Condvar {
12    pub fn new() -> Self {
13        Self::default()
14    }
15
16    /// Wake up all tasks currently waiting on this condition variable.
17    pub fn notify_all(&self) {
18        self.inner.notify_waiters();
19    }
20
21    /// Wake up exactly one task that is currently waiting on this condition variable.
22    ///
23    /// Note: If no task is currently waiting, this might lead to spurious wakeups in the future.
24    pub fn notify_one(&self) {
25        self.inner.notify_one();
26    }
27
28    /// Wait to be woken up while holding a lock
29    /// This function will automatically release the lock before waiting
30    /// and reacquires it after waking up
31    pub async fn wait<'a, T>(&self, guard: MutexGuard<'a, T>) -> MutexGuard<'a, T> {
32        let fut = self.inner.notified();
33        tokio::pin!(fut);
34        fut.as_mut().enable();
35
36        let mutex = MutexGuard::mutex(&guard);
37        drop(guard);
38
39        fut.await;
40        mutex.lock().await
41    }
42
43    /// Same as Self::wait but for a RwLockReadGuard
44    pub async fn rw_read_wait<'a, T>(
45        &self,
46        lock: &'a RwLock<T>,
47        guard: RwLockReadGuard<'a, T>,
48    ) -> RwLockReadGuard<'a, T> {
49        let fut = self.inner.notified();
50        tokio::pin!(fut);
51        fut.as_mut().enable();
52
53        drop(guard);
54
55        fut.await;
56        lock.read().await
57    }
58
59    /// Same as Self::wait but for a RwLockWriteGuard
60    pub async fn rw_write_wait<'a, T>(
61        &self,
62        lock: &'a RwLock<T>,
63        guard: RwLockWriteGuard<'a, T>,
64    ) -> RwLockWriteGuard<'a, T> {
65        let fut = self.inner.notified();
66        tokio::pin!(fut);
67        fut.as_mut().enable();
68
69        drop(guard);
70
71        fut.await;
72        lock.write().await
73    }
74}