futures_async_runtime/
lib.rs

1#![no_std]
2#![cfg_attr(feature = "nightly", feature(generator_trait))]
3#![cfg_attr(feature = "nightly", feature(on_unimplemented))]
4#![cfg_attr(feature = "nightly", feature(arbitrary_self_types))]
5#![cfg_attr(feature = "nightly", feature(optin_builtin_traits))]
6#![cfg_attr(feature = "nightly", feature(pin))]
7
8macro_rules! if_nightly_and_std {
9    ($($i:item)*) => ($(
10        #[cfg(all(feature = "nightly", feature = "std"))]
11        $i
12    )*)
13}
14
15#[cfg(all(feature = "nightly", feature = "std"))]
16#[macro_use]
17extern crate std;
18
19if_nightly_and_std! {
20    extern crate futures_core;
21    extern crate futures_stable;
22
23    mod future;
24    mod stream;
25
26    use std::cell::Cell;
27    use std::mem;
28    use std::ptr;
29    use futures_core::task;
30
31    pub use self::future::*;
32    pub use self::stream::*;
33
34    pub use futures_core::{Async, Future, Stream};
35    pub use futures_stable::{StableFuture, StableStream};
36
37    pub use std::ops::Generator;
38
39#[rustc_on_unimplemented = "async functions must return a `Result` or \
40                                a typedef of `Result`"]
41    pub trait IsResult {
42        type Ok;
43        type Err;
44
45        fn into_result(self) -> Result<Self::Ok, Self::Err>;
46    }
47    impl<T, E> IsResult for Result<T, E> {
48        type Ok = T;
49        type Err = E;
50
51        fn into_result(self) -> Result<Self::Ok, Self::Err> { self }
52    }
53
54    pub fn diverge<T>() -> T { loop {} }
55
56    type StaticContext = *mut task::Context<'static>;
57
58    thread_local!(static CTX: Cell<StaticContext> = Cell::new(ptr::null_mut()));
59
60    struct Reset<'a>(StaticContext, &'a Cell<StaticContext>);
61
62    impl<'a> Reset<'a> {
63        fn new(ctx: &mut task::Context, cell: &'a Cell<StaticContext>) -> Reset<'a> {
64            let stored_ctx = unsafe { mem::transmute::<&mut task::Context, StaticContext>(ctx) };
65            let ctx = cell.replace(stored_ctx);
66            Reset(ctx, cell)
67        }
68
69        fn new_null(cell: &'a Cell<StaticContext>) -> Reset<'a> {
70            let ctx = cell.replace(ptr::null_mut());
71            Reset(ctx, cell)
72        }
73    }
74
75    impl<'a> Drop for Reset<'a> {
76        fn drop(&mut self) {
77            self.1.set(self.0);
78        }
79    }
80
81    pub fn in_ctx<F: FnOnce(&mut task::Context) -> T, T>(f: F) -> T {
82        CTX.with(|cell| {
83            let r = Reset::new_null(cell);
84            if r.0 == ptr::null_mut() {
85                panic!("Cannot use `await!`, `await_item!`, or `#[async] for` outside of an `async` function.")
86            }
87            f(unsafe { &mut *r.0 })
88        })
89    }
90}