%% @doc Fling is a cache library that abuses the constant pool of modules for %% off-heap shared access to arbitrary Erlang terms that is much faster than %% ETS. However, it comes at the cost of a dynamically compiled and loaded %% Erlang module, so this technique is really only suitable for situations %% with very low write needs and very high read concurrency. %% %% Fling takes the approach that the caller is responsible for creating an %% ETS table as the initial cache. Operation of this cache can proceed as %% normal - loading data into ETS as usual. When writes are all or mostly %% finished, the caller turns the ETS table over to a fling gen_server %% which manages the state of the cache from then on. %% %% When puts to the turned over table have hit a certain threshold of %% time with no new puts -- by default this is 5 ticks of 5 seconds each, %% or 25 seconds total -- fling "promotes" the ETS table into a dynamically %% constructed Erlang module which can then be used in place of the ETS %% table for significantly faster lookups. %% %% If a new put occurs in the "module" state, the write is accepted in %% ETS and the timer to promote a new module starts again. -module(fling). -export([ start/0, gen_module_name/0, manage/4, state/1, mode_sync/1, mode/2, get/2, put/2, put_async/2 ]). -type fling_mode() :: { ets, Tid :: ets:tid() } | { mg, ModName :: atom() }. -spec start() -> ok. %% @doc Convenience function to start the application from the command line. %% %% As in `erl -pz ebin deps/*/ebin -s fling' start() -> application:ensure_all_started(fling), application:start(fling). %% @doc This method gives an ETS table away to fling. In general, %% `public' and `protected' tables work best. The pid returned is %% the gen_server managing the state of the given cache. -spec manage( Tid :: ets:tid(), GetKey :: fling_mochiglobal:get_expr_fun(), GetValue :: fling_mochiglobal:get_expr_fun(), ModName :: atom() ) -> Pid :: pid(). manage(Tid, GetKey, GetValue, ModName) -> {ok, Pid} = fling_sup:start_ets_server(GetKey, GetValue, ModName), ets:give_away(Tid, Pid, []), Pid. %% @doc Generate a unique random module name for use when an ETS table %% is promoted. -spec gen_module_name() -> atom(). gen_module_name() -> fling_mochiglobal:gen_module_name(). -spec state( Pid :: pid() ) -> proplists:proplist(). %% @doc Returns the current state of the cache manager. Keys returned are: %% %%