[src]

Module std::sync::atomics

Atomic types

Atomic types provide primitive shared-memory communication between threads, and are the building blocks of other concurrent types.

This module defines atomic versions of a select number of primitive types, including AtomicBool, AtomicInt, AtomicUint, and AtomicOption. Atomic types present operations that, when used correctly, synchronize updates between threads.

Each method takes an Ordering which represents the strength of the memory barrier for that operation. These orderings are the same as C++11 atomic orderings.

Atomic variables are safe to share between threads (they implement Share) but they do not themselves provide the mechanism for sharing. The most common way to share an atomic variable is to put it into an Arc (an atomically-reference-counted shared pointer).

Most atomic types may be stored in static variables, initialized using the provided static initializers like INIT_ATOMIC_BOOL. Atomic statics are often used for lazy global initialization.

Examples

A simple spinlock:

extern crate sync;

use sync::Arc;
use std::sync::atomics::{AtomicUint, SeqCst};
use std::task::deschedule;

fn main() {
    let spinlock = Arc::new(AtomicUint::new(1));

    let spinlock_clone = spinlock.clone();
    spawn(proc() {
        spinlock_clone.store(0, SeqCst);
    });

    // Wait for the other task to release the lock
    while spinlock.load(SeqCst) != 0 {
        // Since tasks may not be preemptive (if they are green threads)
        // yield to the scheduler to let the other task run. Low level
        // concurrent code needs to take into account Rust's two threading
        // models.
        deschedule();
    }
}

Transferring a heap object with AtomicOption:

extern crate sync;

use sync::Arc;
use std::sync::atomics::{AtomicOption, SeqCst};

fn main() {
    struct BigObject;

    let shared_big_object = Arc::new(AtomicOption::empty());

    let shared_big_object_clone = shared_big_object.clone();
    spawn(proc() {
        let unwrapped_big_object = shared_big_object_clone.take(SeqCst);
        if unwrapped_big_object.is_some() {
            println!("got a big object from another task");
        } else {
            println!("other task hasn't sent big object yet");
        }
    });

    shared_big_object.swap(~BigObject, SeqCst);
}

Keep a global count of live tasks:

use std::sync::atomics::{AtomicUint, SeqCst, INIT_ATOMIC_UINT};

static mut GLOBAL_TASK_COUNT: AtomicUint = INIT_ATOMIC_UINT;

unsafe {
    let old_task_count = GLOBAL_TASK_COUNT.fetch_add(1, SeqCst);
    println!("live tasks: {}", old_task_count + 1);
}
AtomicBool

An atomic boolean type.

AtomicInt

A signed atomic integer type, supporting basic atomic arithmetic operations

AtomicOption

An atomic, nullable unique pointer

AtomicPtr

An unsafe atomic pointer. Only supports basic atomic operations

AtomicUint

An unsigned atomic integer type, supporting basic atomic arithmetic operations

Ordering

Atomic memory orderings

pub static INIT_ATOMIC_BOOL: AtomicBool =
AtomicBool { v: Unsafe{value: 0,
                                                                  marker1: marker::InvariantType},
                                                        nocopy: marker::NoCopy }

An AtomicBool initialized to false

 
pub static INIT_ATOMIC_INT: AtomicInt =
AtomicInt  { v: Unsafe{value: 0,
                                                                  marker1: marker::InvariantType},
                                                        nocopy: marker::NoCopy }

An AtomicInt initialized to 0

 
pub static INIT_ATOMIC_UINT: AtomicUint =
AtomicUint { v: Unsafe{value: 0,
                                                                  marker1: marker::InvariantType},
                                                        nocopy: marker::NoCopy }

An AtomicUint initialized to 0

 
fence

An atomic fence.