Ulf Wiger 13 лет назад
Родитель
Сommit
b374ea6f0e
6 измененных файлов с 67 добавлено и 5 удалено
  1. 1 0
      README.md
  2. 1 0
      doc/README.md
  3. 2 2
      doc/edoc-info
  4. 30 2
      doc/gproc.md
  5. 30 0
      src/gproc.erl
  6. 3 1
      src/gproc_sup.erl

+ 1 - 0
README.md

@@ -91,6 +91,7 @@ Freiburg 2007 ([Paper available here](http://github.com/esl/gproc/blob/master/do
 <table width="100%" border="0" summary="list of modules">
 <tr><td><a href="http://github.com/esl/gproc/blob/master/doc/gproc.md" class="module">gproc</a></td></tr>
 <tr><td><a href="http://github.com/esl/gproc/blob/master/doc/gproc_app.md" class="module">gproc_app</a></td></tr>
+<tr><td><a href="http://github.com/esl/gproc/blob/master/doc/gproc_bcast.md" class="module">gproc_bcast</a></td></tr>
 <tr><td><a href="http://github.com/esl/gproc/blob/master/doc/gproc_dist.md" class="module">gproc_dist</a></td></tr>
 <tr><td><a href="http://github.com/esl/gproc/blob/master/doc/gproc_info.md" class="module">gproc_info</a></td></tr>
 <tr><td><a href="http://github.com/esl/gproc/blob/master/doc/gproc_init.md" class="module">gproc_init</a></td></tr>

+ 1 - 0
doc/README.md

@@ -91,6 +91,7 @@ Freiburg 2007 ([Paper available here](erlang07-wiger.pdf)).
 <table width="100%" border="0" summary="list of modules">
 <tr><td><a href="gproc.md" class="module">gproc</a></td></tr>
 <tr><td><a href="gproc_app.md" class="module">gproc_app</a></td></tr>
+<tr><td><a href="gproc_bcast.md" class="module">gproc_bcast</a></td></tr>
 <tr><td><a href="gproc_dist.md" class="module">gproc_dist</a></td></tr>
 <tr><td><a href="gproc_info.md" class="module">gproc_info</a></td></tr>
 <tr><td><a href="gproc_init.md" class="module">gproc_init</a></td></tr>

+ 2 - 2
doc/edoc-info

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

+ 30 - 2
doc/gproc.md

@@ -207,7 +207,7 @@ a = aggregate_counter
 ##Function Index##
 
 
-<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#add_global_aggr_counter-1">add_global_aggr_counter/1</a></td><td>Registers a global (unique) aggregated counter.</td></tr><tr><td valign="top"><a href="#add_global_counter-2">add_global_counter/2</a></td><td>Registers a global (non-unique) counter.</td></tr><tr><td valign="top"><a href="#add_global_name-1">add_global_name/1</a></td><td>Registers a global (unique) name.</td></tr><tr><td valign="top"><a href="#add_global_property-2">add_global_property/2</a></td><td>Registers a global (non-unique) property.</td></tr><tr><td valign="top"><a href="#add_local_aggr_counter-1">add_local_aggr_counter/1</a></td><td>Registers a local (unique) aggregated counter.</td></tr><tr><td valign="top"><a href="#add_local_counter-2">add_local_counter/2</a></td><td>Registers a local (non-unique) counter.</td></tr><tr><td valign="top"><a href="#add_local_name-1">add_local_name/1</a></td><td>Registers a local (unique) name.</td></tr><tr><td valign="top"><a href="#add_local_property-2">add_local_property/2</a></td><td>Registers a local (non-unique) property.</td></tr><tr><td valign="top"><a href="#add_shared_local_counter-2">add_shared_local_counter/2</a></td><td>Registers a local shared (unique) counter.</td></tr><tr><td valign="top"><a href="#audit_process-1">audit_process/1</a></td><td></td></tr><tr><td valign="top"><a href="#await-1">await/1</a></td><td>Equivalent to <a href="#await-2"><tt>await(Key, infinity)</tt></a>.</td></tr><tr><td valign="top"><a href="#await-2">await/2</a></td><td>Wait for a local name to be registered.</td></tr><tr><td valign="top"><a href="#cancel_wait-2">cancel_wait/2</a></td><td>Cancels a previous call to nb_wait/1.</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
+<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="#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_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
 This function is the reverse of monitor/1.</td></tr><tr><td valign="top"><a href="#first-1">first/1</a></td><td>Behaves as ets:first(Tab) for a given type of registration object.</td></tr><tr><td valign="top"><a href="#get_env-3">get_env/3</a></td><td>Equivalent to <a href="#get_env-4"><tt>get_env(Scope, App, Key, [app_env])</tt></a>.</td></tr><tr><td valign="top"><a href="#get_env-4">get_env/4</a></td><td>Read an environment value, potentially cached as a <code>gproc_env</code> property.</td></tr><tr><td valign="top"><a href="#get_set_env-3">get_set_env/3</a></td><td>Equivalent to <a href="#get_set_env-4"><tt>get_set_env(Scope, App, Key, [app_env])</tt></a>.</td></tr><tr><td valign="top"><a href="#get_set_env-4">get_set_env/4</a></td><td>Fetch and cache an environment value, if not already cached.</td></tr><tr><td valign="top"><a href="#get_value-1">get_value/1</a></td><td>Reads the value stored with a key registered to the current process.</td></tr><tr><td valign="top"><a href="#get_value-2">get_value/2</a></td><td>Reads the value stored with a key registered to the process Pid.</td></tr><tr><td valign="top"><a href="#give_away-2">give_away/2</a></td><td>Atomically transfers the key <code>From</code> to the process identified by <code>To</code>.</td></tr><tr><td valign="top"><a href="#goodbye-0">goodbye/0</a></td><td>Unregister all items of the calling process and inform gproc
 to forget about the calling process.</td></tr><tr><td valign="top"><a href="#i-0">i/0</a></td><td>Similar to the built-in shell command <code>i()</code> but inserts information
 about names and properties registered in Gproc, where applicable.</td></tr><tr><td valign="top"><a href="#info-1">info/1</a></td><td>Similar to <code>process_info(Pid)</code> but with additional gproc info.</td></tr><tr><td valign="top"><a href="#info-2">info/2</a></td><td>Similar to process_info(Pid, Item), but with additional gproc info.</td></tr><tr><td valign="top"><a href="#last-1">last/1</a></td><td>Behaves as ets:last(Tab) for a given type of registration object.</td></tr><tr><td valign="top"><a href="#lookup_global_aggr_counter-1">lookup_global_aggr_counter/1</a></td><td>Lookup a global (unique) aggregated counter and returns its value.</td></tr><tr><td valign="top"><a href="#lookup_global_counters-1">lookup_global_counters/1</a></td><td>Look up all global (non-unique) instances of a given Counter.</td></tr><tr><td valign="top"><a href="#lookup_global_name-1">lookup_global_name/1</a></td><td>Lookup a global unique name.</td></tr><tr><td valign="top"><a href="#lookup_global_properties-1">lookup_global_properties/1</a></td><td>Look up all global (non-unique) instances of a given Property.</td></tr><tr><td valign="top"><a href="#lookup_local_aggr_counter-1">lookup_local_aggr_counter/1</a></td><td>Lookup a local (unique) aggregated counter and returns its value.</td></tr><tr><td valign="top"><a href="#lookup_local_counters-1">lookup_local_counters/1</a></td><td>Look up all local (non-unique) instances of a given Counter.</td></tr><tr><td valign="top"><a href="#lookup_local_name-1">lookup_local_name/1</a></td><td>Lookup a local unique name.</td></tr><tr><td valign="top"><a href="#lookup_local_properties-1">lookup_local_properties/1</a></td><td>Look up all local (non-unique) instances of a given Property.</td></tr><tr><td valign="top"><a href="#lookup_pid-1">lookup_pid/1</a></td><td>Lookup the Pid stored with a key.</td></tr><tr><td valign="top"><a href="#lookup_pids-1">lookup_pids/1</a></td><td>Returns a list of pids with the published key Key.</td></tr><tr><td valign="top"><a href="#lookup_value-1">lookup_value/1</a></td><td>Lookup the value stored with a key.</td></tr><tr><td valign="top"><a href="#lookup_values-1">lookup_values/1</a></td><td>Retrieve the <code>{Pid,Value}</code> pairs corresponding to Key.</td></tr><tr><td valign="top"><a href="#monitor-1">monitor/1</a></td><td>monitor a registered name
@@ -320,7 +320,35 @@ 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="cancel_wait-2"></a>
+registered (the difference: await/2 also returns the value).<a name="bcast-2"></a>
+
+###bcast/2##
+
+
+<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>
+
+###bcast/3##
+
+
+<pre>bcast(Nodes::[atom()], Key::<a href="#type-key">key()</a>, Msg::any()) -> Msg</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>
 
 ###cancel_wait/2##
 

+ 30 - 0
src/gproc.erl

@@ -95,6 +95,7 @@
          give_away/2,
          goodbye/0,
          send/2,
+	 bcast/2, bcast/3,
          info/1, info/2,
 	 i/0,
          select/1, select/2, select/3,
@@ -1401,6 +1402,34 @@ send1({T,C,_} = Key, Msg) when C==l; C==g ->
 send1(_, _) ->
     ?THROW_GPROC_ERROR(badarg).
 
+%% @spec (Key::key(), Msg::any()) -> Msg
+%%
+%% @equiv bcast(nodes(), Key, Msg)
+%% @end
+%%
+bcast(Key, Msg) ->
+    bcast(nodes(), Key, Msg).
+
+%% @spec (Nodes::[atom()], Key::key(), Msg::any()) -> Msg
+%%
+%% @doc 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 send/2
+%% @end
+%%
+bcast(Ns, Key, Msg) ->
+    ?CATCH_GPROC_ERROR(bcast1(Ns, Key, Msg), [Key, Msg]).
+
+bcast1(Ns, {T,l,_} = Key, Msg) when T==p; T==a; T==c; T==n; T==p ->
+    send1(Key, Msg),
+    gen_server:abcast(Ns -- [node()], gproc_bcast, {send, Key, Msg}),
+    Msg.
+
 
 %% @spec (Context :: context()) -> key() | '$end_of_table'
 %%
@@ -1727,6 +1756,7 @@ code_change(_FromVsn, S, _Extra) ->
         end,
     {ok, S}.
 
+
 %% @hidden
 terminate(_Reason, _S) ->
     ok.

+ 3 - 1
src/gproc_sup.erl

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