iyi

Standard library, 0.18.0

std/atomic

iyi: the weaker atomic verbs, and the bitwise ones, on the prelude's Atomic(T).

import std/atomic to use it. Source: src/std/atomic.iyi at v0.18.0.

The prelude's Atomic(T) has six verbs and one ordering, sequentially consistent, with no parameter to weaken it; it records that a weaker spelling arrives "as its own verb rather than a parameter, so a call site says what it means". This module is those verbs. Each name carries its ordering as a suffix — add_relaxed, get_acquire, set_release, swap_acq_rel, compare_and_set_acq_rel — so the ordering is a constant the compiler emits as that one instruction, never a runtime branch, and a reader of the call site does not have to look up an argument.

The suffixes: _relaxed is atomic and nothing more (LLVM's monotonic); _acquire is a load nothing after it may move before; _release is a store nothing before it may move after; _acq_rel is both, for a read-modify-write. A load has no release half and a store no acquire half, so get has two weaker spellings and set two; the read-modify-writes have four. compare_and_set_* names the success ordering; the failure ordering is the strongest a failed exchange can carry (acquire under _acquire/_acq_rel, relaxed otherwise).

The bitwise verbs and, nand, xor, max, min are sequentially consistent like the prelude's, and answer what the word held before. Bitwise or is spelled bitwise_or: .or is iyi's recovery keyword (expr.or { fallback }) and cannot be a method name. max/min pick the signed or unsigned instruction from T at compile time.

Atomic.fence is a full fence; fence_acquire, fence_release and fence_acq_rel are the weaker ones. There is no relaxed fence: LLVM has none and neither does the hardware.

T is what the prelude admits: Int32, Int64, UInt8 or UInt64. There is no Atomic(Bool) and no flag type here; the prelude refuses the instantiation, and a flag is a UInt8 word with swap.

Atomic(T)struct, reopened

std/atomiciyi doc src/std/atomic.iyi
struct ::Atomic(T)
  def add_acq_rel(value : T) : T
  def add_acquire(value : T) : T
  def add_relaxed(value : T) : T
  def add_release(value : T) : T
  # `word &= value`; answers what the word held before.
  def and(value : T) : T
  # `word |= value`; answers what the word held before.
  def bitwise_or(value : T) : T
  def compare_and_set_acq_rel(expected : T, desired : T) : Tuple(T, Bool)
  def compare_and_set_acquire(expected : T, desired : T) : Tuple(T, Bool)
  # `compare_and_set` at each weaker ordering: if the word holds
  # `expected` it now holds `desired`; answers what the word held and
  # whether the exchange happened.
  def compare_and_set_relaxed(expected : T, desired : T) : Tuple(T, Bool)
  def compare_and_set_release(expected : T, desired : T) : Tuple(T, Bool)
  # A full fence: nothing crosses it in either direction.
  def self.fence : Nil
  # Both halves, without the total order of `fence`.
  def self.fence_acq_rel : Nil
  # Nothing after this fence moves before it.
  def self.fence_acquire : Nil
  # Nothing before this fence moves after it.
  def self.fence_release : Nil
  # The word, read once; nothing after the read moves before it.
  def get_acquire : T
  # The word, read once, atomic and nothing more.
  def get_relaxed : T
  # `word = max(word, value)`, signed or unsigned as `T` is; answers what
  # the word held before.
  def max(value : T) : T
  # `word = min(word, value)`, signed or unsigned as `T` is; answers what
  # the word held before.
  def min(value : T) : T
  # `word = ~(word & value)`; answers what the word held before.
  def nand(value : T) : T
  # The word, written once, atomic and nothing more.
  def set_relaxed(value : T) : Nil
  # The word, written once; nothing before the write moves after it.
  def set_release(value : T) : Nil
  def sub_acq_rel(value : T) : T
  def sub_acquire(value : T) : T
  def sub_relaxed(value : T) : T
  def sub_release(value : T) : T
  def swap_acq_rel(value : T) : T
  def swap_acquire(value : T) : T
  def swap_relaxed(value : T) : T
  def swap_release(value : T) : T
  # `word ^= value`; answers what the word held before.
  def xor(value : T) : T
end

IyiAtomicstruct, reopened

std/atomiciyi doc src/std/atomic.iyi
struct ::IyiAtomic
  def self.fence(ordering : Symbol, singlethread : Bool) : Nil
end