Skip to content
This repository
Browse code

Added gproc:munreg/3

  • Loading branch information...
commit 75f02985d8ca6a6f3a53e1b57509827103d73d82 1 parent f096466
authored May 03, 2011
25  doc/gproc.md
Source Rendered
@@ -163,7 +163,7 @@ Type and scope for select(), qlc() and stepping:
163 163
 
164 164
 
165 165
 
166  
-<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#add_global_aggr_counter-1">add_global_aggr_counter/1</a></td><td>Registers a global (unique) aggregated counter.</td></tr><tr><td valign="top"><a href="#add_global_counter-2">add_global_counter/2</a></td><td>Registers a global (non-unique) counter.</td></tr><tr><td valign="top"><a href="#add_global_name-1">add_global_name/1</a></td><td>Registers a global (unique) name.</td></tr><tr><td valign="top"><a href="#add_global_property-2">add_global_property/2</a></td><td>Registers a global (non-unique) property.</td></tr><tr><td valign="top"><a href="#add_local_aggr_counter-1">add_local_aggr_counter/1</a></td><td>Registers a local (unique) aggregated counter.</td></tr><tr><td valign="top"><a href="#add_local_counter-2">add_local_counter/2</a></td><td>Registers a local (non-unique) counter.</td></tr><tr><td valign="top"><a href="#add_local_name-1">add_local_name/1</a></td><td>Registers a local (unique) name.</td></tr><tr><td valign="top"><a href="#add_local_property-2">add_local_property/2</a></td><td>Registers a local (non-unique) property.</td></tr><tr><td valign="top"><a href="#audit_process-1">audit_process/1</a></td><td></td></tr><tr><td valign="top"><a href="#await-1">await/1</a></td><td>Equivalent to <a href="#await-2"><tt>await(Key, infinity)</tt></a>.</td></tr><tr><td valign="top"><a href="#await-2">await/2</a></td><td>Wait for a local name to be registered.</td></tr><tr><td valign="top"><a href="#cancel_wait-2">cancel_wait/2</a></td><td></td></tr><tr><td valign="top"><a href="#default-1">default/1</a></td><td></td></tr><tr><td valign="top"><a href="#first-1">first/1</a></td><td>Behaves as ets:first(Tab) for a given type of registration object.</td></tr><tr><td valign="top"><a href="#get_env-3">get_env/3</a></td><td>Equivalent to <a href="#get_env-4"><tt>get_env(Scope, App, Key, [app_env])</tt></a>.</td></tr><tr><td valign="top"><a href="#get_env-4">get_env/4</a></td><td>Fetch an environment value, potentially cached as a <code>gproc_env</code> property.</td></tr><tr><td valign="top"><a href="#get_set_env-3">get_set_env/3</a></td><td>Equivalent to <a href="#get_set_env-4"><tt>get_set_env(Scope, App, Key, [app_env])</tt></a>.</td></tr><tr><td valign="top"><a href="#get_set_env-4">get_set_env/4</a></td><td>Fetch and cache an environment value, if not already cached.</td></tr><tr><td valign="top"><a href="#get_value-1">get_value/1</a></td><td>Read the value stored with a key registered to the current process.</td></tr><tr><td valign="top"><a href="#give_away-2">give_away/2</a></td><td>Atomically transfers the key <code>From</code> to the process identified by <code>To</code>.</td></tr><tr><td valign="top"><a href="#info-1">info/1</a></td><td>Similar to <code>process_info(Pid)</code> but with additional gproc info.</td></tr><tr><td valign="top"><a href="#info-2">info/2</a></td><td>Similar to process_info(Pid, Item), but with additional gproc info.</td></tr><tr><td valign="top"><a href="#last-1">last/1</a></td><td>Behaves as ets:last(Tab) for a given type of registration object.</td></tr><tr><td valign="top"><a href="#lookup_global_aggr_counter-1">lookup_global_aggr_counter/1</a></td><td>Lookup a global (unique) aggregated counter and returns its value.</td></tr><tr><td valign="top"><a href="#lookup_global_counters-1">lookup_global_counters/1</a></td><td>Look up all global (non-unique) instances of a given Counter.</td></tr><tr><td valign="top"><a href="#lookup_global_name-1">lookup_global_name/1</a></td><td>Lookup a global unique name.</td></tr><tr><td valign="top"><a href="#lookup_global_properties-1">lookup_global_properties/1</a></td><td>Look up all global (non-unique) instances of a given Property.</td></tr><tr><td valign="top"><a href="#lookup_local_aggr_counter-1">lookup_local_aggr_counter/1</a></td><td>Lookup a local (unique) aggregated counter and returns its value.</td></tr><tr><td valign="top"><a href="#lookup_local_counters-1">lookup_local_counters/1</a></td><td>Look up all local (non-unique) instances of a given Counter.</td></tr><tr><td valign="top"><a href="#lookup_local_name-1">lookup_local_name/1</a></td><td>Lookup a local unique name.</td></tr><tr><td valign="top"><a href="#lookup_local_properties-1">lookup_local_properties/1</a></td><td>Look up all local (non-unique) instances of a given Property.</td></tr><tr><td valign="top"><a href="#lookup_pid-1">lookup_pid/1</a></td><td>Lookup the Pid stored with a key.</td></tr><tr><td valign="top"><a href="#lookup_pids-1">lookup_pids/1</a></td><td>Returns a list of pids with the published key Key.</td></tr><tr><td valign="top"><a href="#lookup_value-1">lookup_value/1</a></td><td>Lookup the value stored with a key.</td></tr><tr><td valign="top"><a href="#lookup_values-1">lookup_values/1</a></td><td>Retrieve the <code>{Pid,Value}</code> pairs corresponding to Key.</td></tr><tr><td valign="top"><a href="#mreg-3">mreg/3</a></td><td>Register multiple {Key,Value} pairs of a given type and scope.</td></tr><tr><td valign="top"><a href="#nb_wait-1">nb_wait/1</a></td><td>Wait for a local name to be registered.</td></tr><tr><td valign="top"><a href="#next-2">next/2</a></td><td>Behaves as ets:next(Tab,Key) for a given type of registration object.</td></tr><tr><td valign="top"><a href="#prev-2">prev/2</a></td><td>Behaves as ets:prev(Tab,Key) for a given type of registration object.</td></tr><tr><td valign="top"><a href="#reg-1">reg/1</a></td><td>Equivalent to <a href="#reg-2"><tt>reg(Key, default(Key))</tt></a>.</td></tr><tr><td valign="top"><a href="#reg-2">reg/2</a></td><td>Register a name or property for the current process.</td></tr><tr><td valign="top"><a href="#select-1">select/1</a></td><td>Equivalent to <a href="#select-2"><tt>select(all, Pat)</tt></a>.</td></tr><tr><td valign="top"><a href="#select-2">select/2</a></td><td>Perform a select operation on the process registry.</td></tr><tr><td valign="top"><a href="#select-3">select/3</a></td><td>Like <a href="#select-2"><code>select/2</code></a> but returns Limit objects at a time.</td></tr><tr><td valign="top"><a href="#send-2">send/2</a></td><td>Sends a message to the process, or processes, corresponding to Key.</td></tr><tr><td valign="top"><a href="#set_env-5">set_env/5</a></td><td>Updates the cached value as well as underlying environment.</td></tr><tr><td valign="top"><a href="#set_value-2">set_value/2</a></td><td>Sets the value of the registeration entry given by Key.</td></tr><tr><td valign="top"><a href="#start_link-0">start_link/0</a></td><td>Starts the gproc server.</td></tr><tr><td valign="top"><a href="#table-1">table/1</a></td><td>Equivalent to <a href="#table-2"><tt>table(Context, [])</tt></a>.</td></tr><tr><td valign="top"><a href="#table-2">table/2</a></td><td>QLC table generator for the gproc registry.</td></tr><tr><td valign="top"><a href="#unreg-1">unreg/1</a></td><td>Unregister a name or property.</td></tr><tr><td valign="top"><a href="#unregister_name-1">unregister_name/1</a></td><td>Equivalent to <tt>unreg / 1</tt>.</td></tr><tr><td valign="top"><a href="#update_counter-2">update_counter/2</a></td><td>Updates the counter registered as Key for the current process.</td></tr><tr><td valign="top"><a href="#where-1">where/1</a></td><td>Returns the pid registered as Key.</td></tr><tr><td valign="top"><a href="#whereis_name-1">whereis_name/1</a></td><td>Equivalent to <tt>where / 1</tt>.</td></tr></table>
  166
+<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#add_global_aggr_counter-1">add_global_aggr_counter/1</a></td><td>Registers a global (unique) aggregated counter.</td></tr><tr><td valign="top"><a href="#add_global_counter-2">add_global_counter/2</a></td><td>Registers a global (non-unique) counter.</td></tr><tr><td valign="top"><a href="#add_global_name-1">add_global_name/1</a></td><td>Registers a global (unique) name.</td></tr><tr><td valign="top"><a href="#add_global_property-2">add_global_property/2</a></td><td>Registers a global (non-unique) property.</td></tr><tr><td valign="top"><a href="#add_local_aggr_counter-1">add_local_aggr_counter/1</a></td><td>Registers a local (unique) aggregated counter.</td></tr><tr><td valign="top"><a href="#add_local_counter-2">add_local_counter/2</a></td><td>Registers a local (non-unique) counter.</td></tr><tr><td valign="top"><a href="#add_local_name-1">add_local_name/1</a></td><td>Registers a local (unique) name.</td></tr><tr><td valign="top"><a href="#add_local_property-2">add_local_property/2</a></td><td>Registers a local (non-unique) property.</td></tr><tr><td valign="top"><a href="#audit_process-1">audit_process/1</a></td><td></td></tr><tr><td valign="top"><a href="#await-1">await/1</a></td><td>Equivalent to <a href="#await-2"><tt>await(Key, infinity)</tt></a>.</td></tr><tr><td valign="top"><a href="#await-2">await/2</a></td><td>Wait for a local name to be registered.</td></tr><tr><td valign="top"><a href="#cancel_wait-2">cancel_wait/2</a></td><td></td></tr><tr><td valign="top"><a href="#default-1">default/1</a></td><td></td></tr><tr><td valign="top"><a href="#first-1">first/1</a></td><td>Behaves as ets:first(Tab) for a given type of registration object.</td></tr><tr><td valign="top"><a href="#get_env-3">get_env/3</a></td><td>Equivalent to <a href="#get_env-4"><tt>get_env(Scope, App, Key, [app_env])</tt></a>.</td></tr><tr><td valign="top"><a href="#get_env-4">get_env/4</a></td><td>Fetch an environment value, potentially cached as a <code>gproc_env</code> property.</td></tr><tr><td valign="top"><a href="#get_set_env-3">get_set_env/3</a></td><td>Equivalent to <a href="#get_set_env-4"><tt>get_set_env(Scope, App, Key, [app_env])</tt></a>.</td></tr><tr><td valign="top"><a href="#get_set_env-4">get_set_env/4</a></td><td>Fetch and cache an environment value, if not already cached.</td></tr><tr><td valign="top"><a href="#get_value-1">get_value/1</a></td><td>Read the value stored with a key registered to the current process.</td></tr><tr><td valign="top"><a href="#give_away-2">give_away/2</a></td><td>Atomically transfers the key <code>From</code> to the process identified by <code>To</code>.</td></tr><tr><td valign="top"><a href="#info-1">info/1</a></td><td>Similar to <code>process_info(Pid)</code> but with additional gproc info.</td></tr><tr><td valign="top"><a href="#info-2">info/2</a></td><td>Similar to process_info(Pid, Item), but with additional gproc info.</td></tr><tr><td valign="top"><a href="#last-1">last/1</a></td><td>Behaves as ets:last(Tab) for a given type of registration object.</td></tr><tr><td valign="top"><a href="#lookup_global_aggr_counter-1">lookup_global_aggr_counter/1</a></td><td>Lookup a global (unique) aggregated counter and returns its value.</td></tr><tr><td valign="top"><a href="#lookup_global_counters-1">lookup_global_counters/1</a></td><td>Look up all global (non-unique) instances of a given Counter.</td></tr><tr><td valign="top"><a href="#lookup_global_name-1">lookup_global_name/1</a></td><td>Lookup a global unique name.</td></tr><tr><td valign="top"><a href="#lookup_global_properties-1">lookup_global_properties/1</a></td><td>Look up all global (non-unique) instances of a given Property.</td></tr><tr><td valign="top"><a href="#lookup_local_aggr_counter-1">lookup_local_aggr_counter/1</a></td><td>Lookup a local (unique) aggregated counter and returns its value.</td></tr><tr><td valign="top"><a href="#lookup_local_counters-1">lookup_local_counters/1</a></td><td>Look up all local (non-unique) instances of a given Counter.</td></tr><tr><td valign="top"><a href="#lookup_local_name-1">lookup_local_name/1</a></td><td>Lookup a local unique name.</td></tr><tr><td valign="top"><a href="#lookup_local_properties-1">lookup_local_properties/1</a></td><td>Look up all local (non-unique) instances of a given Property.</td></tr><tr><td valign="top"><a href="#lookup_pid-1">lookup_pid/1</a></td><td>Lookup the Pid stored with a key.</td></tr><tr><td valign="top"><a href="#lookup_pids-1">lookup_pids/1</a></td><td>Returns a list of pids with the published key Key.</td></tr><tr><td valign="top"><a href="#lookup_value-1">lookup_value/1</a></td><td>Lookup the value stored with a key.</td></tr><tr><td valign="top"><a href="#lookup_values-1">lookup_values/1</a></td><td>Retrieve the <code>{Pid,Value}</code> pairs corresponding to Key.</td></tr><tr><td valign="top"><a href="#mreg-3">mreg/3</a></td><td>Register multiple {Key,Value} pairs of a given type and scope.</td></tr><tr><td valign="top"><a href="#munreg-3">munreg/3</a></td><td>Unregister multiple Key items of a given type and scope.</td></tr><tr><td valign="top"><a href="#nb_wait-1">nb_wait/1</a></td><td>Wait for a local name to be registered.</td></tr><tr><td valign="top"><a href="#next-2">next/2</a></td><td>Behaves as ets:next(Tab,Key) for a given type of registration object.</td></tr><tr><td valign="top"><a href="#prev-2">prev/2</a></td><td>Behaves as ets:prev(Tab,Key) for a given type of registration object.</td></tr><tr><td valign="top"><a href="#reg-1">reg/1</a></td><td>Equivalent to <a href="#reg-2"><tt>reg(Key, default(Key))</tt></a>.</td></tr><tr><td valign="top"><a href="#reg-2">reg/2</a></td><td>Register a name or property for the current process.</td></tr><tr><td valign="top"><a href="#select-1">select/1</a></td><td>Equivalent to <a href="#select-2"><tt>select(all, Pat)</tt></a>.</td></tr><tr><td valign="top"><a href="#select-2">select/2</a></td><td>Perform a select operation on the process registry.</td></tr><tr><td valign="top"><a href="#select-3">select/3</a></td><td>Like <a href="#select-2"><code>select/2</code></a> but returns Limit objects at a time.</td></tr><tr><td valign="top"><a href="#send-2">send/2</a></td><td>Sends a message to the process, or processes, corresponding to Key.</td></tr><tr><td valign="top"><a href="#set_env-5">set_env/5</a></td><td>Updates the cached value as well as underlying environment.</td></tr><tr><td valign="top"><a href="#set_value-2">set_value/2</a></td><td>Sets the value of the registeration entry given by Key.</td></tr><tr><td valign="top"><a href="#start_link-0">start_link/0</a></td><td>Starts the gproc server.</td></tr><tr><td valign="top"><a href="#table-1">table/1</a></td><td>Equivalent to <a href="#table-2"><tt>table(Context, [])</tt></a>.</td></tr><tr><td valign="top"><a href="#table-2">table/2</a></td><td>QLC table generator for the gproc registry.</td></tr><tr><td valign="top"><a href="#unreg-1">unreg/1</a></td><td>Unregister a name or property.</td></tr><tr><td valign="top"><a href="#unregister_name-1">unregister_name/1</a></td><td>Equivalent to <tt>unreg / 1</tt>.</td></tr><tr><td valign="top"><a href="#update_counter-2">update_counter/2</a></td><td>Updates the counter registered as Key for the current process.</td></tr><tr><td valign="top"><a href="#where-1">where/1</a></td><td>Returns the pid registered as Key.</td></tr><tr><td valign="top"><a href="#whereis_name-1">whereis_name/1</a></td><td>Equivalent to <tt>where / 1</tt>.</td></tr></table>
167 167
 
168 168
 
169 169
 
@@ -800,7 +800,28 @@ object, the return value can be a list of any length.<a name="mreg-3"></a>
800 800
 
801 801
 Register multiple {Key,Value} pairs of a given type and scope.
802 802
 
803  
-This function is more efficient than calling [`reg/2`](#reg-2) repeatedly.<a name="nb_wait-1"></a>
  803
+This function is more efficient than calling [`reg/2`](#reg-2) repeatedly.
  804
+It is also atomic in regard to unique names; either all names are registered
  805
+or none are.<a name="munreg-3"></a>
  806
+
  807
+<h3>munreg/3</h3>
  808
+
  809
+
  810
+
  811
+
  812
+
  813
+<pre>munreg(T::<a href="#type-type">type()</a>, X2::<a href="#type-scope">scope()</a>, L::[Key::any()]) -> true</pre>
  814
+<br></br>
  815
+
  816
+
  817
+
  818
+
  819
+
  820
+
  821
+Unregister multiple Key items of a given type and scope.
  822
+
  823
+This function is usually more efficient than calling [`unreg/1`](#unreg-1)
  824
+repeatedly.<a name="nb_wait-1"></a>
804 825
 
805 826
 <h3>nb_wait/1</h3>
806 827
 
12  doc/gproc_dist.md
Source Rendered
@@ -30,7 +30,7 @@ For a detailed description, see gproc/doc/erlang07-wiger.pdf.
30 30
 
31 31
 
32 32
 
33  
-<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#code_change-4">code_change/4</a></td><td></td></tr><tr><td valign="top"><a href="#elected-2">elected/2</a></td><td></td></tr><tr><td valign="top"><a href="#elected-3">elected/3</a></td><td></td></tr><tr><td valign="top"><a href="#from_leader-3">from_leader/3</a></td><td></td></tr><tr><td valign="top"><a href="#get_leader-0">get_leader/0</a></td><td>Returns the node of the current gproc leader.</td></tr><tr><td valign="top"><a href="#give_away-2">give_away/2</a></td><td></td></tr><tr><td valign="top"><a href="#handle_DOWN-3">handle_DOWN/3</a></td><td></td></tr><tr><td valign="top"><a href="#handle_call-4">handle_call/4</a></td><td></td></tr><tr><td valign="top"><a href="#handle_cast-3">handle_cast/3</a></td><td></td></tr><tr><td valign="top"><a href="#handle_info-2">handle_info/2</a></td><td></td></tr><tr><td valign="top"><a href="#handle_leader_call-4">handle_leader_call/4</a></td><td></td></tr><tr><td valign="top"><a href="#handle_leader_cast-3">handle_leader_cast/3</a></td><td></td></tr><tr><td valign="top"><a href="#init-1">init/1</a></td><td></td></tr><tr><td valign="top"><a href="#leader_call-1">leader_call/1</a></td><td></td></tr><tr><td valign="top"><a href="#leader_cast-1">leader_cast/1</a></td><td></td></tr><tr><td valign="top"><a href="#mreg-2">mreg/2</a></td><td></td></tr><tr><td valign="top"><a href="#reg-1">reg/1</a></td><td></td></tr><tr><td valign="top"><a href="#reg-2">reg/2</a></td><td>
  33
+<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#code_change-4">code_change/4</a></td><td></td></tr><tr><td valign="top"><a href="#elected-2">elected/2</a></td><td></td></tr><tr><td valign="top"><a href="#elected-3">elected/3</a></td><td></td></tr><tr><td valign="top"><a href="#from_leader-3">from_leader/3</a></td><td></td></tr><tr><td valign="top"><a href="#get_leader-0">get_leader/0</a></td><td>Returns the node of the current gproc leader.</td></tr><tr><td valign="top"><a href="#give_away-2">give_away/2</a></td><td></td></tr><tr><td valign="top"><a href="#handle_DOWN-3">handle_DOWN/3</a></td><td></td></tr><tr><td valign="top"><a href="#handle_call-4">handle_call/4</a></td><td></td></tr><tr><td valign="top"><a href="#handle_cast-3">handle_cast/3</a></td><td></td></tr><tr><td valign="top"><a href="#handle_info-2">handle_info/2</a></td><td></td></tr><tr><td valign="top"><a href="#handle_leader_call-4">handle_leader_call/4</a></td><td></td></tr><tr><td valign="top"><a href="#handle_leader_cast-3">handle_leader_cast/3</a></td><td></td></tr><tr><td valign="top"><a href="#init-1">init/1</a></td><td></td></tr><tr><td valign="top"><a href="#leader_call-1">leader_call/1</a></td><td></td></tr><tr><td valign="top"><a href="#leader_cast-1">leader_cast/1</a></td><td></td></tr><tr><td valign="top"><a href="#mreg-2">mreg/2</a></td><td></td></tr><tr><td valign="top"><a href="#munreg-2">munreg/2</a></td><td></td></tr><tr><td valign="top"><a href="#reg-1">reg/1</a></td><td></td></tr><tr><td valign="top"><a href="#reg-2">reg/2</a></td><td>
34 34
 Class = n  - unique name
35 35
 | p  - non-unique property
36 36
 | c  - counter
@@ -207,6 +207,16 @@ Returns the node of the current gproc leader.<a name="give_away-2"></a>
207 207
 
208 208
 `mreg(T, KVL) -> any()`
209 209
 
  210
+<a name="munreg-2"></a>
  211
+
  212
+<h3>munreg/2</h3>
  213
+
  214
+
  215
+
  216
+
  217
+
  218
+`munreg(T, Keys) -> any()`
  219
+
210 220
 <a name="reg-1"></a>
211 221
 
212 222
 <h3>reg/1</h3>
53  src/gproc.erl
@@ -50,6 +50,7 @@
50 50
 -export([start_link/0,
51 51
          reg/1, reg/2, unreg/1,
52 52
          mreg/3,
  53
+	 munreg/3,
53 54
          set_value/2,
54 55
          get_value/1,
55 56
          where/1,
@@ -653,6 +654,8 @@ reg(_, _) ->
653 654
 %% @doc Register multiple {Key,Value} pairs of a given type and scope.
654 655
 %% 
655 656
 %% This function is more efficient than calling {@link reg/2} repeatedly.
  657
+%% It is also atomic in regard to unique names; either all names are registered
  658
+%% or none are.
656 659
 %% @end
657 660
 mreg(T, g, KVL) ->
658 661
     ?CHK_DIST,
@@ -668,6 +671,40 @@ mreg(p, l, KVL) ->
668 671
 mreg(_, _, _) ->
669 672
     erlang:error(badarg).
670 673
 
  674
+%% @spec munreg(type(), scope(), [Key::any()]) -> true
  675
+%%
  676
+%% @doc Unregister multiple Key items of a given type and scope.
  677
+%% 
  678
+%% This function is usually more efficient than calling {@link unreg/1}
  679
+%% repeatedly.
  680
+%% @end
  681
+munreg(T, g, L) ->
  682
+    ?CHK_DIST,
  683
+    gproc_dist:munreg(T, existing(T,g,L));
  684
+munreg(T, l, L) when T==a; T==n ->
  685
+    if is_list(L) ->
  686
+            call({munreg, T, l, existing(T,l,L)});
  687
+       true ->
  688
+            erlang:error(badarg)
  689
+    end;
  690
+munreg(p, l, L) ->
  691
+    local_munreg(p, existing(p,l,L));
  692
+munreg(_, _, _) ->
  693
+    erlang:error(badarg).
  694
+
  695
+existing(T,Scope,L) ->
  696
+    Keys = if T==p; T==c ->
  697
+		   [{{T,Scope,K}, self()} || K <- L];
  698
+	      T==a; T==n ->
  699
+		   [{{T,Scope,K}, T} || K <- L]
  700
+	   end,
  701
+    _ = [case ets:member(?TAB, K) of
  702
+	     false -> erlang:error(badarg);
  703
+	     true  -> true
  704
+	 end || K <- Keys],
  705
+    L.
  706
+
  707
+
671 708
 %% @spec (Key:: key()) -> true
672 709
 %%
673 710
 %% @doc Unregister a name or property.
@@ -682,7 +719,8 @@ unreg(Key) ->
682 719
         {_, l, _} ->
683 720
             case ets:member(?TAB, {Key,self()}) of
684 721
                 true ->
685  
-                    gproc_lib:remove_reg(Key, self());
  722
+                    _ = gproc_lib:remove_reg(Key, self()),
  723
+		    true;
686 724
                 false ->
687 725
                     erlang:error(badarg)
688 726
             end
@@ -735,6 +773,10 @@ local_mreg(T, [_|_] = KVL) ->
735 773
         {true,_}  -> monitor_me()
736 774
     end.
737 775
 
  776
+local_munreg(T, L) when T==p; T==c ->
  777
+    _ = [gproc_lib:remove_reg({T,l,K}) || K <- L],
  778
+    true.
  779
+
738 780
 %% @spec (Key :: key(), Value) -> true
739 781
 %% @doc Sets the value of the registeration entry given by Key
740 782
 %% 
@@ -1115,7 +1157,7 @@ handle_call({reg, {_T,l,_} = Key, Val}, {Pid,_}, S) ->
1115 1157
 handle_call({unreg, {_,l,_} = Key}, {Pid,_}, S) ->
1116 1158
     case ets:member(?TAB, {Pid,Key}) of
1117 1159
         true ->
1118  
-            gproc_lib:remove_reg(Key, Pid),
  1160
+            _ = gproc_lib:remove_reg(Key, Pid),
1119 1161
             {reply, true, S};
1120 1162
         false ->
1121 1163
             {reply, badarg, S}
@@ -1137,6 +1179,9 @@ handle_call({mreg, T, l, L}, {Pid,_}, S) ->
1137 1179
     catch
1138 1180
         error:_  -> {reply, badarg, S}
1139 1181
     end;
  1182
+handle_call({munreg, T, l, L}, {Pid,_}, S) ->
  1183
+    _ = gproc_lib:remove_many(T, l, L, Pid),
  1184
+    {reply, true, S};
1140 1185
 handle_call({set, {_,l,_} = Key, Value}, {Pid,_}, S) ->
1141 1186
     case gproc_lib:do_set_value(Key, Value, Pid) of
1142 1187
         true ->
@@ -1293,7 +1338,7 @@ do_give_away({T,l,_} = K, To, Pid) when T==n; T==a ->
1293 1338
                     gproc_lib:ensure_monitor(ToPid, l),
1294 1339
                     ToPid;
1295 1340
                 undefined ->
1296  
-                    gproc_lib:remove_reg(K, Pid),
  1341
+                    _ = gproc_lib:remove_reg(K, Pid),
1297 1342
                     undefined
1298 1343
             end;
1299 1344
         _ ->
@@ -1318,7 +1363,7 @@ do_give_away({T,l,_} = K, To, Pid) when T==c; T==p ->
1318 1363
                             ToPid
1319 1364
                     end;
1320 1365
                 undefined ->
1321  
-                    gproc_lib:remove_reg(K, Pid),
  1366
+                    _ = gproc_lib:remove_reg(K, Pid),
1322 1367
                     undefined
1323 1368
             end;
1324 1369
         _ ->
15  src/gproc_dist.erl
@@ -25,6 +25,7 @@
25 25
 -export([start_link/0, start_link/1,
26 26
 	 reg/1, reg/2, unreg/1,
27 27
 	 mreg/2,
  28
+	 munreg/2,
28 29
 	 set_value/2,
29 30
 	 give_away/2,
30 31
 	 update_counter/2]).
@@ -98,6 +99,11 @@ mreg(T, KVL) ->
98 99
        true -> erlang:error(badarg)
99 100
     end.
100 101
 
  102
+munreg(T, Keys) ->
  103
+    if is_list(Keys) -> leader_call({munreg, T, g, Keys, self()});
  104
+       true -> erlang:error(badarg)
  105
+    end.
  106
+	     
101 107
 
102 108
 unreg({_,g,_} = Key) ->
103 109
     leader_call({unreg, Key, self()});
@@ -313,6 +319,15 @@ handle_leader_call({mreg, T, g, L, Pid}, _From, S, _E) ->
313 319
 	    end;
314 320
        true -> {reply, badarg, S}
315 321
     end;
  322
+handle_leader_call({munreg, T, g, L, Pid}, _From, S, _E) ->
  323
+    try gproc_lib:remove_many(T, g, L, Pid) of
  324
+	[] ->
  325
+	    {reply, true, S};
  326
+	Objs ->
  327
+	    {reply, true, [{delete, Objs}], S}
  328
+    catch
  329
+	error:_ -> {reply, badarg, S}
  330
+    end;
316 331
 handle_leader_call({set,{T,g,N} =K,V,Pid}, _From, S, _E) ->
317 332
     if T == a ->
318 333
 	    if is_integer(V) ->
35  src/gproc_lib.erl
@@ -192,17 +192,28 @@ ensure_monitor(Pid, Scope) when Scope==g; Scope==l ->
192 192
     end.
193 193
 
194 194
 remove_reg(Key, Pid) ->
195  
-    remove_reg_1(Key, Pid),
196  
-    ets:delete(?TAB, {Pid,Key}).
  195
+    Reg = remove_reg_1(Key, Pid),
  196
+    ets:delete(?TAB, Rev = {Pid,Key}),
  197
+    [Reg, Rev].
  198
+
  199
+remove_many(T, Scope, L, Pid) ->
  200
+    lists:flatmap(fun(K) ->
  201
+			  Key = {T, Scope, K},
  202
+			  remove_reg(Key, Pid)
  203
+		  end, L).
197 204
 
198 205
 remove_reg_1({c,_,_} = Key, Pid) ->
199  
-    remove_counter_1(Key, ets:lookup_element(?TAB, {Key,Pid}, 3), Pid);
  206
+    remove_counter_1(Key, ets:lookup_element(?TAB, Reg = {Key,Pid}, 3), Pid),
  207
+    Reg;
200 208
 remove_reg_1({a,_,_} = Key, _Pid) ->
201  
-    ets:delete(?TAB, {Key,a});
  209
+    ets:delete(?TAB, Reg = {Key,a}),
  210
+    Reg;
202 211
 remove_reg_1({n,_,_} = Key, _Pid) ->
203  
-    ets:delete(?TAB, {Key,n});
  212
+    ets:delete(?TAB, Reg = {Key,n}),
  213
+    Reg;
204 214
 remove_reg_1({_,_,_} = Key, Pid) ->
205  
-    ets:delete(?TAB, {Key, Pid}).
  215
+    ets:delete(?TAB, Reg = {Key, Pid}),
  216
+    Reg.
206 217
 
207 218
 remove_counter_1({c,C,N} = Key, Val, Pid) ->
208 219
     Res = ets:delete(?TAB, {Key, Pid}),
@@ -236,18 +247,6 @@ update_counter({c,l,Ctr} = Key, Incr, Pid) ->
236 247
 update_aggr_counter(C, N, Val) ->
237 248
     catch ets:update_counter(?TAB, {{a,C,N},a}, {3, Val}).
238 249
 
239  
-%% cleanup_counter({c,g,N}=K, Pid, Acc) ->
240  
-%%     remove_reg(K,Pid),
241  
-%%     case ets:lookup(?TAB, {{a,g,N},a}) of
242  
-%%         [Aggr] ->
243  
-%%             [Aggr|Acc];
244  
-%%         [] ->
245  
-%%             Acc
246  
-%%     end;
247  
-%% cleanup_counter(K, Pid, Acc) ->
248  
-%%     remove_reg(K,Pid),
249  
-%%     Acc.
250  
-
251 250
 scan_existing_counters(Ctxt, Name) ->
252 251
     Head = {{{c,Ctxt,Name},'_'},'_','$1'},
253 252
     Cs = ets:select(?TAB, [{Head, [], ['$1']}]),
11  test/gproc_dist_tests.erl
@@ -81,9 +81,14 @@ t_simple_reg([H|_] = Ns) ->
81 81
     ?assertMatch(ok, t_lookup_everywhere(Name, Ns, undefined)),
82 82
     ?assertMatch(ok, t_call(P, die)).
83 83
 
84  
-t_mreg([H|_]) ->
  84
+t_mreg([H|_] = Ns) ->
85 85
     Kvl = ?T_KVL,
  86
+    Keys = [K || {K,_} <- Kvl],
86 87
     P = t_spawn_mreg(H, Kvl),
  88
+    [?assertMatch(ok, t_lookup_everywhere({n,g,K}, Ns, P)) || K <- Keys],
  89
+    ?assertMatch(true, t_call(P, {apply, gproc, munreg, [n, g, Keys]})),
  90
+    timer:sleep(1000),
  91
+    [?assertMatch(ok, t_lookup_everywhere({n,g,K},Ns,undefined)) || K <- Keys],
87 92
     ?assertMatch(ok, t_call(P, die)).
88 93
 
89 94
 t_await_reg([A,B|_]) ->
@@ -143,7 +148,7 @@ t_sync(Ns) ->
143 148
 %% Verify that the gproc_dist:sync() call returns true even if a candidate dies
144 149
 %% while the sync is underway. This test makes use of sys:suspend() to ensure that
145 150
 %% the other candidate doesn't respond too quickly.
146  
-t_sync_cand_dies([A,B|_] = Ns) ->
  151
+t_sync_cand_dies([A,B|_]) ->
147 152
     Leader = rpc:call(A, gproc_dist, get_leader, []),
148 153
     Other = case Leader of 
149 154
 		A -> B;
@@ -220,7 +225,7 @@ t_spawn_reg(Node, Name) ->
220 225
 t_spawn_mreg(Node, KVL) ->
221 226
     Me = self(),
222 227
     spawn(Node, fun() ->
223  
-			?assertMatch(true, gproc:mreg(p, g, KVL)),
  228
+			?assertMatch(true, gproc:mreg(n, g, KVL)),
224 229
 			Me ! {self(), ok},
225 230
 			t_loop()
226 231
 		end),
5  test/gproc_tests.erl
@@ -116,8 +116,9 @@ t_simple_mreg() ->
116 116
     ?assertEqual(true, gproc:mreg(n, l, [{foo, foo_val},
117 117
 					 {bar, bar_val}])),
118 118
     ?assertEqual(P, gproc:where({n,l,foo})),
119  
-    ?assertEqual(P, gproc:where({n,l,bar})).
120  
-    
  119
+    ?assertEqual(P, gproc:where({n,l,bar})),
  120
+    ?assertEqual(true, gproc:munreg(n, l, [foo, bar])).
  121
+
121 122
 
122 123
 t_gproc_crash() ->
123 124
     P = spawn_helper(),

0 notes on commit 75f0298

Please sign in to comment.
Something went wrong with that request. Please try again.