./ct_report/coverage/monitored_map.COVER.html

1 %%==============================================================================
2 %% Copyright 2016 Erlang Solutions Ltd.
3 %%
4 %% Licensed under the Apache License, Version 2.0 (the "License");
5 %% you may not use this file except in compliance with the License.
6 %% You may obtain a copy of the License at
7 %%
8 %% http://www.apache.org/licenses/LICENSE-2.0
9 %%
10 %% Unless required by applicable law or agreed to in writing, software
11 %% distributed under the License is distributed on an "AS IS" BASIS,
12 %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 %% See the License for the specific language governing permissions and
14 %% limitations under the License.
15 %%==============================================================================
16
17 -module(monitored_map).
18 -author('konrad.zemek@erlang-solutions.com').
19
20 -export([new/0, put/4, remove/2, find/2, get/2, get/3, handle_info/2]).
21
22 -ignore_xref([remove/2, find/2, get/2, get/3]).
23
24 -record(monitored_map, {
25 map = #{} :: #{term() => {term(), pid(), reference()}},
26 monitors = #{} :: #{reference() => term()}
27 }).
28
29 -type t() :: #monitored_map{}.
30 -type t(KeyT, ValueT) :: #monitored_map{map :: #{KeyT => {ValueT, pid(), reference()}},
31 monitors :: #{reference() => KeyT}}.
32
33 -export_type([t/0, t/2]).
34
35 %%--------------------------------------------------------------------
36 %% API
37 %%--------------------------------------------------------------------
38
39 -spec new() -> t().
40 new() ->
41 24 #monitored_map{}.
42
43 -spec put(Key :: term(), Value :: term(), Pid :: pid(), MonMap :: t()) -> t().
44 put(Key, Value, Pid, #monitored_map{map = Map, monitors = Monitors} = MonMap) ->
45 721 case maps:get(Key, Map, {undefined, undefined, make_ref()}) of
46 {_, Pid, Ref} ->
47 4 NewMap = maps:put(Key, {Value, Pid, Ref}, Map),
48 4 MonMap#monitored_map{map = NewMap};
49
50 {_, _, OldRef} ->
51 717 demonitor(OldRef),
52 717 Ref = monitor(process, Pid),
53 717 NewMonitors = maps:put(Ref, Key, maps:remove(Ref, Monitors)),
54 717 NewMap = maps:put(Key, {Value, Pid, Ref}, Map),
55 717 MonMap#monitored_map{map = NewMap, monitors = NewMonitors}
56 end.
57
58 -spec remove(Key :: term(), MonMap :: t()) -> t().
59 remove(Key, #monitored_map{map = Map, monitors = Monitors} = MonMap) ->
60
:-(
case maps:find(Key, Map) of
61 {ok, {_Value, _Pid, Ref}} ->
62
:-(
demonitor(Ref),
63
:-(
NewMap = maps:remove(Key, Map),
64
:-(
NewMonitors = maps:remove(Ref, Monitors),
65
:-(
MonMap#monitored_map{map = NewMap, monitors = NewMonitors};
66 _ ->
67
:-(
MonMap
68 end.
69
70 -spec find(Key :: term(), MonMap :: t()) -> {ok, term()} | error.
71 find(Key, #monitored_map{map = Map}) ->
72 124 case maps:find(Key, Map) of
73 46 {ok, {Value, _, _}} -> {ok, Value};
74 78 Other -> Other
75 end.
76
77 -spec get(Key :: term(), MonMap :: t()) -> term() | no_return().
78 get(Key, #monitored_map{map = Map}) ->
79
:-(
{Value, _, _} = maps:get(Key, Map),
80
:-(
Value.
81
82 -spec get(Key :: term(), MonMap :: t(), Default :: term()) -> term().
83 get(Key, #monitored_map{map = Map}, Default) ->
84
:-(
{Value, _, _} = maps:get(Key, Map, {Default, undefined, undefined}),
85
:-(
Value.
86
87 -spec handle_info(Message :: term(), MonMap :: t()) -> t().
88 handle_info({'DOWN', MonitorRef, _Type, _Object, _Info},
89 #monitored_map{map = Map, monitors = Monitors} = MonMap) ->
90 702 case maps:find(MonitorRef, Monitors) of
91 {ok, Key} ->
92 702 NewMap = maps:remove(Key, Map),
93 702 NewMonitors = maps:remove(MonitorRef, Monitors),
94 702 MonMap#monitored_map{map = NewMap, monitors = NewMonitors};
95 error ->
96
:-(
MonMap
97 end;
98 handle_info(_, MonMap) ->
99
:-(
MonMap.
Line Hits Source