aboutsummaryrefslogtreecommitdiff
path: root/src/export
diff options
context:
space:
mode:
Diffstat (limited to 'src/export')
-rw-r--r--src/export/executor.rs110
1 files changed, 0 insertions, 110 deletions
diff --git a/src/export/executor.rs b/src/export/executor.rs
deleted file mode 100644
index e64cc43..0000000
--- a/src/export/executor.rs
+++ /dev/null
@@ -1,110 +0,0 @@
-use super::atomic::{AtomicBool, Ordering};
-use core::{
- cell::UnsafeCell,
- future::Future,
- mem::{self, MaybeUninit},
- pin::Pin,
- task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
-};
-
-static WAKER_VTABLE: RawWakerVTable =
- RawWakerVTable::new(waker_clone, waker_wake, waker_wake, waker_drop);
-
-unsafe fn waker_clone(p: *const ()) -> RawWaker {
- RawWaker::new(p, &WAKER_VTABLE)
-}
-
-unsafe fn waker_wake(p: *const ()) {
- // The only thing we need from a waker is the function to call to pend the async
- // dispatcher.
- let f: fn() = mem::transmute(p);
- f();
-}
-
-unsafe fn waker_drop(_: *const ()) {
- // nop
-}
-
-//============
-// AsyncTaskExecutor
-
-/// Executor for an async task.
-pub struct AsyncTaskExecutor<F: Future> {
- // `task` is protected by the `running` flag.
- task: UnsafeCell<MaybeUninit<F>>,
- running: AtomicBool,
- pending: AtomicBool,
-}
-
-unsafe impl<F: Future> Sync for AsyncTaskExecutor<F> {}
-
-impl<F: Future> AsyncTaskExecutor<F> {
- /// Create a new executor.
- #[inline(always)]
- pub const fn new() -> Self {
- Self {
- task: UnsafeCell::new(MaybeUninit::uninit()),
- running: AtomicBool::new(false),
- pending: AtomicBool::new(false),
- }
- }
-
- /// Check if there is an active task in the executor.
- #[inline(always)]
- pub fn is_running(&self) -> bool {
- self.running.load(Ordering::Relaxed)
- }
-
- /// Checks if a waker has pended the executor and simultaneously clears the flag.
- #[inline(always)]
- fn check_and_clear_pending(&self) -> bool {
- // Ordering::Acquire to enforce that update of task is visible to poll
- self.pending
- .compare_exchange(true, false, Ordering::Acquire, Ordering::Relaxed)
- .is_ok()
- }
-
- // Used by wakers to indicate that the executor needs to run.
- #[inline(always)]
- pub fn set_pending(&self) {
- self.pending.store(true, Ordering::Release);
- }
-
- /// Spawn a future
- #[inline(always)]
- pub fn spawn(&self, future: impl Fn() -> F) -> bool {
- // Try to reserve the executor for a future.
- if self
- .running
- .compare_exchange(false, true, Ordering::AcqRel, Ordering::Relaxed)
- .is_ok()
- {
- // This unsafe is protected by `running` being false and the atomic setting it to true.
- unsafe {
- self.task.get().write(MaybeUninit::new(future()));
- }
- self.set_pending();
-
- true
- } else {
- false
- }
- }
-
- /// Poll the future in the executor.
- #[inline(always)]
- pub fn poll(&self, wake: fn()) {
- if self.is_running() && self.check_and_clear_pending() {
- let waker = unsafe { Waker::from_raw(RawWaker::new(wake as *const (), &WAKER_VTABLE)) };
- let mut cx = Context::from_waker(&waker);
- let future = unsafe { Pin::new_unchecked(&mut *(self.task.get() as *mut F)) };
-
- match future.poll(&mut cx) {
- Poll::Ready(_) => {
- self.running.store(false, Ordering::Release);
- }
- Poll::Pending => {}
- }
- }
- }
-}