~thatonelutenist/actm

5f70c87b5053b46eceb91729c31e4dcb4d133b09 — Nathan McCarty 1 year, 9 months ago 2a78168
feat: Waiter/Trigger

Add Waiter and Trigger utility types, for signaling event completion,
possibly across a sync/async boundary.
3 files changed, 47 insertions(+), 1 deletions(-)

M src/lib.rs
M src/types.rs
A src/types/waiter.rs
M src/lib.rs => src/lib.rs +1 -1
@@ 34,7 34,7 @@ pub mod prelude {
        executor::Executor,
        sync_actor,
        traits::{Actor, Event, EventConsumer, EventProducer},
        types::CompletionToken,
        types::{CompletionToken, Trigger, Waiter},
        util::{AsyncActor, AsyncActorError, SyncActor, SyncActorError, WrappedEvent},
        wrapped_event,
    };

M src/types.rs => src/types.rs +4 -0
@@ 16,6 16,10 @@ use once_cell::sync::Lazy;

use super::traits::{Event, EventConsumer};

mod waiter;

pub use waiter::{Trigger, Waiter};

/// Utility type for generalized errors
pub enum Either<A, B> {
    /// The happy path or preferred option

A src/types/waiter.rs => src/types/waiter.rs +42 -0
@@ 0,0 1,42 @@
//! Utility type for waiting on an event to happen, possibly across a sync/async boundary.

use flume::{Receiver, Sender};

/// Utility type for waiting on an event to happen, possibly across a sync/async boundary.
pub struct Waiter {
    /// Internal channel
    recv: Receiver<()>,
}

/// Utility type for signaling an event has happend, possibly across a sync/async boundary.
pub struct Trigger {
    /// Internal channel
    send: Sender<()>,
}

impl Waiter {
    /// Create a new `Waiter`/`Trigger` pair
    pub fn new() -> (Waiter, Trigger) {
        let (send, recv) = flume::bounded(1);
        (Waiter { recv }, Trigger { send })
    }

    /// Asynchronously wait for the event, returning `true` if the event happened, or `false` if the
    /// `Trigger` was dropped before completion
    pub async fn wait(self) -> bool {
        self.recv.recv_async().await.is_ok()
    }

    /// Synchronously wait for the event, returning `true` if the event happened, or `false` if the
    /// `Trigger` was dropped before completion
    pub fn wait_sync(self) -> bool {
        self.recv.recv().is_ok()
    }
}

impl Trigger {
    /// Consume the trigger and signal the waiter
    pub fn trigger(self) {
        let _ = self.send.send(());
    }
}