winit/src/platform_impl/web/async/waker.rs

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

121 lines
3.2 KiB
Rust
Raw Normal View History

2023-10-16 15:50:22 +02:00
use std::future;
use std::sync::atomic::{AtomicBool, Ordering};
2023-10-16 15:50:22 +02:00
use std::sync::Arc;
use std::task::Poll;
use super::super::main_thread::MainThreadMarker;
use super::{AtomicWaker, Wrapper};
pub struct WakerSpawner<T: 'static>(Wrapper<Handler<T>, Sender, ()>);
2023-10-16 15:50:22 +02:00
pub struct Waker<T: 'static>(Wrapper<Handler<T>, Sender, ()>);
2023-10-16 15:50:22 +02:00
struct Handler<T> {
value: T,
handler: fn(&T, bool),
2023-10-16 15:50:22 +02:00
}
#[derive(Clone)]
struct Sender(Arc<Inner>);
impl<T> WakerSpawner<T> {
#[track_caller]
pub fn new(main_thread: MainThreadMarker, value: T, handler: fn(&T, bool)) -> Option<Self> {
2023-10-16 15:50:22 +02:00
let inner = Arc::new(Inner {
awoken: AtomicBool::new(false),
2023-10-16 15:50:22 +02:00
waker: AtomicWaker::new(),
closed: AtomicBool::new(false),
});
let handler = Handler { value, handler };
let sender = Sender(Arc::clone(&inner));
let wrapper = Wrapper::new(
main_thread,
2023-10-16 15:50:22 +02:00
handler,
|handler, _| {
2023-10-16 15:50:22 +02:00
let handler = handler.borrow();
let handler = handler.as_ref().unwrap();
(handler.handler)(&handler.value, true);
2023-10-16 15:50:22 +02:00
},
{
let inner = Arc::clone(&inner);
move |handler| async move {
while future::poll_fn(|cx| {
if inner.awoken.swap(false, Ordering::Relaxed) {
Poll::Ready(true)
} else {
inner.waker.register(cx.waker());
if inner.awoken.swap(false, Ordering::Relaxed) {
Poll::Ready(true)
} else {
if inner.closed.load(Ordering::Relaxed) {
return Poll::Ready(false);
}
Poll::Pending
}
2023-10-16 15:50:22 +02:00
}
})
.await
{
let handler = handler.borrow();
let handler = handler.as_ref().unwrap();
(handler.handler)(&handler.value, false);
2023-10-16 15:50:22 +02:00
}
}
},
sender,
|inner, _| {
inner.0.awoken.store(true, Ordering::Relaxed);
2023-10-16 15:50:22 +02:00
inner.0.waker.wake();
},
)?;
Some(Self(wrapper))
}
pub fn waker(&self) -> Waker<T> {
Waker(self.0.clone())
}
pub fn take(&self) -> bool {
2023-10-16 15:50:22 +02:00
debug_assert!(
MainThreadMarker::new().is_some(),
2023-10-16 15:50:22 +02:00
"this should only be called from the main thread"
);
self.0.with_sender_data(|inner| inner.0.awoken.swap(false, Ordering::Relaxed))
2023-10-16 15:50:22 +02:00
}
}
impl<T> Drop for WakerSpawner<T> {
fn drop(&mut self) {
self.0.with_sender_data(|inner| {
inner.0.closed.store(true, Ordering::Relaxed);
inner.0.waker.wake();
});
}
}
impl<T> Waker<T> {
pub fn wake(&self) {
self.0.send(())
2023-10-16 15:50:22 +02:00
}
}
impl<T> Clone for Waker<T> {
fn clone(&self) -> Self {
Self(self.0.clone())
}
}
struct Inner {
awoken: AtomicBool,
2023-10-16 15:50:22 +02:00
waker: AtomicWaker,
closed: AtomicBool,
}