abit v0.2.0 Abit.Counter View Source

Use :atomics as an array of counters with N bits per counter. An :atomics is an array of 64 bit integers so the possible counters are below:

Possible counters:

bits | unsigned value range | signed value range
2    | 0..3                 | -2..1
4    | 0..15                | -8..7
8    | 0..255               | -128..127
16   | 0..65535             | -32768..32767
32   | 0..4294967295        | -2147483648..2147483647

If you need 64 bit counters use: Erlang counters

The option :wrap_around is set to false by default. With these small-ish counters this is a safe default. When :wrap_around is false when using put/3 or add/3 the error tuple {:error, :value_out_of_bounds} will be returned instead of wrap around and the stored counter value will not change.

While Erlang :atomics are 1 indexed, Abit.Counter counters are 0 indexed.

Link to this section Summary

Functions

Increments the value of the counter at index with incr.

Returns the value of counter at index.

Returns a new %Abit.Counter{} struct.

Puts the value into the counter at index.

Link to this section Types

Link to this type

t()

View Source
t() :: %Abit.Counter{
  atomics_ref: reference(),
  counters_bit_size: 2 | 4 | 8 | 16 | 32,
  max: pos_integer(),
  min: integer(),
  signed: boolean(),
  size: pos_integer(),
  wrap_around: boolean()
}

Link to this section Functions

Link to this function

add(counter, index, incr)

View Source
add(t(), non_neg_integer(), integer()) ::
  {:ok, {non_neg_integer(), integer()}} | {:error, :value_out_of_bounds}

Increments the value of the counter at index with incr.

Returns {:ok, {index, final_value}} or {:error, :value_out_of_bounds} if option wrap_around is false and value is out of bounds.

Examples

iex> c = Abit.Counter.new(10, 8)
iex> c |> Abit.Counter.add(7, -12)
{:ok, {7, -12}}
iex> c |> Abit.Counter.add(7, 36)
{:ok, {7, 24}}
iex> c |> Abit.Counter.put(1, 1000)
{:error, :value_out_of_bounds}

Returns the value of counter at index.

Examples

iex> c = Abit.Counter.new(10, 8)
iex> c |> Abit.Counter.get(7)
0
Link to this function

new(size, counters_bit_size, options \\ [])

View Source
new(non_neg_integer(), 2 | 4 | 8 | 16 | 32, list()) :: t()

Returns a new %Abit.Counter{} struct.

  • size - minimum number of counters to have (if they don't fill exactly a multiple 64 bit integers, there will be more to fill the :atomics, check the :size key in the returned %Abit.Counter{} struct for the exact number of counters.)
  • counters_bit_size - how many bits a counter should use

Options

  • :signed - whether to have signed or unsigned counters. Defaults to true.
  • :wrap_around - whether counters should wrap around. Defaults to false.

Examples

Abit.Counter.new(100, 8) # minimum 100 counters; 8 bits signed
Abit.Counter.new(10_000, 16, signed: false) # minimum 10_000 counters; 16 bits unsigned
Abit.Counter.new(10_000, 16, wrap_around: false) # don't wrap around
Link to this function

put(counter, index, value)

View Source
put(t(), non_neg_integer(), integer()) ::
  {:ok, {non_neg_integer(), integer()}} | {:error, :value_out_of_bounds}

Puts the value into the counter at index.

Returns {:ok, {index, final_value}} or {:error, :value_out_of_bounds} if option wrap_around is false and value is out of bounds.

Examples

iex> c = Abit.Counter.new(10, 8)
iex> c |> Abit.Counter.put(7, -12)
{:ok, {7, -12}}
iex> c |> Abit.Counter.get(7)
-12
iex> c |> Abit.Counter.put(7, 128)
{:error, :value_out_of_bounds}