File: //usr/lib/erlang/lib/erts-13.0.3/src/counters.erl
%%
%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 2018-2021. 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 counters 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()}.
%% We must inline this function so that the stacktrace points to
%% the correct function.
-compile({inline, [error_with_info/2]}).
-spec new(Size, Opts) -> counters_ref() when
Size :: pos_integer(),
Opts :: [Opt],
Opt :: atomics | write_concurrency.
new(Size, Options) ->
try
case Options of
[atomics] ->
{atomics, atomics:new(Size, [{signed, true}])};
[write_concurrency] ->
{write_concurrency, erts_internal:counters_new(Size)};
[] ->
{atomics, atomics:new(Size, [{signed, true}])};
_ ->
error(badopt)
end
catch
error:badopt ->
ExtraInfo = [{error_info, #{module => erl_erts_errors,
cause => badopt}}],
error(badarg, [Size, Options], ExtraInfo);
error:Error ->
error_with_info(Error, [Size, Options])
end.
-spec get(Ref, Ix) -> integer() when
Ref :: counters_ref(),
Ix :: integer().
get(Ref, Ix) ->
try
case Ref of
{atomics, R} ->
atomics:get(R, Ix);
{write_concurrency, R} ->
erts_internal:counters_get(R, Ix);
_ ->
error(badarg)
end
catch
error:Error ->
error_with_info(Error, [Ref, Ix])
end.
-spec add(Ref, Ix, Incr) -> ok when
Ref :: counters_ref(),
Ix :: integer(),
Incr :: integer().
add(Ref, Ix, Incr) ->
try
case Ref of
{atomics, R} ->
atomics:add(R, Ix, Incr);
{write_concurrency, R} ->
erts_internal:counters_add(R, Ix, Incr);
_ ->
error(badarg)
end
catch
error:Error ->
error_with_info(Error, [Ref, Ix, Incr])
end.
-spec sub(Ref, Ix, Decr) -> ok when
Ref :: counters_ref(),
Ix :: integer(),
Decr :: integer().
sub(Ref, Ix, Decr) ->
try
Incr = -Decr,
case Ref of
{atomics, R} ->
atomics:add(R, Ix, Incr);
{write_concurrency, R} ->
erts_internal:counters_add(R, Ix, Incr);
_ ->
error(badarg)
end
catch
error:Error ->
error_with_info(Error, [Ref, Ix, Decr])
end.
-spec put(Ref, Ix, Value) -> ok when
Ref :: counters_ref(),
Ix :: integer(),
Value :: integer().
put(Ref, Ix, Value) ->
try
case Ref of
{atomics, R} ->
atomics:put(R, Ix, Value);
{write_concurrency, R} ->
erts_internal:counters_put(R, Ix, Value);
_ ->
error(badarg)
end
catch
error:Error ->
error_with_info(Error, [Ref, Ix, Value])
end.
-spec info(Ref) -> Info when
Ref :: counters_ref(),
Info :: #{'size':=Size, 'memory':=Memory},
Size :: non_neg_integer(),
Memory :: non_neg_integer().
info(Ref) ->
try
case Ref of
{atomics, R} ->
atomics:info(R);
{write_concurrency, R} ->
erts_internal:counters_info(R);
_ ->
error(badarg)
end
catch
error:Error ->
error_with_info(Error, [Ref])
end.
error_with_info(Reason, Args) ->
error(Reason, Args, [{error_info, #{module => erl_erts_errors}}]).