1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
//! Convert closures into wakers.
//!
//! A [`Waker`] is just a fancy callback. This crate converts regular closures into wakers.

#![no_std]
#![forbid(unsafe_code)]
#![warn(missing_docs, missing_debug_implementations, rust_2018_idioms)]
#![doc(
    html_favicon_url = "https://raw.githubusercontent.com/smol-rs/smol/master/assets/images/logo_fullsize_transparent.png"
)]
#![doc(
    html_logo_url = "https://raw.githubusercontent.com/smol-rs/smol/master/assets/images/logo_fullsize_transparent.png"
)]

#[cfg(not(feature = "portable-atomic"))]
extern crate alloc;

#[cfg(not(feature = "portable-atomic"))]
use alloc::{sync::Arc, task::Wake};
use core::task::Waker;
#[cfg(feature = "portable-atomic")]
use portable_atomic_util::{task::Wake, Arc};

/// Converts a closure into a [`Waker`].
///
/// The closure gets called every time the waker is woken.
///
/// # Examples
///
/// ```
/// use waker_fn::waker_fn;
///
/// let waker = waker_fn(|| println!("woken"));
///
/// waker.wake_by_ref(); // Prints "woken".
/// waker.wake();        // Prints "woken".
/// ```
pub fn waker_fn<F: Fn() + Send + Sync + 'static>(f: F) -> Waker {
    Waker::from(Arc::new(Helper(f)))
}

struct Helper<F>(F);

#[cfg(not(feature = "portable-atomic"))]
impl<F: Fn() + Send + Sync + 'static> Wake for Helper<F> {
    fn wake(self: Arc<Self>) {
        (self.0)();
    }

    fn wake_by_ref(self: &Arc<Self>) {
        (self.0)();
    }
}
// Note: Unlike std::task::Wake, all methods take `this:` instead of `self:`.
// This is because using portable_atomic_util::Arc as a receiver requires the
// unstable arbitrary_self_types feature.
#[cfg(feature = "portable-atomic")]
impl<F: Fn() + Send + Sync + 'static> Wake for Helper<F> {
    fn wake(this: Arc<Self>) {
        (this.0)();
    }

    fn wake_by_ref(this: &Arc<Self>) {
        (this.0)();
    }
}