#atomic #reference #static

atomic_ref

Atomic &'a T types with support for static allocation

4 releases

Uses old Rust 2015

0.2.1 Sep 19, 2021
0.2.0 Nov 1, 2020
0.1.2 Nov 4, 2016
0.1.1 Sep 3, 2016
0.1.0 Sep 2, 2016

#113 in #atomic

Download history 8/week @ 2024-02-04 3/week @ 2024-02-11 280/week @ 2024-02-18 52/week @ 2024-02-25 48/week @ 2024-03-03 30/week @ 2024-03-10 24/week @ 2024-03-17 24/week @ 2024-03-24 35/week @ 2024-03-31

116 downloads per month
Used in 2 crates

MIT license

18KB
161 lines

AtomicRef

Build Status

An atomic optional reference with support for static allocation.

See the documentation for more information.


lib.rs:

Atomic References

These types act similarially to the Atomic types from std::sync::atomic, Except that instead of containing an integer type or a pointer, they contain an Option<&'a T> value.

Like other option values, these types present operations which, when used correctly, synchronize updates between threads. This type is a form of interior mutability, like Cell<T>, RefCell<T>, or Mutex<T>.

This type in static position is often used for lazy global initialization.

AtomicRef may only contain Sized types, as unsized types have wide pointers which cannot be atomically written to or read from.

Ordering

It is unsound to load or store an atomic reference with the Relaxed memory ordering, as these operations provide no ordering on writes to the data behind the reference. To avoid this issue, loads and stores with Relaxed memory ordering are actually performed with Acquire, Release, or AcqRel ordering, as appropriate.

Examples

Static logger state

use atomic_ref::AtomicRef;
use std::sync::atomic::Ordering;
use std::io::{stdout, Write};

// Define the idea of a logger
trait Logger {
    fn log(&self, msg: &str) {}
}
struct LoggerInfo {
    logger: &'static (dyn Logger + Sync)
}

// The methods for working with our currently defined static logger
static LOGGER: AtomicRef<LoggerInfo> = AtomicRef::new(None);
fn log(msg: &str) -> bool {
    if let Some(info) = LOGGER.load(Ordering::SeqCst) {
        info.logger.log(msg);
        true
    } else {
        false
    }
}
fn set_logger(logger: Option<&'static LoggerInfo>) {
    LOGGER.store(logger, Ordering::SeqCst);
}

// Defining the standard out example logger
struct StdoutLogger;
impl Logger for StdoutLogger {
    fn log(&self, msg: &str) {
        stdout().write(msg.as_bytes());
    }
}
static STDOUT_LOGGER: LoggerInfo = LoggerInfo { logger: &StdoutLogger };

fn main() {
    let res = log("This will fail");
    assert!(!res);
    set_logger(Some(&STDOUT_LOGGER));
    let res = log("This will succeed");
    assert!(res);
}

No runtime deps