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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
//! This crate provides wrappers for async operations in order to help standardize rust async
//! runtimes.
//!
//! SAFETY: The current runtime *must* be cleaned up after each tick of a runtime, and must
//! therefore live shorter than the runtime itself as the runtime can not be dropped while it
//! is running. Without this, async-core causes undefined behavior.
//!
//! SAFETY: In a no_std environment, creating multiple threads is inherently unsafe as there is no
//! safe API wrapping threads. I assume you know what you are doing if you are using this with
//! multiple threads in a no_std environment. Please do not share runtimes between threads this way.
//!
//! SAFETY: DO NOT USE process::exit!
//!
//! ## How to use a runtime:
//!
//! - Import the re-exported Runtime and get_current_runtime.
//! - (Skip this if you are a library developer and want your users to control the runtime) Create
//!   a runtime like you normally would
//! - Don't use that runtime's specifics if you can somehow avoid it. Use get_current_runtime and
//!   the functions provided in the returned RuntimeWrapper
//!
//! ## How to implement a runtime:
//!
//! - Re-export everything so your users can use async_core without needing to add it as a
//!   dependency.
//! - In the runtime, call set_current_runtime and clear_current_runtime:
//! ```
//! set_current_runtime(self);
//! let result = execute_futures(); // Do your cool runtime things here
//! clear_current_runtime();
//! result
//! ```
//! - If your crate has a no_std feature, link that with this crate's no_std feature.
//! - Make absolutely sure you call set_current_runtime and clear_current_runtime.

#![no_std]
#[cfg(not(feature = "no_std"))]
extern crate std;

extern crate alloc;

mod runtime;
pub use runtime::*;

mod defer;
#[cfg(not(feature = "no_std"))]
pub use defer::*;

mod yielding;
pub use yielding::*;

mod joiner;
pub use joiner::*;

use alloc::boxed::Box;
use core::pin::Pin;
use core::{cell::RefCell, future::Future};
use core::{mem, mem::ManuallyDrop, panic};

pub type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + 'a>>;
#[inline]
pub fn prep<'a, T>(future: impl Future<Output = T> + 'a) -> BoxFuture<'a, T> {
    Box::pin(future)
}

#[cfg(feature = "no_std")]
mod no_std_util {
    pub struct ForceShare<T>(pub T);
    unsafe impl<T> Send for ForceShare<T> {}
    unsafe impl<T> Sync for ForceShare<T> {}
    impl<T> ForceShare<T> {
        pub fn with<F, R>(&self, fun: F) -> R
        where
            F: FnOnce(&T) -> R,
        {
            fun(&self.0)
        }
    }
}

#[cfg(feature = "no_std")]
static CURRENT_RUNTIME: no_std_util::ForceShare<
    RefCell<Option<ManuallyDrop<Box<dyn InternalRuntime>>>>,
> = no_std_util::ForceShare(RefCell::new(None));

#[cfg(not(feature = "no_std"))]
std::thread_local! {
    static CURRENT_RUNTIME: RefCell<Option<ManuallyDrop<Box<dyn InternalRuntime>>>> = RefCell::new(None);
}

/// This gets the currently running runtime. PANICS IF IT IS CALLED FROM OUTSIDE THE RUNTIME.
pub async fn get_current_runtime<'a>() -> RuntimeWrapper<'a> {
    CURRENT_RUNTIME.with(|x| {
        if let Some(x) = x.borrow_mut().as_mut() {
            unsafe { RuntimeWrapper(&mut *(x.as_mut() as *mut _)) }
        } else {
            panic!(
                "get_current_runtime MUST only be called from a future running within a Runtime!"
            )
        }
    })
}

/// This sets the currently running runtime. MUST *ONLY* BE CALLED BY A RUNTIME WHEN IT IS ABOUT TO
/// START EXECUTING, AND MUST BE CLEARED AFTERWARDS.
pub fn set_current_runtime(runtime: &mut dyn InternalRuntime) {
    CURRENT_RUNTIME.with(move |x| {
        *x.borrow_mut() = Some(unsafe {
            ManuallyDrop::new(Box::from_raw(
                mem::transmute::<_, *mut dyn InternalRuntime>(runtime),
            ))
        })
    })
}

/// This clears the currently running runtime. MUST *ONLY* BE CALLED BY A RUNTIME WHEN IT WILL
/// (temporarily of permanently) STOP EXECUTING FUTURES. MUST FOLLOW A set_current_runtime CALL.
/// IF THE RUNTIME STARTS TO BE USED AGAIN, set_current_runtime MUST BE CALLED AGAIN.
pub fn clear_current_runtime() {
    CURRENT_RUNTIME.with(|x| *x.borrow_mut() = None)
}