~hime/scope-future

Simple boxed futures for custom allocators
8069b6cc — Robert Straw 14 days ago
(feat) make crate #![no_std] compatible
8133bc75 — Robert Straw 14 days ago
(docs) add LICENSE file
d50a6f5b — Robert Straw 14 days ago
(docs) some documentation & readme updates

refs

master
browse  log 

clone

read-only
https://git.sr.ht/~hime/scope-future
read/write
git@git.sr.ht:~hime/scope-future

You can also use your local clone with git send-email.

#scope-future

This crate allows you to allocate a future inside of an allocator and pass it around as if it were a trait object. (i.e. a Box<dyn Future>) This crate is inspired by stackfuture, but instead of storing the future on the stack it stores the future on an arbitrary heap using the (unstable) Allocator trait.

We also jettison a lot of the concerns about compile time generic sizes, as well as allocation requirements: since the Allocator-crate will get the layout of F and handle alignment for us. It also allows dynamic allocation, so we don't really care how large F is. (It should fail similarly to if you tried to heap-allocate a future and ran out of memory, i.e. panic...)

#Disclaimer

I'm not super-sure this is sound. This is non-trivial to do, without unsafe, due to pinned allocated boxes requiring a 'static lifetime.

That being said the only place we create a Pin is in a context where we were already pinned. Listen if rustc is happy, I'm happy. I just made this crate so I can store futures in a non-global allocator on an embedded system. (Where the rules are made up, and everything I say goes.)

#TODO

  • The allocator API has a lot of fallible allocation methods, I plan to support these to allow runtime handling of failed allocations, but currently have no reason to since my own allocator does not bubble up that information.

  • Probably write some tests. However most of the tests I can think of are "compile-fail" style tests, so I need to research how to make that sort of test-harness.

#Usage

Add this to your Cargo.toml like so:

[dependencies]
scope-future = "0.1"

Then use it as follows:

// inside #[tokio::main], for example ...
// create an allocator w/ your favorite crate
let mut arena = VmArena::with_capacity(1 * 4096);

// create some futures which store their continuations in our arena!
let a = ScopeFuture::wrap_in(async { ... }, &arena); 
let b = ScopeFuture::wrap_in(async { ... }, &arena); 
let c = ScopeFuture::wrap_in(async { ... }, &arena); 

// We join all the futures, finishing their borrow of the arena
let (a, b, c) = futures::join!(a,b,c);
println!("({},{},{})", a, b, c);

// You can't call `#reset` until `a/b/c` either gets dropped or awaited.
// If you move this before `future::join!(...)` it won't compile, nifty :-)
VmArena::reset(&mut arena);