smol-rs / futures-lite

Futures, streams, and async I/O combinators.
Apache License 2.0
439 stars 25 forks source link

no_std support? #19

Closed paulkernfeld closed 3 years ago

paulkernfeld commented 4 years ago

Hi! The background is that I've been looking for a crate for implementing a Stream in an embedded system. I see that this crate does have a std feature, so is this crate intended to support no_std?

In terms of the current state of this:

ghost commented 4 years ago

It seems most failures are due to the fact that future::block_on() is not available on no_std systems. We could fix that by creating a silly implementation of that function that simply spins polling the future and never parks the thread.

I confirm the issue with fastrand not supporting no_std. I have just published futures-lite v1.2.0 that should resolve the problem by disabling future::race() on no_std systems. Let me know if it works now!

paulkernfeld commented 4 years ago

It seems most failures are due to the fact that future::block_on() is not available on no_std systems. We could fix that by creating a silly implementation of that function that simply spins polling the future and never parks the thread.

Funny that you mention the silly implementation! I was just investigating a similar idea. Would a solution like this do the trick? How would you want that added to futures_lite? Would it be like, if you have std you get the good block_on but if you're on no_std you get the spinning one? Or should users have to make a more deliberate decision that they're okay with falling back to the spinning implementation?

I confirm the issue with fastrand not supporting no_std. I have just published futures-lite v1.2.0 that should resolve the problem by disabling future::race() on no_std systems. Let me know if it works now!

Just tried, looks like it's getting stuck on memchr now.

paulkernfeld commented 4 years ago

I'll see if I can make memchr only use std if the std feature is enabled.

paulkernfeld commented 4 years ago

I think #20 should fix this issue.

If it's interesting to you, I'm still not able to use futures_lite in my app for two reasons:

  1. I'm using Stream.then
  2. I have not set up a global allocator

I'm not necessarily saying that futures_lite should support my use case, just providing the info in case it's helpful. 😊

ghost commented 4 years ago

Would a solution like this do the trick?

Yes, that looks about right.

How would you want that added to futures_lite? Would it be like, if you have std you get the good block_on but if you're on no_std you get the spinning one?

Not sure. Perhaps I'd make a crate named spin-on with a spin_on() function and just use that instead of block_on() in doctests.

I'm not necessarily saying that futures_lite should support my use case, just providing the info in case it's helpful. 😊

Thanks, that is indeed helpful! :)

Do you perhaps what's the easiest way to check if futures-lite allows use in no_std environments without a global allocator? I would like to add some kind of test to CI but am not sure how...

paulkernfeld commented 3 years ago

Not sure. Perhaps I'd make a crate named spin-on with a spin_on() function and just use that instead of block_on() in doctests.

I can try setting that up when I have a bit of free time in the next couple days.

Do you perhaps what's the easiest way to check if futures-lite allows use in no_std environments without a global allocator? I would like to add some kind of test to CI but am not sure how...

I see two reasonable approaches. I'd be happy to try implementing one.

ghost commented 3 years ago

Thank you! cargo-nono looks very helpful. Now I just need a way to check if the crate compiles for no_std and no_alloc targets :)

paulkernfeld commented 3 years ago

For no_alloc, I think you could use the cargo build --target thumbv7m-none-eabi strategy, and as long as you don't specify a global allocator I think it should check that your crate works without an allocator. Or, maybe I'm missing something?

ghost commented 3 years ago

Hmm, this successfully builds the crate: cargo build --no-default-features --target thumbv7m-none-eabi

However, if I then create a new project with this code:

#![no_main]
#![no_std]

use futures_lite::*;

#[panic_handler]
fn panic(_panic: &core::panic::PanicInfo<'_>) -> ! {
    loop {}
}

it fails with the following error:

error: no global memory allocator found but one is required; link to std or add `#[global_allocator]` to a static item that implements the GlobalAlloc trait.

So it looks like I can compile it for thumbv7m-none-eabi, but futures-lite still requires alloc.

paulkernfeld commented 3 years ago

All right, I did set up a spin_on crate here. Should I convert the doc tests to use it?

For figuring out the allocator issue, the goal is to find out what dependency is requiring allocation, right? My first idea is to find or write an allocator that panics, then run the unit tests with that allocator enabled. It's not 100% guaranteed to find everything because the tests might not trigger every possible allocation, but it might work.

ghost commented 3 years ago

All right, I did set up a spin_on crate here. Should I convert the doc tests to use it?

Great! :) Yeah, let's try replacing block_on() with spin_on() and see if cargo test --no-default-features passes.

For figuring out the allocator issue, the goal is to find out what dependency is requiring allocation, right?

Yes. Perhaps another (silly) idea is to create a small crate that just imports futures-lite, compile it, grep the rustc error and see if it mentions the allocator :)

bjorn3 commented 3 years ago

As I already commented on u.r-l.o the problem is: https://github.com/stjepang/futures-lite/blob/6976c55a0bbf34f449358f74ed267a6ad3149d13/src/future.rs#L31-L32

This pulls in liballoc.

paulkernfeld commented 3 years ago

Heh, yep, looks like that would do it. @stjepang should we introduce an alloc feature for users who don't want to enable a global allocator?

ghost commented 3 years ago

@paulkernfeld Yeah that's a good idea - I have submitted a PR here: https://github.com/stjepang/futures-lite/pull/23

Does it look right?

ghost commented 3 years ago

Published v1.4.0 which has the alloc Cargo feature.

paulkernfeld commented 3 years ago

Awesome, thanks for the quick implementation! I am ready to consider this issue done!