rust-lang / futures-rs

Zero-cost asynchronous programming in Rust
https://rust-lang.github.io/futures-rs/
Apache License 2.0
5.39k stars 625 forks source link

no_std support for a futures executor #1007

Open dhoove opened 6 years ago

dhoove commented 6 years ago

This comment in #944 gave me some hope that it would soon be possible to use a single-threaded executor with no_std. I would like to be able to use async code for embedded applications. The general-purpose asynchronous CoAP library, mentioned in #860, also sounds very interesting for newer IoT devices. Wouldn't this also require a no_std executor?

TDHolmes commented 4 years ago

This should be quite possible now that async fully works on embedded. Here's a proof of concept from Ferrous Systems (blog post on it).

A number of things would have to change about the current single threaded executor to get this to work though. It uses Arc/Rc and spawns a thread, whereas for embedded reference counters aren't available in core and obviously you wouldn't spawn a thread for the executor.

Perhaps a simple, separate bare bones executor would be useful?

Nemo157 commented 4 years ago

The most basic possible executor requires 2 things that aren't available in core:

  1. Some form of shared ownership, this is Arc normally, but depending on other details could be something as simple as an &'static _ (if you only want to support a single future in the lifetime of the application).
  2. Some way to do parking/unparking of the main thread, this is Thread::{park, unpark} normally, but some systems such as the Cortex-M series have dedicated assembly instructions that can be used for this (WFE/SEV).

Since these details are platform specific it might be possible to have a generic executor that is capable of having concrete implementations plugged into it for them. But then the generic executor part becomes so trivial I don't see any reason to not just have platform specific executors.

TDHolmes commented 4 years ago
  1. Some form of shared ownership, this is Arc normally, but depending on other details could be something as simple as an &'static _ (if you only want to support a single future in the lifetime of the application).

I think it's reasonable to require an allocator for a generic executor, so things like Arc and Box could be used in embedded (alloc crate).

  1. Some way to do parking/unparking of the main thread, this is Thread::{park, unpark} normally, but some systems such as the Cortex-M series have dedicated assembly instructions that can be used for this (WFE/SEV).

Agreed that this is a problem. It could be abstracted as you say, but I suppose you're right, the local_pool executor is pretty small and trivial, maybe it does make sense to have these executors implemented elsewhere.

mkroening commented 4 years ago

I created a pool based on LocalPool which is generic over a park and an unpark function. It works very well on my cortex-m board. Creation looks like this: EmbeddedPool::new(asm::sev, asm::wfe).

Should I create PR to discuss it or would it be better for me to publish it in a separate crate?

TDHolmes commented 4 years ago

Awesome! Either way, I'd be interested to take a look.

mkroening commented 4 years ago

I created a PR containing my work, open for discussion! #2185

kuon commented 4 years ago

Maybe this could be integrated in some way? https://github.com/Dirbaio/static-executor