Browse Source

more accurate exceptions

Ulf Wiger 13 years ago
parent
commit
f1c92b6624
6 changed files with 244 additions and 152 deletions
  1. 47 47
      doc/gproc.md
  2. 1 1
      doc/gproc_dist.md
  3. 2 2
      doc/gproc_lib.md
  4. 2 2
      doc/gproc_monitor.md
  5. 165 100
      src/gproc.erl
  6. 27 0
      src/gproc_int.hrl

+ 47 - 47
doc/gproc.md

@@ -56,7 +56,7 @@ will improve performance.
 
 
 
-<pre>context() = {<a href="#type-scope">scope()</a>, <a href="#type-type">type()</a>} | <a href="#type-type">type()</a></pre>
+<pre>context() = {[scope()](#type-scope), [type()](#type-type)} | [type()](#type-type)</pre>
 
 
 {'all','all'} is the default
@@ -67,7 +67,7 @@ will improve performance.
 
 
 
-<pre>headpat() = {<a href="#type-keypat">keypat()</a>, <a href="#type-pidpat">pidpat()</a>, ValPat}</pre>
+<pre>headpat() = {[keypat()](#type-keypat), [pidpat()](#type-pidpat), ValPat}</pre>
 
 
 
@@ -75,7 +75,7 @@ will improve performance.
 
 
 
-<pre>key() = {<a href="#type-type">type()</a>, <a href="#type-scope">scope()</a>, any()}</pre>
+<pre>key() = {[type()](#type-type), [scope()](#type-scope), any()}</pre>
 
 
 
@@ -83,7 +83,7 @@ will improve performance.
 
 
 
-<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>keypat() = {[sel_type()](#type-sel_type) | [sel_var()](#type-sel_var), l | g | [sel_var()](#type-sel_var), any()}</pre>
 
 
 
@@ -91,7 +91,7 @@ will improve performance.
 
 
 
-<pre>pidpat() = pid() | <a href="#type-sel_var">sel_var()</a></pre>
+<pre>pidpat() = pid() | [sel_var()](#type-sel_var)</pre>
 
 
 
@@ -99,7 +99,7 @@ will improve performance.
 
 
 
-<pre>reg_id() = {<a href="#type-type">type()</a>, <a href="#type-scope">scope()</a>, any()}</pre>
+<pre>reg_id() = {[type()](#type-type), [scope()](#type-scope), any()}</pre>
 
 
 
@@ -118,7 +118,7 @@ l = local registration; g = global registration
 
 
 
-<pre>sel_pattern() = [{<a href="#type-headpat">headpat()</a>, Guards, Prod}]</pre>
+<pre>sel_pattern() = [{[headpat()](#type-headpat), Guards, Prod}]</pre>
 
 
 
@@ -134,7 +134,7 @@ l = local registration; g = global registration
 
 
 
-<pre>sel_type() = <a href="#type-type">type()</a> | names | props | counters | aggr_counters</pre>
+<pre>sel_type() = [type()](#type-type) | names | props | counters | aggr_counters</pre>
 
 
 
@@ -161,7 +161,7 @@ a = aggregate_counter
 
 
 
-<pre>unique_id() = {n | a, <a href="#type-scope">scope()</a>, any()}</pre>
+<pre>unique_id() = {n | a, [scope()](#type-scope), any()}</pre>
 <a name="index"></a>
 
 ##Function Index##
@@ -303,7 +303,7 @@ Registers a local shared (unique) counter.<a name="audit_process-1"></a>
 
 
 
-<pre>await(Key::<a href="#type-key">key()</a>) -> {pid(), Value}</pre>
+<pre>await(Key::[key()](#type-key)) -&gt; {pid(), Value}</pre>
 <br></br>
 
 
@@ -316,7 +316,7 @@ Equivalent to [`await(Key, infinity)`](#await-2).<a name="await-2"></a>
 
 
 
-<pre>await(Key::<a href="#type-key">key()</a>, Timeout) -> {pid(), Value}</pre>
+<pre>await(Key::[key()](#type-key), Timeout) -&gt; {pid(), Value}</pre>
 <ul class="definitions"><li><pre>Timeout = integer() | infinity</pre></li></ul>
 
 
@@ -334,7 +334,7 @@ registered (the difference: await/2 also returns the value).<a name="cancel_wait
 
 
 
-<pre>cancel_wait(Key::<a href="#type-key">key()</a>, Ref) -> ok</pre>
+<pre>cancel_wait(Key::[key()](#type-key), Ref) -&gt; ok</pre>
 <ul class="definitions"><li><pre>Ref = all | reference()</pre></li></ul>
 
 
@@ -369,7 +369,7 @@ are canceled.<a name="cancel_wait_or_monitor-1"></a>
 
 
 
-<pre>demonitor(Key::<a href="#type-key">key()</a>, Ref::reference()) -> ok</pre>
+<pre>demonitor(Key::[key()](#type-key), Ref::reference()) -&gt; ok</pre>
 <br></br>
 
 
@@ -384,7 +384,7 @@ set on a unique name. This function always succeeds given legal input.<a name="f
 
 
 
-<pre>first(Context::<a href="#type-context">context()</a>) -> <a href="#type-key">key()</a> | '$end_of_table'</pre>
+<pre>first(Context::[context()](#type-context)) -&gt; [key()](#type-key) | '$end_of_table'</pre>
 <br></br>
 
 
@@ -402,7 +402,7 @@ The registry behaves as an ordered_set table.<a name="get_env-3"></a>
 
 
 
-<pre>get_env(Scope::<a href="#type-scope">scope()</a>, App::atom(), Key::atom()) -> term()</pre>
+<pre>get_env(Scope::[scope()](#type-scope), App::atom(), Key::atom()) -&gt; term()</pre>
 <br></br>
 
 
@@ -415,8 +415,8 @@ Equivalent to [`get_env(Scope, App, Key, [app_env])`](#get_env-4).<a name="get_e
 
 
 
-<pre>get_env(Scope::<a href="#type-scope">scope()</a>, App::atom(), Key::atom(), Strategy) -> term()</pre>
-<ul class="definitions"><li><pre>Strategy = [Alternative]</pre></li><li><pre>Alternative = app_env | os_env | inherit | {inherit, pid()} | {inherit, <a href="#type-unique_id">unique_id()</a>} | init_arg | {mnesia, ActivityType, Oid, Pos} | {default, term()} | error</pre></li></ul>
+<pre>get_env(Scope::[scope()](#type-scope), App::atom(), Key::atom(), Strategy) -&gt; term()</pre>
+<ul class="definitions"><li><pre>Strategy = [Alternative]</pre></li><li><pre>Alternative = app_env | os_env | inherit | {inherit, pid()} | {inherit, &lt;a href="#type-unique_id"&gt;unique_id()&lt;/a&gt;} | init_arg | {mnesia, ActivityType, Oid, Pos} | {default, term()} | error</pre></li></ul>
 
 
 
@@ -475,7 +475,7 @@ e.g. `get_env(l, mnesia, dir, [app_env, error])`.<a name="get_set_env-3"></a>
 
 
 
-<pre>get_set_env(Scope::<a href="#type-scope">scope()</a>, App::atom(), Key::atom()) -> term()</pre>
+<pre>get_set_env(Scope::[scope()](#type-scope), App::atom(), Key::atom()) -&gt; term()</pre>
 <br></br>
 
 
@@ -488,7 +488,7 @@ Equivalent to [`get_set_env(Scope, App, Key, [app_env])`](#get_set_env-4).<a nam
 
 
 
-<pre>get_set_env(Scope::<a href="#type-scope">scope()</a>, App::atom(), Key::atom(), Strategy) -> Value</pre>
+<pre>get_set_env(Scope::[scope()](#type-scope), App::atom(), Key::atom(), Strategy) -&gt; Value</pre>
 <br></br>
 
 
@@ -545,7 +545,7 @@ will be read.<a name="give_away-2"></a>
 
 
 
-<pre>give_away(From::<a href="#type-key">key()</a>, To::pid() | <a href="#type-key">key()</a>) -> undefined | pid()</pre>
+<pre>give_away(From::[key()](#type-key), To::pid() | [key()](#type-key)) -&gt; undefined | pid()</pre>
 <br></br>
 
 
@@ -650,7 +650,7 @@ same as [`http://www.erlang.org/doc/man/erlang.html#process_info-2`](http://www.
 
 
 
-<pre>last(Context::<a href="#type-context">context()</a>) -> <a href="#type-key">key()</a> | '$end_of_table'</pre>
+<pre>last(Context::[context()](#type-context)) -&gt; [key()](#type-key) | '$end_of_table'</pre>
 <br></br>
 
 
@@ -808,7 +808,7 @@ Lookup the Pid stored with a key.
 
 
 
-<pre>lookup_pids(Key::<a href="#type-key">key()</a>) -> [pid()]</pre>
+<pre>lookup_pids(Key::[key()](#type-key)) -&gt; [pid()]</pre>
 <br></br>
 
 
@@ -841,7 +841,7 @@ Lookup the value stored with a key.
 
 
 
-<pre>lookup_values(Key::<a href="#type-key">key()</a>) -> [{pid(), Value}]</pre>
+<pre>lookup_values(Key::[key()](#type-key)) -&gt; [{pid(), Value}]</pre>
 <br></br>
 
 
@@ -860,7 +860,7 @@ object, the return value can be a list of any length.<a name="monitor-1"></a>
 
 
 
-<pre>monitor(Key::<a href="#type-key">key()</a>) -> reference()</pre>
+<pre>monitor(Key::[key()](#type-key)) -&gt; reference()</pre>
 <br></br>
 
 
@@ -881,7 +881,7 @@ If the name is not yet registered, the same message is sent immediately.<a name=
 
 
 
-<pre>mreg(T::<a href="#type-type">type()</a>, X2::<a href="#type-scope">scope()</a>, KVL::[{Key::any(), Value::any()}]) -> true</pre>
+<pre>mreg(T::[type()](#type-type), C::[scope()](#type-scope), KVL::[{Key::any(), Value::any()}]) -&gt; true</pre>
 <br></br>
 
 
@@ -900,7 +900,7 @@ or none are.<a name="munreg-3"></a>
 
 
 
-<pre>munreg(T::<a href="#type-type">type()</a>, X2::<a href="#type-scope">scope()</a>, L::[Key::any()]) -> true</pre>
+<pre>munreg(T::[type()](#type-type), C::[scope()](#type-scope), L::[Key::any()]) -&gt; true</pre>
 <br></br>
 
 
@@ -918,7 +918,7 @@ repeatedly.<a name="nb_wait-1"></a>
 
 
 
-<pre>nb_wait(Key::<a href="#type-key">key()</a>) -> Ref</pre>
+<pre>nb_wait(Key::[key()](#type-key)) -&gt; Ref</pre>
 <br></br>
 
 
@@ -933,7 +933,7 @@ The caller can expect to receive a message,
 
 
 
-<pre>next(Context::<a href="#type-context">context()</a>, Key::<a href="#type-key">key()</a>) -> <a href="#type-key">key()</a> | '$end_of_table'</pre>
+<pre>next(Context::[context()](#type-context), Key::[key()](#type-key)) -&gt; [key()](#type-key) | '$end_of_table'</pre>
 <br></br>
 
 
@@ -951,7 +951,7 @@ The registry behaves as an ordered_set table.<a name="prev-2"></a>
 
 
 
-<pre>prev(Context::<a href="#type-context">context()</a>, Key::<a href="#type-key">key()</a>) -> <a href="#type-key">key()</a> | '$end_of_table'</pre>
+<pre>prev(Context::[context()](#type-context), Key::[key()](#type-key)) -&gt; [key()](#type-key) | '$end_of_table'</pre>
 <br></br>
 
 
@@ -969,7 +969,7 @@ The registry behaves as an ordered_set table.<a name="reg-1"></a>
 
 
 
-<pre>reg(Key::<a href="#type-key">key()</a>) -> true</pre>
+<pre>reg(Key::[key()](#type-key)) -&gt; true</pre>
 <br></br>
 
 
@@ -982,7 +982,7 @@ Equivalent to [`reg(Key, default(Key))`](#reg-2).<a name="reg-2"></a>
 
 
 
-<pre>reg(Key::<a href="#type-key">key()</a>, Value) -> true</pre>
+<pre>reg(Key::[key()](#type-key), Value) -&gt; true</pre>
 <br></br>
 
 
@@ -999,7 +999,7 @@ Register a name or property for the current process
 
 
 
-<pre>reg_shared(Key::<a href="#type-key">key()</a>) -> true</pre>
+<pre>reg_shared(Key::[key()](#type-key)) -&gt; true</pre>
 <br></br>
 
 
@@ -1017,7 +1017,7 @@ Register a resource, but don't tie it to a particular process.
 
 
 
-<pre>reg_shared(Key::<a href="#type-key">key()</a>, Value) -> true</pre>
+<pre>reg_shared(Key::[key()](#type-key), Value) -&gt; true</pre>
 <br></br>
 
 
@@ -1044,7 +1044,7 @@ an aggregated counter which is owned by a process.<a name="register_name-2"></a>
 
 
 
-<pre>register_name(Name::<a href="#type-key">key()</a>, Pid::pid()) -> yes | no</pre>
+<pre>register_name(Name::[key()](#type-key), Pid::pid()) -&gt; yes | no</pre>
 <br></br>
 
 
@@ -1090,7 +1090,7 @@ see http://www.erlang.org/doc/man/ets.html#select-1<a name="select-2"></a>
 
 
 
-<pre>select(Context::<a href="#type-context">context()</a>, Pat::<a href="#type-sel_pattern">sel_pattern()</a>) -> [{Key, Pid, Value}]</pre>
+<pre>select(Context::[context()](#type-context), Pat::[sel_pattern()](#type-sel_pattern)) -&gt; [{Key, Pid, Value}]</pre>
 <br></br>
 
 
@@ -1108,7 +1108,7 @@ but the select patterns are transformed appropriately.<a name="select-3"></a>
 
 
 
-<pre>select(Context::<a href="#type-context">context()</a>, Pat::<a href="#type-sel_patten">sel_patten()</a>, Limit::integer()) -> {[Match], Continuation} | '$end_of_table'</pre>
+<pre>select(Context::[context()](#type-context), Pat::[sel_patten()](#type-sel_patten), Limit::integer()) -&gt; {[Match], Continuation} | '$end_of_table'</pre>
 <br></br>
 
 
@@ -1125,7 +1125,7 @@ See [`http://www.erlang.org/doc/man/ets.html#select-3`](http://www.erlang.org/do
 
 
 
-<pre>select_count(Pat::<a href="#type-select_pattern">select_pattern()</a>) -> [<a href="#type-sel_object">sel_object()</a>]</pre>
+<pre>select_count(Pat::[select_pattern()](#type-select_pattern)) -&gt; [[sel_object()](#type-sel_object)]</pre>
 <br></br>
 
 
@@ -1138,7 +1138,7 @@ Equivalent to [`select_count(all, Pat)`](#select_count-2).<a name="select_count-
 
 
 
-<pre>select_count(Context::<a href="#type-context">context()</a>, Pat::<a href="#type-sel_pattern">sel_pattern()</a>) -> [{Key, Pid, Value}]</pre>
+<pre>select_count(Context::[context()](#type-context), Pat::[sel_pattern()](#type-sel_pattern)) -&gt; [{Key, Pid, Value}]</pre>
 <br></br>
 
 
@@ -1156,7 +1156,7 @@ but the select patterns are transformed appropriately.<a name="send-2"></a>
 
 
 
-<pre>send(Key::<a href="#type-key">key()</a>, Msg::any()) -> Msg</pre>
+<pre>send(Key::[key()](#type-key), Msg::any()) -&gt; Msg</pre>
 <br></br>
 
 
@@ -1176,7 +1176,7 @@ property), Msg will be send to all processes that have such an object.<a name="s
 
 
 
-<pre>set_env(Scope::<a href="#type-scope">scope()</a>, App::atom(), Key::atom(), Value::term(), Strategy) -> Value</pre>
+<pre>set_env(Scope::[scope()](#type-scope), App::atom(), Key::atom(), Value::term(), Strategy) -&gt; Value</pre>
 <ul class="definitions"><li><pre>Strategy = [Alternative]</pre></li><li><pre>Alternative = app_env | os_env | {os_env, VAR} | {mnesia, ActivityType, Oid, Pos}</pre></li></ul>
 
 
@@ -1202,7 +1202,7 @@ to `undefined`.<a name="set_value-2"></a>
 
 
 
-<pre>set_value(Key::<a href="#type-key">key()</a>, Value) -> true</pre>
+<pre>set_value(Key::[key()](#type-key), Value) -&gt; true</pre>
 <br></br>
 
 
@@ -1256,7 +1256,7 @@ Equivalent to [`table({all, all})`](#table-1).<a name="table-1"></a>
 
 
 
-<pre>table(Context::<a href="#type-context">context()</a>) -> any()</pre>
+<pre>table(Context::[context()](#type-context)) -&gt; any()</pre>
 <br></br>
 
 
@@ -1269,7 +1269,7 @@ Equivalent to [`table(Context, [])`](#table-2).<a name="table-2"></a>
 
 
 
-<pre>table(Context::<a href="#type-context">context()</a>, Opts) -> any()</pre>
+<pre>table(Context::[context()](#type-context), Opts) -&gt; any()</pre>
 <br></br>
 
 
@@ -1284,7 +1284,7 @@ See [`http://www.erlang.org/doc/man/qlc.html`](http://www.erlang.org/doc/man/qlc
 
 
 
-<pre>unreg(Key::<a href="#type-key">key()</a>) -> true</pre>
+<pre>unreg(Key::[key()](#type-key)) -&gt; true</pre>
 <br></br>
 
 
@@ -1297,7 +1297,7 @@ Unregister a name or property.<a name="unreg_shared-1"></a>
 
 
 
-<pre>unreg_shared(Key::<a href="#type-key">key()</a>) -> true</pre>
+<pre>unreg_shared(Key::[key()](#type-key)) -&gt; true</pre>
 <br></br>
 
 
@@ -1321,7 +1321,7 @@ Equivalent to `unreg / 1`.<a name="update_counter-2"></a>
 
 
 
-<pre>update_counter(Key::<a href="#type-key">key()</a>, Incr::integer()) -> integer()</pre>
+<pre>update_counter(Key::[key()](#type-key), Incr::integer()) -&gt; integer()</pre>
 <br></br>
 
 
@@ -1349,7 +1349,7 @@ will fail if the type of object referred to by Key is not a counter.<a name="upd
 
 
 
-<pre>where(Key::<a href="#type-key">key()</a>) -> pid()</pre>
+<pre>where(Key::[key()](#type-key)) -&gt; pid()</pre>
 <br></br>
 
 

+ 1 - 1
doc/gproc_dist.md

@@ -10,7 +10,7 @@ Extended process registry.
 
 
 
-__Behaviours:__ [`gen_leader`](/Users/uwiger/FL/git/gproc/deps/gen_leader/doc/gen_leader.md).
+__Behaviours:__ [`gen_leader`](/Users/uwiger/ETC/git/gproc/deps/gen_leader/doc/gen_leader.md).
 
 __Authors:__ Ulf Wiger ([`ulf.wiger@erlang-solutions.com`](mailto:ulf.wiger@erlang-solutions.com)).<a name="description"></a>
 

+ 2 - 2
doc/gproc_lib.md

@@ -82,7 +82,7 @@ For a detailed description, see gproc/doc/erlang07-wiger.pdf.<a name="index"></a
 
 
 
-<pre>insert_many(T::<a href="#type-type">type()</a>, Scope::<a href="#type-scope">scope()</a>, KVL::[{<a href="#type-key">key()</a>, any()}], Pid::pid()) -> {true, list()} | false</pre>
+<pre>insert_many(T::[type()](#type-type), Scope::[scope()](#type-scope), KVL::[{[key()](#type-key), any()}], Pid::pid()) -&gt; {true, list()} | false</pre>
 <br></br>
 
 
@@ -93,7 +93,7 @@ For a detailed description, see gproc/doc/erlang07-wiger.pdf.<a name="index"></a
 
 
 
-<pre>insert_reg(K::<a href="#type-key">key()</a>, Value::any(), Pid::pid() | shared, Scope::<a href="#type-scope">scope()</a>) -> boolean()</pre>
+<pre>insert_reg(K::[key()](#type-key), Value::any(), Pid::pid() | shared, Scope::[scope()](#type-scope)) -&gt; boolean()</pre>
 <br></br>
 
 

+ 2 - 2
doc/gproc_monitor.md

@@ -52,7 +52,7 @@ Starts the server
 
 
 
-<pre>subscribe(Key::<a href="#type-key">key()</a>) -> ok</pre>
+<pre>subscribe(Key::[key()](#type-key)) -&gt; ok</pre>
 <br></br>
 
 
@@ -78,7 +78,7 @@ sent immediately, indicating the current status of the name.<a name="unsubscribe
 
 
 
-<pre>unsubscribe(Key::<a href="#type-key">key()</a>) -> ok</pre>
+<pre>unsubscribe(Key::[key()](#type-key)) -&gt; ok</pre>
 <br></br>
 
 

+ 165 - 100
src/gproc.erl

@@ -138,7 +138,7 @@
 %% this shouldn't be necessary
 -export([audit_process/1]).
 
-
+-include("gproc_int.hrl").
 -include("gproc.hrl").
 -include_lib("eunit/include/eunit.hrl").
 
@@ -149,7 +149,7 @@
 -define(CHK_DIST,
         case whereis(gproc_dist) of
             undefined ->
-                erlang:error(local_only);
+		?THROW(local_only);
             _ ->
                 ok
         end).
@@ -174,7 +174,7 @@ start_link() ->
 %% @doc Registers a local (unique) name. @equiv reg({n,l,Name})
 %% @end
 %%
-add_local_name(Name)  -> reg({n,l,Name}, undefined).
+add_local_name(Name)  -> ?CATCH(reg1({n,l,Name}, undefined), [Name]).
 
 
 %% spec(Name::any()) -> true
@@ -182,7 +182,7 @@ add_local_name(Name)  -> reg({n,l,Name}, undefined).
 %% @doc Registers a global (unique) name. @equiv reg({n,g,Name})
 %% @end
 %%
-add_global_name(Name) -> reg({n,g,Name}, undefined).
+add_global_name(Name) -> ?CATCH(reg1({n,g,Name}, undefined), [Name]).
 
 
 %% spec(Name::any(), Value::any()) -> true
@@ -190,14 +190,14 @@ add_global_name(Name) -> reg({n,g,Name}, undefined).
 %% @doc Registers a local (non-unique) property. @equiv reg({p,l,Name},Value)
 %% @end
 %%
-add_local_property(Name , Value) -> reg({p,l,Name}, Value).
+add_local_property(Name , Value) -> ?CATCH(reg1({p,l,Name}, Value), [Name, Value]).
 
 %% spec(Name::any(), Value::any()) -> true
 %%
 %% @doc Registers a global (non-unique) property. @equiv reg({p,g,Name},Value)
 %% @end
 %%
-add_global_property(Name, Value) -> reg({p,g,Name}, Value).
+add_global_property(Name, Value) -> ?CATCH(reg1({p,g,Name}, Value), [Name, Value]).
 
 %% spec(Name::any(), Initial::integer()) -> true
 %%
@@ -205,7 +205,7 @@ add_global_property(Name, Value) -> reg({p,g,Name}, Value).
 %% @end
 %%
 add_local_counter(Name, Initial) when is_integer(Initial) ->
-    reg({c,l,Name}, Initial).
+    ?CATCH(reg1({c,l,Name}, Initial), [Name, Initial]).
 
 
 %% spec(Name::any(), Initial::integer()) -> true
@@ -224,7 +224,7 @@ add_shared_local_counter(Name, Initial) when is_integer(Initial) ->
 %% @end
 %%
 add_global_counter(Name, Initial) when is_integer(Initial) ->
-    reg({c,g,Name}, Initial).
+    ?CATCH(reg1({c,g,Name}, Initial), [Name, Initial]).
 
 %% spec(Name::any()) -> true
 %%
@@ -232,7 +232,7 @@ add_global_counter(Name, Initial) when is_integer(Initial) ->
 %% @equiv reg({a,l,Name})
 %% @end
 %%
-add_local_aggr_counter(Name)  -> reg({a,l,Name}).
+add_local_aggr_counter(Name)  -> ?CATCH(reg1({a,l,Name}), [Name]).
 
 %% spec(Name::any()) -> true
 %%
@@ -240,7 +240,7 @@ add_local_aggr_counter(Name)  -> reg({a,l,Name}).
 %% @equiv reg({a,g,Name})
 %% @end
 %%
-add_global_aggr_counter(Name) -> reg({a,g,Name}).
+add_global_aggr_counter(Name) -> ?CATCH(reg1({a,g,Name}), [Name]).
 
 
 %% @spec (Name::any()) -> pid()
@@ -513,7 +513,7 @@ lookup_env(Scope, App, Key, P) ->
     end.
 
 cache_env(Scope, App, Key, Value) ->
-    reg({p, Scope, {gproc_env, App, Key}}, Value).
+    ?CATCH(reg1({p, Scope, {gproc_env, App, Key}}, Value), [Scope,App,Key,Value]).
 
 update_cached_env(Scope, App, Key, Value) ->
     case lookup_env(Scope, App, Key, self()) of
@@ -581,7 +581,10 @@ is_string(S) ->
 %% @equiv reg(Key, default(Key))
 %% @end
 reg(Key) ->
-    reg(Key, default(Key)).
+    ?CATCH(reg1(Key), [Key]).
+
+reg1(Key) ->
+    reg1(Key, default(Key)).
 
 default({T,_,_}) when T==c -> 0;
 default(_) -> undefined.
@@ -590,7 +593,7 @@ default(_) -> undefined.
 %% @equiv await(Key,infinity)
 %%
 await(Key) ->
-    await(Key, infinity).
+    ?CATCH(await1(Key, infinity), [Key]).
 
 %% @spec await(Key::key(), Timeout) -> {pid(),Value}
 %%   Timeout = integer() | infinity
@@ -604,10 +607,13 @@ await(Key) ->
 %% registered (the difference: await/2 also returns the value).
 %% @end
 %%
-await({n,g,_} = Key, Timeout) ->
+await(Key, Timeout) ->
+    ?CATCH(await1(Key, Timeout), [Key, Timeout]).
+
+await1({n,g,_} = Key, Timeout) ->
     ?CHK_DIST,
     request_wait(Key, Timeout);
-await({n,l,_} = Key, Timeout) ->
+await1({n,l,_} = Key, Timeout) ->
     case ets:lookup(?TAB, {Key, n}) of
         [{_, Pid, Value}] ->
 	    case is_process_alive(Pid) of
@@ -626,8 +632,8 @@ await({n,l,_} = Key, Timeout) ->
         _ ->
             request_wait(Key, Timeout)
     end;
-await(K, T) ->
-    erlang:error(badarg, [K, T]).
+await1(_, _) ->
+    throw(badarg).
 
 request_wait({n,C,_} = Key, Timeout) when C==l; C==g ->
     TRef = case Timeout of
@@ -635,7 +641,7 @@ request_wait({n,C,_} = Key, Timeout) when C==l; C==g ->
                T when is_integer(T), T > 0 ->
                    erlang:start_timer(T, self(), gproc_timeout);
                _ ->
-                   erlang:error(badarg, [Key, Timeout])
+                   ?THROW(badarg)
            end,
     WRef = case {call({await,Key,self()}, C), C} of
                {{R, {Kg,Pg,Vg}}, g} ->
@@ -653,7 +659,7 @@ request_wait({n,C,_} = Key, Timeout) when C==l; C==g ->
             {Pid, V};
         {timeout, TRef, gproc_timeout} ->
             cancel_wait(Key, WRef),
-            erlang:error(timeout, [Key, Timeout])
+            ?THROW(timeout)
     end.
 
 
@@ -664,13 +670,16 @@ request_wait({n,C,_} = Key, Timeout) when C==l; C==g ->
 %% {gproc, Ref, registered, {Key, Pid, Value}}, once the name is registered.
 %% @end
 %%
-nb_wait({n,g,_} = Key) ->
+nb_wait(Key) ->
+    ?CATCH(nb_wait1(Key), [Key]).
+
+nb_wait1({n,g,_} = Key) ->
     ?CHK_DIST,
     call({await, Key, self()}, g);
-nb_wait({n,l,_} = Key) ->
+nb_wait1({n,l,_} = Key) ->
     call({await, Key, self()}, l);
-nb_wait(Key) ->
-    erlang:error(badarg, [Key]).
+nb_wait1(_) ->
+    ?THROW(badarg).
 
 %% @spec cancel_wait(Key::key(), Ref) -> ok
 %%    Ref = all | reference()
@@ -681,19 +690,25 @@ nb_wait(Key) ->
 %% are canceled.
 %% @end
 %%
-cancel_wait({_,g,_} = Key, Ref) ->
+cancel_wait(Key, Ref) ->
+    ?CATCH(cancel_wait1(Key, Ref), [Key, Ref]).
+
+cancel_wait1({_,g,_} = Key, Ref) ->
     ?CHK_DIST,
     cast({cancel_wait, self(), Key, Ref}, g),
     ok;
-cancel_wait({_,l,_} = Key, Ref) ->
+cancel_wait1({_,l,_} = Key, Ref) ->
     cast({cancel_wait, self(), Key, Ref}, l),
     ok.
 
-cancel_wait_or_monitor({_,g,_} = Key) ->
+cancel_wait_or_monitor(Key) ->
+    ?CATCH(cancel_wait_or_monitor1(Key), [Key]).
+
+cancel_wait_or_monitor1({_,g,_} = Key) ->
     ?CHK_DIST,
     cast({cancel_wait_or_monitor, self(), Key}, g),
     ok;
-cancel_wait_or_monitor({_,l,_} = Key) ->
+cancel_wait_or_monitor1({_,l,_} = Key) ->
     cast({cancel_wait_or_monitor, self(), Key}, l),
     ok.
 
@@ -708,13 +723,16 @@ cancel_wait_or_monitor({_,l,_} = Key) ->
 %%
 %% If the name is not yet registered, the same message is sent immediately.
 %% @end
-monitor({T,g,_} = Key) when T==n; T==a ->
+monitor(Key) ->
+    ?CATCH(monitor1(Key), [Key]).
+
+monitor1({T,g,_} = Key) when T==n; T==a ->
     ?CHK_DIST,
     call({monitor, Key, self()}, g);
-monitor({T,l,_} = Key) when T==n; T==a ->
+monitor1({T,l,_} = Key) when T==n; T==a ->
     call({monitor, Key, self()}, l);
-monitor(Key) ->
-    erlang:error(badarg, [Key]).
+monitor1(_) ->
+    ?THROW(badarg).
 
 %% @spec demonitor(key(), reference()) -> ok
 %%
@@ -722,33 +740,39 @@ monitor(Key) ->
 %% This function is the reverse of monitor/1. It removes a monitor previously
 %% set on a unique name. This function always succeeds given legal input.
 %% @end
-demonitor({T,g,_} = Key, Ref) when T==n; T==a ->
+demonitor(Key, Ref) ->
+    ?CATCH(demonitor1(Key, Ref), [Key, Ref]).
+
+demonitor1({T,g,_} = Key, Ref) when T==n; T==a ->
     ?CHK_DIST,
     call({demonitor, Key, Ref, self()}, g);
-demonitor({T,l,_} = Key, Ref) when T==n; T==a ->
+demonitor1({T,l,_} = Key, Ref) when T==n; T==a ->
     call({demonitor, Key, Ref, self()}, l);
-demonitor(Key, Ref) ->
-    erlang:error(badarg, [Key, Ref]).
+demonitor1(_, _) ->
+    ?THROW(badarg).
 
 %% @spec reg(Key::key(), Value) -> true
 %%
 %% @doc Register a name or property for the current process
 %%
 %%
-reg({_,g,_} = Key, Value) ->
+reg(Key, Value) ->
+    ?CATCH(reg1(Key, Value), [Key, Value]).
+
+reg1({_,g,_} = Key, Value) ->
     %% anything global
     ?CHK_DIST,
     gproc_dist:reg(Key, Value);
-reg({p,l,_} = Key, Value) ->
+reg1({p,l,_} = Key, Value) ->
     local_reg(Key, Value);
-reg({a,l,_} = Key, undefined) ->
+reg1({a,l,_} = Key, undefined) ->
     call({reg, Key, undefined});
-reg({c,l,_} = Key, Value) when is_integer(Value) ->
+reg1({c,l,_} = Key, Value) when is_integer(Value) ->
     call({reg, Key, Value});
-reg({n,l,_} = Key, Value) ->
+reg1({n,l,_} = Key, Value) ->
     call({reg, Key, Value});
-reg(_, _) ->
-    erlang:error(badarg).
+reg1(_, _) ->
+    ?THROW(badarg).
 
 
 %% @spec reg_shared(Key::key()) -> true
@@ -758,9 +782,12 @@ reg(_, _) ->
 %% `reg_shared({c,l,C}) -> reg_shared({c,l,C}, 0).'
 %% `reg_shared({a,l,A}) -> reg_shared({a,l,A}, undefined).'
 %% @end
-reg_shared({c,_,_} = Key) ->
+reg_shared(Key) ->
+    ?CATCH(reg_shared1(Key), [Key]).
+
+reg_shared1({c,_,_} = Key) ->
     reg_shared(Key, 0);
-reg_shared({a,_,_} = Key) ->
+reg_shared1({a,_,_} = Key) ->
     reg_shared(Key, undefined).
 
 
@@ -779,16 +806,19 @@ reg_shared({a,_,_} = Key) ->
 %% an aggregated counter which is owned by a process.
 %% @end
 %%
-reg_shared({_,g,_} = Key, Value) ->
+reg_shared(Key, Value) ->
+    ?CATCH(reg_shared1(Key, Value), [Key, Value]).
+
+reg_shared1({_,g,_} = Key, Value) ->
     %% anything global
     ?CHK_DIST,
     gproc_dist:reg_shared(Key, Value);
-reg_shared({a,l,_} = Key, undefined) ->
+reg_shared1({a,l,_} = Key, undefined) ->
     call({reg_shared, Key, undefined});
-reg_shared({c,l,_} = Key, Value) when is_integer(Value) ->
+reg_shared1({c,l,_} = Key, Value) when is_integer(Value) ->
     call({reg_shared, Key, Value});
-reg_shared(_, _) ->
-    erlang:error(badarg).
+reg_shared1(_, _) ->
+    ?THROW(badarg).
 
 %% @spec mreg(type(), scope(), [{Key::any(), Value::any()}]) -> true
 %%
@@ -798,19 +828,22 @@ reg_shared(_, _) ->
 %% It is also atomic in regard to unique names; either all names are registered
 %% or none are.
 %% @end
-mreg(T, g, KVL) ->
+mreg(T, C, KVL) ->
+    ?CATCH(mreg1(T, C, KVL), [T, C, KVL]).
+
+mreg1(T, g, KVL) ->
     ?CHK_DIST,
     gproc_dist:mreg(T, KVL);
-mreg(T, l, KVL) when T==a; T==n ->
+mreg1(T, l, KVL) when T==a; T==n ->
     if is_list(KVL) ->
             call({mreg, T, l, KVL});
        true ->
             erlang:error(badarg)
     end;
-mreg(p, l, KVL) ->
+mreg1(p, l, KVL) ->
     local_mreg(p, KVL);
-mreg(_, _, _) ->
-    erlang:error(badarg).
+mreg1(_, _, _) ->
+    ?THROW(badarg).
 
 %% @spec munreg(type(), scope(), [Key::any()]) -> true
 %%
@@ -819,19 +852,22 @@ mreg(_, _, _) ->
 %% This function is usually more efficient than calling {@link unreg/1}
 %% repeatedly.
 %% @end
-munreg(T, g, L) ->
+munreg(T, C, L) ->
+    ?CATCH(munreg1(T, C, L), [T, C, L]).
+
+munreg1(T, g, L) ->
     ?CHK_DIST,
     gproc_dist:munreg(T, existing(T,g,L));
-munreg(T, l, L) when T==a; T==n ->
+munreg1(T, l, L) when T==a; T==n ->
     if is_list(L) ->
             call({munreg, T, l, existing(T,l,L)});
        true ->
             erlang:error(badarg)
     end;
-munreg(p, l, L) ->
+munreg1(p, l, L) ->
     local_munreg(p, existing(p,l,L));
-munreg(_, _, _) ->
-    erlang:error(badarg).
+munreg1(_, _, _) ->
+    ?THROW(badarg).
 
 existing(T,Scope,L) ->
     Keys = if T==p; T==c ->
@@ -851,6 +887,9 @@ existing(T,Scope,L) ->
 %% @doc Unregister a name or property.
 %% @end
 unreg(Key) ->
+    ?CATCH(unreg1(Key), [Key]).
+
+unreg1(Key) ->
     case Key of
         {_, g, _} ->
             ?CHK_DIST,
@@ -863,7 +902,7 @@ unreg(Key) ->
                     _ = gproc_lib:remove_reg(Key, self(), unreg),
                     true;
                 false ->
-                    erlang:error(badarg)
+                    ?THROW(badarg)
             end
     end.
 
@@ -872,6 +911,9 @@ unreg(Key) ->
 %% @doc Unregister a shared resource.
 %% @end
 unreg_shared(Key) ->
+    ?CATCH(unreg_shared1(Key), [Key]).
+
+unreg_shared1(Key) ->
     case Key of
         {_, g, _} ->
             ?CHK_DIST,
@@ -879,7 +921,7 @@ unreg_shared(Key) ->
         {T, l, _} when T == c;
                        T == a -> call({unreg_shared, Key});
         _ ->
-	    erlang:error(badarg)
+	    ?THROW(badarg)
     end.
 
 %% @spec (key(), pid()) -> yes | no
@@ -946,7 +988,7 @@ select_count(Pat) ->
 %% but the select patterns are transformed appropriately.
 %% @end
 select_count(Context, Pat) ->
-    ets: select_count(?TAB, pattern(Pat, Context)).
+    ets:select_count(?TAB, pattern(Pat, Context)).
 
 
 %%% Local properties can be registered in the local process, since
@@ -954,14 +996,14 @@ select_count(Context, Pat) ->
 %%%
 local_reg(Key, Value) ->
     case gproc_lib:insert_reg(Key, Value, self(), l) of
-        false -> erlang:error(badarg);
+        false -> ?THROW(badarg);
         true  -> monitor_me()
     end.
 
 local_mreg(_, []) -> true;
 local_mreg(T, [_|_] = KVL) ->
     case gproc_lib:insert_many(T, l, KVL, self()) of
-        false     -> erlang:error(badarg);
+        false     -> ?THROW(badarg);
         {true,_}  -> monitor_me()
     end.
 
@@ -979,16 +1021,19 @@ local_munreg(T, L) when T==p; T==c ->
 %% it must be an integer.
 %% @end
 %%
-set_value({_,g,_} = Key, Value) ->
+set_value(Key, Value) ->
+    ?CATCH(set_value1(Key, Value), [Key, Value]).
+
+set_value1({_,g,_} = Key, Value) ->
     ?CHK_DIST,
     gproc_dist:set_value(Key, Value);
-set_value({a,l,_} = Key, Value) when is_integer(Value) ->
+set_value1({a,l,_} = Key, Value) when is_integer(Value) ->
     call({set, Key, Value});
-set_value({n,l,_} = Key, Value) ->
+set_value1({n,l,_} = Key, Value) ->
     %% we cannot do this locally, since we have to check that the object
     %% exists first - not an atomic update.
     call({set, Key, Value});
-set_value({p,l,_} = Key, Value) ->
+set_value1({p,l,_} = Key, Value) ->
     %% we _can_ to this locally, since there is no race condition - no
     %% other process can update our properties.
     case gproc_lib:do_set_value(Key, Value, self()) of
@@ -996,10 +1041,10 @@ set_value({p,l,_} = Key, Value) ->
         false ->
             erlang:error(badarg)
     end;
-set_value({c,l,_} = Key, Value) when is_integer(Value) ->
+set_value1({c,l,_} = Key, Value) when is_integer(Value) ->
     gproc_lib:do_set_counter_value(Key, Value, self());
-set_value(_, _) ->
-    erlang:error(badarg).
+set_value1(_, _) ->
+    ?THROW(badarg).
 
 %% @spec (Key) -> Value
 %% @doc Reads the value stored with a key registered to the current process.
@@ -1007,7 +1052,7 @@ set_value(_, _) ->
 %% If no such key is registered to the current process, this function exits.
 %% @end
 get_value(Key) ->
-    get_value(Key, self()).
+    ?CATCH(get_value1(Key, self()), [Key]).
 
 %% @spec (Key, Pid) -> Value
 %% @doc Reads the value stored with a key registered to the process Pid.
@@ -1016,26 +1061,29 @@ get_value(Key) ->
 %% will be read.
 %% @end
 %%
-get_value({T,_,_} = Key, Pid) when is_pid(Pid) ->
+get_value(Key, Pid) ->
+    ?CATCH(get_value1(Key, Pid), [Key, Pid]).
+
+get_value1({T,_,_} = Key, Pid) when is_pid(Pid) ->
     if T==n orelse T==a ->
             case ets:lookup(?TAB, {Key, T}) of
                 [{_, P, Value}] when P == Pid -> Value;
-                _ -> erlang:error(badarg)
+                _ -> ?THROW(badarg)
             end;
        true ->
             ets:lookup_element(?TAB, {Key, Pid}, 3)
     end;
-get_value({T,_,_} = K, shared) when T==c; T==a ->
+get_value1({T,_,_} = K, shared) when T==c; T==a ->
     Key = case T of
 	      c -> {K, shared};
 	      a -> {K, a}
 	  end,
     case ets:lookup(?TAB, Key) of
 	[{_, shared, Value}] -> Value;
-	_ -> erlang:error(badarg)
+	_ -> ?THROW(badarg)
     end;
-get_value(_, _) ->
-    erlang:error(badarg).
+get_value1(_, _) ->
+    ?THROW(badarg).
 
 
 %% @spec (Key) -> Pid
@@ -1066,7 +1114,10 @@ lookup_value({T,_,_} = Key) ->
 %% cases.
 %% @end
 %%
-where({T,_,_}=Key) ->
+where(Key) ->
+    ?CATCH(where1(Key), [Key]).
+
+where1({T,_,_}=Key) ->
     if T==n orelse T==a ->
             case ets:lookup(?TAB, {Key,T}) of
                 [{_, P, _Value}] ->
@@ -1079,12 +1130,12 @@ where({T,_,_}=Key) ->
                     undefined
             end;
        true ->
-            erlang:error(badarg)
+            ?THROW(badarg)
     end.
 
 %% @equiv where/1
 whereis_name(Key) ->
-    where(Key).
+    ?CATCH(where1(Key), [Key]).
 
 %% @spec (Key::key()) -> [pid()]
 %%
@@ -1138,13 +1189,16 @@ lookup_values({T,_,_} = Key) ->
 %% will fail if the type of object referred to by Key is not a counter.
 %% @end
 %%
-update_counter({c,l,_} = Key, Incr) when is_integer(Incr) ->
+update_counter(Key, Incr) ->
+    ?CATCH(update_counter1(Key, Incr), [Key, Incr]).
+
+update_counter1({c,l,_} = Key, Incr) when is_integer(Incr) ->
     gproc_lib:update_counter(Key, Incr, self());
-update_counter({c,g,_} = Key, Incr) when is_integer(Incr) ->
+update_counter1({c,g,_} = Key, Incr) when is_integer(Incr) ->
     ?CHK_DIST,
     gproc_dist:update_counter(Key, Incr);
-update_counter(_, _) ->
-    erlang:error(badarg).
+update_counter1(_, _) ->
+    ?THROW(badarg).
 
 
 %% @spec (Key) -> {ValueBefore, ValueAfter}
@@ -1161,10 +1215,13 @@ update_counter(_, _) ->
 %% updates. Aggregated counters are updated accordingly.
 %% @end
 %%
-reset_counter({c,g,_} = Key) ->
+reset_counter(Key) ->
+    ?CATCH(reset_counter1(Key), [Key]).
+
+reset_counter1({c,g,_} = Key) ->
     ?CHK_DIST,
     gproc_dist:reset_counter(Key);
-reset_counter({c,l,_} = Key) ->
+reset_counter1({c,l,_} = Key) ->
     Current = ets:lookup_element(?TAB, {Key, self()}, 3),
     Initial = case ets:lookup(?TAB, {self(), Key}) of
 		  [{_, r}] -> 0;
@@ -1173,11 +1230,13 @@ reset_counter({c,l,_} = Key) ->
 	      end,
     {Current, update_counter(Key, Initial - Current)}.
 
+update_shared_counter(Key, Incr) ->
+    ?CATCH(update_shared_counter1(Key, Incr), [Key, Incr]).
 
-update_shared_counter({c,g,_} = Key, Incr) ->
+update_shared_counter1({c,g,_} = Key, Incr) ->
     ?CHK_DIST,
     gproc_dist:update_shared_counter(Key, Incr);
-update_shared_counter({c,l,_} = Key, Incr) ->
+update_shared_counter1({c,l,_} = Key, Incr) ->
     gproc_lib:update_counter(Key, Incr, shared).
 
 %% @spec (From::key(), To::pid() | key()) -> undefined | pid()
@@ -1198,11 +1257,14 @@ update_shared_counter({c,l,_} = Key, Incr) ->
 %% Fails with `badarg' if the calling process does not have a `From' key
 %% registered.
 %% @end
-give_away({_,l,_} = Key, ToPid) when is_pid(ToPid), node(ToPid) == node() ->
+give_away(Key, ToPid) ->
+    ?CATCH(give_away1(Key, ToPid), [Key, ToPid]).
+
+give_away1({_,l,_} = Key, ToPid) when is_pid(ToPid), node(ToPid) == node() ->
     call({give_away, Key, ToPid});
-give_away({_,l,_} = Key, {n,l,_} = ToKey) ->
+give_away1({_,l,_} = Key, {n,l,_} = ToKey) ->
     call({give_away, Key, ToKey});
-give_away({_,g,_} = Key, To) ->
+give_away1({_,g,_} = Key, To) ->
     ?CHK_DIST,
     gproc_dist:give_away(Key, To).
 
@@ -1227,13 +1289,16 @@ goodbye() ->
 %% property), Msg will be send to all processes that have such an object.
 %% @end
 %%
-send({T,C,_} = Key, Msg) when C==l; C==g ->
+send(Key, Msg) ->
+    ?CATCH(send1(Key, Msg), [Key, Msg]).
+
+send1({T,C,_} = Key, Msg) when C==l; C==g ->
     if T == n orelse T == a ->
             case ets:lookup(?TAB, {Key, T}) of
                 [{_, Pid, _}] ->
                     Pid ! Msg;
                 _ ->
-                    erlang:error(badarg)
+                    ?THROW(badarg)
             end;
        T==p orelse T==c ->
             %% BUG - if the key part contains select wildcards, we may end up
@@ -1245,8 +1310,8 @@ send({T,C,_} = Key, Msg) when C==l; C==g ->
        true ->
             erlang:error(badarg)
     end;
-send(_, _) ->
-    erlang:error(badarg).
+send1(_, _) ->
+    ?THROW(badarg).
 
 
 %% @spec (Context :: context()) -> key() | '$end_of_table'
@@ -1583,13 +1648,13 @@ call(Req) ->
     call(Req, l).
 
 call(Req, l) ->
-    chk_reply(gen_server:call(?MODULE, Req), Req);
+    chk_reply(gen_server:call(?MODULE, Req));
 call(Req, g) ->
-    chk_reply(gproc_dist:leader_call(Req), Req).
+    chk_reply(gproc_dist:leader_call(Req)).
 
-chk_reply(Reply, Req) ->
+chk_reply(Reply) ->
     case Reply of
-        badarg -> erlang:error(badarg, Req);
+        badarg -> ?THROW(badarg);
         _  -> Reply
     end.
 

+ 27 - 0
src/gproc_int.hrl

@@ -0,0 +1,27 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved via the world wide web at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
+%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
+%% AB. All Rights Reserved.''
+%%
+%% @author Ulf Wiger <ulf.wiger@feuerlabs.com
+%%
+%% gproc_int.hrl: Shared internal definitions
+
+-define(CATCH(Expr, Args),
+	try Expr
+	catch
+	    throw:{gproc_error, GprocError} ->
+		erlang:error(GprocError, Args)
+	end).
+
+-define(THROW(E), throw({gproc_error, E})).