Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/aarc-rs/aarc

Atomically updatable variants of Arc and Weak for lock-free concurrency.
https://github.com/aarc-rs/aarc

Last synced: 7 days ago
JSON representation

Atomically updatable variants of Arc and Weak for lock-free concurrency.

Awesome Lists containing this project

README

        

# aarc

- [Quickstart](#quickstart)
- [Motivation](#motivation)
- [Examples](#examples)
- [Roadmap](#roadmap)
- [Resources](#resources)

### Quickstart

- [`Arc`](https://docs.rs/aarc/latest/aarc/struct.Arc.html) /
[`Weak`](https://docs.rs/aarc/latest/aarc/struct.Weak.html): drop-in replacements for the standard library's `Arc`
and `Weak`, but implemented with deferred reclamation semantics.
- [`AtomicArc`](https://docs.rs/aarc/latest/aarc/struct.AtomicArc.html) /
[`AtomicWeak`](https://docs.rs/aarc/latest/aarc/struct.AtomicWeak.html): variants of `Arc` and
`Weak` with atomically updatable pointers, supporting standard atomic operations like `load` and `compare_exchange`.
- [`Guard`](https://docs.rs/aarc/latest/aarc/struct.Guard.html): A novel smart pointer that can be loaded from
`AtomicArc` or `AtomicWeak`, designed to reduce contention when multiple threads operate on the same atomic variable.
It prevents deallocation but does not contribute to reference counts. (This was renamed from `Snapshot` in an earlier
version, to reduce confusion.)

### Motivation

Data structures built with `Arc` typically require locks for synchronization, as only
the reference counts may be atomically updated, not the pointer nor the contained data. While locks
are often the right approach, lock-free data structures can have better theoretical and practical
performance guarantees in highly-contended settings.

Instead of protecting in-place updates with locks, an alternative approach is to perform copy-on-write updates by
atomically installing pointers. To avoid use-afer-free, mechanisms for safe memory reclamation (SMR) are typically
utilized (i.e. hazard pointers, epoch-based reclamation). `aarc` uses the blazingly fast algorithm provided by the
[`fast-smr`](https://github.com/aarc-rs/fast-smr) crate and builds on top of it, hiding unsafety and providing
convenient RAII semantics through reference-counted pointers.

### Examples

Example 1: [Treiber Stack](https://en.wikipedia.org/wiki/Treiber_stack)

```rust no_run
use std::ptr::null;
use aarc::{Arc, AsPtr, AtomicArc, Guard};

struct StackNode {
val: usize,
next: Option>,
}

struct Stack {
top: AtomicArc,
}

impl Stack {
fn push(&self, val: usize) {
let mut top = self.top.load();
loop {
let top_ptr = top.as_ref().map_or(null(), AsPtr::as_ptr);
let new_node = Arc::new(StackNode {
val,
next: top.as_ref().map(Arc::from),
});
match self.top.compare_exchange(top_ptr, Some(&new_node)) {
Ok(()) => break,
Err(before) => top = before,
}
}
}
fn pop(&self) -> Option> {
let mut top = self.top.load();
while let Some(top_node) = top.as_ref() {
match self
.top
.compare_exchange(top_node.as_ptr(), top_node.next.as_ref())
{
Ok(()) => return top,
Err(actual_top) => top = actual_top,
}
}
None
}
}
```

### Roadmap

- [ ] relax atomic orderings from SeqCst to Acq/Rel
- [ ] add tagged pointers
- [ ] add more tests and stabilize APIs

### Resources

1. [Anderson, Daniel, et al. "Concurrent Deferred Reference Counting with Constant-Time Overhead."](https://dl.acm.org/doi/10.1145/3453483.3454060)
2. [Anderson, Daniel, et al. "Turning Manual Concurrent Memory Reclamation into Automatic Reference Counting."](https://dl.acm.org/doi/10.1145/3519939.3523730)