Browse Source

simplified gproc_pt, added some edoc

Ulf Wiger 12 years ago
parent
commit
3b32300125
15 changed files with 1188 additions and 1125 deletions
  1. 20 15
      README.md
  2. 20 15
      doc/README.md
  3. 1 1
      doc/edoc-info
  4. 678 326
      doc/gproc.md
  5. 11 11
      doc/gproc_app.md
  6. 20 20
      doc/gproc_bcast.md
  7. 88 80
      doc/gproc_dist.md
  8. 11 7
      doc/gproc_info.md
  9. 15 7
      doc/gproc_init.md
  10. 54 46
      doc/gproc_lib.md
  11. 26 15
      doc/gproc_monitor.md
  12. 142 71
      doc/gproc_ps.md
  13. 54 0
      doc/gproc_pt.md
  14. 10 10
      doc/gproc_sup.md
  15. 38 501
      src/gproc_pt.erl

+ 20 - 15
README.md

@@ -1,17 +1,17 @@
 
 
-#The gproc application#
-
+# The gproc application #
 
 __Authors:__ Ulf Wiger ([`ulf.wiger@erlang-solutions.com`](mailto:ulf.wiger@erlang-solutions.com)), Joseph Wayne Norton ([`norton@geminimobile.com`](mailto:norton@geminimobile.com)).
 
 Extended process dictionary
 
-##Note##
 
+## Note ##
 
 Gproc has two dependencies: `gen_leader` and `edown`. Since most people don't
 actively use either, they are no longer fetched by default.
+
 * To enable fetching of `gen_leader`, export the OS environment variable`GPROC_DIST=true` (this can be done e.g. from a GNU Makefile)
 
 * `edown` is fetched on-demand whenver `rebar get-deps doc` is called (which
@@ -19,10 +19,10 @@ actively use either, they are no longer fetched by default.
 
 
 
-##Introduction##
-
+## Introduction ##
 
 Gproc is a process dictionary for Erlang, which provides a number of useful features beyond what the built-in dictionary has:
+
 * Use any term as a process alias
 
 * Register a process under several aliases
@@ -43,8 +43,7 @@ Gproc is a process dictionary for Erlang, which provides a number of useful feat
 
 
 
-###Use case: System inspection##
-
+### Use case: System inspection ###
 
 Gproc was designed to work as a central index for "process metadata", i.e.
 properties that describe the role and characteristics of each process. Having
@@ -52,11 +51,14 @@ a single registry that is flexible enough to hold important types of property
 makes it easier to (a) find processes of a certain type, and (b) query and
 browse key data in a running system.
 
-###Use case: Pub/Sub patterns##
 
+### Use case: Pub/Sub patterns ###
 
 An interesting application of gproc is building publish/subscribe patterns.
-Example:<pre>
+Example:
+
+```
+
 subscribe(EventType) ->
     %% Gproc notation: {p, l, Name} means {(p)roperty, (l)ocal, Name}
     gproc:reg({p, l, {?MODULE, EventType}}).
@@ -64,10 +66,11 @@ subscribe(EventType) ->
 notify(EventType, Msg) ->
     Key = {?MODULE, EventType},
     gproc:send({p, l, Key}, {self(), Key, Msg}).
-</pre>
 
-###Use case: Environment handling##
+```
+
 
+### Use case: Environment handling ###
 
 Gproc provides a set of functions to read environment variables, possibly from
 alternative sources, and cache them for efficient lookup. Caching also provides
@@ -77,8 +80,8 @@ which values they actually ended up using.
 See [`gproc:get_env/4`](http://github.com/esl/gproc/blob/master/doc/gproc.md#get_env-4), [`gproc:get_set_env/4`](http://github.com/esl/gproc/blob/master/doc/gproc.md#get_set_env-4) and
 [`gproc:set_env/5`](http://github.com/esl/gproc/blob/master/doc/gproc.md#set_env-5) for details.
 
-##Testing##
 
+## Testing ##
 
 Gproc has a QuickCheck test suite, covering a fairly large part of the local
 gproc functionality, although none of the global registry. It requires a
@@ -88,16 +91,17 @@ available, and if it isn't, the code in gproc_eqc.erl will be "defined away".
 There is also an eunit suite, covering the basic operations for local and
 global gproc.
 
-##Building Edoc##
 
+## Building Edoc ##
 
 
 By default, `./rebar doc` generates Github-flavored Markdown files.
-If you want to change this, remove the `edoc_opts` line from `rebar.config`.Gproc was first introduced at the ACM SIGPLAN Erlang Workshop in
+If you want to change this, remove the `edoc_opts` line from `rebar.config`.
+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)).
 
 
-##Modules##
+## Modules ##
 
 
 <table width="100%" border="0" summary="list of modules">
@@ -110,5 +114,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_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_ps.md" class="module">gproc_ps</a></td></tr>
+<tr><td><a href="http://github.com/esl/gproc/blob/master/doc/gproc_pt.md" class="module">gproc_pt</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>
 

+ 20 - 15
doc/README.md

@@ -1,17 +1,17 @@
 
 
-#The gproc application#
-
+# The gproc application #
 
 __Authors:__ Ulf Wiger ([`ulf.wiger@erlang-solutions.com`](mailto:ulf.wiger@erlang-solutions.com)), Joseph Wayne Norton ([`norton@geminimobile.com`](mailto:norton@geminimobile.com)).
 
 Extended process dictionary
 
-##Note##
 
+## Note ##
 
 Gproc has two dependencies: `gen_leader` and `edown`. Since most people don't
 actively use either, they are no longer fetched by default.
+
 * To enable fetching of `gen_leader`, export the OS environment variable`GPROC_DIST=true` (this can be done e.g. from a GNU Makefile)
 
 * `edown` is fetched on-demand whenver `rebar get-deps doc` is called (which
@@ -19,10 +19,10 @@ actively use either, they are no longer fetched by default.
 
 
 
-##Introduction##
-
+## Introduction ##
 
 Gproc is a process dictionary for Erlang, which provides a number of useful features beyond what the built-in dictionary has:
+
 * Use any term as a process alias
 
 * Register a process under several aliases
@@ -43,8 +43,7 @@ Gproc is a process dictionary for Erlang, which provides a number of useful feat
 
 
 
-###Use case: System inspection##
-
+### Use case: System inspection ###
 
 Gproc was designed to work as a central index for "process metadata", i.e.
 properties that describe the role and characteristics of each process. Having
@@ -52,11 +51,14 @@ a single registry that is flexible enough to hold important types of property
 makes it easier to (a) find processes of a certain type, and (b) query and
 browse key data in a running system.
 
-###Use case: Pub/Sub patterns##
 
+### Use case: Pub/Sub patterns ###
 
 An interesting application of gproc is building publish/subscribe patterns.
-Example:<pre>
+Example:
+
+```
+
 subscribe(EventType) ->
     %% Gproc notation: {p, l, Name} means {(p)roperty, (l)ocal, Name}
     gproc:reg({p, l, {?MODULE, EventType}}).
@@ -64,10 +66,11 @@ subscribe(EventType) ->
 notify(EventType, Msg) ->
     Key = {?MODULE, EventType},
     gproc:send({p, l, Key}, {self(), Key, Msg}).
-</pre>
 
-###Use case: Environment handling##
+```
+
 
+### Use case: Environment handling ###
 
 Gproc provides a set of functions to read environment variables, possibly from
 alternative sources, and cache them for efficient lookup. Caching also provides
@@ -77,8 +80,8 @@ which values they actually ended up using.
 See [`gproc:get_env/4`](gproc.md#get_env-4), [`gproc:get_set_env/4`](gproc.md#get_set_env-4) and
 [`gproc:set_env/5`](gproc.md#set_env-5) for details.
 
-##Testing##
 
+## Testing ##
 
 Gproc has a QuickCheck test suite, covering a fairly large part of the local
 gproc functionality, although none of the global registry. It requires a
@@ -88,16 +91,17 @@ available, and if it isn't, the code in gproc_eqc.erl will be "defined away".
 There is also an eunit suite, covering the basic operations for local and
 global gproc.
 
-##Building Edoc##
 
+## Building Edoc ##
 
 
 By default, `./rebar doc` generates Github-flavored Markdown files.
-If you want to change this, remove the `edoc_opts` line from `rebar.config`.Gproc was first introduced at the ACM SIGPLAN Erlang Workshop in
+If you want to change this, remove the `edoc_opts` line from `rebar.config`.
+Gproc was first introduced at the ACM SIGPLAN Erlang Workshop in
 Freiburg 2007 ([Paper available here](erlang07-wiger.pdf)).
 
 
-##Modules##
+## Modules ##
 
 
 <table width="100%" border="0" summary="list of modules">
@@ -110,5 +114,6 @@ Freiburg 2007 ([Paper available here](erlang07-wiger.pdf)).
 <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_ps.md" class="module">gproc_ps</a></td></tr>
+<tr><td><a href="gproc_pt.md" class="module">gproc_pt</a></td></tr>
 <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}.
 {packages,[]}.
 {modules,[gproc,gproc_app,gproc_bcast,gproc_dist,gproc_info,gproc_init,
-          gproc_lib,gproc_monitor,gproc_ps,gproc_sup]}.
+          gproc_lib,gproc_monitor,gproc_ps,gproc_pt,gproc_sup]}.

+ 678 - 326
doc/gproc.md

@@ -1,6 +1,6 @@
 
 
-#Module gproc#
+# Module gproc #
 * [Description](#description)
 * [Data Types](#types)
 * [Function Index](#index)
@@ -9,13 +9,12 @@
 
 Extended process registry
 This module implements an extended process registry.
-
 __Behaviours:__ [`gen_server`](gen_server.md).
 
-__Authors:__ Ulf Wiger ([`ulf@wiger.net`](mailto:ulf@wiger.net)).<a name="description"></a>
-
-##Description##
+__Authors:__ Ulf Wiger ([`ulf@wiger.net`](mailto:ulf@wiger.net)).
+<a name="description"></a>
 
+## Description ##
 
 
 
@@ -24,8 +23,8 @@ For a detailed description, see
 
 
 
-##Tuning Gproc performance##
 
+## Tuning Gproc performance ##
 
 
 
@@ -35,6 +34,7 @@ sacrificing consistency. A few things can be tuned by setting the following
 application environment variables in the top application of `gproc`
 (usually `gproc`):
 
+
 * `{ets_options, list()}` - Currently, the options `{write_concurrency, F}`
 and `{read_concurrency, F}` are allowed. The default is
 `[{write_concurrency, true}, {read_concurrency, true}]`
@@ -45,166 +45,238 @@ will improve performance.
 
 <a name="types"></a>
 
-##Data Types##
+## Data Types ##
+
 
 
 
+### <a name="type-context">context()</a> ###
 
-###<a name="type-context">context()</a>##
 
 
+<pre><code>
+context() = {<a href="#type-scope">scope()</a>, <a href="#type-type">type()</a>} | <a href="#type-type">type()</a>
+</code></pre>
 
-<pre>context() = {<a href="#type-scope">scope()</a>, <a href="#type-type">type()</a>} | <a href="#type-type">type()</a></pre>
 
 
 {'all','all'} is the default
 
 
 
-###<a name="type-ctr_incr">ctr_incr()</a>##
+
+### <a name="type-ctr_incr">ctr_incr()</a> ###
+
+
+
+<pre><code>
+ctr_incr() = integer()
+</code></pre>
+
+
+
+
+
+### <a name="type-ctr_setval">ctr_setval()</a> ###
 
 
 
-<pre>ctr_incr() = integer()</pre>
+<pre><code>
+ctr_setval() = integer()
+</code></pre>
 
 
 
-###<a name="type-ctr_setval">ctr_setval()</a>##
 
 
+### <a name="type-ctr_thr">ctr_thr()</a> ###
 
-<pre>ctr_setval() = integer()</pre>
 
 
+<pre><code>
+ctr_thr() = integer()
+</code></pre>
 
-###<a name="type-ctr_thr">ctr_thr()</a>##
 
 
 
-<pre>ctr_thr() = integer()</pre>
 
+### <a name="type-ctr_update">ctr_update()</a> ###
 
 
-###<a name="type-ctr_update">ctr_update()</a>##
 
+<pre><code>
+ctr_update() = <a href="#type-ctr_incr">ctr_incr()</a> | {<a href="#type-ctr_incr">ctr_incr()</a>, <a href="#type-ctr_thr">ctr_thr()</a>, <a href="#type-ctr_setval">ctr_setval()</a>}
+</code></pre>
 
 
-<pre>ctr_update() = <a href="#type-ctr_incr">ctr_incr()</a> | {<a href="#type-ctr_incr">ctr_incr()</a>, <a href="#type-ctr_thr">ctr_thr()</a>, <a href="#type-ctr_setval">ctr_setval()</a>}</pre>
 
 
 
-###<a name="type-headpat">headpat()</a>##
+### <a name="type-headpat">headpat()</a> ###
 
 
 
-<pre>headpat() = {<a href="#type-keypat">keypat()</a>, <a href="#type-pidpat">pidpat()</a>, ValPat}</pre>
+<pre><code>
+headpat() = {<a href="#type-keypat">keypat()</a>, <a href="#type-pidpat">pidpat()</a>, ValPat}
+</code></pre>
 
 
 
-###<a name="type-increment">increment()</a>##
 
 
+### <a name="type-increment">increment()</a> ###
 
-<pre>increment() = <a href="#type-ctr_incr">ctr_incr()</a> | <a href="#type-ctr_update">ctr_update()</a> | [<a href="#type-ctr_update">ctr_update()</a>]</pre>
 
 
+<pre><code>
+increment() = <a href="#type-ctr_incr">ctr_incr()</a> | <a href="#type-ctr_update">ctr_update()</a> | [<a href="#type-ctr_update">ctr_update()</a>]
+</code></pre>
 
-###<a name="type-key">key()</a>##
 
 
 
-<pre>key() = {<a href="#type-type">type()</a>, <a href="#type-scope">scope()</a>, any()}</pre>
+
+### <a name="type-key">key()</a> ###
+
+
+
+<pre><code>
+key() = {<a href="#type-type">type()</a>, <a href="#type-scope">scope()</a>, any()}
+</code></pre>
+
 
 
 update_counter increment
 
 
-###<a name="type-keypat">keypat()</a>##
+
+### <a name="type-keypat">keypat()</a> ###
+
+
+
+<pre><code>
+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()}
+</code></pre>
+
+
+
 
 
+### <a name="type-pidpat">pidpat()</a> ###
 
-<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>
 
 
+<pre><code>
+pidpat() = pid() | <a href="#type-sel_var">sel_var()</a>
+</code></pre>
 
-###<a name="type-pidpat">pidpat()</a>##
 
 
 
-<pre>pidpat() = pid() | <a href="#type-sel_var">sel_var()</a></pre>
 
+### <a name="type-reg_id">reg_id()</a> ###
 
 
-###<a name="type-reg_id">reg_id()</a>##
 
+<pre><code>
+reg_id() = {<a href="#type-type">type()</a>, <a href="#type-scope">scope()</a>, any()}
+</code></pre>
 
 
-<pre>reg_id() = {<a href="#type-type">type()</a>, <a href="#type-scope">scope()</a>, any()}</pre>
 
 
 
-###<a name="type-scope">scope()</a>##
+### <a name="type-scope">scope()</a> ###
 
 
 
-<pre>scope() = l | g</pre>
+<pre><code>
+scope() = l | g
+</code></pre>
+
 
 
 l = local registration; g = global registration
 
 
 
-###<a name="type-sel_pattern">sel_pattern()</a>##
+
+### <a name="type-sel_pattern">sel_pattern()</a> ###
+
+
+
+<pre><code>
+sel_pattern() = [{<a href="#type-headpat">headpat()</a>, Guards, Prod}]
+</code></pre>
+
 
 
 
-<pre>sel_pattern() = [{<a href="#type-headpat">headpat()</a>, Guards, Prod}]</pre>
 
+### <a name="type-sel_scope">sel_scope()</a> ###
 
 
-###<a name="type-sel_scope">sel_scope()</a>##
 
+<pre><code>
+sel_scope() = scope | all | global | local
+</code></pre>
 
 
-<pre>sel_scope() = scope | all | global | local</pre>
 
 
 
-###<a name="type-sel_type">sel_type()</a>##
+### <a name="type-sel_type">sel_type()</a> ###
 
 
 
-<pre>sel_type() = <a href="#type-type">type()</a> | names | props | counters | aggr_counters</pre>
+<pre><code>
+sel_type() = <a href="#type-type">type()</a> | names | props | counters | aggr_counters
+</code></pre>
 
 
 
-###<a name="type-sel_var">sel_var()</a>##
 
 
+### <a name="type-sel_var">sel_var()</a> ###
 
-<pre>sel_var() = DollarVar | '_'</pre>
 
 
+<pre><code>
+sel_var() = DollarVar | '_'
+</code></pre>
 
-###<a name="type-type">type()</a>##
 
 
 
-<pre>type() = n | p | c | a</pre>
+
+### <a name="type-type">type()</a> ###
+
+
+
+<pre><code>
+type() = n | p | c | a
+</code></pre>
+
 
 
 n = name; p = property; c = counter;
 a = aggregate_counter
 
 
-###<a name="type-unique_id">unique_id()</a>##
+
+### <a name="type-unique_id">unique_id()</a> ###
 
 
 
-<pre>unique_id() = {n | a, <a href="#type-scope">scope()</a>, any()}</pre>
+<pre><code>
+unique_id() = {n | a, <a href="#type-scope">scope()</a>, any()}
+</code></pre>
+
+
 <a name="index"></a>
 
-##Function Index##
+## 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="#await-3">await/3</a></td><td>Wait for a local name to be registered on <code>Node</code>.</td></tr><tr><td valign="top"><a href="#bcast-2">bcast/2</a></td><td>Equivalent to <a href="#bcast-3"><tt>bcast(nodes(), Key, Msg)</tt></a>.</td></tr><tr><td valign="top"><a href="#bcast-3">bcast/3</a></td><td>Sends a message to processes corresponding to Key on Nodes.</td></tr><tr><td valign="top"><a href="#cancel_wait-2">cancel_wait/2</a></td><td>Cancels a previous call to nb_wait/1.</td></tr><tr><td valign="top"><a href="#cancel_wait-3">cancel_wait/3</a></td><td>Cancels a previous call to nb_wait/2.</td></tr><tr><td valign="top"><a href="#cancel_wait_or_monitor-1">cancel_wait_or_monitor/1</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
@@ -217,102 +289,113 @@ a unique name registered via gproc.</td></tr><tr><td valign="top"><a href="#mreg
 
 <a name="functions"></a>
 
-##Function Details##
+## Function Details ##
 
 <a name="add_global_aggr_counter-1"></a>
 
-###add_global_aggr_counter/1##
-
+### add_global_aggr_counter/1 ###
 
 `add_global_aggr_counter(Name) -> any()`
 
 Equivalent to [`reg({a, g, Name})`](#reg-1).
 
-Registers a global (unique) aggregated counter.<a name="add_global_counter-2"></a>
-
-###add_global_counter/2##
+Registers a global (unique) aggregated counter.
+<a name="add_global_counter-2"></a>
 
+### add_global_counter/2 ###
 
 `add_global_counter(Name, Initial) -> any()`
 
-Registers a global (non-unique) counter. @equiv reg({c,g,Name},Value)<a name="add_global_name-1"></a>
-
-###add_global_name/1##
+Registers a global (non-unique) counter. @equiv reg({c,g,Name},Value)
+<a name="add_global_name-1"></a>
 
+### add_global_name/1 ###
 
 `add_global_name(Name) -> any()`
 
-Registers a global (unique) name. @equiv reg({n,g,Name})<a name="add_global_property-2"></a>
-
-###add_global_property/2##
+Registers a global (unique) name. @equiv reg({n,g,Name})
+<a name="add_global_property-2"></a>
 
+### add_global_property/2 ###
 
 `add_global_property(Name, Value) -> any()`
 
-Registers a global (non-unique) property. @equiv reg({p,g,Name},Value)<a name="add_local_aggr_counter-1"></a>
-
-###add_local_aggr_counter/1##
+Registers a global (non-unique) property. @equiv reg({p,g,Name},Value)
+<a name="add_local_aggr_counter-1"></a>
 
+### add_local_aggr_counter/1 ###
 
 `add_local_aggr_counter(Name) -> any()`
 
 Equivalent to [`reg({a, l, Name})`](#reg-1).
 
-Registers a local (unique) aggregated counter.<a name="add_local_counter-2"></a>
-
-###add_local_counter/2##
+Registers a local (unique) aggregated counter.
+<a name="add_local_counter-2"></a>
 
+### add_local_counter/2 ###
 
 `add_local_counter(Name, Initial) -> any()`
 
-Registers a local (non-unique) counter. @equiv reg({c,l,Name},Value)<a name="add_local_name-1"></a>
-
-###add_local_name/1##
+Registers a local (non-unique) counter. @equiv reg({c,l,Name},Value)
+<a name="add_local_name-1"></a>
 
+### add_local_name/1 ###
 
 `add_local_name(Name) -> any()`
 
-Registers a local (unique) name. @equiv reg({n,l,Name})<a name="add_local_property-2"></a>
-
-###add_local_property/2##
+Registers a local (unique) name. @equiv reg({n,l,Name})
+<a name="add_local_property-2"></a>
 
+### add_local_property/2 ###
 
 `add_local_property(Name, Value) -> any()`
 
-Registers a local (non-unique) property. @equiv reg({p,l,Name},Value)<a name="add_shared_local_counter-2"></a>
-
-###add_shared_local_counter/2##
+Registers a local (non-unique) property. @equiv reg({p,l,Name},Value)
+<a name="add_shared_local_counter-2"></a>
 
+### add_shared_local_counter/2 ###
 
 `add_shared_local_counter(Name, Initial) -> any()`
 
 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>
+
+### audit_process/1 ###
 
-###audit_process/1##
 
+<pre><code>
+audit_process(Pid::pid()) -&gt; ok
+</code></pre>
 
-<pre>audit_process(Pid::pid()) -&gt; ok</pre>
 <br></br>
 
 
+
 <a name="await-1"></a>
 
-###await/1##
+### await/1 ###
+
 
+<pre><code>
+await(Key::<a href="#type-key">key()</a>) -&gt; {pid(), Value}
+</code></pre>
 
-<pre>await(Key::<a href="#type-key">key()</a>) -> {pid(), Value}</pre>
 <br></br>
 
 
-Equivalent to [`await(Key, infinity)`](#await-2).<a name="await-2"></a>
+Equivalent to [`await(Key, infinity)`](#await-2).
+<a name="await-2"></a>
+
+### await/2 ###
 
-###await/2##
 
+<pre><code>
+await(Key::<a href="#type-key">key()</a>, Timeout) -&gt; {pid(), Value}
+</code></pre>
 
-<pre>await(Key::<a href="#type-key">key()</a>, Timeout) -> {pid(), Value}</pre>
-<ul class="definitions"><li><pre>Timeout = integer() | infinity</pre></li></ul>
+<ul class="definitions"><li><code>Timeout = integer() | infinity</code></li></ul>
 
 Wait for a local name to be registered.
 The function raises an exception if the timeout expires. Timeout must be
@@ -320,128 +403,163 @@ either an interger > 0 or 'infinity'.
 A small optimization: we first perform a lookup, to see if the name
 is already registered. This way, the cost of the operation will be
 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="await-3"></a>
+registered (the difference: await/2 also returns the value).
+<a name="await-3"></a>
 
-###await/3##
+### await/3 ###
 
 
-<pre>await(Node::node(), Key::<a href="#type-key">key()</a>, Timeout) -> {pid(), Value}</pre>
-<ul class="definitions"><li><pre>Timeout = integer() | infinity</pre></li></ul>
+<pre><code>
+await(Node::node(), Key::<a href="#type-key">key()</a>, Timeout) -&gt; {pid(), Value}
+</code></pre>
+
+<ul class="definitions"><li><code>Timeout = integer() | infinity</code></li></ul>
 
 Wait for a local name to be registered on `Node`.
 This function works exactly like [`await/2`](#await-2), but queries a remote
 node instead. An exception is thrown if `Node` cannot be reached. If gproc
 is not running on a given node, this is treated the same as the node being
-down.<a name="bcast-2"></a>
+down.
+<a name="bcast-2"></a>
+
+### bcast/2 ###
 
-###bcast/2##
 
+<pre><code>
+bcast(Key::<a href="#type-key">key()</a>, Msg::any()) -&gt; Msg
+</code></pre>
 
-<pre>bcast(Key::<a href="#type-key">key()</a>, Msg::any()) -> Msg</pre>
 <br></br>
 
 
-Equivalent to [`bcast(nodes(), Key, Msg)`](#bcast-3).<a name="bcast-3"></a>
+Equivalent to [`bcast(nodes(), Key, Msg)`](#bcast-3).
+<a name="bcast-3"></a>
 
-###bcast/3##
+### bcast/3 ###
 
 
-<pre>bcast(Nodes::[atom()], Key::<a href="#type-key">key()</a>, Msg::any()) -> Msg</pre>
-<br></br>
+<pre><code>
+bcast(Nodes::[atom()], Key::<a href="#type-key">key()</a>, Msg::any()) -&gt; Msg
+</code></pre>
 
+<br></br>
 
 
 
 Sends a message to processes corresponding to Key on Nodes.
 
+
 This function complements `send/2` and works on locally registered resources
 that `send/2` supports. Messages are routed via a special broadcast server
 on each node to ensure that ordering is preserved. Distributed delivery
 is asynchronous and carries the same guarantees as normal message passing
 (with the added proviso that the broadcast server also needs to be available).
 
-__See also:__ [send/2](#send-2).<a name="cancel_wait-2"></a>
+__See also:__ [send/2](#send-2).
+<a name="cancel_wait-2"></a>
 
-###cancel_wait/2##
+### cancel_wait/2 ###
 
 
-<pre>cancel_wait(Key::<a href="#type-key">key()</a>, Ref) -> ok</pre>
-<ul class="definitions"><li><pre>Ref = all | reference()</pre></li></ul>
+<pre><code>
+cancel_wait(Key::<a href="#type-key">key()</a>, Ref) -&gt; ok
+</code></pre>
 
+<ul class="definitions"><li><code>Ref = all | reference()</code></li></ul>
 
 
 Cancels a previous call to nb_wait/1
 
+
 If `Ref = all`, all wait requests on `Key` from the calling process
-are canceled.<a name="cancel_wait-3"></a>
+are canceled.
+<a name="cancel_wait-3"></a>
 
-###cancel_wait/3##
+### cancel_wait/3 ###
 
 
-<pre>cancel_wait(Node::node(), Key::<a href="#type-key">key()</a>, Ref) -> ok</pre>
-<ul class="definitions"><li><pre>Ref = all | reference()</pre></li></ul>
+<pre><code>
+cancel_wait(Node::node(), Key::<a href="#type-key">key()</a>, Ref) -&gt; ok
+</code></pre>
 
+<ul class="definitions"><li><code>Ref = all | reference()</code></li></ul>
 
 
 Cancels a previous call to nb_wait/2
 
-This function works just like [`cancel_wait/2`](#cancel_wait-2), but talks to a remote
-node.<a name="cancel_wait_or_monitor-1"></a>
 
-###cancel_wait_or_monitor/1##
+This function works just like [`cancel_wait/2`](#cancel_wait-2), but talks to a remote
+node.
+<a name="cancel_wait_or_monitor-1"></a>
 
+### cancel_wait_or_monitor/1 ###
 
 `cancel_wait_or_monitor(Key) -> any()`
 
-<a name="default-1"></a>
 
-###default/1##
+<a name="default-1"></a>
 
+### default/1 ###
 
 `default(X1) -> any()`
 
+
 <a name="demonitor-2"></a>
 
-###demonitor/2##
+### demonitor/2 ###
+
 
+<pre><code>
+demonitor(Key::<a href="#type-key">key()</a>, Ref::reference()) -&gt; ok
+</code></pre>
 
-<pre>demonitor(Key::<a href="#type-key">key()</a>, Ref::reference()) -> ok</pre>
 <br></br>
 
 
 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>
+set on a unique name. This function always succeeds given legal input.
+<a name="first-1"></a>
 
-###first/1##
+### first/1 ###
 
 
-<pre>first(Context::<a href="#type-context">context()</a>) -> <a href="#type-key">key()</a> | '$end_of_table'</pre>
-<br></br>
+<pre><code>
+first(Context::<a href="#type-context">context()</a>) -&gt; <a href="#type-key">key()</a> | '$end_of_table'
+</code></pre>
 
+<br></br>
 
 
 
 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).
-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>
 
-###get_env/3##
+### get_env/3 ###
 
 
-<pre>get_env(Scope::<a href="#type-scope">scope()</a>, App::atom(), Key::atom()) -> term()</pre>
+<pre><code>
+get_env(Scope::<a href="#type-scope">scope()</a>, App::atom(), Key::atom()) -&gt; term()
+</code></pre>
+
 <br></br>
 
 
-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>
 
-###get_env/4##
+### 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><code>
+get_env(Scope::<a href="#type-scope">scope()</a>, App::atom(), Key::atom(), Strategy) -&gt; term()
+</code></pre>
 
+<ul class="definitions"><li><code>Strategy = [Alternative]</code></li><li><code>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</code></li></ul>
 
 
 Read an environment value, potentially cached as a `gproc_env` property.
@@ -487,71 +605,91 @@ whichever comes first
 * The last instance of `{default, Value}`, or `undefined`, if there is no
 matching alternative, default or `error` entry in the list.
 
+
 The `error` option can be used to assert that a value has been previously
 cached. Alternatively, it can be used to assert that a value is either cached
 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>
+
+### get_set_env/3 ###
 
-###get_set_env/3##
 
+<pre><code>
+get_set_env(Scope::<a href="#type-scope">scope()</a>, App::atom(), Key::atom()) -&gt; term()
+</code></pre>
 
-<pre>get_set_env(Scope::<a href="#type-scope">scope()</a>, App::atom(), Key::atom()) -> term()</pre>
 <br></br>
 
 
-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>
 
-###get_set_env/4##
+### get_set_env/4 ###
 
 
-<pre>get_set_env(Scope::<a href="#type-scope">scope()</a>, App::atom(), Key::atom(), Strategy) -> Value</pre>
-<br></br>
+<pre><code>
+get_set_env(Scope::<a href="#type-scope">scope()</a>, App::atom(), Key::atom(), Strategy) -&gt; Value
+</code></pre>
 
+<br></br>
 
 
 
 Fetch and cache an environment value, if not already cached.
 
+
 This function does the same thing as [`get_env/4`](#get_env-4), but also updates the
 cache. Note that the cache will be updated even if the result of the lookup
 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>
 
-###get_value/1##
+### get_value/1 ###
 
 
-<pre>get_value(Key) -&gt; Value</pre>
-<br></br>
+<pre><code>
+get_value(Key) -&gt; Value
+</code></pre>
 
+<br></br>
 
 
 
 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>
 
-###get_value/2##
+If no such key is registered to the current process, this function exits.
+<a name="get_value-2"></a>
 
+### get_value/2 ###
 
-<pre>get_value(Key, Pid) -&gt; Value</pre>
-<br></br>
 
+<pre><code>
+get_value(Key, Pid) -&gt; Value
+</code></pre>
+
+<br></br>
 
 
 
 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))
-will be read.<a name="give_away-2"></a>
+will be read.
+<a name="give_away-2"></a>
 
-###give_away/2##
+### give_away/2 ###
 
 
-<pre>give_away(From::<a href="#type-key">key()</a>, To::pid() | <a href="#type-key">key()</a>) -> undefined | pid()</pre>
-<br></br>
+<pre><code>
+give_away(From::<a href="#type-key">key()</a>, To::pid() | <a href="#type-key">key()</a>) -&gt; undefined | pid()
+</code></pre>
 
+<br></br>
 
 
 
@@ -574,227 +712,299 @@ and the `From` key is effectively unregistered.
 It is allowed to give away a key to oneself, but of course, this operation
 will have no effect.
 
+
 Fails with `badarg` if the calling process does not have a `From` key
-registered.<a name="goodbye-0"></a>
+registered.
+<a name="goodbye-0"></a>
 
-###goodbye/0##
+### goodbye/0 ###
 
 
-<pre>goodbye() -&gt; ok</pre>
-<br></br>
+<pre><code>
+goodbye() -&gt; ok
+</code></pre>
 
+<br></br>
 
 
 
 Unregister all items of the calling process and inform gproc
 to forget about the calling process.
 
+
 This function is more efficient than letting gproc perform these
-cleanup operations.<a name="i-0"></a>
+cleanup operations.
+<a name="i-0"></a>
 
-###i/0##
+### i/0 ###
 
 
-<pre>i() -&gt; ok</pre>
+<pre><code>
+i() -&gt; ok
+</code></pre>
+
 <br></br>
 
 
 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>
 
-###info/1##
+### info/1 ###
 
 
-<pre>info(Pid::pid()) -&gt; ProcessInfo</pre>
-<ul class="definitions"><li><pre>ProcessInfo = [{gproc, [{Key, Value}]} | ProcessInfo]</pre></li></ul>
+<pre><code>
+info(Pid::pid()) -&gt; ProcessInfo
+</code></pre>
 
+<ul class="definitions"><li><code>ProcessInfo = [{gproc, [{Key, Value}]} | ProcessInfo]</code></li></ul>
 
 
 Similar to `process_info(Pid)` but with additional gproc info.
 
+
 Returns the same information as process_info(Pid), but with the
 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>
 
-###info/2##
+### info/2 ###
 
 
-<pre>info(Pid::pid(), Item::atom()) -&gt; {Item, Info}</pre>
-<br></br>
+<pre><code>
+info(Pid::pid(), Item::atom()) -&gt; {Item, Info}
+</code></pre>
 
+<br></br>
 
 
 
 Similar to process_info(Pid, Item), but with additional gproc info.
 
+
 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
-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>
 
-###last/1##
+### last/1 ###
 
 
-<pre>last(Context::<a href="#type-context">context()</a>) -> <a href="#type-key">key()</a> | '$end_of_table'</pre>
-<br></br>
+<pre><code>
+last(Context::<a href="#type-context">context()</a>) -&gt; <a href="#type-key">key()</a> | '$end_of_table'
+</code></pre>
 
+<br></br>
 
 
 
 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).
-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>
+
+### lookup_global_aggr_counter/1 ###
 
-###lookup_global_aggr_counter/1##
 
+<pre><code>
+lookup_global_aggr_counter(Name::any()) -&gt; integer()
+</code></pre>
 
-<pre>lookup_global_aggr_counter(Name::any()) -&gt; integer()</pre>
 <br></br>
 
 
 Equivalent to [`where({a, g, Name})`](#where-1).
 
 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>
 
-###lookup_global_counters/1##
+### lookup_global_counters/1 ###
 
 
-<pre>lookup_global_counters(Counter::any()) -&gt; [{pid(), Value::integer()}]</pre>
+<pre><code>
+lookup_global_counters(Counter::any()) -&gt; [{pid(), Value::integer()}]
+</code></pre>
+
 <br></br>
 
 
 Equivalent to [`lookup_values({c, g, Counter})`](#lookup_values-1).
 
 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>
+
+### lookup_global_name/1 ###
 
-###lookup_global_name/1##
 
+<pre><code>
+lookup_global_name(Name::any()) -&gt; pid()
+</code></pre>
 
-<pre>lookup_global_name(Name::any()) -&gt; pid()</pre>
 <br></br>
 
 
 Equivalent to [`where({n, g, Name})`](#where-1).
 
-Lookup a global unique name. Fails if there is no such name.<a name="lookup_global_properties-1"></a>
+Lookup a global unique name. Fails if there is no such name.
+<a name="lookup_global_properties-1"></a>
+
+### lookup_global_properties/1 ###
 
-###lookup_global_properties/1##
 
+<pre><code>
+lookup_global_properties(Property::any()) -&gt; [{pid(), Value}]
+</code></pre>
 
-<pre>lookup_global_properties(Property::any()) -&gt; [{pid(), Value}]</pre>
 <br></br>
 
 
 Equivalent to [`lookup_values({p, g, Property})`](#lookup_values-1).
 
 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>
 
-###lookup_local_aggr_counter/1##
+### lookup_local_aggr_counter/1 ###
 
 
-<pre>lookup_local_aggr_counter(Name::any()) -&gt; integer()</pre>
+<pre><code>
+lookup_local_aggr_counter(Name::any()) -&gt; integer()
+</code></pre>
+
 <br></br>
 
 
 Equivalent to [`where({a, l, Name})`](#where-1).
 
 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>
+
+### lookup_local_counters/1 ###
 
-###lookup_local_counters/1##
 
+<pre><code>
+lookup_local_counters(Counter::any()) -&gt; [{pid(), Value::integer()}]
+</code></pre>
 
-<pre>lookup_local_counters(Counter::any()) -&gt; [{pid(), Value::integer()}]</pre>
 <br></br>
 
 
 Equivalent to [`lookup_values({c, l, Counter})`](#lookup_values-1).
 
 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>
 
-###lookup_local_name/1##
+### lookup_local_name/1 ###
 
 
-<pre>lookup_local_name(Name::any()) -&gt; pid()</pre>
+<pre><code>
+lookup_local_name(Name::any()) -&gt; pid()
+</code></pre>
+
 <br></br>
 
 
 Equivalent to [`where({n, l, Name})`](#where-1).
 
-Lookup a local unique name. Fails if there is no such name.<a name="lookup_local_properties-1"></a>
+Lookup a local unique name. Fails if there is no such name.
+<a name="lookup_local_properties-1"></a>
+
+### lookup_local_properties/1 ###
 
-###lookup_local_properties/1##
 
+<pre><code>
+lookup_local_properties(Property::any()) -&gt; [{pid(), Value}]
+</code></pre>
 
-<pre>lookup_local_properties(Property::any()) -&gt; [{pid(), Value}]</pre>
 <br></br>
 
 
 Equivalent to [`lookup_values({p, l, Property})`](#lookup_values-1).
 
 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>
 
-###lookup_pid/1##
+### lookup_pid/1 ###
 
 
-<pre>lookup_pid(Key) -&gt; Pid</pre>
+<pre><code>
+lookup_pid(Key) -&gt; Pid
+</code></pre>
+
 <br></br>
 
 
 Lookup the Pid stored with a key.
+
 <a name="lookup_pids-1"></a>
 
-###lookup_pids/1##
+### lookup_pids/1 ###
 
 
-<pre>lookup_pids(Key::<a href="#type-key">key()</a>) -> [pid()]</pre>
-<br></br>
+<pre><code>
+lookup_pids(Key::<a href="#type-key">key()</a>) -&gt; [pid()]
+</code></pre>
 
+<br></br>
 
 
 
 Returns a list of pids with the published key Key
 
+
 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.
-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>
+
+### lookup_value/1 ###
 
-###lookup_value/1##
 
+<pre><code>
+lookup_value(Key) -&gt; Value
+</code></pre>
 
-<pre>lookup_value(Key) -&gt; Value</pre>
 <br></br>
 
 
 Lookup the value stored with a key.
+
 <a name="lookup_values-1"></a>
 
-###lookup_values/1##
+### lookup_values/1 ###
 
 
-<pre>lookup_values(Key::<a href="#type-key">key()</a>) -> [{pid(), Value}]</pre>
-<br></br>
+<pre><code>
+lookup_values(Key::<a href="#type-key">key()</a>) -&gt; [{pid(), Value}]
+</code></pre>
 
+<br></br>
 
 
 
 Retrieve the `{Pid,Value}` pairs corresponding to Key.
 
+
 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 return value can be a list of any length.<a name="monitor-1"></a>
+object, the return value can be a list of any length.
+<a name="monitor-1"></a>
 
-###monitor/1##
+### monitor/1 ###
 
 
-<pre>monitor(Key::<a href="#type-key">key()</a>) -> reference()</pre>
-<br></br>
+<pre><code>
+monitor(Key::<a href="#type-key">key()</a>) -&gt; reference()
+</code></pre>
 
+<br></br>
 
 
 
@@ -804,139 +1014,183 @@ 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##
+If the name is not yet registered, the same message is sent immediately.
+<a name="mreg-3"></a>
 
+### mreg/3 ###
 
-<pre>mreg(T::<a href="#type-type">type()</a>, C::<a href="#type-scope">scope()</a>, KVL::[{Key::any(), Value::any()}]) -> true</pre>
-<br></br>
 
+<pre><code>
+mreg(T::<a href="#type-type">type()</a>, C::<a href="#type-scope">scope()</a>, KVL::[{Key::any(), Value::any()}]) -&gt; true
+</code></pre>
+
+<br></br>
 
 
 
 Register multiple {Key,Value} pairs of a given type and scope.
 
+
 This function is more efficient than calling [`reg/2`](#reg-2) repeatedly.
 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>
 
-###munreg/3##
+### munreg/3 ###
 
 
-<pre>munreg(T::<a href="#type-type">type()</a>, C::<a href="#type-scope">scope()</a>, L::[Key::any()]) -> true</pre>
-<br></br>
+<pre><code>
+munreg(T::<a href="#type-type">type()</a>, C::<a href="#type-scope">scope()</a>, L::[Key::any()]) -&gt; true
+</code></pre>
 
+<br></br>
 
 
 
 Unregister multiple Key items of a given type and scope.
 
+
 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>
+
+### nb_wait/1 ###
 
-###nb_wait/1##
 
+<pre><code>
+nb_wait(Key::<a href="#type-key">key()</a>) -&gt; Ref
+</code></pre>
 
-<pre>nb_wait(Key::<a href="#type-key">key()</a>) -> Ref</pre>
 <br></br>
 
 
 Wait for a local name to be registered.
 The caller can expect to receive a message,
-{gproc, Ref, registered, {Key, Pid, Value}}, once the name is registered.<a name="nb_wait-2"></a>
+{gproc, Ref, registered, {Key, Pid, Value}}, once the name is registered.
+<a name="nb_wait-2"></a>
+
+### nb_wait/2 ###
 
-###nb_wait/2##
 
+<pre><code>
+nb_wait(Node::node(), Key::<a href="#type-key">key()</a>) -&gt; Ref
+</code></pre>
 
-<pre>nb_wait(Node::node(), Key::<a href="#type-key">key()</a>) -> Ref</pre>
 <br></br>
 
 
 Wait for a local name to be registered on `Node`.
 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>
 
-###next/2##
+### 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>
-<br></br>
+<pre><code>
+next(Context::<a href="#type-context">context()</a>, Key::<a href="#type-key">key()</a>) -&gt; <a href="#type-key">key()</a> | '$end_of_table'
+</code></pre>
 
+<br></br>
 
 
 
 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).
-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>
 
-###prev/2##
+### 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>
-<br></br>
+<pre><code>
+prev(Context::<a href="#type-context">context()</a>, Key::<a href="#type-key">key()</a>) -&gt; <a href="#type-key">key()</a> | '$end_of_table'
+</code></pre>
 
+<br></br>
 
 
 
 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).
-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>
 
-###reg/1##
+### reg/1 ###
 
 
-<pre>reg(Key::<a href="#type-key">key()</a>) -> true</pre>
+<pre><code>
+reg(Key::<a href="#type-key">key()</a>) -&gt; true
+</code></pre>
+
 <br></br>
 
 
-Equivalent to [`reg(Key, default(Key))`](#reg-2).<a name="reg-2"></a>
+Equivalent to [`reg(Key, default(Key))`](#reg-2).
+<a name="reg-2"></a>
 
-###reg/2##
+### reg/2 ###
 
 
-<pre>reg(Key::<a href="#type-key">key()</a>, Value) -> true</pre>
-<br></br>
+<pre><code>
+reg(Key::<a href="#type-key">key()</a>, Value) -&gt; true
+</code></pre>
 
+<br></br>
 
 
 
 Register a name or property for the current process
 
+
+
 <a name="reg_or_locate-1"></a>
 
-###reg_or_locate/1##
+### reg_or_locate/1 ###
+
 
+<pre><code>
+reg_or_locate(Key::<a href="#type-key">key()</a>) -&gt; true
+</code></pre>
 
-<pre>reg_or_locate(Key::<a href="#type-key">key()</a>) -> true</pre>
 <br></br>
 
 
-Equivalent to [`reg_or_locate(Key, default(Key))`](#reg_or_locate-2).<a name="reg_or_locate-2"></a>
+Equivalent to [`reg_or_locate(Key, default(Key))`](#reg_or_locate-2).
+<a name="reg_or_locate-2"></a>
 
-###reg_or_locate/2##
+### reg_or_locate/2 ###
 
 
-<pre>reg_or_locate(Key::<a href="#type-key">key()</a>, Value) -> {pid(), NewValue}</pre>
-<br></br>
+<pre><code>
+reg_or_locate(Key::<a href="#type-key">key()</a>, Value) -&gt; {pid(), NewValue}
+</code></pre>
 
+<br></br>
 
 
 
 Try registering a unique name, or return existing registration.
 
+
 This function tries to register the name `Key`, if available.
 If such a registration already exists, the pid and value of
-the current registration is returned instead.<a name="reg_or_locate-3"></a>
+the current registration is returned instead.
+<a name="reg_or_locate-3"></a>
 
-###reg_or_locate/3##
+### reg_or_locate/3 ###
 
 
-<pre>reg_or_locate(Key::<a href="#type-key">key()</a>, Value, Fun::function()) -> {pid(), NewValue}</pre>
-<br></br>
+<pre><code>
+reg_or_locate(Key::<a href="#type-key">key()</a>, Value, Fun::function()) -&gt; {pid(), NewValue}
+</code></pre>
 
+<br></br>
 
 
 
@@ -948,30 +1202,38 @@ This function checks whether a local name is registered; if not, it spawns
 a new process (with `spawn(Fun)`) and gives it the name.
 The pid and value of the resulting registration is returned.
 
+
 This function is only available for local registration. While it could
 theoretically be done in the global case, the spawning of a new process
-on a remote node by the leader instance is more problematic.<a name="reg_shared-1"></a>
+on a remote node by the leader instance is more problematic.
+<a name="reg_shared-1"></a>
 
-###reg_shared/1##
+### reg_shared/1 ###
 
 
-<pre>reg_shared(Key::<a href="#type-key">key()</a>) -> true</pre>
-<br></br>
+<pre><code>
+reg_shared(Key::<a href="#type-key">key()</a>) -&gt; true
+</code></pre>
 
+<br></br>
 
 
 
 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({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>
 
-###reg_shared/2##
+### reg_shared/2 ###
 
 
-<pre>reg_shared(Key::<a href="#type-key">key()</a>, Value) -> true</pre>
-<br></br>
+<pre><code>
+reg_shared(Key::<a href="#type-key">key()</a>, Value) -&gt; true
+</code></pre>
 
+<br></br>
 
 
 
@@ -986,39 +1248,51 @@ results, shared resources appear as other similar resources, except that
 `Pid == shared`. To wit, update_counter({c,l,myCounter}, 1, shared) would
 increment the shared counter `myCounter` with 1, provided it exists.
 
+
 A shared aggregated counter will track updates in exactly the same way as
-an aggregated counter which is owned by a process.<a name="register_name-2"></a>
+an aggregated counter which is owned by a process.
+<a name="register_name-2"></a>
 
-###register_name/2##
+### register_name/2 ###
 
 
-<pre>register_name(Name::<a href="#type-key">key()</a>, Pid::pid()) -> yes | no</pre>
+<pre><code>
+register_name(Name::<a href="#type-key">key()</a>, Pid::pid()) -&gt; yes | no
+</code></pre>
+
 <br></br>
 
 
-Behaviour support callback<a name="reset_counter-1"></a>
+Behaviour support callback
+<a name="reset_counter-1"></a>
 
-###reset_counter/1##
+### reset_counter/1 ###
 
 
-<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>
+<pre><code>
+reset_counter(Key) -&gt; {ValueBefore, ValueAfter}
+</code></pre>
 
+<ul class="definitions"><li><code>Key = {c, Scope, Name}</code></li><li><code>Scope = l | g</code></li><li><code>ValueBefore = integer()</code></li><li><code>ValueAfter = integer()</code></li></ul>
 
 
 Reads and resets a counter in a "thread-safe" way
 
+
 This function reads the current value of a counter and then resets it to its
 initial value. The reset operation is done using [`update_counter/2`](#update_counter-2),
 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>
 
-###select/1##
+### select/1 ###
 
 
-<pre>select(Continuation::Arg) -&gt; [Match] | {[Match], Continuation} | '$end_of_table'</pre>
-<ul class="definitions"><li><pre>Arg = Continuation | <a href="#type-sel_pattern">sel_pattern()</a></pre></li><li><pre>Match = {Key, Pid, Value}</pre></li></ul>
+<pre><code>
+select(Continuation::Arg) -&gt; [Match] | {[Match], Continuation} | '$end_of_table'
+</code></pre>
 
+<ul class="definitions"><li><code>Arg = Continuation | <a href="#type-sel_pattern">sel_pattern()</a></code></li><li><code>Match = {Key, Pid, Value}</code></li></ul>
 
 
 Perform a select operation on the process registry
@@ -1041,17 +1315,21 @@ When only a pattern as single argument is given, both global and local scope,
 as well as all types of object can be searched. Note that the pattern may
 still limit the select operation so that scanning the entire table is avoided.
 
+
 The physical representation in the registry may differ from the above,
 but the select patterns are transformed appropriately. The logical
 representation for the gproc select operations is given by
-<code><a href="#type-headpat">headpat()</a></code>.<a name="select-2"></a>
+<code><a href="#type-headpat">headpat()</a></code>.
+<a name="select-2"></a>
 
-###select/2##
+### select/2 ###
 
 
-<pre>select(Context::<a href="#type-context">context()</a>, Pat::<a href="#type-sel_pattern">sel_pattern()</a>) -> [{Key, Pid, Value}]</pre>
-<br></br>
+<pre><code>
+select(Context::<a href="#type-context">context()</a>, Pat::<a href="#type-sel_pattern">sel_pattern()</a>) -&gt; [{Key, Pid, Value}]
+</code></pre>
 
+<br></br>
 
 
 
@@ -1062,6 +1340,7 @@ Perform a select operation with limited context on the process registry
 The physical representation in the registry may differ from the above,
 but the select patterns are transformed appropriately.
 
+
 Note that limiting the context is just a convenience function, allowing you
 to write a simpler select pattern and still avoid searching the entire
 registry. Whenever variables are used in the head pattern, this will result
@@ -1069,67 +1348,91 @@ in a wider scan, even if the values are restricted through a guard (e.g.
 `select([{'$1','$2','$3'}, [{'==', '$1', p}], ...])` will count as a wild
 pattern on the key and result in a full scan). In this case, specifying a
 Context will allow gproc to perform some variable substitution and ensure
-that the scan is limited.<a name="select-3"></a>
+that the scan is limited.
+<a name="select-3"></a>
 
-###select/3##
+### 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>
-<br></br>
+<pre><code>
+select(Context::<a href="#type-context">context()</a>, Pat::<a href="#type-sel_patten">sel_patten()</a>, Limit::integer()) -&gt; {[Match], Continuation} | '$end_of_table'
+</code></pre>
 
+<br></br>
 
 
 
 Like [`select/2`](#select-2) but returns Limit objects at a time.
 
-See [`http://www.erlang.org/doc/man/ets.html#select-3`](http://www.erlang.org/doc/man/ets.html#select-3).<a name="select_count-1"></a>
 
-###select_count/1##
+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>
+
+### select_count/1 ###
 
 
-<pre>select_count(Pat::<a href="#type-sel_pattern">sel_pattern()</a>) -> [<a href="#type-sel_object">sel_object()</a>]</pre>
+<pre><code>
+select_count(Pat::<a href="#type-sel_pattern">sel_pattern()</a>) -&gt; [<a href="#type-sel_object">sel_object()</a>]
+</code></pre>
+
 <br></br>
 
 
-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>
 
-###select_count/2##
+### 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>
-<br></br>
+<pre><code>
+select_count(Context::<a href="#type-context">context()</a>, Pat::<a href="#type-sel_pattern">sel_pattern()</a>) -&gt; [{Key, Pid, Value}]
+</code></pre>
 
+<br></br>
 
 
 
 Perform a select_count operation on the process registry.
 
+
 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>
 
-###send/2##
+### send/2 ###
 
 
-<pre>send(Key::<a href="#type-key">key()</a>, Msg::any()) -> Msg</pre>
-<br></br>
+<pre><code>
+send(Key::<a href="#type-process">process()</a> | <a href="#type-key">key()</a>, Msg::any()) -&gt; Msg
+</code></pre>
 
+<br></br>
 
 
 
 Sends a message to the process, or processes, corresponding to Key.
 
+
+
 If Key belongs to a unique object (name or aggregated counter), this
 function will send a message to the corresponding process, or fail if there
 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.
 
-###set_env/5##
 
+Key can also be anything that the erlang:send/2, or '!' operator accepts as a process
+identifier, namely a pid(), an atom(), or `{Name::atom(), Node::atom()}`.
+<a name="set_env-5"></a>
 
-<pre>set_env(Scope::<a href="#type-scope">scope()</a>, App::atom(), Key::atom(), Value::term(), Strategy) -> 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>
+### set_env/5 ###
 
 
+<pre><code>
+set_env(Scope::<a href="#type-scope">scope()</a>, App::atom(), Key::atom(), Value::term(), Strategy) -&gt; Value
+</code></pre>
+
+<ul class="definitions"><li><code>Strategy = [Alternative]</code></li><li><code>Alternative = app_env | os_env | {os_env, VAR} | {mnesia, ActivityType, Oid, Pos}</code></li></ul>
+
 
 Updates the cached value as well as underlying environment.
 
@@ -1140,17 +1443,21 @@ environment outside gproc. This function modifies the cached value, and then
 proceeds to update the underlying environment (OS environment variable or
 application environment variable).
 
+
 When the `mnesia` alternative is used, gproc will try to update any existing
 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)
-to `undefined`.<a name="set_value-2"></a>
+to `undefined`.
+<a name="set_value-2"></a>
 
-###set_value/2##
+### set_value/2 ###
 
 
-<pre>set_value(Key::<a href="#type-key">key()</a>, Value) -> true</pre>
-<br></br>
+<pre><code>
+set_value(Key::<a href="#type-key">key()</a>, Value) -&gt; true
+</code></pre>
 
+<br></br>
 
 
 
@@ -1161,47 +1468,63 @@ Sets the value of the registeration entry given by Key
 Key is assumed to exist and belong to the calling process.
 If it doesn't, this function will exit.
 
+
 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>
 
-###start_link/0##
+### start_link/0 ###
 
 
-<pre>start_link() -&gt; {ok, pid()}</pre>
-<br></br>
+<pre><code>
+start_link() -&gt; {ok, pid()}
+</code></pre>
 
+<br></br>
 
 
 
 Starts the gproc server.
 
+
 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>
 
-###table/0##
+### table/0 ###
 
 
-<pre>table() -&gt; any()</pre>
+<pre><code>
+table() -&gt; any()
+</code></pre>
+
 <br></br>
 
 
-Equivalent to [`table({all, all})`](#table-1).<a name="table-1"></a>
+Equivalent to [`table({all, all})`](#table-1).
+<a name="table-1"></a>
+
+### table/1 ###
 
-###table/1##
 
+<pre><code>
+table(Context::<a href="#type-context">context()</a>) -&gt; any()
+</code></pre>
 
-<pre>table(Context::<a href="#type-context">context()</a>) -> any()</pre>
 <br></br>
 
 
-Equivalent to [`table(Context, [])`](#table-2).<a name="table-2"></a>
+Equivalent to [`table(Context, [])`](#table-2).
+<a name="table-2"></a>
 
-###table/2##
+### table/2 ###
 
 
-<pre>table(Context::<a href="#type-context">context()</a>, Opts) -> any()</pre>
-<br></br>
+<pre><code>
+table(Context::<a href="#type-context">context()</a>, Opts) -&gt; any()
+</code></pre>
 
+<br></br>
 
 
 
@@ -1209,6 +1532,7 @@ QLC table generator for the gproc registry.
 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).
 
+
 NOTE: By default, the gproc table generator will not filter out entries
 belonging to processes that have just died, but which have yet to be cleared
 out of the registry. Use the option `check_pids` (or `{check_pids, true}`)
@@ -1216,39 +1540,50 @@ if you want to filter out dead entries already in the query. There will be
 some overhead associated with doing so, and given that the process monitoring
 is asynchronous, there can never be any guarantee that there are no dead
 entries in the list by the time your program processes it.
+
 <a name="unreg-1"></a>
 
-###unreg/1##
+### unreg/1 ###
 
 
-<pre>unreg(Key::<a href="#type-key">key()</a>) -> true</pre>
+<pre><code>
+unreg(Key::<a href="#type-key">key()</a>) -&gt; true
+</code></pre>
+
 <br></br>
 
 
-Unregister a name or property.<a name="unreg_shared-1"></a>
+Unregister a name or property.
+<a name="unreg_shared-1"></a>
 
-###unreg_shared/1##
+### unreg_shared/1 ###
 
 
-<pre>unreg_shared(Key::<a href="#type-key">key()</a>) -> true</pre>
-<br></br>
+<pre><code>
+unreg_shared(Key::<a href="#type-key">key()</a>) -&gt; true
+</code></pre>
 
+<br></br>
 
-Unregister a shared resource.<a name="unregister_name-1"></a>
 
-###unregister_name/1##
+Unregister a shared resource.
+<a name="unregister_name-1"></a>
 
+### unregister_name/1 ###
 
 `unregister_name(Key) -> any()`
 
-Equivalent to `unreg / 1`.<a name="update_counter-2"></a>
+Equivalent to `unreg / 1`.
+<a name="update_counter-2"></a>
 
-###update_counter/2##
+### update_counter/2 ###
 
 
-<pre>update_counter(Key::<a href="#type-key">key()</a>, Incr::<a href="#type-increment">increment()</a>) -> integer()</pre>
-<br></br>
+<pre><code>
+update_counter(Key::<a href="#type-key">key()</a>, Incr::<a href="#type-increment">increment()</a>) -&gt; integer()
+</code></pre>
 
+<br></br>
 
 
 
@@ -1260,16 +1595,20 @@ This function works almost exactly 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
 will fail if the type of object referred to by Key is not a counter.
 
+
 Aggregated counters with the same name will be updated automatically.
 The `UpdateOp` patterns are the same as for `ets:update_counter/3`, except
-that the position is omitted; in gproc, the value position is always `3`.<a name="update_counters-2"></a>
+that the position is omitted; in gproc, the value position is always `3`.
+<a name="update_counters-2"></a>
 
-###update_counters/2##
+### update_counters/2 ###
 
 
-<pre>update_counters(X1::<a href="#type-scope">scope()</a>, Cs::[{<a href="#type-key">key()</a>, pid(), <a href="#type-increment">increment()</a>}]) -> [{<a href="#type-key">key()</a>, pid(), integer()}]</pre>
-<br></br>
+<pre><code>
+update_counters(X1::<a href="#type-scope">scope()</a>, Cs::[{<a href="#type-key">key()</a>, pid(), <a href="#type-increment">increment()</a>}]) -&gt; [{<a href="#type-key">key()</a>, pid(), integer()}]
+</code></pre>
 
+<br></br>
 
 
 
@@ -1281,14 +1620,18 @@ This function is not atomic, except (in a sense) for global counters. For local
 it is more of a convenience function. For global counters, it is much more efficient
 than calling `gproc:update_counter/2` for each individual counter.
 
-The return value is the corresponding list of `[{Counter, Pid, NewValue}]`.<a name="update_shared_counter-2"></a>
 
-###update_shared_counter/2##
+The return value is the corresponding list of `[{Counter, Pid, NewValue}]`.
+<a name="update_shared_counter-2"></a>
+
+### update_shared_counter/2 ###
 
 
-<pre>update_shared_counter(Key::<a href="#type-key">key()</a>, Incr) -> integer() | [integer()]</pre>
-<ul class="definitions"><li><pre>Incr = IncrVal | UpdateOp | [UpdateOp]</pre></li><li><pre>UpdateOp = IncrVal | {IncrVal, Threshold, SetValue}</pre></li><li><pre>IncrVal = integer()</pre></li></ul>
+<pre><code>
+update_shared_counter(Key::<a href="#type-key">key()</a>, Incr) -&gt; integer() | [integer()]
+</code></pre>
 
+<ul class="definitions"><li><code>Incr = IncrVal | UpdateOp | [UpdateOp]</code></li><li><code>UpdateOp = IncrVal | {IncrVal, Threshold, SetValue}</code></li><li><code>IncrVal = integer()</code></li></ul>
 
 
 Updates the shared counter registered as Key.
@@ -1299,38 +1642,46 @@ This function works almost exactly 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
 will fail if the type of object referred to by Key is not a counter.
 
+
 Aggregated counters with the same name will be updated automatically.
 The `UpdateOp` patterns are the same as for `ets:update_counter/3`, except
-that the position is omitted; in gproc, the value position is always `3`.<a name="where-1"></a>
+that the position is omitted; in gproc, the value position is always `3`.
+<a name="where-1"></a>
 
-###where/1##
+### where/1 ###
 
 
-<pre>where(Key::<a href="#type-key">key()</a>) -> pid()</pre>
-<br></br>
+<pre><code>
+where(Key::<a href="#type-key">key()</a>) -&gt; pid()
+</code></pre>
 
+<br></br>
 
 
 
 Returns the pid registered as Key
 
+
 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
-cases.<a name="whereis_name-1"></a>
-
-###whereis_name/1##
+cases.
+<a name="whereis_name-1"></a>
 
+### whereis_name/1 ###
 
 `whereis_name(Key) -> any()`
 
-Equivalent to `where / 1`.<a name="wide_await-3"></a>
+Equivalent to `where / 1`.
+<a name="wide_await-3"></a>
 
-###wide_await/3##
+### wide_await/3 ###
 
 
-<pre>wide_await(Nodes::[node()], Key::<a href="#type-key">key()</a>, Timeout) -> {pid(), Value}</pre>
-<ul class="definitions"><li><pre>Timeout = integer() | infinity</pre></li></ul>
+<pre><code>
+wide_await(Nodes::[node()], Key::<a href="#type-key">key()</a>, Timeout) -&gt; {pid(), Value}
+</code></pre>
 
+<ul class="definitions"><li><code>Timeout = integer() | infinity</code></li></ul>
 
 
 Wait for a local name to be registered on any of `Nodes`.
@@ -1339,5 +1690,6 @@ the `Nodes` list at the same time. The first node to respond with a
 process registered as `Key` will provide the result. Other results are
 ignored. `Key` must be a unique name with local scope, i.e. `{n,l,Name}`.
 
+
 An exception is thrown upon timeout, or if no node can be reached (if gproc is
-not running on a given node, this is treated the same as the node being down).
+not running on a given node, this is treated the same as the node being down).

+ 11 - 11
doc/gproc_app.md

@@ -1,13 +1,13 @@
 
 
-#Module gproc_app#
+# Module gproc_app #
 * [Function Index](#index)
 * [Function Details](#functions)
 
+__Behaviours:__ [`application`](application.md).
+<a name="index"></a>
 
-__Behaviours:__ [`application`](application.md).<a name="index"></a>
-
-##Function Index##
+## 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>
@@ -15,26 +15,26 @@ __Behaviours:__ [`application`](application.md).<a name="index"></a>
 
 <a name="functions"></a>
 
-##Function Details##
+## Function Details ##
 
 <a name="start-0"></a>
 
-###start/0##
-
+### start/0 ###
 
 `start() -> any()`
 
-<a name="start-2"></a>
 
-###start/2##
+<a name="start-2"></a>
 
+### start/2 ###
 
 `start(Type, StartArgs) -> any()`
 
-<a name="stop-1"></a>
 
-###stop/1##
+<a name="stop-1"></a>
 
+### stop/1 ###
 
 `stop(State) -> any()`
 
+

+ 20 - 20
doc/gproc_bcast.md

@@ -1,6 +1,6 @@
 
 
-#Module gproc_bcast#
+# Module gproc_bcast #
 * [Description](#description)
 * [Function Index](#index)
 * [Function Details](#functions)
@@ -8,12 +8,12 @@
 
 Gproc message broadcast server
 This module is used to support gproc:bcast(Key, Msg).
-
 __Behaviours:__ [`gen_server`](gen_server.md).
 
-__Authors:__ Ulf Wiger ([`ulf@wiger.net`](mailto:ulf@wiger.net)).<a name="description"></a>
+__Authors:__ Ulf Wiger ([`ulf@wiger.net`](mailto:ulf@wiger.net)).
+<a name="description"></a>
 
-##Description##
+## Description ##
 
 
 gproc:bcast/2 allows for e.g. distributed publish/subscribe, without
@@ -21,7 +21,7 @@ having to resort to global property registration.
 To ensure that erlang's message ordering guarantees are kept, all sends
 are channeled through a broadcast server on each node.<a name="index"></a>
 
-##Function Index##
+## Function Index ##
 
 
 <table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#code_change-3">code_change/3</a></td><td></td></tr><tr><td valign="top"><a href="#handle_call-3">handle_call/3</a></td><td></td></tr><tr><td valign="top"><a href="#handle_cast-2">handle_cast/2</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="#init-1">init/1</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="#terminate-2">terminate/2</a></td><td></td></tr></table>
@@ -29,54 +29,54 @@ are channeled through a broadcast server on each node.<a name="index"></a>
 
 <a name="functions"></a>
 
-##Function Details##
+## Function Details ##
 
 <a name="code_change-3"></a>
 
-###code_change/3##
-
+### code_change/3 ###
 
 `code_change(X1, S, X3) -> any()`
 
-<a name="handle_call-3"></a>
 
-###handle_call/3##
+<a name="handle_call-3"></a>
 
+### handle_call/3 ###
 
 `handle_call(X1, X2, S) -> any()`
 
-<a name="handle_cast-2"></a>
 
-###handle_cast/2##
+<a name="handle_cast-2"></a>
 
+### handle_cast/2 ###
 
 `handle_cast(X1, S) -> any()`
 
-<a name="handle_info-2"></a>
 
-###handle_info/2##
+<a name="handle_info-2"></a>
 
+### handle_info/2 ###
 
 `handle_info(X1, S) -> any()`
 
-<a name="init-1"></a>
 
-###init/1##
+<a name="init-1"></a>
 
+### init/1 ###
 
 `init(X1) -> any()`
 
-<a name="start_link-0"></a>
 
-###start_link/0##
+<a name="start_link-0"></a>
 
+### start_link/0 ###
 
 `start_link() -> any()`
 
-<a name="terminate-2"></a>
 
-###terminate/2##
+<a name="terminate-2"></a>
 
+### terminate/2 ###
 
 `terminate(X1, X2) -> any()`
 
+

+ 88 - 80
doc/gproc_dist.md

@@ -1,26 +1,26 @@
 
 
-#Module gproc_dist#
+# Module gproc_dist #
 * [Description](#description)
 * [Function Index](#index)
 * [Function Details](#functions)
 
 
 Extended process registry.
-
 __Behaviours:__ [`gen_leader`](/Users/uwiger/FL/git/gen_leader/doc/gen_leader.md).
 
-__Authors:__ Ulf Wiger ([`ulf@wiger.net`](mailto:ulf@wiger.net)).<a name="description"></a>
-
-##Description##
+__Authors:__ Ulf Wiger ([`ulf@wiger.net`](mailto:ulf@wiger.net)).
+<a name="description"></a>
 
+## Description ##
 
 This module implements an extended process registry
 
 
-For a detailed description, see gproc/doc/erlang07-wiger.pdf.<a name="index"></a>
+For a detailed description, see gproc/doc/erlang07-wiger.pdf.
+<a name="index"></a>
 
-##Function Index##
+## 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_info-3">handle_info/3</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>
@@ -33,147 +33,150 @@ Scope = l | g (global or local).</td></tr><tr><td valign="top"><a href="#reg_or_
 
 <a name="functions"></a>
 
-##Function Details##
+## Function Details ##
 
 <a name="code_change-4"></a>
 
-###code_change/4##
-
+### code_change/4 ###
 
 `code_change(FromVsn, S, Extra, E) -> any()`
 
-<a name="elected-2"></a>
 
-###elected/2##
+<a name="elected-2"></a>
 
+### elected/2 ###
 
 `elected(S, E) -> any()`
 
-<a name="elected-3"></a>
 
-###elected/3##
+<a name="elected-3"></a>
 
+### elected/3 ###
 
 `elected(S, E, Node) -> any()`
 
-<a name="from_leader-3"></a>
 
-###from_leader/3##
+<a name="from_leader-3"></a>
 
+### from_leader/3 ###
 
 `from_leader(Ops, S, E) -> any()`
 
+
 <a name="get_leader-0"></a>
 
-###get_leader/0##
+### get_leader/0 ###
 
 
-<pre>get_leader() -&gt; node()</pre>
-<br></br>
+<pre><code>
+get_leader() -&gt; node()
+</code></pre>
 
+<br></br>
 
-Returns the node of the current gproc leader.<a name="give_away-2"></a>
 
-###give_away/2##
+Returns the node of the current gproc leader.
+<a name="give_away-2"></a>
 
+### give_away/2 ###
 
 `give_away(Key, To) -> any()`
 
-<a name="handle_DOWN-3"></a>
 
-###handle_DOWN/3##
+<a name="handle_DOWN-3"></a>
 
+### handle_DOWN/3 ###
 
 `handle_DOWN(Node, S, E) -> any()`
 
-<a name="handle_call-4"></a>
 
-###handle_call/4##
+<a name="handle_call-4"></a>
 
+### handle_call/4 ###
 
 `handle_call(X1, X2, S, E) -> any()`
 
-<a name="handle_cast-3"></a>
 
-###handle_cast/3##
+<a name="handle_cast-3"></a>
 
+### handle_cast/3 ###
 
 `handle_cast(Msg, S, X3) -> any()`
 
-<a name="handle_info-2"></a>
 
-###handle_info/2##
+<a name="handle_info-2"></a>
 
+### handle_info/2 ###
 
 `handle_info(X1, S) -> any()`
 
-<a name="handle_info-3"></a>
 
-###handle_info/3##
+<a name="handle_info-3"></a>
 
+### handle_info/3 ###
 
 `handle_info(Msg, S, E) -> any()`
 
-<a name="handle_leader_call-4"></a>
 
-###handle_leader_call/4##
+<a name="handle_leader_call-4"></a>
 
+### handle_leader_call/4 ###
 
 `handle_leader_call(X1, From, State, E) -> any()`
 
-<a name="handle_leader_cast-3"></a>
 
-###handle_leader_cast/3##
+<a name="handle_leader_cast-3"></a>
 
+### handle_leader_cast/3 ###
 
 `handle_leader_cast(X1, S, E) -> any()`
 
-<a name="init-1"></a>
 
-###init/1##
+<a name="init-1"></a>
 
+### init/1 ###
 
 `init(Opts) -> any()`
 
-<a name="leader_call-1"></a>
 
-###leader_call/1##
+<a name="leader_call-1"></a>
 
+### leader_call/1 ###
 
 `leader_call(Req) -> any()`
 
-<a name="leader_cast-1"></a>
 
-###leader_cast/1##
+<a name="leader_cast-1"></a>
 
+### leader_cast/1 ###
 
 `leader_cast(Msg) -> any()`
 
-<a name="mreg-2"></a>
 
-###mreg/2##
+<a name="mreg-2"></a>
 
+### mreg/2 ###
 
 `mreg(T, KVL) -> any()`
 
-<a name="munreg-2"></a>
 
-###munreg/2##
+<a name="munreg-2"></a>
 
+### munreg/2 ###
 
 `munreg(T, Keys) -> any()`
 
-<a name="reg-1"></a>
 
-###reg/1##
+<a name="reg-1"></a>
 
+### reg/1 ###
 
 `reg(Key) -> any()`
 
-<a name="reg-2"></a>
 
-###reg/2##
+<a name="reg-2"></a>
 
+### reg/2 ###
 
 `reg(Key, Value) -> any()`
 
@@ -182,68 +185,72 @@ Class = n  - unique name
 | p  - non-unique property
 | c  - counter
 | a  - aggregated counter
-Scope = l | g (global or local)<a name="reg_or_locate-3"></a>
-
-###reg_or_locate/3##
+Scope = l | g (global or local)
+<a name="reg_or_locate-3"></a>
 
+### reg_or_locate/3 ###
 
 `reg_or_locate(Key, Value, Pid) -> any()`
 
-<a name="reg_shared-2"></a>
 
-###reg_shared/2##
+<a name="reg_shared-2"></a>
 
+### reg_shared/2 ###
 
 `reg_shared(Key, Value) -> any()`
 
-<a name="reset_counter-1"></a>
 
-###reset_counter/1##
+<a name="reset_counter-1"></a>
 
+### reset_counter/1 ###
 
 `reset_counter(Key) -> any()`
 
-<a name="set_value-2"></a>
 
-###set_value/2##
+<a name="set_value-2"></a>
 
+### set_value/2 ###
 
 `set_value(Key, Value) -> any()`
 
-<a name="start_link-0"></a>
 
-###start_link/0##
+<a name="start_link-0"></a>
 
+### start_link/0 ###
 
 `start_link() -> any()`
 
-<a name="start_link-1"></a>
 
-###start_link/1##
+<a name="start_link-1"></a>
 
+### start_link/1 ###
 
 `start_link(Nodes) -> any()`
 
-<a name="surrendered-3"></a>
 
-###surrendered/3##
+<a name="surrendered-3"></a>
 
+### surrendered/3 ###
 
 `surrendered(State, X2, E) -> any()`
 
+
 <a name="sync-0"></a>
 
-###sync/0##
+### sync/0 ###
 
 
-<pre>sync() -&gt; true</pre>
-<br></br>
+<pre><code>
+sync() -&gt; true
+</code></pre>
 
+<br></br>
 
 
 
 Synchronize with the gproc leader
 
+
 This function can be used to ensure that data has been replicated from the
 leader to the current node. It does so by asking the leader to ping all
 live participating nodes. The call will return `true` when all these nodes
@@ -251,45 +258,46 @@ have either responded or died. In the special case where the leader dies
 during an ongoing sync, the call will fail with a timeout exception.
 (Actually, it should be a `leader_died` exception; more study needed to find
 out why gen_leader times out in this situation, rather than reporting that
-the leader died.)<a name="terminate-2"></a>
-
-###terminate/2##
+the leader died.)
+<a name="terminate-2"></a>
 
+### terminate/2 ###
 
 `terminate(Reason, S) -> any()`
 
-<a name="unreg-1"></a>
 
-###unreg/1##
+<a name="unreg-1"></a>
 
+### unreg/1 ###
 
 `unreg(Key) -> any()`
 
-<a name="unreg_shared-1"></a>
 
-###unreg_shared/1##
+<a name="unreg_shared-1"></a>
 
+### unreg_shared/1 ###
 
 `unreg_shared(Key) -> any()`
 
-<a name="update_counter-2"></a>
 
-###update_counter/2##
+<a name="update_counter-2"></a>
 
+### update_counter/2 ###
 
 `update_counter(Key, Incr) -> any()`
 
-<a name="update_counters-1"></a>
 
-###update_counters/1##
+<a name="update_counters-1"></a>
 
+### update_counters/1 ###
 
 `update_counters(List) -> any()`
 
-<a name="update_shared_counter-2"></a>
 
-###update_shared_counter/2##
+<a name="update_shared_counter-2"></a>
 
+### update_shared_counter/2 ###
 
 `update_shared_counter(Key, Incr) -> any()`
 
+

+ 11 - 7
doc/gproc_info.md

@@ -1,13 +1,13 @@
 
 
-#Module gproc_info#
+# Module gproc_info #
 * [Function Index](#index)
 * [Function Details](#functions)
 
+__Authors:__ Ulf Wiger ([`ulf.wiger@erlang-solutions.com`](mailto:ulf.wiger@erlang-solutions.com)).
+<a name="index"></a>
 
-__Authors:__ Ulf Wiger ([`ulf.wiger@erlang-solutions.com`](mailto:ulf.wiger@erlang-solutions.com)).<a name="index"></a>
-
-##Function Index##
+## 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>
@@ -15,14 +15,18 @@ __Authors:__ Ulf Wiger ([`ulf.wiger@erlang-solutions.com`](mailto:ulf.wiger@erla
 
 <a name="functions"></a>
 
-##Function Details##
+## Function Details ##
 
 <a name="i-0"></a>
 
-###i/0##
+### i/0 ###
+
 
+<pre><code>
+i() -&gt; ok
+</code></pre>
 
-<pre>i() -&gt; ok</pre>
 <br></br>
 
 
+

+ 15 - 7
doc/gproc_init.md

@@ -1,13 +1,13 @@
 
 
-#Module gproc_init#
+# Module gproc_init #
 * [Function Index](#index)
 * [Function Details](#functions)
 
 
 <a name="index"></a>
 
-##Function Index##
+## 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>
@@ -15,23 +15,31 @@
 
 <a name="functions"></a>
 
-##Function Details##
+## Function Details ##
 
 <a name="hard_reset-0"></a>
 
-###hard_reset/0##
+### hard_reset/0 ###
 
 
-<pre>hard_reset() -&gt; ok</pre>
+<pre><code>
+hard_reset() -&gt; ok
+</code></pre>
+
 <br></br>
 
 
+
 <a name="soft_reset-0"></a>
 
-###soft_reset/0##
+### soft_reset/0 ###
 
 
-<pre>soft_reset() -&gt; ok</pre>
+<pre><code>
+soft_reset() -&gt; ok
+</code></pre>
+
 <br></br>
 
 
+

+ 54 - 46
doc/gproc_lib.md

@@ -1,24 +1,24 @@
 
 
-#Module gproc_lib#
+# Module gproc_lib #
 * [Description](#description)
 * [Function Index](#index)
 * [Function Details](#functions)
 
 
 Extended process registry.
+__Authors:__ Ulf Wiger ([`ulf@wiger.net`](mailto:ulf@wiger.net)).
+<a name="description"></a>
 
-__Authors:__ Ulf Wiger ([`ulf@wiger.net`](mailto:ulf@wiger.net)).<a name="description"></a>
-
-##Description##
-
+## Description ##
 
 This module implements an extended process registry
 
 
-For a detailed description, see gproc/doc/erlang07-wiger.pdf.<a name="index"></a>
+For a detailed description, see gproc/doc/erlang07-wiger.pdf.
+<a name="index"></a>
 
-##Function Index##
+## Function Index ##
 
 
 <table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#add_monitor-3">add_monitor/3</a></td><td></td></tr><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="#notify-3">notify/3</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_monitor-3">remove_monitor/3</a></td><td></td></tr><tr><td valign="top"><a href="#remove_monitors-3">remove_monitors/3</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="#remove_reg-4">remove_reg/4</a></td><td></td></tr><tr><td valign="top"><a href="#remove_reverse_mapping-3">remove_reverse_mapping/3</a></td><td></td></tr><tr><td valign="top"><a href="#remove_wait-4">remove_wait/4</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>
@@ -26,142 +26,150 @@ For a detailed description, see gproc/doc/erlang07-wiger.pdf.<a name="index"></a
 
 <a name="functions"></a>
 
-##Function Details##
+## Function Details ##
 
 <a name="add_monitor-3"></a>
 
-###add_monitor/3##
-
+### add_monitor/3 ###
 
 `add_monitor(T, Pid, Ref) -> any()`
 
-<a name="await-3"></a>
 
-###await/3##
+<a name="await-3"></a>
 
+### await/3 ###
 
 `await(Key, WPid, From) -> any()`
 
-<a name="do_set_counter_value-3"></a>
 
-###do_set_counter_value/3##
+<a name="do_set_counter_value-3"></a>
 
+### do_set_counter_value/3 ###
 
 `do_set_counter_value(Key, Value, Pid) -> any()`
 
-<a name="do_set_value-3"></a>
 
-###do_set_value/3##
+<a name="do_set_value-3"></a>
 
+### do_set_value/3 ###
 
 `do_set_value(Key, Value, Pid) -> any()`
 
-<a name="ensure_monitor-2"></a>
 
-###ensure_monitor/2##
+<a name="ensure_monitor-2"></a>
 
+### ensure_monitor/2 ###
 
 `ensure_monitor(Pid, Scope) -> any()`
 
+
 <a name="insert_many-4"></a>
 
-###insert_many/4##
+### insert_many/4 ###
+
 
+<pre><code>
+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()) -&gt; {true, list()} | false
+</code></pre>
 
-<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>
 <br></br>
 
 
+
 <a name="insert_reg-4"></a>
 
-###insert_reg/4##
+### insert_reg/4 ###
+
 
+<pre><code>
+insert_reg(K::<a href="#type-key">key()</a>, Value::any(), Pid::pid() | shared, Scope::<a href="#type-scope">scope()</a>) -&gt; boolean()
+</code></pre>
 
-<pre>insert_reg(K::<a href="#type-key">key()</a>, Value::any(), Pid::pid() | shared, Scope::<a href="#type-scope">scope()</a>) -> boolean()</pre>
 <br></br>
 
 
-<a name="notify-2"></a>
 
-###notify/2##
+<a name="notify-2"></a>
 
+### notify/2 ###
 
 `notify(Key, Opts) -> any()`
 
-<a name="notify-3"></a>
 
-###notify/3##
+<a name="notify-3"></a>
 
+### notify/3 ###
 
 `notify(Event, Key, Opts) -> any()`
 
-<a name="remove_many-4"></a>
 
-###remove_many/4##
+<a name="remove_many-4"></a>
 
+### remove_many/4 ###
 
 `remove_many(T, Scope, L, Pid) -> any()`
 
-<a name="remove_monitor-3"></a>
 
-###remove_monitor/3##
+<a name="remove_monitor-3"></a>
 
+### remove_monitor/3 ###
 
 `remove_monitor(T, Pid, Ref) -> any()`
 
-<a name="remove_monitors-3"></a>
 
-###remove_monitors/3##
+<a name="remove_monitors-3"></a>
 
+### remove_monitors/3 ###
 
 `remove_monitors(Key, Pid, MPid) -> any()`
 
-<a name="remove_reg-3"></a>
 
-###remove_reg/3##
+<a name="remove_reg-3"></a>
 
+### remove_reg/3 ###
 
 `remove_reg(Key, Pid, Event) -> any()`
 
-<a name="remove_reg-4"></a>
 
-###remove_reg/4##
+<a name="remove_reg-4"></a>
 
+### remove_reg/4 ###
 
 `remove_reg(Key, Pid, Event, Opts) -> any()`
 
-<a name="remove_reverse_mapping-3"></a>
 
-###remove_reverse_mapping/3##
+<a name="remove_reverse_mapping-3"></a>
 
+### remove_reverse_mapping/3 ###
 
 `remove_reverse_mapping(Event, Pid, Key) -> any()`
 
-<a name="remove_wait-4"></a>
 
-###remove_wait/4##
+<a name="remove_wait-4"></a>
 
+### remove_wait/4 ###
 
 `remove_wait(Key, Pid, Ref, Waiters) -> any()`
 
-<a name="update_aggr_counter-3"></a>
 
-###update_aggr_counter/3##
+<a name="update_aggr_counter-3"></a>
 
+### update_aggr_counter/3 ###
 
 `update_aggr_counter(C, N, Val) -> any()`
 
-<a name="update_counter-3"></a>
 
-###update_counter/3##
+<a name="update_counter-3"></a>
 
+### update_counter/3 ###
 
 `update_counter(Key, Incr, Pid) -> any()`
 
-<a name="valid_opts-2"></a>
 
-###valid_opts/2##
+<a name="valid_opts-2"></a>
 
+### valid_opts/2 ###
 
 `valid_opts(Type, Default) -> any()`
 
+

+ 26 - 15
doc/gproc_monitor.md

@@ -1,6 +1,6 @@
 
 
-#Module gproc_monitor#
+# Module gproc_monitor #
 * [Description](#description)
 * [Function Index](#index)
 * [Function Details](#functions)
@@ -10,12 +10,12 @@
 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>
+__Authors:__ Ulf Wiger ([`ulf.wiger@feuerlabs.com`](mailto:ulf.wiger@feuerlabs.com)).
+<a name="index"></a>
 
-##Function Index##
+## 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>
@@ -26,27 +26,33 @@ Unsubscribe from registration events for a certain name.</td></tr></table>
 
 <a name="functions"></a>
 
-##Function Details##
+## Function Details ##
 
 <a name="start_link-0"></a>
 
-###start_link/0##
+### start_link/0 ###
+
 
+<pre><code>
+start_link() -&gt; {ok, Pid} | ignore | {error, Error}
+</code></pre>
 
-<pre>start_link() -&gt; {ok, Pid} | ignore | {error, Error}</pre>
 <br></br>
 
 
 
 Starts the server
+
 <a name="subscribe-1"></a>
 
-###subscribe/1##
+### subscribe/1 ###
 
 
-<pre>subscribe(Key::<a href="#type-key">key()</a>) -> ok</pre>
-<br></br>
+<pre><code>
+subscribe(Key::<a href="#type-key">key()</a>) -&gt; ok
+</code></pre>
 
+<br></br>
 
 
 
@@ -60,19 +66,24 @@ 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>
+sent immediately, indicating the current status of the name.
+<a name="unsubscribe-1"></a>
 
-###unsubscribe/1##
+### unsubscribe/1 ###
 
 
-<pre>unsubscribe(Key::<a href="#type-key">key()</a>) -> ok</pre>
-<br></br>
+<pre><code>
+unsubscribe(Key::<a href="#type-key">key()</a>) -&gt; ok
+</code></pre>
 
+<br></br>
 
 
 
 
 Unsubscribe from registration events for a certain name
 
-This function is the reverse of subscribe/1. It removes the subscription.
+
+This function is the reverse of subscribe/1. It removes the subscription.

+ 142 - 71
doc/gproc_ps.md

@@ -1,6 +1,6 @@
 
 
-#Module gproc_ps#
+# Module gproc_ps #
 * [Description](#description)
 * [Data Types](#types)
 * [Function Index](#index)
@@ -9,11 +9,10 @@
 
 Gproc Publish/Subscribe patterns
 This module implements a few convenient functions for publish/subscribe.
+__Authors:__ Ulf Wiger ([`ulf@wiger.net`](mailto:ulf@wiger.net)).
+<a name="description"></a>
 
-__Authors:__ Ulf Wiger ([`ulf@wiger.net`](mailto:ulf@wiger.net)).<a name="description"></a>
-
-##Description##
-
+## Description ##
 
 
 
@@ -21,6 +20,7 @@ Publish/subscribe with Gproc relies entirely on gproc properties and counters.
 This makes for a very concise implementation, as the monitoring of subscribers and
 removal of subscriptions comes for free with Gproc.
 
+
 Using this module instead of rolling your own (which is easy enough) brings the
 benefit of consistency, in tracing and debugging.
 The implementation can also serve to illustrate how to use gproc properties and
@@ -28,43 +28,59 @@ counters to good effect.
 
 <a name="types"></a>
 
-##Data Types##
+## Data Types ##
+
+
+
+
+### <a name="type-event">event()</a> ###
 
 
 
+<pre><code>
+event() = any()
+</code></pre>
 
-###<a name="type-event">event()</a>##
 
 
 
-<pre>event() = any()</pre>
 
+### <a name="type-msg">msg()</a> ###
 
 
-###<a name="type-msg">msg()</a>##
 
+<pre><code>
+msg() = any()
+</code></pre>
 
 
-<pre>msg() = any()</pre>
 
 
 
-###<a name="type-scope">scope()</a>##
+### <a name="type-scope">scope()</a> ###
 
 
 
-<pre>scope() = l | g</pre>
+<pre><code>
+scope() = l | g
+</code></pre>
 
 
 
-###<a name="type-status">status()</a>##
 
 
+### <a name="type-status">status()</a> ###
+
+
+
+<pre><code>
+status() = 1 | 0
+</code></pre>
+
 
-<pre>status() = 1 | 0</pre>
 <a name="index"></a>
 
-##Function Index##
+## Function Index ##
 
 
 <table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#change_cond-3">change_cond/3</a></td><td>Change the condition specification of an existing subscription.</td></tr><tr><td valign="top"><a href="#create_single-2">create_single/2</a></td><td>Creates a single-shot subscription entry for Event.</td></tr><tr><td valign="top"><a href="#delete_single-2">delete_single/2</a></td><td>Deletes the single-shot subscription for Event.</td></tr><tr><td valign="top"><a href="#disable_single-2">disable_single/2</a></td><td>Disables the single-shot subscription for Event.</td></tr><tr><td valign="top"><a href="#enable_single-2">enable_single/2</a></td><td>Enables the single-shot subscription for Event.</td></tr><tr><td valign="top"><a href="#list_singles-2">list_singles/2</a></td><td>Lists all single-shot subscribers of Event, together with their status.</td></tr><tr><td valign="top"><a href="#list_subs-2">list_subs/2</a></td><td>List the pids of all processes subscribing to <code>Event</code></td></tr><tr><td valign="top"><a href="#notify_single_if_true-4">notify_single_if_true/4</a></td><td>Create/enable a single subscription for event; notify at once if F() -> true.</td></tr><tr><td valign="top"><a href="#publish-3">publish/3</a></td><td>Publish the message <code>Msg</code> to all subscribers of <code>Event</code></td></tr><tr><td valign="top"><a href="#publish_cond-3">publish_cond/3</a></td><td>Publishes the message <code>Msg</code> to conditional subscribers of <code>Event</code></td></tr><tr><td valign="top"><a href="#subscribe-2">subscribe/2</a></td><td>Subscribe to events of type <code>Event</code></td></tr><tr><td valign="top"><a href="#subscribe_cond-3">subscribe_cond/3</a></td><td>Subscribe conditionally to events of type <code>Event</code></td></tr><tr><td valign="top"><a href="#tell_singles-3">tell_singles/3</a></td><td>Publish <code>Msg</code> to all single-shot subscribers of <code>Event</code></td></tr><tr><td valign="top"><a href="#unsubscribe-2">unsubscribe/2</a></td><td>Remove subscribtion created using <code>subscribe(Scope, Event)</code></td></tr></table>
@@ -72,16 +88,18 @@ counters to good effect.
 
 <a name="functions"></a>
 
-##Function Details##
+## Function Details ##
 
 <a name="change_cond-3"></a>
 
-###change_cond/3##
+### change_cond/3 ###
 
 
-<pre>change_cond(Scope::<a href="#type-scope">scope()</a>, Event::<a href="#type-event">event()</a>, Spec::undefined | <a href="ets.md#type-match_spec">ets:match_spec()</a>) -> true</pre>
-<br></br>
+<pre><code>
+change_cond(Scope::<a href="#type-scope">scope()</a>, Event::<a href="#type-event">event()</a>, Spec::undefined | <a href="ets.md#type-match_spec">ets:match_spec()</a>) -&gt; true
+</code></pre>
 
+<br></br>
 
 
 
@@ -93,16 +111,20 @@ This function atomically changes the condition spec of an existing
 subscription (see [`subscribe_cond/3`](#subscribe_cond-3)). An exception is raised if
 the subscription doesn't already exist.
 
+
 Note that this function can also be used to change a conditional subscription
 to an unconditional one (by setting `Spec = undefined`), or a 'normal'
-subscription to a conditional one.<a name="create_single-2"></a>
+subscription to a conditional one.
+<a name="create_single-2"></a>
 
-###create_single/2##
+### create_single/2 ###
 
 
-<pre>create_single(Scope::<a href="#type-scope">scope()</a>, Event::<a href="#type-event">event()</a>) -> true</pre>
-<br></br>
+<pre><code>
+create_single(Scope::<a href="#type-scope">scope()</a>, Event::<a href="#type-event">event()</a>) -&gt; true
+</code></pre>
 
+<br></br>
 
 
 
@@ -121,30 +143,38 @@ The function creates a gproc counter entry, `{c,Scope,{gproc_ps_event,Event}}`,
 will have either of the values `0` (disabled) or `1` (enabled). Initially, the value
 is `1`, meaning the subscription is enabled.
 
+
 Counters are used in this case, since they can be atomically updated by both the
 subscriber (owner) and publisher. The publisher sets the counter value to `0` as soon
-as it has delivered a message.<a name="delete_single-2"></a>
+as it has delivered a message.
+<a name="delete_single-2"></a>
 
-###delete_single/2##
+### delete_single/2 ###
 
 
-<pre>delete_single(Scope::<a href="#type-scope">scope()</a>, Event::<a href="#type-event">event()</a>) -> true</pre>
-<br></br>
+<pre><code>
+delete_single(Scope::<a href="#type-scope">scope()</a>, Event::<a href="#type-event">event()</a>) -&gt; true
+</code></pre>
 
+<br></br>
 
 
 
 Deletes the single-shot subscription for Event
 
+
 This function deletes the counter entry representing the single-shot description.
-An exception will be raised if there is no such subscription.<a name="disable_single-2"></a>
+An exception will be raised if there is no such subscription.
+<a name="disable_single-2"></a>
 
-###disable_single/2##
+### disable_single/2 ###
 
 
-<pre>disable_single(Scope::<a href="#type-scope">scope()</a>, Event::<a href="#type-event">event()</a>) -> integer()</pre>
-<br></br>
+<pre><code>
+disable_single(Scope::<a href="#type-scope">scope()</a>, Event::<a href="#type-event">event()</a>) -&gt; integer()
+</code></pre>
 
+<br></br>
 
 
 
@@ -161,14 +191,18 @@ This function is insensitive to concurrency, using 'wrapping' ets counter update
 This guarantees that the counter will have either the value 1 or 0, depending on which
 update happened last.
 
-The return value indicates the previous status.<a name="enable_single-2"></a>
 
-###enable_single/2##
+The return value indicates the previous status.
+<a name="enable_single-2"></a>
 
+### enable_single/2 ###
 
-<pre>enable_single(Scope::<a href="#type-scope">scope()</a>, Event::<a href="#type-event">event()</a>) -> integer()</pre>
-<br></br>
 
+<pre><code>
+enable_single(Scope::<a href="#type-scope">scope()</a>, Event::<a href="#type-event">event()</a>) -&gt; integer()
+</code></pre>
+
+<br></br>
 
 
 
@@ -189,51 +223,67 @@ This function is insensitive to concurrency, using 'wrapping' ets counter update
 This guarantees that the counter will have either the value 1 or 0, depending on which
 update happened last.
 
-The return value indicates the previous status.<a name="list_singles-2"></a>
 
-###list_singles/2##
+The return value indicates the previous status.
+<a name="list_singles-2"></a>
+
+### list_singles/2 ###
 
 
-<pre>list_singles(Scope::<a href="#type-scope">scope()</a>, Event::<a href="#type-event">event()</a>) -> [{pid(), <a href="#type-status">status()</a>}]</pre>
+<pre><code>
+list_singles(Scope::<a href="#type-scope">scope()</a>, Event::<a href="#type-event">event()</a>) -&gt; [{pid(), <a href="#type-status">status()</a>}]
+</code></pre>
+
 <br></br>
 
 
-Lists all single-shot subscribers of Event, together with their status<a name="list_subs-2"></a>
+Lists all single-shot subscribers of Event, together with their status
+<a name="list_subs-2"></a>
 
-###list_subs/2##
+### list_subs/2 ###
 
 
-<pre>list_subs(Scope::<a href="#type-scope">scope()</a>, Event::<a href="#type-event">event()</a>) -> [pid()]</pre>
-<br></br>
+<pre><code>
+list_subs(Scope::<a href="#type-scope">scope()</a>, Event::<a href="#type-event">event()</a>) -&gt; [pid()]
+</code></pre>
 
+<br></br>
 
 
 
 List the pids of all processes subscribing to `Event`
 
-This function uses `gproc:select/2` to find all properties indicating a subscription.<a name="notify_single_if_true-4"></a>
 
-###notify_single_if_true/4##
+This function uses `gproc:select/2` to find all properties indicating a subscription.
+<a name="notify_single_if_true-4"></a>
 
+### notify_single_if_true/4 ###
 
-<pre>notify_single_if_true(Scope::<a href="#type-scope">scope()</a>, Event::<a href="#type-event">event()</a>, F::fun(() -> boolean()), Msg::<a href="#type-msg">msg()</a>) -> ok</pre>
-<br></br>
 
+<pre><code>
+notify_single_if_true(Scope::<a href="#type-scope">scope()</a>, Event::<a href="#type-event">event()</a>, F::fun(() -&gt; boolean()), Msg::<a href="#type-msg">msg()</a>) -&gt; ok
+</code></pre>
+
+<br></br>
 
 
 
 Create/enable a single subscription for event; notify at once if F() -> true
 
+
 This function is a convenience function, wrapping a single-shot pub/sub around a
 user-provided boolean test. `Msg` should be what the publisher will send later, if the
-immediate test returns `false`.<a name="publish-3"></a>
+immediate test returns `false`.
+<a name="publish-3"></a>
 
-###publish/3##
+### publish/3 ###
 
 
-<pre>publish(Scope::<a href="#type-scope">scope()</a>, Event::<a href="#type-event">event()</a>, Msg::<a href="#type-msg">msg()</a>) -> ok</pre>
-<br></br>
+<pre><code>
+publish(Scope::<a href="#type-scope">scope()</a>, Event::<a href="#type-event">event()</a>, Msg::<a href="#type-msg">msg()</a>) -&gt; ok
+</code></pre>
 
+<br></br>
 
 
 
@@ -247,32 +297,40 @@ The message delivered to each subscriber will be of the form:
 
 `{gproc_ps_event, Event, Msg}`
 
+
 The function uses `gproc:send/2` to send a message to all processes which have a
-property `{p,Scope,{gproc_ps_event,Event}}`.<a name="publish_cond-3"></a>
+property `{p,Scope,{gproc_ps_event,Event}}`.
+<a name="publish_cond-3"></a>
 
-###publish_cond/3##
+### publish_cond/3 ###
 
 
-<pre>publish_cond(Scope::<a href="#type-scope">scope()</a>, Event::<a href="#type-event">event()</a>, Msg::<a href="#type-msg">msg()</a>) -> <a href="#type-msg">msg()</a></pre>
-<br></br>
+<pre><code>
+publish_cond(Scope::<a href="#type-scope">scope()</a>, Event::<a href="#type-event">event()</a>, Msg::<a href="#type-msg">msg()</a>) -&gt; <a href="#type-msg">msg()</a>
+</code></pre>
 
+<br></br>
 
 
 
 Publishes the message `Msg` to conditional subscribers of `Event`
 
+
 The message will be delivered to each subscriber provided their respective
 condition tests succeed.
 
 
-__See also:__ [subscribe_cond/3](#subscribe_cond-3).<a name="subscribe-2"></a>
+__See also:__ [subscribe_cond/3](#subscribe_cond-3).
+<a name="subscribe-2"></a>
 
-###subscribe/2##
+### subscribe/2 ###
 
 
-<pre>subscribe(Scope::<a href="#type-scope">scope()</a>, Event::<a href="#type-event">event()</a>) -> true</pre>
-<br></br>
+<pre><code>
+subscribe(Scope::<a href="#type-scope">scope()</a>, Event::<a href="#type-event">event()</a>) -&gt; true
+</code></pre>
 
+<br></br>
 
 
 
@@ -288,16 +346,20 @@ delivered to the current process, along with all other subscribers.
 This function creates a property, `{p,Scope,{gproc_ps_event,Event}}`, which
 can be searched and displayed for debugging purposes.
 
+
 Note that, as with [`gproc:reg/1`](gproc.md#reg-1), this function will raise an
 exception if you try to subscribe to the same event twice from the same
-process.<a name="subscribe_cond-3"></a>
+process.
+<a name="subscribe_cond-3"></a>
 
-###subscribe_cond/3##
+### subscribe_cond/3 ###
 
 
-<pre>subscribe_cond(Scope::<a href="#type-scope">scope()</a>, Event::<a href="#type-event">event()</a>, Spec::undefined | <a href="ets.md#type-match_spec">ets:match_spec()</a>) -> true</pre>
-<br></br>
+<pre><code>
+subscribe_cond(Scope::<a href="#type-scope">scope()</a>, Event::<a href="#type-event">event()</a>, Spec::undefined | <a href="ets.md#type-match_spec">ets:match_spec()</a>) -&gt; true
+</code></pre>
 
+<br></br>
 
 
 
@@ -333,16 +395,20 @@ expects it to be either undefined or a valid match spec).
 This means that `Cond=undefined` and `Cond=[{'_',[],[true]}]` are
 equivalent.
 
+
 Note that, as with [`gproc:reg/1`](gproc.md#reg-1), this function will raise an
 exception if you try to subscribe to the same event twice from the same
-process.<a name="tell_singles-3"></a>
+process.
+<a name="tell_singles-3"></a>
 
-###tell_singles/3##
+### tell_singles/3 ###
 
 
-<pre>tell_singles(Scope::<a href="#type-scope">scope()</a>, Event::<a href="#type-event">event()</a>, Msg::<a href="#type-msg">msg()</a>) -> [pid()]</pre>
-<br></br>
+<pre><code>
+tell_singles(Scope::<a href="#type-scope">scope()</a>, Event::<a href="#type-event">event()</a>, Msg::<a href="#type-msg">msg()</a>) -&gt; [pid()]
+</code></pre>
 
+<br></br>
 
 
 
@@ -357,18 +423,23 @@ context switch happens just after the select operation (finding the active subsc
 and before the process is able to update the counters. In this case, it is possible
 that more than one can be delivered.
 
+
 The way to prevent this from happening is to ensure that only one process publishes
-for `Event`.<a name="unsubscribe-2"></a>
+for `Event`.
+<a name="unsubscribe-2"></a>
 
-###unsubscribe/2##
+### unsubscribe/2 ###
 
 
-<pre>unsubscribe(Scope::<a href="#type-scope">scope()</a>, Event::<a href="#type-event">event()</a>) -> true</pre>
-<br></br>
+<pre><code>
+unsubscribe(Scope::<a href="#type-scope">scope()</a>, Event::<a href="#type-event">event()</a>) -&gt; true
+</code></pre>
 
+<br></br>
 
 
 
 Remove subscribtion created using `subscribe(Scope, Event)`
 
-This removes the property created through `subscribe/2`.
+
+This removes the property created through `subscribe/2`.

+ 54 - 0
doc/gproc_pt.md

@@ -0,0 +1,54 @@
+
+
+# Module gproc_pt #
+* [Description](#description)
+* [Function Index](#index)
+* [Function Details](#functions)
+
+
+Parse transform utility for gproc users.
+__Authors:__ Ulf Wiger ([`ulf@wiger.net`](mailto:ulf@wiger.net)), Dmitry Demeshchuk ([`demeshchuk@gmail.com`](mailto:demeshchuk@gmail.com)).
+<a name="description"></a>
+
+## Description ##
+
+
+
+This module provides some closer syntactical integration for
+people who are enthusiastic gproc users.
+
+
+
+Specifically, this module transforms `Pid ! Msg` into
+`gproc:send(Pid, Msg)`, which, apart from accepting any type for
+`Pid` that `!` understands, is also able to handle a gproc "triple",
+e.g. `{n, l, Name}` or even `{p, l, Prop}` (in the latter case, the
+message may be delivered to multiple recipients).
+
+
+
+Users should be aware that parse transforms may be confusing to
+the casual reader, since they extend the semantics of possibly
+ubiquitous constructs (as is the case with this transform). Therefore,
+you should document clearly that this is happening.
+
+
+Original suggestion by Dimitry Demeschuk.<a name="index"></a>
+
+## Function Index ##
+
+
+<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#parse_transform-2">parse_transform/2</a></td><td></td></tr></table>
+
+
+<a name="functions"></a>
+
+## Function Details ##
+
+<a name="parse_transform-2"></a>
+
+### parse_transform/2 ###
+
+`parse_transform(Forms, Options) -> any()`
+
+

+ 10 - 10
doc/gproc_sup.md

@@ -1,13 +1,13 @@
 
 
-#Module gproc_sup#
+# Module gproc_sup #
 * [Function Index](#index)
 * [Function Details](#functions)
 
+__Behaviours:__ [`supervisor`](supervisor.md).
+<a name="index"></a>
 
-__Behaviours:__ [`supervisor`](supervisor.md).<a name="index"></a>
-
-##Function Index##
+## 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>
@@ -15,19 +15,19 @@ __Behaviours:__ [`supervisor`](supervisor.md).<a name="index"></a>
 
 <a name="functions"></a>
 
-##Function Details##
+## Function Details ##
 
 <a name="init-1"></a>
 
-###init/1##
-
+### init/1 ###
 
 `init(Args) -> any()`
 
-The main GPROC supervisor.<a name="start_link-1"></a>
-
-###start_link/1##
+The main GPROC supervisor.
+<a name="start_link-1"></a>
 
+### start_link/1 ###
 
 `start_link(Args) -> any()`
 
+

+ 38 - 501
src/gproc_pt.erl

@@ -3,518 +3,55 @@
 %% 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.''
-%% 
-%%     $Id$
+%%
+%% @author Ulf Wiger <ulf@wiger.net>
+%% @author Dmitry Demeshchuk <demeshchuk@gmail.com>
+%%
+%% @doc Parse transform utility for gproc users.
+%%
+%% This module provides some closer syntactical integration for
+%% people who are enthusiastic gproc users.
+%%
+%% Specifically, this module transforms `Pid ! Msg' into
+%% `gproc:send(Pid, Msg)', which, apart from accepting any type for
+%% `Pid' that `!' understands, is also able to handle a gproc "triple",
+%% e.g. `{n, l, Name}' or even `{p, l, Prop}' (in the latter case, the
+%% message may be delivered to multiple recipients).
+%%
+%% Users should be aware that parse transforms may be confusing to
+%% the casual reader, since they extend the semantics of possibly
+%% ubiquitous constructs (as is the case with this transform). Therefore,
+%% you should document clearly that this is happening.
+%%
+%% Original suggestion by Dimitry Demeschuk.
+%% @end
 %%
 -module(gproc_pt).
 
-%% A identity transformer of Erlang abstract syntax.
-
-%% This module only traverses legal Erlang code. This is most noticeable
-%% in guards where only a limited number of expressions are allowed.
-%% N.B. if this module is to be used as a basis for tranforms then
-%% all the error cases must be handled otherwise this module just crashes!
-
 -export([parse_transform/2]).
 
 parse_transform(Forms, _Options) ->
-    forms(Forms).
-
-%% forms(Fs) -> lists:map(fun (F) -> form(F) end, Fs).
-
-forms([F0|Fs0]) ->
-    F1 = form(F0),
-    Fs1 = forms(Fs0),
-    [F1|Fs1];
-forms([]) -> [].
-
-%% -type form(Form) -> Form.
-%%  Here we show every known form and valid internal structure. We do not
-%%  that the ordering is correct!
-
-%% First the various attributes.
-form({attribute,Line,module,Mod}) ->
-    {attribute,Line,module,Mod};
-form({attribute,Line,file,{File,Line}}) ->	%This is valid anywhere.
-    {attribute,Line,file,{File,Line}};
-form({attribute,Line,export,Es0}) ->
-    Es1 = farity_list(Es0),
-    {attribute,Line,export,Es1};
-form({attribute,Line,import,{Mod,Is0}}) ->
-    Is1 = farity_list(Is0),
-    {attribute,Line,import,{Mod,Is1}};
-form({attribute,Line,compile,C}) ->
-    {attribute,Line,compile,C};
-form({attribute,Line,record,{Name,Defs0}}) ->
-    Defs1 = record_defs(Defs0),
-    {attribute,Line,record,{Name,Defs1}};
-form({attribute,Line,asm,{function,N,A,Code}}) ->
-    {attribute,Line,asm,{function,N,A,Code}};
-form({attribute,Line,Attr,Val}) ->		%The general attribute.
-    {attribute,Line,Attr,Val};
-form({function,Line,Name0,Arity0,Clauses0}) ->
-    {Name,Arity,Clauses} = function(Name0, Arity0, Clauses0),
-    {function,Line,Name,Arity,Clauses};
-% Mnemosyne, ignore...
-form({rule,Line,Name,Arity,Body}) ->
-    {rule,Line,Name,Arity,Body}; % Dont dig into this
-%% Extra forms from the parser.
-form({error,E}) -> {error,E};
-form({warning,W}) -> {warning,W};
-form({eof,Line}) -> {eof,Line}.
-
-%% -type farity_list([Farity]) -> [Farity] when Farity <= {atom(),integer()}.
-
-farity_list([{Name,Arity}|Fas]) ->
-    [{Name,Arity}|farity_list(Fas)];
-farity_list([]) -> [].
-
-%% -type record_defs([RecDef]) -> [RecDef].
-%%  N.B. Field names are full expressions here but only atoms are allowed
-%%  by the *parser*!
-
-record_defs([{record_field,Line,{atom,La,A},Val0}|Is]) ->
-    Val1 = expr(Val0),
-    [{record_field,Line,{atom,La,A},Val1}|record_defs(Is)];
-record_defs([{record_field,Line,{atom,La,A}}|Is]) ->
-    [{record_field,Line,{atom,La,A}}|record_defs(Is)];
-record_defs([]) -> [].
-
-%% -type function(atom(), integer(), [Clause]) -> {atom(),integer(),[Clause]}.
-
-function(Name, Arity, Clauses0) ->
-    Clauses1 = clauses(Clauses0),
-    {Name,Arity,Clauses1}.
-
-%% -type clauses([Clause]) -> [Clause].
-
-clauses([C0|Cs]) ->
-    C1 = clause(C0),
-    [C1|clauses(Cs)];
-clauses([]) -> [].
-
-%% -type clause(Clause) -> Clause.
-
-clause({clause,Line,H0,G0,B0}) ->
-    H1 = head(H0),
-    G1 = guard(G0),
-    B1 = exprs(B0),
-    {clause,Line,H1,G1,B1}.
-
-%% -type head([Pattern]) -> [Pattern].
-
-head(Ps) -> patterns(Ps).
-
-%% -type patterns([Pattern]) -> [Pattern].
-%%  These patterns are processed "sequentially" for purposes of variable
-%%  definition etc.
-
-patterns([P0|Ps]) ->
-    P1 = pattern(P0),
-    [P1|patterns(Ps)];
-patterns([]) -> [].
-
-%% -type pattern(Pattern) -> Pattern.
-%%  N.B. Only valid patterns are included here.
-
-pattern({var,Line,V}) -> {var,Line,V};
-pattern({match,Line,L0,R0}) ->
-    L1 = pattern(L0),
-    R1 = pattern(R0),
-    {match,Line,L1,R1};
-pattern({integer,Line,I}) -> {integer,Line,I};
-pattern({char,Line,C}) -> {char,Line,C};
-pattern({float,Line,F}) -> {float,Line,F};
-pattern({atom,Line,A}) -> {atom,Line,A};
-pattern({string,Line,S}) -> {string,Line,S};
-pattern({nil,Line}) -> {nil,Line};
-pattern({cons,Line,H0,T0}) ->
-    H1 = pattern(H0),
-    T1 = pattern(T0),
-    {cons,Line,H1,T1};
-pattern({tuple,Line,Ps0}) ->
-    Ps1 = pattern_list(Ps0),
-    {tuple,Line,Ps1};
-%%pattern({struct,Line,Tag,Ps0}) ->
-%%    Ps1 = pattern_list(Ps0),
-%%    {struct,Line,Tag,Ps1};
-pattern({record,Line,Name,Pfs0}) ->
-    Pfs1 = pattern_fields(Pfs0),
-    {record,Line,Name,Pfs1};
-pattern({record_index,Line,Name,Field0}) ->
-    Field1 = pattern(Field0),
-    {record_index,Line,Name,Field1};
-%% record_field occurs in query expressions
-pattern({record_field,Line,Rec0,Name,Field0}) ->
-    Rec1 = expr(Rec0),
-    Field1 = expr(Field0),
-    {record_field,Line,Rec1,Name,Field1};
-pattern({record_field,Line,Rec0,Field0}) ->
-    Rec1 = expr(Rec0),
-    Field1 = expr(Field0),
-    {record_field,Line,Rec1,Field1};
-pattern({bin,Line,Fs}) ->
-    Fs2 = pattern_grp(Fs),
-    {bin,Line,Fs2};
-pattern({op,Line,Op,A}) ->
-    {op,Line,Op,A};
-pattern({op,Line,Op,L,R}) ->
-    {op,Line,Op,L,R}.
-
-pattern_grp([{bin_element,L1,E1,S1,T1} | Fs]) ->
-    S2 = case S1 of
-	     default ->
-		 default;
-	     _ ->
-		 expr(S1)
-	 end,
-    T2 = case T1 of
-	     default ->
-		 default;
-	     _ ->
-		 bit_types(T1)
-	 end,
-    [{bin_element,L1,expr(E1),S2,T2} | pattern_grp(Fs)];
-pattern_grp([]) ->
-    [].
-
-bit_types([]) ->
+    do_transform(Forms).
+
+do_transform([{op, L, '!', Lhs, Rhs}|Fs]) ->
+    [NewLhs] = do_transform([Lhs]),
+    [NewRhs] = do_transform([Rhs]),
+    [{call, L, {remote, L, {atom, L, gproc}, {atom, L, send}},
+        [NewLhs, NewRhs]} | do_transform(Fs)];
+do_transform([]) ->
     [];
-bit_types([Atom | Rest]) when is_atom(Atom) ->
-    [Atom | bit_types(Rest)];
-bit_types([{Atom, Integer} | Rest]) when is_atom(Atom), is_integer(Integer) ->
-    [{Atom, Integer} | bit_types(Rest)].
-
-
-
-%% -type pattern_list([Pattern]) -> [Pattern].
-%%  These patterns are processed "in parallel" for purposes of variable
-%%  definition etc.
-
-pattern_list([P0|Ps]) ->
-    P1 = pattern(P0),
-    [P1|pattern_list(Ps)];
-pattern_list([]) -> [].
-
-%% -type pattern_fields([Field]) -> [Field].
-%%  N.B. Field names are full expressions here but only atoms are allowed
-%%  by the *linter*!.
-
-pattern_fields([{record_field,Lf,{atom,La,F},P0}|Pfs]) ->
-    P1 = pattern(P0),
-    [{record_field,Lf,{atom,La,F},P1}|pattern_fields(Pfs)];
-pattern_fields([{record_field,Lf,{var,La,'_'},P0}|Pfs]) ->
-    P1 = pattern(P0),
-    [{record_field,Lf,{var,La,'_'},P1}|pattern_fields(Pfs)];
-pattern_fields([]) -> [].
-
-%% -type guard([GuardTest]) -> [GuardTest].
-
-guard([G0|Gs]) when is_list(G0) ->
-    [guard0(G0) | guard(Gs)];
-guard(L) ->
-    guard0(L).
-
-guard0([G0|Gs]) ->
-    G1 =  guard_test(G0),
-    [G1|guard0(Gs)];
-guard0([]) -> [].
-
-guard_test(Expr={call,Line,{atom,La,F},As0}) ->
-    case erl_internal:type_test(F, length(As0)) of
-	true -> 
-	    As1 = gexpr_list(As0),
-	    {call,Line,{atom,La,F},As1};
-	_ ->
-	    gexpr(Expr)
-    end;
-guard_test(Any) ->
-    gexpr(Any).
-
-%% Before R9, there were special rules regarding the expressions on
-%% top level in guards. Those limitations are now lifted - therefore
-%% there is no need for a special clause for the toplevel expressions.
-%% -type gexpr(GuardExpr) -> GuardExpr.
-
-gexpr({var,Line,V}) -> {var,Line,V};
-gexpr({integer,Line,I}) -> {integer,Line,I};
-gexpr({char,Line,C}) -> {char,Line,C};
-gexpr({float,Line,F}) -> {float,Line,F};
-gexpr({atom,Line,A}) -> {atom,Line,A};
-gexpr({string,Line,S}) -> {string,Line,S};
-gexpr({nil,Line}) -> {nil,Line};
-gexpr({cons,Line,H0,T0}) ->
-    H1 = gexpr(H0),
-    T1 = gexpr(T0),				%They see the same variables
-    {cons,Line,H1,T1};
-gexpr({tuple,Line,Es0}) ->
-    Es1 = gexpr_list(Es0),
-    {tuple,Line,Es1};
-gexpr({record_index,Line,Name,Field0}) ->
-    Field1 = gexpr(Field0),
-    {record_index,Line,Name,Field1};
-gexpr({record_field,Line,Rec0,Name,Field0}) ->
-    Rec1 = gexpr(Rec0),
-    Field1 = gexpr(Field0),
-    {record_field,Line,Rec1,Name,Field1};
-gexpr({record,Line,Name,Inits0}) ->
-    Inits1 = grecord_inits(Inits0),
-    {record,Line,Name,Inits1};
-gexpr({call,Line,{atom,La,F},As0}) ->
-    case erl_internal:guard_bif(F, length(As0)) of
-	true -> As1 = gexpr_list(As0),
-		{call,Line,{atom,La,F},As1}
-    end;
-% Guard bif's can be remote, but only in the module erlang...
-gexpr({call,Line,{remote,La,{atom,Lb,erlang},{atom,Lc,F}},As0}) ->
-    case erl_internal:guard_bif(F, length(As0)) or
-	 erl_internal:arith_op(F, length(As0)) or 
-	 erl_internal:comp_op(F, length(As0)) or
-	 erl_internal:bool_op(F, length(As0)) of
-	true -> As1 = gexpr_list(As0),
-		{call,Line,{remote,La,{atom,Lb,erlang},{atom,Lc,F}},As1}
-    end;
-% Unfortunately, writing calls as {M,F}(...) is also allowed.
-gexpr({call,Line,{tuple,La,[{atom,Lb,erlang},{atom,Lc,F}]},As0}) ->
-    case erl_internal:guard_bif(F, length(As0)) or
-	 erl_internal:arith_op(F, length(As0)) or 
-	 erl_internal:comp_op(F, length(As0)) or
-	 erl_internal:bool_op(F, length(As0)) of
-	true -> As1 = gexpr_list(As0),
-		{call,Line,{tuple,La,[{atom,Lb,erlang},{atom,Lc,F}]},As1}
-    end;
-gexpr({bin,Line,Fs}) ->
-    Fs2 = pattern_grp(Fs),
-    {bin,Line,Fs2};
-gexpr({op,Line,Op,A0}) ->
-    case erl_internal:arith_op(Op, 1) or 
-	 erl_internal:bool_op(Op, 1) of
-	true -> A1 = gexpr(A0),
-		{op,Line,Op,A1}
-    end;
-gexpr({op,Line,Op,L0,R0}) when Op =:= 'andalso'; Op =:= 'orelse' ->
-    %% R11B: andalso/orelse are now allowed in guards.
-    L1 = gexpr(L0),
-    R1 = gexpr(R0),			%They see the same variables
-    {op,Line,Op,L1,R1};
-gexpr({op,Line,Op,L0,R0}) ->
-    case erl_internal:arith_op(Op, 2) or
-	  erl_internal:bool_op(Op, 2) or 
-	  erl_internal:comp_op(Op, 2) of
-	true ->
-	    L1 = gexpr(L0),
-	    R1 = gexpr(R0),			%They see the same variables
-	    {op,Line,Op,L1,R1}
-    end.
-
-%% -type gexpr_list([GuardExpr]) -> [GuardExpr].
-%%  These expressions are processed "in parallel" for purposes of variable
-%%  definition etc.
-
-gexpr_list([E0|Es]) ->
-    E1 = gexpr(E0),
-    [E1|gexpr_list(Es)];
-gexpr_list([]) -> [].
-
-grecord_inits([{record_field,Lf,{atom,La,F},Val0}|Is]) ->
-    Val1 = gexpr(Val0),
-    [{record_field,Lf,{atom,La,F},Val1}|grecord_inits(Is)];
-grecord_inits([{record_field,Lf,{var,La,'_'},Val0}|Is]) ->
-    Val1 = gexpr(Val0),
-    [{record_field,Lf,{var,La,'_'},Val1}|grecord_inits(Is)];
-grecord_inits([]) -> [].
-
-%% -type exprs([Expression]) -> [Expression].
-%%  These expressions are processed "sequentially" for purposes of variable
-%%  definition etc.
-
-exprs([E0|Es]) ->
-    E1 = expr(E0),
-    [E1|exprs(Es)];
-exprs([]) -> [].
-
-%% -type expr(Expression) -> Expression.
-
-expr({var,Line,V}) -> {var,Line,V};
-expr({integer,Line,I}) -> {integer,Line,I};
-expr({float,Line,F}) -> {float,Line,F};
-expr({atom,Line,A}) -> {atom,Line,A};
-expr({string,Line,S}) -> {string,Line,S};
-expr({char,Line,C}) -> {char,Line,C};
-expr({nil,Line}) -> {nil,Line};
-expr({cons,Line,H0,T0}) ->
-    H1 = expr(H0),
-    T1 = expr(T0),				%They see the same variables
-    {cons,Line,H1,T1};
-expr({lc,Line,E0,Qs0}) ->
-    Qs1 = lc_bc_quals(Qs0),
-    E1 = expr(E0),
-    {lc,Line,E1,Qs1};
-expr({bc,Line,E0,Qs0}) ->
-    Qs1 = lc_bc_quals(Qs0),
-    E1 = expr(E0),
-    {bc,Line,E1,Qs1};
-expr({tuple,Line,Es0}) ->
-    Es1 = expr_list(Es0),
-    {tuple,Line,Es1};
-%%expr({struct,Line,Tag,Es0}) ->
-%%    Es1 = pattern_list(Es0),
-%%    {struct,Line,Tag,Es1};
-expr({record_index,Line,Name,Field0}) ->
-    Field1 = expr(Field0),
-    {record_index,Line,Name,Field1};
-expr({record,Line,Name,Inits0}) ->
-    Inits1 = record_inits(Inits0),
-    {record,Line,Name,Inits1};
-expr({record_field,Line,Rec0,Name,Field0}) ->
-    Rec1 = expr(Rec0),
-    Field1 = expr(Field0),
-    {record_field,Line,Rec1,Name,Field1};
-expr({record,Line,Rec0,Name,Upds0}) ->
-    Rec1 = expr(Rec0),
-    Upds1 = record_updates(Upds0),
-    {record,Line,Rec1,Name,Upds1};
-expr({record_field,Line,Rec0,Field0}) ->
-    Rec1 = expr(Rec0),
-    Field1 = expr(Field0),
-    {record_field,Line,Rec1,Field1};
-expr({block,Line,Es0}) ->
-    %% Unfold block into a sequence.
-    Es1 = exprs(Es0),
-    {block,Line,Es1};
-expr({'if',Line,Cs0}) ->
-    Cs1 = icr_clauses(Cs0),
-    {'if',Line,Cs1};
-expr({'case',Line,E0,Cs0}) ->
-    E1 = expr(E0),
-    Cs1 = icr_clauses(Cs0),
-    {'case',Line,E1,Cs1};
-expr({'receive',Line,Cs0}) ->
-    Cs1 = icr_clauses(Cs0),
-    {'receive',Line,Cs1};
-expr({'receive',Line,Cs0,To0,ToEs0}) ->
-    To1 = expr(To0),
-    ToEs1 = exprs(ToEs0),
-    Cs1 = icr_clauses(Cs0),
-    {'receive',Line,Cs1,To1,ToEs1};
-expr({'try',Line,Es0,Scs0,Ccs0,As0}) ->
-    Es1 = exprs(Es0),
-    Scs1 = icr_clauses(Scs0),
-    Ccs1 = icr_clauses(Ccs0),
-    As1 = exprs(As0),
-    {'try',Line,Es1,Scs1,Ccs1,As1};
-expr({'fun',Line,Body}) ->
-    case Body of
-	{clauses,Cs0} ->
-	    Cs1 = fun_clauses(Cs0),
-	    {'fun',Line,{clauses,Cs1}};
-	{function,F,A} ->
-	    {'fun',Line,{function,F,A}};
-	{function,M,F,A} ->			%R10B-6: fun M:F/A.
-	    {'fun',Line,{function,M,F,A}}
-    end;
-expr({call,Line,F0,As0}) ->
-    %% N.B. If F an atom then call to local function or BIF, if F a
-    %% remote structure (see below) then call to other module,
-    %% otherwise apply to "function".
-    F1 = expr(F0),
-    As1 = expr_list(As0),
-    {call,Line,F1,As1};
-expr({'catch',Line,E0}) ->
-    %% No new variables added.
-    E1 = expr(E0),
-    {'catch',Line,E1};
-expr({'query', Line, E0}) ->
-    %% lc expression
-    E = expr(E0),
-    {'query', Line, E};
-expr({match,Line,P0,E0}) ->
-    E1 = expr(E0),
-    P1 = pattern(P0),
-    {match,Line,P1,E1};
-expr({bin,Line,Fs}) ->
-    Fs2 = pattern_grp(Fs),
-    {bin,Line,Fs2};
-expr({op,Line,Op,A0}) ->
-    A1 = expr(A0),
-    {op,Line,Op,A1};
-expr({op, Line, '!', L0, R0}) ->
-    {call,Line,{remote,Line,{atom,Line,gproc},{atom,Line,send}},[L0, R0]};
-expr({op,Line,Op,L0,R0}) ->
-    L1 = expr(L0),
-    R1 = expr(R0),				%They see the same variables
-    {op,Line,Op,L1,R1};
-%% The following are not allowed to occur anywhere!
-expr({remote,Line,M0,F0}) ->
-    M1 = expr(M0),
-    F1 = expr(F0),
-    {remote,Line,M1,F1}.
-
-%% -type expr_list([Expression]) -> [Expression].
-%%  These expressions are processed "in parallel" for purposes of variable
-%%  definition etc.
-
-expr_list([E0|Es]) ->
-    E1 = expr(E0),
-    [E1|expr_list(Es)];
-expr_list([]) -> [].
-
-%% -type record_inits([RecordInit]) -> [RecordInit].
-%%  N.B. Field names are full expressions here but only atoms are allowed
-%%  by the *linter*!.
-
-record_inits([{record_field,Lf,{atom,La,F},Val0}|Is]) ->
-    Val1 = expr(Val0),
-    [{record_field,Lf,{atom,La,F},Val1}|record_inits(Is)];
-record_inits([{record_field,Lf,{var,La,'_'},Val0}|Is]) ->
-    Val1 = expr(Val0),
-    [{record_field,Lf,{var,La,'_'},Val1}|record_inits(Is)];
-record_inits([]) -> [].
-
-%% -type record_updates([RecordUpd]) -> [RecordUpd].
-%%  N.B. Field names are full expressions here but only atoms are allowed
-%%  by the *linter*!.
-
-record_updates([{record_field,Lf,{atom,La,F},Val0}|Us]) ->
-    Val1 = expr(Val0),
-    [{record_field,Lf,{atom,La,F},Val1}|record_updates(Us)];
-record_updates([]) -> [].
-
-%% -type icr_clauses([Clause]) -> [Clause].
-
-icr_clauses([C0|Cs]) ->
-    C1 = clause(C0),
-    [C1|icr_clauses(Cs)];
-icr_clauses([]) -> [].
-
-%% -type lc_bc_quals([Qualifier]) -> [Qualifier].
-%%  Allow filters to be both guard tests and general expressions.
-
-lc_bc_quals([{generate,Line,P0,E0}|Qs]) ->
-    E1 = expr(E0),
-    P1 = pattern(P0),
-    [{generate,Line,P1,E1}|lc_bc_quals(Qs)];
-lc_bc_quals([{b_generate,Line,P0,E0}|Qs]) ->
-    E1 = expr(E0),
-    P1 = pattern(P0),
-    [{b_generate,Line,P1,E1}|lc_bc_quals(Qs)];
-lc_bc_quals([E0|Qs]) ->
-    E1 = expr(E0),
-    [E1|lc_bc_quals(Qs)];
-lc_bc_quals([]) -> [].
-
-%% -type fun_clauses([Clause]) -> [Clause].
-
-fun_clauses([C0|Cs]) ->
-    C1 = clause(C0),
-    [C1|fun_clauses(Cs)];
-fun_clauses([]) -> [].
+do_transform([F|Fs]) when is_tuple(F) ->
+    [list_to_tuple(do_transform(tuple_to_list(F))) | do_transform(Fs)];
+do_transform([F|Fs]) ->
+    [do_transform(F) | do_transform(Fs)];
+do_transform(F) ->
+    F.