-module(erlang_ds_register).
-dialyzer([
{nowarn_function, bench/0},
{nowarn_function, get_type_handlers_appvar/0}
]).
-export([
get_type_handlers/0,
register_type_handler/1,
unregister_type_handler/1
]).
-export([
get_updater/1,
register_updater/2,
register_updaters/1,
unregister_updater/1,
unregister_updaters/1
]).
-export([
build_lookup/0
]).
%% only used for testing
-export([
bench/0
]).
get_type_handlers() ->
case erlang:function_exported(erlang_ds_lookup, type_handlers, 0) of
true ->
erlang_ds_lookup:type_handlers();
false ->
build_lookup(),
erlang_ds_lookup:type_handlers()
end.
get_type_handlers_appvar() ->
application:get_env(erlang_ds, type_handlers, []).
%% To verify how much faster the module-based version is
%% On my machine, module-based lookup is 5-12x faster
bench() ->
register_type_handler(a),
register_type_handler(b),
register_type_handler(c),
Seq = lists:seq(1, 100000),
{Timer1, Res1} = timer:tc(fun() ->
[get_type_handlers() || _ <- Seq]
end),
{Timer2, Res2} = timer:tc(fun() ->
[get_type_handlers_appvar() || _ <- Seq]
end),
io:format("PrintingResults:~n~p~nFrom Module: ~p.~nFrom App Var: ~p",[Res1 ++ Res2, Timer1, Timer2]).
register_type_handler(Mod) when is_atom(Mod) ->
with_app_var(type_handlers, erlang_ds_builder:default_type_modules(), fun(Mods) ->
case lists:member(Mod, Mods) of
true ->
Mods;
false ->
[Mod | Mods]
end
end),
build_lookup().
unregister_type_handler(Mod) when is_atom(Mod) ->
with_app_var(type_handlers, erlang_ds_builder:default_type_modules(), fun(Mods) ->
Mods -- [Mod]
end),
build_lookup().
get_updater(UpdaterKey) ->
case erlang:function_exported(erlang_ds_lookup, updater, 1) of
true ->
erlang_ds_lookup:updater(UpdaterKey);
false ->
build_lookup(),
erlang_ds_lookup:updater(UpdaterKey)
end.
register_updater(Key0, MFA0) ->
{Key, MFA} = ds_util:normalize_updater_pair(Key0, MFA0),
store_updater(Key, MFA).
register_updaters(KeyMFAs) ->
Updaters = ds_util:normalize_updaters(KeyMFAs),
store_updaters(Updaters).
store_updater(Key, MFA) ->
with_app_var(updaters, erlang_ds_builder:default_updaters(), fun(Updaters) ->
ds:set(Updaters, Key, MFA)
end),
build_lookup().
store_updaters(NewUpdaters) ->
with_app_var(updaters, erlang_ds_builder:default_updaters(), fun(Updaters) ->
ds:set(Updaters, NewUpdaters)
end),
build_lookup().
unregister_updater(Key0) ->
Key = ds_util:normalize_updater_key(Key0),
with_app_var(updaters, erlang_ds_builder:default_updaters(), fun(Updaters) ->
ds:delete(Updaters, Key)
end),
build_lookup().
unregister_updaters(Keys0) ->
Keys = [ds_util:normalize_updater_key(K) || K <- Keys0],
with_app_var(updaters, erlang_ds_builder:default_updaters(), fun(Updaters) ->
ds:delete_list(Updaters, Keys)
end),
build_lookup().
build_lookup() ->
erlang_ds_builder:build().
with_app_var(Key, Default, Fun) ->
Var = application:get_env(erlang_ds, Key, Default),
NewVar = Fun(Var),
application:set_env(erlang_ds, Key, NewVar).