Events/Observer pattern

Hakan Mattsson hakan@REDACTED
Fri Nov 25 10:47:27 CET 2005


On Thu, 24 Nov 2005, Matthias Lang wrote:

ML> Corrado Santoro writes:
ML> 
ML>  > Matthias Lang wrote:
ML>  > > I don't think there's anything in the standard library which does
ML>  > > that.
ML> 
ML>  > Why? Don't you think that gen_event could exactly fit in the problem?
ML> 
ML> No, gen_event doesn't provide the interface he asked for. You have to
ML> add code. Quite a bit of code.
ML> 
ML> How much code is needed to do this using gen_event? How much using
ML> gen_server? I think it's the same: one data structure, one module, six
ML> callback functions. I.e. gen_event provides no benefit, even in
ML> an application it might be expected to be good at! No wonder it's not
ML> used much.
ML> 
ML> FWIW, as is often the case, doing this in classic Erlang is neater and
ML> simpler. Here's a no-frills version:
ML> 
ML>     loop(Pids) ->
ML>         receive
ML>            {reg, Pid} -> loop([Pid|Pids]);
ML>            {unreg, Pid} -> loop([X || X <- Pids, X =/= Pid]);
ML>            {send, Msg} -> [ X ! Msg || X <- Pids], loop(Pids)
ML>         end.

If you want to cope system messages and smooth upgrade
of your code, you need to start your process with
proc_lib and add a few lines more. See sys and proc_lib
about the details. But it is still quite comprehensive.

/Håkan


-module(obs).

-export([
	 start/0,
	 init/1,
	 system_continue/3,
	 system_terminate/4,
	 system_code_change/4
	]).

start() ->
    proc_lib:start_link(?MODULE, init, [self()], infinity).

init(Parent) ->
    proc_lib:init_ack(Parent, {ok, self()}),
    loop(Parent, []).

loop(Parent, Pids) ->
    receive
	{reg, Pid} ->
	    loop(Parent, [Pid|Pids]);
	{unreg, Pid} ->
	    loop(Parent, [X || X <- Pids, X =/= Pid]);
	{send, Msg} -> 
	    [ X ! Msg || X <- Pids],
	    loop(Parent, Pids);
	{system, From, Msg} ->
	    sys:handle_system_msg(Msg, From, Parent, ?MODULE, [], Pids)
    end.

system_continue(Parent, _Debug, Pids) ->
    loop(Parent, Pids).

system_terminate(_Reason, Parent, _Debug, Pids) ->
    loop(Parent, Pids).

system_code_change(Pids, _Module, _OldVsn, _Extra) ->
    {ok, Pids}.


More information about the erlang-questions mailing list