Something went wrong. Try again.
A hardware-accelerated GPU terminal emulator focusing to run in desktops and browsers.
Something went wrong. Try again.
3.5 kB · 129 lines
Rust
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130use std::future;use std::sync::atomic::{AtomicBool, AtomicUsize, 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 Waker<T: 'static>(Wrapper<Handler<T>, Sender, usize>);
struct Handler<T> { value: T, handler: fn(&T, usize),}
#[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> { let inner = Arc::new(Inner { counter: AtomicUsize::new(0), waker: AtomicWaker::new(), closed: AtomicBool::new(false), });
let handler = Handler { value, handler };
let sender = Sender(Arc::clone(&inner));
let wrapper = Wrapper::new( main_thread, handler, |handler, count| { let handler = handler.borrow(); let handler = handler.as_ref().unwrap(); (handler.handler)(&handler.value, count); }, { 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)) } else { inner.waker.register(cx.waker());
let count = inner.counter.swap(0, Ordering::Relaxed);
if count > 0 { Poll::Ready(Some(count)) } else { if inner.closed.load(Ordering::Relaxed) { return Poll::Ready(None); }
Poll::Pending } } }) .await { let handler = handler.borrow(); let handler = handler.as_ref().unwrap(); (handler.handler)(&handler.value, count); } } }, sender, |inner, _| { inner.0.counter.fetch_add(1, Ordering::Relaxed); inner.0.waker.wake(); }, )?;
Some(Self(wrapper)) }
pub fn waker(&self) -> Waker<T> { Waker(self.0.clone()) }
pub fn fetch(&self) -> usize { 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)) }}
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(1) }}
impl<T> Clone for Waker<T> { fn clone(&self) -> Self { Self(self.0.clone()) }}
struct Inner { counter: AtomicUsize, waker: AtomicWaker, closed: AtomicBool,}