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;
use std::time::{Duration, SystemTime};

use crate::events::event::{try_consume_one, AutoUnregister};
use crate::Event;

use super::waiter::{Signaler, Waiter};

type WaitOne = Waiter<bool>;

impl Signaler for WaitOne {
    fn fire(&self, pos: usize) -> Result<(), Box<dyn Error>> {
        let lock = self.lock();
        let mut data = match lock {
            Ok(data) => data,
            Err(error) => {
                return Err(format!("Failed to fire event: {}", error).into());
            }
        };

        *data = pos == 0;
        self.condvar.notify_all();
        Ok(())
    }

    fn clear(&self, _: usize) -> Result<(), Box<dyn Error>> {
        Ok(())
    }
}

/// Waits for a single event to be fired
///
/// # Examples
///
/// This example spawns a thread that will set the event of the created event after a short delay.
///
/// The main thread will wait on the event and return true if it's been set, otherwise it will
/// timeout and return false
///
///```
/// use std::thread::{sleep, spawn};
/// use std::time::Duration;
/// use win_events::{ManualResetEvent, wait_one};
///
/// let evt0 = ManualResetEvent::new(false);
/// let evt_inner = evt0.clone();
///
/// let worker = spawn(move || {
///    sleep(Duration::from_millis(10));
///    evt_inner.set()
/// });
///
/// let wait_result = wait_one(
///    &evt0,
///    Duration::from_millis(100),
/// ).unwrap();
///
/// assert_eq!(true, wait_result);
/// worker.join().unwrap()
///```
pub fn wait_one(event: &dyn Event, dur: Duration) -> Result<bool, Box<dyn Error>> {
    // Check to see if the event is already fired, if it is no need to even wait
    if event.handle().is_set() && try_consume_one(event)? {
        return Ok(true);
    }

    let signaler = Arc::new(WaitOne::new(false));

    // Register the signaler info with the registered handlers

    let registered = AutoUnregister::register_signaler(Arc::<WaitOne>::clone(&signaler), 0, event)?;

    // wait on the event to be fired
    let start = SystemTime::now();
    let mut dur_remaining = dur;
    let result = loop {
        let data = signaler.lock()?;
        let lock_result = signaler
            .condvar
            .wait_timeout_while(data, dur_remaining, |fired| !*fired);

        let (mut fired, timeout) = match lock_result {
            Ok(result) => result,
            Err(error) => break Err(format!("Wait failed: {}", error).into()),
        };

        // Check to see if the wait timed out
        if timeout.timed_out() {
            break Ok(false);
        }

        // consume the event
        if event.handle().can_consume() && try_consume_one(event)? {
            break Ok(true);
        }

        // reset fired event value
        *fired = false;

        // Calculate the remaining time
        let result = start.elapsed();
        match result {
            Ok(elapsed) => dur_remaining = dur - elapsed,
            // The system time can change and cause this to return early... I'm sure it's fine
            Err(_) => {
                break Ok(false);
            }
        }
    };

    // release this here
    drop(registered);
    result
}