Synchronous and Asynchronous Synchronization Primitives
Word-sized low-level synchronization primitives providing both asynchronous and synchronous interfaces.
Features
- No heap allocation.
- No hidden global variables.
- Provides both asynchronous and synchronous interfaces.
- Small memory footprint.
Loomsupport:features = ["loom"].
Lock
saa::Lock is a low-level shared-exclusive lock providing both asynchronous and synchronous interfaces. Synchronous locking methods such as lock_sync and share_sync can be used alongside their asynchronous counterparts lock_async and share_async simultaneously. saa::Lock implements an allocation-free fair wait queue shared between both synchronous and asynchronous methods.
Examples
use Lock;
let lock = default;
lock.lock_sync;
assert!;
assert!;
assert!;
assert!;
async ;
Barrier
saa::Barrier is a synchronization primitive to enable a number of tasks to start execution at the same time.
use Arc;
use thread;
use Barrier;
let barrier = new;
let mut threads = Vecnew;
for _ in 0..8
for thread in threads
Semaphore
saa::Semaphore is a synchronization primitive that allows a fixed number of threads to access a resource concurrently.
Examples
use Semaphore;
let semaphore = default;
semaphore.acquire_many_sync;
assert!;
assert!;
assert!;
assert!;
assert!;
async ;
Gate
saa::Gate is an unbounded barrier that can be opened or sealed manually as needed.
Examples
use Arc;
use thread;
use Gate;
use State;
let gate = new;
let mut threads = Vecnew;
for _ in 0..4
let mut count = 0;
while count != 4
for thread in threads
Pager
saa::Pager enables remotely waiting for a resource to become available.
Examples
use pin;
use ;
use State;
let gate = default;
let mut pinned_pager = pin!;
assert!;
assert_eq!;
assert_eq!;
Notes
Using synchronous methods in an asynchronous context may lead to deadlocks. Consider a scenario where an asynchronous runtime uses two threads to execute three tasks.
- ThreadId(0):
task-0: share-waiting / pending||task-1: "synchronous"-lock-waiting. - ThreadId(1):
task-2: release-lock / ready: wake-up task-0->task-2: lock-waiting / pending.
In this example, task-0 has logically acquired a shared lock transferred from task-2; however, it may remain in the task queue indefinitely depending on the asynchronous runtime's scheduling policy.