Summary
AtomicCell<T> provides a cell-like box-like lock-free mechanism for shared objects.
Motivation
Rust has the following synchronization... things:
Mutex<T>
AtomicPtr<T>
- Maybe a few other things (
RwLock<T>? who uses that? :p)
But besides AtomicPtr<T>, which is unsafe, there's nothing that can do compare-and-swap-ey lock-free operations on stuff.
Guide
AtomicCell<T> provides a way to work with/protect shared data without locking. This is in contrast to Mutex<T>, which locks the data to a specific thread.
[TODO not described]
Implementation
An AtomicCell<T> is vaguely similar to a Cell<T> or a Mutex<T>, and much closer to a Box<T>. It provides (at least) the following methods:
fn new(start_value: T) -> AtomicCell<T>;
fn swap(&self, other: &AtomicCell<T> /* perhaps an Ordering? */) /* -> bool ?*/;
fn get(&self /* perhaps an Ordering? */) -> T where T: Copy;
fn set(&self, val: T /* perhaps an Ordering? */);
fn replace(&self, val: T /* perhaps an Ordering? */) -> T;
It's mainly a safe wrapper around AtomicPtr<T>, and swap is more efficient than replace.
This efficiency difference boils down to heap allocations: AtomicCell<T> is similar to Box<T>, which means it has to allocate T in memory. When you have two AtomicCell<T>s, swap can simply swap their pointers, while with replace you first need to allocate heap memory for the new value, swap that pointer, and then read the resulting pointer.
Drawbacks
- This lacks a compare-and-swap mechanism. I couldn't figure this one out.
- Like any additions to the standard library, this increases its complexity, which implies an increase in maintenance costs (code, documentation, tutorials).
Rationale and Alternatives
One could think of adding swap to Mutex<T>. However, Mutex<T> stores the data in the structure itself, not on the heap, which means you can't use compare-and-swap/lock-free operations on it.
One alternative is to add swapping straight to Arc<Mutex<T>> instead. This seems rather awkward tho.
Unresolved questions
Currently:
- Should we use
Ordering?
- I don't know how
Ordering works.
- Is there any way to add a zero-cost compare-and-swap mechanism, or should we defer the cost to the user?
- Mainly, if the type is bigger than the hardware's compare-and-swap instruction, or if the
Eq/PartialEq isn't a raw memory equality, it gets really tricky really fast.
- Do the benefits outweigh the maintenance costs?
- How do we explain this to new users? Can we explain it differently to experienced users?
Summary
AtomicCell<T>provides a cell-like box-like lock-free mechanism for shared objects.Motivation
Rust has the following synchronization... things:
Mutex<T>AtomicPtr<T>RwLock<T>? who uses that? :p)But besides
AtomicPtr<T>, which is unsafe, there's nothing that can do compare-and-swap-ey lock-free operations on stuff.Guide
AtomicCell<T>provides a way to work with/protect shared data without locking. This is in contrast toMutex<T>, which locks the data to a specific thread.[TODO not described]
Implementation
An
AtomicCell<T>is vaguely similar to aCell<T>or aMutex<T>, and much closer to aBox<T>. It provides (at least) the following methods:It's mainly a safe wrapper around
AtomicPtr<T>, andswapis more efficient thanreplace.This efficiency difference boils down to heap allocations:
AtomicCell<T>is similar toBox<T>, which means it has to allocateTin memory. When you have twoAtomicCell<T>s,swapcan simply swap their pointers, while withreplaceyou first need to allocate heap memory for the new value, swap that pointer, and then read the resulting pointer.Drawbacks
Rationale and Alternatives
One could think of adding swap to
Mutex<T>. However,Mutex<T>stores the data in the structure itself, not on the heap, which means you can't use compare-and-swap/lock-free operations on it.One alternative is to add swapping straight to
Arc<Mutex<T>>instead. This seems rather awkward tho.Unresolved questions
Currently:
Ordering?Orderingworks.Eq/PartialEqisn't a raw memory equality, it gets really tricky really fast.