PageRenderTime 479ms CodeModel.GetById 32ms RepoModel.GetById 10ms app.codeStats 0ms

/src/mochiglobal.erl

http://github.com/basho/mochiweb
Erlang | 127 lines | 82 code | 14 blank | 31 comment | 1 complexity | 2e3151aa1c638bafb486e4ccacafce45 MD5 | raw file
Possible License(s): MIT
  1. %% @author Bob Ippolito <bob@mochimedia.com>
  2. %% @copyright 2010 Mochi Media, Inc.
  3. %%
  4. %% Permission is hereby granted, free of charge, to any person obtaining a
  5. %% copy of this software and associated documentation files (the "Software"),
  6. %% to deal in the Software without restriction, including without limitation
  7. %% the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8. %% and/or sell copies of the Software, and to permit persons to whom the
  9. %% Software is furnished to do so, subject to the following conditions:
  10. %%
  11. %% The above copyright notice and this permission notice shall be included in
  12. %% all copies or substantial portions of the Software.
  13. %%
  14. %% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. %% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. %% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  17. %% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. %% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. %% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  20. %% DEALINGS IN THE SOFTWARE.
  21. %% @doc Abuse module constant pools as a "read-only shared heap" (since erts 5.6)
  22. %% <a href="http://www.erlang.org/pipermail/erlang-questions/2009-March/042503.html">[1]</a>.
  23. -module(mochiglobal).
  24. -author("Bob Ippolito <bob@mochimedia.com>").
  25. -export([get/1, get/2, put/2, delete/1]).
  26. -spec get(atom()) -> any() | undefined.
  27. %% @equiv get(K, undefined)
  28. get(K) ->
  29. get(K, undefined).
  30. -spec get(atom(), T) -> any() | T.
  31. %% @doc Get the term for K or return Default.
  32. get(K, Default) ->
  33. get(K, Default, key_to_module(K)).
  34. get(_K, Default, Mod) ->
  35. try Mod:term()
  36. catch error:undef ->
  37. Default
  38. end.
  39. -spec put(atom(), any()) -> ok.
  40. %% @doc Store term V at K, replaces an existing term if present.
  41. put(K, V) ->
  42. put(K, V, key_to_module(K)).
  43. put(_K, V, Mod) ->
  44. Bin = compile(Mod, V),
  45. code:purge(Mod),
  46. {module, Mod} = code:load_binary(Mod, atom_to_list(Mod) ++ ".erl", Bin),
  47. ok.
  48. -spec delete(atom()) -> boolean().
  49. %% @doc Delete term stored at K, no-op if non-existent.
  50. delete(K) ->
  51. delete(K, key_to_module(K)).
  52. delete(_K, Mod) ->
  53. code:purge(Mod),
  54. code:delete(Mod).
  55. -spec key_to_module(atom()) -> atom().
  56. key_to_module(K) ->
  57. list_to_atom("mochiglobal:" ++ atom_to_list(K)).
  58. -spec compile(atom(), any()) -> binary().
  59. compile(Module, T) ->
  60. {ok, Module, Bin} = compile:forms(forms(Module, T),
  61. [verbose, report_errors]),
  62. Bin.
  63. -spec forms(atom(), any()) -> [erl_syntax:syntaxTree()].
  64. forms(Module, T) ->
  65. [erl_syntax:revert(X) || X <- term_to_abstract(Module, term, T)].
  66. -spec term_to_abstract(atom(), atom(), any()) -> [erl_syntax:syntaxTree()].
  67. term_to_abstract(Module, Getter, T) ->
  68. [%% -module(Module).
  69. erl_syntax:attribute(
  70. erl_syntax:atom(module),
  71. [erl_syntax:atom(Module)]),
  72. %% -export([Getter/0]).
  73. erl_syntax:attribute(
  74. erl_syntax:atom(export),
  75. [erl_syntax:list(
  76. [erl_syntax:arity_qualifier(
  77. erl_syntax:atom(Getter),
  78. erl_syntax:integer(0))])]),
  79. %% Getter() -> T.
  80. erl_syntax:function(
  81. erl_syntax:atom(Getter),
  82. [erl_syntax:clause([], none, [erl_syntax:abstract(T)])])].
  83. %%
  84. %% Tests
  85. %%
  86. -ifdef(TEST).
  87. -include_lib("eunit/include/eunit.hrl").
  88. get_put_delete_test() ->
  89. K = '$$test$$mochiglobal',
  90. delete(K),
  91. ?assertEqual(
  92. bar,
  93. get(K, bar)),
  94. try
  95. ?MODULE:put(K, baz),
  96. ?assertEqual(
  97. baz,
  98. get(K, bar)),
  99. ?MODULE:put(K, wibble),
  100. ?assertEqual(
  101. wibble,
  102. ?MODULE:get(K))
  103. after
  104. delete(K)
  105. end,
  106. ?assertEqual(
  107. bar,
  108. get(K, bar)),
  109. ?assertEqual(
  110. undefined,
  111. ?MODULE:get(K)),
  112. ok.
  113. -endif.