1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 2018. All Rights Reserved.
5%%
6%% Licensed under the Apache License, Version 2.0 (the "License");
7%% you may not use this file except in compliance with the License.
8%% You may obtain a copy of the License at
9%%
10%%     http://www.apache.org/licenses/LICENSE-2.0
11%%
12%% Unless required by applicable law or agreed to in writing, software
13%% distributed under the License is distributed on an "AS IS" BASIS,
14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15%% See the License for the specific language governing permissions and
16%% limitations under the License.
17%%
18%% %CopyrightEnd%
19%%
20
21%% Purpose : Main atomics API module.
22
23-module(counters).
24
25-export([new/2,
26         get/2,
27         add/3,
28         sub/3,
29         put/3,
30         info/1]).
31
32-export_type([counters_ref/0]).
33
34-opaque counters_ref() :: {atomics, reference()} | {write_concurrency, reference()}.
35
36-spec new(Size, Opts) -> counters_ref() when
37      Size :: pos_integer(),
38      Opts :: [Opt],
39      Opt :: atomics | write_concurrency.
40new(Size, [atomics]) ->
41    {atomics, atomics:new(Size, [{signed, true}])};
42new(Size, [write_concurrency]) ->
43    {write_concurrency, erts_internal:counters_new(Size)};
44new(Size, []) ->
45    new(Size, [atomics]);
46new(_, _) ->
47    erlang:error(badarg).
48
49-spec get(Ref, Ix) -> integer() when
50      Ref  :: counters_ref(),
51      Ix :: integer().
52get({atomics,Ref}, Ix) ->
53    atomics:get(Ref, Ix);
54get({write_concurrency, Ref}, Ix) ->
55    erts_internal:counters_get(Ref, Ix);
56get(_, _) ->
57    erlang:error(badarg).
58
59
60
61-spec add(Ref, Ix, Incr) -> ok when
62      Ref  :: counters_ref(),
63      Ix :: integer(),
64      Incr :: integer().
65add({atomics, Ref}, Ix, Incr) ->
66    atomics:add(Ref, Ix, Incr);
67add({write_concurrency, Ref}, Ix, Incr) ->
68    erts_internal:counters_add(Ref, Ix, Incr);
69add(_, _, _) ->
70    erlang:error(badarg).
71
72
73-spec sub(Ref, Ix, Decr) -> ok when
74      Ref  :: counters_ref(),
75      Ix :: integer(),
76      Decr :: integer().
77sub(Ref, Ix, Decr) ->
78    add(Ref, Ix, -Decr).
79
80
81-spec put(Ref, Ix, Value) -> ok when
82      Ref  :: counters_ref(),
83      Ix :: integer(),
84      Value :: integer().
85put({atomics, Ref}, Ix, Value) ->
86    atomics:put(Ref, Ix, Value);
87put({write_concurrency, Ref}, Ix, Value) ->
88    erts_internal:counters_put(Ref, Ix, Value);
89put(_, _, _) ->
90    erlang:error(badarg).
91
92
93-spec info(Ref) -> Info when
94      Ref  :: counters_ref(),
95      Info :: #{'size':=Size, 'memory':=Memory},
96      Size :: non_neg_integer(),
97      Memory :: non_neg_integer().
98info({atomics, Ref}) ->
99    atomics:info(Ref);
100info({write_concurrency, Ref}) ->
101    erts_internal:counters_info(Ref);
102info(_) ->
103    erlang:error(badarg).
104
105