-
-
Save fpdevil/6268346 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
%%%------------------------------------------------------------------- | |
%%% @author Fernando Benavides <[email protected]> | |
%%% @copyright (C) 2011 Inaka Networks S.R.L. | |
%%% @doc It listens and just repeats... | |
%%% @end | |
%%%------------------------------------------------------------------- | |
-module(gen_event_repeater). | |
-author('Fernando Benavides <[email protected]>'). | |
-behaviour(gen_event). | |
-export([start/2, start/1, start_link/1, start_link/2]). | |
-export([init/1, handle_event/2, handle_call/2, handle_info/2, terminate/2, code_change/3]). | |
-include("elog.hrl"). | |
-include("records.hrl"). | |
-record(state, {dispatcher :: pid(), | |
reference :: reference()}). | |
-type state() :: #state{}. | |
%% ==================================================================== | |
%% External functions | |
%% ==================================================================== | |
-spec start(pid() | atom() | {global, atom()}) -> {ok, pid()}. | |
start(Source) -> | |
subscribe(Source, gen_event:start()). | |
-spec start({local, atom()} | {global, atom()}, pid() | atom() | {global, atom()}) -> {ok, pid()}. | |
start(Name, Source) -> | |
subscribe(Source, gen_event:start(Name)). | |
-spec start_link(pid() | atom() | {global, atom()}) -> {ok, pid()}. | |
start_link(Source) -> | |
subscribe(Source, gen_event:start_link()). | |
-spec start_link({local, atom()} | {global, atom()}, pid() | atom() | {global, atom()}) -> {ok, pid()}. | |
start_link(Name, Source) -> | |
subscribe(Source, gen_event:start_link(Name)). | |
%% ==================================================================== | |
%% Server functions | |
%% ==================================================================== | |
%% @hidden | |
-spec init(pid()) -> {ok, state()}. | |
init(Dispatcher) -> | |
Ref = erlang:monitor(process, Dispatcher), | |
{ok, #state{dispatcher = Dispatcher, reference = Ref}}. | |
%% @hidden | |
-spec handle_event(term(), state()) -> {ok, state()}. | |
handle_event(Event, State) -> | |
gen_event:notify(State#state.dispatcher, Event), | |
{ok, State}. | |
%% @hidden | |
-spec handle_call(term(), state()) -> {ok, ok, state()}. | |
handle_call(_Call, State) -> {ok, ok, State}. | |
%% @hidden | |
-spec handle_info(term(), state()) -> {ok, state()} | remove_handler. | |
handle_info({'DOWN', Ref, _Type, _Dispatcher, Info}, State = #state{reference = Ref}) -> | |
?WARN("Our dispatcher (~p) died... removing ourselves from the source...~n\t~p~n", [State#state.dispatcher, Info]), | |
remove_handler; | |
handle_info(Info, State) -> | |
State#state.dispatcher ! Info, | |
{ok, State}. | |
%% @hidden | |
-spec terminate(term(), state()) -> ok. | |
terminate(remove_handler, _State) -> | |
ok; | |
terminate(stop, State) -> | |
?INFO("Source dispatcher stopped. Stopping our own dispatcher too...~n", []), | |
gen_event:stop(State#state.dispatcher); | |
terminate(Reason, State) -> | |
?INFO("Source dispatcher exited (~p). Exiting our own dispatcher too...~n", [Reason]), | |
exit(State#state.dispatcher, Reason). | |
%% @hidden | |
-spec code_change(term(), state(), term()) -> {ok, state()}. | |
code_change(_OldVsn, State, _Extra) -> {ok, State}. | |
%% ==================================================================== | |
%% Private functions | |
%% ==================================================================== | |
subscribe(Source, {ok, Pid}) -> | |
try gen_event:add_handler(Source, {?MODULE, Pid}, Pid) of | |
ok -> {ok, Pid} | |
catch | |
_:Error -> | |
?WARN("gen_event:add_handler error:~n~p~n", [Error]), | |
gen_event:stop(Pid), | |
throw(Error) | |
end; | |
subscribe(Source, {error, {already_started, Pid}}) -> | |
try | |
case lists:member({?MODULE, Pid}, gen_event:which_handlers(Source)) of | |
true -> | |
{ok, Pid}; | |
false -> | |
ok = gen_event:add_handler(Source, {?MODULE, Pid}, Pid), | |
{ok, Pid} | |
end | |
catch | |
_:Error -> | |
?WARN("gen_event:add_handler error:~n~p~n", [Error]), | |
gen_event:stop(Pid), | |
throw(Error) | |
end. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment