atomics(3)

πŸ“¦
version 29.0.6 Β· 4 versions
, in ubuntu stonking

πŸ¦‹ atomics β€” Atomic Functions πŸ’…

ok so bestie, welcome to atomics, the Erlang module that does Atomic Functions. it's in the erts manual section and honestly? it's giving raw power. let's get into it. ✨


🌸 DESCRIPTION 🌸

This module hands you a whole set of functions for doing atomic operations on mutable atomic variables. and the way it does it?? it uses only atomic hardware instructions with no software-level locking at all β€” which is exactly why it's so ridiculously efficient for concurrent access. no cap. πŸ”₯

The atomics are organized into arrays, with these semantics, and bestie you need to know all of them:

  • Atomics are 64 bit integers.
  • Atomics can be represented as either signed or unsigned.
  • Atomics wrap around at overflow and underflow operations.
  • All operations guarantee atomicity. No intermediate results can be seen. The result of one mutation can only be the input to one following mutation. (iconic behaviour honestly πŸ’…)
  • All atomic operations are mutually ordered. If atomic B is updated after atomic A, then that is how it will appear to any concurrent readers. No one can read the new value of B and then read the old value of A.
  • Indexes into atomic arrays are one-based. An atomic array of arity N contains N atomics with index from 1 to N. (yes bestie, 1 to N, not 0. we're not doing the zero thing here.)

πŸŽ€ DATA TYPES πŸŽ€

  • -opaque atomics_ref() β€” Identifies an atomic array returned from new/2. this is your little handle, your main character ticket to the array 🌈

✨ FUNCTIONS ✨

add(Ref, Ix, Incr) -> ok

when
    Ref :: atomics_ref(),
    Ix :: pos_integer(),
    Incr :: integer().

Add Incr to atomic. simple as that. 🫢

add_get(Ref, Ix, Incr) -> integer()

when
    Ref :: atomics_ref(),
    Ix :: pos_integer(),
    Incr :: integer().

Atomically add Incr to atomic and return the result. it adds and tells you what you got β€” overachiever behaviour, we love her πŸ‘‘

compare_exchange(Ref, Ix, Expected, Desired) -> ok | integer()

when
    Ref :: atomics_ref(),
    Ix :: pos_integer(),
    Expected :: integer(),
    Desired :: integer().

Atomically compare the atomic with Expected, and if those are equal, set atomic to Desired.

Return ok if Desired was written. Return the actual atomic value if not equal to Expected. so basically it either says "slay, done" or it tells you what the value actually was. πŸ’…

exchange(Ref, Ix, Desired) -> integer()

when
    Ref :: atomics_ref(),
    Ix :: pos_integer(),
    Desired :: integer().

Atomically replace the value of the atomic with Desired and return the previous value. out with the old, in with the new, and she hands you the old one on the way out πŸŽ€

get(Ref, Ix) -> integer()

when Ref :: atomics_ref(), Ix :: pos_integer().

Read atomic value. that's it. that's the function. lowkey the most chill one here 🌸

info(Ref) -> Info

when
    Ref :: atomics_ref(),
    Info ::
        #{size := Size,
          max := Max,
          min := Min,
          memory := Memory},
    Size :: non_neg_integer(),
    Max :: integer(),
    Min :: integer(),
    Memory :: non_neg_integer().

Return information about an atomic array in a map. πŸ“‹

The map has the following keys:

  • size β€” The number of atomics in the array.
  • max β€” The highest possible value an atomic in this array can hold.
  • min β€” The lowest possible value an atomic in this array can hold.
  • memory β€” Approximate memory consumption for the array in bytes.

new(Arity, Opts) -> atomics_ref()

when
    Arity :: pos_integer(),
    Opts :: [Opt],
    Opt :: {signed, boolean()}.

Create a new array of Arity number of atomics. All atomics in the array are initially set to zero. fresh array, blank slate, clean girl aesthetic ✨

Argument Opts is a list of the following possible options:

  • {signed, boolean()} β€” Indicate if the elements of the array will be treated as signed or unsigned integers. Default is true (signed).

The integer interval for signed atomics are from -(1 bsl 63) to (1 bsl 63)-1 and for unsigned atomics from 0 to (1 bsl 64)-1. those numbers are big big. πŸ™ˆ

Atomics are not tied to the current process and are automatically garbage collected when they are no longer referenced. she's independent, she cleans up after herself πŸ’…

put(Ref, Ix, Value) -> ok

when
    Ref :: atomics_ref(),
    Ix :: pos_integer(),
    Value :: integer().

Set atomic to Value. done and dusted 🫢

sub(Ref, Ix, Decr) -> ok

when
    Ref :: atomics_ref(),
    Ix :: pos_integer(),
    Decr :: integer().

Subtract Decr from atomic. math but make it atomic 🧚

sub_get(Ref, Ix, Decr) -> integer()

when
    Ref :: atomics_ref(),
    Ix :: pos_integer(),
    Decr :: integer().

Atomically subtract Decr from atomic and return the result. subtract AND report back β€” she does both, she's a multitasker, she's the moment ⭐


real talk bestie: remember the wrap-around thing. overflow and underflow just wrap, and indexes start at 1 always. don't come at her with a 0 🌈

and that's the whole page!! this one came to you from Ericsson AB, rocking erts 17.0.6, dated with the atomics(3) energy we know and love. mwah πŸ’– bye bestie, go be atomic βœ¨πŸ’…πŸŽ€

πŸ“¦ where this page comes from