win-events 0.0.2

A poor attempt to implement WaitForMultipleObjects and the ManualReset, AutoReset and Pulse types
Documentation
use std::error::Error;
use std::sync::{Arc, MutexGuard};

use crate::waiters::waiter::Signaler;

/// Trait for each event type to implement
pub(crate) trait EventState: Send + Sync {
    /// Checks to see if the current EventState has been set
    fn is_set(&self) -> bool;

    /// Sets EventState
    fn set(&self);

    /// Clears the EventState
    fn clear(&self);

    /// Registers a signaler object with an event to notify waiting threads when an event is set
    fn register_signaler(
        &self,
        pos: usize,
        signaler: Arc<dyn Signaler>,
    ) -> Result<(), Box<dyn Error>>;

    /// Removes the signaler when a waiting thread continues
    fn remove_signaler(&self, signaler: &Arc<dyn Signaler>) -> Result<(), Box<dyn Error>>;

    /// An optional mutex if the event needs to be locked before consuming
    fn wake_lock(&self) -> Result<Option<MutexGuard<()>>, Box<dyn Error>>;

    /// Expected to be used with the wake lock, call can consume to see if the event is consumable
    fn can_consume(&self) -> bool;

    /// Expected to be used with the wake lock, tells the event a waiting thread is releasing and
    /// consuming the event
    fn consume(&self);
}

/// Wrapper struct passing around the internal state which is only accessible by this crate
pub struct EventHandle {
    state: Box<dyn EventState>,
}

impl EventHandle {
    pub(crate) fn new(state: Box<dyn EventState>) -> EventHandle {
        EventHandle { state }
    }

    pub(crate) fn is_set(&self) -> bool {
        self.state.is_set()
    }

    pub(crate) fn set(&self) {
        self.state.set()
    }

    pub(crate) fn clear(&self) {
        self.state.clear()
    }

    pub(crate) fn wake_lock(&self) -> Result<Option<MutexGuard<()>>, Box<dyn Error>> {
        self.state.wake_lock()
    }

    pub(crate) fn can_consume(&self) -> bool {
        self.state.can_consume()
    }

    pub(crate) fn consume(&self) {
        self.state.consume()
    }
}

/// A public trait for passing in the events into a wait function, which gives access to the
/// private EventHandle's state
pub trait Event: Sync {
    fn handle(&self) -> &Arc<EventHandle>;
}

pub(crate) fn try_consume_one(event: &dyn Event) -> Result<bool, Box<dyn Error>> {
    let _ = event.handle().wake_lock()?;
    if event.handle().can_consume() {
        event.handle().consume();
        Ok(true)
    } else {
        Ok(false)
    }
}

pub(crate) fn try_consume_all(events: &Vec<&dyn Event>) -> Result<bool, Box<dyn Error>> {
    let mut locks = Vec::with_capacity(events.len());

    for event in events {
        let wake_lock = event.handle().wake_lock()?;
        if !event.handle().can_consume() {
            return Ok(false);
        }
        locks.push(wake_lock)
    }

    for event in events {
        event.handle().consume()
    }

    Ok(true)
}

pub(crate) struct AutoUnregister {
    signaler: Arc<dyn Signaler>,
    handle: Arc<EventHandle>,
}

impl AutoUnregister {
    pub(crate) fn new(signaler: Arc<dyn Signaler>, handle: Arc<EventHandle>) -> AutoUnregister {
        AutoUnregister { signaler, handle }
    }

    pub(crate) fn register_signaler(
        signaler: Arc<dyn Signaler>,
        pos: usize,
        event: &dyn Event,
    ) -> Result<AutoUnregister, Box<dyn Error>> {
        let auto_unregister =
            AutoUnregister::new(Arc::clone(&signaler), Arc::clone(event.handle()));

        event.handle().state.register_signaler(pos, signaler)?;

        Ok(auto_unregister)
    }
}

impl Drop for AutoUnregister {
    fn drop(&mut self) {
        match self.handle.state.remove_signaler(&self.signaler) {
            _ => {}
        }
    }
}

/// EventGuard
///
/// Simple RAII class to set an event and automatically clear it when it goes out of scope
///
/// # Examples
///
/// ```
/// use win_events::{EventGuard, ManualResetEvent};///
///
/// let event = ManualResetEvent::new(false);///
/// assert!(!event.is_set());///
/// let event_guard = EventGuard::new(&event);
/// assert!(event.is_set());
/// drop(event_guard);
/// assert!(!event.is_set());
///
/// ```
pub struct EventGuard {
    handle: Arc<EventHandle>,
}

impl EventGuard {
    pub fn new(event: &dyn Event) -> EventGuard {
        let handle = Arc::clone(event.handle());
        handle.set();
        EventGuard { handle }
    }
}

impl Drop for EventGuard {
    fn drop(&mut self) {
        self.handle.clear()
    }
}