use std::error::Error;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Mutex, MutexGuard};
use std::time::Duration;
use crate::events::event::{EventHandle, EventState};
use crate::waiters::waiter::{Signaler, WaitList};
use crate::{wait_one, Event};
struct AutoResetEventInfo {
fired: AtomicBool,
waiters: WaitList,
wake_lock: Mutex<()>,
}
impl AutoResetEventInfo {
fn new(init: bool) -> AutoResetEventInfo {
AutoResetEventInfo {
fired: AtomicBool::new(init),
waiters: WaitList::new(),
wake_lock: Mutex::new(()),
}
}
}
impl AutoResetEventInfo {
fn set_value(&self, value: bool) {
self.fired.store(value, Ordering::Relaxed);
self.waiters.fire()
}
}
impl EventState for AutoResetEventInfo {
fn is_set(&self) -> bool {
self.fired.load(Ordering::Relaxed)
}
fn set(&self) {
self.set_value(true)
}
fn clear(&self) {
self.set_value(false)
}
fn register_signaler(
&self,
pos: usize,
signaler: Arc<dyn Signaler>,
) -> Result<(), Box<dyn Error>> {
if self.is_set() {
signaler.fire(pos)?;
}
self.waiters.register_signaler(pos, signaler)
}
fn remove_signaler(&self, signaler: &Arc<dyn Signaler>) -> Result<(), Box<dyn Error>> {
self.waiters.remove_signaler(signaler)
}
fn wake_lock(&self) -> Result<Option<MutexGuard<()>>, Box<dyn Error>> {
let result = self.wake_lock.lock();
match result {
Ok(guard) => Ok(Some(guard)),
Err(error) => Err(format!("Could not lock wake mutex: {}", error).into()),
}
}
fn can_consume(&self) -> bool {
self.fired.load(Ordering::Relaxed)
}
fn consume(&self) {
self.fired.store(false, Ordering::Relaxed)
}
}
#[derive(Clone)]
pub struct AutoResetEvent {
info: Arc<EventHandle>,
}
impl AutoResetEvent {
pub fn new(init: bool) -> AutoResetEvent {
let state: Box<dyn EventState> = Box::new(AutoResetEventInfo::new(init));
AutoResetEvent {
info: Arc::new(EventHandle::new(state)),
}
}
pub fn is_set(&self) -> bool {
self.info.is_set()
}
pub fn set(&self) {
self.info.set()
}
pub fn clear(&self) {
self.info.clear()
}
pub fn wait(&self, dur: Duration) -> Result<bool, Box<dyn Error>> {
wait_one(self, dur)
}
}
impl Event for AutoResetEvent {
fn handle(&self) -> &Arc<EventHandle> {
&self.info
}
}