#![ cfg_attr( feature = "external_doc", feature(external_doc) ) ]
#![ cfg_attr( feature = "external_doc", doc(include = "../README.md") ) ]
#![ doc ( html_root_url = "https://docs.rs/naja_async_runtime" ) ]
#![ deny ( missing_docs ) ]
#![ forbid ( unsafe_code ) ]
#![ allow ( clippy::suspicious_else_formatting ) ]
#![ warn
(
missing_debug_implementations ,
missing_docs ,
nonstandard_style ,
rust_2018_idioms ,
trivial_casts ,
trivial_numeric_casts ,
unused_extern_crates ,
unused_qualifications ,
single_use_lifetimes ,
unreachable_pub ,
variant_size_differences ,
)]
mod import
{
pub(crate) use
{
once_cell :: { unsync::OnceCell } ,
std :: { cfg, fmt, future::Future, error::Error as StdError } ,
};
#[ cfg(any( feature = "bindgen", feature = "localpool", feature = "juliex", feature = "threadpool", feature = "tokio_ct" )) ]
pub(crate) use futures::future::FutureExt;
#[ cfg(any( feature = "localpool", feature = "tokio_ct" )) ]
pub(crate) use std::cell::RefCell;
#[ cfg( feature = "bindgen" ) ]
pub(crate) use
{
wasm_bindgen_futures :: { spawn_local } ,
};
#[ cfg( feature = "localpool" ) ]
pub(crate) use
{
futures :: { task::LocalSpawnExt, executor::{ LocalPool as FutLocalPool, LocalSpawner } } ,
};
#[ cfg( feature = "threadpool" ) ]
pub(crate) use
{
futures :: { task::SpawnExt, executor::{ ThreadPool as FutThreadPool } } ,
};
#[ cfg(any( feature = "juliex", feature = "threadpool" )) ]
pub(crate) use
{
once_cell :: { sync::OnceCell as SyncOnceCell } ,
};
#[ cfg( feature = "tokio_ct" ) ]
pub(crate) use
{
tokio :: { runtime::current_thread::Runtime as TokioCtRuntime } ,
};
}
mod error ;
mod config ;
mod executor ;
pub use error::*;
pub use config::*;
#[ cfg( feature = "localpool" ) ] pub use executor::localpool ;
#[ cfg( feature = "async_std" ) ] pub use executor::async_std ;
#[ cfg( feature = "tokio_ct" ) ] pub use executor::tokio_ct ;
#[ cfg(all( feature = "macros", feature = "juliex" )) ] pub use naja_runtime_macros::juliex ;
#[ cfg(all( feature = "macros", feature = "threadpool" )) ] pub use naja_runtime_macros::threadpool ;
#[ cfg(all( feature = "macros", feature = "async_std" )) ] pub use naja_runtime_macros::async_std ;
#[ cfg(all( feature = "macros", feature = "localpool" )) ] pub use naja_runtime_macros::localpool ;
#[ cfg(all( feature = "macros", feature = "bindgen" )) ] pub use naja_runtime_macros::bindgen ;
#[ cfg(all( feature = "macros", feature = "tokio_ct" )) ] pub use naja_runtime_macros::tokio_ct ;
use
{
import :: { * } ,
executor :: { Executor } ,
};
std::thread_local!
(
pub(crate) static EXEC: OnceCell<Executor> = OnceCell::new();
);
#[cfg_attr(feature = "localpool", doc = r##"
```rust
use async_runtime as rt;
// Will be used for spawning on the current thread only, if you create other threads,
// you have to init them too, and you can choose a different executor on different threads.
//
rt::init( rt::Config::LocalPool ).expect( "Set thread executor" );
rt::spawn( async {} ).expect( "spawn future" );
rt::localpool::run();
```
"##)]
pub fn init( config: Config ) -> Result< (), Error >
{
EXEC.with( |exec| -> Result< (), Error >
{
exec.set( Executor::new( config ) ).map_err( |_| ErrorKind::DoubleExecutorInit.into() )
})
}
pub fn init_allow_same( config: Config ) -> Result< (), Error >
{
if let Some(cfg) = current_rt() {
if config == cfg
{
return Ok(())
}}
init( config )
}
#[ cfg_attr( feature = "localpool", doc = r##"
```
use async_runtime as rt;
rt::init( rt::Config::LocalPool ).expect( "no double executor init" );
rt::spawn( async
{
println!( "async execution" );
}).expect( "spawn on localpool" );
```
"##)]
pub fn spawn( fut: impl Future< Output=() > + 'static + Send ) -> Result< (), Error >
{
EXEC.with( move |exec| -> Result< (), Error >
{
match exec.get()
{
Some(e) => e.spawn( fut ) ,
None => Err( ErrorKind::NoExecutorInitialized.into() ) ,
}
})
}
pub fn spawn_local( fut: impl Future< Output=() > + 'static ) -> Result< (), Error >
{
EXEC.with( move |exec|
{
match exec.get()
{
Some(e) => e.spawn_local( fut ) ,
None => Err( ErrorKind::NoExecutorInitialized.into() ) ,
}
})
}
#[ cfg_attr( all( feature = "juliex", feature = "macros" ), doc = r##"
```
use async_runtime as rt;
#[ rt::juliex ]
//
async fn main()
{
let handle = rt::spawn_handle( async
{
"hello"
}).expect( "spawn on localpool" );
assert_eq!( "hello", handle.await );
}
```
"##)]
pub fn spawn_handle<T: Send + 'static>( fut: impl Future< Output=T > + Send + 'static )
-> Result< Box< dyn Future< Output=T > + Unpin + Send + 'static >, Error >
{
EXEC.with( move |exec|
{
match exec.get()
{
Some(e) => e.spawn_handle( fut ) ,
None => Err( ErrorKind::NoExecutorInitialized.into() ) ,
}
})
}
pub fn spawn_handle_local<T: 'static + Send>( fut: impl Future< Output=T > + 'static )
-> Result< Box< dyn Future< Output=T > + 'static + Unpin >, Error >
{
EXEC.with( move |exec|
{
match exec.get()
{
Some(e) => e.spawn_handle_local( fut ) ,
None => Err( ErrorKind::NoExecutorInitialized.into() ) ,
}
})
}
pub fn current_rt() -> Option<Config>
{
EXEC.with( move |exec|
{
exec.get().map( |e| e.config() )
})
}
#[ cfg(not( target_arch = "wasm32" )) ]
pub fn block_on< F: Future >( fut: F ) -> F::Output
{
futures::executor::block_on( fut )
}