Skip to content

Commit

Permalink
web: squash UserWakeUp events
Browse files Browse the repository at this point in the history
  • Loading branch information
daxpedda committed May 20, 2024
1 parent d5fdf2b commit 11bf122
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 29 deletions.
2 changes: 1 addition & 1 deletion src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1021,7 +1021,7 @@ mod tests {
x(Resumed);

// Window events.
let with_window_event = |wev| x(WindowEvent { window_id: wid, event: wev });
let with_window_event = |wev| x(Window { window_id: wid, event: wev });

with_window_event(CloseRequested);
with_window_event(Destroyed);
Expand Down
44 changes: 20 additions & 24 deletions src/platform_impl/web/async/waker.rs
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
use std::future;
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use std::sync::atomic::{AtomicBool, Ordering};
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, usize>);
pub struct WakerSpawner<T: 'static>(Wrapper<Handler<T>, Sender, ()>);

pub struct Waker<T: 'static>(Wrapper<Handler<T>, Sender, usize>);
pub struct Waker<T: 'static>(Wrapper<Handler<T>, Sender, ()>);

struct Handler<T> {
value: T,
handler: fn(&T, usize),
handler: fn(&T),
}

#[derive(Clone)]
struct Sender(Arc<Inner>);

impl<T> WakerSpawner<T> {
#[track_caller]
pub fn new(main_thread: MainThreadMarker, value: T, handler: fn(&T, usize)) -> Option<Self> {
pub fn new(main_thread: MainThreadMarker, value: T, handler: fn(&T)) -> Option<Self> {
let inner = Arc::new(Inner {
counter: AtomicUsize::new(0),
awoken: AtomicBool::new(false),
waker: AtomicWaker::new(),
closed: AtomicBool::new(false),
});
Expand All @@ -34,30 +34,26 @@ impl<T> WakerSpawner<T> {
let wrapper = Wrapper::new(
main_thread,
handler,
|handler, count| {
|handler, _| {
let handler = handler.borrow();
let handler = handler.as_ref().unwrap();
(handler.handler)(&handler.value, count);
(handler.handler)(&handler.value);
},
{
let inner = Arc::clone(&inner);

move |handler| async move {
while let Some(count) = future::poll_fn(|cx| {
let count = inner.counter.swap(0, Ordering::Relaxed);

if count > 0 {
Poll::Ready(Some(count))
while future::poll_fn(|cx| {
if inner.awoken.swap(false, Ordering::Relaxed) {
Poll::Ready(true)
} else {
inner.waker.register(cx.waker());

let count = inner.counter.swap(0, Ordering::Relaxed);

if count > 0 {
Poll::Ready(Some(count))
if inner.awoken.swap(false, Ordering::Relaxed) {
Poll::Ready(true)
} else {
if inner.closed.load(Ordering::Relaxed) {
return Poll::Ready(None);
return Poll::Ready(false);
}

Poll::Pending
Expand All @@ -68,13 +64,13 @@ impl<T> WakerSpawner<T> {
{
let handler = handler.borrow();
let handler = handler.as_ref().unwrap();
(handler.handler)(&handler.value, count);
(handler.handler)(&handler.value);
}
}
},
sender,
|inner, _| {
inner.0.counter.fetch_add(1, Ordering::Relaxed);
inner.0.awoken.store(true, Ordering::Relaxed);
inner.0.waker.wake();
},
)?;
Expand All @@ -86,13 +82,13 @@ impl<T> WakerSpawner<T> {
Waker(self.0.clone())
}

pub fn fetch(&self) -> usize {
pub fn take(&self) -> bool {
debug_assert!(
MainThreadMarker::new().is_some(),
"this should only be called from the main thread"
);

self.0.with_sender_data(|inner| inner.0.counter.swap(0, Ordering::Relaxed))
self.0.with_sender_data(|inner| inner.0.awoken.swap(false, Ordering::Relaxed))
}
}

Expand All @@ -107,7 +103,7 @@ impl<T> Drop for WakerSpawner<T> {

impl<T> Waker<T> {
pub fn wake(&self) {
self.0.send(1)
self.0.send(())
}
}

Expand All @@ -118,7 +114,7 @@ impl<T> Clone for Waker<T> {
}

struct Inner {
counter: AtomicUsize,
awoken: AtomicBool,
waker: AtomicWaker,
closed: AtomicBool,
}
10 changes: 6 additions & 4 deletions src/platform_impl/web/event_loop/runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ impl Shared {
let document = window.document().expect("Failed to obtain document");

Shared(Rc::<Execution>::new_cyclic(|weak| {
let proxy_spawner = WakerSpawner::new(main_thread, weak.clone(), |runner, _count| {
let proxy_spawner = WakerSpawner::new(main_thread, weak.clone(), |runner| {
if let Some(runner) = runner.upgrade() {
Shared(runner).send_event(Event::UserWakeUp);
}
Expand Down Expand Up @@ -197,7 +197,7 @@ impl Shared {
// Set the event callback to use for the event loop runner
// This the event callback is a fairly thin layer over the user-provided callback that closes
// over a RootActiveEventLoop reference
pub fn set_listener(&self, event_handler: Box<EventHandler>) {
pub(crate) fn set_listener(&self, event_handler: Box<EventHandler>) {
{
let mut runner = self.0.runner.borrow_mut();
assert!(matches!(*runner, RunnerEnum::Pending));
Expand Down Expand Up @@ -602,8 +602,10 @@ impl Shared {

// Pre-fetch `UserEvent`s to avoid having to wait until the next event loop cycle.
events.extend(
iter::repeat(Event::UserWakeUp)
.take(self.0.proxy_spawner.fetch())
self.0
.proxy_spawner
.take()
.then_some(Event::UserWakeUp)
.map(EventWrapper::from),
);

Expand Down

0 comments on commit 11bf122

Please sign in to comment.