Просмотр исходного кода

gproc_monitor, local only, no test cases

Ulf Wiger 13 лет назад
Родитель
Сommit
a8297b276b
15 измененных файлов с 805 добавлено и 472 удалено
  1. 9 18
      README.md
  2. 9 18
      doc/README.md
  3. 1 1
      doc/edoc-info
  4. 208 244
      doc/gproc.md
  5. 8 16
      doc/gproc_app.md
  6. 41 78
      doc/gproc_dist.md
  7. 7 13
      doc/gproc_info.md
  8. 9 16
      doc/gproc_init.md
  9. 39 38
      doc/gproc_lib.md
  10. 92 0
      doc/gproc_monitor.md
  11. 7 14
      doc/gproc_sup.md
  12. 120 13
      src/gproc.erl
  13. 25 2
      src/gproc_lib.erl
  14. 227 0
      src/gproc_monitor.erl
  15. 3 1
      src/gproc_sup.erl

+ 9 - 18
README.md

@@ -1,10 +1,7 @@
 
 
 
 
-<h1>The gproc application</h1>
+#The gproc application#
 
 
-The gproc application
-=====================
-Extended process dictionary.
 
 
 __Authors:__ Ulf Wiger ([`ulf.wiger@erlang-solutions.com`](mailto:ulf.wiger@erlang-solutions.com)), Joseph Wayne Norton ([`norton@geminimobile.com`](mailto:norton@geminimobile.com)).
 __Authors:__ Ulf Wiger ([`ulf.wiger@erlang-solutions.com`](mailto:ulf.wiger@erlang-solutions.com)), Joseph Wayne Norton ([`norton@geminimobile.com`](mailto:norton@geminimobile.com)).
 
 
@@ -12,8 +9,7 @@ Extended process dictionary
 
 
 
 
 
 
-<h2>Introduction</h2>
-
+##Introduction##
 
 
 
 
 
 
@@ -43,8 +39,7 @@ Gproc is a process dictionary for Erlang, which provides a number of useful feat
 
 
 
 
 
 
-<h3>Use case: System inspection</h3>
-
+###Use case: System inspection##
 
 
 
 
 
 
@@ -57,8 +52,7 @@ browse key data in a running system.
 
 
 
 
 
 
-<h3>Use case: Pub/Sub patterns</h3>
-
+###Use case: Pub/Sub patterns##
 
 
 
 
 
 
@@ -78,8 +72,7 @@ notify(EventType, Msg) ->
 
 
 
 
 
 
-<h3>Use case: Environment handling</h3>
-
+###Use case: Environment handling##
 
 
 
 
 
 
@@ -96,8 +89,7 @@ See [`gproc:get_env/4`](http://github.com/esl/gproc/blob/master/doc/gproc.md#get
 
 
 
 
 
 
-<h2>Testing</h2>
-
+##Testing##
 
 
 
 
 
 
@@ -114,8 +106,7 @@ global gproc.
 
 
 
 
 
 
-<h2>Building Edoc</h2>
-
+##Building Edoc##
 
 
 
 
 
 
@@ -125,8 +116,7 @@ Gproc was first introduced at the ACM SIGPLAN Erlang Workshop in
 Freiburg 2007 ([Paper available here](http://github.com/esl/gproc/blob/master/doc/erlang07-wiger.pdf)).
 Freiburg 2007 ([Paper available here](http://github.com/esl/gproc/blob/master/doc/erlang07-wiger.pdf)).
 
 
 
 
-<h2 class="indextitle">Modules</h2>
-
+##Modules##
 
 
 
 
 <table width="100%" border="0" summary="list of modules">
 <table width="100%" border="0" summary="list of modules">
@@ -136,5 +126,6 @@ Freiburg 2007 ([Paper available here](http://github.com/esl/gproc/blob/master/do
 <tr><td><a href="http://github.com/esl/gproc/blob/master/doc/gproc_info.md" class="module">gproc_info</a></td></tr>
 <tr><td><a href="http://github.com/esl/gproc/blob/master/doc/gproc_info.md" class="module">gproc_info</a></td></tr>
 <tr><td><a href="http://github.com/esl/gproc/blob/master/doc/gproc_init.md" class="module">gproc_init</a></td></tr>
 <tr><td><a href="http://github.com/esl/gproc/blob/master/doc/gproc_init.md" class="module">gproc_init</a></td></tr>
 <tr><td><a href="http://github.com/esl/gproc/blob/master/doc/gproc_lib.md" class="module">gproc_lib</a></td></tr>
 <tr><td><a href="http://github.com/esl/gproc/blob/master/doc/gproc_lib.md" class="module">gproc_lib</a></td></tr>
+<tr><td><a href="http://github.com/esl/gproc/blob/master/doc/gproc_monitor.md" class="module">gproc_monitor</a></td></tr>
 <tr><td><a href="http://github.com/esl/gproc/blob/master/doc/gproc_sup.md" class="module">gproc_sup</a></td></tr></table>
 <tr><td><a href="http://github.com/esl/gproc/blob/master/doc/gproc_sup.md" class="module">gproc_sup</a></td></tr></table>
 
 

+ 9 - 18
doc/README.md

@@ -1,10 +1,7 @@
 
 
 
 
-<h1>The gproc application</h1>
+#The gproc application#
 
 
-The gproc application
-=====================
-Extended process dictionary.
 
 
 __Authors:__ Ulf Wiger ([`ulf.wiger@erlang-solutions.com`](mailto:ulf.wiger@erlang-solutions.com)), Joseph Wayne Norton ([`norton@geminimobile.com`](mailto:norton@geminimobile.com)).
 __Authors:__ Ulf Wiger ([`ulf.wiger@erlang-solutions.com`](mailto:ulf.wiger@erlang-solutions.com)), Joseph Wayne Norton ([`norton@geminimobile.com`](mailto:norton@geminimobile.com)).
 
 
@@ -12,8 +9,7 @@ Extended process dictionary
 
 
 
 
 
 
-<h2>Introduction</h2>
-
+##Introduction##
 
 
 
 
 
 
@@ -43,8 +39,7 @@ Gproc is a process dictionary for Erlang, which provides a number of useful feat
 
 
 
 
 
 
-<h3>Use case: System inspection</h3>
-
+###Use case: System inspection##
 
 
 
 
 
 
@@ -57,8 +52,7 @@ browse key data in a running system.
 
 
 
 
 
 
-<h3>Use case: Pub/Sub patterns</h3>
-
+###Use case: Pub/Sub patterns##
 
 
 
 
 
 
@@ -78,8 +72,7 @@ notify(EventType, Msg) ->
 
 
 
 
 
 
-<h3>Use case: Environment handling</h3>
-
+###Use case: Environment handling##
 
 
 
 
 
 
@@ -96,8 +89,7 @@ See [`gproc:get_env/4`](gproc.md#get_env-4), [`gproc:get_set_env/4`](gproc.md#ge
 
 
 
 
 
 
-<h2>Testing</h2>
-
+##Testing##
 
 
 
 
 
 
@@ -114,8 +106,7 @@ global gproc.
 
 
 
 
 
 
-<h2>Building Edoc</h2>
-
+##Building Edoc##
 
 
 
 
 
 
@@ -125,8 +116,7 @@ Gproc was first introduced at the ACM SIGPLAN Erlang Workshop in
 Freiburg 2007 ([Paper available here](erlang07-wiger.pdf)).
 Freiburg 2007 ([Paper available here](erlang07-wiger.pdf)).
 
 
 
 
-<h2 class="indextitle">Modules</h2>
-
+##Modules##
 
 
 
 
 <table width="100%" border="0" summary="list of modules">
 <table width="100%" border="0" summary="list of modules">
@@ -136,5 +126,6 @@ Freiburg 2007 ([Paper available here](erlang07-wiger.pdf)).
 <tr><td><a href="gproc_info.md" class="module">gproc_info</a></td></tr>
 <tr><td><a href="gproc_info.md" class="module">gproc_info</a></td></tr>
 <tr><td><a href="gproc_init.md" class="module">gproc_init</a></td></tr>
 <tr><td><a href="gproc_init.md" class="module">gproc_init</a></td></tr>
 <tr><td><a href="gproc_lib.md" class="module">gproc_lib</a></td></tr>
 <tr><td><a href="gproc_lib.md" class="module">gproc_lib</a></td></tr>
+<tr><td><a href="gproc_monitor.md" class="module">gproc_monitor</a></td></tr>
 <tr><td><a href="gproc_sup.md" class="module">gproc_sup</a></td></tr></table>
 <tr><td><a href="gproc_sup.md" class="module">gproc_sup</a></td></tr></table>
 
 

+ 1 - 1
doc/edoc-info

@@ -1,4 +1,4 @@
 {application,gproc}.
 {application,gproc}.
 {packages,[]}.
 {packages,[]}.
 {modules,[gproc,gproc_app,gproc_dist,gproc_info,gproc_init,gproc_lib,
 {modules,[gproc,gproc_app,gproc_dist,gproc_info,gproc_init,gproc_lib,
-          gproc_sup]}.
+          gproc_monitor,gproc_sup]}.

+ 208 - 244
doc/gproc.md

@@ -1,9 +1,6 @@
-Module gproc
-============
 
 
 
 
-<h1>Module gproc</h1>
-
+#Module gproc#
 * [Description](#description)
 * [Description](#description)
 * [Data Types](#types)
 * [Data Types](#types)
 * [Function Index](#index)
 * [Function Index](#index)
@@ -17,10 +14,9 @@ This module implements an extended process registry.
 
 
 __Behaviours:__ [`gen_server`](gen_server.md).
 __Behaviours:__ [`gen_server`](gen_server.md).
 
 
-__Authors:__ Ulf Wiger ([`ulf.wiger@erlang-consulting.com`](mailto:ulf.wiger@erlang-consulting.com)).
-
-<h2><a name="description">Description</a></h2>
+__Authors:__ Ulf Wiger ([`ulf.wiger@erlang-consulting.com`](mailto:ulf.wiger@erlang-consulting.com)).<a name="description"></a>
 
 
+##Description##
 
 
 
 
 
 
@@ -30,8 +26,7 @@ For a detailed description, see
 
 
 
 
 
 
-<h2>Tuning Gproc performance</h2>
-
+##Tuning Gproc performance##
 
 
 
 
 
 
@@ -50,75 +45,67 @@ starting the `gproc` and `gproc_dist` servers. Default is `[]`. It is
 likely that `{priority, high | max}` and/or increasing `min_heap_size`
 likely that `{priority, high | max}` and/or increasing `min_heap_size`
 will improve performance.
 will improve performance.
 
 
+<a name="types"></a>
 
 
-
-<h2><a name="types">Data Types</a></h2>
+##Data Types##
 
 
 
 
 
 
 
 
+###<a name="type-context">context()</a>##
 
 
-<h3 class="typedecl"><a name="type-context">context()</a></h3>
 
 
 
 
-
-
-<pre>context() = {<a href="#type-scope">scope()</a>, <a href="#type-type">type()</a>} | <a href="#type-type">type()</a></pre>
+<pre>context() = {[scope()](#type-scope), [type()](#type-type)} | [type()](#type-type)</pre>
 
 
 
 
 {'all','all'} is the default
 {'all','all'} is the default
 
 
 
 
 
 
-<h3 class="typedecl"><a name="type-headpat">headpat()</a></h3>
-
-
+###<a name="type-headpat">headpat()</a>##
 
 
 
 
-<pre>headpat() = {<a href="#type-keypat">keypat()</a>, <a href="#type-pidpat">pidpat()</a>, ValPat}</pre>
 
 
+<pre>headpat() = {[keypat()](#type-keypat), [pidpat()](#type-pidpat), ValPat}</pre>
 
 
 
 
-<h3 class="typedecl"><a name="type-key">key()</a></h3>
 
 
+###<a name="type-key">key()</a>##
 
 
 
 
 
 
-<pre>key() = {<a href="#type-type">type()</a>, <a href="#type-scope">scope()</a>, any()}</pre>
+<pre>key() = {[type()](#type-type), [scope()](#type-scope), any()}</pre>
 
 
 
 
 
 
-<h3 class="typedecl"><a name="type-keypat">keypat()</a></h3>
+###<a name="type-keypat">keypat()</a>##
 
 
 
 
 
 
+<pre>keypat() = {[sel_type()](#type-sel_type) | [sel_var()](#type-sel_var), l | g | [sel_var()](#type-sel_var), any()}</pre>
 
 
-<pre>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()}</pre>
 
 
 
 
+###<a name="type-pidpat">pidpat()</a>##
 
 
-<h3 class="typedecl"><a name="type-pidpat">pidpat()</a></h3>
 
 
 
 
-
-
-<pre>pidpat() = pid() | <a href="#type-sel_var">sel_var()</a></pre>
+<pre>pidpat() = pid() | [sel_var()](#type-sel_var)</pre>
 
 
 
 
 sel_var() = DollarVar | '_'.
 sel_var() = DollarVar | '_'.
 
 
 
 
-<h3 class="typedecl"><a name="type-reg_id">reg_id()</a></h3>
-
-
+###<a name="type-reg_id">reg_id()</a>##
 
 
 
 
-<pre>reg_id() = {<a href="#type-type">type()</a>, <a href="#type-scope">scope()</a>, any()}</pre>
 
 
+<pre>reg_id() = {[type()](#type-type), [scope()](#type-scope), any()}</pre>
 
 
 
 
-<h3 class="typedecl"><a name="type-scope">scope()</a></h3>
 
 
+###<a name="type-scope">scope()</a>##
 
 
 
 
 
 
@@ -129,17 +116,15 @@ l = local registration; g = global registration
 
 
 
 
 
 
-<h3 class="typedecl"><a name="type-sel_pattern">sel_pattern()</a></h3>
+###<a name="type-sel_pattern">sel_pattern()</a>##
 
 
 
 
 
 
+<pre>sel_pattern() = [{[headpat()](#type-headpat), Guards, Prod}]</pre>
 
 
-<pre>sel_pattern() = [{<a href="#type-headpat">headpat()</a>, Guards, Prod}]</pre>
 
 
 
 
-
-<h3 class="typedecl"><a name="type-sel_scope">sel_scope()</a></h3>
-
+###<a name="type-sel_scope">sel_scope()</a>##
 
 
 
 
 
 
@@ -147,17 +132,15 @@ l = local registration; g = global registration
 
 
 
 
 
 
-<h3 class="typedecl"><a name="type-sel_type">sel_type()</a></h3>
-
+###<a name="type-sel_type">sel_type()</a>##
 
 
 
 
 
 
-<pre>sel_type() = <a href="#type-type">type()</a> | names | props | counters | aggr_counters</pre>
+<pre>sel_type() = [type()](#type-type) | names | props | counters | aggr_counters</pre>
 
 
 
 
 
 
-<h3 class="typedecl"><a name="type-type">type()</a></h3>
-
+###<a name="type-type">type()</a>##
 
 
 
 
 
 
@@ -168,33 +151,32 @@ n = name; p = property; c = counter;
 a = aggregate_counter
 a = aggregate_counter
 
 
 
 
-<h3 class="typedecl"><a name="type-unique_id">unique_id()</a></h3>
-
-
-
+###<a name="type-unique_id">unique_id()</a>##
 
 
-<pre>unique_id() = {n | a, <a href="#type-scope">scope()</a>, any()}</pre>
 
 
 
 
-<h2><a name="index">Function Index</a></h2>
+<pre>unique_id() = {n | a, [scope()](#type-scope), any()}</pre>
+<a name="index"></a>
 
 
+##Function Index##
 
 
 
 
-<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="#add_shared_local_counter-2">add_shared_local_counter/2</a></td><td>Registers a local shared (unique) counter.</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>Read 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>Reads the value stored with a key registered to the current process.</td></tr><tr><td valign="top"><a href="#get_value-2">get_value/2</a></td><td>Reads the value stored with a key registered to the process Pid.</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="#goodbye-0">goodbye/0</a></td><td>Unregister all items of the calling process and inform gproc  
+<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="#add_shared_local_counter-2">add_shared_local_counter/2</a></td><td>Registers a local shared (unique) counter.</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="#demonitor-2">demonitor/2</a></td><td>Remove a monitor on a registered name
+This function is the reverse of monitor/1.</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>Read 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>Reads the value stored with a key registered to the current process.</td></tr><tr><td valign="top"><a href="#get_value-2">get_value/2</a></td><td>Reads the value stored with a key registered to the process Pid.</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="#goodbye-0">goodbye/0</a></td><td>Unregister all items of the calling process and inform gproc  
 to forget about the calling process.</td></tr><tr><td valign="top"><a href="#i-0">i/0</a></td><td>Similar to the built-in shell command <code>i()</code> but inserts information
 to forget about the calling process.</td></tr><tr><td valign="top"><a href="#i-0">i/0</a></td><td>Similar to the built-in shell command <code>i()</code> but inserts information
-about names and properties registered in Gproc, where applicable.</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="#reg_shared-1">reg_shared/1</a></td><td>Register a resource, but don't tie it to a particular process.</td></tr><tr><td valign="top"><a href="#reg_shared-2">reg_shared/2</a></td><td>Register a resource, but don't tie it to a particular process.</td></tr><tr><td valign="top"><a href="#reset_counter-1">reset_counter/1</a></td><td>Reads and resets a counter in a "thread-safe" way.</td></tr><tr><td valign="top"><a href="#select-1">select/1</a></td><td>
+about names and properties registered in Gproc, where applicable.</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="#monitor-1">monitor/1</a></td><td>monitor a registered name
+This function works much like erlang:monitor(process, Pid), but monitors
+a unique name registered via gproc.</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="#reg_shared-1">reg_shared/1</a></td><td>Register a resource, but don't tie it to a particular process.</td></tr><tr><td valign="top"><a href="#reg_shared-2">reg_shared/2</a></td><td>Register a resource, but don't tie it to a particular process.</td></tr><tr><td valign="top"><a href="#register_name-2">register_name/2</a></td><td>Behaviour support callback.</td></tr><tr><td valign="top"><a href="#reset_counter-1">reset_counter/1</a></td><td>Reads and resets a counter in a "thread-safe" way.</td></tr><tr><td valign="top"><a href="#select-1">select/1</a></td><td>
 see http://www.erlang.org/doc/man/ets.html#select-1.</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="#select_count-1">select_count/1</a></td><td>Equivalent to <a href="#select_count-2"><tt>select_count(all, Pat)</tt></a>.</td></tr><tr><td valign="top"><a href="#select_count-2">select_count/2</a></td><td>Perform a select_count operation on the process registry.</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-0">table/0</a></td><td>Equivalent to <a href="#table-1"><tt>table({all, all})</tt></a>.</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="#unreg_shared-1">unreg_shared/1</a></td><td>Unregister a shared resource.</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="#update_shared_counter-2">update_shared_counter/2</a></td><td></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>
 see http://www.erlang.org/doc/man/ets.html#select-1.</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="#select_count-1">select_count/1</a></td><td>Equivalent to <a href="#select_count-2"><tt>select_count(all, Pat)</tt></a>.</td></tr><tr><td valign="top"><a href="#select_count-2">select_count/2</a></td><td>Perform a select_count operation on the process registry.</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-0">table/0</a></td><td>Equivalent to <a href="#table-1"><tt>table({all, all})</tt></a>.</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="#unreg_shared-1">unreg_shared/1</a></td><td>Unregister a shared resource.</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="#update_shared_counter-2">update_shared_counter/2</a></td><td></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><a name="functions">Function Details</a></h2>
-
+##Function Details##
 
 
 <a name="add_global_aggr_counter-1"></a>
 <a name="add_global_aggr_counter-1"></a>
 
 
-<h3>add_global_aggr_counter/1</h3>
-
+###add_global_aggr_counter/1##
 
 
 
 
 
 
@@ -207,8 +189,7 @@ 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>
-
+###add_global_counter/2##
 
 
 
 
 
 
@@ -219,8 +200,7 @@ Registers a global (unique) aggregated counter.<a name="add_global_counter-2"></
 
 
 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>
-
+###add_global_name/1##
 
 
 
 
 
 
@@ -231,8 +211,7 @@ Registers a global (non-unique) counter. @equiv reg({c,g,Name},Value)<a name="ad
 
 
 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>
-
+###add_global_property/2##
 
 
 
 
 
 
@@ -243,8 +222,7 @@ Registers a global (unique) name. @equiv reg({n,g,Name})<a name="add_global_prop
 
 
 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>
-
+###add_local_aggr_counter/1##
 
 
 
 
 
 
@@ -257,8 +235,7 @@ 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>
-
+###add_local_counter/2##
 
 
 
 
 
 
@@ -269,8 +246,7 @@ Registers a local (unique) aggregated counter.<a name="add_local_counter-2"></a>
 
 
 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>
-
+###add_local_name/1##
 
 
 
 
 
 
@@ -281,8 +257,7 @@ Registers a local (non-unique) counter. @equiv reg({c,l,Name},Value)<a name="add
 
 
 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>
-
+###add_local_property/2##
 
 
 
 
 
 
@@ -293,8 +268,7 @@ Registers a local (unique) name. @equiv reg({n,l,Name})<a name="add_local_proper
 
 
 Registers a local (non-unique) property. @equiv reg({p,l,Name},Value)<a name="add_shared_local_counter-2"></a>
 Registers a local (non-unique) property. @equiv reg({p,l,Name},Value)<a name="add_shared_local_counter-2"></a>
 
 
-<h3>add_shared_local_counter/2</h3>
-
+###add_shared_local_counter/2##
 
 
 
 
 
 
@@ -307,25 +281,23 @@ Equivalent to [`reg_shared({c, l, Name}, Value)`](#reg_shared-2).
 
 
 Registers a local shared (unique) counter.<a name="audit_process-1"></a>
 Registers a local shared (unique) counter.<a name="audit_process-1"></a>
 
 
-<h3>audit_process/1</h3>
-
+###audit_process/1##
 
 
 
 
 
 
 
 
-<pre>audit_process(Pid::pid()) -> ok</pre>
+<pre>audit_process(Pid::pid()) -&gt; ok</pre>
 <br></br>
 <br></br>
 
 
 
 
 <a name="await-1"></a>
 <a name="await-1"></a>
 
 
-<h3>await/1</h3>
+###await/1##
 
 
 
 
 
 
 
 
-
-<pre>await(Key::<a href="#type-key">key()</a>) -> {pid(), Value}</pre>
+<pre>await(Key::[key()](#type-key)) -&gt; {pid(), Value}</pre>
 <br></br>
 <br></br>
 
 
 
 
@@ -333,13 +305,12 @@ Registers a local shared (unique) counter.<a name="audit_process-1"></a>
 
 
 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>
-
+###await/2##
 
 
 
 
 
 
 
 
-<pre>await(Key::<a href="#type-key">key()</a>, Timeout) -> {pid(), Value}</pre>
+<pre>await(Key::[key()](#type-key), Timeout) -&gt; {pid(), Value}</pre>
 <ul class="definitions"><li><pre>Timeout = integer() | infinity</pre></li></ul>
 <ul class="definitions"><li><pre>Timeout = integer() | infinity</pre></li></ul>
 
 
 
 
@@ -352,8 +323,7 @@ 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>
-
+###cancel_wait/2##
 
 
 
 
 
 
@@ -362,23 +332,36 @@ registered (the difference: await/2 also returns the value).<a name="cancel_wait
 
 
 <a name="default-1"></a>
 <a name="default-1"></a>
 
 
-<h3>default/1</h3>
-
+###default/1##
 
 
 
 
 
 
 
 
 `default(X1) -> any()`
 `default(X1) -> any()`
 
 
-<a name="first-1"></a>
+<a name="demonitor-2"></a>
+
+###demonitor/2##
+
+
+
+
+<pre>demonitor(Key::[key()](#type-key), Ref::reference()) -&gt; ok</pre>
+<br></br>
+
+
+
 
 
-<h3>first/1</h3>
+Remove a monitor on a registered name
+This function is the reverse of monitor/1. It removes a monitor previously
+set on a unique name. This function always succeeds given legal input.<a name="first-1"></a>
 
 
+###first/1##
 
 
 
 
 
 
 
 
-<pre>first(Context::<a href="#type-context">context()</a>) -> <a href="#type-key">key()</a> | '$end_of_table'</pre>
+<pre>first(Context::[context()](#type-context)) -&gt; [key()](#type-key) | '$end_of_table'</pre>
 <br></br>
 <br></br>
 
 
 
 
@@ -391,13 +374,12 @@ 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_env-3"></a>
 The registry behaves as an ordered_set table.<a name="get_env-3"></a>
 
 
-<h3>get_env/3</h3>
+###get_env/3##
 
 
 
 
 
 
 
 
-
-<pre>get_env(Scope::<a href="#type-scope">scope()</a>, App::atom(), Key::atom()) -> term()</pre>
+<pre>get_env(Scope::[scope()](#type-scope), App::atom(), Key::atom()) -&gt; term()</pre>
 <br></br>
 <br></br>
 
 
 
 
@@ -405,14 +387,13 @@ The registry behaves as an ordered_set table.<a name="get_env-3"></a>
 
 
 Equivalent to [`get_env(Scope, App, Key, [app_env])`](#get_env-4).<a name="get_env-4"></a>
 Equivalent to [`get_env(Scope, App, Key, [app_env])`](#get_env-4).<a name="get_env-4"></a>
 
 
-<h3>get_env/4</h3>
-
+###get_env/4##
 
 
 
 
 
 
 
 
-<pre>get_env(Scope::<a href="#type-scope">scope()</a>, App::atom(), Key::atom(), Strategy) -> term()</pre>
-<ul class="definitions"><li><pre>Strategy = [Alternative]</pre></li><li><pre>Alternative = app_env | os_env | inherit | {inherit, pid()} | {inherit, <a href="#type-unique_id">unique_id()</a>} | init_arg | {mnesia, ActivityType, Oid, Pos} | {default, term()} | error</pre></li></ul>
+<pre>get_env(Scope::[scope()](#type-scope), App::atom(), Key::atom(), Strategy) -&gt; term()</pre>
+<ul class="definitions"><li><pre>Strategy = [Alternative]</pre></li><li><pre>Alternative = app_env | os_env | inherit | {inherit, pid()} | {inherit, &lt;a href="#type-unique_id"&gt;unique_id()&lt;/a&gt;} | init_arg | {mnesia, ActivityType, Oid, Pos} | {default, term()} | error</pre></li></ul>
 
 
 
 
 
 
@@ -466,13 +447,12 @@ cached. Alternatively, it can be used to assert that a value is either cached
 or at least defined somewhere,
 or at least defined somewhere,
 e.g. `get_env(l, mnesia, dir, [app_env, error])`.<a name="get_set_env-3"></a>
 e.g. `get_env(l, mnesia, dir, [app_env, error])`.<a name="get_set_env-3"></a>
 
 
-<h3>get_set_env/3</h3>
+###get_set_env/3##
 
 
 
 
 
 
 
 
-
-<pre>get_set_env(Scope::<a href="#type-scope">scope()</a>, App::atom(), Key::atom()) -> term()</pre>
+<pre>get_set_env(Scope::[scope()](#type-scope), App::atom(), Key::atom()) -&gt; term()</pre>
 <br></br>
 <br></br>
 
 
 
 
@@ -480,13 +460,12 @@ e.g. `get_env(l, mnesia, dir, [app_env, error])`.<a name="get_set_env-3"></a>
 
 
 Equivalent to [`get_set_env(Scope, App, Key, [app_env])`](#get_set_env-4).<a name="get_set_env-4"></a>
 Equivalent to [`get_set_env(Scope, App, Key, [app_env])`](#get_set_env-4).<a name="get_set_env-4"></a>
 
 
-<h3>get_set_env/4</h3>
-
+###get_set_env/4##
 
 
 
 
 
 
 
 
-<pre>get_set_env(Scope::<a href="#type-scope">scope()</a>, App::atom(), Key::atom(), Strategy) -> Value</pre>
+<pre>get_set_env(Scope::[scope()](#type-scope), App::atom(), Key::atom(), Strategy) -&gt; Value</pre>
 <br></br>
 <br></br>
 
 
 
 
@@ -503,13 +482,12 @@ is `undefined`.
 
 
 __See also:__ [get_env/4](#get_env-4).<a name="get_value-1"></a>
 __See also:__ [get_env/4](#get_env-4).<a name="get_value-1"></a>
 
 
-<h3>get_value/1</h3>
+###get_value/1##
 
 
 
 
 
 
 
 
-
-<pre>get_value(Key) -> Value</pre>
+<pre>get_value(Key) -&gt; Value</pre>
 <br></br>
 <br></br>
 
 
 
 
@@ -521,13 +499,12 @@ Reads 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="get_value-2"></a>
 If no such key is registered to the current process, this function exits.<a name="get_value-2"></a>
 
 
-<h3>get_value/2</h3>
-
+###get_value/2##
 
 
 
 
 
 
 
 
-<pre>get_value(Key, Pid) -> Value</pre>
+<pre>get_value(Key, Pid) -&gt; Value</pre>
 <br></br>
 <br></br>
 
 
 
 
@@ -540,13 +517,12 @@ Reads the value stored with a key registered to the process Pid.
 If `Pid == shared`, the value of a shared key (see [`reg_shared/1`](#reg_shared-1))
 If `Pid == shared`, the value of a shared key (see [`reg_shared/1`](#reg_shared-1))
 will be read.<a name="give_away-2"></a>
 will be read.<a name="give_away-2"></a>
 
 
-<h3>give_away/2</h3>
-
+###give_away/2##
 
 
 
 
 
 
 
 
-<pre>give_away(From::<a href="#type-key">key()</a>, To::pid() | <a href="#type-key">key()</a>) -> undefined | pid()</pre>
+<pre>give_away(From::[key()](#type-key), To::pid() | [key()](#type-key)) -&gt; undefined | pid()</pre>
 <br></br>
 <br></br>
 
 
 
 
@@ -576,13 +552,12 @@ will have no effect.
 Fails with `badarg` if the calling process does not have a `From` key
 Fails with `badarg` if the calling process does not have a `From` key
 registered.<a name="goodbye-0"></a>
 registered.<a name="goodbye-0"></a>
 
 
-<h3>goodbye/0</h3>
+###goodbye/0##
 
 
 
 
 
 
 
 
-
-<pre>goodbye() -> ok</pre>
+<pre>goodbye() -&gt; ok</pre>
 <br></br>
 <br></br>
 
 
 
 
@@ -596,13 +571,12 @@ to forget about the calling process.
 This function is more efficient than letting gproc perform these
 This function is more efficient than letting gproc perform these
 cleanup operations.<a name="i-0"></a>
 cleanup operations.<a name="i-0"></a>
 
 
-<h3>i/0</h3>
-
+###i/0##
 
 
 
 
 
 
 
 
-<pre>i() -> ok</pre>
+<pre>i() -&gt; ok</pre>
 <br></br>
 <br></br>
 
 
 
 
@@ -611,13 +585,12 @@ cleanup operations.<a name="i-0"></a>
 Similar to the built-in shell command `i()` but inserts information
 Similar to the built-in shell command `i()` but inserts information
 about names and properties registered in Gproc, where applicable.<a name="info-1"></a>
 about names and properties registered in Gproc, where applicable.<a name="info-1"></a>
 
 
-<h3>info/1</h3>
+###info/1##
 
 
 
 
 
 
 
 
-
-<pre>info(Pid::pid()) -> ProcessInfo</pre>
+<pre>info(Pid::pid()) -&gt; ProcessInfo</pre>
 <ul class="definitions"><li><pre>ProcessInfo = [{gproc, [{Key, Value}]} | ProcessInfo]</pre></li></ul>
 <ul class="definitions"><li><pre>ProcessInfo = [{gproc, [{Key, Value}]} | ProcessInfo]</pre></li></ul>
 
 
 
 
@@ -630,13 +603,12 @@ 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>
-
+###info/2##
 
 
 
 
 
 
 
 
-<pre>info(Pid::pid(), Item::atom()) -> {Item, Info}</pre>
+<pre>info(Pid::pid(), Item::atom()) -&gt; {Item, Info}</pre>
 <br></br>
 <br></br>
 
 
 
 
@@ -650,13 +622,12 @@ 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>
+###last/1##
 
 
 
 
 
 
 
 
-
-<pre>last(Context::<a href="#type-context">context()</a>) -> <a href="#type-key">key()</a> | '$end_of_table'</pre>
+<pre>last(Context::[context()](#type-context)) -&gt; [key()](#type-key) | '$end_of_table'</pre>
 <br></br>
 <br></br>
 
 
 
 
@@ -669,13 +640,12 @@ 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>
-
+###lookup_global_aggr_counter/1##
 
 
 
 
 
 
 
 
-<pre>lookup_global_aggr_counter(Name::any()) -> integer()</pre>
+<pre>lookup_global_aggr_counter(Name::any()) -&gt; integer()</pre>
 <br></br>
 <br></br>
 
 
 
 
@@ -686,13 +656,12 @@ 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>
-
+###lookup_global_counters/1##
 
 
 
 
 
 
 
 
-<pre>lookup_global_counters(Counter::any()) -> [{pid(), Value::integer()}]</pre>
+<pre>lookup_global_counters(Counter::any()) -&gt; [{pid(), Value::integer()}]</pre>
 <br></br>
 <br></br>
 
 
 
 
@@ -703,13 +672,12 @@ 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>
+###lookup_global_name/1##
 
 
 
 
 
 
 
 
-
-<pre>lookup_global_name(Name::any()) -> pid()</pre>
+<pre>lookup_global_name(Name::any()) -&gt; pid()</pre>
 <br></br>
 <br></br>
 
 
 
 
@@ -719,13 +687,12 @@ 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>
 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>
-
+###lookup_global_properties/1##
 
 
 
 
 
 
 
 
-<pre>lookup_global_properties(Property::any()) -> [{pid(), Value}]</pre>
+<pre>lookup_global_properties(Property::any()) -&gt; [{pid(), Value}]</pre>
 <br></br>
 <br></br>
 
 
 
 
@@ -736,13 +703,12 @@ 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>
+###lookup_local_aggr_counter/1##
 
 
 
 
 
 
 
 
-
-<pre>lookup_local_aggr_counter(Name::any()) -> integer()</pre>
+<pre>lookup_local_aggr_counter(Name::any()) -&gt; integer()</pre>
 <br></br>
 <br></br>
 
 
 
 
@@ -753,13 +719,12 @@ 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>
-
+###lookup_local_counters/1##
 
 
 
 
 
 
 
 
-<pre>lookup_local_counters(Counter::any()) -> [{pid(), Value::integer()}]</pre>
+<pre>lookup_local_counters(Counter::any()) -&gt; [{pid(), Value::integer()}]</pre>
 <br></br>
 <br></br>
 
 
 
 
@@ -770,13 +735,12 @@ 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>
+###lookup_local_name/1##
 
 
 
 
 
 
 
 
-
-<pre>lookup_local_name(Name::any()) -> pid()</pre>
+<pre>lookup_local_name(Name::any()) -&gt; pid()</pre>
 <br></br>
 <br></br>
 
 
 
 
@@ -786,13 +750,12 @@ 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>
 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>
-
+###lookup_local_properties/1##
 
 
 
 
 
 
 
 
-<pre>lookup_local_properties(Property::any()) -> [{pid(), Value}]</pre>
+<pre>lookup_local_properties(Property::any()) -&gt; [{pid(), Value}]</pre>
 <br></br>
 <br></br>
 
 
 
 
@@ -803,13 +766,12 @@ 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>
+###lookup_pid/1##
 
 
 
 
 
 
 
 
-
-<pre>lookup_pid(Key) -> Pid</pre>
+<pre>lookup_pid(Key) -&gt; Pid</pre>
 <br></br>
 <br></br>
 
 
 
 
@@ -818,13 +780,12 @@ Returns a list of {Pid, Value} tuples for all matching objects.<a name="lookup_p
 Lookup the Pid stored with a key.
 Lookup the Pid stored with a key.
 <a name="lookup_pids-1"></a>
 <a name="lookup_pids-1"></a>
 
 
-<h3>lookup_pids/1</h3>
-
+###lookup_pids/1##
 
 
 
 
 
 
 
 
-<pre>lookup_pids(Key::<a href="#type-key">key()</a>) -> [pid()]</pre>
+<pre>lookup_pids(Key::[key()](#type-key)) -&gt; [pid()]</pre>
 <br></br>
 <br></br>
 
 
 
 
@@ -838,13 +799,12 @@ 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>
+###lookup_value/1##
 
 
 
 
 
 
 
 
-
-<pre>lookup_value(Key) -> Value</pre>
+<pre>lookup_value(Key) -&gt; Value</pre>
 <br></br>
 <br></br>
 
 
 
 
@@ -853,13 +813,12 @@ For non-unique types, the return value can be a list of any length.<a name="look
 Lookup the value stored with a key.
 Lookup the value stored with a key.
 <a name="lookup_values-1"></a>
 <a name="lookup_values-1"></a>
 
 
-<h3>lookup_values/1</h3>
-
+###lookup_values/1##
 
 
 
 
 
 
 
 
-<pre>lookup_values(Key::<a href="#type-key">key()</a>) -> [{pid(), Value}]</pre>
+<pre>lookup_values(Key::[key()](#type-key)) -&gt; [{pid(), Value}]</pre>
 <br></br>
 <br></br>
 
 
 
 
@@ -871,15 +830,35 @@ 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="monitor-1"></a>
+
+###monitor/1##
+
 
 
-<h3>mreg/3</h3>
+
+
+<pre>monitor(Key::[key()](#type-key)) -&gt; reference()</pre>
+<br></br>
 
 
 
 
 
 
 
 
 
 
-<pre>mreg(T::<a href="#type-type">type()</a>, X2::<a href="#type-scope">scope()</a>, KVL::[{Key::any(), Value::any()}]) -> true</pre>
+
+monitor a registered name
+This function works much like erlang:monitor(process, Pid), but monitors
+a unique name registered via gproc. A message, `{gproc, unreg, Ref, Key}`  
+will be sent to the requesting process, if the name is unregistered or  
+the registered process dies.
+
+If the name is not yet registered, the same message is sent immediately.<a name="mreg-3"></a>
+
+###mreg/3##
+
+
+
+
+<pre>mreg(T::[type()](#type-type), X2::[scope()](#type-scope), KVL::[{Key::any(), Value::any()}]) -&gt; true</pre>
 <br></br>
 <br></br>
 
 
 
 
@@ -893,13 +872,12 @@ This function is more efficient than calling [`reg/2`](#reg-2) repeatedly.
 It is also atomic in regard to unique names; either all names are registered
 It is also atomic in regard to unique names; either all names are registered
 or none are.<a name="munreg-3"></a>
 or none are.<a name="munreg-3"></a>
 
 
-<h3>munreg/3</h3>
+###munreg/3##
 
 
 
 
 
 
 
 
-
-<pre>munreg(T::<a href="#type-type">type()</a>, X2::<a href="#type-scope">scope()</a>, L::[Key::any()]) -> true</pre>
+<pre>munreg(T::[type()](#type-type), X2::[scope()](#type-scope), L::[Key::any()]) -&gt; true</pre>
 <br></br>
 <br></br>
 
 
 
 
@@ -912,13 +890,12 @@ Unregister multiple Key items of a given type and scope.
 This function is usually more efficient than calling [`unreg/1`](#unreg-1)
 This function is usually more efficient than calling [`unreg/1`](#unreg-1)
 repeatedly.<a name="nb_wait-1"></a>
 repeatedly.<a name="nb_wait-1"></a>
 
 
-<h3>nb_wait/1</h3>
-
+###nb_wait/1##
 
 
 
 
 
 
 
 
-<pre>nb_wait(Key::<a href="#type-key">key()</a>) -> Ref</pre>
+<pre>nb_wait(Key::[key()](#type-key)) -&gt; Ref</pre>
 <br></br>
 <br></br>
 
 
 
 
@@ -928,13 +905,12 @@ 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>
+###next/2##
 
 
 
 
 
 
 
 
-
-<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>
+<pre>next(Context::[context()](#type-context), Key::[key()](#type-key)) -&gt; [key()](#type-key) | '$end_of_table'</pre>
 <br></br>
 <br></br>
 
 
 
 
@@ -947,13 +923,12 @@ 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>
-
+###prev/2##
 
 
 
 
 
 
 
 
-<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>
+<pre>prev(Context::[context()](#type-context), Key::[key()](#type-key)) -&gt; [key()](#type-key) | '$end_of_table'</pre>
 <br></br>
 <br></br>
 
 
 
 
@@ -966,13 +941,12 @@ 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>
+###reg/1##
 
 
 
 
 
 
 
 
-
-<pre>reg(Key::<a href="#type-key">key()</a>) -> true</pre>
+<pre>reg(Key::[key()](#type-key)) -&gt; true</pre>
 <br></br>
 <br></br>
 
 
 
 
@@ -980,13 +954,12 @@ The registry behaves as an ordered_set table.<a name="reg-1"></a>
 
 
 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>
-
+###reg/2##
 
 
 
 
 
 
 
 
-<pre>reg(Key::<a href="#type-key">key()</a>, Value) -> true</pre>
+<pre>reg(Key::[key()](#type-key), Value) -&gt; true</pre>
 <br></br>
 <br></br>
 
 
 
 
@@ -998,13 +971,12 @@ Register a name or property for the current process
 
 
 <a name="reg_shared-1"></a>
 <a name="reg_shared-1"></a>
 
 
-<h3>reg_shared/1</h3>
-
+###reg_shared/1##
 
 
 
 
 
 
 
 
-<pre>reg_shared(Key::<a href="#type-key">key()</a>) -> true</pre>
+<pre>reg_shared(Key::[key()](#type-key)) -&gt; true</pre>
 <br></br>
 <br></br>
 
 
 
 
@@ -1017,13 +989,12 @@ Register a resource, but don't tie it to a particular process.
 `reg_shared({c,l,C}) -> reg_shared({c,l,C}, 0).`
 `reg_shared({c,l,C}) -> reg_shared({c,l,C}, 0).`
 `reg_shared({a,l,A}) -> reg_shared({a,l,A}, undefined).`<a name="reg_shared-2"></a>
 `reg_shared({a,l,A}) -> reg_shared({a,l,A}, undefined).`<a name="reg_shared-2"></a>
 
 
-<h3>reg_shared/2</h3>
+###reg_shared/2##
 
 
 
 
 
 
 
 
-
-<pre>reg_shared(Key::<a href="#type-key">key()</a>, Value) -> true</pre>
+<pre>reg_shared(Key::[key()](#type-key), Value) -&gt; true</pre>
 <br></br>
 <br></br>
 
 
 
 
@@ -1043,15 +1014,27 @@ results, shared resources appear as other similar resources, except that
 increment the shared counter `myCounter` with 1, provided it exists.
 increment the shared counter `myCounter` with 1, provided it exists.
 
 
 A shared aggregated counter will track updates in exactly the same way as
 A shared aggregated counter will track updates in exactly the same way as
-an aggregated counter which is owned by a process.<a name="reset_counter-1"></a>
+an aggregated counter which is owned by a process.<a name="register_name-2"></a>
+
+###register_name/2##
+
+
+
+
+<pre>register_name(Name::[key()](#type-key), Pid::pid()) -&gt; yes | no</pre>
+<br></br>
+
 
 
-<h3>reset_counter/1</h3>
 
 
 
 
+Behaviour support callback<a name="reset_counter-1"></a>
 
 
+###reset_counter/1##
 
 
 
 
-<pre>reset_counter(Key) -> {ValueBefore, ValueAfter}</pre>
+
+
+<pre>reset_counter(Key) -&gt; {ValueBefore, ValueAfter}</pre>
 <ul class="definitions"><li><pre>Key = {c, Scope, Name}</pre></li><li><pre>Scope = l | g</pre></li><li><pre>ValueBefore = integer()</pre></li><li><pre>ValueAfter = integer()</pre></li></ul>
 <ul class="definitions"><li><pre>Key = {c, Scope, Name}</pre></li><li><pre>Scope = l | g</pre></li><li><pre>ValueBefore = integer()</pre></li><li><pre>ValueAfter = integer()</pre></li></ul>
 
 
 
 
@@ -1065,13 +1048,12 @@ initial value. The reset operation is done using [`update_counter/2`](#update_co
 which allows for concurrent calls to [`update_counter/2`](#update_counter-2) without losing
 which allows for concurrent calls to [`update_counter/2`](#update_counter-2) without losing
 updates. Aggregated counters are updated accordingly.<a name="select-1"></a>
 updates. Aggregated counters are updated accordingly.<a name="select-1"></a>
 
 
-<h3>select/1</h3>
+###select/1##
 
 
 
 
 
 
 
 
-
-<pre>select(Continuation::term()) -> {[Match], Continuation} | '$end_of_table'</pre>
+<pre>select(Continuation::term()) -&gt; {[Match], Continuation} | '$end_of_table'</pre>
 <br></br>
 <br></br>
 
 
 
 
@@ -1080,13 +1062,12 @@ updates. Aggregated counters are updated accordingly.<a name="select-1"></a>
 
 
 see http://www.erlang.org/doc/man/ets.html#select-1<a name="select-2"></a>
 see http://www.erlang.org/doc/man/ets.html#select-1<a name="select-2"></a>
 
 
-<h3>select/2</h3>
-
+###select/2##
 
 
 
 
 
 
 
 
-<pre>select(Context::<a href="#type-context">context()</a>, Pat::<a href="#type-sel_pattern">sel_pattern()</a>) -> [{Key, Pid, Value}]</pre>
+<pre>select(Context::[context()](#type-context), Pat::[sel_pattern()](#type-sel_pattern)) -&gt; [{Key, Pid, Value}]</pre>
 <br></br>
 <br></br>
 
 
 
 
@@ -1099,13 +1080,12 @@ 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>
+###select/3##
 
 
 
 
 
 
 
 
-
-<pre>select(Context::<a href="#type-context">context()</a>, Pat::<a href="#type-sel_patten">sel_patten()</a>, Limit::integer()) -> {[Match], Continuation} | '$end_of_table'</pre>
+<pre>select(Context::[context()](#type-context), Pat::[sel_patten()](#type-sel_patten), Limit::integer()) -&gt; {[Match], Continuation} | '$end_of_table'</pre>
 <br></br>
 <br></br>
 
 
 
 
@@ -1117,13 +1097,12 @@ 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="select_count-1"></a>
 See [`http://www.erlang.org/doc/man/ets.html#select-3`](http://www.erlang.org/doc/man/ets.html#select-3).<a name="select_count-1"></a>
 
 
-<h3>select_count/1</h3>
-
+###select_count/1##
 
 
 
 
 
 
 
 
-<pre>select_count(Pat::<a href="#type-select_pattern">select_pattern()</a>) -> [<a href="#type-sel_object">sel_object()</a>]</pre>
+<pre>select_count(Pat::[select_pattern()](#type-select_pattern)) -&gt; [[sel_object()](#type-sel_object)]</pre>
 <br></br>
 <br></br>
 
 
 
 
@@ -1131,13 +1110,12 @@ See [`http://www.erlang.org/doc/man/ets.html#select-3`](http://www.erlang.org/do
 
 
 Equivalent to [`select_count(all, Pat)`](#select_count-2).<a name="select_count-2"></a>
 Equivalent to [`select_count(all, Pat)`](#select_count-2).<a name="select_count-2"></a>
 
 
-<h3>select_count/2</h3>
-
+###select_count/2##
 
 
 
 
 
 
 
 
-<pre>select_count(Context::<a href="#type-context">context()</a>, Pat::<a href="#type-sel_pattern">sel_pattern()</a>) -> [{Key, Pid, Value}]</pre>
+<pre>select_count(Context::[context()](#type-context), Pat::[sel_pattern()](#type-sel_pattern)) -&gt; [{Key, Pid, Value}]</pre>
 <br></br>
 <br></br>
 
 
 
 
@@ -1150,13 +1128,12 @@ Perform a select_count 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="send-2"></a>
 but the select patterns are transformed appropriately.<a name="send-2"></a>
 
 
-<h3>send/2</h3>
+###send/2##
 
 
 
 
 
 
 
 
-
-<pre>send(Key::<a href="#type-key">key()</a>, Msg::any()) -> Msg</pre>
+<pre>send(Key::[key()](#type-key), Msg::any()) -&gt; Msg</pre>
 <br></br>
 <br></br>
 
 
 
 
@@ -1171,13 +1148,12 @@ 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_env-5"></a>
 property), Msg will be send to all processes that have such an object.<a name="set_env-5"></a>
 
 
-<h3>set_env/5</h3>
-
+###set_env/5##
 
 
 
 
 
 
 
 
-<pre>set_env(Scope::<a href="#type-scope">scope()</a>, App::atom(), Key::atom(), Value::term(), Strategy) -> Value</pre>
+<pre>set_env(Scope::[scope()](#type-scope), App::atom(), Key::atom(), Value::term(), Strategy) -&gt; Value</pre>
 <ul class="definitions"><li><pre>Strategy = [Alternative]</pre></li><li><pre>Alternative = app_env | os_env | {os_env, VAR} | {mnesia, ActivityType, Oid, Pos}</pre></li></ul>
 <ul class="definitions"><li><pre>Strategy = [Alternative]</pre></li><li><pre>Alternative = app_env | os_env | {os_env, VAR} | {mnesia, ActivityType, Oid, Pos}</pre></li></ul>
 
 
 
 
@@ -1198,13 +1174,12 @@ object, changing only the `Pos` position. If no such object exists, it will
 create a new object, setting any other attributes (except `Pos` and the key)
 create a new object, setting any other attributes (except `Pos` and the key)
 to `undefined`.<a name="set_value-2"></a>
 to `undefined`.<a name="set_value-2"></a>
 
 
-<h3>set_value/2</h3>
+###set_value/2##
 
 
 
 
 
 
 
 
-
-<pre>set_value(Key::<a href="#type-key">key()</a>, Value) -> true</pre>
+<pre>set_value(Key::[key()](#type-key), Value) -&gt; true</pre>
 <br></br>
 <br></br>
 
 
 
 
@@ -1222,13 +1197,12 @@ 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>
-
+###start_link/0##
 
 
 
 
 
 
 
 
-<pre>start_link() -> {ok, pid()}</pre>
+<pre>start_link() -&gt; {ok, pid()}</pre>
 <br></br>
 <br></br>
 
 
 
 
@@ -1241,13 +1215,12 @@ 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-0"></a>
 starting the gproc application.<a name="table-0"></a>
 
 
-<h3>table/0</h3>
+###table/0##
 
 
 
 
 
 
 
 
-
-<pre>table() -> any()</pre>
+<pre>table() -&gt; any()</pre>
 <br></br>
 <br></br>
 
 
 
 
@@ -1255,13 +1228,12 @@ starting the gproc application.<a name="table-0"></a>
 
 
 Equivalent to [`table({all, all})`](#table-1).<a name="table-1"></a>
 Equivalent to [`table({all, all})`](#table-1).<a name="table-1"></a>
 
 
-<h3>table/1</h3>
-
+###table/1##
 
 
 
 
 
 
 
 
-<pre>table(Context::<a href="#type-context">context()</a>) -> any()</pre>
+<pre>table(Context::[context()](#type-context)) -&gt; any()</pre>
 <br></br>
 <br></br>
 
 
 
 
@@ -1269,13 +1241,12 @@ Equivalent to [`table({all, all})`](#table-1).<a name="table-1"></a>
 
 
 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>
-
+###table/2##
 
 
 
 
 
 
 
 
-<pre>table(Context::<a href="#type-context">context()</a>, Opts) -> any()</pre>
+<pre>table(Context::[context()](#type-context), Opts) -&gt; any()</pre>
 <br></br>
 <br></br>
 
 
 
 
@@ -1285,13 +1256,12 @@ 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>
+###unreg/1##
 
 
 
 
 
 
 
 
-
-<pre>unreg(Key::<a href="#type-key">key()</a>) -> true</pre>
+<pre>unreg(Key::[key()](#type-key)) -&gt; true</pre>
 <br></br>
 <br></br>
 
 
 
 
@@ -1299,13 +1269,12 @@ See [`http://www.erlang.org/doc/man/qlc.html`](http://www.erlang.org/doc/man/qlc
 
 
 Unregister a name or property.<a name="unreg_shared-1"></a>
 Unregister a name or property.<a name="unreg_shared-1"></a>
 
 
-<h3>unreg_shared/1</h3>
-
+###unreg_shared/1##
 
 
 
 
 
 
 
 
-<pre>unreg_shared(Key::<a href="#type-key">key()</a>) -> true</pre>
+<pre>unreg_shared(Key::[key()](#type-key)) -&gt; true</pre>
 <br></br>
 <br></br>
 
 
 
 
@@ -1313,8 +1282,7 @@ Unregister a name or property.<a name="unreg_shared-1"></a>
 
 
 Unregister a shared resource.<a name="unregister_name-1"></a>
 Unregister a shared resource.<a name="unregister_name-1"></a>
 
 
-<h3>unregister_name/1</h3>
-
+###unregister_name/1##
 
 
 
 
 
 
@@ -1325,13 +1293,12 @@ Unregister a shared resource.<a name="unregister_name-1"></a>
 
 
 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>
-
+###update_counter/2##
 
 
 
 
 
 
 
 
-<pre>update_counter(Key::<a href="#type-key">key()</a>, Incr::integer()) -> integer()</pre>
+<pre>update_counter(Key::[key()](#type-key), Incr::integer()) -&gt; integer()</pre>
 <br></br>
 <br></br>
 
 
 
 
@@ -1345,8 +1312,7 @@ 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="update_shared_counter-2"></a>
 will fail if the type of object referred to by Key is not a counter.<a name="update_shared_counter-2"></a>
 
 
-<h3>update_shared_counter/2</h3>
-
+###update_shared_counter/2##
 
 
 
 
 
 
@@ -1355,13 +1321,12 @@ will fail if the type of object referred to by Key is not a counter.<a name="upd
 
 
 <a name="where-1"></a>
 <a name="where-1"></a>
 
 
-<h3>where/1</h3>
-
+###where/1##
 
 
 
 
 
 
 
 
-<pre>where(Key::<a href="#type-key">key()</a>) -> pid()</pre>
+<pre>where(Key::[key()](#type-key)) -&gt; pid()</pre>
 <br></br>
 <br></br>
 
 
 
 
@@ -1375,8 +1340,7 @@ 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>
-
+###whereis_name/1##
 
 
 
 
 
 

+ 8 - 16
doc/gproc_app.md

@@ -1,9 +1,6 @@
-Module gproc_app
-================
 
 
 
 
-<h1>Module gproc_app</h1>
-
+#Module gproc_app#
 * [Function Index](#index)
 * [Function Index](#index)
 * [Function Details](#functions)
 * [Function Details](#functions)
 
 
@@ -12,24 +9,21 @@ Module gproc_app
 
 
 
 
 
 
-__Behaviours:__ [`application`](application.md).
-
-<h2><a name="index">Function Index</a></h2>
+__Behaviours:__ [`application`](application.md).<a name="index"></a>
 
 
+##Function Index##
 
 
 
 
 <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><a name="functions">Function Details</a></h2>
-
+##Function Details##
 
 
 <a name="start-0"></a>
 <a name="start-0"></a>
 
 
-<h3>start/0</h3>
-
+###start/0##
 
 
 
 
 
 
@@ -38,8 +32,7 @@ __Behaviours:__ [`application`](application.md).
 
 
 <a name="start-2"></a>
 <a name="start-2"></a>
 
 
-<h3>start/2</h3>
-
+###start/2##
 
 
 
 
 
 
@@ -48,8 +41,7 @@ __Behaviours:__ [`application`](application.md).
 
 
 <a name="stop-1"></a>
 <a name="stop-1"></a>
 
 
-<h3>stop/1</h3>
-
+###stop/1##
 
 
 
 
 
 

+ 41 - 78
doc/gproc_dist.md

@@ -1,9 +1,6 @@
-Module gproc_dist
-=================
 
 
 
 
-<h1>Module gproc_dist</h1>
-
+#Module gproc_dist#
 * [Description](#description)
 * [Description](#description)
 * [Function Index](#index)
 * [Function Index](#index)
 * [Function Details](#functions)
 * [Function Details](#functions)
@@ -13,21 +10,19 @@ Extended process registry.
 
 
 
 
 
 
-__Behaviours:__ [`gen_leader`](/Users/uwiger/ETC/git/gproc/deps/gen_leader/doc/gen_leader.md).
-
-__Authors:__ Ulf Wiger ([`ulf.wiger@erlang-solutions.com`](mailto:ulf.wiger@erlang-solutions.com)).
+__Behaviours:__ [`gen_leader`](/Users/uwiger/mine/git/gproc/deps/gen_leader/doc/gen_leader.md).
 
 
-<h2><a name="description">Description</a></h2>
+__Authors:__ Ulf Wiger ([`ulf.wiger@erlang-solutions.com`](mailto:ulf.wiger@erlang-solutions.com)).<a name="description"></a>
 
 
+##Description##
 
 
 
 
 This module implements an extended process registry
 This module implements an extended process registry
 
 
 
 
-For a detailed description, see gproc/doc/erlang07-wiger.pdf.
-
-<h2><a name="index">Function Index</a></h2>
+For a detailed description, see gproc/doc/erlang07-wiger.pdf.<a name="index"></a>
 
 
+##Function Index##
 
 
 
 
 <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>
 <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>
@@ -38,15 +33,13 @@ Class = n  - unique name
 Scope = l | g (global or local).</td></tr><tr><td valign="top"><a href="#reg_shared-2">reg_shared/2</a></td><td></td></tr><tr><td valign="top"><a href="#reset_counter-1">reset_counter/1</a></td><td></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="#sync-0">sync/0</a></td><td>Synchronize with the gproc leader.</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="#unreg_shared-1">unreg_shared/1</a></td><td></td></tr><tr><td valign="top"><a href="#update_counter-2">update_counter/2</a></td><td></td></tr><tr><td valign="top"><a href="#update_shared_counter-2">update_shared_counter/2</a></td><td></td></tr></table>
 Scope = l | g (global or local).</td></tr><tr><td valign="top"><a href="#reg_shared-2">reg_shared/2</a></td><td></td></tr><tr><td valign="top"><a href="#reset_counter-1">reset_counter/1</a></td><td></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="#sync-0">sync/0</a></td><td>Synchronize with the gproc leader.</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="#unreg_shared-1">unreg_shared/1</a></td><td></td></tr><tr><td valign="top"><a href="#update_counter-2">update_counter/2</a></td><td></td></tr><tr><td valign="top"><a href="#update_shared_counter-2">update_shared_counter/2</a></td><td></td></tr></table>
 
 
 
 
+<a name="functions"></a>
 
 
-
-<h2><a name="functions">Function Details</a></h2>
-
+##Function Details##
 
 
 <a name="code_change-4"></a>
 <a name="code_change-4"></a>
 
 
-<h3>code_change/4</h3>
-
+###code_change/4##
 
 
 
 
 
 
@@ -55,8 +48,7 @@ Scope = l | g (global or local).</td></tr><tr><td valign="top"><a href="#reg_sha
 
 
 <a name="elected-2"></a>
 <a name="elected-2"></a>
 
 
-<h3>elected/2</h3>
-
+###elected/2##
 
 
 
 
 
 
@@ -65,8 +57,7 @@ Scope = l | g (global or local).</td></tr><tr><td valign="top"><a href="#reg_sha
 
 
 <a name="elected-3"></a>
 <a name="elected-3"></a>
 
 
-<h3>elected/3</h3>
-
+###elected/3##
 
 
 
 
 
 
@@ -75,8 +66,7 @@ Scope = l | g (global or local).</td></tr><tr><td valign="top"><a href="#reg_sha
 
 
 <a name="from_leader-3"></a>
 <a name="from_leader-3"></a>
 
 
-<h3>from_leader/3</h3>
-
+###from_leader/3##
 
 
 
 
 
 
@@ -85,13 +75,12 @@ Scope = l | g (global or local).</td></tr><tr><td valign="top"><a href="#reg_sha
 
 
 <a name="get_leader-0"></a>
 <a name="get_leader-0"></a>
 
 
-<h3>get_leader/0</h3>
+###get_leader/0##
 
 
 
 
 
 
 
 
-
-<pre>get_leader() -> node()</pre>
+<pre>get_leader() -&gt; node()</pre>
 <br></br>
 <br></br>
 
 
 
 
@@ -99,8 +88,7 @@ Scope = l | g (global or local).</td></tr><tr><td valign="top"><a href="#reg_sha
 
 
 Returns the node of the current gproc leader.<a name="give_away-2"></a>
 Returns the node of the current gproc leader.<a name="give_away-2"></a>
 
 
-<h3>give_away/2</h3>
-
+###give_away/2##
 
 
 
 
 
 
@@ -109,8 +97,7 @@ Returns the node of the current gproc leader.<a name="give_away-2"></a>
 
 
 <a name="handle_DOWN-3"></a>
 <a name="handle_DOWN-3"></a>
 
 
-<h3>handle_DOWN/3</h3>
-
+###handle_DOWN/3##
 
 
 
 
 
 
@@ -119,8 +106,7 @@ Returns the node of the current gproc leader.<a name="give_away-2"></a>
 
 
 <a name="handle_call-4"></a>
 <a name="handle_call-4"></a>
 
 
-<h3>handle_call/4</h3>
-
+###handle_call/4##
 
 
 
 
 
 
@@ -129,8 +115,7 @@ Returns the node of the current gproc leader.<a name="give_away-2"></a>
 
 
 <a name="handle_cast-3"></a>
 <a name="handle_cast-3"></a>
 
 
-<h3>handle_cast/3</h3>
-
+###handle_cast/3##
 
 
 
 
 
 
@@ -139,8 +124,7 @@ Returns the node of the current gproc leader.<a name="give_away-2"></a>
 
 
 <a name="handle_info-2"></a>
 <a name="handle_info-2"></a>
 
 
-<h3>handle_info/2</h3>
-
+###handle_info/2##
 
 
 
 
 
 
@@ -149,8 +133,7 @@ Returns the node of the current gproc leader.<a name="give_away-2"></a>
 
 
 <a name="handle_leader_call-4"></a>
 <a name="handle_leader_call-4"></a>
 
 
-<h3>handle_leader_call/4</h3>
-
+###handle_leader_call/4##
 
 
 
 
 
 
@@ -159,8 +142,7 @@ Returns the node of the current gproc leader.<a name="give_away-2"></a>
 
 
 <a name="handle_leader_cast-3"></a>
 <a name="handle_leader_cast-3"></a>
 
 
-<h3>handle_leader_cast/3</h3>
-
+###handle_leader_cast/3##
 
 
 
 
 
 
@@ -169,8 +151,7 @@ Returns the node of the current gproc leader.<a name="give_away-2"></a>
 
 
 <a name="init-1"></a>
 <a name="init-1"></a>
 
 
-<h3>init/1</h3>
-
+###init/1##
 
 
 
 
 
 
@@ -179,8 +160,7 @@ Returns the node of the current gproc leader.<a name="give_away-2"></a>
 
 
 <a name="leader_call-1"></a>
 <a name="leader_call-1"></a>
 
 
-<h3>leader_call/1</h3>
-
+###leader_call/1##
 
 
 
 
 
 
@@ -189,8 +169,7 @@ Returns the node of the current gproc leader.<a name="give_away-2"></a>
 
 
 <a name="leader_cast-1"></a>
 <a name="leader_cast-1"></a>
 
 
-<h3>leader_cast/1</h3>
-
+###leader_cast/1##
 
 
 
 
 
 
@@ -199,8 +178,7 @@ Returns the node of the current gproc leader.<a name="give_away-2"></a>
 
 
 <a name="mreg-2"></a>
 <a name="mreg-2"></a>
 
 
-<h3>mreg/2</h3>
-
+###mreg/2##
 
 
 
 
 
 
@@ -209,8 +187,7 @@ Returns the node of the current gproc leader.<a name="give_away-2"></a>
 
 
 <a name="munreg-2"></a>
 <a name="munreg-2"></a>
 
 
-<h3>munreg/2</h3>
-
+###munreg/2##
 
 
 
 
 
 
@@ -219,8 +196,7 @@ Returns the node of the current gproc leader.<a name="give_away-2"></a>
 
 
 <a name="reg-1"></a>
 <a name="reg-1"></a>
 
 
-<h3>reg/1</h3>
-
+###reg/1##
 
 
 
 
 
 
@@ -229,8 +205,7 @@ Returns the node of the current gproc leader.<a name="give_away-2"></a>
 
 
 <a name="reg-2"></a>
 <a name="reg-2"></a>
 
 
-<h3>reg/2</h3>
-
+###reg/2##
 
 
 
 
 
 
@@ -246,8 +221,7 @@ Class = n  - unique name
 | a  - aggregated counter
 | a  - aggregated counter
 Scope = l | g (global or local)<a name="reg_shared-2"></a>
 Scope = l | g (global or local)<a name="reg_shared-2"></a>
 
 
-<h3>reg_shared/2</h3>
-
+###reg_shared/2##
 
 
 
 
 
 
@@ -256,8 +230,7 @@ Scope = l | g (global or local)<a name="reg_shared-2"></a>
 
 
 <a name="reset_counter-1"></a>
 <a name="reset_counter-1"></a>
 
 
-<h3>reset_counter/1</h3>
-
+###reset_counter/1##
 
 
 
 
 
 
@@ -266,8 +239,7 @@ Scope = l | g (global or local)<a name="reg_shared-2"></a>
 
 
 <a name="set_value-2"></a>
 <a name="set_value-2"></a>
 
 
-<h3>set_value/2</h3>
-
+###set_value/2##
 
 
 
 
 
 
@@ -276,8 +248,7 @@ Scope = l | g (global or local)<a name="reg_shared-2"></a>
 
 
 <a name="start_link-0"></a>
 <a name="start_link-0"></a>
 
 
-<h3>start_link/0</h3>
-
+###start_link/0##
 
 
 
 
 
 
@@ -286,8 +257,7 @@ Scope = l | g (global or local)<a name="reg_shared-2"></a>
 
 
 <a name="start_link-1"></a>
 <a name="start_link-1"></a>
 
 
-<h3>start_link/1</h3>
-
+###start_link/1##
 
 
 
 
 
 
@@ -296,8 +266,7 @@ Scope = l | g (global or local)<a name="reg_shared-2"></a>
 
 
 <a name="surrendered-3"></a>
 <a name="surrendered-3"></a>
 
 
-<h3>surrendered/3</h3>
-
+###surrendered/3##
 
 
 
 
 
 
@@ -306,13 +275,12 @@ Scope = l | g (global or local)<a name="reg_shared-2"></a>
 
 
 <a name="sync-0"></a>
 <a name="sync-0"></a>
 
 
-<h3>sync/0</h3>
+###sync/0##
 
 
 
 
 
 
 
 
-
-<pre>sync() -> true</pre>
+<pre>sync() -&gt; true</pre>
 <br></br>
 <br></br>
 
 
 
 
@@ -331,8 +299,7 @@ during an ongoing sync, the call will fail with a timeout exception.
 out why gen_leader times out in this situation, rather than reporting that
 out why gen_leader times out in this situation, rather than reporting that
 the leader died.)<a name="terminate-2"></a>
 the leader died.)<a name="terminate-2"></a>
 
 
-<h3>terminate/2</h3>
-
+###terminate/2##
 
 
 
 
 
 
@@ -341,8 +308,7 @@ the leader died.)<a name="terminate-2"></a>
 
 
 <a name="unreg-1"></a>
 <a name="unreg-1"></a>
 
 
-<h3>unreg/1</h3>
-
+###unreg/1##
 
 
 
 
 
 
@@ -351,8 +317,7 @@ the leader died.)<a name="terminate-2"></a>
 
 
 <a name="unreg_shared-1"></a>
 <a name="unreg_shared-1"></a>
 
 
-<h3>unreg_shared/1</h3>
-
+###unreg_shared/1##
 
 
 
 
 
 
@@ -361,8 +326,7 @@ the leader died.)<a name="terminate-2"></a>
 
 
 <a name="update_counter-2"></a>
 <a name="update_counter-2"></a>
 
 
-<h3>update_counter/2</h3>
-
+###update_counter/2##
 
 
 
 
 
 
@@ -371,8 +335,7 @@ the leader died.)<a name="terminate-2"></a>
 
 
 <a name="update_shared_counter-2"></a>
 <a name="update_shared_counter-2"></a>
 
 
-<h3>update_shared_counter/2</h3>
-
+###update_shared_counter/2##
 
 
 
 
 
 

+ 7 - 13
doc/gproc_info.md

@@ -1,9 +1,6 @@
-Module gproc_info
-=================
 
 
 
 
-<h1>Module gproc_info</h1>
-
+#Module gproc_info#
 * [Function Index](#index)
 * [Function Index](#index)
 * [Function Details](#functions)
 * [Function Details](#functions)
 
 
@@ -12,29 +9,26 @@ Module gproc_info
 
 
 
 
 
 
-__Authors:__ Ulf Wiger ([`ulf.wiger@erlang-solutions.com`](mailto:ulf.wiger@erlang-solutions.com)).
-
-<h2><a name="index">Function Index</a></h2>
+__Authors:__ Ulf Wiger ([`ulf.wiger@erlang-solutions.com`](mailto:ulf.wiger@erlang-solutions.com)).<a name="index"></a>
 
 
+##Function Index##
 
 
 
 
 <table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#i-0">i/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="#i-0">i/0</a></td><td></td></tr></table>
 
 
 
 
+<a name="functions"></a>
 
 
-
-<h2><a name="functions">Function Details</a></h2>
-
+##Function Details##
 
 
 <a name="i-0"></a>
 <a name="i-0"></a>
 
 
-<h3>i/0</h3>
-
+###i/0##
 
 
 
 
 
 
 
 
-<pre>i() -> ok</pre>
+<pre>i() -&gt; ok</pre>
 <br></br>
 <br></br>
 
 
 
 

+ 9 - 16
doc/gproc_init.md

@@ -1,50 +1,43 @@
-Module gproc_init
-=================
 
 
 
 
-<h1>Module gproc_init</h1>
-
+#Module gproc_init#
 * [Function Index](#index)
 * [Function Index](#index)
 * [Function Details](#functions)
 * [Function Details](#functions)
 
 
 
 
 
 
 
 
+<a name="index"></a>
 
 
-
-<h2><a name="index">Function Index</a></h2>
-
+##Function Index##
 
 
 
 
 <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><a name="functions">Function Details</a></h2>
-
+##Function Details##
 
 
 <a name="hard_reset-0"></a>
 <a name="hard_reset-0"></a>
 
 
-<h3>hard_reset/0</h3>
-
+###hard_reset/0##
 
 
 
 
 
 
 
 
-<pre>hard_reset() -> ok</pre>
+<pre>hard_reset() -&gt; ok</pre>
 <br></br>
 <br></br>
 
 
 
 
 <a name="soft_reset-0"></a>
 <a name="soft_reset-0"></a>
 
 
-<h3>soft_reset/0</h3>
-
+###soft_reset/0##
 
 
 
 
 
 
 
 
-<pre>soft_reset() -> ok</pre>
+<pre>soft_reset() -&gt; ok</pre>
 <br></br>
 <br></br>
 
 
 
 

+ 39 - 38
doc/gproc_lib.md

@@ -1,9 +1,6 @@
-Module gproc_lib
-================
 
 
 
 
-<h1>Module gproc_lib</h1>
-
+#Module gproc_lib#
 * [Description](#description)
 * [Description](#description)
 * [Function Index](#index)
 * [Function Index](#index)
 * [Function Details](#functions)
 * [Function Details](#functions)
@@ -13,33 +10,29 @@ Extended process registry.
 
 
 
 
 
 
-__Authors:__ Ulf Wiger ([`ulf.wiger@ericsson.com`](mailto:ulf.wiger@ericsson.com)).
-
-<h2><a name="description">Description</a></h2>
+__Authors:__ Ulf Wiger ([`ulf.wiger@ericsson.com`](mailto:ulf.wiger@ericsson.com)).<a name="description"></a>
 
 
+##Description##
 
 
 
 
 This module implements an extended process registry
 This module implements an extended process registry
 
 
 
 
-For a detailed description, see gproc/doc/erlang07-wiger.pdf.
-
-<h2><a name="index">Function Index</a></h2>
-
+For a detailed description, see gproc/doc/erlang07-wiger.pdf.<a name="index"></a>
 
 
+##Function Index##
 
 
-<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#await-3">await/3</a></td><td></td></tr><tr><td valign="top"><a href="#do_set_counter_value-3">do_set_counter_value/3</a></td><td></td></tr><tr><td valign="top"><a href="#do_set_value-3">do_set_value/3</a></td><td></td></tr><tr><td valign="top"><a href="#ensure_monitor-2">ensure_monitor/2</a></td><td></td></tr><tr><td valign="top"><a href="#insert_many-4">insert_many/4</a></td><td></td></tr><tr><td valign="top"><a href="#insert_reg-4">insert_reg/4</a></td><td></td></tr><tr><td valign="top"><a href="#remove_many-4">remove_many/4</a></td><td></td></tr><tr><td valign="top"><a href="#remove_reg-2">remove_reg/2</a></td><td></td></tr><tr><td valign="top"><a href="#update_aggr_counter-3">update_aggr_counter/3</a></td><td></td></tr><tr><td valign="top"><a href="#update_counter-3">update_counter/3</a></td><td></td></tr><tr><td valign="top"><a href="#valid_opts-2">valid_opts/2</a></td><td></td></tr></table>
 
 
+<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#await-3">await/3</a></td><td></td></tr><tr><td valign="top"><a href="#do_set_counter_value-3">do_set_counter_value/3</a></td><td></td></tr><tr><td valign="top"><a href="#do_set_value-3">do_set_value/3</a></td><td></td></tr><tr><td valign="top"><a href="#ensure_monitor-2">ensure_monitor/2</a></td><td></td></tr><tr><td valign="top"><a href="#insert_many-4">insert_many/4</a></td><td></td></tr><tr><td valign="top"><a href="#insert_reg-4">insert_reg/4</a></td><td></td></tr><tr><td valign="top"><a href="#notify-2">notify/2</a></td><td></td></tr><tr><td valign="top"><a href="#remove_many-4">remove_many/4</a></td><td></td></tr><tr><td valign="top"><a href="#remove_reg-2">remove_reg/2</a></td><td></td></tr><tr><td valign="top"><a href="#remove_reg-3">remove_reg/3</a></td><td></td></tr><tr><td valign="top"><a href="#update_aggr_counter-3">update_aggr_counter/3</a></td><td></td></tr><tr><td valign="top"><a href="#update_counter-3">update_counter/3</a></td><td></td></tr><tr><td valign="top"><a href="#valid_opts-2">valid_opts/2</a></td><td></td></tr></table>
 
 
 
 
+<a name="functions"></a>
 
 
-<h2><a name="functions">Function Details</a></h2>
-
+##Function Details##
 
 
 <a name="await-3"></a>
 <a name="await-3"></a>
 
 
-<h3>await/3</h3>
-
+###await/3##
 
 
 
 
 
 
@@ -48,8 +41,7 @@ For a detailed description, see gproc/doc/erlang07-wiger.pdf.
 
 
 <a name="do_set_counter_value-3"></a>
 <a name="do_set_counter_value-3"></a>
 
 
-<h3>do_set_counter_value/3</h3>
-
+###do_set_counter_value/3##
 
 
 
 
 
 
@@ -58,8 +50,7 @@ For a detailed description, see gproc/doc/erlang07-wiger.pdf.
 
 
 <a name="do_set_value-3"></a>
 <a name="do_set_value-3"></a>
 
 
-<h3>do_set_value/3</h3>
-
+###do_set_value/3##
 
 
 
 
 
 
@@ -68,8 +59,7 @@ For a detailed description, see gproc/doc/erlang07-wiger.pdf.
 
 
 <a name="ensure_monitor-2"></a>
 <a name="ensure_monitor-2"></a>
 
 
-<h3>ensure_monitor/2</h3>
-
+###ensure_monitor/2##
 
 
 
 
 
 
@@ -78,33 +68,39 @@ For a detailed description, see gproc/doc/erlang07-wiger.pdf.
 
 
 <a name="insert_many-4"></a>
 <a name="insert_many-4"></a>
 
 
-<h3>insert_many/4</h3>
+###insert_many/4##
 
 
 
 
 
 
 
 
-
-<pre>insert_many(T::<a href="#type-type">type()</a>, Scope::<a href="#type-scope">scope()</a>, KVL::[{<a href="#type-key">key()</a>, any()}], Pid::pid()) -> {true, list()} | false</pre>
+<pre>insert_many(T::[type()](#type-type), Scope::[scope()](#type-scope), KVL::[{[key()](#type-key), any()}], Pid::pid()) -&gt; {true, list()} | false</pre>
 <br></br>
 <br></br>
 
 
 
 
 <a name="insert_reg-4"></a>
 <a name="insert_reg-4"></a>
 
 
-<h3>insert_reg/4</h3>
-
+###insert_reg/4##
 
 
 
 
 
 
 
 
-<pre>insert_reg(K::<a href="#type-key">key()</a>, Value::any(), Pid::pid() | shared, Scope::<a href="#type-scope">scope()</a>) -> boolean()</pre>
+<pre>insert_reg(K::[key()](#type-key), Value::any(), Pid::pid() | shared, Scope::[scope()](#type-scope)) -&gt; boolean()</pre>
 <br></br>
 <br></br>
 
 
 
 
-<a name="remove_many-4"></a>
+<a name="notify-2"></a>
+
+###notify/2##
+
 
 
-<h3>remove_many/4</h3>
 
 
 
 
+`notify(Key, Opts) -> any()`
+
+<a name="remove_many-4"></a>
+
+###remove_many/4##
+
 
 
 
 
 
 
@@ -112,28 +108,34 @@ For a detailed description, see gproc/doc/erlang07-wiger.pdf.
 
 
 <a name="remove_reg-2"></a>
 <a name="remove_reg-2"></a>
 
 
-<h3>remove_reg/2</h3>
-
+###remove_reg/2##
 
 
 
 
 
 
 
 
 `remove_reg(Key, Pid) -> any()`
 `remove_reg(Key, Pid) -> any()`
 
 
-<a name="update_aggr_counter-3"></a>
+<a name="remove_reg-3"></a>
+
+###remove_reg/3##
 
 
-<h3>update_aggr_counter/3</h3>
 
 
 
 
 
 
+`remove_reg(Key, Pid, Opts) -> any()`
+
+<a name="update_aggr_counter-3"></a>
+
+###update_aggr_counter/3##
+
+
 
 
 
 
 `update_aggr_counter(C, N, Val) -> any()`
 `update_aggr_counter(C, N, Val) -> any()`
 
 
 <a name="update_counter-3"></a>
 <a name="update_counter-3"></a>
 
 
-<h3>update_counter/3</h3>
-
+###update_counter/3##
 
 
 
 
 
 
@@ -142,8 +144,7 @@ For a detailed description, see gproc/doc/erlang07-wiger.pdf.
 
 
 <a name="valid_opts-2"></a>
 <a name="valid_opts-2"></a>
 
 
-<h3>valid_opts/2</h3>
-
+###valid_opts/2##
 
 
 
 
 
 

+ 92 - 0
doc/gproc_monitor.md

@@ -0,0 +1,92 @@
+
+
+#Module gproc_monitor#
+* [Description](#description)
+* [Function Index](#index)
+* [Function Details](#functions)
+
+
+
+This module implements a notification system for gproc names
+When a process subscribes to notifications for a given name, a message
+will be sent each time that name is registered.
+
+
+
+__Behaviours:__ [`gen_server`](gen_server.md).
+
+__Authors:__ Ulf Wiger ([`ulf.wiger@feuerlabs.com`](mailto:ulf.wiger@feuerlabs.com)).<a name="index"></a>
+
+##Function Index##
+
+
+<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#start_link-0">start_link/0</a></td><td>
+Starts the server.</td></tr><tr><td valign="top"><a href="#subscribe-1">subscribe/1</a></td><td>  
+Subscribe to registration events for a certain name.</td></tr><tr><td valign="top"><a href="#unsubscribe-1">unsubscribe/1</a></td><td>  
+Unsubscribe from registration events for a certain name.</td></tr></table>
+
+
+<a name="functions"></a>
+
+##Function Details##
+
+<a name="start_link-0"></a>
+
+###start_link/0##
+
+
+
+
+<pre>start_link() -&gt; {ok, Pid} | ignore | {error, Error}</pre>
+<br></br>
+
+
+
+
+
+Starts the server
+<a name="subscribe-1"></a>
+
+###subscribe/1##
+
+
+
+
+<pre>subscribe(Key::[key()](#type-key)) -&gt; ok</pre>
+<br></br>
+
+
+
+
+
+
+  
+Subscribe to registration events for a certain name
+
+
+
+The subscribing process will receive a `{gproc_monitor, Name, Pid}` message
+whenever a process registers under the given name, and a
+`{gproc_monitor, Name, undefined}` message when the name is unregistered,  
+either explicitly, or because the registered process dies.
+
+When the subscription is first ordered, one of the above messages will be
+sent immediately, indicating the current status of the name.<a name="unsubscribe-1"></a>
+
+###unsubscribe/1##
+
+
+
+
+<pre>unsubscribe(Key::[key()](#type-key)) -&gt; ok</pre>
+<br></br>
+
+
+
+
+
+
+  
+Unsubscribe from registration events for a certain name
+
+This function is the reverse of subscribe/1. It removes the subscription.

+ 7 - 14
doc/gproc_sup.md

@@ -1,9 +1,6 @@
-Module gproc_sup
-================
 
 
 
 
-<h1>Module gproc_sup</h1>
-
+#Module gproc_sup#
 * [Function Index](#index)
 * [Function Index](#index)
 * [Function Details](#functions)
 * [Function Details](#functions)
 
 
@@ -12,24 +9,21 @@ Module gproc_sup
 
 
 
 
 
 
-__Behaviours:__ [`supervisor`](supervisor.md).
-
-<h2><a name="index">Function Index</a></h2>
+__Behaviours:__ [`supervisor`](supervisor.md).<a name="index"></a>
 
 
+##Function Index##
 
 
 
 
 <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><a name="functions">Function Details</a></h2>
-
+##Function Details##
 
 
 <a name="init-1"></a>
 <a name="init-1"></a>
 
 
-<h3>init/1</h3>
-
+###init/1##
 
 
 
 
 
 
@@ -40,8 +34,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>
-
+###start_link/1##
 
 
 
 
 
 

+ 120 - 13
src/gproc.erl

@@ -73,6 +73,8 @@
          await/1, await/2,
          await/1, await/2,
          nb_wait/1,
          nb_wait/1,
          cancel_wait/2,
          cancel_wait/2,
+	 monitor/1,
+	 demonitor/2,
          lookup_pid/1,
          lookup_pid/1,
          lookup_pids/1,
          lookup_pids/1,
          lookup_value/1,
          lookup_value/1,
@@ -119,6 +121,7 @@
 
 
 %% Callbacks for behaviour support
 %% Callbacks for behaviour support
 -export([whereis_name/1,
 -export([whereis_name/1,
+	 register_name/2,
          unregister_name/1]).
          unregister_name/1]).
 
 
 -export([default/1]).
 -export([default/1]).
@@ -665,6 +668,38 @@ cancel_wait({_,l,_} = Key, Ref) ->
     ok.
     ok.
 
 
 
 
+%% @spec monitor(key()) -> reference()
+%%
+%% @doc monitor a registered name
+%% This function works much like erlang:monitor(process, Pid), but monitors
+%% a unique name registered via gproc. A message, `{gproc, unreg, Ref, Key}'
+%% will be sent to the requesting process, if the name is unregistered or
+%% the registered process dies.
+%%
+%% If the name is not yet registered, the same message is sent immediately.
+%% @end
+monitor({T,g,_} = Key) when T==n; T==a ->
+    ?CHK_DIST,
+    call({monitor, Key}, g);
+monitor({T,l,_} = Key) when T==n; T==a ->
+    call({monitor, Key}, l);
+monitor(Key) ->
+    erlang:error(badarg, [Key]).
+
+%% @spec demonitor(key(), reference()) -> ok
+%%
+%% @doc Remove a monitor on a registered name
+%% This function is the reverse of monitor/1. It removes a monitor previously
+%% set on a unique name. This function always succeeds given legal input.
+%% @end
+demonitor({T,g,_} = Key, Ref) when T==n; T==a ->
+    ?CHK_DIST,
+    call({demonitor, Key, Ref}, g);
+demonitor({T,l,_} = Key, Ref) when T==n; T==a ->
+    call({demonitor, Key, Ref}, l);
+demonitor(Key, Ref) ->
+    erlang:error(badarg, [Key, Ref]).
+
 %% @spec reg(Key::key(), Value) -> true
 %% @spec reg(Key::key(), Value) -> true
 %%
 %%
 %% @doc Register a name or property for the current process
 %% @doc Register a name or property for the current process
@@ -817,6 +852,17 @@ unreg_shared(Key) ->
 	    erlang:error(badarg)
 	    erlang:error(badarg)
     end.
     end.
 
 
+%% @spec (key(), pid()) -> yes | no
+%%
+%% @doc Behaviour support callback
+%% @end
+register_name({n,_,_} = Name, Pid) when Pid == self() ->
+    try reg(Name), yes
+    catch
+	error:_ ->
+	    no
+    end.
+
 %% @equiv unreg/1
 %% @equiv unreg/1
 unregister_name(Key) ->
 unregister_name(Key) ->
     unreg(Key).
     unreg(Key).
@@ -1336,6 +1382,35 @@ handle_call({reg, {_T,l,_} = Key, Val}, {Pid,_}, S) ->
         false ->
         false ->
             {reply, badarg, S}
             {reply, badarg, S}
     end;
     end;
+handle_call({monitor, {T,_,_} = Key}, {Pid, _}, S)
+  when T==n; T==a ->
+    Ref = make_ref(),
+    case where(Key) of
+	undefined ->
+	    Pid ! {gproc, unreg, Ref, Key};
+	RegPid ->
+	    case ets:lookup(?TAB, {RegPid, Key}) of
+		[{K,r}] ->
+		    ets:insert(?TAB, {K, [{monitor, [Pid]}]});
+		[{K, Opts}] ->
+		    ets:insert(?TAB, {K, add_monitor(Opts, Pid, Ref)})
+	    end
+    end,
+    {reply, Ref, S};
+handle_call({demonitor, {T,_,_} = Key, Ref}, {Pid,_}, S)
+  when T==n; T==a ->
+    case where(Key) of
+	undefined ->
+	    ok;  % be nice
+	RegPid ->
+	    case ets:lookup(?TAB, {RegPid, Key}) of
+		[{_K,r}] ->
+		    ok;   % be nice
+		[{K, Opts}] ->
+		    ets:insert(?TAB, {K, remove_monitor(Opts, Pid, Ref)})
+	    end
+    end,
+    {reply, ok, S};
 handle_call({reg_shared, {_T,l,_} = Key, Val}, _From, S) ->
 handle_call({reg_shared, {_T,l,_} = Key, Val}, _From, S) ->
     case try_insert_reg(Key, Val, shared) of
     case try_insert_reg(Key, Val, shared) of
     %% case try_insert_shared(Key, Val) of
     %% case try_insert_shared(Key, Val) of
@@ -1345,15 +1420,26 @@ handle_call({reg_shared, {_T,l,_} = Key, Val}, _From, S) ->
 	    {reply, badarg, S}
 	    {reply, badarg, S}
     end;
     end;
 handle_call({unreg, {_,l,_} = Key}, {Pid,_}, S) ->
 handle_call({unreg, {_,l,_} = Key}, {Pid,_}, S) ->
-    case ets:member(?TAB, {Pid,Key}) of
-        true ->
+    case ets:lookup(?TAB, {Pid,Key}) of
+        [{_, r}] ->
             _ = gproc_lib:remove_reg(Key, Pid),
             _ = gproc_lib:remove_reg(Key, Pid),
             {reply, true, S};
             {reply, true, S};
-        false ->
+        [{_, Opts}] when is_list(Opts) ->
+            _ = gproc_lib:remove_reg(Key, Pid, Opts),
+            {reply, true, S};
+        [] ->
             {reply, badarg, S}
             {reply, badarg, S}
     end;
     end;
 handle_call({unreg_shared, {_,l,_} = Key}, _, S) ->
 handle_call({unreg_shared, {_,l,_} = Key}, _, S) ->
-    _ = gproc_lib:remove_reg(Key, shared),
+    case ets:lookup(?TAB, {shared, Key}) of
+	[{_, r}] ->
+	    _ = gproc_lib:remove_reg(Key, shared);
+	[{_, Opts}] ->
+	    _ = gproc_lib:remove_reg(Key, shared, Opts);
+	[] ->
+	    %% don't crash if shared key already unregged.
+	    ok
+    end,
     {reply, true, S};
     {reply, true, S};
 handle_call({await, {_,l,_} = Key, Pid}, From, S) ->
 handle_call({await, {_,l,_} = Key, Pid}, From, S) ->
     %% Passing the pid explicitly is needed when leader_call is used,
     %% Passing the pid explicitly is needed when leader_call is used,
@@ -1487,14 +1573,16 @@ process_is_down(Pid) when is_pid(Pid) ->
         false ->
         false ->
             ok;
             ok;
         true ->
         true ->
-            Revs = ets:select(?TAB, [{{{Pid,'$1'}, '_'},
-                                      [{'==',{element,2,'$1'},l}], ['$1']}]),
+            Revs = ets:select(?TAB, [{{{Pid,'$1'}, '$2'},
+                                      [{'==',{element,2,'$1'},l}],
+				      [{{'$1','$2'}}]}]),
             lists:foreach(
             lists:foreach(
-              fun({n,l,_}=K) ->
+              fun({{n,l,_}=K, R}) ->
                       Key = {K,n},
                       Key = {K,n},
                       case ets:lookup(?TAB, Key) of
                       case ets:lookup(?TAB, Key) of
                           [{_, Pid, _}] ->
                           [{_, Pid, _}] ->
-                              ets:delete(?TAB, Key);
+                              ets:delete(?TAB, Key),
+			      opt_notify(R, K);
                           [{_, Waiters}] ->
                           [{_, Waiters}] ->
                               case [W || {P,_} = W <- Waiters,
                               case [W || {P,_} = W <- Waiters,
                                          P =/= Pid] of
                                          P =/= Pid] of
@@ -1506,14 +1594,15 @@ process_is_down(Pid) when is_pid(Pid) ->
                           [] ->
                           [] ->
                               true
                               true
                       end;
                       end;
-                 ({c,l,C} = K) ->
+                 ({{c,l,C} = K, _}) ->
                       Key = {K, Pid},
                       Key = {K, Pid},
                       [{_, _, Value}] = ets:lookup(?TAB, Key),
                       [{_, _, Value}] = ets:lookup(?TAB, Key),
                       ets:delete(?TAB, Key),
                       ets:delete(?TAB, Key),
                       gproc_lib:update_aggr_counter(l, C, -Value);
                       gproc_lib:update_aggr_counter(l, C, -Value);
-                 ({a,l,_} = K) ->
-                      ets:delete(?TAB, {K,a});
-                 ({p,_,_} = K) ->
+                 ({{a,l,_} = K, R}) ->
+                      ets:delete(?TAB, {K,a}),
+		      opt_notify(R, K);
+                 ({{p,_,_} = K, _}) ->
                       ets:delete(?TAB, {K, Pid})
                       ets:delete(?TAB, {K, Pid})
               end, Revs),
               end, Revs),
             ets:select_delete(?TAB, [{{{Pid,{'_',l,'_'}},'_'}, [], [true]}]),
             ets:select_delete(?TAB, [{{{Pid,{'_',l,'_'}},'_'}, [], [true]}]),
@@ -1521,6 +1610,12 @@ process_is_down(Pid) when is_pid(Pid) ->
             ok
             ok
     end.
     end.
 
 
+opt_notify(r, _) ->
+    ok;
+opt_notify(Opts, Key) ->
+    gproc_lib:notify(Key, Opts).
+
+
 do_give_away({T,l,_} = K, To, Pid) when T==n; T==a ->
 do_give_away({T,l,_} = K, To, Pid) when T==n; T==a ->
     Key = {K, T},
     Key = {K, T},
     case ets:lookup(?TAB, Key) of
     case ets:lookup(?TAB, Key) of
@@ -1607,7 +1702,19 @@ set_monitors({Pids, Cont}) ->
     _ = [erlang:monitor(process,Pid) || Pid <- Pids],
     _ = [erlang:monitor(process,Pid) || Pid <- Pids],
     set_monitors(ets:select(Cont)).
     set_monitors(ets:select(Cont)).
 
 
-
+add_monitor([{monitor, Mons}|T], Pid, Ref) ->
+    [{monitor, [{Pid,Ref}|Mons]}|T];
+add_monitor([H|T], Pid, Ref) ->
+    [H|add_monitor(T, Pid, Ref)];
+add_monitor([], Pid, Ref) ->
+    [{monitor, [{Pid, Ref}]}].
+
+remove_monitor([{monitor, Mons}|T], Pid, Ref) ->
+    [{monitor, Mons -- [{Pid, Ref}]}|T];
+remove_monitor([H|T], Pid, Ref) ->
+    [H|remove_monitor(T, Pid, Ref)];
+remove_monitor([], _Pid, _Ref) ->
+    [].
 
 
 monitor_me() ->
 monitor_me() ->
     case ets:insert_new(?TAB, {{self(),l}}) of
     case ets:insert_new(?TAB, {{self(),l}}) of

+ 25 - 2
src/gproc_lib.erl

@@ -28,7 +28,8 @@
          insert_many/4,
          insert_many/4,
          insert_reg/4,
          insert_reg/4,
          remove_many/4,
          remove_many/4,
-         remove_reg/2,
+         remove_reg/2, remove_reg/3,
+	 notify/2,
          update_aggr_counter/3,
          update_aggr_counter/3,
          update_counter/3,
          update_counter/3,
 	 valid_opts/2]).
 	 valid_opts/2]).
@@ -209,16 +210,38 @@ ensure_monitor(Pid, Scope) when Scope==g; Scope==l ->
     end.
     end.
 
 
 remove_reg(Key, Pid) ->
 remove_reg(Key, Pid) ->
+    remove_reg(Key, Pid, []).
+
+remove_reg(Key, Pid, Opts) ->
     Reg = remove_reg_1(Key, Pid),
     Reg = remove_reg_1(Key, Pid),
     ets:delete(?TAB, Rev = {Pid,Key}),
     ets:delete(?TAB, Rev = {Pid,Key}),
+    notify(Key, Opts),
     [Reg, Rev].
     [Reg, Rev].
 
 
+notify(Key, Opts) ->
+    case lists:keyfind(monitor, 1, Opts) of
+	false ->
+	    [];
+	{_, Mons} ->
+	    [begin P ! {gproc, unreg, Ref, Key}, P end || {P, Ref} <- Mons]
+    end.
+
 remove_many(T, Scope, L, Pid) ->
 remove_many(T, Scope, L, Pid) ->
     lists:flatmap(fun(K) ->
     lists:flatmap(fun(K) ->
                           Key = {T, Scope, K},
                           Key = {T, Scope, K},
-                          remove_reg(Key, Pid)
+                          remove_reg(Key, Pid, unreg_opts(Key, Pid))
                   end, L).
                   end, L).
 
 
+unreg_opts(Key, Pid) ->
+    case ets:lookup(?TAB, {Pid, Key}) of
+	[] ->
+	    [];
+	[{_,r}] ->
+	    [];
+	[{_,Opts}] ->
+	    Opts
+    end.
+
 remove_reg_1({c,_,_} = Key, Pid) ->
 remove_reg_1({c,_,_} = Key, Pid) ->
     remove_counter_1(Key, ets:lookup_element(?TAB, Reg = {Key,Pid}, 3), Pid),
     remove_counter_1(Key, ets:lookup_element(?TAB, Reg = {Key,Pid}, 3), Pid),
     Reg;
     Reg;

+ 227 - 0
src/gproc_monitor.erl

@@ -0,0 +1,227 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved via the world wide web at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
+%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
+%% AB. All Rights Reserved.''
+%%
+%% @author Ulf Wiger <ulf.wiger@feuerlabs.com>
+%%
+%% @doc
+%% This module implements a notification system for gproc names
+%% When a process subscribes to notifications for a given name, a message
+%% will be sent each time that name is registered
+-module(gproc_monitor).
+
+-behaviour(gen_server).
+
+%% API
+-export([subscribe/1,
+	 unsubscribe/1]).
+
+%% Process start function
+-export([start_link/0]).
+
+%% gen_server callbacks
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
+	 terminate/2, code_change/3]).
+
+-define(SERVER, ?MODULE).
+-define(TAB, ?MODULE).
+
+-record(state, {}).
+
+%%%===================================================================
+%%% API
+%%%===================================================================
+
+%%--------------------------------------------------------------------
+%% @spec subscribe(key()) -> ok
+%%
+%% @doc
+%% Subscribe to registration events for a certain name
+%%
+%% The subscribing process will receive a `{gproc_monitor, Name, Pid}' message
+%% whenever a process registers under the given name, and a
+%% `{gproc_monitor, Name, undefined}' message when the name is unregistered,
+%% either explicitly, or because the registered process dies.
+%%
+%% When the subscription is first ordered, one of the above messages will be
+%% sent immediately, indicating the current status of the name.
+%% @end
+%%--------------------------------------------------------------------
+subscribe({T,S,_} = Key) when (T==n orelse T==a)
+			      andalso (S==g orelse S==l) ->
+    try gproc:reg({p,l,{?MODULE,Key}})
+    catch
+	error:badarg -> ok
+    end,
+    gen_server:cast(?SERVER, {subscribe, self(), Key}).
+
+
+%%--------------------------------------------------------------------
+%% @spec unsubscribe(key()) -> ok
+%%
+%% @doc
+%% Unsubscribe from registration events for a certain name
+%%
+%% This function is the reverse of subscribe/1. It removes the subscription.
+%% @end
+%%--------------------------------------------------------------------
+unsubscribe({T,S,_} = Key) when (T==n orelse T==a)
+				andalso (S==g orelse S==l) ->
+    try gproc:unreg({p, l, {?MODULE,Key}})
+    catch
+	error:badarg -> ok
+    end,
+    ok.
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Starts the server
+%%
+%% @spec start_link() -> {ok, Pid} | ignore | {error, Error}
+%% @end
+%%--------------------------------------------------------------------
+start_link() ->
+    Me = self(),
+    case ets:info(?TAB, owner) of
+	undefined ->
+	    ets:new(?TAB, [ordered_set, protected, named_table,
+			      {heir, self(), []}]);
+	Me ->
+	    ok
+    end,
+    {ok, Pid} = proc_lib:start_link(?MODULE, init, [Me]),
+    ets:give_away(?TAB, Pid, []),
+    {ok, Pid}.
+
+%%%===================================================================
+%%% gen_server callbacks
+%%%===================================================================
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Initializes the server
+%%
+%% @spec init(Args) -> {ok, State} |
+%%                     {ok, State, Timeout} |
+%%                     ignore |
+%%                     {stop, Reason}
+%% @end
+%%--------------------------------------------------------------------
+init(Parent) ->
+    register(?SERVER, self()),
+    proc_lib:init_ack(Parent, {ok, self()}),
+    receive {'ETS-TRANSFER',?TAB,_,_} -> ok end,
+    gen_server:enter_loop(?MODULE, [], #state{}).
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Handling call messages
+%%
+%% @spec handle_call(Request, From, State) ->
+%%                                   {reply, Reply, State} |
+%%                                   {reply, Reply, State, Timeout} |
+%%                                   {noreply, State} |
+%%                                   {noreply, State, Timeout} |
+%%                                   {stop, Reason, Reply, State} |
+%%                                   {stop, Reason, State}
+%% @end
+%%--------------------------------------------------------------------
+handle_call(_Request, _From, State) ->
+    Reply = ok,
+    {reply, Reply, State}.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Handling cast messages
+%%
+%% @spec handle_cast(Msg, State) -> {noreply, State} |
+%%                                  {noreply, State, Timeout} |
+%%                                  {stop, Reason, State}
+%% @end
+%%--------------------------------------------------------------------
+handle_cast({subscribe, Pid, Key}, State) ->
+    Status = gproc:where(Key),
+    do_monitor(Key, Status),
+    Pid ! {?MODULE, Key, Status},
+    {noreply, State}.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Handling all non call/cast messages
+%%
+%% @spec handle_info(Info, State) -> {noreply, State} |
+%%                                   {noreply, State, Timeout} |
+%%                                   {stop, Reason, State}
+%% @end
+%%--------------------------------------------------------------------
+handle_info({gproc, unreg, _Ref, Name}, State) ->
+    ets:delete(?TAB, Name),
+    notify(Name, undefined),
+    do_monitor(Name, undefined),
+    {noreply, State};
+handle_info({gproc, _, registered, {{T,_,_} = Name, Pid, _}}, State)
+  when T==n; T==a ->
+    notify(Name, Pid),
+    do_monitor(Name, Pid),
+    {noreply, State};
+handle_info(_, State) ->
+    {noreply, State}.
+
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% This function is called by a gen_server when it is about to
+%% terminate. It should be the opposite of Module:init/1 and do any
+%% necessary cleaning up. When it returns, the gen_server terminates
+%% with Reason. The return value is ignored.
+%%
+%% @spec terminate(Reason, State) -> void()
+%% @end
+%%--------------------------------------------------------------------
+terminate(_Reason, _State) ->
+    ok.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Convert process state when code is changed
+%%
+%% @spec code_change(OldVsn, State, Extra) -> {ok, NewState}
+%% @end
+%%--------------------------------------------------------------------
+code_change(_OldVsn, State, _Extra) ->
+    {ok, State}.
+
+%%%===================================================================
+%%% Internal functions
+%%%===================================================================
+
+do_monitor(Name, undefined) ->
+    gproc:nb_wait(Name);
+do_monitor(Name, Pid) when is_pid(Pid) ->
+    case ets:member(?TAB, Name) of
+	false ->
+	    Ref = gproc:monitor(Name),
+	    ets:insert(?TAB, {Name, Ref});
+	true ->
+	    ok
+    end.
+
+notify(Name, Where) ->
+    gproc:send({p, l, {?MODULE, Name}}, {?MODULE, Name, Where}).

+ 3 - 1
src/gproc_sup.erl

@@ -48,7 +48,9 @@ init(_Args) ->
                    [{gproc_dist, {gproc_dist, start_link, [Env]},
                    [{gproc_dist, {gproc_dist, start_link, [Env]},
                      permanent, 2000, worker, [gproc_dist]}]
                      permanent, 2000, worker, [gproc_dist]}]
            end,
            end,
-    {ok,{{one_for_one, 15, 60}, [GProc | Dist]}}.
+    Mon = {gproc_monitor, {gproc_monitor, start_link, []},
+	   permanent, 2000, worker, [gproc_monitor]},
+    {ok,{{one_for_one, 15, 60}, [GProc| Dist] ++ [Mon]}}.
 
 
 
 
 %%%----------------------------------------------------------------------
 %%%----------------------------------------------------------------------