[](https://crates.io/crates/safina)
[](http://www.apache.org/licenses/LICENSE-2.0)
[](https://github.com/rust-secure-code/safety-dance/)
[](https://gitlab.com/leonhard-llc/safina-rs/-/pipelines)
A safe Rust async runtime.
# Features
- `forbid(unsafe_code)`
- Depends only on `std` at runtime
- Good test coverage (>80%)
- Good performance
# Limitations
- No `fs` module yet.
[async-fs](https://crates.io/crates/async-fs) is a fast async networking library
that works well with Safina. It contains some unsafe code.
- The `net` module has poor performance.
[async-net](https://crates.io/crates/async-net) is a fast async networking library
that works well with Safina. It contains some unsafe code.
# Benchmark
```
% ulimit -n 100000 && cargo run --release --package bench
safina tokio
schedule 554ns 635ns
yield 1150ns 729ns
sleep 814ns 842ns
mutex 14201ns 14768ns
oneshot 2510ns 810ns
channel 2526ns 863ns
tcp_echo 28502ns 8187ns
```
[safina-rs/bench/src/main.rs](https://gitlab.com/leonhard-llc/safina-rs/-/blob/main/bench/src/main.rs)
# Examples
```rust
use std::sync::Arc;
use safina::executor::Executor;
let executor: Arc<Executor> = Arc::default();
let (sender, receiver) = std::sync::mpsc::channel();
executor.spawn(async move {
sender.send(()).unwrap();
});
receiver.recv().unwrap();
```
```rust
let result = safina::executor::block_on(async {
prepare_request().await?;
execute_request().await
})?;
```
# Alternatives
- [smol](https://crates.io/crates/smol)
- Popular
- Contains some `unsafe` code
- [async-std](https://crates.io/crates/async-std)
- Very popular
- Contains generous amounts of `unsafe` code
- [futures](https://crates.io/crates/futures)
- Very popular
- Contains generous amounts of `unsafe` code
- [tokio](https://crates.io/crates/tokio)
- Very popular
- Fast
- Internally extremely complicated
- Full of `unsafe` code
- [bastion](https://crates.io/crates/bastion)
- Generous amounts of `unsafe` code
- [`nostd_async`](https://crates.io/crates/nostd_async)
# Cargo Geiger Safety Report
```
Metric output format: x/y
x = unsafe code used by the build
y = total unsafe code found in the crate
Symbols:
🔒 = No `unsafe` usage found, declares #![forbid(unsafe_code)]
❓ = No `unsafe` usage found, missing #![forbid(unsafe_code)]
☢️ = `unsafe` usage found
Functions Expressions Impls Traits Methods Dependency
0/0 0/0 0/0 0/0 0/0 🔒 safina 0.7.1
0/0 0/0 0/0 0/0 0/0 🔒 └── safina-macros 0.1.3
0/0 0/0 0/0 0/0 0/0 🔒 ├── safe-proc-macro2 1.0.95
0/0 0/0 0/0 0/0 0/0 🔒 │ └── unicode-xid 0.2.6
0/0 0/0 0/0 0/0 0/0 🔒 └── safe-quote 1.0.40
0/0 0/0 0/0 0/0 0/0 🔒 └── safe-proc-macro2 1.0.95
0/0 0/0 0/0 0/0 0/0
```
# Changelog
<details>
<summary>Changelog</summary>
- v0.7.1 2025-07-01
- Add `yield_once()`
- v0.7.0 2025-06-30
- Require Rust 2024 edition.
- Add `OptionAb::into_a`, etc.
- Threadpool queue is now unbounded, removed `TryScheduleError::QueueFull`.
- `SyncSender` no longer requires `Clone`.
- After Executor drops, silently discard new tasks and don't panic.
- Add `Executor::get_thread_executor_weak`.
- v0.6.0 2024-11-02 - Simplify `ExecutorBuilder`.
- v0.5.0 2024-10-27 - Add `ExecutorBuilder` and simplify `Executor` constructors.
- v0.4.1 2024-10-27 - Improve `async_test`:
- Make `async_test` a default feature so it shows up in docs.rs.
- Timeout after 5s.
- Override timeout with `#[async_test(timeout_sec = 1)]`.
- Support `#[should_panic]` and other test modifier macros.
- Stop adding `_` to the end of the test name.
- v0.4.0 2024-10-26 - Merge crates into this crate.
- [safina-async-test](https://crates.io/crates/safina-async-test)
- [safina-async-test-core](https://crates.io/crates/safina-async-test-core)
(to [safina-macros](https://crates.io/crates/safina-macros) crate)
- [safina-executor](https://crates.io/crates/safina-executor)
- [safina-net](https://crates.io/crates/safina-net)
- [safina-select](https://crates.io/crates/safina-select)
- [safina-sync](https://crates.io/crates/safina-sync)
- [safina-threadpool](https://crates.io/crates/safina-threadpool)
- [safina-timer](https://crates.io/crates/safina-timer)
- v0.3.3 - Update docs.
- v0.3.2 - Add `threadpool` module.
- v0.3.1
- Add `sync_channel` and `SyncSender`.
- Add `Receiver::async_recv` to let users await without writing ugly `(&mut receiver).await`.
- Remove `Receiver::blocking` and add `try_recv`, `recv`, etc.
- v0.3.0
- Move structs into sub-modules.
- Replace `Promise` with `oneshot`, `OneSender`, and `Receiver` that supports async and blocking reads.
- `schedule_blocking` to return new `sync::Receiver`.
- v0.2.1 - Update docs.
- v0.2.0
- `Executor::new` and `Executor::with_name` to return `Result`.
- `ThreadPool::new` to return `Result`.
- `ThreadPool::try_schedule` to return an error when it fails to restart panicked threads.
- `ThreadPool::schedule` to handle failure starting replacement threads.
- v0.1.10 - `block_on` functions to take futures that are not `Send`.
- v0.1.9 - Use `once_cell` by default.
- v0.1.8 - Support stable with rust 1.51 and `once_cell`.
- v0.1.7 - Add [safina-net](https://crates.io/crates/safina-net)
- v0.1.6 - Use [safina-executor](https://crates.io/crates/safina-executor) v0.1.3 API
- v0.1.5 - Add [`safina::sync::Mutex`](https://docs.rs/safina-sync/latest/safina::sync/struct.Mutex.html)
- v0.1.4 - Upgrade to new safina-executor version which removes need for `Box::pin`.
- v0.1.3 - Update docs
- 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
</details>
# TO DO
- Add `init` function that makes an executor and starts the timer thread.
- Add an `#[async_main]` macro
- `safina::sync::unbounded_channel()`
- Make [`safina::sync::MutexGuard`] Send.
License: Apache-2.0