use std::fmt;
use std::future::Future;
use std::mem;
use std::pin::Pin;
use std::sync::Arc;
use std::task::Context;
use std::task::Poll;
use std::task::Waker;
use crate::internal::mutex::Mutex;
use crate::internal::waitlist::WaitList;
use crate::internal::waitlist::WaiterId;
use crate::internal::wake_all;
use crate::internal::waker_batch::WakerBatch;
pub struct ManualResetEvent {
state: Mutex<State>,
}
impl ManualResetEvent {
pub const fn new() -> Self {
Self::with_state(false)
}
pub const fn with_state(is_set: bool) -> Self {
Self {
state: Mutex::new(State {
is_set,
waiters: WaitList::new(),
}),
}
}
pub fn is_set(&self) -> bool {
self.state.lock().is_set
}
pub fn set(&self) {
let wakers = {
let mut state = self.state.lock();
if state.is_set {
return;
}
state.is_set = true;
let mut wakers = WakerBatch::new();
while let Some((_id, waiter)) = state.waiters.unlink_first_waiter(|waiter| {
waiter.notified = true;
true
}) {
if let Some(waker) = waiter.waker.take() {
wakers.push(waker);
}
}
wakers
};
wake_all(wakers.into_iter());
}
pub fn reset(&self) {
self.state.lock().is_set = false;
}
pub async fn wait(&self) {
let fut = ManualResetEventWait {
waiter: None,
event: self,
};
fut.await
}
pub async fn wait_owned(self: Arc<Self>) {
let fut = OwnedManualResetEventWait {
waiter: None,
event: self,
};
fut.await
}
fn poll_wait(&self, waiter_id: &mut Option<WaiterId>, cx: &mut Context<'_>) -> Poll<()> {
let (poll, retired_waker) = {
let mut state = self.state.lock();
match *waiter_id {
Some(id) if state.waiters.waiter_mut(id).notified => {
let waiter = state.remove_waiter(id);
*waiter_id = None;
(Poll::Ready(()), waiter.waker)
}
Some(id) => {
debug_assert!(
!state.is_set,
"a linked waiter must belong to an unset event"
);
let waiter = state.waiters.waiter_mut(id);
let retired = (!waiter.will_wake(cx.waker()))
.then(|| waiter.replace_waker(cx.waker().clone()));
(Poll::Pending, retired)
}
None if state.is_set => (Poll::Ready(()), None),
None => {
*waiter_id = Some(state.waiters.push_back(Waiter {
notified: false,
waker: Some(cx.waker().clone()),
}));
(Poll::Pending, None)
}
}
};
drop(retired_waker);
poll
}
fn unregister_waiter(&self, waiter_id: &mut Option<WaiterId>) {
let Some(id) = waiter_id.take() else {
return;
};
let waiter = {
let mut state = self.state.lock();
state.remove_waiter(id)
};
drop(waiter);
}
}
impl Default for ManualResetEvent {
fn default() -> Self {
Self::new()
}
}
impl fmt::Debug for ManualResetEvent {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ManualResetEvent")
.field("is_set", &self.is_set())
.finish_non_exhaustive()
}
}
#[derive(Debug)]
struct State {
is_set: bool,
waiters: WaitList<Waiter>,
}
impl State {
fn remove_waiter(&mut self, id: WaiterId) -> Waiter {
self.waiters.unlink_waiter(id, |_| true);
self.waiters.remove_unlinked_waiter(id)
}
}
#[derive(Debug)]
struct Waiter {
notified: bool,
waker: Option<Waker>,
}
impl Waiter {
fn will_wake(&self, waker: &Waker) -> bool {
self.waker
.as_ref()
.expect("an unnotified waiter must retain its waker")
.will_wake(waker)
}
fn replace_waker(&mut self, waker: Waker) -> Waker {
let current = self
.waker
.as_mut()
.expect("an unnotified waiter must retain its waker");
mem::replace(current, waker)
}
}
#[must_use = "futures do nothing unless you `.await` or poll them"]
struct ManualResetEventWait<'a> {
waiter: Option<WaiterId>,
event: &'a ManualResetEvent,
}
impl Future for ManualResetEventWait<'_> {
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let Self { waiter, event } = self.get_mut();
event.poll_wait(waiter, cx)
}
}
impl Drop for ManualResetEventWait<'_> {
fn drop(&mut self) {
self.event.unregister_waiter(&mut self.waiter);
}
}
#[must_use = "futures do nothing unless you `.await` or poll them"]
struct OwnedManualResetEventWait {
waiter: Option<WaiterId>,
event: Arc<ManualResetEvent>,
}
impl Future for OwnedManualResetEventWait {
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let Self { waiter, event } = self.get_mut();
event.poll_wait(waiter, cx)
}
}
impl Drop for OwnedManualResetEventWait {
fn drop(&mut self) {
self.event.unregister_waiter(&mut self.waiter);
}
}