[go: up one dir, main page]

saa 0.3.0

Low-level synchronization primitives that provide both synchronous and asynchronous interfaces
Documentation
saa-0.3.0 has been yanked.

Synchronous and Asynchronous Synchronization Primitives

Cargo Crates.io GitHub Workflow Status

Low-level synchronization primitives that provide both synchronous and asynchronous interfaces.

Features

  • Asynchronous counterparts of synchronous methods.
  • Loom support: features = ["loom"].
  • No spin-locks and no busy loops.

Lock

saa::Lock is a Low-level shared-exclusive lock that provides both synchronous and asynchronous interfaces. Synchronous locking methods such as lock_exclusive_sync or lock_shared_sync can be used with their asynchronous counterparts, lock_exclusive_async or lock_shared_async, at the same time. saa::Lock implements a heap-allocation-free fair wait queue that is shared among both synchronous and asynchronous methods.

Notes

Use of synchronous methods in an asynchronous context may lead to a deadlock. Suppose a scenario where an asynchronous runtime provides two threads executing three tasks.

  • ThreadId(0): task-0: shared-lock-waiting / pending || task-1: "synchronous"-exclusive-lock-waiting.
  • ThreadId(1): task-2: release-exclusive-lock / ready: wake-up task-0 -> task-2: exclusive-lock-waiting / pending.

In the above example, task-0 logically has acquired a shared lock which was transferred from task-2, it may remain in the task queue indefinitely, depending on the scheduling policy of the asynchronous runtime.

Examples

use saa::Lock;

let lock = Lock::default();

lock.lock_exclusive_sync();

assert!(!lock.try_lock_exclusive());
assert!(!lock.try_lock_shared());

assert!(!lock.unlock_shared());
assert!(lock.unlock_exclusive());

async {
    lock.lock_shared_async();
    assert!(lock.unlock_shared());
};

Semaphore

saa::Semaphore is a synchronization primitive that allows a fixed number of threads to access a resource concurrently.

Examples

use saa::Semaphore;

let semaphore = Semaphore::default();

semaphore.acquire_many_sync(Semaphore::MAX_PERMITS - 1);

assert!(semaphore.try_acquire());
assert!(!semaphore.try_acquire());

assert!(semaphore.release());
assert!(!semaphore.release_many(Semaphore::MAX_PERMITS));
assert!(semaphore.release_many(Semaphore::MAX_PERMITS - 1));

async {
    semaphore.acquire_async().await;
    assert!(semaphore.release());
};

Changelog