abit v0.3.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 using put/3 or add/3 when the value
would be out of bounds the error tuple {:error, :value_out_of_bounds}
will be returned and the stored counter value will not change.
While Erlang :atomics are 1 indexed, Abit.Counter counters are 0 indexed.
Enumerable protocol
Abit.Counter implements the Enumerable protocol, so all Enum functions can be used:
iex> c = Abit.Counter.new(1000, 16, signed: false)
iex> c |> Abit.Counter.put(700, 54321)
iex> c |> Enum.max()
54321
Examples
iex> c = Abit.Counter.new(1000, 8, signed: false)
iex> c |> Abit.Counter.put(0, 100)
{:ok, {0, 100}}
iex> c |> Abit.Counter.add(0, 100)
{:ok, {0, 200}}
iex> c |> Abit.Counter.add(0, 100)
{:error, :value_out_of_bounds}
Link to this section Summary
Functions
Increments the value of the counter at index with incr.
Returns the value of counter at index.
Returns all counters from atomics at index.
Returns true if any counter has the value integer,
false otherwise.
Returns a new %Abit.Counter{} struct.
Puts the value into the counter at index.
Link to this section Types
t()
View Sourcet() :: %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
add(counter, index, incr)
View Sourceadd(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
get_all_at_atomic(counter, atomic_index)
View Source (since 0.2.4)get_all_at_atomic(t(), pos_integer()) :: [integer()]
Returns all counters from atomics at index.
Index of atomics are one-based.
Examples
iex> c = Abit.Counter.new(100, 8)
iex> c |> Abit.Counter.put(3, -70)
iex> c |> Abit.Counter.get_all_at_atomic(1)
[0, 0, 0, 0, -70, 0, 0, 0]
Returns true if any counter has the value integer,
false otherwise.
Examples
iex> c = Abit.Counter.new(100, 8)
iex> c |> Abit.Counter.member?(0)
true
iex> c |> Abit.Counter.member?(80)
false
new(size, counters_bit_size, options \\ [])
View Sourcenew(non_neg_integer(), 2 | 4 | 8 | 16 | 32, list()) :: t()
Returns a new %Abit.Counter{} struct.
size- minimum number of counters to have, counters will fully fill the:atomics. Check the:sizekey in the returned%Abit.Counter{}for the exact number of counterscounters_bit_size- how many bits a counter should use
Options
:signed- whether to have signed or unsigned counters. Defaults totrue.:wrap_around- whether counters should wrap around. Defaults tofalse.
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
put(counter, index, value)
View Sourceput(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}