OTPにはイベントマネージャ(event manager)という概念があります。
このイベントマネージャに対して、イベント(event)を送信することにより、決められた動作を行なうことができます。
例えば、エラーのログを取るイベントマネージャに対して、エラーが起きたことをイベントで伝えるといった
ような使い方をします。
イベントマネージャがどのように動作を行なうかということはユーザが定義しなければなりません。 このイベントに対する取り扱い方式を決める物がイベントハンドラというものです。上の例では、 エラーのログを取るという動作がイベントハンドラとして定義されています。
Erlangでこのイベント管理を担当しているのが、OTPの gen_event です。
以下に使用するサンプルを掲示します。
-module(terminal_logger).
-export([init/1, handle_event/2, terminate/2]).
init(_Args) ->
{ok, []}.
handle_event(ErrorMsg, State) ->
io:format("***Error*** ~p~n",[ErrorMsg]),
{ok, State}.
terminate(_Args, _State) ->
ok.
1> gen_event:start_link({local, error_man}).
{ok,<0.33.0>}
2> gen_event:add_handler(error_man, terminal_logger,[]).
ok
3> gen_event:notify(error_man, no_reply).
***Error*** no_reply
ok
4> gen_event:stop(error_man).
ok
例を見てもらってわかる通り、gen_eventは比較的簡単です。ここではgen_eventのイベントマネージャの 起動方法から学びます。
イベントマネージャを起動するには、以下の関数を使います。
1> gen_event:start_link({local, error_man}).
{ok,<0.33.0>}
イベントマネージャの動作を定義するために、イベントハンドラを与えます。
イベントハンドラの追加には以下の関数を使います。
パラメータHandlerにより指定されたモジュールには、次のコールバック関数が必要となります。
gen_event:add_handler/3
のパラメータArgsが、InitArgsとして渡されます。
返り値は決められた形にしなければなりません。以下の部分でイベントハンドラを追加しています。
2> gen_event:add_handler(error_man, terminal_logger,[]).
ok
コールバックは次の部分です。
-module(terminal_logger).
.....
init(_Args) ->
{ok, []}.
.....
gen_event:add_handlerで指定された値と、同じ名前のモジュールの中にあるコールバックが実行されます。
それでは、イベントマネージャに対してイベントを通知してみましょう。イベントの通知には以下の 関数を使います。
gen_event:notify/2 のコールバック関数は次のような書式になっています。なお、コールバック関数が含まれるモジュールは gen_event:add_handler/3 で指定されたモジュールです。
3> gen_event:notify(error_man, no_reply).
***Error*** no_reply
ok
handle_event(ErrorMsg, State) ->
io:format("***Error*** ~p~n",[ErrorMsg]),
{ok, State}.
gen_event:add_handler/3 で設定したハンドラを終了するには、次の関数を使います。
この関数は、次のコールバックを必要としています。
最後にイベントマネージャの停止をします。これには次の関数を使います。
Module:terminate(stop,...)
を呼び出します。4> gen_event:stop(error_man).
ok
実際にはgen_eventはもっと多彩なことが出来ます。詳しい内容については次の節で扱います。