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
//! Asynchronous values. //! //! This module provides the runtime for `async`/`await` feature. The runtime //! relies on the Thread-Local Storage feature of [Drone threads](thr) and //! should be initialized with [`future::init`]. There are two ways to use //! `async`/`await` in Drone applications: //! //! 1. The preferred way is to use `libcore-drone` crate as a dependency. Place //! the following to the Cargo.toml: //! //! ```toml //! [dependencies] //! core = { package = "libcore-drone", version = "0.11.0" } //! ``` //! //! This way you can use native Rust `async`/`await` syntax. //! //! 2. Without `libcore-drone`, attempting to use `.await` will result in the //! following errors: //! //! ```text //! error[E0433]: failed to resolve: could not find `poll_with_tls_context` in `future` //! error[E0433]: failed to resolve: could not find `from_generator` in `future` //! ``` //! //! You can use [`future::fallback`] module instead. Refer the module //! documentation for examples. pub mod fallback; mod gen_future; pub use self::gen_future::from_generator; use crate::thr::{local, TaskCell, Thread, ThreadLocal}; use core::{ future::Future, mem::transmute, pin::Pin, sync::atomic::{AtomicUsize, Ordering}, task::Poll, }; static LOCAL_TASK_FN: AtomicUsize = AtomicUsize::new(0); /// Uses the thread-local storage of `T` for the `futures` task system. /// /// This function should be called before polling any future. pub fn init<T: Thread>() { LOCAL_TASK_FN.store(local_task_fn::<T> as usize, Ordering::Relaxed); } /// Polls a future in the current task context. pub fn poll_with_context<F>(f: Pin<&mut F>) -> Poll<F::Output> where F: Future, { local_task().get_context(|cx| F::poll(f, cx)) } fn local_task() -> &'static TaskCell { let ptr = LOCAL_TASK_FN.load(Ordering::Relaxed); if ptr == 0 { panic!("drone_core::future::init not called"); } else { unsafe { transmute::<usize, unsafe fn() -> &'static TaskCell>(ptr)() } } } unsafe fn local_task_fn<T: Thread>() -> &'static TaskCell { local::<T>().task() }