Packages
ra
3.1.2
3.1.9
3.1.8
3.1.7
3.1.6
3.1.5
3.1.4
3.1.3
3.1.2
3.1.1
3.1.0
3.0.2
3.0.1
3.0.0
3.0.0-beta.1
2.17.3
2.17.2
2.17.1
2.17.0
2.16.13
2.16.12
2.16.11
2.16.10
2.16.9
2.16.8
2.16.7
2.16.6
2.16.5
2.16.4
2.16.3
2.16.2
2.16.1
2.16.0
2.16.0-pre.12
2.16.0-pre.11
2.16.0-pre.10
2.16.0-pre.9
2.16.0-pre.8
2.16.0-pre.7
2.16.0-pre.6
2.16.0-pre.5
2.16.0-pre.4
2.16.0-pre.3
2.16.0-pre.2
2.16.0-pre.1
2.15.4
2.15.3
2.15.2
2.15.1
2.15.0
2.14.0
2.13.6
2.13.5
2.13.4
2.13.3
2.13.2
2.13.1
2.13.0
2.13.0-pre.1
2.12.0
2.11.0
2.11.0-pre.1
2.10.2-pre.2
2.10.2-pre.1
2.10.1
2.10.0
2.10.0-pre.3
2.10.0-pre.2
2.10.0-pre.1
2.9.10-pre.1
2.9.1
2.9.1-pre.2
2.9.1-pre.1
2.9.0
2.8.0
retired
2.7.3
2.7.2
2.7.1
2.7.0
2.7.0-pre.3
2.7.0-pre.2
2.7.0-pre.1
2.6.3
2.6.2
2.6.1
2.6.0-pre.1
2.5.1
2.5.1-pre.1
2.5.0
2.4.9
2.4.8
2.4.7
2.4.6
2.4.5
2.4.4
2.4.3
2.4.2
retired
2.4.1
2.4.0
2.3.0
2.2.0
2.1.0
2.0.13
2.0.12
2.0.11
2.0.10
2.0.9
2.0.8
2.0.7
2.0.6
2.0.5
2.0.4
2.0.3
2.0.2
2.0.1
2.0.0
1.1.9
1.1.8
1.1.7
1.1.6
1.1.5
1.1.4
1.1.3
1.1.2
1.1.1
1.1.0
1.0.8
1.0.7
1.0.6
1.0.5
1.0.4
1.0.3
1.0.2
1.0.1
1.0.0
0.9.6
0.9.5
0.9.4
0.9.2
0.3.3
retired
0.3.2
retired
0.3.1
retired
Raft library
Current section
Files
Jump to
Current section
Files
src/ra_flru.erl
%% This Source Code Form is subject to the terms of the Mozilla Public
%% License, v. 2.0. If a copy of the MPL was not distributed with this
%% file, You can obtain one at https://mozilla.org/MPL/2.0/.
%%
%% Copyright (c) 2017-2025 Broadcom. All Rights Reserved. The term Broadcom refers to Broadcom Inc. and/or its subsidiaries.
%%
%% @hidden
-module(ra_flru).
%% small fixed size simple lru cache
%% inefficient on larger sizes
-export([
new/2,
fetch/2,
insert/3,
evict/2,
evict_all/1,
size/1,
max_size/1
]).
-define(MAX_SIZE, 5).
-type kv_item() :: {Key :: term(), Value :: term()}.
-type handler_fun() :: fun((kv_item()) -> ok).
-record(?MODULE, {max_size = ?MAX_SIZE :: non_neg_integer(),
items = [] :: [term()],
handler = fun (_) -> ok end :: handler_fun()}).
-opaque state() :: #?MODULE{}.
-export_type([
state/0
]).
-spec new(non_neg_integer(), handler_fun()) ->
state().
new(MaxSize, Handler) ->
#?MODULE{handler = Handler,
max_size = MaxSize}.
-spec fetch(term(), state()) ->
{ok, term(), state()} | error.
fetch(Key, #?MODULE{items = [{Key, Value} | _]} = State) ->
%% head optimisation
{ok, Value, State};
fetch(Key, #?MODULE{items = Items0} = State0) ->
case lists:keytake(Key, 1, Items0) of
{value, {_, Value} = T, Items} ->
{ok, Value, State0#?MODULE{items = [T | Items]}};
false ->
error
end.
-spec insert(term(), term(), state()) -> state().
insert(Key, Value, #?MODULE{items = Items,
max_size = M,
handler = Handler} = State)
when length(Items) =:= M ->
%% cache is full, discard last item
[Old | Rem] = lists:reverse(Items),
%% call the handler
ok = Handler(Old),
State#?MODULE{items = [{Key, Value} | lists:reverse(Rem)]};
insert(Key, Value, #?MODULE{items = Items} = State) ->
%% else just append it
State#?MODULE{items = [{Key, Value} | Items]}.
-spec evict(Key :: term(), state()) ->
{Evicted :: kv_item(), state()} | error.
evict(Key, #?MODULE{items = Items0,
handler = Handler} = State) ->
case lists:keytake(Key, 1, Items0) of
{value, T, Items} ->
ok = Handler(T),
{T, State#?MODULE{items = Items}};
false ->
error
end.
-spec evict_all(state()) -> state().
evict_all(#?MODULE{items = Items,
handler = Handler}) ->
[Handler(T) || T <- Items],
#?MODULE{items = []}.
-spec size(state()) -> non_neg_integer().
size(#?MODULE{items = Items}) ->
length(Items).
-spec max_size(state()) -> non_neg_integer().
max_size(#?MODULE{max_size = MaxSize}) ->
MaxSize.
-ifdef(TEST).
-include_lib("eunit/include/eunit.hrl").
evit_test() ->
C0 = new(3, fun(I) -> ?debugFmt("~w evicted", [I]) end),
C1 = insert(k1, v1, C0),
C2 = insert(k2, v2, C1),
{{k1, v1}, C3} = evict(k1, C2),
error = evict(k3, C3),
ok.
basics_test() ->
C0 = new(3, fun(I) -> ?debugFmt("~w evicted", [I]) end),
C1 = insert(k1, v1, C0),
C2 = insert(k2, v2, C1),
C3 = insert(k3, v3, C2),
C4 = insert(k4, v4, C3),
?assertEqual(error, fetch(k1, C4)),
{ok, v2, C5} = fetch(k2, C4),
C6 = insert(k5, v5, C5),
%% k2 should still be readable here
{ok, v2, C7} = fetch(k2, C6),
%% k3 should have been evicted
error = fetch(k3, C7),
ok.
-endif.