1#![no_std]
6#![warn(missing_docs, missing_debug_implementations, rust_2018_idioms)]
7
8extern crate alloc;
9
10use alloc::sync::Arc;
11use core::mem::{self, ManuallyDrop};
12use core::task::{RawWaker, RawWakerVTable, Waker};
13
14pub fn waker_fn<F: Fn() + Send + Sync + 'static>(f: F) -> Waker {
29 let raw = Arc::into_raw(Arc::new(f)) as *const ();
30 let vtable = &Helper::<F>::VTABLE;
31 unsafe { Waker::from_raw(RawWaker::new(raw, vtable)) }
32}
33
34struct Helper<F>(F);
35
36impl<F: Fn() + Send + Sync + 'static> Helper<F> {
37 const VTABLE: RawWakerVTable = RawWakerVTable::new(
38 Self::clone_waker,
39 Self::wake,
40 Self::wake_by_ref,
41 Self::drop_waker,
42 );
43
44 unsafe fn clone_waker(ptr: *const ()) -> RawWaker {
45 let arc = ManuallyDrop::new(Arc::from_raw(ptr as *const F));
46 mem::forget(arc.clone());
47 RawWaker::new(ptr, &Self::VTABLE)
48 }
49
50 unsafe fn wake(ptr: *const ()) {
51 let arc = Arc::from_raw(ptr as *const F);
52 (arc)();
53 }
54
55 unsafe fn wake_by_ref(ptr: *const ()) {
56 let arc = ManuallyDrop::new(Arc::from_raw(ptr as *const F));
57 (arc)();
58 }
59
60 unsafe fn drop_waker(ptr: *const ()) {
61 drop(Arc::from_raw(ptr as *const F));
62 }
63}