RegProcName ! {event, E}
E就係一個事件(可以係任何Erlang數据類型),RegProcName即處理進程的注冊名。事件發送出去後,發送方就毋需關心該事件會被如何處理了~~
現在我們看看處理事件的進程(事件處理器 - event handler),看個例子:
-module(event_handler).
-export([make/1, add_handler/2, event/2]).
%創建一個名為Name的新事件處理器
%其接收到事件後,會執行函數no_op/1
make(Name) ->
register(Name, spawn(fun() -> my_handler(fun no_op/1) end)).
add_handler(Name, Fun) -> Name ! {add, Fun}.
%產生一個事件
event(Name, X) -> Name ! {event, X}.
my_handler(Fun) ->
receive
{add, Fun1} ->
my_handler(Fun1);
{event, Any} ->
(catch Fun(Any)),
my_handler(Fun)
end.
no_op(_) -> void.
上例的事件處理器有如下功能:
event_handler:make(Name):創建一個名為Name的事件處理器;
event_handler:event(Name, X):向名為Name的事件處理器發送事件X;
event_handler:add_handler(Name, Fun):將事件處理器的處理函數(最初係一個什么都不幹的函數no_op/1)替換為Fun,替換後當接收到事件時,就會調用新的處理函數Fun來處理該事件。
運行試試效果如何:
1> event_handler:make(errors).
true
2> event_handler:event(errors, hi).
{event, hi}
Well,沒咩特別事發生,因為現在的處理函數什么都不幹~~我們接著寫個回調模塊(callback module)來設立一個會做實際工作的事件處理函數:
-module(motor_controller).
-export([add_event_handler/0]).
add_event_handler() ->
event_handler:add_handler(errors, fun controller/1).
controller(too_hot) -> io:format("Turn off the motor!n");
controller(X) -> io:format("~w ignored event: ~p~n", [?MODULE, X]).
上述代碼編譯之後就會添加一個事件處理函數了:
3> c(motor_controller).
{ok, motor_controller}
4> motor_controller:add_event_handler().
{add, #Fun}
現在向事件處理器發送信息,將由函數motor_controller:controller/1來處理:
5> event_handler:event(errors, cool).
motor_controller ignored event: cool
{event, cool}
6> event_handler:event(errors, too_hot).
Turn off the motor
{event, too_hot}
好了,上面寫了一大堆,到底都做了些什么呢?首先我們提供了一個接收事件的事件處理器(這里係一個注冊名為errors的進程),然后定義了如何發送事件給該處理器(發送方毋需知道處理器會對事件作什么處理),最后我們看到怎么在運行過程中動態的更新事件處理函數。
譯自《Programming Erlang》
0 意見