A rust library for sharing and updating arbitrary slices between threads, optimized for wait-free reads

Overview

atomicslice

A Rust library for thread-safe shared slices that are just about as fast as possible to read while also being writable.

Overview

Use AtomicSlice<T> like you would a RwLock<[T]>, and know that .read() is wait-free. Pass it between threads as Arc<AtomicSlice<T>> or between scoped threads as &AtomicSlice<T>, and call .read() and .write() as much as you like. The slice can be of any length at construction time, but subsequence writes must pass slices of the same length.

Reading from an AtomicSlice<T> is optimized to be wait-free and as fast as possible. Calling .read() results in a total of three atomic operations, and never blocks or otherwise spins or waits. Calling .write() in the other hand may result in some waiting.

Implementation Details

Internally, AtomicSlice<T> stores a pool of multiple redundant slices, one of which is conceptually being read from while the others are conceptually ready for writing while possibly being read from by a few .read() stragglers. Which of these pools to read from is indicated by a shared atomic integer status, which uses bit-packing to also encode locking information for all slices simultaneously.

To read, the status is fetched and all pool use counts are incremented, in a single atomic operation. Once the active slice index is known, the other slices which aren't in use have their use counts decremented. Then, the active slice is guarded and may be read from as desired. After the client is doing reading, the active slice's use count is similarly decremented. The .read() method performs the first two operations and returns a lock guard object whose drop() method performs the third.

The write() method AtomicSlice<T> is effectively guarded by a mutex, such that writes are serialized. Once that is acquired, the .write() method locates a separate slice in the pool from the currently active one, and spins until its use count goes to zero. At this point, no new or current reads will access the out-of-use slice, and so the .write() method copies the supplied data into it. Finally, the index of the current slice is updated to point to the newly-filled slice, where readers will begin finding the new data.

Currently, a pool size of exactly two is used, which is the bare minimum but seems to work well enough. In the future, I may do some profiling to see what the tradeoffs are.


Discussion

  • Is it safe to relax some of the atomic orderings to be less than Ordering::SeqCst?
    • Idk, probably? Acquire and Release are probably the way to go for most of them, I just currently struggle to understand their exact implications.
  • Why not use the arc-swap Crate?
    • Because I eventually plan to expose the internals as raw pointers and atomics operations to an LLVM-based JIT engine as part of another project. That project involves realtime DSP where arrays need to be continuously read and occasionally updated. The unusual intersection of requirements for wait-free code, a focus on array data, and the need to understand the low-level sequence of atomic operations required led me to write my own. That, and it was a fun exercise.
  • Couldn't you get away with implementing .read() as a single load from an AtomicPtr?
    • Yes, if you're okay with leaking memory every time you write. Theoretically, you could implement this correctly by allocating and leaking an array everytime you call .write(), and then pointing all readers to it using a single atomic pointer only. To prevent a catastrophic leak like this, a minimum of two additional operations are needed to synchronize with the begin and end of a slice's use by the .read() method.
You might also like...
QuickCheck bug hunting in Rust standard library data structures

BugHunt, Rust This project is aiming to provide "stateful" QuickCheck models for Rust's standard library. That is, we build up a random list of operat

A simple rust library for working with ZIP archives

rust-zip A simple rust library to read and write Zip archives, which is also my pet project for learning Rust. At the moment you can list the files in

An attempt to rewrite lite-client for TON Blockchain in Rust using ton-labs-adnl library.

An attempt to rewrite lite-client for TON Blockchain in Rust using ton-labs-adnl library.

A new shellcode injection technique. Given as C++ header, standalone Rust program or library.
A new shellcode injection technique. Given as C++ header, standalone Rust program or library.

FunctionStomping Description This is a brand-new technique for shellcode injection to evade AVs and EDRs. This technique is inspired by Module Stompin

Extended precision integer Rust library. Provides signed/unsigned integer 256 to 2048.

Extended precision integer Rust library. Provides signed/unsigned integer 256 to 2048.

An R interface to Rust's h3o library
An R interface to Rust's h3o library

h3o h3o is a system-dependency free package to interact with the H3 Geospatial Indexing system by Uber. h3o utilizes the Rust library h3o with is a pu

Kepler is a vulnerability database and lookup store and API currently utilising National Vulnerability Database and NPM Advisories as data sources
Kepler is a vulnerability database and lookup store and API currently utilising National Vulnerability Database and NPM Advisories as data sources

Kepler — Kepler is a vulnerability database and lookup store and API currently utilising National Vulnerability Database and NPM Advisories as data so

Cross-platform async library for system information fetching 🦀
Cross-platform async library for system information fetching 🦀

heim Cross-platform library for system information fetching heim is an ongoing attempt to create the best tool for system information fetching (ex., C

Memory hacking library for windows.

Memory hacking library for windows.

Owner
Tim Straubinger
Tim Straubinger
Custom memory allocator that helps discover reads from uninitialized memory

libdiffuzz: security-oriented alternative to Memory Sanitizer This is a drop-in replacement for OS memory allocator that can be used to detect uses of

Sergey 155 Dec 3, 2022
The Arbitrary trait

Arbitrary The trait for generating structured data from arbitrary, unstructured input. About The Arbitrary crate lets you construct arbitrary instance

Rust Fuzzing Authority 407 Dec 24, 2022
Xori is an automation-ready disassembly and static analysis library for PE32, 32+ and shellcode

Xori - Custom disassembly framework Xori is an automation-ready disassembly and static analysis library that consumes shellcode or PE binaries and pro

ENDGAME 712 Nov 28, 2022
Rust library for building and running BPF/eBPF modules

RedBPF A Rust eBPF toolchain. Overview The redbpf project is a collection of tools and libraries to build eBPF programs using Rust. It includes: redbp

foniod 1.5k Jan 1, 2023
Advanced Fuzzing Library - Slot your Fuzzer together in Rust! Scales across cores and machines. For Windows, Android, MacOS, Linux, no_std, ...

LibAFL, the fuzzer library. Advanced Fuzzing Library - Slot your own fuzzers together and extend their features using Rust. LibAFL is written and main

Advanced Fuzzing League ++ 1.2k Jan 6, 2023
Mundane is a Rust cryptography library backed by BoringSSL that is difficult to misuse, ergonomic, and performant (in that order).

Mundane Mundane is a Rust cryptography library backed by BoringSSL that is difficult to misuse, ergonomic, and performant (in that order). Issues and

Google 1.1k Jan 3, 2023
Linux anti-debugging and anti-analysis rust library

DebugOff Library Linux anti-analysis Rust library The goal of this library is to make both static and dynamic (debugging) analysis more difficult. The

null 65 Jan 7, 2023
unfuck is a utility and library for deobfuscating obfuscated Python 2.7 bytecode

unfuck is a utility and library for deobfuscating obfuscated Python 2.7 bytecode. It is essentially a reimplementation of the Python VM with taint tracking.

Lander Brandt 171 Dec 14, 2022
CVEs for the Rust standard library

Rust CVE Preface This is a list of CVEs for unsound APIs in the Rust standard library. These bugs break Rust's memory safety guarantee and lead to sec

Yechan Bae 26 Dec 4, 2022
Rust library for developing safe canisters.

IC Kit This library provides an alternative to ic-cdk that can help developers write canisters and unit test them in their Rust code. Install Add this

Psychedelic 26 Nov 28, 2022