Browse Source

system: add CondVar

x 2 years ago
parent
commit
61b35c2b79
2 changed files with 55 additions and 2 deletions
  1. 47 0
      src/system/condvar.rs
  2. 8 2
      src/system/mod.rs

+ 47 - 0
src/system/condvar.rs

@@ -0,0 +1,47 @@
+use std::{
+    future::Future,
+    pin::Pin,
+    sync::atomic::{AtomicBool, Ordering},
+    task::{Context, Poll},
+};
+
+/// Condition variable which allows a task to block until woken up
+pub struct CondVar {
+    is_active: AtomicBool,
+}
+
+impl CondVar {
+    pub fn new() -> Self {
+        Self { is_active: AtomicBool::new(false) }
+    }
+
+    /// Wakeup the waiting task. Subsequent calls to this do nothing until `wait()` is called.
+    pub fn notify(&mut self) {
+        self.is_active.store(true, Ordering::Relaxed)
+    }
+
+    /// Reset the condition variable and wait for a notification
+    pub async fn wait(&self) -> CondVarWait<'_> {
+        self.is_active.store(false, Ordering::SeqCst);
+        CondVarWait { condvar: self }
+    }
+
+    fn is_active(&self) -> bool {
+        self.is_active.load(Ordering::Relaxed)
+    }
+}
+
+pub struct CondVarWait<'a> {
+    condvar: &'a CondVar,
+}
+
+impl<'a> Future for CondVarWait<'a> {
+    type Output = ();
+
+    fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
+        match self.condvar.is_active() {
+            true => Poll::Ready(()),
+            false => Poll::Pending,
+        }
+    }
+}

+ 8 - 2
src/system/mod.rs

@@ -16,9 +16,13 @@
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
 
-use std::time::Duration;
+use std::{sync::Arc, time::Duration};
 
-use smol::Timer;
+use smol::{Executor, Timer};
+
+/// Condition variable which allows a task to block until woken up
+pub mod condvar;
+pub use condvar::CondVar;
 
 /// Implementation of async background task spawning which are stoppable
 /// using channel signalling.
@@ -33,6 +37,8 @@ pub use subscriber::{Subscriber, SubscriberPtr, Subscription};
 pub mod timeout;
 pub use timeout::io_timeout;
 
+pub type ExecutorPtr = Arc<Executor<'static>>;
+
 /// Sleep for any number of seconds.
 pub async fn sleep(seconds: u64) {
     Timer::after(Duration::from_secs(seconds)).await;