Current section
Files
Jump to
Current section
Files
src/booklet_ffi.erl
-module(booklet_ffi).
-behaviour(application).
-export([start/2, stop/1]).
-export([make/1, get/1, set/2, update/2, erase/1]).
-compile([no_auto_import]).
% -- Public API ----------------------------------------------------------------
make(DefaultValue) ->
{erlang:make_ref(), DefaultValue}.
get({Key, DefaultValue}) ->
Table = persistent_term:get(?MODULE),
try
ets:lookup_element(Table, Key, 3)
catch
error:badarg ->
DefaultValue
end.
set({Key, _}, Value) ->
Table = persistent_term:get(?MODULE),
true = ets:insert(Table, {Key, 0, Value}),
nil.
update({Key, DefaultValue} = Booklet, Updater) ->
Table = persistent_term:get(?MODULE),
case ets:lookup(Table, Key) of
[{_, Rev, Value}] ->
NewValue = Updater(Value),
Replacement = {const, {Key, Rev + 1, NewValue}},
case ets:select_replace(Table, [{{Key, Rev, '_'}, [], [Replacement]}]) of
0 ->
update(Booklet, Updater);
_ ->
NewValue
end;
[] ->
NewValue = Updater(DefaultValue),
case ets:insert_new(Table, {Key, 0, NewValue}) of
true ->
NewValue;
false ->
update(Booklet, Updater)
end
end.
erase({Key, _}) ->
Table = persistent_term:get(?MODULE),
ets:delete(Table, Key),
nil.
% -- APPLICATION ---------------------------------------------------------------
start(_StartType, _StartArgs) ->
Table =
ets:new(booklet,
[set, public, {keypos, 1}, {write_concurrency, auto}, {read_concurrency, true}]),
ok = persistent_term:put(?MODULE, Table),
{ok, erlang:self()}.
stop(_State) ->
persistent_term:erase(?MODULE),
ok.