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
//! Libcore wrapper allowing async/await //! //! # Usage //! //! Put the following in your Cargo.toml: //! //! ```toml //! [dependencies] //! core = { package = "core-futures-tls", version = "0.1.0" } //! ``` //! //! # Why //! //! Currently, async/await is not usable from libcore. Attempting to call .await //! from a `no_std` crate will yield the following error: //! //! ```norun //! 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` //! ``` //! //! This is due to await lowering to some code calling the functions //! `::core::futures::poll_with_tls_context` and `::core::futures::from_generator` //! in order to setup a per-thread context containing the current task. Those //! functions, however, do not exist. The equivalent functions are defined in //! libstd. They set up a thread-local variable which contains the current task //! being executed. When polling a future, this task will get retrieved in order //! to call the future's `poll` function. //! //! //! As mentioned, the libstd version of those functions use a thread-local //! variable, which is only supported in rust's libstd through the //! `thread_local!` macro - which doesn't exist in libcore. There is, however, //! an alternative: The (unstable) `#[thread_local]` attribute, which uses ELF //! TLS. Note that ELF TLS is not portable to all targets - it needs to be //! supported by the OS, the loader, etc... //! //! Here's a small example of the thread_local attribute in action: //! //! ```rust //! #![feature(thread_local)] //! use core::cell::Cell; //! #[thread_local] //! static TLS_CX: Cell<i32> = Cell::new(1); //! ``` //! //! Using this trick, we can copy paste libstd's implementation of the //! `poll_with_tls_context`/`from_generator` functions, but replacing the //! `thread_local!` macro with a `#[thread_local]` macro. Ez pz. //! //! # Wrapping libcore //! //! This trick is nice, but compiling a custom libcore is fastidious. Instead, //! we're going to wrap libcore, exposing our own libcore that just reexports //! the real libcore's functions, and adding our own extra stuff. This, //! surprisingly, can be done simply by declaring a `core` dependency with the //! `package` attribute set to our "real" crates.io package name. This will //! trick cargo into giving rustc our wrapper core as if it was the real //! libcore. //! //! So that's it. All this crate does is reexport libcore, adding a couple //! functions in the future module. You just have to use the following in your //! Cargo.toml in order to use it, and rust will happily use `core-futures-tls` //! as if it was the libcore. //! //! ```toml //! [dependencies] //! core = { package = "core-futures-tls", version = "0.1.0" } //! ``` //! //! # Closing thoughts //! //! While this crate still uses TLS, it should be possible to create a version //! that stores the thread local context in a global for single-threaded systems //! such as microcontrollers. This is left as an exercise to the reader. #![no_std] #![feature(thread_local, generator_trait, optin_builtin_traits)] pub mod future; pub use core::*;