Browse Source

added surrender/2

Ulf Wiger 14 years ago
parent
commit
4ffd1faec8
8 changed files with 465 additions and 300 deletions
  1. 309 200
      doc/gproc.md
  2. 2 8
      doc/gproc_app.md
  3. 13 49
      doc/gproc_dist.md
  4. 2 6
      doc/gproc_init.md
  5. 1 1
      doc/gproc_lib.md
  6. 3 7
      doc/gproc_sup.md
  7. 84 18
      src/gproc.erl
  8. 51 11
      src/gproc_dist.erl

+ 309 - 200
doc/gproc.md

@@ -29,69 +29,98 @@ For a detailed description, see
 [erlang07-wiger.pdf](erlang07-wiger.pdf).
 [erlang07-wiger.pdf](erlang07-wiger.pdf).
 
 
 
 
+
 <h2><a name="types">Data Types</a></h2>
 <h2><a name="types">Data Types</a></h2>
 
 
 
 
-<a name="type-context"></a>
 
 
 
 
-<h3 class="typedecl">context()</h3>
 
 
-<tt>context() = {<a href="#type-scope">scope()</a>, <a href="#type-type">type()</a>} | <a href="#type-type">type()</a></tt>
+<h3 class="typedecl"><a name="type-context">context()</a></h3>
+
+
+
+
+`context() = {[scope()](#type-scope), [type()](#type-type)} | [type()](#type-type)`
+
 
 
 Local scope is the default
 Local scope is the default
-<a name="type-headpat"></a>
 
 
 
 
-<h3 class="typedecl">headpat()</h3>
+<h3 class="typedecl"><a name="type-headpat">headpat()</a></h3>
+
+
+
+
+`headpat() = {[keypat()](#type-keypat), [pidpat()](#type-pidpat), ValPat}`
+
+
+
+<h3 class="typedecl"><a name="type-key">key()</a></h3>
+
 
 
-<tt>headpat() = {<a href="#type-keypat">keypat()</a>, <a href="#type-pidpat">pidpat()</a>, ValPat}</tt>
-<a name="type-key"></a>
 
 
 
 
-<h3 class="typedecl">key()</h3>
+`key() = {[type()](#type-type), [scope()](#type-scope), any()}`
 
 
-<tt>key() = {<a href="#type-type">type()</a>, <a href="#type-scope">scope()</a>, any()}</tt>
-<a name="type-keypat"></a>
 
 
 
 
-<h3 class="typedecl">keypat()</h3>
+<h3 class="typedecl"><a name="type-keypat">keypat()</a></h3>
 
 
-<tt>keypat() = {<a href="#type-sel_type">sel_type()</a> | <a href="#type-sel_var">sel_var()</a>, l | g | <a href="#type-sel_var">sel_var()</a>, any()}</tt>
-<a name="type-pidpat"></a>
 
 
 
 
-<h3 class="typedecl">pidpat()</h3>
 
 
-<tt>pidpat() = pid() | <a href="#type-sel_var">sel_var()</a></tt>
+`keypat() = {[sel_type()](#type-sel_type) | [sel_var()](#type-sel_var), l | g | [sel_var()](#type-sel_var), any()}`
+
+
+
+<h3 class="typedecl"><a name="type-pidpat">pidpat()</a></h3>
+
+
+
+
+`pidpat() = pid() | [sel_var()](#type-sel_var)`
+
 
 
 sel_var() = DollarVar | '_'.
 sel_var() = DollarVar | '_'.
-<a name="type-scope"></a>
 
 
 
 
-<h3 class="typedecl">scope()</h3>
+<h3 class="typedecl"><a name="type-scope">scope()</a></h3>
+
+
+
+
+`scope() = l | g`
 
 
-<tt>scope() = l | g</tt>
 
 
 l = local registration; g = global registration
 l = local registration; g = global registration
-<a name="type-sel_pattern"></a>
 
 
 
 
-<h3 class="typedecl">sel_pattern()</h3>
+<h3 class="typedecl"><a name="type-sel_pattern">sel_pattern()</a></h3>
+
 
 
-<tt>sel_pattern() = [{<a href="#type-headpat">headpat()</a>, Guards, Prod}]</tt>
-<a name="type-sel_type"></a>
 
 
 
 
-<h3 class="typedecl">sel_type()</h3>
+`sel_pattern() = [{[headpat()](#type-headpat), Guards, Prod}]`
 
 
-<tt>sel_type() = n | p | c | a | names | props | counters | aggr_counters</tt>
-<a name="type-type"></a>
 
 
 
 
-<h3 class="typedecl">type()</h3>
+<h3 class="typedecl"><a name="type-sel_type">sel_type()</a></h3>
+
+
+
+
+`sel_type() = n | p | c | a | names | props | counters | aggr_counters`
+
+
+
+<h3 class="typedecl"><a name="type-type">type()</a></h3>
+
+
+
+
+`type() = n | p | c | a`
 
 
-<tt>type() = n | p | c | a</tt>
 
 
 n = name; p = property; c = counter;
 n = name; p = property; c = counter;
 a = aggregate_counter
 a = aggregate_counter
@@ -100,18 +129,16 @@ a = aggregate_counter
 
 
 
 
 
 
-<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_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="#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_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>
+<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_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="#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_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="#surrender-2">surrender/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="#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>
 
 
 
 
-<a name="functions"></a>
 
 
 
 
-<h2>Function Details</h2>
+<h2><a name="functions">Function Details</a></h2>
 
 
 
 
 <a name="add_global_aggr_counter-1"></a>
 <a name="add_global_aggr_counter-1"></a>
 
 
-
 <h3>add_global_aggr_counter/1</h3>
 <h3>add_global_aggr_counter/1</h3>
 
 
 
 
@@ -124,9 +151,7 @@ a = aggregate_counter
 
 
 Equivalent to [`reg({a, g, Name})`](#reg-1).
 Equivalent to [`reg({a, g, Name})`](#reg-1).
 
 
-Registers a global (unique) aggregated counter.
-<a name="add_global_counter-2"></a>
-
+Registers a global (unique) aggregated counter.<a name="add_global_counter-2"></a>
 
 
 <h3>add_global_counter/2</h3>
 <h3>add_global_counter/2</h3>
 
 
@@ -138,9 +163,7 @@ Registers a global (unique) aggregated counter.
 
 
 
 
 
 
-Registers a global (non-unique) counter. @equiv reg({c,g,Name},Value)
-<a name="add_global_name-1"></a>
-
+Registers a global (non-unique) counter. @equiv reg({c,g,Name},Value)<a name="add_global_name-1"></a>
 
 
 <h3>add_global_name/1</h3>
 <h3>add_global_name/1</h3>
 
 
@@ -152,9 +175,7 @@ Registers a global (non-unique) counter. @equiv reg({c,g,Name},Value)
 
 
 
 
 
 
-Registers a global (unique) name. @equiv reg({n,g,Name})
-<a name="add_global_property-2"></a>
-
+Registers a global (unique) name. @equiv reg({n,g,Name})<a name="add_global_property-2"></a>
 
 
 <h3>add_global_property/2</h3>
 <h3>add_global_property/2</h3>
 
 
@@ -166,9 +187,7 @@ Registers a global (unique) name. @equiv reg({n,g,Name})
 
 
 
 
 
 
-Registers a global (non-unique) property. @equiv reg({p,g,Name},Value)
-<a name="add_local_aggr_counter-1"></a>
-
+Registers a global (non-unique) property. @equiv reg({p,g,Name},Value)<a name="add_local_aggr_counter-1"></a>
 
 
 <h3>add_local_aggr_counter/1</h3>
 <h3>add_local_aggr_counter/1</h3>
 
 
@@ -182,9 +201,7 @@ Registers a global (non-unique) property. @equiv reg({p,g,Name},Value)
 
 
 Equivalent to [`reg({a, l, Name})`](#reg-1).
 Equivalent to [`reg({a, l, Name})`](#reg-1).
 
 
-Registers a local (unique) aggregated counter.
-<a name="add_local_counter-2"></a>
-
+Registers a local (unique) aggregated counter.<a name="add_local_counter-2"></a>
 
 
 <h3>add_local_counter/2</h3>
 <h3>add_local_counter/2</h3>
 
 
@@ -196,9 +213,7 @@ Registers a local (unique) aggregated counter.
 
 
 
 
 
 
-Registers a local (non-unique) counter. @equiv reg({c,l,Name},Value)
-<a name="add_local_name-1"></a>
-
+Registers a local (non-unique) counter. @equiv reg({c,l,Name},Value)<a name="add_local_name-1"></a>
 
 
 <h3>add_local_name/1</h3>
 <h3>add_local_name/1</h3>
 
 
@@ -210,9 +225,7 @@ Registers a local (non-unique) counter. @equiv reg({c,l,Name},Value)
 
 
 
 
 
 
-Registers a local (unique) name. @equiv reg({n,l,Name})
-<a name="add_local_property-2"></a>
-
+Registers a local (unique) name. @equiv reg({n,l,Name})<a name="add_local_property-2"></a>
 
 
 <h3>add_local_property/2</h3>
 <h3>add_local_property/2</h3>
 
 
@@ -224,9 +237,7 @@ Registers a local (unique) name. @equiv reg({n,l,Name})
 
 
 
 
 
 
-Registers a local (non-unique) property. @equiv reg({p,l,Name},Value)
-<a name="audit_process-1"></a>
-
+Registers a local (non-unique) property. @equiv reg({p,l,Name},Value)<a name="audit_process-1"></a>
 
 
 <h3>audit_process/1</h3>
 <h3>audit_process/1</h3>
 
 
@@ -236,32 +247,34 @@ Registers a local (non-unique) property. @equiv reg({p,l,Name},Value)
 
 
 `audit_process(Pid) -> any()`
 `audit_process(Pid) -> any()`
 
 
-
 <a name="await-1"></a>
 <a name="await-1"></a>
 
 
-
 <h3>await/1</h3>
 <h3>await/1</h3>
 
 
 
 
 
 
 
 
 
 
-<tt>await(Key::<a href="#type-key">key()</a>) -> {pid(), Value}</tt>
 
 
+<pre>await(Key::<a href="#type-key">key()</a>) -> {pid(), Value}</pre>
+
+<br></br>
 
 
 
 
-Equivalent to [`await(Key, infinity)`](#await-2).
-<a name="await-2"></a>
 
 
 
 
+Equivalent to [`await(Key, infinity)`](#await-2).<a name="await-2"></a>
+
 <h3>await/2</h3>
 <h3>await/2</h3>
 
 
 
 
 
 
 
 
 
 
-<tt>await(Key::<a href="#type-key">key()</a>, Timeout) -> {pid(), Value}</tt>* `Timeout = integer() | infinity`
 
 
+<pre>await(Key::<a href="#type-key">key()</a>, Timeout) -> {pid(), Value}</pre>
+
+<ul class="definitions"><li><tt>Timeout = integer() | infinity</tt></li></ul>
 
 
 
 
 
 
@@ -271,9 +284,7 @@ either an interger > 0 or 'infinity'.
 A small optimization: we first perform a lookup, to see if the name
 A small optimization: we first perform a lookup, to see if the name
 is already registered. This way, the cost of the operation will be
 is already registered. This way, the cost of the operation will be
 roughly the same as of where/1 in the case where the name is already
 roughly the same as of where/1 in the case where the name is already
-registered (the difference: await/2 also returns the value).
-<a name="cancel_wait-2"></a>
-
+registered (the difference: await/2 also returns the value).<a name="cancel_wait-2"></a>
 
 
 <h3>cancel_wait/2</h3>
 <h3>cancel_wait/2</h3>
 
 
@@ -283,10 +294,8 @@ registered (the difference: await/2 also returns the value).
 
 
 `cancel_wait(Key, Ref) -> any()`
 `cancel_wait(Key, Ref) -> any()`
 
 
-
 <a name="default-1"></a>
 <a name="default-1"></a>
 
 
-
 <h3>default/1</h3>
 <h3>default/1</h3>
 
 
 
 
@@ -295,17 +304,19 @@ registered (the difference: await/2 also returns the value).
 
 
 `default(X1) -> any()`
 `default(X1) -> any()`
 
 
-
 <a name="first-1"></a>
 <a name="first-1"></a>
 
 
-
 <h3>first/1</h3>
 <h3>first/1</h3>
 
 
 
 
 
 
 
 
 
 
-<tt>first(Type::<a href="#type-type">type()</a>) -> <a href="#type-key">key()</a> | '$end_of_table'</tt>
+
+<pre>first(Type::<a href="#type-type">type()</a>) -> <a href="#type-key">key()</a> | '$end_of_table'</pre>
+
+<br></br>
+
 
 
 
 
 
 
@@ -314,9 +325,7 @@ registered (the difference: await/2 also returns the value).
 Behaves as ets:first(Tab) for a given type of registration object.
 Behaves as ets:first(Tab) for a given type of registration object.
 
 
 See [`http://www.erlang.org/doc/man/ets.html#first-1`](http://www.erlang.org/doc/man/ets.html#first-1).
 See [`http://www.erlang.org/doc/man/ets.html#first-1`](http://www.erlang.org/doc/man/ets.html#first-1).
-The registry behaves as an ordered_set table.
-<a name="get_value-1"></a>
-
+The registry behaves as an ordered_set table.<a name="get_value-1"></a>
 
 
 <h3>get_value/1</h3>
 <h3>get_value/1</h3>
 
 
@@ -324,17 +333,19 @@ The registry behaves as an ordered_set table.
 
 
 
 
 
 
-<tt>get_value(Key) -> Value</tt>
 
 
+<pre>get_value(Key) -> Value</pre>
+
+<br></br>
 
 
 
 
 
 
 
 
-Read the value stored with a key registered to the current process.
 
 
-If no such key is registered to the current process, this function exits.
-<a name="info-1"></a>
 
 
+Read the value stored with a key registered to the current process.
+
+If no such key is registered to the current process, this function exits.<a name="info-1"></a>
 
 
 <h3>info/1</h3>
 <h3>info/1</h3>
 
 
@@ -342,8 +353,10 @@ If no such key is registered to the current process, this function exits.
 
 
 
 
 
 
-<tt>info(Pid::pid()) -> ProcessInfo</tt>* `ProcessInfo = [{gproc, [{Key, Value}]} | ProcessInfo]`
 
 
+<pre>info(Pid::pid()) -> ProcessInfo</pre>
+
+<ul class="definitions"><li><tt>ProcessInfo = [{gproc, [{Key, Value}]} | ProcessInfo]</tt></li></ul>
 
 
 
 
 
 
@@ -353,9 +366,7 @@ Similar to `process_info(Pid)` but with additional gproc info.
 
 
 Returns the same information as process_info(Pid), but with the
 Returns the same information as process_info(Pid), but with the
 addition of a `gproc` information item, containing the `{Key,Value}`
 addition of a `gproc` information item, containing the `{Key,Value}`
-pairs registered to the process.
-<a name="info-2"></a>
-
+pairs registered to the process.<a name="info-2"></a>
 
 
 <h3>info/2</h3>
 <h3>info/2</h3>
 
 
@@ -363,7 +374,11 @@ pairs registered to the process.
 
 
 
 
 
 
-<tt>info(Pid::pid(), Item::atom()) -> {Item, Info}</tt>
+
+<pre>info(Pid::pid(), Item::atom()) -> {Item, Info}</pre>
+
+<br></br>
+
 
 
 
 
 
 
@@ -373,9 +388,7 @@ Similar to process_info(Pid, Item), but with additional gproc info.
 
 
 For `Item = gproc`, this function returns a list of `{Key, Value}` pairs
 For `Item = gproc`, this function returns a list of `{Key, Value}` pairs
 registered to the process Pid. For other values of Item, it returns the
 registered to the process Pid. For other values of Item, it returns the
-same as [`http://www.erlang.org/doc/man/erlang.html#process_info-2`](http://www.erlang.org/doc/man/erlang.html#process_info-2).
-<a name="last-1"></a>
-
+same as [`http://www.erlang.org/doc/man/erlang.html#process_info-2`](http://www.erlang.org/doc/man/erlang.html#process_info-2).<a name="last-1"></a>
 
 
 <h3>last/1</h3>
 <h3>last/1</h3>
 
 
@@ -383,7 +396,11 @@ same as [`http://www.erlang.org/doc/man/erlang.html#process_info-2`](http://www.
 
 
 
 
 
 
-<tt>last(Context::<a href="#type-context">context()</a>) -> <a href="#type-key">key()</a> | '$end_of_table'</tt>
+
+<pre>last(Context::<a href="#type-context">context()</a>) -> <a href="#type-key">key()</a> | '$end_of_table'</pre>
+
+<br></br>
+
 
 
 
 
 
 
@@ -392,9 +409,7 @@ same as [`http://www.erlang.org/doc/man/erlang.html#process_info-2`](http://www.
 Behaves as ets:last(Tab) for a given type of registration object.
 Behaves as ets:last(Tab) for a given type of registration object.
 
 
 See [`http://www.erlang.org/doc/man/ets.html#last-1`](http://www.erlang.org/doc/man/ets.html#last-1).
 See [`http://www.erlang.org/doc/man/ets.html#last-1`](http://www.erlang.org/doc/man/ets.html#last-1).
-The registry behaves as an ordered_set table.
-<a name="lookup_global_aggr_counter-1"></a>
-
+The registry behaves as an ordered_set table.<a name="lookup_global_aggr_counter-1"></a>
 
 
 <h3>lookup_global_aggr_counter/1</h3>
 <h3>lookup_global_aggr_counter/1</h3>
 
 
@@ -402,16 +417,18 @@ The registry behaves as an ordered_set table.
 
 
 
 
 
 
-<tt>lookup_global_aggr_counter(Name::any()) -> integer()</tt>
+
+<pre>lookup_global_aggr_counter(Name::any()) -> integer()</pre>
+
+<br></br>
+
 
 
 
 
 
 
 Equivalent to [`where({a, g, Name})`](#where-1).
 Equivalent to [`where({a, g, Name})`](#where-1).
 
 
 Lookup a global (unique) aggregated counter and returns its value.
 Lookup a global (unique) aggregated counter and returns its value.
-Fails if there is no such object.
-<a name="lookup_global_counters-1"></a>
-
+Fails if there is no such object.<a name="lookup_global_counters-1"></a>
 
 
 <h3>lookup_global_counters/1</h3>
 <h3>lookup_global_counters/1</h3>
 
 
@@ -419,16 +436,18 @@ Fails if there is no such object.
 
 
 
 
 
 
-<tt>lookup_global_counters(Counter::any()) -> [{pid(), Value::integer()}]</tt>
+
+<pre>lookup_global_counters(Counter::any()) -> [{pid(), Value::integer()}]</pre>
+
+<br></br>
+
 
 
 
 
 
 
 Equivalent to [`lookup_values({c, g, Counter})`](#lookup_values-1).
 Equivalent to [`lookup_values({c, g, Counter})`](#lookup_values-1).
 
 
 Look up all global (non-unique) instances of a given Counter.
 Look up all global (non-unique) instances of a given Counter.
-Returns a list of {Pid, Value} tuples for all matching objects.
-<a name="lookup_global_name-1"></a>
-
+Returns a list of {Pid, Value} tuples for all matching objects.<a name="lookup_global_name-1"></a>
 
 
 <h3>lookup_global_name/1</h3>
 <h3>lookup_global_name/1</h3>
 
 
@@ -436,15 +455,17 @@ Returns a list of {Pid, Value} tuples for all matching objects.
 
 
 
 
 
 
-<tt>lookup_global_name(Name::any()) -> pid()</tt>
 
 
+<pre>lookup_global_name(Name::any()) -> pid()</pre>
+
+<br></br>
 
 
 
 
-Equivalent to [`where({n, g, Name})`](#where-1).
 
 
-Lookup a global unique name. Fails if there is no such name.
-<a name="lookup_global_properties-1"></a>
 
 
+Equivalent to [`where({n, g, Name})`](#where-1).
+
+Lookup a global unique name. Fails if there is no such name.<a name="lookup_global_properties-1"></a>
 
 
 <h3>lookup_global_properties/1</h3>
 <h3>lookup_global_properties/1</h3>
 
 
@@ -452,16 +473,18 @@ Lookup a global unique name. Fails if there is no such name.
 
 
 
 
 
 
-<tt>lookup_global_properties(Property::any()) -> [{pid(), Value}]</tt>
+
+<pre>lookup_global_properties(Property::any()) -> [{pid(), Value}]</pre>
+
+<br></br>
+
 
 
 
 
 
 
 Equivalent to [`lookup_values({p, g, Property})`](#lookup_values-1).
 Equivalent to [`lookup_values({p, g, Property})`](#lookup_values-1).
 
 
 Look up all global (non-unique) instances of a given Property.
 Look up all global (non-unique) instances of a given Property.
-Returns a list of {Pid, Value} tuples for all matching objects.
-<a name="lookup_local_aggr_counter-1"></a>
-
+Returns a list of {Pid, Value} tuples for all matching objects.<a name="lookup_local_aggr_counter-1"></a>
 
 
 <h3>lookup_local_aggr_counter/1</h3>
 <h3>lookup_local_aggr_counter/1</h3>
 
 
@@ -469,16 +492,18 @@ Returns a list of {Pid, Value} tuples for all matching objects.
 
 
 
 
 
 
-<tt>lookup_local_aggr_counter(Name::any()) -> integer()</tt>
+
+<pre>lookup_local_aggr_counter(Name::any()) -> integer()</pre>
+
+<br></br>
+
 
 
 
 
 
 
 Equivalent to [`where({a, l, Name})`](#where-1).
 Equivalent to [`where({a, l, Name})`](#where-1).
 
 
 Lookup a local (unique) aggregated counter and returns its value.
 Lookup a local (unique) aggregated counter and returns its value.
-Fails if there is no such object.
-<a name="lookup_local_counters-1"></a>
-
+Fails if there is no such object.<a name="lookup_local_counters-1"></a>
 
 
 <h3>lookup_local_counters/1</h3>
 <h3>lookup_local_counters/1</h3>
 
 
@@ -486,16 +511,18 @@ Fails if there is no such object.
 
 
 
 
 
 
-<tt>lookup_local_counters(Counter::any()) -> [{pid(), Value::integer()}]</tt>
+
+<pre>lookup_local_counters(Counter::any()) -> [{pid(), Value::integer()}]</pre>
+
+<br></br>
+
 
 
 
 
 
 
 Equivalent to [`lookup_values({c, l, Counter})`](#lookup_values-1).
 Equivalent to [`lookup_values({c, l, Counter})`](#lookup_values-1).
 
 
 Look up all local (non-unique) instances of a given Counter.
 Look up all local (non-unique) instances of a given Counter.
-Returns a list of {Pid, Value} tuples for all matching objects.
-<a name="lookup_local_name-1"></a>
-
+Returns a list of {Pid, Value} tuples for all matching objects.<a name="lookup_local_name-1"></a>
 
 
 <h3>lookup_local_name/1</h3>
 <h3>lookup_local_name/1</h3>
 
 
@@ -503,15 +530,17 @@ Returns a list of {Pid, Value} tuples for all matching objects.
 
 
 
 
 
 
-<tt>lookup_local_name(Name::any()) -> pid()</tt>
+
+<pre>lookup_local_name(Name::any()) -> pid()</pre>
+
+<br></br>
 
 
 
 
 
 
-Equivalent to [`where({n, l, Name})`](#where-1).
 
 
-Lookup a local unique name. Fails if there is no such name.
-<a name="lookup_local_properties-1"></a>
+Equivalent to [`where({n, l, Name})`](#where-1).
 
 
+Lookup a local unique name. Fails if there is no such name.<a name="lookup_local_properties-1"></a>
 
 
 <h3>lookup_local_properties/1</h3>
 <h3>lookup_local_properties/1</h3>
 
 
@@ -519,16 +548,18 @@ Lookup a local unique name. Fails if there is no such name.
 
 
 
 
 
 
-<tt>lookup_local_properties(Property::any()) -> [{pid(), Value}]</tt>
+
+<pre>lookup_local_properties(Property::any()) -> [{pid(), Value}]</pre>
+
+<br></br>
+
 
 
 
 
 
 
 Equivalent to [`lookup_values({p, l, Property})`](#lookup_values-1).
 Equivalent to [`lookup_values({p, l, Property})`](#lookup_values-1).
 
 
 Look up all local (non-unique) instances of a given Property.
 Look up all local (non-unique) instances of a given Property.
-Returns a list of {Pid, Value} tuples for all matching objects.
-<a name="lookup_pid-1"></a>
-
+Returns a list of {Pid, Value} tuples for all matching objects.<a name="lookup_pid-1"></a>
 
 
 <h3>lookup_pid/1</h3>
 <h3>lookup_pid/1</h3>
 
 
@@ -536,22 +567,28 @@ Returns a list of {Pid, Value} tuples for all matching objects.
 
 
 
 
 
 
-<tt>lookup_pid(Key) -> Pid</tt>
 
 
+<pre>lookup_pid(Key) -> Pid</pre>
 
 
+<br></br>
 
 
-Lookup the Pid stored with a key.
 
 
-<a name="lookup_pids-1"></a>
 
 
 
 
+Lookup the Pid stored with a key.
+<a name="lookup_pids-1"></a>
+
 <h3>lookup_pids/1</h3>
 <h3>lookup_pids/1</h3>
 
 
 
 
 
 
 
 
 
 
-<tt>lookup_pids(Key::<a href="#type-key">key()</a>) -> [pid()]</tt>
+
+<pre>lookup_pids(Key::<a href="#type-key">key()</a>) -> [pid()]</pre>
+
+<br></br>
+
 
 
 
 
 
 
@@ -561,9 +598,7 @@ Returns a list of pids with the published key Key
 
 
 If the type of registration entry is either name or aggregated counter,
 If the type of registration entry is either name or aggregated counter,
 this function will return either an empty list, or a list of one pid.
 this function will return either an empty list, or a list of one pid.
-For non-unique types, the return value can be a list of any length.
-<a name="lookup_value-1"></a>
-
+For non-unique types, the return value can be a list of any length.<a name="lookup_value-1"></a>
 
 
 <h3>lookup_value/1</h3>
 <h3>lookup_value/1</h3>
 
 
@@ -571,22 +606,28 @@ For non-unique types, the return value can be a list of any length.
 
 
 
 
 
 
-<tt>lookup_value(Key) -> Value</tt>
 
 
+<pre>lookup_value(Key) -> Value</pre>
 
 
+<br></br>
 
 
-Lookup the value stored with a key.
 
 
-<a name="lookup_values-1"></a>
 
 
 
 
+Lookup the value stored with a key.
+<a name="lookup_values-1"></a>
+
 <h3>lookup_values/1</h3>
 <h3>lookup_values/1</h3>
 
 
 
 
 
 
 
 
 
 
-<tt>lookup_values(Key::<a href="#type-key">key()</a>) -> [{pid(), Value}]</tt>
+
+<pre>lookup_values(Key::<a href="#type-key">key()</a>) -> [{pid(), Value}]</pre>
+
+<br></br>
+
 
 
 
 
 
 
@@ -596,9 +637,7 @@ Retrieve the `{Pid,Value}` pairs corresponding to Key.
 
 
 Key refer to any type of registry object. If it refers to a unique
 Key refer to any type of registry object. If it refers to a unique
 object, the list will be of length 0 or 1. If it refers to a non-unique
 object, the list will be of length 0 or 1. If it refers to a non-unique
-object, the return value can be a list of any length.
-<a name="mreg-3"></a>
-
+object, the return value can be a list of any length.<a name="mreg-3"></a>
 
 
 <h3>mreg/3</h3>
 <h3>mreg/3</h3>
 
 
@@ -606,17 +645,19 @@ object, the return value can be a list of any length.
 
 
 
 
 
 
-<tt>mreg(T::<a href="#type-type">type()</a>, X2::<a href="#type-scope">scope()</a>, KVL::[{Key::any(), Value::any()}]) -> true</tt>
+
+<pre>mreg(T::<a href="#type-type">type()</a>, X2::<a href="#type-scope">scope()</a>, KVL::[{Key::any(), Value::any()}]) -> true</pre>
+
+<br></br>
 
 
 
 
 
 
 
 
 
 
-Register multiple {Key,Value} pairs of a given type and scope.
 
 
-This function is more efficient than calling [`reg/2`](#reg-2) repeatedly.
-<a name="nb_wait-1"></a>
+Register multiple {Key,Value} pairs of a given type and scope.
 
 
+This function is more efficient than calling [`reg/2`](#reg-2) repeatedly.<a name="nb_wait-1"></a>
 
 
 <h3>nb_wait/1</h3>
 <h3>nb_wait/1</h3>
 
 
@@ -624,15 +665,17 @@ This function is more efficient than calling [`reg/2`](#reg-2) repeatedly.
 
 
 
 
 
 
-<tt>nb_wait(Key::<a href="#type-key">key()</a>) -> Ref</tt>
+
+<pre>nb_wait(Key::<a href="#type-key">key()</a>) -> Ref</pre>
+
+<br></br>
+
 
 
 
 
 
 
 Wait for a local name to be registered.
 Wait for a local name to be registered.
 The caller can expect to receive a message,
 The caller can expect to receive a message,
-{gproc, Ref, registered, {Key, Pid, Value}}, once the name is registered.
-<a name="next-2"></a>
-
+{gproc, Ref, registered, {Key, Pid, Value}}, once the name is registered.<a name="next-2"></a>
 
 
 <h3>next/2</h3>
 <h3>next/2</h3>
 
 
@@ -640,7 +683,11 @@ The caller can expect to receive a message,
 
 
 
 
 
 
-<tt>next(Context::<a href="#type-context">context()</a>, Key::<a href="#type-key">key()</a>) -> <a href="#type-key">key()</a> | '$end_of_table'</tt>
+
+<pre>next(Context::<a href="#type-context">context()</a>, Key::<a href="#type-key">key()</a>) -> <a href="#type-key">key()</a> | '$end_of_table'</pre>
+
+<br></br>
+
 
 
 
 
 
 
@@ -649,9 +696,7 @@ The caller can expect to receive a message,
 Behaves as ets:next(Tab,Key) for a given type of registration object.
 Behaves as ets:next(Tab,Key) for a given type of registration object.
 
 
 See [`http://www.erlang.org/doc/man/ets.html#next-2`](http://www.erlang.org/doc/man/ets.html#next-2).
 See [`http://www.erlang.org/doc/man/ets.html#next-2`](http://www.erlang.org/doc/man/ets.html#next-2).
-The registry behaves as an ordered_set table.
-<a name="prev-2"></a>
-
+The registry behaves as an ordered_set table.<a name="prev-2"></a>
 
 
 <h3>prev/2</h3>
 <h3>prev/2</h3>
 
 
@@ -659,7 +704,11 @@ The registry behaves as an ordered_set table.
 
 
 
 
 
 
-<tt>prev(Context::<a href="#type-context">context()</a>, Key::<a href="#type-key">key()</a>) -> <a href="#type-key">key()</a> | '$end_of_table'</tt>
+
+<pre>prev(Context::<a href="#type-context">context()</a>, Key::<a href="#type-key">key()</a>) -> <a href="#type-key">key()</a> | '$end_of_table'</pre>
+
+<br></br>
+
 
 
 
 
 
 
@@ -668,9 +717,7 @@ The registry behaves as an ordered_set table.
 Behaves as ets:prev(Tab,Key) for a given type of registration object.
 Behaves as ets:prev(Tab,Key) for a given type of registration object.
 
 
 See [`http://www.erlang.org/doc/man/ets.html#prev-2`](http://www.erlang.org/doc/man/ets.html#prev-2).
 See [`http://www.erlang.org/doc/man/ets.html#prev-2`](http://www.erlang.org/doc/man/ets.html#prev-2).
-The registry behaves as an ordered_set table.
-<a name="reg-1"></a>
-
+The registry behaves as an ordered_set table.<a name="reg-1"></a>
 
 
 <h3>reg/1</h3>
 <h3>reg/1</h3>
 
 
@@ -678,31 +725,35 @@ The registry behaves as an ordered_set table.
 
 
 
 
 
 
-<tt>reg(Key::<a href="#type-key">key()</a>) -> true</tt>
 
 
+<pre>reg(Key::<a href="#type-key">key()</a>) -> true</pre>
 
 
+<br></br>
 
 
-Equivalent to [`reg(Key, default(Key))`](#reg-2).
-<a name="reg-2"></a>
 
 
 
 
+
+Equivalent to [`reg(Key, default(Key))`](#reg-2).<a name="reg-2"></a>
+
 <h3>reg/2</h3>
 <h3>reg/2</h3>
 
 
 
 
 
 
 
 
 
 
-<tt>reg(Key::<a href="#type-key">key()</a>, Value) -> true</tt>
 
 
+<pre>reg(Key::<a href="#type-key">key()</a>, Value) -> true</pre>
 
 
+<br></br>
 
 
 
 
 
 
-Register a name or property for the current process
 
 
 
 
-<a name="select-1"></a>
 
 
+Register a name or property for the current process
+
+<a name="select-1"></a>
 
 
 <h3>select/1</h3>
 <h3>select/1</h3>
 
 
@@ -710,21 +761,27 @@ Register a name or property for the current process
 
 
 
 
 
 
-<tt>select(Pat::<a href="#type-select_pattern">select_pattern()</a>) -> list(<a href="#type-sel_object">sel_object()</a>)</tt>
 
 
+<pre>select(Pat::<a href="#type-select_pattern">select_pattern()</a>) -> list(<a href="#type-sel_object">sel_object()</a>)</pre>
 
 
+<br></br>
 
 
-Equivalent to [`select(all, Pat)`](#select-2).
-<a name="select-2"></a>
 
 
 
 
+
+Equivalent to [`select(all, Pat)`](#select-2).<a name="select-2"></a>
+
 <h3>select/2</h3>
 <h3>select/2</h3>
 
 
 
 
 
 
 
 
 
 
-<tt>select(Type::<a href="#type-sel_type">sel_type()</a>, Pat::<a href="#type-sel_pattern">sel_pattern()</a>) -> [{Key, Pid, Value}]</tt>
+
+<pre>select(Type::<a href="#type-sel_type">sel_type()</a>, Pat::<a href="#type-sel_pattern">sel_pattern()</a>) -> [{Key, Pid, Value}]</pre>
+
+<br></br>
+
 
 
 
 
 
 
@@ -733,9 +790,7 @@ Equivalent to [`select(all, Pat)`](#select-2).
 Perform a select operation on the process registry.
 Perform a select operation on the process registry.
 
 
 The physical representation in the registry may differ from the above,
 The physical representation in the registry may differ from the above,
-but the select patterns are transformed appropriately.
-<a name="select-3"></a>
-
+but the select patterns are transformed appropriately.<a name="select-3"></a>
 
 
 <h3>select/3</h3>
 <h3>select/3</h3>
 
 
@@ -743,17 +798,19 @@ but the select patterns are transformed appropriately.
 
 
 
 
 
 
-<tt>select(Type::<a href="#type-sel_type">sel_type()</a>, Pat::<a href="#type-sel_patten">sel_patten()</a>, Limit::integer()) -> [{Key, Pid, Value}]</tt>
+
+<pre>select(Type::<a href="#type-sel_type">sel_type()</a>, Pat::<a href="#type-sel_patten">sel_patten()</a>, Limit::integer()) -> [{Key, Pid, Value}]</pre>
+
+<br></br>
 
 
 
 
 
 
 
 
 
 
-Like [`select/2`](#select-2) but returns Limit objects at a time.
 
 
-See [`http://www.erlang.org/doc/man/ets.html#select-3`](http://www.erlang.org/doc/man/ets.html#select-3).
-<a name="send-2"></a>
+Like [`select/2`](#select-2) but returns Limit objects at a time.
 
 
+See [`http://www.erlang.org/doc/man/ets.html#select-3`](http://www.erlang.org/doc/man/ets.html#select-3).<a name="send-2"></a>
 
 
 <h3>send/2</h3>
 <h3>send/2</h3>
 
 
@@ -761,7 +818,11 @@ See [`http://www.erlang.org/doc/man/ets.html#select-3`](http://www.erlang.org/do
 
 
 
 
 
 
-<tt>send(Key::<a href="#type-key">key()</a>, Msg::any()) -> Msg</tt>
+
+<pre>send(Key::<a href="#type-key">key()</a>, Msg::any()) -> Msg</pre>
+
+<br></br>
+
 
 
 
 
 
 
@@ -772,9 +833,7 @@ Sends a message to the process, or processes, corresponding to Key.
 If Key belongs to a unique object (name or aggregated counter), this
 If Key belongs to a unique object (name or aggregated counter), this
 function will send a message to the corresponding process, or fail if there
 function will send a message to the corresponding process, or fail if there
 is no such process. If Key is for a non-unique object type (counter or
 is no such process. If Key is for a non-unique object type (counter or
-property), Msg will be send to all processes that have such an object.
-<a name="set_value-2"></a>
-
+property), Msg will be send to all processes that have such an object.<a name="set_value-2"></a>
 
 
 <h3>set_value/2</h3>
 <h3>set_value/2</h3>
 
 
@@ -782,7 +841,11 @@ property), Msg will be send to all processes that have such an object.
 
 
 
 
 
 
-<tt>set_value(Key::<a href="#type-key">key()</a>, Value) -> true</tt>
+
+<pre>set_value(Key::<a href="#type-key">key()</a>, Value) -> true</pre>
+
+<br></br>
+
 
 
 
 
 
 
@@ -796,9 +859,7 @@ Key is assumed to exist and belong to the calling process.
 If it doesn't, this function will exit.
 If it doesn't, this function will exit.
 
 
 Value can be any term, unless the object is a counter, in which case
 Value can be any term, unless the object is a counter, in which case
-it must be an integer.
-<a name="start_link-0"></a>
-
+it must be an integer.<a name="start_link-0"></a>
 
 
 <h3>start_link/0</h3>
 <h3>start_link/0</h3>
 
 
@@ -806,7 +867,11 @@ it must be an integer.
 
 
 
 
 
 
-<tt>start_link() -> {ok, pid()}</tt>
+
+<pre>start_link() -> {ok, pid()}</pre>
+
+<br></br>
+
 
 
 
 
 
 
@@ -815,39 +880,79 @@ it must be an integer.
 Starts the gproc server.
 Starts the gproc server.
 
 
 This function is intended to be called from gproc_sup, as part of
 This function is intended to be called from gproc_sup, as part of
-starting the gproc application.
-<a name="table-1"></a>
+starting the gproc application.<a name="surrender-2"></a>
+
+<h3>surrender/2</h3>
+
+
+
+
+
+
+<pre>surrender(From::<a href="#type-key">key()</a>, To::pid() | <a href="#type-key">key()</a>) -> undefined | pid()</pre>
+
+<br></br>
+
+
+
+
+
+
+Atomically transfers the key `From` to the process identified by `To`.
 
 
 
 
+
+This function transfers any gproc key (name, property, counter, aggr. counter)  
+from one process to another, and returns the pid of the new owner.
+
+
+
+`To` must be either a pid or a unique name (name or aggregated counter), but
+does not necessarily have to resolve to an existing process. If there is
+no process registered with the `To` key, `surrender/2` returns `undefined`,
+and the `From` key is effectively unregistered.
+
+
+
+It is allowed to surrender a key to oneself, but of course, this operation  
+will have no effect.
+
+Fails with `badarg` if the calling process does not have a `From` key
+registered.<a name="table-1"></a>
+
 <h3>table/1</h3>
 <h3>table/1</h3>
 
 
 
 
 
 
 
 
 
 
-<tt>table(Context::<a href="#type-context">context()</a>) -> any()</tt>
 
 
+<pre>table(Context::<a href="#type-context">context()</a>) -> any()</pre>
+
+<br></br>
 
 
 
 
-Equivalent to [`table(Context, [])`](#table-2).
-<a name="table-2"></a>
 
 
 
 
+Equivalent to [`table(Context, [])`](#table-2).<a name="table-2"></a>
+
 <h3>table/2</h3>
 <h3>table/2</h3>
 
 
 
 
 
 
 
 
 
 
-<tt>table(Context::<a href="#type-context">context()</a>, Opts) -> any()</tt>
+
+<pre>table(Context::<a href="#type-context">context()</a>, Opts) -> any()</pre>
+
+<br></br>
+
 
 
 
 
 
 
 QLC table generator for the gproc registry.
 QLC table generator for the gproc registry.
 Context specifies which subset of the registry should be queried.
 Context specifies which subset of the registry should be queried.
-See [`http://www.erlang.org/doc/man/qlc.html`](http://www.erlang.org/doc/man/qlc.html).
-<a name="unreg-1"></a>
-
+See [`http://www.erlang.org/doc/man/qlc.html`](http://www.erlang.org/doc/man/qlc.html).<a name="unreg-1"></a>
 
 
 <h3>unreg/1</h3>
 <h3>unreg/1</h3>
 
 
@@ -855,13 +960,15 @@ See [`http://www.erlang.org/doc/man/qlc.html`](http://www.erlang.org/doc/man/qlc
 
 
 
 
 
 
-<tt>unreg(Key::<a href="#type-key">key()</a>) -> true</tt>
+
+<pre>unreg(Key::<a href="#type-key">key()</a>) -> true</pre>
+
+<br></br>
 
 
 
 
 
 
-Unregister a name or property.
-<a name="unregister_name-1"></a>
 
 
+Unregister a name or property.<a name="unregister_name-1"></a>
 
 
 <h3>unregister_name/1</h3>
 <h3>unregister_name/1</h3>
 
 
@@ -873,9 +980,7 @@ Unregister a name or property.
 
 
 
 
 
 
-Equivalent to `unreg / 1`.
-<a name="update_counter-2"></a>
-
+Equivalent to `unreg / 1`.<a name="update_counter-2"></a>
 
 
 <h3>update_counter/2</h3>
 <h3>update_counter/2</h3>
 
 
@@ -883,7 +988,11 @@ Equivalent to `unreg / 1`.
 
 
 
 
 
 
-<tt>update_counter(Key::<a href="#type-key">key()</a>, Incr::integer()) -> integer()</tt>
+
+<pre>update_counter(Key::<a href="#type-key">key()</a>, Incr::integer()) -> integer()</pre>
+
+<br></br>
+
 
 
 
 
 
 
@@ -893,9 +1002,7 @@ Updates the counter registered as Key for the current process.
 
 
 This function works like ets:update_counter/3
 This function works like ets:update_counter/3
 (see [`http://www.erlang.org/doc/man/ets.html#update_counter-3`](http://www.erlang.org/doc/man/ets.html#update_counter-3)), but
 (see [`http://www.erlang.org/doc/man/ets.html#update_counter-3`](http://www.erlang.org/doc/man/ets.html#update_counter-3)), but
-will fail if the type of object referred to by Key is not a counter.
-<a name="where-1"></a>
-
+will fail if the type of object referred to by Key is not a counter.<a name="where-1"></a>
 
 
 <h3>where/1</h3>
 <h3>where/1</h3>
 
 
@@ -903,7 +1010,11 @@ will fail if the type of object referred to by Key is not a counter.
 
 
 
 
 
 
-<tt>where(Key::<a href="#type-key">key()</a>) -> pid()</tt>
+
+<pre>where(Key::<a href="#type-key">key()</a>) -> pid()</pre>
+
+<br></br>
+
 
 
 
 
 
 
@@ -913,9 +1024,7 @@ Returns the pid registered as Key
 
 
 The type of registration entry must be either name or aggregated counter.
 The type of registration entry must be either name or aggregated counter.
 Otherwise this function will exit. Use [`lookup_pids/1`](#lookup_pids-1) in these
 Otherwise this function will exit. Use [`lookup_pids/1`](#lookup_pids-1) in these
-cases.
-<a name="whereis_name-1"></a>
-
+cases.<a name="whereis_name-1"></a>
 
 
 <h3>whereis_name/1</h3>
 <h3>whereis_name/1</h3>
 
 
@@ -929,4 +1038,4 @@ cases.
 
 
 Equivalent to `where / 1`.
 Equivalent to `where / 1`.
 
 
-_Generated by EDoc, Mar 18 2011, 13:31:52._
+_Generated by EDoc, Mar 29 2011, 14:24:55._

+ 2 - 8
doc/gproc_app.md

@@ -21,15 +21,13 @@ __Behaviours:__ [`application`](application.md).
 <table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#start-0">start/0</a></td><td></td></tr><tr><td valign="top"><a href="#start-2">start/2</a></td><td></td></tr><tr><td valign="top"><a href="#stop-1">stop/1</a></td><td></td></tr></table>
 <table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#start-0">start/0</a></td><td></td></tr><tr><td valign="top"><a href="#start-2">start/2</a></td><td></td></tr><tr><td valign="top"><a href="#stop-1">stop/1</a></td><td></td></tr></table>
 
 
 
 
-<a name="functions"></a>
 
 
 
 
-<h2>Function Details</h2>
+<h2><a name="functions">Function Details</a></h2>
 
 
 
 
 <a name="start-0"></a>
 <a name="start-0"></a>
 
 
-
 <h3>start/0</h3>
 <h3>start/0</h3>
 
 
 
 
@@ -38,10 +36,8 @@ __Behaviours:__ [`application`](application.md).
 
 
 `start() -> any()`
 `start() -> any()`
 
 
-
 <a name="start-2"></a>
 <a name="start-2"></a>
 
 
-
 <h3>start/2</h3>
 <h3>start/2</h3>
 
 
 
 
@@ -50,10 +46,8 @@ __Behaviours:__ [`application`](application.md).
 
 
 `start(Type, StartArgs) -> any()`
 `start(Type, StartArgs) -> any()`
 
 
-
 <a name="stop-1"></a>
 <a name="stop-1"></a>
 
 
-
 <h3>stop/1</h3>
 <h3>stop/1</h3>
 
 
 
 
@@ -64,4 +58,4 @@ __Behaviours:__ [`application`](application.md).
 
 
 
 
 
 
-_Generated by EDoc, Mar 18 2011, 13:31:52._
+_Generated by EDoc, Mar 29 2011, 14:24:55._

+ 13 - 49
doc/gproc_dist.md

@@ -13,7 +13,7 @@ Extended process registry.
 
 
 
 
 
 
-__Behaviours:__ [`gen_leader`](gen_leader.md).
+__Behaviours:__ [`gen_leader`](/Users/uwiger/ETC/git/gproc/deps/gen_leader/doc/gen_leader.md).
 
 
 __Authors:__ Ulf Wiger ([`ulf.wiger@ericsson.com`](mailto:ulf.wiger@ericsson.com)).
 __Authors:__ Ulf Wiger ([`ulf.wiger@ericsson.com`](mailto:ulf.wiger@ericsson.com)).
 
 
@@ -35,18 +35,16 @@ Class = n  - unique name
 | p  - non-unique property
 | p  - non-unique property
 | c  - counter
 | c  - counter
 | a  - aggregated counter
 | a  - aggregated counter
-Scope = l | g (global or local).</td></tr><tr><td valign="top"><a href="#set_value-2">set_value/2</a></td><td></td></tr><tr><td valign="top"><a href="#start_link-0">start_link/0</a></td><td></td></tr><tr><td valign="top"><a href="#start_link-1">start_link/1</a></td><td></td></tr><tr><td valign="top"><a href="#surrendered-3">surrendered/3</a></td><td></td></tr><tr><td valign="top"><a href="#terminate-2">terminate/2</a></td><td></td></tr><tr><td valign="top"><a href="#unreg-1">unreg/1</a></td><td></td></tr><tr><td valign="top"><a href="#update_counter-2">update_counter/2</a></td><td></td></tr></table>
+Scope = l | g (global or local).</td></tr><tr><td valign="top"><a href="#set_value-2">set_value/2</a></td><td></td></tr><tr><td valign="top"><a href="#start_link-0">start_link/0</a></td><td></td></tr><tr><td valign="top"><a href="#start_link-1">start_link/1</a></td><td></td></tr><tr><td valign="top"><a href="#surrender-2">surrender/2</a></td><td></td></tr><tr><td valign="top"><a href="#surrendered-3">surrendered/3</a></td><td></td></tr><tr><td valign="top"><a href="#terminate-2">terminate/2</a></td><td></td></tr><tr><td valign="top"><a href="#unreg-1">unreg/1</a></td><td></td></tr><tr><td valign="top"><a href="#update_counter-2">update_counter/2</a></td><td></td></tr></table>
 
 
 
 
-<a name="functions"></a>
 
 
 
 
-<h2>Function Details</h2>
+<h2><a name="functions">Function Details</a></h2>
 
 
 
 
 <a name="code_change-4"></a>
 <a name="code_change-4"></a>
 
 
-
 <h3>code_change/4</h3>
 <h3>code_change/4</h3>
 
 
 
 
@@ -55,10 +53,8 @@ Scope = l | g (global or local).</td></tr><tr><td valign="top"><a href="#set_val
 
 
 `code_change(FromVsn, S, Extra, E) -> any()`
 `code_change(FromVsn, S, Extra, E) -> any()`
 
 
-
 <a name="elected-2"></a>
 <a name="elected-2"></a>
 
 
-
 <h3>elected/2</h3>
 <h3>elected/2</h3>
 
 
 
 
@@ -67,10 +63,8 @@ Scope = l | g (global or local).</td></tr><tr><td valign="top"><a href="#set_val
 
 
 `elected(S, E) -> any()`
 `elected(S, E) -> any()`
 
 
-
 <a name="elected-3"></a>
 <a name="elected-3"></a>
 
 
-
 <h3>elected/3</h3>
 <h3>elected/3</h3>
 
 
 
 
@@ -79,10 +73,8 @@ Scope = l | g (global or local).</td></tr><tr><td valign="top"><a href="#set_val
 
 
 `elected(S, E, Node) -> any()`
 `elected(S, E, Node) -> any()`
 
 
-
 <a name="from_leader-3"></a>
 <a name="from_leader-3"></a>
 
 
-
 <h3>from_leader/3</h3>
 <h3>from_leader/3</h3>
 
 
 
 
@@ -91,10 +83,8 @@ Scope = l | g (global or local).</td></tr><tr><td valign="top"><a href="#set_val
 
 
 `from_leader(Ops, S, E) -> any()`
 `from_leader(Ops, S, E) -> any()`
 
 
-
 <a name="handle_DOWN-3"></a>
 <a name="handle_DOWN-3"></a>
 
 
-
 <h3>handle_DOWN/3</h3>
 <h3>handle_DOWN/3</h3>
 
 
 
 
@@ -103,10 +93,8 @@ Scope = l | g (global or local).</td></tr><tr><td valign="top"><a href="#set_val
 
 
 `handle_DOWN(Node, S, E) -> any()`
 `handle_DOWN(Node, S, E) -> any()`
 
 
-
 <a name="handle_call-4"></a>
 <a name="handle_call-4"></a>
 
 
-
 <h3>handle_call/4</h3>
 <h3>handle_call/4</h3>
 
 
 
 
@@ -115,10 +103,8 @@ Scope = l | g (global or local).</td></tr><tr><td valign="top"><a href="#set_val
 
 
 `handle_call(X1, X2, S, X4) -> any()`
 `handle_call(X1, X2, S, X4) -> any()`
 
 
-
 <a name="handle_cast-3"></a>
 <a name="handle_cast-3"></a>
 
 
-
 <h3>handle_cast/3</h3>
 <h3>handle_cast/3</h3>
 
 
 
 
@@ -127,10 +113,8 @@ Scope = l | g (global or local).</td></tr><tr><td valign="top"><a href="#set_val
 
 
 `handle_cast(Msg, S, X3) -> any()`
 `handle_cast(Msg, S, X3) -> any()`
 
 
-
 <a name="handle_info-2"></a>
 <a name="handle_info-2"></a>
 
 
-
 <h3>handle_info/2</h3>
 <h3>handle_info/2</h3>
 
 
 
 
@@ -139,10 +123,8 @@ Scope = l | g (global or local).</td></tr><tr><td valign="top"><a href="#set_val
 
 
 `handle_info(X1, S) -> any()`
 `handle_info(X1, S) -> any()`
 
 
-
 <a name="handle_leader_call-4"></a>
 <a name="handle_leader_call-4"></a>
 
 
-
 <h3>handle_leader_call/4</h3>
 <h3>handle_leader_call/4</h3>
 
 
 
 
@@ -151,10 +133,8 @@ Scope = l | g (global or local).</td></tr><tr><td valign="top"><a href="#set_val
 
 
 `handle_leader_call(X1, From, S, E) -> any()`
 `handle_leader_call(X1, From, S, E) -> any()`
 
 
-
 <a name="handle_leader_cast-3"></a>
 <a name="handle_leader_cast-3"></a>
 
 
-
 <h3>handle_leader_cast/3</h3>
 <h3>handle_leader_cast/3</h3>
 
 
 
 
@@ -163,10 +143,8 @@ Scope = l | g (global or local).</td></tr><tr><td valign="top"><a href="#set_val
 
 
 `handle_leader_cast(X1, S, E) -> any()`
 `handle_leader_cast(X1, S, E) -> any()`
 
 
-
 <a name="init-1"></a>
 <a name="init-1"></a>
 
 
-
 <h3>init/1</h3>
 <h3>init/1</h3>
 
 
 
 
@@ -175,10 +153,8 @@ Scope = l | g (global or local).</td></tr><tr><td valign="top"><a href="#set_val
 
 
 `init(Opts) -> any()`
 `init(Opts) -> any()`
 
 
-
 <a name="leader_call-1"></a>
 <a name="leader_call-1"></a>
 
 
-
 <h3>leader_call/1</h3>
 <h3>leader_call/1</h3>
 
 
 
 
@@ -187,10 +163,8 @@ Scope = l | g (global or local).</td></tr><tr><td valign="top"><a href="#set_val
 
 
 `leader_call(Req) -> any()`
 `leader_call(Req) -> any()`
 
 
-
 <a name="leader_cast-1"></a>
 <a name="leader_cast-1"></a>
 
 
-
 <h3>leader_cast/1</h3>
 <h3>leader_cast/1</h3>
 
 
 
 
@@ -199,10 +173,8 @@ Scope = l | g (global or local).</td></tr><tr><td valign="top"><a href="#set_val
 
 
 `leader_cast(Msg) -> any()`
 `leader_cast(Msg) -> any()`
 
 
-
 <a name="mreg-2"></a>
 <a name="mreg-2"></a>
 
 
-
 <h3>mreg/2</h3>
 <h3>mreg/2</h3>
 
 
 
 
@@ -211,10 +183,8 @@ Scope = l | g (global or local).</td></tr><tr><td valign="top"><a href="#set_val
 
 
 `mreg(T, KVL) -> any()`
 `mreg(T, KVL) -> any()`
 
 
-
 <a name="reg-1"></a>
 <a name="reg-1"></a>
 
 
-
 <h3>reg/1</h3>
 <h3>reg/1</h3>
 
 
 
 
@@ -223,10 +193,8 @@ Scope = l | g (global or local).</td></tr><tr><td valign="top"><a href="#set_val
 
 
 `reg(Key) -> any()`
 `reg(Key) -> any()`
 
 
-
 <a name="reg-2"></a>
 <a name="reg-2"></a>
 
 
-
 <h3>reg/2</h3>
 <h3>reg/2</h3>
 
 
 
 
@@ -243,10 +211,8 @@ Class = n  - unique name
 | c  - counter
 | c  - counter
 | a  - aggregated counter
 | a  - aggregated counter
 Scope = l | g (global or local)
 Scope = l | g (global or local)
-
 <a name="set_value-2"></a>
 <a name="set_value-2"></a>
 
 
-
 <h3>set_value/2</h3>
 <h3>set_value/2</h3>
 
 
 
 
@@ -255,10 +221,8 @@ Scope = l | g (global or local)
 
 
 `set_value(Key, Value) -> any()`
 `set_value(Key, Value) -> any()`
 
 
-
 <a name="start_link-0"></a>
 <a name="start_link-0"></a>
 
 
-
 <h3>start_link/0</h3>
 <h3>start_link/0</h3>
 
 
 
 
@@ -267,10 +231,8 @@ Scope = l | g (global or local)
 
 
 `start_link() -> any()`
 `start_link() -> any()`
 
 
-
 <a name="start_link-1"></a>
 <a name="start_link-1"></a>
 
 
-
 <h3>start_link/1</h3>
 <h3>start_link/1</h3>
 
 
 
 
@@ -279,10 +241,18 @@ Scope = l | g (global or local)
 
 
 `start_link(Nodes) -> any()`
 `start_link(Nodes) -> any()`
 
 
+<a name="surrender-2"></a>
 
 
-<a name="surrendered-3"></a>
+<h3>surrender/2</h3>
 
 
 
 
+
+
+
+`surrender(Key, To) -> any()`
+
+<a name="surrendered-3"></a>
+
 <h3>surrendered/3</h3>
 <h3>surrendered/3</h3>
 
 
 
 
@@ -291,10 +261,8 @@ Scope = l | g (global or local)
 
 
 `surrendered(S, X2, E) -> any()`
 `surrendered(S, X2, E) -> any()`
 
 
-
 <a name="terminate-2"></a>
 <a name="terminate-2"></a>
 
 
-
 <h3>terminate/2</h3>
 <h3>terminate/2</h3>
 
 
 
 
@@ -303,10 +271,8 @@ Scope = l | g (global or local)
 
 
 `terminate(Reason, S) -> any()`
 `terminate(Reason, S) -> any()`
 
 
-
 <a name="unreg-1"></a>
 <a name="unreg-1"></a>
 
 
-
 <h3>unreg/1</h3>
 <h3>unreg/1</h3>
 
 
 
 
@@ -315,10 +281,8 @@ Scope = l | g (global or local)
 
 
 `unreg(Key) -> any()`
 `unreg(Key) -> any()`
 
 
-
 <a name="update_counter-2"></a>
 <a name="update_counter-2"></a>
 
 
-
 <h3>update_counter/2</h3>
 <h3>update_counter/2</h3>
 
 
 
 
@@ -329,4 +293,4 @@ Scope = l | g (global or local)
 
 
 
 
 
 
-_Generated by EDoc, Mar 18 2011, 13:31:52._
+_Generated by EDoc, Mar 29 2011, 14:24:55._

+ 2 - 6
doc/gproc_init.md

@@ -19,15 +19,13 @@ Module gproc_init
 <table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#hard_reset-0">hard_reset/0</a></td><td></td></tr><tr><td valign="top"><a href="#soft_reset-0">soft_reset/0</a></td><td></td></tr></table>
 <table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#hard_reset-0">hard_reset/0</a></td><td></td></tr><tr><td valign="top"><a href="#soft_reset-0">soft_reset/0</a></td><td></td></tr></table>
 
 
 
 
-<a name="functions"></a>
 
 
 
 
-<h2>Function Details</h2>
+<h2><a name="functions">Function Details</a></h2>
 
 
 
 
 <a name="hard_reset-0"></a>
 <a name="hard_reset-0"></a>
 
 
-
 <h3>hard_reset/0</h3>
 <h3>hard_reset/0</h3>
 
 
 
 
@@ -36,10 +34,8 @@ Module gproc_init
 
 
 `hard_reset() -> any()`
 `hard_reset() -> any()`
 
 
-
 <a name="soft_reset-0"></a>
 <a name="soft_reset-0"></a>
 
 
-
 <h3>soft_reset/0</h3>
 <h3>soft_reset/0</h3>
 
 
 
 
@@ -50,4 +46,4 @@ Module gproc_init
 
 
 
 
 
 
-_Generated by EDoc, Mar 18 2011, 13:31:51._
+_Generated by EDoc, Mar 29 2011, 14:24:55._

+ 1 - 1
doc/gproc_lib.md

@@ -22,4 +22,4 @@ This module implements an extended process registry
 
 
 For a detailed description, see gproc/doc/erlang07-wiger.pdf.
 For a detailed description, see gproc/doc/erlang07-wiger.pdf.
 
 
-_Generated by EDoc, Mar 18 2011, 13:31:51._
+_Generated by EDoc, Mar 29 2011, 14:24:55._

+ 3 - 7
doc/gproc_sup.md

@@ -21,15 +21,13 @@ __Behaviours:__ [`supervisor`](supervisor.md).
 <table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#init-1">init/1</a></td><td>The main GPROC supervisor.</td></tr><tr><td valign="top"><a href="#start_link-1">start_link/1</a></td><td></td></tr></table>
 <table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#init-1">init/1</a></td><td>The main GPROC supervisor.</td></tr><tr><td valign="top"><a href="#start_link-1">start_link/1</a></td><td></td></tr></table>
 
 
 
 
-<a name="functions"></a>
 
 
 
 
-<h2>Function Details</h2>
+<h2><a name="functions">Function Details</a></h2>
 
 
 
 
 <a name="init-1"></a>
 <a name="init-1"></a>
 
 
-
 <h3>init/1</h3>
 <h3>init/1</h3>
 
 
 
 
@@ -40,9 +38,7 @@ __Behaviours:__ [`supervisor`](supervisor.md).
 
 
 
 
 
 
-The main GPROC supervisor.
-<a name="start_link-1"></a>
-
+The main GPROC supervisor.<a name="start_link-1"></a>
 
 
 <h3>start_link/1</h3>
 <h3>start_link/1</h3>
 
 
@@ -54,4 +50,4 @@ The main GPROC supervisor.
 
 
 
 
 
 
-_Generated by EDoc, Mar 18 2011, 13:31:51._
+_Generated by EDoc, Mar 29 2011, 14:24:55._

+ 84 - 18
src/gproc.erl

@@ -52,6 +52,7 @@
 	 lookup_value/1,
 	 lookup_value/1,
          lookup_values/1,
          lookup_values/1,
          update_counter/2,
          update_counter/2,
+	 surrender/2,
          send/2,
          send/2,
          info/1, info/2,
          info/1, info/2,
          select/1, select/2, select/3,
          select/1, select/2, select/3,
@@ -631,7 +632,31 @@ update_counter({c,g,_} = Key, Incr) when is_integer(Incr) ->
 update_counter(_, _) ->
 update_counter(_, _) ->
     erlang:error(badarg).
     erlang:error(badarg).
 
 
-
+%% @spec (From::key(), To::pid() | key()) -> undefined | pid()
+%%
+%% @doc Atomically transfers the key `From' to the process identified by `To'.
+%%
+%% This function transfers any gproc key (name, property, counter, aggr. counter)
+%% from one process to another, and returns the pid of the new owner.
+%%
+%% `To' must be either a pid or a unique name (name or aggregated counter), but
+%% does not necessarily have to resolve to an existing process. If there is 
+%% no process registered with the `To' key, `surrender/2' returns `undefined',
+%% and the `From' key is effectively unregistered.
+%%
+%% It is allowed to surrender a key to oneself, but of course, this operation
+%% will have no effect.
+%%
+%% Fails with `badarg' if the calling process does not have a `From' key 
+%% registered.
+%% @end
+surrender({_,l,_} = Key, ToPid) when is_pid(ToPid), node(ToPid) == node() ->
+    call({surrender, Key, ToPid});
+surrender({_,l,_} = Key, {n,l,_} = ToKey) ->
+    call({surrender, Key, ToKey});
+surrender({_,g,_} = Key, To) ->
+    ?CHK_DIST,
+    gproc_dist:surrender(Key, To).
 
 
 %% @spec (Key::key(), Msg::any()) -> Msg
 %% @spec (Key::key(), Msg::any()) -> Msg
 %%
 %%
@@ -840,23 +865,6 @@ handle_call({await, {_,l,_} = Key, Pid}, {_, Ref}, S) ->
         {reply, Reply, _} ->
         {reply, Reply, _} ->
             {reply, Reply, S}
             {reply, Reply, S}
     end;
     end;
-%%     Rev = {{Pid,Key}, r},
-%%     case ets:lookup(?TAB, {Key,T}) of
-%%         [{_, P, Value}] ->
-%%             %% for symmetry, we always reply with Ref and then send a message
-%%             gen_server:reply(From, Ref),
-%%             Pid ! {gproc, Ref, registered, {Key, P, Value}},
-%%             {noreply, S};
-%%         [{K, Waiters}] ->
-%%             NewWaiters = [{Pid,Ref} | Waiters],
-%%             ets:insert(?TAB, [{K, NewWaiters}, Rev]),
-%%             gproc_lib:ensure_monitor(Pid,l),
-%%             {reply, Ref, S};
-%%         [] ->
-%%             ets:insert(?TAB, [{{Key,T}, [{Pid,Ref}]}, Rev]),
-%%             gproc_lib:ensure_monitor(Pid,l),
-%%             {reply, Ref, S}
-%%     end;
 handle_call({mreg, T, l, L}, {Pid,_}, S) ->
 handle_call({mreg, T, l, L}, {Pid,_}, S) ->
     try gproc_lib:insert_many(T, l, L, Pid) of
     try gproc_lib:insert_many(T, l, L, Pid) of
         {true,_} -> {reply, true, S};
         {true,_} -> {reply, true, S};
@@ -879,6 +887,9 @@ handle_call({audit_process, Pid}, _, S) ->
 	    ignore
 	    ignore
     end,
     end,
     {reply, ok, S};
     {reply, ok, S};
+handle_call({surrender, Key, To}, {Pid,_}, S) ->
+    Reply = do_surrender(Key, To, Pid),
+    {reply, Reply, S};
 handle_call(_, _, S) ->
 handle_call(_, _, S) ->
     {reply, badarg, S}.
     {reply, badarg, S}.
 
 
@@ -1000,6 +1011,61 @@ process_is_down(Pid) ->
     ets:select_delete(?TAB, [{{{Pid,{'_',l,'_'}},'_'}, [], [true]}]),
     ets:select_delete(?TAB, [{{{Pid,{'_',l,'_'}},'_'}, [], [true]}]),
     ok.
     ok.
 
 
+do_surrender({T,l,_} = K, To, Pid) when T==n; T==a ->
+    Key = {K, T},
+    case ets:lookup(?TAB, Key) of
+	[{_, Pid, Value}] ->
+	    %% Pid owns the reg; allowed to surrender
+	    case pid_to_surrender_to(To) of
+		Pid ->
+		    %% Surrender to ourselves? Why not? We'll allow it,
+		    %% but nothing needs to be done.
+		    Pid;
+		ToPid when is_pid(ToPid) ->
+		    ets:insert(?TAB, [{Key, ToPid, Value},
+				      {{ToPid, K}, r}]),
+		    ets:delete(?TAB, {Pid, K}),
+		    gproc_lib:ensure_monitor(ToPid, l),
+		    ToPid;
+		undefined ->
+		    gproc_lib:remove_reg(K, Pid),
+		    undefined
+	    end;
+	_ ->
+	    badarg
+    end;
+do_surrender({T,l,_} = K, To, Pid) when T==c; T==p ->
+    Key = {K, Pid},
+    case ets:lookup(?TAB, Key) of
+	[{_, Pid, Value}] ->
+	    case pid_to_surrender_to(To) of
+		ToPid when is_pid(ToPid) ->
+		    ToKey = {K, ToPid},
+		    ets:insert(?TAB, [{ToKey, ToPid, Value},
+				      {{ToPid, K}, r}]),
+		    ets:delete(?TAB, {Pid, K}),
+		    ets:delete(?TAB, Key),
+		    gproc_lib:ensure_monitor(ToPid, l),
+		    ToPid;
+		undefined ->
+		    gproc_lib:remove_reg(K, Pid),
+		    undefined
+	    end;
+	_ ->
+	    badarg
+    end.
+			
+
+pid_to_surrender_to(P) when is_pid(P), node(P) == node() ->		    
+    P;
+pid_to_surrender_to({T,l,_} = Key) when T==n; T==a ->
+    case ets:lookup(?TAB, {Key, T}) of
+	[{_, Pid, _}] ->
+	    Pid;
+	_ ->
+	    undefined
+    end.
+
 create_tabs() ->
 create_tabs() ->
     case ets:info(?TAB, name) of
     case ets:info(?TAB, name) of
 	undefined ->
 	undefined ->

+ 51 - 11
src/gproc_dist.erl

@@ -26,6 +26,7 @@
 	 reg/1, reg/2, unreg/1,
 	 reg/1, reg/2, unreg/1,
 	 mreg/2,
 	 mreg/2,
 	 set_value/2,
 	 set_value/2,
+	 surrender/2,
 	 update_counter/2]).
 	 update_counter/2]).
 
 
 -export([leader_call/1, leader_cast/1]).
 -export([leader_call/1, leader_cast/1]).
@@ -57,6 +58,8 @@
 start_link() ->
 start_link() ->
     start_link({[node()|nodes()], []}).
     start_link({[node()|nodes()], []}).
 
 
+start_link(all) ->
+    start_link({[node()|nodes()], []});
 start_link(Nodes) when is_list(Nodes) ->
 start_link(Nodes) when is_list(Nodes) ->
     start_link({Nodes, []});
     start_link({Nodes, []});
 start_link({Nodes, Opts}) ->
 start_link({Nodes, Opts}) ->
@@ -107,7 +110,8 @@ set_value({_,g,_} = Key, Value) ->
 set_value(_, _) ->
 set_value(_, _) ->
     erlang:error(badarg).
     erlang:error(badarg).
 
 
-
+surrender({_,g,_} = Key, To) ->
+    leader_call({surrender, Key, To, self()}).
 
 
 
 
 update_counter({c,g,_} = Key, Incr) when is_integer(Incr) ->
 update_counter({c,g,_} = Key, Incr) when is_integer(Incr) ->
@@ -216,17 +220,39 @@ handle_leader_call({unreg, {T,g,Name} = K, Pid}, _From, S, _E) ->
 		    case ets:lookup(?TAB, {{a,g,Name},a}) of
 		    case ets:lookup(?TAB, {{a,g,Name},a}) of
 			[Aggr] ->
 			[Aggr] ->
 			    %% updated by remove_reg/2
 			    %% updated by remove_reg/2
-			    {reply, true, [{delete,[{K,Pid}]},
+			    {reply, true, [{delete,[Key, {Pid,K}]},
 					   {insert, [Aggr]}], S};
 					   {insert, [Aggr]}], S};
 			[] ->
 			[] ->
-			    {reply, true, [{delete, [{K, Pid}]}], S}
+			    {reply, true, [{delete, [Key, {Pid,K}]}], S}
 		    end;
 		    end;
 	       true ->
 	       true ->
-		    {reply, true, [{delete, [{K,Pid}]}], S}
+		    {reply, true, [{delete, [Key]}], S}
 	    end;
 	    end;
 	false ->
 	false ->
 	    {reply, badarg, S}
 	    {reply, badarg, S}
     end;
     end;
+handle_leader_call({surrender, {T,g,_} = K, To, Pid}, _From, S, _E)
+  when T == a; T == n ->
+    Key = {K, T},
+    case ets:lookup(?TAB, Key) of
+	[{_, Pid, Value}] ->
+	    case pid_to_surrender_to(To) of 
+		Pid ->
+		    {reply, Pid, S};
+		ToPid when is_pid(ToPid) ->
+		    ets:insert(?TAB, [{Key, ToPid, Value},
+				      {{ToPid,K}, r}]),
+		    gproc_lib:ensure_monitor(ToPid, g),
+		    {reply, ToPid, [{delete, [Key, {Pid,K}]},
+				   {insert, [{Key, ToPid, Value}]}], S};
+		undefined ->
+		    ets:delete(?TAB, Key),
+		    ets:delete(?TAB, {Pid, K}),
+		    {reply, undefined, [{delete, [Key, {Pid,K}]}], S}
+	    end;
+	_ ->
+	    {reply, badarg, S}
+    end;
 handle_leader_call({mreg, T, g, L, Pid}, _From, S, _E) ->
 handle_leader_call({mreg, T, g, L, Pid}, _From, S, _E) ->
     if T==p; T==n ->
     if T==p; T==n ->
 	    try gproc_lib:insert_many(T, g, Pid, L) of
 	    try gproc_lib:insert_many(T, g, Pid, L) of
@@ -346,15 +372,19 @@ from_leader(Ops, S, _E) ->
 
 
 delete_globals(Globals) ->
 delete_globals(Globals) ->
     lists:foreach(
     lists:foreach(
-      fun({Key, Pid}) ->
+      fun({{_,g,_},T} = K) when is_atom(T) ->
+	      ets:delete(?TAB, K);
+	 ({Key, Pid}) when is_pid(Pid) ->
               K = ets_key(Key,Pid),
               K = ets_key(Key,Pid),
 	      ets:delete(?TAB, K),
 	      ets:delete(?TAB, K),
-	      ets:delete(?TAB, {Pid, Key}),
-		  case node(Pid) =:= node() of
-			  true ->
-				  ets:delete(?TAB, {Pid,g});
-			  _ -> ok
-		  end
+	      ets:delete(?TAB, {Pid, Key});
+	 ({Pid, K}) when is_pid(Pid) ->
+	      ets:delete(?TAB, {Pid, K})
+	      %% case node(Pid) =:= node() of
+	      %% 	  true ->
+	      %% 	      ets:delete(?TAB, {Pid,g});
+	      %% 	  _ -> ok
+	      %% end
       end, Globals).
       end, Globals).
 
 
 ets_key({T,_,_} = K, _) when T==n; T==a ->
 ets_key({T,_,_} = K, _) when T==n; T==a ->
@@ -428,3 +458,13 @@ update_aggr_counter({c,g,Ctr}, Incr) ->
             ets:insert(?TAB, New),
             ets:insert(?TAB, New),
             [New]
             [New]
     end.
     end.
+
+pid_to_surrender_to(P) when is_pid(P) ->                 
+    P;
+pid_to_surrender_to({T,g,_} = Key) when T==n; T==a ->
+    case ets:lookup(?TAB, {Key, T}) of
+        [{_, Pid, _}] ->
+            Pid;
+        _ ->
+            undefined
+    end.