%%%------------------------------------------------------------------- %%% @author Evgeny Khramtsov %%% %%% %%% Copyright (C) 2002-2020 ProcessOne, SARL. 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. %%% %%%------------------------------------------------------------------- -module(p1_shaper). %% API -export([new/1, new/2, update/2, pp/1]). -record(state, {maxrate = 0 :: integer(), burst_size = 0 :: integer(), acquired_credit = 0 :: integer(), lasttime = 0 :: integer()}). -opaque state() :: #state{}. -export_type([state/0]). %%%=================================================================== %%% API %%%=================================================================== -spec new(integer()) -> state(). new(MaxRate) -> new(MaxRate, MaxRate). -spec new(integer(), integer()) -> state(). new(MaxRate, BurstSize) -> #state{maxrate = MaxRate, burst_size = BurstSize, acquired_credit = BurstSize, lasttime = p1_time_compat:system_time(micro_seconds)}. -spec update(state(), non_neg_integer()) -> {state(), non_neg_integer()}. update(#state{maxrate = MR, burst_size = BS, acquired_credit = AC, lasttime = L} = State, Size) -> Now = p1_time_compat:system_time(micro_seconds), AC2 = min(BS, AC + (MR*(Now - L) div 1000000) - Size), Pause = if AC2 >= 0 -> 0; true -> -1000*AC2 div MR end, {State#state{acquired_credit = AC2, lasttime = Now}, Pause}. -spec pp(any()) -> iolist(). pp(Term) -> io_lib_pretty:print(Term, fun pp/2). %%%=================================================================== %%% Internal functions %%%=================================================================== -spec pp(atom(), non_neg_integer()) -> [atom()] | no. pp(state, 4) -> record_info(fields, state); pp(_, _) -> no.