Browse Source

Add gen_server via registration interface.

Roberto Ostinelli 5 years ago
parent
commit
61d60f2b57
3 changed files with 137 additions and 12 deletions
  1. 41 9
      src/syn.erl
  2. 30 3
      test/syn_registry_SUITE.erl
  3. 66 0
      test/syn_test_gen_server.erl

+ 41 - 9
src/syn.erl

@@ -27,11 +27,14 @@
 
 %% API
 -export([start/0, stop/0]).
--export([whereis/1, whereis/2]).
 -export([register/2, register/3]).
 -export([unregister/1]).
+-export([whereis/1, whereis/2]).
 -export([registry_count/0, registry_count/1]).
 
+%% gen_server via interface
+-export([register_name/2, unregister_name/1, whereis_name/1, send/2]).
+
 %% ===================================================================
 %% API
 %% ===================================================================
@@ -44,14 +47,6 @@ start() ->
 stop() ->
     ok = application:stop(syn).
 
--spec whereis(Name :: term()) -> pid() | undefined.
-whereis(Name) ->
-    syn_registry:whereis(Name).
-
--spec whereis(Name :: term(), with_meta) -> {pid(), Meta :: term()} | undefined.
-whereis(Name, with_meta) ->
-    syn_registry:whereis(Name, with_meta).
-
 -spec register(Name :: term(), Pid :: pid()) -> ok | {error, Reason :: term()}.
 register(Name, Pid) ->
     syn_registry:register(Name, Pid).
@@ -64,6 +59,14 @@ register(Name, Pid, Meta) ->
 unregister(Name) ->
     syn_registry:unregister(Name).
 
+-spec whereis(Name :: term()) -> pid() | undefined.
+whereis(Name) ->
+    syn_registry:whereis(Name).
+
+-spec whereis(Name :: term(), with_meta) -> {pid(), Meta :: term()} | undefined.
+whereis(Name, with_meta) ->
+    syn_registry:whereis(Name, with_meta).
+
 -spec registry_count() -> non_neg_integer().
 registry_count() ->
     syn_registry:count().
@@ -71,3 +74,32 @@ registry_count() ->
 -spec registry_count(Node :: atom()) -> non_neg_integer().
 registry_count(Node) ->
     syn_registry:count(Node).
+
+%% gen_server via interface
+-spec register_name(Name :: term(), Pid :: pid()) -> yes | no.
+register_name(Name, Pid) ->
+    case syn_registry:register(Name, Pid) of
+        ok -> yes;
+        _ -> no
+    end.
+
+-spec unregister_name(Name :: term()) -> term().
+unregister_name(Name) ->
+    case syn_registry:unregister(Name) of
+        ok -> Name;
+        _ -> nil
+    end.
+
+-spec whereis_name(Name :: term()) -> pid() | undefined.
+whereis_name(Name) ->
+    syn_registry:whereis(Name).
+
+-spec send(Name :: term(), Message :: term()) -> pid().
+send(Name, Message) ->
+    case whereis_name(Name) of
+        undefined ->
+            {badarg, {Name, Message}};
+        Pid ->
+            Pid ! Message,
+            Pid
+    end.

+ 30 - 3
test/syn_registry_SUITE.erl

@@ -36,7 +36,8 @@
     single_node_register_and_monitor/1,
     single_node_register_and_unregister/1,
     single_node_registration_errors/1,
-    single_node_registry_count/1
+    single_node_registry_count/1,
+    single_node_register_gen_server/1
 ]).
 -export([
     two_nodes_register_monitor_and_unregister/1,
@@ -93,7 +94,8 @@ groups() ->
             single_node_register_and_monitor,
             single_node_register_and_unregister,
             single_node_registration_errors,
-            single_node_registry_count
+            single_node_registry_count,
+            single_node_register_gen_server
         ]},
         {two_nodes_process_registration, [shuffle], [
             two_nodes_register_monitor_and_unregister,
@@ -281,6 +283,30 @@ single_node_registry_count(_Config) ->
     0 = syn:registry_count(),
     0 = syn:registry_count(node()).
 
+single_node_register_gen_server(_Config) ->
+    %% start
+    ok = syn:start(),
+    %% start gen server via syn
+    {ok, Pid} = syn_test_gen_server:start_link(),
+    %% retrieve
+    Pid = syn:whereis(syn_test_gen_server),
+    %% call
+    pong = syn_test_gen_server:ping(),
+    %% send via syn
+    syn:send(syn_test_gen_server, {self(), send_ping}),
+    receive
+        send_pong -> ok
+    after 1000 ->
+        ok = did_not_receive_gen_server_pong
+    end,
+    %% stop server
+    syn_test_gen_server:stop(),
+    timer:sleep(200),
+    %% retrieve
+    undefined = syn:whereis(syn_test_gen_server),
+    %% send via syn
+    {badarg, {syn_test_gen_server, anything}} = (catch syn:send(syn_test_gen_server, anything)).
+
 two_nodes_register_monitor_and_unregister(Config) ->
     %% get slave
     SlaveNode = proplists:get_value(slave_node, Config),
@@ -357,7 +383,8 @@ two_nodes_registry_count(Config) ->
     0 = syn:registry_count(node()),
     0 = syn:registry_count(SlaveNode),
     %% kill proc
-    syn_test_suite_helper:kill_process(RemotePid).
+    syn_test_suite_helper:kill_process(RemotePid),
+    syn_test_suite_helper:kill_process(PidUnregistered).
 
 three_nodes_partial_netsplit_consistency(Config) ->
     %% get slaves

+ 66 - 0
test/syn_test_gen_server.erl

@@ -0,0 +1,66 @@
+%% ==========================================================================================================
+%% Syn - A global Process Registry and Process Group manager.
+%%
+%% The MIT License (MIT)
+%%
+%% Copyright (c) 2015-2019 Roberto Ostinelli <roberto@ostinelli.net> and Neato Robotics, Inc.
+%%
+%% Permission is hereby granted, free of charge, to any person obtaining a copy
+%% of this software and associated documentation files (the "Software"), to deal
+%% in the Software without restriction, including without limitation the rights
+%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+%% copies of the Software, and to permit persons to whom the Software is
+%% furnished to do so, subject to the following conditions:
+%%
+%% The above copyright notice and this permission notice shall be included in
+%% all copies or substantial portions of the Software.
+%%
+%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+%% THE SOFTWARE.
+%% ==========================================================================================================
+-module(syn_test_gen_server).
+-behaviour(gen_server).
+
+%% API
+-export([start_link/0]).
+-export([ping/0]).
+-export([stop/0]).
+
+%% gen_server callbacks
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
+
+start_link() ->
+    gen_server:start_link({via, syn, ?MODULE}, ?MODULE, [], []).
+
+ping() ->
+    gen_server:call({via, syn, ?MODULE}, ping).
+
+stop() ->
+    gen_server:cast({via, syn, ?MODULE}, stop).
+
+init(State) ->
+    {ok, State}.
+
+handle_call(ping, _From, State) ->
+    {reply, pong, State}.
+
+handle_cast(stop, State) ->
+    {stop, normal, State};
+
+handle_cast(_Msg, State) ->
+    {noreply, State}.
+
+handle_info({SenderPid, send_ping}, State) ->
+    SenderPid ! send_pong,
+    {noreply, State}.
+
+terminate(_Reason, _State) ->
+    ok.
+
+code_change(_OldVsn, State, _Extra) ->
+    {ok, State}.