Skip to content
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
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,15 @@ All notable changes to this project will be documented in this file.
### New features

* Add an opt-in `asyncband::blocking::FutureExt` bridge with `block_on` and `wait_timeout` methods for waiting on runtime-agnostic futures from synchronous code.
* Add SPSC, MPSC, SPMC, and MPMC queues with rendezvous, bounded, and unbounded capacities.
* Add overflow, backpressure, and unbounded broadcast retention policies.
* Add coalescing watch channels and single-producer and multi-producer Disruptor-style multicast sequencers.
* Add `sync`, `channel`, and `coordination` public module and Cargo feature groups.

### Breaking changes

* Gate all exported primitives behind opt-in Cargo features and enable no features by default; downstream dependencies must explicitly enable the APIs they use.
* Group all channel families under `asyncband::channel` and remove the previous root-level oneshot, MPSC, and broadcast implementations.
* Remove `admission::FairShare` and its `admission` Cargo feature from the feature set.
* Remove the `asyncband::atomicbox` module and its `AtomicBox` and `AtomicOptionBox` types from the public API.
* Rename `oneshot::Sender::is_closed` and `oneshot::Receiver::is_closed` to `is_disconnected`.
Expand Down
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 9 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Asyncband is a runtime-agnostic library providing essential synchronization prim

## Available primitives

The crate enables no primitives by default. Categories describe each primitive's primary purpose and do not add another module level, so public paths remain concise, such as `asyncband::mutex` and `asyncband::once::OnceCell`.
The crate enables no primitives by default. Synchronization primitives retain their existing root paths, while transfer APIs are grouped under `asyncband::channel`. The `sync`, `channel`, and `coordination` umbrella features enable their corresponding leaf features.

| Category | Primitive | Feature | Purpose |
| ----------------------- | ------------------------------------------------------------------------------------ | -------------- | ----------------------------------------------------------------------- |
Expand All @@ -44,13 +44,16 @@ The crate enables no primitives by default. Categories describe each primitive's
| | [`Latch`](https://docs.rs/asyncband/*/asyncband/latch/struct.Latch.html) | `latch` | Wait until a one-way countdown completes. |
| | [`WaitGroup`](https://docs.rs/asyncband/*/asyncband/waitgroup/struct.WaitGroup.html) | `waitgroup` | Wait for a dynamic group of tasks to finish. |
| | [`shutdown`](https://docs.rs/asyncband/*/asyncband/shutdown/) | `shutdown` | Coordinate shutdown signals and completion. |
| Channels | [`oneshot::channel`](https://docs.rs/asyncband/*/asyncband/oneshot/fn.channel.html) | `oneshot` | Send one value between two tasks. |
| | [`mpsc::bounded`](https://docs.rs/asyncband/*/asyncband/mpsc/fn.bounded.html) | `mpsc` | Send values from multiple producers through a bounded channel. |
| | [`mpsc::unbounded`](https://docs.rs/asyncband/*/asyncband/mpsc/fn.unbounded.html) | `mpsc` | Send values from multiple producers through an unbounded channel. |
| | [`broadcast::overflow`](https://docs.rs/asyncband/*/asyncband/broadcast/overflow/) | `broadcast` | Broadcast values and report when slow receivers miss overwritten items. |
| Channels | [`channel::oneshot`](https://docs.rs/asyncband/*/asyncband/channel/oneshot/) | `oneshot` | Send one value between two tasks. |
| | [`channel::{spsc,mpsc,spmc,mpmc}`](https://docs.rs/asyncband/*/asyncband/channel/) | `queue` | Send each value to one competing receiver. |
| | [`channel::broadcast`](https://docs.rs/asyncband/*/asyncband/channel/broadcast/) | `broadcast` | Select overflow, backpressure, or unbounded multicast retention. |
| | [`channel::watch`](https://docs.rs/asyncband/*/asyncband/channel/watch/) | `watch` | Distribute the latest state and coalesce intermediate versions. |
| | [`channel::disruptor`](https://docs.rs/asyncband/*/asyncband/channel/disruptor/) | `disruptor` | Publish through bounded sequenced multicast rings. |
| Workload control | [`Semaphore`](https://docs.rs/asyncband/*/asyncband/semaphore/struct.Semaphore.html) | `semaphore` | Control concurrent access with permits. |
| | [`Group`](https://docs.rs/asyncband/*/asyncband/singleflight/struct.Group.html) | `singleflight` | Coalesce concurrent calls for the same key. |

See the [channel design for 0.7](docs/channel-design.md) for the topology matrix, overload policies, cancellation rules, and Disruptor invariants.

## Installation

Add the dependency to your `Cargo.toml` via:
Expand Down Expand Up @@ -99,7 +102,7 @@ All synchronization primitives in this library are runtime-agnostic, meaning the

## Thread Safety

Asyncband primitives and guards implement `Send` and `Sync` only when the protected or transferred value satisfies the necessary bounds. In particular, owned read guards that may move destruction to another thread require the protected value to be `Send` as well as `Sync`. See each type's documentation for its exact bounds.
Asyncband primitives and guards implement `Send` and `Sync` only when the protected or transferred value satisfies the necessary bounds. In particular, owned read guards that may move destruction to another thread require the protected value to be `Send` as well as `Sync`. A channel endpoint is cloneable and `Sync` only when its topology supports multiple producers or consumers; single-side endpoints require exclusive access. See each type's documentation for its exact bounds.

## Minimum Supported Rust Version (MSRV)

Expand Down
22 changes: 21 additions & 1 deletion asyncband/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,30 +38,50 @@ rustdoc-args = ["--cfg", "docsrs"]
[features]
default = []

channel = ["broadcast", "disruptor", "oneshot", "queue", "watch"]
coordination = ["shutdown", "singleflight"]
full = ["blocking", "channel", "coordination", "sync"]
sync = [
"barrier",
"condvar",
"latch",
"mutex",
"once",
"once-cell",
"once-map",
"rwlock",
"semaphore",
"waitgroup",
]

barrier = []
blocking = []
broadcast = []
condvar = ["mutex"]
disruptor = []
latch = []
mpsc = []
mutex = []
once = ["semaphore"]
once-cell = ["semaphore"]
once-map = ["dep:hashbrown", "once-cell"]
oneshot = []
queue = []
rwlock = []
semaphore = []
shutdown = ["latch", "waitgroup"]
singleflight = ["dep:hashbrown", "once-cell"]
waitgroup = []
watch = []

[dependencies]
hashbrown = { workspace = true, default-features = false, features = [
"inline-more",
], optional = true }

[dev-dependencies]
pollster.workspace = true
tokio = { workspace = true, features = ["full"] }
tokio-test.workspace = true

[lints]
workspace = true
Loading