1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
//! [![crates.io version](https://img.shields.io/crates/v/safina.svg)](https://crates.io/crates/safina)
//! [![license: Apache 2.0](https://gitlab.com/leonhard-llc/safina-rs/-/raw/main/license-apache-2.0.svg)](http://www.apache.org/licenses/LICENSE-2.0)
//! [![unsafe forbidden](https://gitlab.com/leonhard-llc/safina-rs/-/raw/main/unsafe-forbidden-success.svg)](https://github.com/rust-secure-code/safety-dance/)
//! [![pipeline status](https://gitlab.com/leonhard-llc/safina-rs/badges/main/pipeline.svg)](https://gitlab.com/leonhard-llc/safina-rs/-/pipelines)
//!
//! A safe Rust async runtime.
//!
//! # Features
//! - `forbid(unsafe_code)`
//! - Depends only on `std`
//! - Good test coverage (>92%)
//!
//! # Limitations
//! - Requires Rust `nightly`, for
//!   [OnceCell](https://doc.rust-lang.org/std/lazy/struct.OnceCell.html)
//!   and
//!   [Wake trait](https://doc.rust-lang.org/std/task/trait.Wake.html)
//! - Allocates memory.  You can avoid allocations by using advanced functions, like
//!   [`safina_executor::spawn_unpin`](https://docs.rs/safina-executor/latest/safina_executor/fn.spawn_unpin.html).
//! - Not optimized
//!
//! # Documentation
//! https://docs.rs/safina
//!
//! [`safina_async_test`](https://crates.io/crates/safina_async_test)
//! has an `#[async_test]` macro for running `async fn` test functions.
//!
//! # Examples
//! ```rust
//! # fn f() {
//! safina::increase_threads_to(1);
//! let (sender, receiver) = std::sync::mpsc::channel();
//! safina::spawn(async move {
//!     sender.send(()).unwrap();
//! });
//! receiver.recv().unwrap();
//! # }
//! ```
//!
//! ```rust
//! # async fn prepare_request() -> Result<(), std::io::Error> { Ok(()) }
//! # async fn execute_request() -> Result<(), std::io::Error> { Ok(()) }
//! # fn f() -> Result<(), std::io::Error> {
//! std::thread::spawn(safina_executor::work);
//! let result = safina::block_on(async {
//!     prepare_request().await?;
//!     execute_request().await
//! })?;
//! # Ok(())
//! # }
//! ```
//!
//! # Alternatives
//! - [smol](https://crates.io/crates/smol)
//!   - Popular
//!   - Contains generous amounts of `unsafe` code
//! - [async-std](https://crates.io/crates/async-std)
//!   - Very popular
//!   - Contains generous amounts of `unsafe` code
//! - [tokio](https://crates.io/crates/tokio)
//!   - Very popular
//!   - Fast
//!   - Internally extremely complicated
//!   - Full of `unsafe`
//! - [nostd_async](https://crates.io/crates/nostd_async)
//!
//! # Changelog
//! - v0.1.3 - Update readme
//! - v0.1.2 - Renamed `safina` crate to `safina-executor`.
//!   Added new `safina` crate with re-exports, examples, and integration tests.
//! - v0.1.1 - Add badges to readme
//! - v0.1.0 - First published version
//!
//! # TO DO
//! - Add an integration test
//! - Add `init` function that starts worker threads and the timer thread.
//! - Make it work on Rust stable
//! - Add an #[async_main] macro
//!
//! # Release Process
//! 1. Edit `Cargo.toml` and bump version number.
//! 1. Run `./release.sh`
#![forbid(unsafe_code)]

pub use safina_executor::{block_on, increase_threads_to, spawn, work};
pub use safina_select::{
    select_ab, select_abc, select_abcd, select_abcde, OptionAB, OptionABC, OptionABCD, OptionABCDE,
};
pub use safina_timer::{
    sleep_for, sleep_until, start_timer_thread, with_deadline, with_timeout, DeadlineExceeded,
};