waker_fn/
lib.rs

1//! Convert closures into wakers.
2//!
3//! A [`Waker`] is just a fancy callback. This crate converts regular closures into wakers.
4
5#![no_std]
6#![forbid(unsafe_code)]
7#![warn(missing_docs, missing_debug_implementations, rust_2018_idioms)]
8#![doc(
9    html_favicon_url = "https://raw.githubusercontent.com/smol-rs/smol/master/assets/images/logo_fullsize_transparent.png"
10)]
11#![doc(
12    html_logo_url = "https://raw.githubusercontent.com/smol-rs/smol/master/assets/images/logo_fullsize_transparent.png"
13)]
14
15#[cfg(not(feature = "portable-atomic"))]
16extern crate alloc;
17
18#[cfg(not(feature = "portable-atomic"))]
19use alloc::{sync::Arc, task::Wake};
20use core::task::Waker;
21#[cfg(feature = "portable-atomic")]
22use portable_atomic_util::{task::Wake, Arc};
23
24/// Converts a closure into a [`Waker`].
25///
26/// The closure gets called every time the waker is woken.
27///
28/// # Examples
29///
30/// ```
31/// use waker_fn::waker_fn;
32///
33/// let waker = waker_fn(|| println!("woken"));
34///
35/// waker.wake_by_ref(); // Prints "woken".
36/// waker.wake();        // Prints "woken".
37/// ```
38pub fn waker_fn<F: Fn() + Send + Sync + 'static>(f: F) -> Waker {
39    Waker::from(Arc::new(Helper(f)))
40}
41
42struct Helper<F>(F);
43
44#[cfg(not(feature = "portable-atomic"))]
45impl<F: Fn() + Send + Sync + 'static> Wake for Helper<F> {
46    fn wake(self: Arc<Self>) {
47        (self.0)();
48    }
49
50    fn wake_by_ref(self: &Arc<Self>) {
51        (self.0)();
52    }
53}
54// Note: Unlike std::task::Wake, all methods take `this:` instead of `self:`.
55// This is because using portable_atomic_util::Arc as a receiver requires the
56// unstable arbitrary_self_types feature.
57#[cfg(feature = "portable-atomic")]
58impl<F: Fn() + Send + Sync + 'static> Wake for Helper<F> {
59    fn wake(this: Arc<Self>) {
60        (this.0)();
61    }
62
63    fn wake_by_ref(this: &Arc<Self>) {
64        (this.0)();
65    }
66}