﻿--- lib/stdlib/src/gen.erl.orig	Tue Jun 10 19:16:04 2008 UTC
+++ lib/stdlib/src/gen.erl	Thu Aug 28 11:42:18 2008 UTC
@@ -36,12 +36,14 @@
 %% start(GenMod, LinkP, Name, Mod, Args, Options)
 %% start_link(Mod, Args, Options)
 %% start_link(Name, Mod, Args, Options) where:
-%%    Name = {local, atom()} | {global, atom()}
+%%    Name = {local, atom()} | {global, atom()} |
+%%           {global_group, atom()} | {global_group, Where, atom()}
 %%    Mod  = atom(), callback module implementing the 'real' fsm
 %%    Args = term(), init arguments (to Mod:init/1)
 %%    Options = [{debug, [Flag]}]
 %%      Flag = trace | log | {logfile, File} | statistics | debug
 %%          (debug == log && statistics)
+%%    Where = {node, node()} | {group, atom()}
 %% Returns: {ok, Pid} |
 %%          {error, {already_started, Pid}} |
 %%          {error, Reason}
@@ -140,19 +142,21 @@
 call({global, _Name}=Process, Label, Request, Timeout)
   when Timeout =:= infinity;
        is_integer(Timeout), Timeout >= 0 ->
-    case where(Process) of
-	Pid when is_pid(Pid) ->
-	    Node = node(Pid),
- 	    try do_call(Pid, Label, Request, Timeout)
- 	    catch
- 		exit:{nodedown, Node} ->
- 		    %% A nodedown not yet detected by global,
- 		    %% pretend that it was.
- 		    exit(noproc)
-	    end;
-	undefined ->
-	    exit(noproc)
-    end;
+    do_global_call(Process, Label, Request, Timeout);
+
+%% Global group by name
+call({global_group, _Name}=Process, Label, Request, Timeout)
+  when Timeout =:= infinity;
+       is_integer(Timeout), Timeout >= 0 ->
+    do_global_call(Process, Label, Request, Timeout);
+
+%% Call by name registered on the specified node or in the
+%% specified global group
+call({global_group, _Where, _Name}=Process, Label, Request, Timeout)
+  when Timeout =:= infinity;
+       is_integer(Timeout), Timeout >= 0 ->
+    do_global_call(Process, Label, Request, Timeout);
+
 %% Local by name in disguise
 call({Name, Node}, Label, Request, Timeout)
   when Node =:= node(), Timeout =:= infinity;
@@ -169,6 +173,21 @@
  	    do_call(Process, Label, Request, Timeout)
     end.

+do_global_call(Process, Label, Request, Timeout) ->
+    case where(Process) of
+	Pid when is_pid(Pid) ->
+	    Node = node(Pid),
+ 	    try do_call(Pid, Label, Request, Timeout)
+ 	    catch
+ 		exit:{nodedown, Node} ->
+ 		    %% A nodedown not yet detected by global,
+ 		    %% pretend that it was.
+ 		    exit(noproc)
+	    end;
+	undefined ->
+	    exit(noproc)
+    end.
+
 do_call(Process, Label, Request, Timeout) ->
     %% We trust the arguments to be correct, i.e
     %% Process is either a local or remote pid,
@@ -257,11 +276,15 @@
 %%%-----------------------------------------------------------------
 %%%  Misc. functions.
 %%%-----------------------------------------------------------------
+where({local, Name})               -> whereis(Name);
 where({global, Name})    -> global:safe_whereis_name(Name);
-where({local, Name})  -> whereis(Name).
+where({global_group, Name})        -> global_group:whereis_name(Name);
+where({global_group, Where, Name}) -> global_group:whereis_name(Where, Name).

+name({local,  Name})               -> Name;
 name({global, Name})    -> Name;
-name({local, Name})     -> Name.
+name({global_group, Name})         -> Name;
+name({global_group, _Where, Name}) -> Name.

 name_register({local, Name} = LN) ->
     try register(Name, self()) of
@@ -271,6 +294,13 @@
 	    {false, where(LN)}
     end;
 name_register({global, Name} = GN) ->
+    name_register_global(GN, Name);
+name_register({global_group, Name} = GN) ->
+    name_register_global(GN, Name);
+name_register({global_group, _Where, Name} = GN) ->
+    name_register_global(GN, Name).
+
+name_register_global(GN, Name) ->
     case global:register_name(Name, self()) of
 	yes -> true;
 	no -> {false, where(GN)}
