Skip to content

Instantly share code, notes, and snippets.

@seancribbs
Created January 9, 2009 01:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save seancribbs/44974 to your computer and use it in GitHub Desktop.
Save seancribbs/44974 to your computer and use it in GitHub Desktop.
%%%-------------------------------------------------------------------
%%% File: gen_phone.erl
%%% @author Sean Cribbs <> []
%%% @copyright 2009 Sean Cribbs
%%% @doc
%%%
%%% @end
%%%
%%% @since 2009-01-08 by Sean Cribbs
%%%-------------------------------------------------------------------
-module(gen_phone).
-author('').
-behaviour(gen_server).
%% API
-export([start_link/2, send_message/2, stop/1]).
%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).
-record(state, {me, neighbor}).
%%====================================================================
%% API
%%====================================================================
%%--------------------------------------------------------------------
%% @spec start_link() -> {ok,Pid} | ignore | {error,Error}
%% @doc Starts the server
%% @end
%%--------------------------------------------------------------------
start_link(Me, Neighbor) ->
gen_server:start_link({global, Me}, ?MODULE, [Me, Neighbor], []).
send_message(Message, Who) ->
gen_server:call({global, Who}, {send_message, Message}).
stop(Who) ->
gen_server:call({global, Who}, stop).
%%====================================================================
%% gen_server callbacks
%%====================================================================
%%--------------------------------------------------------------------
%% @spec init(Args) -> {ok, State} |
%% {ok, State, Timeout} |
%% ignore |
%% {stop, Reason}
%% @doc Initiates the server
%% @end
%%--------------------------------------------------------------------
init([Me, Neighbor]) ->
{ok, #state{me=Me, neighbor=Neighbor}}.
%%--------------------------------------------------------------------
%% @spec
%% handle_call(Request, From, State) -> {reply, Reply, State} |
%% {reply, Reply, State, Timeout} |
%% {noreply, State} |
%% {noreply, State, Timeout} |
%% {stop, Reason, Reply, State} |
%% {stop, Reason, State}
%% @doc Handling call messages
%% @end
%%--------------------------------------------------------------------
handle_call({send_message, Message}, _From, State) ->
global:send(State#state.neighbor, {State#state.me, Message}),
{reply, ok, State};
handle_call(stop, _From, _State) ->
{stop, normal};
handle_call(_Request, _From, State) ->
Reply = ok,
{reply, Reply, State}.
%%--------------------------------------------------------------------
%% @spec handle_cast(Msg, State) -> {noreply, State} |
%% {noreply, State, Timeout} |
%% {stop, Reason, State}
%% @doc Handling cast messages
%% @end
%%--------------------------------------------------------------------
handle_cast(_Msg, State) ->
{noreply, State}.
%%--------------------------------------------------------------------
%% @spec handle_info(Info, State) -> {noreply, State} |
%% {noreply, State, Timeout} |
%% {stop, Reason, State}
%% @doc Handling all non call/cast messages
%% @end
%%--------------------------------------------------------------------
handle_info(Message, State) when is_tuple(Message) ->
MyName = State#state.me,
Neighbor = State#state.neighbor,
io:format("~p~n", [Message]),
case check_circle(Message, MyName) of
true ->
ok;
_ ->
global:send(Neighbor, {MyName, Message})
end,
{noreply, State};
handle_info(_Info, State) ->
{noreply, State}.
%%--------------------------------------------------------------------
%% @spec terminate(Reason, State) -> void()
%% @doc This function is called by a gen_server when it is about to
%% terminate. It should be the opposite of Module:init/1 and do any necessary
%% cleaning up. When it returns, the gen_server terminates with Reason.
%% The return value is ignored.
%% @end
%%--------------------------------------------------------------------
terminate(_Reason, _State) ->
ok.
%%--------------------------------------------------------------------
%% @spec code_change(OldVsn, State, Extra) -> {ok, NewState}
%% @doc Convert process state when code is changed
%% @end
%%--------------------------------------------------------------------
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
check_circle({MyName, _Message}, MyName) ->
true;
check_circle({_Sender, Message}, MyName) when is_tuple(Message) ->
check_circle(Message, MyName);
check_circle(_,_) -> false.
-module(telephone).
-export([start/3, send_message/2, stop/1]).
start(MyName, Neighbor, Node) ->
pong = net_adm:ping(Node),
Pid = spawn_link(node(), fun() -> loop(MyName, Neighbor) end),
global:register_name(MyName, Pid).
send_message(Message, Who) ->
global:send(Who, {send_message, Message}).
stop(MyName) ->
global:send(MyName, stop).
loop(MyName, Neighbor) ->
receive
stop -> ok;
{send_message, Message} ->
global:send(Neighbor, {MyName, Message}),
loop(MyName, Neighbor);
Message when is_tuple(Message) ->
io:format("~p~n", [Message]),
case check_circle(Message, MyName) of
true ->
ok;
_ ->
global:send(Neighbor, {MyName, Message})
end,
loop(MyName, Neighbor);
_ ->
loop(MyName, Neighbor)
end.
check_circle({MyName, _Message}, MyName) ->
true;
check_circle({_Sender, Message}, MyName) when is_tuple(Message) ->
check_circle(Message, MyName);
check_circle(_,_) -> false.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment