Search code examples
rustatomic

Getting 'unordered' semantics in Rust


How do I create a fixed length list of integers V with the "unordered" semantics of LLVM (see https://llvm.org/docs/Atomics.html).

The "unordered" semantics means if you read a location in the thread, you will get a previously written value (not necessarily the most recent one, as the optimisers is allowed to rearrange / cache values from the array). This can be viewed as the "natural" behaviour of reading and writing the raw memory, as long as values are only written and read in a single CPU instruction (so other threads never see "half a written value").

It is important to me this is as close to the performance of a single-threaded array of integers as possible, because writes are extremely rare, and I am happy for them to be lost.


Solution

  • rustc exposes a fair number of LLVM intrinsics through the std::intrinsics module, which is permanently unstable.

    Still, it is available in Nightly, and there you can find:

    With those at hand, you can use UnsafeCell as a basic building block to build your own UnorderedAtomicXXX.

    You can follow the std atomics to help with your implementation. The basics should look like:

    pub struct UnorderedAtomic(UnsafeCell<i32>);
    
    impl UnorderedAtomic {
        pub fn new() -> Self {
            UnorderedAtomic(Default::default())
        }
    
        pub fn load(&self) -> i32 {
            unsafe { atomic_load_unordered(self.0.get()) }
        }
    
        pub fn store(&self, i: i32) {
            unsafe { atomic_store_unordered(self.0.get(), i) }
        }
    
        unsafe fn raw(&self) -> *mut i32 { self.0.get() }
    }
    

    It's unclear whether you can get unordered compare/exchange or fetch/add.