Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adding support for no_std executor #7

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ runtime_tokio = [
"tokio",
"atomic_refcell"
]
# runtime_nostd = [
# "core"
# ]
runtime_nostd = [
"executor"
]

[dependencies]
bastion-executor = { version = "0.3", optional = true, features = [] }
Expand All @@ -31,6 +31,7 @@ tokio = { version = "0.2", optional = true, features = ["rt-core", "blocking", "
# core = { package = "core-futures-tls", version = "0.1.0", optional = true }
lightproc = { version = "0.3.4", optional = true }
atomic_refcell = { version = "0.1.6", optional = true }
executor = { version = "0.7.0", optional = true }

[dev-dependencies.tokio]
features = ["rt-core", "blocking", "time" ]
3 changes: 1 addition & 2 deletions ci.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,4 @@
cargo test --features=runtime_bastion
cargo test --features=runtime_asyncstd
cargo test --features=runtime_tokio
# Disabled until we have async / await in no_std
# cargo test --features=runtime_nostd
cargo test --features=runtime_nostd
40 changes: 38 additions & 2 deletions src/executors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ use crate::join_handle::{InnerJoinHandle, JoinHandle};
use crate::AgnostikExecutor;
#[cfg(feature = "runtime_tokio")]
use crate::LocalAgnostikExecutor;
use std::future::Future;

use core::future::Future;
#[cfg(feature = "runtime_asyncstd")]
pub(crate) struct AsyncStdExecutor;

Expand Down Expand Up @@ -144,3 +143,40 @@ impl AgnostikExecutor for BastionExecutor {
bastion_executor::run::run(future, ProcStack::default())
}
}

#[cfg(feature = "runtime_nostd")]
pub(crate) struct NoStdExecutor;

#[cfg(feature = "runtime_nostd")]
impl NoStdExecutor {
pub fn new() -> Self {
NoStdExecutor {}
}
}

#[cfg(feature = "runtime_nostd")]
impl AgnostikExecutor for NoStdExecutor {
fn spawn<F>(&self, _future: F) -> JoinHandle<F::Output>
where
F: Future + Send + 'static,
F::Output: Send + 'static,
{
panic!("no threads on no_std environments")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Threads aren't necessary for spawning tasks, it's possible to have fully capable core-only executors, they're just going to necessarily be much more device specific than any using std.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

awesome, I thought someone might say something about this, I'm curious what people think should be done about these cases for no_std , a better message? no_std multithreading is a bit out of my knowledge base.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤷‍♂️ I would say that no_std users should likely just supply their own, it's unlikely that there's a decent one-size-fits-all approach possible.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yah, I agree, i'm a web assembly dev and I don't even really have an option in this respect :)

}

fn spawn_blocking<F, T>(&self, _task: F) -> JoinHandle<T>
where
F: FnOnce() -> T + Send + 'static,
T: Send + 'static,
{
panic!("no threads on no_std environments")
}

fn block_on<F>(&self, future: F) -> F::Output
where
F: Future + Send + 'static,
F::Output: Send + 'static,
{
executor::block_on(future)
}
}
11 changes: 10 additions & 1 deletion src/join_handle.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Generic join handle type.

use std::{
use core::{
future::Future,
pin::Pin,
task::{Context, Poll},
Expand All @@ -22,13 +22,20 @@ use tokio::task::JoinHandle as TokioHandle;
/// agnostik will panic if the task failed to execute.
pub struct JoinHandle<R>(pub(crate) InnerJoinHandle<R>);

pub struct NoStdJoinHandle<T> {
__phantom: core::marker::PhantomData<T>
}

pub(crate) enum InnerJoinHandle<R> {
#[cfg(feature = "runtime_bastion")]
Bastion(RecoverableHandle<R>),
#[cfg(feature = "runtime_asyncstd")]
AsyncStd(AsyncStdHandle<R>),
#[cfg(feature = "runtime_tokio")]
Tokio(TokioHandle<R>),
#[cfg(feature = "runtime_nostd")]
#[allow(dead_code)]
NoStd(NoStdJoinHandle<R>),
}

impl<R> Future for JoinHandle<R>
Expand All @@ -49,6 +56,8 @@ where
InnerJoinHandle::Tokio(ref mut handle) => Pin::new(handle)
.poll(cx)
.map(|val| val.expect("task failed to execute")),
#[cfg(feature = "runtime_nostd")]
InnerJoinHandle::NoStd(_) => panic!("no threads on no_std environments"),
}
}
}
14 changes: 12 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@
//! - `Agnostik::async_std()` for async std
//! - `Agnostik::tokio()` for tokio. **Warning:** See "How to use tokio runtime"
//! - `Agnostik::tokio_with_runtime(runtime)` if you want to use your own `tokio::runtime::Runtime` object. **Warning:** See "How to use tokio runtime"
//! - `Agnostik::no_std()` (coming soon) to create an exeutor that works in a nostd environment
//! - `Agnostik::no_std()` (coming soon) to create an executor that works in a nostd environment
//!
//! ### How to use tokio runtime
//!
Expand Down Expand Up @@ -125,12 +125,13 @@
//!
//! You can replace 1 and 2 with `Agnostik::tokio()`, because this method call will
//! create a Runtime object using `Runtime::new()`.
#![cfg_attr(feature="runtime_nostd", no_std)]

mod executors;
pub mod join_handle;

use join_handle::JoinHandle;
use std::future::Future;
use core::future::Future;

/// This trait represents a generic executor that can spawn a future, spawn a blocking task,
/// and wait for a future to finish.
Expand Down Expand Up @@ -221,6 +222,15 @@ impl Agnostik {
pub fn tokio_with_runtime(runtime: tokio::runtime::Runtime) -> impl AgnostikExecutor {
executors::TokioExecutor::with_runtime(runtime)
}

#[cfg(feature = "runtime_nostd")]
/// Returns an [AgnostikExecutor], that will use a no_std executor from [executor] package
///
/// [executor]: https://docs.rs/executor
/// [AgnostikExecutor]: ../trait.AgnostikExecutor.html
pub fn no_std() -> impl AgnostikExecutor {
executors::NoStdExecutor::new()
}
}

#[allow(unused)]
Expand Down
14 changes: 14 additions & 0 deletions tests/no_std.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
pub use agnostik::prelude::*;

#[cfg(feature = "runtime_nostd")]
#[test]
fn test_no_std() {
let agnostik = Agnostik::no_std();
agnostik.block_on(async {
let mut i = 0;
while i < 5 {
println!("Counting from no_std: {}", i);
i+=1;
}
});
}