3 releases (breaking)

0.3.0 Dec 15, 2024
0.2.0 Dec 8, 2024
0.1.0 Dec 6, 2024

#282 in Concurrency

Download history 171/week @ 2024-12-02 144/week @ 2024-12-09 71/week @ 2024-12-16

386 downloads per month

MIT license

39KB
846 lines

This crate implements three lock-free structures for object transfers:

  • an AtomicSlot<T> type
  • small one-shot SPSC channels
  • fully-featured MPMC channels

All of these structures are synchronized without any locks and without spinning/yielding. This crate is compatible with no_std targets, except for the _blocking methods.

AtomicSlot<T>

You can atomically swap the contents of this slot from any thread. Think of it as Mutex<Option<Box<T>>> without any actual locking.

One shot SPSC channels

let (tx, rx) = async_fifo::slot::oneshot();
let item = "Hello, world!";
tx.send(Box::new(item));

let _task = async {
    assert_eq!(*rx.await, item);
};

Very simple single-use channels with a sync and async API, blocking/non-blocking. This builds on AtomicSlot<T>, so the item has to be boxed. Most useful for the transfer of return values in the context of remote procedure calling, as "reply pipes".

let (tx, [mut rx1, mut rx2]) = async_fifo::fifo::new();
let item = "Hello, world!";
tx.send(item);
assert_eq!(rx2.try_recv(), Some(item));

// producers can be cloned
let _tx2 = tx.clone();

// asynchronous use
let _task = async {
    loop {
        println!("Received: {:?}", rx1.recv().await);
    }
};

These channels have the following characteristics:

  • Multi-Producer / Multi-Consumer (MPMC) with every item routed to exactly one consumer
  • Asynchronous and synchronous API, both blocking and non-blocking
  • Strict delivery order: these channels have strong FIFO guarantees
  • Batch production and consumption (both atomic)
  • Send operations are guaranteed to succeed immediately without any sort of yielding/blocking
  • Producers can be cloned (but not consumers)

Internal Details

Fifos internally own a chain of blocks.

  • blocks have a number of item slots (32 by default)
  • they are allocated and appended to the chain by producers
  • they are then populated by producers and consumed by consumers
  • fully consumed first blocks get recycled and appended again at the end of the chain (when no one is visiting them anymore)
  • the fifo has atomic cursors to track which block slots are available for production and consumption

No runtime deps

Features