AtomicFlags behaviour (atomic_flags v1.0.1)

Copy Markdown

Flags array implemented on top of :atomics module. See __using__/1 and callback docs for more information about available option and usage.

Example module

All examples and doctests are using this module as an example

defmodule RoomFlags do
  use AtomicFlags,
    global: true,
    schema: [
      :bin,
      tri: 3,
      lights: [
        :off,
        :on
      ],
      coin: [
        :head,
        :edge,
        :tails
      ]
    ]
end

Summary

Callbacks

Cycles the value to the next one after steps. It is equivalent to executing next/2 for steps amount of times.

Gets the value of the flag.

Returns boolean/0 indicating if the term is a valid key for the flags array. Can be used in guards

Creates an :atomics array which will store the information about flags.

Creates a global :atomics array. This function is generated only if global: true is specified in the use macro call.

Cycles the value to the next one. Returns the new value, the one which is set as the result of the next call.

Resets the value to theif default ones. That is 0 for numerical flags or the first value for the enumerable flags.

Resets all values to theif default ones. That is 0 for numerical flags or the first value for the enumerable flags.

Sets the value of the flag.

Tries to perform the compare and exchange operation on the flag. Returns :ok if operation is successful or {:error, value} when the from value is different from the value which is inside the flags array.

Returns a Keyword.t/0 list representing the current state of the array.

Functions

Generates an implmenetation of the behaviour and all required functions for operation with the flags based on the specified schema.

Types

key()

@type key() :: atom()

t()

@type t() :: :atomics.atomics_ref()

value()

@type value() :: term()

Callbacks

cycle(t, key, steps)

(optional)
@callback cycle(t(), key(), steps :: integer()) :: value()

Cycles the value to the next one after steps. It is equivalent to executing next/2 for steps amount of times.

Example:

iex> flags = RoomFlags.new()
iex> RoomFlags.cycle(flags, :lights, 1)
:on
iex> RoomFlags.cycle(flags, :lights, 2)
:on
iex> RoomFlags.cycle(flags, :lights, 3)
:off
iex> RoomFlags.cycle(flags, :lights, -3)
:on

get(t, key)

(optional)
@macrocallback get(t(), key()) :: Macro.t()

Gets the value of the flag.

Example:

iex> flags = RoomFlags.new()
iex> RoomFlags.get(flags, :lights)
:off
iex> RoomFlags.set(flags, :lights, :on)
iex> RoomFlags.get(flags, :lights)
:on

is_key(term)

(optional)
@macrocallback is_key(term()) :: Macro.t()

Returns boolean/0 indicating if the term is a valid key for the flags array. Can be used in guards

Example:

iex> RoomFlags.is_key(:lights)
true
iex> RoomFlags.is_key(:definitely_not_a_key)
false

new()

@callback new() :: :atomics.atomics_ref()

Creates an :atomics array which will store the information about flags.

Example:

iex> flags = RoomFlags.new()
iex> RoomFlags.get(flags, :lights)
:off

new_global()

(optional)
@callback new_global() :: :atomics.atomics_ref()

Creates a global :atomics array. This function is generated only if global: true is specified in the use macro call.

Example:

iex> RoomFlags.new_global()
iex> RoomFlags.get(:lights)
:off

next(t, key)

(optional)
@callback next(t(), key()) :: value()

Cycles the value to the next one. Returns the new value, the one which is set as the result of the next call.

Example:

iex> flags = RoomFlags.new()
iex> RoomFlags.next(flags, :lights)
:on
iex> RoomFlags.next(flags, :lights)
:off
iex> RoomFlags.next(flags, :lights)
:on
iex> RoomFlags.get(flags, :lights)
:on

iex> flags = RoomFlags.new()
iex> RoomFlags.next(flags, :coin)
:edge
iex> RoomFlags.next(flags, :coin)
:tails
iex> RoomFlags.next(flags, :coin)
:head
iex> RoomFlags.next(flags, :coin)
:edge
iex> RoomFlags.next(flags, :coin)
:tails

reset(t, key)

(optional)
@macrocallback reset(t(), key()) :: Macro.t()

Resets the value to theif default ones. That is 0 for numerical flags or the first value for the enumerable flags.

Example:

iex> flags = RoomFlags.new()
iex> RoomFlags.set(flags, :lights, :on)
iex> RoomFlags.reset(flags, :lights)
iex> RoomFlags.get(flags, :lights)
:off

reset_all(t)

(optional)
@callback reset_all(t()) :: :ok

Resets all values to theif default ones. That is 0 for numerical flags or the first value for the enumerable flags.

Example:

iex> flags = RoomFlags.new()
iex> RoomFlags.set(flags, :lights, :on)
iex> RoomFlags.reset_all(flags)
iex> RoomFlags.get(flags, :lights)
:off

set(t, key, value)

(optional)
@macrocallback set(t(), key(), value()) :: Macro.t()

Sets the value of the flag.

Example:

iex> flags = RoomFlags.new()
iex> RoomFlags.set(flags, :lights, :on)
iex> RoomFlags.get(flags, :lights)
:on

swap(t, key, list)

(optional)
@macrocallback swap(t(), key(), from: value(), to: value()) :: :ok

Tries to perform the compare and exchange operation on the flag. Returns :ok if operation is successful or {:error, value} when the from value is different from the value which is inside the flags array.

NOTE: You MUST specify options in the format from: <fromvalue>, to: <tovalue>. In that specific order. This is done to explicitly note the direction of the swap.

Example:

iex> flags = RoomFlags.new()
iex> RoomFlags.swap(flags, :lights, from: :off, to: :on)
:ok
iex> RoomFlags.get(flags, :lights)
:on
iex> RoomFlags.swap(flags, :lights, from: :off, to: :on)
{:error, :on}

to_list(t)

(optional)
@callback to_list(t()) :: Keyword.t()

Returns a Keyword.t/0 list representing the current state of the array.

Example:

iex> flags = RoomFlags.new()
iex> RoomFlags.to_list(flags)
[
  bin: 0,
  tri: 0,
  lights: :off,
  coin: :head
]

Functions

__using__(opts)

(macro)

Generates an implmenetation of the behaviour and all required functions for operation with the flags based on the specified schema.

Options

  • :schema — A list, defining a schema. Example entries are:

    • :flag — defines a binary 0 or 1 flag under the name :flag
    • states: 3 — defines a flag with values of 0, 1 or 2 under the name :states
    • ligths: [:on, :off] — defines an enumerable flag of values :on and :off under the name :lights. Enumerable values can be of any type.
  • :only — A keyword list of {function, arity} which defines what functions or macros will be generated

  • :except — A keyword list of {function, arity} which defines what functions or macros won't be generated

  • :global — If true, creates a function new_global/0 which sets up a global array in persistent_term. And also generates adds this global array as the default for the first argument in every function and macro.

    Persistent term key

    :persistent_term key is __MODULE__.