#async #atomic #tokio #loom


Easy switching between std::sync, tokio::sync and loom::sync

8 releases

0.2.8 Aug 4, 2021
0.2.7 Aug 4, 2021
0.1.3 Jul 31, 2021

#618 in Concurrency

27 downloads per month

MIT license

226 lines



crate.io downloads

crate.io version


Easy switching between std::sync, tokio::sync and loom::sync


This crate provides two modules sync and atomic.

Module atomic provides atomic primitives that are typedefs to core::sync::atomic by default and loom::sync::atomic when feature permutation_testing is enabled.

Module sync is similar to module atomic -- it provides primitives from std::sync on default, tokio::sync on async_tokio and loom::sync on permutation_testing.

Currently, it only provides Arc and RwLock, but more primitives will be added in future.

It also comes with unified typedef to deal with the difference between these libraries:

  • RwLockReadGuard
  • RwLockWriteGuard
  • LockResult
  • TryLockResult

There is also macros to deal with the difference between calling to asynchronous and synchronous function in Rust:

  • obtain_read_lock!(reference to rwlock)
  • obtain_write_lock!(reference to rwlock)

To create a function uses sync::RwLock, uses concurrency_toolkit::maybe_async::maybe_async, which automatically removes all async-related keywords if async_tokio is not used.

Example for using concurrency_toolkit::maybe_async::maybe_async:

use concurrency_toolkit::maybe_async::maybe_async;
use concurrency_toolkit::sync::{RwLock, obtain_read_lock, obtain_write_lock};

fn get(rwlock: &RwLock<i32>) -> i32 {

fn set(rwlock: &RwLock<i32>, val: i32) {
    *obtain_write_lock!(rwlock).unwrap() = val;

fn add(rwlock: &RwLock<i32>, val: i32) {
    set(rwlock, get(rwlock).await + val).await;


This crate provides proc macro concurrency_toolkit::test to run your test:

fn test() {
    // ...

It will automatically start async runtime or call loom::model for you if required.

However, unlike maybe_async::maybe_async, this proc macro requires the function to not be declared as async due to implementation detail (syn doesn't provides an easy way to parse async function), but it still can remove async-related keywords just like maybe_async::maybe_async`.


This crate currently supports 3 features:

  • default where std::sync is used;
  • async_tokio where tokio::sync is used in mod sync and std::sync::atomic is used for mod atomic;
  • permutation_testing where loom::sync is used.

These features are exclusive, so I recommend you to use default-features = false when adding this crate as a dependency and let the user to explicitly opt-in features they want.


~459K SLoC