1 unstable release

0.1.0 Mar 26, 2018

#1912 in Asynchronous

78 stars & 15 watchers

8KB
148 lines

A no_std compatible, allocation-less, single-threaded futures executor; targeted at supporting embedded use-cases.

Targets

There are two primary targets supported at the moment: thumbv6m, thumbv7m. These two targets use the builtin event system to allow for sleeping while the future is idle waiting on input.

There is also basic support for any target that has full atomic support. This is less efficient as it uses a busy-loop while idle, but is useful for testing code on a "native" target (i.e. your machine).

Safety

You'll note that the signature for Executor::block_on takes &'static mut self. This is necessary because we can't use reference counting for the wakers like normal allocation-using executors. Instead we have a pre-allocated waker stored in the executor and hand a reference to that out to any future running on it. Because a waker must be an Arc-like type, even after the future completes we can't know that there isn't still a live reference, necessitating it to have a 'static lifetime.

There are two ways to use this executor, either statically allocate it or dynamically allocate it and leak it (e.g. with Box::leak if you have std allocation available). You need a mutable reference, so if statically allocating will need to use either a static mut or some target specific form of interior borrowing. If using static mut you must be careful of re-entrancy to ensure you don't accidentally create multiple mutable references to the executor.

Examples

#![feature(const_fn)]
use embrio_executor::Executor;

static mut EXECUTOR: Executor = Executor::new();

// Safety: We are in a non-reentrant context, so this is the only reference
// to the executor that will ever exist.
let executor = unsafe { &mut EXECUTOR };

assert_eq!(executor.block_on(async { 5 }), 5);

Dependencies

~180KB