Struct crossbeam_epoch::Atomic
source · pub struct Atomic<T> { /* private fields */ }
Expand description
An atomic pointer that can be safely shared between threads.
The pointer must be properly aligned. Since it is aligned, a tag can be stored into the unused
least significant bits of the address. More precisely, a tag should be less than (1 << mem::align_of::<T>().trailing_zeros())
.
Any method that loads the pointer must be passed a reference to a Guard
.
Implementations
sourceimpl<T> Atomic<T>
impl<T> Atomic<T>
sourcepub fn null() -> Atomic<T>
pub fn null() -> Atomic<T>
Returns a new null atomic pointer.
Examples
use crossbeam_epoch::Atomic;
let a = Atomic::<i32>::null();
sourcepub fn new(value: T) -> Atomic<T>
pub fn new(value: T) -> Atomic<T>
Allocates value
on the heap and returns a new atomic pointer pointing to it.
Examples
use crossbeam_epoch::Atomic;
let a = Atomic::new(1234);
sourcepub fn load<'g>(&self, ord: Ordering, _: &'g Guard) -> Shared<'g, T>
pub fn load<'g>(&self, ord: Ordering, _: &'g Guard) -> Shared<'g, T>
Loads a Shared
from the atomic pointer.
This method takes an Ordering
argument which describes the memory ordering of this
operation.
Examples
use crossbeam_epoch::{self as epoch, Atomic};
use std::sync::atomic::Ordering::SeqCst;
let a = Atomic::new(1234);
let guard = &epoch::pin();
let p = a.load(SeqCst, guard);
sourcepub fn load_consume<'g>(&self, _: &'g Guard) -> Shared<'g, T>
pub fn load_consume<'g>(&self, _: &'g Guard) -> Shared<'g, T>
Loads a Shared
from the atomic pointer using a “consume” memory ordering.
This is similar to the “acquire” ordering, except that an ordering is only guaranteed with operations that “depend on” the result of the load. However consume loads are usually much faster than acquire loads on architectures with a weak memory model since they don’t require memory fence instructions.
The exact definition of “depend on” is a bit vague, but it works as you would expect in practice since a lot of software, especially the Linux kernel, rely on this behavior.
Examples
use crossbeam_epoch::{self as epoch, Atomic};
let a = Atomic::new(1234);
let guard = &epoch::pin();
let p = a.load_consume(guard);
sourcepub fn store<'g, P: Pointer<T>>(&self, new: P, ord: Ordering)
pub fn store<'g, P: Pointer<T>>(&self, new: P, ord: Ordering)
Stores a Shared
or Owned
pointer into the atomic pointer.
This method takes an Ordering
argument which describes the memory ordering of this
operation.
Examples
use crossbeam_epoch::{self as epoch, Atomic, Owned, Shared};
use std::sync::atomic::Ordering::SeqCst;
let a = Atomic::new(1234);
a.store(Shared::null(), SeqCst);
a.store(Owned::new(1234), SeqCst);
sourcepub fn swap<'g, P: Pointer<T>>(
&self,
new: P,
ord: Ordering,
_: &'g Guard
) -> Shared<'g, T>
pub fn swap<'g, P: Pointer<T>>(
&self,
new: P,
ord: Ordering,
_: &'g Guard
) -> Shared<'g, T>
Stores a Shared
or Owned
pointer into the atomic pointer, returning the previous
Shared
.
This method takes an Ordering
argument which describes the memory ordering of this
operation.
Examples
use crossbeam_epoch::{self as epoch, Atomic, Owned, Shared};
use std::sync::atomic::Ordering::SeqCst;
let a = Atomic::new(1234);
let guard = &epoch::pin();
let p = a.swap(Shared::null(), SeqCst, guard);
sourcepub fn compare_and_set<'g, O, P>(
&self,
current: Shared<'_, T>,
new: P,
ord: O,
_: &'g Guard
) -> Result<Shared<'g, T>, CompareAndSetError<'g, T, P>>where
O: CompareAndSetOrdering,
P: Pointer<T>,
pub fn compare_and_set<'g, O, P>(
&self,
current: Shared<'_, T>,
new: P,
ord: O,
_: &'g Guard
) -> Result<Shared<'g, T>, CompareAndSetError<'g, T, P>>where
O: CompareAndSetOrdering,
P: Pointer<T>,
Stores the pointer new
(either Shared
or Owned
) into the atomic pointer if the current
value is the same as current
. The tag is also taken into account, so two pointers to the
same object, but with different tags, will not be considered equal.
The return value is a result indicating whether the new pointer was written. On success the
pointer that was written is returned. On failure the actual current value and new
are
returned.
This method takes a CompareAndSetOrdering
argument which describes the memory
ordering of this operation.
Examples
use crossbeam_epoch::{self as epoch, Atomic, Owned, Shared};
use std::sync::atomic::Ordering::SeqCst;
let a = Atomic::new(1234);
let guard = &epoch::pin();
let mut curr = a.load(SeqCst, guard);
let res1 = a.compare_and_set(curr, Shared::null(), SeqCst, guard);
let res2 = a.compare_and_set(curr, Owned::new(5678), SeqCst, guard);
sourcepub fn compare_and_set_weak<'g, O, P>(
&self,
current: Shared<'_, T>,
new: P,
ord: O,
_: &'g Guard
) -> Result<Shared<'g, T>, CompareAndSetError<'g, T, P>>where
O: CompareAndSetOrdering,
P: Pointer<T>,
pub fn compare_and_set_weak<'g, O, P>(
&self,
current: Shared<'_, T>,
new: P,
ord: O,
_: &'g Guard
) -> Result<Shared<'g, T>, CompareAndSetError<'g, T, P>>where
O: CompareAndSetOrdering,
P: Pointer<T>,
Stores the pointer new
(either Shared
or Owned
) into the atomic pointer if the current
value is the same as current
. The tag is also taken into account, so two pointers to the
same object, but with different tags, will not be considered equal.
Unlike compare_and_set
, this method is allowed to spuriously fail even when comparison
succeeds, which can result in more efficient code on some platforms. The return value is a
result indicating whether the new pointer was written. On success the pointer that was
written is returned. On failure the actual current value and new
are returned.
This method takes a CompareAndSetOrdering
argument which describes the memory
ordering of this operation.
Examples
use crossbeam_epoch::{self as epoch, Atomic, Owned, Shared};
use std::sync::atomic::Ordering::SeqCst;
let a = Atomic::new(1234);
let guard = &epoch::pin();
let mut new = Owned::new(5678);
let mut ptr = a.load(SeqCst, guard);
loop {
match a.compare_and_set_weak(ptr, new, SeqCst, guard) {
Ok(p) => {
ptr = p;
break;
}
Err(err) => {
ptr = err.current;
new = err.new;
}
}
}
let mut curr = a.load(SeqCst, guard);
loop {
match a.compare_and_set_weak(curr, Shared::null(), SeqCst, guard) {
Ok(_) => break,
Err(err) => curr = err.current,
}
}
sourcepub fn fetch_and<'g>(
&self,
val: usize,
ord: Ordering,
_: &'g Guard
) -> Shared<'g, T>
pub fn fetch_and<'g>(
&self,
val: usize,
ord: Ordering,
_: &'g Guard
) -> Shared<'g, T>
Bitwise “and” with the current tag.
Performs a bitwise “and” operation on the current tag and the argument val
, and sets the
new tag to the result. Returns the previous pointer.
This method takes an Ordering
argument which describes the memory ordering of this
operation.
Examples
use crossbeam_epoch::{self as epoch, Atomic, Shared};
use std::sync::atomic::Ordering::SeqCst;
let a = Atomic::<i32>::from(Shared::null().with_tag(3));
let guard = &epoch::pin();
assert_eq!(a.fetch_and(2, SeqCst, guard).tag(), 3);
assert_eq!(a.load(SeqCst, guard).tag(), 2);
sourcepub fn fetch_or<'g>(
&self,
val: usize,
ord: Ordering,
_: &'g Guard
) -> Shared<'g, T>
pub fn fetch_or<'g>(
&self,
val: usize,
ord: Ordering,
_: &'g Guard
) -> Shared<'g, T>
Bitwise “or” with the current tag.
Performs a bitwise “or” operation on the current tag and the argument val
, and sets the
new tag to the result. Returns the previous pointer.
This method takes an Ordering
argument which describes the memory ordering of this
operation.
Examples
use crossbeam_epoch::{self as epoch, Atomic, Shared};
use std::sync::atomic::Ordering::SeqCst;
let a = Atomic::<i32>::from(Shared::null().with_tag(1));
let guard = &epoch::pin();
assert_eq!(a.fetch_or(2, SeqCst, guard).tag(), 1);
assert_eq!(a.load(SeqCst, guard).tag(), 3);
sourcepub fn fetch_xor<'g>(
&self,
val: usize,
ord: Ordering,
_: &'g Guard
) -> Shared<'g, T>
pub fn fetch_xor<'g>(
&self,
val: usize,
ord: Ordering,
_: &'g Guard
) -> Shared<'g, T>
Bitwise “xor” with the current tag.
Performs a bitwise “xor” operation on the current tag and the argument val
, and sets the
new tag to the result. Returns the previous pointer.
This method takes an Ordering
argument which describes the memory ordering of this
operation.
Examples
use crossbeam_epoch::{self as epoch, Atomic, Shared};
use std::sync::atomic::Ordering::SeqCst;
let a = Atomic::<i32>::from(Shared::null().with_tag(1));
let guard = &epoch::pin();
assert_eq!(a.fetch_xor(3, SeqCst, guard).tag(), 1);
assert_eq!(a.load(SeqCst, guard).tag(), 2);