1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
| %% @author Bob Ippolito <bob@mochimedia.com>
| %% @copyright 2010 Mochi Media, Inc.
| %% @doc Abuse module constant pools as a "read-only shared heap" (since erts 5.6)
| %% <a href="http://www.erlang.org/pipermail/erlang-questions/2009-March/042503.html">[1]</a>.
| -module(mochiglobal).
| -author("Bob Ippolito <bob@mochimedia.com>").
| -export([get/1, get/2, put/2, delete/1]).
|
| -spec get(atom()) -> any() | undefined.
| %% @equiv get(K, undefined)
| get(K) ->
| get(K, undefined).
|
| -spec get(atom(), T) -> any() | T.
| %% @doc Get the term for K or return Default.
| get(K, Default) ->
| get(K, Default, key_to_module(K)).
|
| get(_K, Default, Mod) ->
| try Mod:term()
| catch error:undef ->
| Default
| end.
|
| -spec put(atom(), any()) -> ok.
| %% @doc Store term V at K, replaces an existing term if present.
| put(K, V) ->
| put(K, V, key_to_module(K)).
|
| put(_K, V, Mod) ->
| Bin = compile(Mod, V),
| code:purge(Mod),
| {module, Mod} = code:load_binary(Mod, atom_to_list(Mod) ++ ".erl", Bin),
| ok.
|
| -spec delete(atom()) -> boolean().
| %% @doc Delete term stored at K, no-op if non-existent.
| delete(K) ->
| delete(K, key_to_module(K)).
|
| delete(_K, Mod) ->
| code:purge(Mod),
| code:delete(Mod).
|
| -spec key_to_module(atom()) -> atom().
| key_to_module(K) ->
| list_to_atom("mochiglobal:" ++ atom_to_list(K)).
|
| -spec compile(atom(), any()) -> binary().
| compile(Module, T) ->
| {ok, Module, Bin} = compile:forms(forms(Module, T),
| [verbose, report_errors]),
| Bin.
|
| -spec forms(atom(), any()) -> [erl_syntax:syntaxTree()].
| forms(Module, T) ->
| [erl_syntax:revert(X) || X <- term_to_abstract(Module, term, T)].
|
| -spec term_to_abstract(atom(), atom(), any()) -> [erl_syntax:syntaxTree()].
| term_to_abstract(Module, Getter, T) ->
| [%% -module(Module).
| erl_syntax:attribute(
| erl_syntax:atom(module),
| [erl_syntax:atom(Module)]),
| %% -export([Getter/0]).
| erl_syntax:attribute(
| erl_syntax:atom(export),
| [erl_syntax:list(
| [erl_syntax:arity_qualifier(
| erl_syntax:atom(Getter),
| erl_syntax:integer(0))])]),
| %% Getter() -> T.
| erl_syntax:function(
| erl_syntax:atom(Getter),
| [erl_syntax:clause([], none, [erl_syntax:abstract(T)])])].
|
|