Browse Source

optimized await + minor bug fixes

Ulf Wiger 15 years ago
parent
commit
c89642575e
2 changed files with 27 additions and 9 deletions
  1. 4 2
      src/Unit-Quick-Files/gproc_eqc.erl
  2. 23 7
      src/gproc.erl

+ 4 - 2
src/Unit-Quick-Files/gproc_eqc.erl

@@ -109,13 +109,15 @@ name() -> elements([x,y,z,w]).
 %% generator key
 key() -> #key{class=class(), scope=scope(), name=name()}.
 
+
 %% generator value
 value() -> frequency([{8, int()}, {1, undefined}, {1, make_ref()}]).
 
 
 %% helpers
-is_register_ok(_S,_Pid,#key{class=Class},Value)
-  when Class == c, not is_integer(Value) ->
+is_register_ok(_S,_Pid,#key{class=c},Value) when not is_integer(Value) ->
+    false;
+is_register_ok(_S,_Pid,#key{class=a},Value) when not is_integer(Value) ->
     false;
 is_register_ok(S,Pid,Key,_Value) ->
     [] == [ Pid1 || #reg{pid=Pid1,key=Key1}

+ 23 - 7
src/gproc.erl

@@ -272,9 +272,23 @@ default(_) -> undefined.
 %% @doc Wait for a local name to be registered.
 %% The function raises an exception if the timeout expires. Timeout must be 
 %% 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).
 %% @end
 %%
 await({n,l,_} = Key, Timeout) ->
+    case ets:lookup(?TAB, {Key, n}) of
+        [{_, Pid, Value}] ->
+            {Pid, Value};
+        _ ->
+            request_wait(Key, Timeout)
+    end;
+await(K, T) ->
+    erlang:error(badarg, [K, T]).
+
+request_wait({n,l,_} = Key, Timeout) ->
     TRef = case Timeout of
                infinity -> no_timer;
                T when is_integer(T), T > 0 ->
@@ -289,9 +303,8 @@ await({n,l,_} = Key, Timeout) ->
         {timeout, TRef, timeout} ->
             cancel_wait(Key, WRef),
             erlang:error(timeout, [Key, Timeout])
-    end;
-await(K, T) ->
-    erlang:error(badarg, [K, T]).
+    end.
+
 
 %% @spec nb_wait(Key::key()) -> Ref
 %%
@@ -502,10 +515,10 @@ lookup_value({T,_,_} = Key) ->
 where({T,_,_}=Key) ->
     if T==n orelse T==a ->
             case ets:lookup(?TAB, {Key,T}) of
-                [] ->
-                    undefined;
                 [{_, P, _Value}] ->
-                    P
+                    P;
+                _ ->  % may be [] or [{Key,Waiters}]
+                    undefined
             end;
        true ->
             erlang:error(badarg)
@@ -580,7 +593,7 @@ send({T,C,_} = Key, Msg) when C==l; C==g ->
             case ets:lookup(?TAB, {Key, T}) of
                 [{_, Pid, _}] ->
                     Pid ! Msg;
-                [] ->
+                _ ->
                     erlang:error(badarg)
             end;
        T==p orelse T==c ->
@@ -826,6 +839,9 @@ try_insert_reg({T,l,_} = Key, Val, Pid) ->
     case gproc_lib:insert_reg(Key, Val, Pid, l) of
         false ->
             case ets:lookup(?TAB, {Key,T}) of
+                %% In this particular case, the lookup cannot result in
+                %% [{_, Waiters}], since the insert_reg/4 function would
+                %% have succeeded then.
                 [{_, OtherPid, _}] ->
                     case is_process_alive(OtherPid) of
                         true ->