compact_waitgroup/lib.rs
1//! A compact asynchronous WaitGroup synchronization primitive.
2//!
3//! # Usage
4//!
5//! ## [`MonoWaitGroup`]
6//!
7//! ```rust
8//! # use compact_waitgroup::MonoWaitGroup;
9//! # futures_executor::block_on(async {
10//! let (wg, handle) = MonoWaitGroup::new();
11//! assert!(!wg.is_done());
12//! std::thread::spawn(move || {
13//! // Long-running task
14//! handle.done();
15//! });
16//! // Wait for the task to complete
17//! wg.await;
18//! # });
19//! ```
20//!
21//! ## [`WaitGroup`]
22//!
23//! ```rust
24//! # use compact_waitgroup::WaitGroup;
25//! # futures_executor::block_on(async {
26//! let (wg, handle) = WaitGroup::new();
27//! let handle_cloned = handle.clone();
28//! assert!(!wg.is_done());
29//! std::thread::spawn(move || {
30//! // Long-running task
31//! handle_cloned.done();
32//! });
33//! std::thread::spawn(move || {
34//! // Another long-running task
35//! handle.done();
36//! });
37//! // Wait for all tasks to complete
38//! wg.await;
39//! # });
40//! ```
41//!
42//! # Memory Layout
43//!
44//! This crate is designed to be extremely lightweight. The memory footprint
45//! depends on the architecture and the enabled features.
46//!
47//! By default, [`MonoWaitGroup`] shares the same underlying memory structure as
48//! [`WaitGroup`]. However, this means [`MonoWaitGroup`] carries a `usize` field
49//! for reference counting of workers, which is redundant for the singly-owned
50//! [`MonoWorkerHandle`].
51//!
52//! Enabling the `compact-mono` feature changes the internal definition of
53//! [`MonoWaitGroup`]. It switches to a dedicated, stripped-down layout that
54//! removes the reference counter.
55//!
56//! | Component | Default (64-bit) | With `compact-mono` (64-bit) | Saving |
57//! | --- | --- | --- | --- |
58//! | **[`WaitGroup`]** | 32 bytes | 32 bytes | 0 bytes |
59//! | **[`MonoWaitGroup`]** | **32 bytes** | **24 bytes** | **8 bytes** |
60//!
61//! **Note**:
62//! - Sizes include the [`core::task::Waker`] (16 bytes) and required alignment
63//! padding.
64//! - 32 bytes is often more friendly to global memory allocators.
65#![no_std]
66extern crate alloc;
67
68mod core_impl;
69mod state;
70mod twin_ref;
71mod utils;
72mod wait_group;
73
74pub use crate::wait_group::{MonoWaitGroup, MonoWorkerHandle, WaitGroup, WorkerHandle};
75
76#[cfg(test)]
77mod tests;