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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
//! [![crates.io version](https://img.shields.io/crates/v/safina-sync.svg)](https://crates.io/crates/safina-sync)
//! [![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)
//!
//! Structs for sharing or sending data between async tasks.
//!
//! It is part of [`safina`](https://crates.io/crates/safina), a safe async runtime.
//!
//! # Features
//! - `Mutex` with an async lock method
//! - `oneshot` and `sync_channel` with async and blocking methods
//! - `forbid(unsafe_code)`
//! - Depends only on `std`
//! - 100% test coverage
//! - Works with [`safina-executor`](https://crates.io/crates/safina-executor) or any async executor
//!
//! # Limitations
//! - Allocates
//! - No const constructor.
//!   Uses `std::sync::Mutex` internally, which does not have a const constructor.
//!   See [rust#66806](https://github.com/rust-lang/rust/issues/66806)
//!   and [const-eval#3](https://github.com/rust-lang/const-eval/issues/3).
//!   You can work around this with unstable
//!   [`core::lazy::OnceCell`](https://doc.rust-lang.org/core/lazy/struct.OnceCell.html)
//!   or various `unsafe` crates:
//!   [`lazy_static`](https://crates.io/crates/lazy_static),
//!   [`once_cell`](https://crates.io/crates/once_cell),
//!   [`lazycell`](https://crates.io/crates/lazycell), and
//!   [`conquer-once`](https://crates.io/crates/conquer-once).
//!
//! # Documentation
//! <https://docs.rs/safina-sync>
//!
//! # Examples
//! ```rust
//! use std::sync::Arc;
//! use safina_async_test::async_test;
//! use safina_sync::Mutex;
//! # async fn some_async_fn() {}
//! # fn get_shared_data() -> Arc<Mutex<u32>> {
//! #     Arc::new(Mutex::new(0))
//! # }
//! # #[async_test]
//! # async fn test1() {
//! #     let addr = String::new();
//! let shared_counter: Arc<Mutex<u32>> = get_shared_data();
//! {
//!     let mut counter_guard = shared_counter.lock().await;
//!     *counter_guard += 1;
//!     // some_async_fn().await; // Cannot await while holding a MutexGuard.
//! }
//! some_async_fn().await; // Await is ok after releasing MutexGuard.
//! # }
//! ```
//!
//! # Alternatives
//! - [async-lock](https://crates.io/crates/async-lock)
//!   - Contains a little `unsafe` code
//! - [futures-locks](https://crates.io/crates/futures-locks)
//!   - Contains a little `unsafe` code
//! - [futures-util](https://crates.io/crates/futures-util)
//!   - Very popular
//!   - Full of `unsafe`
//! - [tokio-sync](https://crates.io/crates/tokio-sync)
//!   - Very popular
//!   - Fast
//!   - Internally incredibly complicated
//!   - Full of `unsafe`
//!
//! # Changelog
//! - v0.2.4
//!   - Implement `Eq` and `PartialEq` for `Receiver`, `OneSender`, and `SyncSender`.
//!   - Fix bug where `await` on `Receiver` would not wake senders.
//! - v0.2.3 Fix race condition.
//! - v0.2.2 Fix deadlock on Linux.
//! - v0.2.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.2.0 - Replace `Promise` with `oneshot`, `OneSender`, and `Receiver` that supports async and blocking reads.
//! - v0.1.6 - Update docs.
//! - v0.1.5 - Update docs
//! - v0.1.4 - Update docs, make `MutexGuard::new` non-public
//! - v0.1.3 - Fix Promise type parameter
//! - v0.1.2 - Add Promise
//! - v0.1.1 - Improve Mutex performance when there are many waiters
//! - v0.1.0 - First published version
//!
//! # TO DO
//! - Add `Barrier`
//! - Add `RwLock`
//! - Add `WaitableBool`
//! - Add `UnboundedChannel`
//! - Add `WaitableQueue` (multiple receivers)
//! - Add `UnboundedWaitableQueue`
//! - Add `Topic` (copies message to every receiver)
//!
//! # Release Process
//! 1. Edit `Cargo.toml` and bump version number.
//! 1. Run `./release.sh`
#![forbid(unsafe_code)]

mod mutex;
pub use mutex::*;

mod channel;
pub use channel::*;