%%
%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
%% You may obtain a copy of the License at
%%
%% http://www.apache.org/licenses/LICENSE-2.0
%%
%% Unless required by applicable law or agreed to in writing, software
%% distributed under the License is distributed on an "AS IS" BASIS,
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%% See the License for the specific language governing permissions and
%% limitations under the License.
%%
%% %CopyrightEnd%
%%
%% Purpose : Main atomics API module.
-module(counters).
-export([new/2,
get/2,
add/3,
sub/3,
put/3,
info/1]).
-export_type([counters_ref/0]).
-opaque counters_ref() :: {atomics, reference()} | {write_concurrency, reference()}.
-spec new(Size, Opts) -> counters_ref() when
Size :: pos_integer(),
Opts :: [Opt],
Opt :: atomics | write_concurrency.
new(Size, [atomics]) ->
{atomics, atomics:new(Size, [{signed, true}])};
new(Size, [write_concurrency]) ->
{write_concurrency, erts_internal:counters_new(Size)};
new(Size, []) ->
new(Size, [atomics]);
new(_, _) ->
erlang:error(badarg).
-spec get(Ref, Ix) -> integer() when
Ref :: counters_ref(),
Ix :: integer().
get({atomics,Ref}, Ix) ->
atomics:get(Ref, Ix);
get({write_concurrency, Ref}, Ix) ->
erts_internal:counters_get(Ref, Ix);
get(_, _) ->
erlang:error(badarg).
-spec add(Ref, Ix, Incr) -> ok when
Ref :: counters_ref(),
Ix :: integer(),
Incr :: integer().
add({atomics, Ref}, Ix, Incr) ->
atomics:add(Ref, Ix, Incr);
add({write_concurrency, Ref}, Ix, Incr) ->
erts_internal:counters_add(Ref, Ix, Incr);
add(_, _, _) ->
erlang:error(badarg).
-spec sub(Ref, Ix, Decr) -> ok when
Ref :: counters_ref(),
Ix :: integer(),
Decr :: integer().
sub(Ref, Ix, Decr) ->
add(Ref, Ix, -Decr).
-spec put(Ref, Ix, Value) -> ok when
Ref :: counters_ref(),
Ix :: integer(),
Value :: integer().
put({atomics, Ref}, Ix, Value) ->
atomics:put(Ref, Ix, Value);
put({write_concurrency, Ref}, Ix, Value) ->
erts_internal:counters_put(Ref, Ix, Value);
put(_, _, _) ->
erlang:error(badarg).
-spec info(Ref) -> Info when
Ref :: counters_ref(),
Info :: #{'size':=Size, 'memory':=Memory},
Size :: non_neg_integer(),
Memory :: non_neg_integer().
info({atomics, Ref}) ->
atomics:info(Ref);
info({write_concurrency, Ref}) ->
erts_internal:counters_info(Ref);
info(_) ->
erlang:error(badarg).