pub struct Sack<T> { /* private fields */ }Expand description
A lock-free sack data structure.
A sack is a concurrent data structure that allows adding items and draining them in a lock-free manner. It is implemented as a singly-linked list where the head is an atomic pointer. This allows multiple producers to add items concurrently without locks.
§How it works
The Sack is essentially a LIFO (last-in, first-out) stack. When an item is
added, it is pushed to the front of the list. When the sack is drained, the
entire list is atomically swapped with an empty list, and the old list is
returned as a draining iterator.
This design has the following properties:
- Lock-free: Adding and draining items are lock-free operations, which means they don’t require mutual exclusion. This makes them very fast and scalable.
- Concurrent producers: Multiple threads can add items to the sack concurrently.
- Single consumer: Only one thread can drain the sack at a time. This is
enforced by the
&selfreceiver on thedrainmethod.
§Example
use sack::Sack;
use std::sync::Arc;
use std::thread;
let sack = Arc::new(Sack::new());
// Spawn a producer thread.
let producer = {
let sack = Arc::clone(&sack);
thread::spawn(move || {
for i in 0..10 {
sack.add(i);
}
})
};
// Wait for the producer to finish.
producer.join().unwrap();
// Drain the sack and collect the items.
let mut items: Vec<_> = sack.drain().collect();
items.sort();
assert_eq!(items, (0..10).collect::<Vec<_>>());Implementations§
Source§impl<T> Sack<T>
impl<T> Sack<T>
Trait Implementations§
Auto Trait Implementations§
impl<T> !Freeze for Sack<T>
impl<T> RefUnwindSafe for Sack<T>
impl<T> Send for Sack<T>
impl<T> Sync for Sack<T>
impl<T> Unpin for Sack<T>
impl<T> UnwindSafe for Sack<T>where
T: RefUnwindSafe,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more