use std::any::type_name;
use std::cell::{Cell, UnsafeCell};
use std::fmt;
use std::future::Future;
use std::marker::{PhantomData, PhantomPinned};
use std::panic::{RefUnwindSafe, UnwindSafe};
use std::pin::Pin;
use std::ptr::NonNull;
use std::rc::Rc;
use std::task::{self, Poll, Waker};
use awaiter_set::{Awaiter, AwaiterSet};
#[derive(Clone)]
pub struct LocalManualResetEvent {
inner: Rc<Inner>,
}
struct Inner {
is_set: Cell<bool>,
waiters: UnsafeCell<AwaiterSet>,
_not_send: PhantomData<*const ()>,
}
impl UnwindSafe for Inner {}
impl RefUnwindSafe for Inner {}
impl Inner {
fn set(&self) {
if self.is_set.get() {
return;
}
self.is_set.set(true);
{
let waiters = unsafe { &mut *self.waiters.get() };
waiters.advance_generation();
}
loop {
let waker = {
let waiters = unsafe { &mut *self.waiters.get() };
waiters.notify_one_prior_generation()
};
match waker {
Some(w) => w.wake(),
None => break,
}
}
}
fn reset(&self) {
self.is_set.set(false);
}
fn try_wait(&self) -> bool {
self.is_set.get()
}
unsafe fn poll_wait(&self, mut awaiter: Pin<&mut Awaiter>, waker: Waker) -> Poll<()> {
if awaiter.as_ref().take_notification() {
return Poll::Ready(());
}
if self.is_set.get() {
return Poll::Ready(());
}
let waiters = unsafe { &mut *self.waiters.get() };
unsafe {
waiters.register(awaiter.as_mut(), waker);
}
Poll::Pending
}
unsafe fn drop_wait(&self, mut awaiter: Pin<&mut Awaiter>) {
if awaiter.is_registered() {
let waiters = unsafe { &mut *self.waiters.get() };
unsafe {
waiters.unregister(awaiter.as_mut());
}
}
}
}
impl LocalManualResetEvent {
#[must_use]
pub fn boxed() -> Self {
Self {
inner: Rc::new(Inner {
is_set: Cell::new(false),
waiters: UnsafeCell::new(AwaiterSet::new()),
_not_send: PhantomData,
}),
}
}
#[must_use]
pub unsafe fn embedded(
place: Pin<&EmbeddedLocalManualResetEvent>,
) -> EmbeddedLocalManualResetEventRef {
let inner = NonNull::from_ref(&place.get_ref().inner);
EmbeddedLocalManualResetEventRef { inner }
}
#[inline]
#[cfg_attr(coverage_nightly, coverage(off))]
pub fn set(&self) {
self.inner.set();
}
#[inline]
#[cfg_attr(coverage_nightly, coverage(off))]
pub fn reset(&self) {
self.inner.reset();
}
#[inline]
#[cfg_attr(coverage_nightly, coverage(off))]
#[must_use]
pub fn try_wait(&self) -> bool {
self.inner.try_wait()
}
#[must_use]
pub fn wait(&self) -> LocalManualResetWaitFuture {
LocalManualResetWaitFuture {
inner: Rc::clone(&self.inner),
awaiter: Awaiter::new(),
}
}
}
pub struct LocalManualResetWaitFuture {
inner: Rc<Inner>,
awaiter: Awaiter,
}
impl UnwindSafe for LocalManualResetWaitFuture {}
impl RefUnwindSafe for LocalManualResetWaitFuture {}
impl Future for LocalManualResetWaitFuture {
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<()> {
let waker = cx.waker().clone();
let this = unsafe { self.get_unchecked_mut() };
let awaiter = unsafe { Pin::new_unchecked(&mut this.awaiter) };
unsafe { this.inner.poll_wait(awaiter, waker) }
}
}
impl Drop for LocalManualResetWaitFuture {
fn drop(&mut self) {
let awaiter = unsafe { Pin::new_unchecked(&mut self.awaiter) };
unsafe {
self.inner.drop_wait(awaiter);
}
}
}
#[cfg_attr(coverage_nightly, coverage(off))]
impl fmt::Debug for LocalManualResetEvent {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct(type_name::<Self>())
.field("is_set", &self.inner.is_set.get())
.finish()
}
}
#[cfg_attr(coverage_nightly, coverage(off))]
impl fmt::Debug for LocalManualResetWaitFuture {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct(type_name::<Self>())
.finish_non_exhaustive()
}
}
pub struct EmbeddedLocalManualResetEvent {
inner: Inner,
_pinned: PhantomPinned,
}
impl EmbeddedLocalManualResetEvent {
#[must_use]
pub fn new() -> Self {
Self {
inner: Inner {
is_set: Cell::new(false),
waiters: UnsafeCell::new(AwaiterSet::new()),
_not_send: PhantomData,
},
_pinned: PhantomPinned,
}
}
}
impl Default for EmbeddedLocalManualResetEvent {
#[cfg_attr(coverage_nightly, coverage(off))] fn default() -> Self {
Self::new()
}
}
impl UnwindSafe for EmbeddedLocalManualResetEvent {}
impl RefUnwindSafe for EmbeddedLocalManualResetEvent {}
#[derive(Clone, Copy)]
pub struct EmbeddedLocalManualResetEventRef {
inner: NonNull<Inner>,
}
impl UnwindSafe for EmbeddedLocalManualResetEventRef {}
impl RefUnwindSafe for EmbeddedLocalManualResetEventRef {}
impl EmbeddedLocalManualResetEventRef {
fn inner(&self) -> &Inner {
unsafe { self.inner.as_ref() }
}
#[inline]
#[cfg_attr(coverage_nightly, coverage(off))]
pub fn set(&self) {
self.inner().set();
}
#[inline]
#[cfg_attr(coverage_nightly, coverage(off))]
pub fn reset(&self) {
self.inner().reset();
}
#[inline]
#[cfg_attr(coverage_nightly, coverage(off))]
#[must_use]
pub fn try_wait(&self) -> bool {
self.inner().try_wait()
}
#[must_use]
pub fn wait(&self) -> EmbeddedLocalManualResetWaitFuture {
EmbeddedLocalManualResetWaitFuture {
inner: self.inner,
awaiter: Awaiter::new(),
}
}
}
pub struct EmbeddedLocalManualResetWaitFuture {
inner: NonNull<Inner>,
awaiter: Awaiter,
}
impl UnwindSafe for EmbeddedLocalManualResetWaitFuture {}
impl RefUnwindSafe for EmbeddedLocalManualResetWaitFuture {}
impl Future for EmbeddedLocalManualResetWaitFuture {
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<()> {
let waker = cx.waker().clone();
let this = unsafe { self.get_unchecked_mut() };
let inner = unsafe { this.inner.as_ref() };
let awaiter = unsafe { Pin::new_unchecked(&mut this.awaiter) };
unsafe { inner.poll_wait(awaiter, waker) }
}
}
impl Drop for EmbeddedLocalManualResetWaitFuture {
fn drop(&mut self) {
let inner = unsafe { self.inner.as_ref() };
let awaiter = unsafe { Pin::new_unchecked(&mut self.awaiter) };
unsafe {
inner.drop_wait(awaiter);
}
}
}
#[cfg_attr(coverage_nightly, coverage(off))]
impl fmt::Debug for EmbeddedLocalManualResetEvent {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct(type_name::<Self>()).finish_non_exhaustive()
}
}
#[cfg_attr(coverage_nightly, coverage(off))]
impl fmt::Debug for EmbeddedLocalManualResetEventRef {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let is_set = self.try_wait();
f.debug_struct(type_name::<Self>())
.field("is_set", &is_set)
.finish()
}
}
#[cfg_attr(coverage_nightly, coverage(off))]
impl fmt::Debug for EmbeddedLocalManualResetWaitFuture {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct(type_name::<Self>())
.finish_non_exhaustive()
}
}
#[cfg(test)]
#[cfg_attr(coverage_nightly, coverage(off))]
mod tests {
use std::task::Waker;
use static_assertions::{assert_impl_all, assert_not_impl_any};
use super::*;
assert_impl_all!(LocalManualResetEvent: Clone, UnwindSafe, RefUnwindSafe);
assert_not_impl_any!(LocalManualResetEvent: Send, Sync);
assert_impl_all!(LocalManualResetWaitFuture: UnwindSafe, RefUnwindSafe);
assert_not_impl_any!(LocalManualResetWaitFuture: Send, Sync, Unpin);
assert_impl_all!(EmbeddedLocalManualResetEvent: UnwindSafe, RefUnwindSafe);
assert_not_impl_any!(EmbeddedLocalManualResetEvent: Send, Sync, Unpin);
assert_impl_all!(EmbeddedLocalManualResetEventRef: Clone, Copy, UnwindSafe, RefUnwindSafe);
assert_not_impl_any!(EmbeddedLocalManualResetEventRef: Send, Sync);
assert_impl_all!(EmbeddedLocalManualResetWaitFuture: UnwindSafe, RefUnwindSafe);
assert_not_impl_any!(EmbeddedLocalManualResetWaitFuture: Send, Sync, Unpin);
#[test]
fn starts_unset() {
let event = LocalManualResetEvent::boxed();
assert!(!event.try_wait());
}
#[test]
fn set_and_reset() {
let event = LocalManualResetEvent::boxed();
event.set();
assert!(event.try_wait());
event.reset();
assert!(!event.try_wait());
}
#[test]
fn clone_shares_state() {
let a = LocalManualResetEvent::boxed();
let b = a.clone();
a.set();
assert!(b.try_wait());
}
#[test]
fn wait_completes_when_already_set() {
futures::executor::block_on(async {
let event = LocalManualResetEvent::boxed();
event.set();
event.wait().await;
});
}
#[test]
fn wait_completes_after_set() {
futures::executor::block_on(async {
let event = LocalManualResetEvent::boxed();
let future = event.wait();
event.set();
future.await;
});
}
#[test]
fn drop_future_while_waiting() {
futures::executor::block_on(async {
let event = LocalManualResetEvent::boxed();
{
let _f = event.wait();
}
event.set();
event.wait().await;
});
}
#[test]
fn embedded_set_and_wait() {
futures::executor::block_on(async {
let container = Box::pin(EmbeddedLocalManualResetEvent::new());
let event = unsafe { LocalManualResetEvent::embedded(container.as_ref()) };
event.set();
event.wait().await;
});
}
#[test]
fn embedded_clone_shares_state() {
futures::executor::block_on(async {
let container = Box::pin(EmbeddedLocalManualResetEvent::new());
let a = unsafe { LocalManualResetEvent::embedded(container.as_ref()) };
let b = a;
a.set();
assert!(b.try_wait());
b.wait().await;
});
}
#[test]
fn embedded_reset_after_set() {
let container = Box::pin(EmbeddedLocalManualResetEvent::new());
let event = unsafe { LocalManualResetEvent::embedded(container.as_ref()) };
event.set();
event.reset();
assert!(!event.try_wait());
}
#[test]
fn embedded_drop_future_while_waiting() {
futures::executor::block_on(async {
let container = Box::pin(EmbeddedLocalManualResetEvent::new());
let event = unsafe { LocalManualResetEvent::embedded(container.as_ref()) };
{
let _future = event.wait();
}
event.set();
event.wait().await;
});
}
#[test]
fn wait_registers_then_completes() {
let event = LocalManualResetEvent::boxed();
let mut future = Box::pin(event.wait());
let waker = Waker::noop();
let mut cx = task::Context::from_waker(waker);
assert!(future.as_mut().poll(&mut cx).is_pending());
event.set();
assert!(future.as_mut().poll(&mut cx).is_ready());
}
#[test]
fn drop_registered_future() {
let event = LocalManualResetEvent::boxed();
let mut future = Box::pin(event.wait());
let waker = Waker::noop();
let mut cx = task::Context::from_waker(waker);
assert!(future.as_mut().poll(&mut cx).is_pending());
drop(future);
event.set();
let mut future2 = Box::pin(event.wait());
assert!(future2.as_mut().poll(&mut cx).is_ready());
}
#[test]
fn embedded_wait_registers_then_completes() {
let container = Box::pin(EmbeddedLocalManualResetEvent::new());
let event = unsafe { LocalManualResetEvent::embedded(container.as_ref()) };
let mut future = Box::pin(event.wait());
let waker = Waker::noop();
let mut cx = task::Context::from_waker(waker);
assert!(future.as_mut().poll(&mut cx).is_pending());
event.set();
assert!(future.as_mut().poll(&mut cx).is_ready());
}
#[test]
fn embedded_drop_registered_future() {
let container = Box::pin(EmbeddedLocalManualResetEvent::new());
let event = unsafe { LocalManualResetEvent::embedded(container.as_ref()) };
let mut future = Box::pin(event.wait());
let waker = Waker::noop();
let mut cx = task::Context::from_waker(waker);
assert!(future.as_mut().poll(&mut cx).is_pending());
drop(future);
event.set();
let mut future2 = Box::pin(event.wait());
assert!(future2.as_mut().poll(&mut cx).is_ready());
}
#[test]
fn embedded_multiple_waiters_released() {
let container = Box::pin(EmbeddedLocalManualResetEvent::new());
let event = unsafe { LocalManualResetEvent::embedded(container.as_ref()) };
let mut f1 = Box::pin(event.wait());
let mut f2 = Box::pin(event.wait());
let mut f3 = Box::pin(event.wait());
let waker = Waker::noop();
let mut cx = task::Context::from_waker(waker);
assert!(f1.as_mut().poll(&mut cx).is_pending());
assert!(f2.as_mut().poll(&mut cx).is_pending());
assert!(f3.as_mut().poll(&mut cx).is_pending());
event.set();
assert!(f1.as_mut().poll(&mut cx).is_ready());
assert!(f2.as_mut().poll(&mut cx).is_ready());
assert!(f3.as_mut().poll(&mut cx).is_ready());
}
#[test]
fn set_with_reentrant_waker_does_not_alias() {
use testing::ReentrantWakerData;
let event = LocalManualResetEvent::boxed();
let event_clone = event.clone();
let waker_data = ReentrantWakerData::new(move || {
event_clone.reset();
let mut new_future = Box::pin(event_clone.wait());
let noop = Waker::noop();
let mut cx = task::Context::from_waker(noop);
assert!(new_future.as_mut().poll(&mut cx).is_pending());
});
let waker = unsafe { waker_data.waker() };
let mut cx = task::Context::from_waker(&waker);
let mut future = Box::pin(event.wait());
assert!(future.as_mut().poll(&mut cx).is_pending());
event.set();
assert!(waker_data.was_woken());
}
#[test]
fn embedded_set_with_reentrant_waker_does_not_alias() {
use testing::ReentrantWakerData;
let container = Box::pin(EmbeddedLocalManualResetEvent::new());
let event = unsafe { LocalManualResetEvent::embedded(container.as_ref()) };
let waker_data = ReentrantWakerData::new(move || {
event.reset();
let mut new_future = Box::pin(event.wait());
let noop = Waker::noop();
let mut cx = task::Context::from_waker(noop);
assert!(new_future.as_mut().poll(&mut cx).is_pending());
});
let waker = unsafe { waker_data.waker() };
let mut cx = task::Context::from_waker(&waker);
let mut future = Box::pin(event.wait());
assert!(future.as_mut().poll(&mut cx).is_pending());
event.set();
assert!(waker_data.was_woken());
}
#[test]
fn try_wait_returns_false_when_unset() {
let event = LocalManualResetEvent::boxed();
assert!(!event.try_wait());
}
#[test]
fn try_wait_returns_true_when_set() {
let event = LocalManualResetEvent::boxed();
event.set();
assert!(event.try_wait());
}
#[test]
fn embedded_try_wait_returns_false_when_unset() {
let container = Box::pin(EmbeddedLocalManualResetEvent::new());
let event = unsafe { LocalManualResetEvent::embedded(container.as_ref()) };
assert!(!event.try_wait());
}
#[test]
fn embedded_try_wait_returns_true_when_set() {
let container = Box::pin(EmbeddedLocalManualResetEvent::new());
let event = unsafe { LocalManualResetEvent::embedded(container.as_ref()) };
event.set();
assert!(event.try_wait());
}
#[test]
fn embedded_set_wakes_registered_waiter() {
use testing::ReentrantWakerData;
let container = Box::pin(EmbeddedLocalManualResetEvent::new());
let event = unsafe { LocalManualResetEvent::embedded(container.as_ref()) };
let waker_data = ReentrantWakerData::new(|| {});
let waker = unsafe { waker_data.waker() };
let mut cx = task::Context::from_waker(&waker);
let mut future = Box::pin(event.wait());
assert!(future.as_mut().poll(&mut cx).is_pending());
event.set();
assert!(waker_data.was_woken());
}
#[test]
fn drop_unregisters_waiter() {
use testing::ReentrantWakerData;
let event = LocalManualResetEvent::boxed();
let tracker1 = ReentrantWakerData::new(|| {});
let waker1 = unsafe { tracker1.waker() };
let mut cx1 = task::Context::from_waker(&waker1);
let tracker2 = ReentrantWakerData::new(|| {});
let waker2 = unsafe { tracker2.waker() };
let mut cx2 = task::Context::from_waker(&waker2);
let mut future1 = Box::pin(event.wait());
assert!(future1.as_mut().poll(&mut cx1).is_pending());
let mut future2 = Box::pin(event.wait());
assert!(future2.as_mut().poll(&mut cx2).is_pending());
drop(future1);
event.set();
assert!(!tracker1.was_woken());
assert!(tracker2.was_woken());
}
#[test]
fn embedded_drop_unregisters_waiter() {
use testing::ReentrantWakerData;
let container = Box::pin(EmbeddedLocalManualResetEvent::new());
let event = unsafe { LocalManualResetEvent::embedded(container.as_ref()) };
let tracker1 = ReentrantWakerData::new(|| {});
let waker1 = unsafe { tracker1.waker() };
let mut cx1 = task::Context::from_waker(&waker1);
let tracker2 = ReentrantWakerData::new(|| {});
let waker2 = unsafe { tracker2.waker() };
let mut cx2 = task::Context::from_waker(&waker2);
let mut future1 = Box::pin(event.wait());
assert!(future1.as_mut().poll(&mut cx1).is_pending());
let mut future2 = Box::pin(event.wait());
assert!(future2.as_mut().poll(&mut cx2).is_pending());
drop(future1);
event.set();
assert!(!tracker1.was_woken());
assert!(tracker2.was_woken());
}
#[test]
fn set_when_already_set_is_noop() {
let event = LocalManualResetEvent::boxed();
event.set();
assert!(event.try_wait());
event.set();
assert!(event.try_wait());
}
#[test]
fn embedded_set_when_already_set_is_noop() {
let container = Box::pin(EmbeddedLocalManualResetEvent::new());
let event = unsafe { LocalManualResetEvent::embedded(container.as_ref()) };
event.set();
assert!(event.try_wait());
event.set();
assert!(event.try_wait());
}
#[test]
fn drop_forwarding_with_reentrant_waker_does_not_alias() {
use testing::ReentrantWakerData;
let event = LocalManualResetEvent::boxed();
let event_clone = event.clone();
let mut future1 = Box::pin(event.wait());
let noop_waker = Waker::noop();
let mut noop_cx = task::Context::from_waker(noop_waker);
assert!(future1.as_mut().poll(&mut noop_cx).is_pending());
let waker_data = ReentrantWakerData::new(move || {
event_clone.set();
});
let waker = unsafe { waker_data.waker() };
let mut reentrant_cx = task::Context::from_waker(&waker);
let mut future2 = Box::pin(event.wait());
assert!(future2.as_mut().poll(&mut reentrant_cx).is_pending());
event.set();
drop(future1);
assert!(waker_data.was_woken());
}
#[test]
fn reentrant_reset_does_not_skip_awaiters() {
use testing::ReentrantWakerData;
let event = LocalManualResetEvent::boxed();
let event_for_waker = event.clone();
let waker_data_a = ReentrantWakerData::new(move || {
event_for_waker.reset();
});
let waker_a = unsafe { waker_data_a.waker() };
let mut cx_a = task::Context::from_waker(&waker_a);
let noop = Waker::noop();
let mut cx_b = task::Context::from_waker(noop);
let mut future_a = Box::pin(event.wait());
assert!(future_a.as_mut().poll(&mut cx_a).is_pending());
let mut future_b = Box::pin(event.wait());
assert!(future_b.as_mut().poll(&mut cx_b).is_pending());
event.set();
assert!(waker_data_a.was_woken());
assert!(future_b.as_mut().poll(&mut cx_b).is_ready());
}
#[test]
fn reentrant_drop_of_sibling_waiter_does_not_skip_others() {
use std::cell::RefCell;
use std::rc::Rc;
use testing::ReentrantWakerData;
let event = LocalManualResetEvent::boxed();
let event_for_waker = event.clone();
let future_b_holder: Rc<RefCell<Option<Pin<Box<LocalManualResetWaitFuture>>>>> =
Rc::new(RefCell::new(None));
let holder_for_waker = Rc::clone(&future_b_holder);
let waker_data_a = ReentrantWakerData::new(move || {
drop(holder_for_waker.borrow_mut().take());
event_for_waker.reset();
});
let waker_a = unsafe { waker_data_a.waker() };
let mut cx_a = task::Context::from_waker(&waker_a);
let noop = Waker::noop();
let mut cx_noop = task::Context::from_waker(noop);
let mut future_a = Box::pin(event.wait());
assert!(future_a.as_mut().poll(&mut cx_a).is_pending());
let mut future_b = Box::pin(event.wait());
assert!(future_b.as_mut().poll(&mut cx_noop).is_pending());
*future_b_holder.borrow_mut() = Some(future_b);
let mut future_c = Box::pin(event.wait());
assert!(future_c.as_mut().poll(&mut cx_noop).is_pending());
event.set();
assert!(waker_data_a.was_woken());
assert!(future_b_holder.borrow().is_none());
assert!(future_c.as_mut().poll(&mut cx_noop).is_ready());
}
#[test]
fn reentrant_drop_of_tail_sibling_does_not_skip_others() {
use std::cell::RefCell;
use std::rc::Rc;
use testing::ReentrantWakerData;
let event = LocalManualResetEvent::boxed();
let event_for_waker = event.clone();
let future_c_holder: Rc<RefCell<Option<Pin<Box<LocalManualResetWaitFuture>>>>> =
Rc::new(RefCell::new(None));
let holder_for_waker = Rc::clone(&future_c_holder);
let waker_data_a = ReentrantWakerData::new(move || {
drop(holder_for_waker.borrow_mut().take());
event_for_waker.reset();
});
let waker_a = unsafe { waker_data_a.waker() };
let mut cx_a = task::Context::from_waker(&waker_a);
let noop = Waker::noop();
let mut cx_noop = task::Context::from_waker(noop);
let mut future_a = Box::pin(event.wait());
assert!(future_a.as_mut().poll(&mut cx_a).is_pending());
let mut future_b = Box::pin(event.wait());
assert!(future_b.as_mut().poll(&mut cx_noop).is_pending());
let mut future_c = Box::pin(event.wait());
assert!(future_c.as_mut().poll(&mut cx_noop).is_pending());
*future_c_holder.borrow_mut() = Some(future_c);
event.set();
assert!(waker_data_a.was_woken());
assert!(future_c_holder.borrow().is_none());
assert!(future_b.as_mut().poll(&mut cx_noop).is_ready());
}
#[test]
fn reentrant_register_during_set_does_not_notify_new_awaiter() {
use std::cell::RefCell;
use std::rc::Rc;
use testing::ReentrantWakerData;
let event = LocalManualResetEvent::boxed();
let event_for_waker = event.clone();
let late_future_holder: Rc<RefCell<Option<Pin<Box<LocalManualResetWaitFuture>>>>> =
Rc::new(RefCell::new(None));
let holder_for_waker = Rc::clone(&late_future_holder);
let waker_data_a = ReentrantWakerData::new(move || {
event_for_waker.reset();
let noop = Waker::noop();
let mut cx_noop = task::Context::from_waker(noop);
let mut new_future = Box::pin(event_for_waker.wait());
assert!(new_future.as_mut().poll(&mut cx_noop).is_pending());
*holder_for_waker.borrow_mut() = Some(new_future);
});
let waker_a = unsafe { waker_data_a.waker() };
let mut cx_a = task::Context::from_waker(&waker_a);
let mut future_a = Box::pin(event.wait());
assert!(future_a.as_mut().poll(&mut cx_a).is_pending());
event.set();
assert!(waker_data_a.was_woken());
let noop = Waker::noop();
let mut cx_noop = task::Context::from_waker(noop);
let mut late_future = late_future_holder
.borrow_mut()
.take()
.expect("reentrant waker registers the late future");
assert!(late_future.as_mut().poll(&mut cx_noop).is_pending());
event.set();
assert!(late_future.as_mut().poll(&mut cx_noop).is_ready());
}
#[test]
fn reset_while_waiters_registered() {
let event = LocalManualResetEvent::boxed();
let waker = Waker::noop();
let mut cx = task::Context::from_waker(waker);
let mut future = Box::pin(event.wait());
assert!(future.as_mut().poll(&mut cx).is_pending());
event.reset();
assert!(future.as_mut().poll(&mut cx).is_pending());
event.set();
assert!(future.as_mut().poll(&mut cx).is_ready());
}
#[test]
fn embedded_default_creates_unset_event() {
let container = Box::pin(EmbeddedLocalManualResetEvent::default());
let event = unsafe { LocalManualResetEvent::embedded(container.as_ref()) };
assert!(!event.try_wait());
}
}