pure/concurrency/atomics

    Dark Mode
Search:
  Source   Edit

Types and operations for atomic operations and lockless algorithms.

Unstable API.

Example:

import pure/concurrency/atomics
# Atomic
var loc: Atomic[int]
loc.store(4)
assert loc.load == 4
loc.store(2)
assert loc.load(moRelaxed) == 2
loc.store(9)
assert loc.load(moAcquire) == 9
loc.store(0, moRelease)
assert loc.load == 0

assert loc.exchange(7) == 0
assert loc.load == 7

var expected = 7
assert loc.compareExchange(expected, 5, moRelaxed, moRelaxed)
assert expected == 7
assert loc.load == 5

assert not loc.compareExchange(expected, 12, moRelaxed, moRelaxed)
assert expected == 5
assert loc.load == 5

assert loc.fetchAdd(1) == 5
assert loc.fetchAdd(2) == 6
assert loc.fetchSub(3) == 8

loc.atomicInc(1)
assert loc.load == 6

# AtomicFlag
var flag: AtomicFlag

assert not flag.testAndSet
assert flag.testAndSet
flag.clear(moRelaxed)
assert not flag.testAndSet

Types

Atomic[T] = object
  when T is Trivial:
    when sizeof(T) == 1:
      value
    elif sizeof(T) == 2:
      value
    elif sizeof(T) == 4:
      value
    elif sizeof(T) == 8:
      value
  else:
      nonAtomicValue
      guard

  
  Source   Edit
AtomicFlag {.importc: "atomic_flag", size: 1, header: "<stdatomic.h>".} = object
  Source   Edit
MemoryOrder {.importc: "memory_order", header: "<stdatomic.h>".} = enum
  moRelaxed, moConsume, moAcquire, moRelease, moAcquireRelease,
  moSequentiallyConsistent
  Source   Edit

Procs

proc `+=`[T: SomeInteger](location: var Atomic[T]; value: T) {.inline.}
Atomically increments the atomic integer by some value.   Source   Edit
proc `-=`[T: SomeInteger](location: var Atomic[T]; value: T) {.inline.}
Atomically decrements the atomic integer by some value.   Source   Edit
proc atomicDec[T: SomeInteger](location: var Atomic[T]; value: T = 1) {.inline.}
Atomically decrements the atomic integer by some value.   Source   Edit
proc atomicInc[T: SomeInteger](location: var Atomic[T]; value: T = 1) {.inline.}
Atomically increments the atomic integer by some value.   Source   Edit
proc clear(location: var AtomicFlag;
           order: MemoryOrder = moSequentiallyConsistent) {.
    importc: "atomic_flag_clear_explicit", header: "<stdatomic.h>", ...raises: [],
    tags: [].}
  Source   Edit
proc compareExchange[T: not Trivial](location: var Atomic[T]; expected: var T;
                                     desired: T; order: MemoryOrder = moSequentiallyConsistent): bool {.
    inline.}
  Source   Edit
proc compareExchange[T: not Trivial](location: var Atomic[T]; expected: var T;
                                     desired: T; success, failure: MemoryOrder): bool {.
    inline.}
  Source   Edit
proc compareExchange[T: Trivial](location: var Atomic[T]; expected: var T;
                                 desired: T;
                                 order: MemoryOrder = moSequentiallyConsistent): bool {.
    inline.}
  Source   Edit
proc compareExchange[T: Trivial](location: var Atomic[T]; expected: var T;
                                 desired: T; success, failure: MemoryOrder): bool {.
    inline.}
  Source   Edit
proc compareExchangeWeak[T: not Trivial](location: var Atomic[T];
    expected: var T; desired: T; order: MemoryOrder = moSequentiallyConsistent): bool {.
    inline.}
  Source   Edit
proc compareExchangeWeak[T: not Trivial](location: var Atomic[T];
    expected: var T; desired: T; success, failure: MemoryOrder): bool {.inline.}
  Source   Edit
proc compareExchangeWeak[T: Trivial](location: var Atomic[T]; expected: var T;
                                     desired: T; order: MemoryOrder = moSequentiallyConsistent): bool {.
    inline.}
  Source   Edit
proc compareExchangeWeak[T: Trivial](location: var Atomic[T]; expected: var T;
                                     desired: T; success, failure: MemoryOrder): bool {.
    inline.}
  Source   Edit
proc exchange[T: not Trivial](location: var Atomic[T]; desired: T;
                              order: MemoryOrder = moSequentiallyConsistent): T {.
    inline.}
  Source   Edit
proc exchange[T: Trivial](location: var Atomic[T]; desired: T;
                          order: MemoryOrder = moSequentiallyConsistent): T {.
    inline.}
  Source   Edit
proc fence(order: MemoryOrder) {.importc: "atomic_thread_fence",
                                 header: "<stdatomic.h>", ...raises: [], tags: [].}
  Source   Edit
proc fetchAdd[T: SomeInteger](location: var Atomic[T]; value: T;
                              order: MemoryOrder = moSequentiallyConsistent): T {.
    inline.}
  Source   Edit
proc fetchAnd[T: SomeInteger](location: var Atomic[T]; value: T;
                              order: MemoryOrder = moSequentiallyConsistent): T {.
    inline.}
  Source   Edit
proc fetchOr[T: SomeInteger](location: var Atomic[T]; value: T;
                             order: MemoryOrder = moSequentiallyConsistent): T {.
    inline.}
  Source   Edit
proc fetchSub[T: SomeInteger](location: var Atomic[T]; value: T;
                              order: MemoryOrder = moSequentiallyConsistent): T {.
    inline.}
  Source   Edit
proc fetchXor[T: SomeInteger](location: var Atomic[T]; value: T;
                              order: MemoryOrder = moSequentiallyConsistent): T {.
    inline.}
  Source   Edit
proc load[T: not Trivial](location: var Atomic[T];
                          order: MemoryOrder = moSequentiallyConsistent): T {.
    inline.}
  Source   Edit
proc load[T: Trivial](location: var Atomic[T];
                      order: MemoryOrder = moSequentiallyConsistent): T {.inline.}
  Source   Edit
proc signalFence(order: MemoryOrder) {.importc: "atomic_signal_fence",
                                       header: "<stdatomic.h>", ...raises: [],
                                       tags: [].}
  Source   Edit
proc store[T: not Trivial](location: var Atomic[T]; desired: T;
                           order: MemoryOrder = moSequentiallyConsistent) {.
    inline.}
  Source   Edit
proc store[T: Trivial](location: var Atomic[T]; desired: T;
                       order: MemoryOrder = moSequentiallyConsistent) {.inline.}
  Source   Edit
proc testAndSet(location: var AtomicFlag;
                order: MemoryOrder = moSequentiallyConsistent): bool {.
    importc: "atomic_flag_test_and_set_explicit", header: "<stdatomic.h>",
    ...raises: [], tags: [].}
  Source   Edit

Templates

template nonAtomicType(T: typedesc[Trivial]): untyped
  Source   Edit