[−][src]Struct atomig::Atomic
The main type of this library: a generic atomic type.
Via the methods of this type you can perform various atomic operations. You
can use any type T
that implements Atom
. This includes primitive
atomics (the ones found in std::sync::atomic
), other primitive types and
potentially your own types. Additional methods are usable if T
implements
AtomLogic
or AtomInteger
.
All methods use Atom::pack
and Atom::unpack
to convert between the
underlying atomic value and the real value T
. For types that implement
PrimitiveAtom
, these two methods are a simple ID
function, meaning that there is no runtime overhead. Other types should
make sure their pack
and unpack
operations are fast, as they are used a
lot in this type.
For all methods that do a comparison (e.g. compare_and_swap
), keep in
mind that the comparison is performed on the bits of the underlying type
which can sometimes lead to unexpected behavior. For example, for floats,
there are many bit patterns that represent NaN. So the atomic might indeed
store a NaN representation at a moment, but compare_and_swap
called with
current = NaN
might not swap, because both NaN differ in the bit
representation.
The interface of this type very closely matches the interface of the atomic
types in std::sync::atomic
. The documentation was copied (and slightly
adjusted) from there!
Implementations
impl<T: Atom> Atomic<T>
[src]
pub fn new(v: T) -> Self
[src]
pub fn into_inner(self) -> T
[src]
Consumes the atomic and returns the contained value.
This is safe because passing self
by value guarantees that no other
threads are concurrently accessing the atomic data.
pub fn load(&self, order: Ordering) -> T
[src]
Loads the value from the atomic.
load
takes an Ordering
argument which describes the memory
ordering of this operation. Possible values are SeqCst
, Acquire
and
Relaxed
.
Panics
Panics if order
is Release
or AcqRel
.
Examples
use atomig::{Atomic, Ordering}; let x = Atomic::new(5); assert_eq!(x.load(Ordering::SeqCst), 5);
pub fn store(&self, v: T, order: Ordering)
[src]
Stores a value into the atomic.
store
takes an Ordering
argument which describes the memory
ordering of this operation. Possible values are SeqCst
, Release
and
Relaxed
.
Panics
Panics if order
is Acquire
or AcqRel
.
Examples
use atomig::{Atomic, Ordering}; let x = Atomic::new(5); x.store(10, Ordering::SeqCst); assert_eq!(x.load(Ordering::SeqCst), 10);
pub fn swap(&self, v: T, order: Ordering) -> T
[src]
Stores a value into the atomic, returning the previous value.
swap
takes an Ordering
argument which describes the memory
ordering of this operation. All ordering modes are possible. Note that
using Acquire
makes the store part of this operation Relaxed
, and
using Release
makes the load part Relaxed
.
Examples
use atomig::{Atomic, Ordering}; let x = Atomic::new(5); assert_eq!(x.swap(10, Ordering::SeqCst), 5);
pub fn compare_and_swap(&self, current: T, new: T, order: Ordering) -> T
[src]
Stores a value into the atomic if the current value is the same as the
current
value.
The return value is always the previous value. If it is equal to
current
, then the atomic was updated.
compare_and_swap
also takes an Ordering
argument which describes
the memory ordering of this operation. Notice that even when using
AcqRel
, the operation might fail and hence just perform an Acquire
load, but not have Release
semantics. Using Acquire
makes the store
part of this operation Relaxed
if it happens, and using Release
makes the load part Relaxed
.
Examples
use atomig::{Atomic, Ordering}; let x = Atomic::new(5); assert_eq!(x.compare_and_swap(5, 10, Ordering::SeqCst), 5); assert_eq!(x.load(Ordering::SeqCst), 10); assert_eq!(x.compare_and_swap(6, 12, Ordering::SeqCst), 10); assert_eq!(x.load(Ordering::SeqCst), 10);
pub fn compare_exchange(
&self,
current: T,
new: T,
success: Ordering,
failure: Ordering
) -> Result<T, T>
[src]
&self,
current: T,
new: T,
success: Ordering,
failure: Ordering
) -> Result<T, T>
Stores a value into the atomic if the current value is the same as the
current
value.
The return value is a result indicating whether the new value was
written and containing the previous value. On success this value is
guaranteed to be equal to current
.
compare_exchange
takes two Ordering
arguments to describe the
memory ordering of this operation. The first describes the required
ordering if the operation succeeds while the second describes the
required ordering when the operation fails. Using Acquire
as success
ordering makes the store part of this operation Relaxed
, and using
Release
makes the successful load Relaxed
. The failure ordering can
only be SeqCst
, Acquire
or Relaxed
and must be equivalent to or
weaker than the success ordering.
Examples
use atomig::{Atomic, Ordering}; let x = Atomic::new(5); assert_eq!( x.compare_exchange(5, 10, Ordering::Acquire, Ordering::Relaxed), Ok(5), ); assert_eq!(x.load(Ordering::Relaxed), 10); assert_eq!( x.compare_exchange(6, 12, Ordering::SeqCst, Ordering::Acquire), Err(10), ); assert_eq!(x.load(Ordering::Relaxed), 10);
pub fn compare_exchange_weak(
&self,
current: T,
new: T,
success: Ordering,
failure: Ordering
) -> Result<T, T>
[src]
&self,
current: T,
new: T,
success: Ordering,
failure: Ordering
) -> Result<T, T>
Stores a value into the atomic if the current value is the same as the
current
value.
Unlike compare_exchange
, this function is allowed to spuriously fail
even when the comparison succeeds, which can result in more efficient
code on some platforms. The return value is a result indicating whether
the new value was written and containing the previous value.
compare_exchange_weak
takes two Ordering
arguments to describe
the memory ordering of this operation. The first describes the required
ordering if the operation succeeds while the second describes the
required ordering when the operation fails. Using Acquire
as success
ordering makes the store part of this operation Relaxed
, and using
Release
makes the successful load Relaxed
. The failure ordering can
only be SeqCst
, Acquire
or Relaxed
and must be equivalent to or
weaker than the success ordering.
Examples
use atomig::{Atomic, Ordering}; let x = Atomic::new(4); let mut old = x.load(Ordering::Relaxed); loop { let new = old * 2; match x.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) { Ok(_) => break, Err(x) => old = x, } }
impl<T: AtomLogic> Atomic<T> where
<<T as Atom>::Repr as PrimitiveAtom>::Impl: AtomicLogicImpl,
[src]
<<T as Atom>::Repr as PrimitiveAtom>::Impl: AtomicLogicImpl,
pub fn fetch_and(&self, val: T, order: Ordering) -> T
[src]
Bitwise "and" with the current value.
Performs a bitwise "and" operation on the current value and the
argument val
, and sets the new value to the result.
Returns the previous value.
fetch_and
takes an Ordering
argument which describes the memory
ordering of this operation. All ordering modes are possible. Note that
using Acquire
makes the store part of this operation Relaxed
, and
using Release
makes the load part Relaxed
.
Examples
use atomig::{Atomic, Ordering}; let x = Atomic::new(0b101101); assert_eq!(x.fetch_and(0b110011, Ordering::SeqCst), 0b101101); assert_eq!(x.load(Ordering::SeqCst), 0b100001);
pub fn fetch_nand(&self, val: T, order: Ordering) -> T
[src]
Bitwise "nand" with the current value.
Performs a bitwise "nand" operation on the current value and the
argument val
, and sets the new value to the result.
Returns the previous value.
fetch_nand
takes an Ordering
argument which describes the memory
ordering of this operation. All ordering modes are possible. Note that
using Acquire
makes the store part of this operation Relaxed
, and
using Release
makes the load part Relaxed
.
Examples
use atomig::{Atomic, Ordering}; let x = Atomic::new(0x13); assert_eq!(x.fetch_nand(0x31, Ordering::SeqCst), 0x13); assert_eq!(x.load(Ordering::SeqCst), !(0x13 & 0x31));
pub fn fetch_or(&self, val: T, order: Ordering) -> T
[src]
Bitwise "or" with the current value.
Performs a bitwise "or" operation on the current value and the
argument val
, and sets the new value to the result.
Returns the previous value.
fetch_or
takes an Ordering
argument which describes the memory
ordering of this operation. All ordering modes are possible. Note that
using Acquire
makes the store part of this operation Relaxed
, and
using Release
makes the load part Relaxed
.
Examples
use atomig::{Atomic, Ordering}; let x = Atomic::new(0b101101); assert_eq!(x.fetch_or(0b110011, Ordering::SeqCst), 0b101101); assert_eq!(x.load(Ordering::SeqCst), 0b111111);
pub fn fetch_xor(&self, val: T, order: Ordering) -> T
[src]
Bitwise "xor" with the current value.
Performs a bitwise "xor" operation on the current value and the
argument val
, and sets the new value to the result.
Returns the previous value.
fetch_xor
takes an Ordering
argument which describes the memory
ordering of this operation. All ordering modes are possible. Note that
using Acquire
makes the store part of this operation Relaxed
, and
using Release
makes the load part Relaxed
.
Examples
use atomig::{Atomic, Ordering}; let x = Atomic::new(0b101101); assert_eq!(x.fetch_xor(0b110011, Ordering::SeqCst), 0b101101); assert_eq!(x.load(Ordering::SeqCst), 0b011110);
impl<T: AtomInteger> Atomic<T> where
<<T as Atom>::Repr as PrimitiveAtom>::Impl: AtomicIntegerImpl,
[src]
<<T as Atom>::Repr as PrimitiveAtom>::Impl: AtomicIntegerImpl,
pub fn fetch_add(&self, val: T, order: Ordering) -> T
[src]
Adds to the current value, returning the previous value.
This operation wraps around on overflow.
fetch_add
takes an Ordering
argument which describes the memory
ordering of this operation. All ordering modes are possible. Note that
using Acquire
makes the store part of this operation Relaxed
, and
using Release
makes the load part Relaxed
.
Examples
use atomig::{Atomic, Ordering}; let x = Atomic::new(0); assert_eq!(x.fetch_add(10, Ordering::SeqCst), 0); assert_eq!(x.load(Ordering::SeqCst), 10);
pub fn fetch_sub(&self, val: T, order: Ordering) -> T
[src]
Subtracts from the current value, returning the previous value.
This operation wraps around on overflow.
fetch_sub
takes an Ordering
argument which describes the memory
ordering of this operation. All ordering modes are possible. Note that
using Acquire
makes the store part of this operation Relaxed
, and
using Release
makes the load part Relaxed
.
Examples
use atomig::{Atomic, Ordering}; let x = Atomic::new(20); assert_eq!(x.fetch_sub(10, Ordering::SeqCst), 20); assert_eq!(x.load(Ordering::SeqCst), 10);
pub fn fetch_max(&self, val: T, order: Ordering) -> T
[src]
Maximum with the current value.
Finds the maximum of the current value and the argument val
, and sets
the new value to the result.
Returns the previous value.
fetch_max
takes an Ordering
argument which describes the memory
ordering of this operation. All ordering modes are possible. Note that
using Acquire
makes the store part of this operation Relaxed
, and
using Release
makes the load part Relaxed
.
Examples
use atomig::{Atomic, Ordering}; let foo = Atomic::new(23); assert_eq!(foo.fetch_max(42, Ordering::SeqCst), 23); assert_eq!(foo.load(Ordering::SeqCst), 42);
If you want to obtain the maximum value in one step, you can use the following:
use atomig::{Atomic, Ordering}; let foo = Atomic::new(23); let bar = 42; let max_foo = foo.fetch_max(bar, Ordering::SeqCst).max(bar); assert!(max_foo == 42);
pub fn fetch_min(&self, val: T, order: Ordering) -> T
[src]
Minimum with the current value.
Finds the minimum of the current value and the argument val
, and sets
the new value to the result.
Returns the previous value.
fetch_min
takes an Ordering
argument which describes the memory
ordering of this operation. All ordering modes are possible. Note that
using Acquire
makes the store part of this operation Relaxed
, and
using Release
makes the load part Relaxed
.
Examples
use atomig::{Atomic, Ordering}; let foo = Atomic::new(23); assert_eq!(foo.fetch_min(42, Ordering::Relaxed), 23); assert_eq!(foo.load(Ordering::Relaxed), 23); assert_eq!(foo.fetch_min(22, Ordering::Relaxed), 23); assert_eq!(foo.load(Ordering::Relaxed), 22);
If you want to obtain the minimum value in one step, you can use the following:
use atomig::{Atomic, Ordering}; let foo = Atomic::new(23); let bar = 12; let min_foo = foo.fetch_min(bar, Ordering::SeqCst).min(bar); assert!(min_foo == 12);
pub fn fetch_update<F>(
&self,
set_order: Ordering,
fetch_order: Ordering,
f: F
) -> Result<T, T> where
F: FnMut(T) -> Option<T>,
[src]
&self,
set_order: Ordering,
fetch_order: Ordering,
f: F
) -> Result<T, T> where
F: FnMut(T) -> Option<T>,
Fetches the value, and applies a function to it that returns an
optional new value. Returns a Result
of Ok(previous_value)
if the
function returned Some(_)
, else Err(previous_value)
.
Note: This may call the function multiple times if the value has been
changed from other threads in the meantime, as long as the function
returns Some(_)
, but the function will have been applied but once to
the stored value.
fetch_update
takes two Ordering
arguments to describe the memory
ordering of this operation. The first describes the required ordering
for loads and failed updates while the second describes the required
ordering when the operation finally succeeds. Beware that this is
different from the two modes in compare_exchange
!
Using Acquire
as success ordering makes the store part of this
operation Relaxed
, and using Release
makes the final successful
load Relaxed
. The (failed) load ordering can only be SeqCst
,
Acquire
or Relaxed
and must be equivalent to or weaker than the
success ordering.
Examples
use atomig::{Atomic, Ordering}; let x = Atomic::new(7); assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |_| None), Err(7)); assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(7)); assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(8)); assert_eq!(x.load(Ordering::SeqCst), 9);
Trait Implementations
impl<T: Atom + Debug> Debug for Atomic<T>
[src]
impl<T: Atom + Default> Default for Atomic<T>
[src]
impl<'de, T: Atom + Deserialize<'de>> Deserialize<'de> for Atomic<T>
[src]
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where
D: Deserializer<'de>,
[src]
D: Deserializer<'de>,
impl<T: Atom> From<T> for Atomic<T>
[src]
impl<T: Atom + Serialize> Serialize for Atomic<T>
[src]
Auto Trait Implementations
impl<T> RefUnwindSafe for Atomic<T> where
<<T as Atom>::Repr as PrimitiveAtom>::Impl: RefUnwindSafe,
<<T as Atom>::Repr as PrimitiveAtom>::Impl: RefUnwindSafe,
impl<T> Send for Atomic<T> where
<<T as Atom>::Repr as PrimitiveAtom>::Impl: Send,
<<T as Atom>::Repr as PrimitiveAtom>::Impl: Send,
impl<T> Sync for Atomic<T> where
<<T as Atom>::Repr as PrimitiveAtom>::Impl: Sync,
<<T as Atom>::Repr as PrimitiveAtom>::Impl: Sync,
impl<T> Unpin for Atomic<T> where
<<T as Atom>::Repr as PrimitiveAtom>::Impl: Unpin,
<<T as Atom>::Repr as PrimitiveAtom>::Impl: Unpin,
impl<T> UnwindSafe for Atomic<T> where
<<T as Atom>::Repr as PrimitiveAtom>::Impl: UnwindSafe,
<<T as Atom>::Repr as PrimitiveAtom>::Impl: UnwindSafe,
Blanket Implementations
impl<T> Any for T where
T: 'static + ?Sized,
[src]
T: 'static + ?Sized,
impl<T> Borrow<T> for T where
T: ?Sized,
[src]
T: ?Sized,
impl<T> BorrowMut<T> for T where
T: ?Sized,
[src]
T: ?Sized,
fn borrow_mut(&mut self) -> &mut T
[src]
impl<T> DeserializeOwned for T where
T: for<'de> Deserialize<'de>,
[src]
T: for<'de> Deserialize<'de>,
impl<T> From<!> for T
[src]
impl<T> From<T> for T
[src]
impl<T, U> Into<U> for T where
U: From<T>,
[src]
U: From<T>,
impl<T, U> TryFrom<U> for T where
U: Into<T>,
[src]
U: Into<T>,
type Error = Infallible
The type returned in the event of a conversion error.
fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
[src]
impl<T, U> TryInto<U> for T where
U: TryFrom<T>,
[src]
U: TryFrom<T>,