новости сообщество форум вики
Статья   Обсуждение   Просмотр   История  

MAN Страницы/gen event


 

gen_event 3

stdlib 1.14.3
Ericsson AB
ERLANG MODULE DEFINITION

МОДУЛЬ

gen_event - Generic Event Handling System - Поведение реализующее основы системы обработки событий

ОПИСАНИЕ



Модуль поведения предназначенный для построения системы обработки событий состоящей из центрального процесса - менеджера событий - и произвольного числа динамически добавляемых и удаляемых обработчиков событий.

Менеджер событий реализованный при помощи этого модуля обладает стандартным набором интерфейсных функций и включает возможность обнаружения и отслеживания ошибок. Также он может использоватся внутри дерева контроля OTP. Обратитесь к Принципам структуры OTP (OTP Design Principles) за более полной информацией.

Каждый обработчик событий должен быть реализован в виде callback-модуля экспортирующего предопределенный набор функций. Ниже приведена схема отношении между функциями поведения и callback-функциями:

gen_event модуль                   Callback-модуль
---------------                    -------------
gen_event:start_link       ----->  -

gen_event:add_handler
gen_event:add_suphandler   ----->  Module:init/1

gen_event:notify
gen_event:sync_notify      ----->  Module:handle_event/2

gen_event:call             ----->  Module:handle_call/2

-                          ----->  Module:handle_info/2

gen_event:delete_handler   ----->  Module:terminate/2

gen_event:swap_handler
gen_event:swap_sup_handler ----->  Module1:terminate/2
Module2:init/1

gen_event:which_handlers   ----->  -

gen_event:stop             ----->  Module:terminate/2

-                          ----->  Module:code_change/3


Так как каждый обработчик событий является отдельным callback-модулем, менеджер событий может обладать несколькими callback-модулями, которые динамически добавляются и удаляются. Следовательно поведение gen_event более терпимо к ошибкам callback-модулей чем остальные поведения. Если callback-функция установленного обработчика события дает сбой по причине Reason, или же возвращает неверно структурированное значение Term, сам менеджер событий продолжит свою работу, удалив проблемный обработчик при помощи callback-функции Module:terminate/2 (см. ниже), передав ей в виде аргумента {error, {\&'EXIT\&', Reason}} или {error, Term} соответственно. Остальные обработчики затронуты не будут.



Для отладки менеджера можно использовать модуль sys.

Что примечательно - что менеджер событий по-умолчанию перехватывает сообщения о завершении связанных с ним процессов.

Если не определено другого, все функции в этом модуле будут завершатся с ошибкой (? fails), если заданный менеджер событий не существует или переданны неправильные аргументы.

ЭКСПОРТ



start_link() -> Result
start_link(EventMgrName) -> Result


Типы

EventMgrName = {local, Name} | {global, Name}
Name = atom()
Result = {ok, Pid} | {error, {already_started, Pid}}
Pid = pid()




Создает процесс менеджера событий как часть дерева контроля. Функция должна быть вызвана, косвенно или непосредственно, супервизором, что, помимо всего прочего, гарантирует его связь с созданным процессом.



Менеджер событий будет зарегистрирован под именем Name, либо локально, в случае EventMgrName={local, Name}, либо глобально, в случае EventMgrName={global, Name}, при помощи функциq register/2 и global:register_name/2 соответственно. А если никакого имени EventMgrName не переданно, то менеджер событий зарегистрирован не будет.

Если менеджер событий успешно создан, функция вернет {ok, Pid}, где Pid - идентификатор созданного процесса. Если же процесс с именем EventMgrName уже существует, функция вернет кортеж {error, {already_started, Pid}}, где Pid - идентификатор этого процесса.



start() -> Result


start(EventMgrName) -> Result


Типы

EventMgrName = {local, Name} | {global, Name}
Name = atom()
Result = {ok, Pid} | {error, {already_started, Pid}}
Pid = pid()




Создает обособленный процесс менеджера событий, т.е. процесс вне дерева контроля и не имеющий супервизора.



Обратитесь к start_link/0, 1 за информацией об аргументах и возвращаемых значениях.



add_handler(EventMgrRef, Handler, Args) -> Result
Типы

EventMgr = Name | {Name, Node} | {global, Name} | pid()
Name = Node = atom()
Handler = Module | {Module, Id}
Module = atom()
Id = term()
Args = term()
Result = ok | {\&'EXIT\&', Reason} | term()
Reason = term()




Добавляет новый обработчик событий в менеджер событий EventMgrRef. Менеджер событий вызовет callback-функцию Module:init/1 для инициализации обработчика и его внутреннего состояния.



Терм EventMgrRef может быть:

  • Идентификатором процесса менеджера,
  • Атомом Name, в случае локальной регистрации менеджера событий,
  • Кортежем {Name, Node}, в случае локальной регистрации на другом узле, либо
  • Кортежем {global, Name}, в случае глобальной регистрации менеджера.


Handler - имя callback-модуля Module или кортеж {Module, Id}, где Id - произвольный терм. Представление {Module, Id} позволяет точно определить необходимый обработчик, в случае когда несколько обработчиков событий используют один и тот же callback-модуль.

Args - произвольный терм, который передается как аргумент в callback-функцию Module:init/1.



Если callback-функция Module:init/1 вернула верное значение, менеджер добавляет обработчик в список и эта функция возвращает ok. В противном случае, если callback-функция Module:init/1 дала сбой по причине Reason или же вернула неверно структурированное значение Term, этот обработчик игнорируется, а функция возвращает кортеж {\&'EXIT\&', Reason} или же терм Term соответственно.



add_sup_handler(EventMgrRef, Handler, Args) -> Result
Типы

EventMgr = Name | {Name, Node} | {global, Name} | pid()
Name = Node = atom()
Handler = Module | {Module, Id}
Module = atom()
Id = term()
Args = term()
Result = ok | {\&'EXIT\&', Reason} | term()
Reason = term()




Добавляет обработчик событий аналогично функции add_handler/3 с тем только отличием, что дополнительно создает связь между новым обработчиком и вызывающим процессом.
  • Если вызывающий процесс завершится по причине Reason, менеджер событий удалит связанный с ним обработчик, вызвав callback-функцию Module:terminate/2 с аргументом {stop, Reason}.
  • Если обработчик событий будет удален, менеджер пошлет сообщение {gen_event_EXIT, Handler, Reason} связанному с ним процессу, где Reason - одно из представленных значений:
  • -
Атом normal - если обработчик был удален вызовом функции delete_handler/3, или атом remove_handler был возращен одной из его callback-функций (см. ниже).
-

Атом shutdown - если обработчик был удален из-за завершения контролирующего менеджера событий.

-

Кортеж {swapped, NewHandler, Pid} - если процесс с идентификатором Pid заменил это обработчик другим обработчиком событий NewHandler при помощи функций swap_handler/3 или swap_sup_handler/3.

-

Произвольный терм - в случае удаления из-за сбоя в обработчике событий - зависит от типа и причины ошибки.



Обратитесь к add_handler/3 за подробным описанием аргументов и возвращаемых значений.

notify(EventMgrRef, Event) -> ok


sync_notify(EventMgrRef, Event) -> ok


Типы

EventMgrRef = Name | {Name, Node} | {global, Name} | pid()
Name = Node = atom()
Event = term()




Сообщает менеджеру событий EventMgrRef о произошедшем событии Event. Менежджер вызовет callback-функцию Module:handle_event/2 в каждом из установленных обработчиков для обработки этого события.



Функция notify асинхронна и возвращает управление сразу же после посылки сообщения, в то время как функция sync_notify синхронна, т.е. возвращает атом ok только после того как событие было обработано всеми установленными обработчиками.

Обратитесь к add_handler/3 за подробным описанием аргумента EventMgrRef.

Событие Event - произвольный терм, передаваемый в качестве одного из аргументов callback-функции Module:handle_event/2.

Стоит отметить, что функция notify не дает сбой даже если заданного менеджера событий не существует, кроме случая когда он определен как атом-имя Name.



call(EventMgrRef, Handler, Request) -> Result


call(EventMgrRef, Handler, Request, Timeout) -> Result


Типы

EventMgrRef = Name | {Name, Node} | {global, Name} | pid()
Name = Node = atom()
Handler = Module | {Module, Id}
Module = atom()
Id = term()
Request = term()
Timeout = int()>0 | infinity
Result = Reply | {error, Error}
Reply = term()
Error = bad_module | {\&'EXIT\&', Reason} | term()
Reason = term()




Создает синхронихированный запрос к обработчику событий Handler, установленному в менеджере событий EventMgrRef и ожидает ответа в течении определенного промежутка времени (таймаута). Менеджер событий вызовет callback-функцию Module:handle_call/2 для обработки этого запроса.



Обратитесь к add_handler/3 за подробным описанием аргументов EventMgrRef и Handler.

Request - произвольный терм передаваемый в качестве одного из аргументов callback-фукнции Module:handle_call/2.

Timeout - это целочисленное значение большее нуля, определяющее промежуток времени в миллисекундах, в течении которого будет ожидатся ответ, либо же атом infinity для бесконечного ожидания. Значение по умолчанию: 5000. Если ответа в течении заданного времени не поступит, данная функция даст сбой (завершится с ошибкой? fail).

Возвращаемое значение Reply является возвращаемым значением callback-функции Module:handle_call/2. Если указанного обработчика событий не существует, данная функция вернет {error, bad_module}. Если же the callback-функция дает сбой по причине Reason или же возвращает неверно структурированные данные Term, эта функция вернет кортеж {error, {\&'EXIT\&', Reason}} или {error, Term}, соответственно.



delete_handler(EventMgrRef, Handler, Args) -> Result
Типы

EventMgrRef = Name | {Name, Node} | {global, Name} | pid()
Name = Node = atom()
Handler = Module | {Module, Id}
Module = atom()
Id = term()
Args = term()
Result = term() | {error, module_not_found} | {\&'EXIT\&', Reason}
Reason = term()




Удаляет обработчик событий Handler из менеджера событий EventMgrRef. Менеджер событий вызовет callback-функцию удалемого обработчика Module:terminate/2, для его уничтожения.



Обратитесь к add_handler/3 за подробным описанием аргументов EventMgrRef и Handler.

Args - произвольный терм передаваемый в качестве одного из аргументов callback-функции Module:terminate/2.

При нормальном выполении эта функция вернет тоже значение, что и callback-функция Module:terminate/2. В противном случае, если указанного обработчика событий не существует, эта функция вернет {error, module_not_found}, либо же кортеж {\&'EXIT\&', Reason}, в случае если callback-функция даст сбой по причине Reason.



swap_handler(EventMgrRef, {Handler1,Args1}, {Handler2,Args2}) -> Result
Типы

EventMgrRef = Name | {Name, Node} | {global, Name} | pid()
Name = Node = atom()
Handler1 = Handler2 = Module | {Module, Id}
Module = atom()
Id = term()
Args1 = Args2 = term()
Result = ok | {error, Error}
Error = {\&'EXIT\&', Reason} | term()
Reason = term()




Замещает старый обработчик событий в менеджере EventMgrRef на новый.



Обратитесь к add_handler/3 за подробным описанием аргументов.

Сначале удаляется старый обработчик событий Handler1. Для этого менеджер событий вызывает callback-функцию Module1:terminate(Args1, ...), где Module1 - callback-модуль обработчика Handler1, и запоминает значение, которое она вернет.

После чего добавляется и инициализурется новый обработчик событий Handler2 при помощи вызова callback-функции Module2:init({Args2, Term}), где Module2 - callback-модуль обработчика Handler2, а Term - значение полученное в результате вызова callback-функции старого обработчика Module1:terminate/2. Это дает возможность передачи накопленной информации из старого обработчика событий Handler1 новому Handler2.

Новый обработчик будет добавлен даже если старый не был установлен. В таком случае Term=error, либо, в случае если callback-функция старого обработчика Module1:terminate/2 дала сбой по причине Reason, Term={\&'EXIT\&', Reason}. Также, старый обработчик будет удален даже если инициализиция нового обработчика Module2:init/1 провалилась.

Если существовала контролирующая связка между старым обработчиком Handler1 и процессом Pid, вместо нее будет создана такая же связка между новым обработчиком Handler2 и процессом Pid.

В случае корректного возврата инициализацией нового обработчика Module2:init/1, эта функция вернет атом ok, в противном случае, если callback-функция Module2:init/1 дала сбой по причине Reason или вернула неверно структурированные данные Term, эта функция вернет кортеж {error, {\&'EXIT\&', Reason}} или {error, Term}, соответственно.



swap_sup_handler(EventMgrRef, {Handler1,Args1}, {Handler2,Args2}) -> Result
Типы

EventMgrRef = Name | {Name, Node} | {global, Name} | pid()
Name = Node = atom()
Handler1 = Handler 2 = Module | {Module, Id}
Module = atom()
Id = term()
Args1 = Args2 = term()
Result = ok | {error, Error}
Error = {\&'EXIT\&', Reason} | term()
Reason = term()




Заменяет обработчик событий в менеджере событий EventMgrRef так же как и swap_handler/3, но, в дополнение, создает контролирующую связку нового обработчика Handler2 с вызывающим процессом.



Обратитесь к swap_handler/3 за описанием аргументов и возвращаемых значений.



which_handlers(EventMgrRef) -> [Handler]
Типы

EventMgrRef = Name | {Name, Node} | {global, Name} | pid()
Name = Node = atom()
Handler = Module | {Module, Id}
Module = atom()
Id = term()




Возвращает список всех обработчиков событий установленнх в менеджере событий EventMgrRef.



Обратитесь к add_handler/3 за описанием аргумента EventMgrRef и переменной Handler.



stop(EventMgrRef) -> ok
Типы

EventMgrRef = Name | {Name, Node} | {global, Name} | pid()
Name = Node = atom()




Завершает процесс менеджера событий EventMgrRef. Перед завершением, менеджер вызовет callback-функцию Module:terminate(stop, ...) каждого из установленных обработчиков событий.



Обратитесь к add_handler/3 за описанием аргумента.

CALLBACK\-ФУНКЦИИ



Нижеперечисленные функции должны быть экспортированы в каждом callback-модуле поведения gen_event.

ЭКСПОРТ



Module:init(InitArgs) -> {ok,State}


Типы

InitArgs = Args | {Args, Term}
Args = Term = term()
State = term()




Когда новый обработчик событий добавляется в менеджер событий, эта функция вызывается для его инициализации.



Если обработчик событий добавляется при помощи функций gen_event:add_handler/3 или gen_event:add_sup_handler/3, терм InitArgs является передаваемым в эти функции аргументом Args.

Если же создаваемый обработчик заменяет другой ввиду вызова функций gen_event:swap_handler/3 или gen_event:swap_sup_handler/3, или же из-за возрата swap-кортежа одной из callback-функций, InitArgs - кортеж {Args, Term}, где Args - значение полученное как аргумент вызванной функции или же как значение из возвращенного swap-кортежа, а Term - результат завершения замещаемого обработчика событий. Обратитесь к gen_event:swap_handler/3 за подробностями.

Функция должна вернуть кортеж {ok, State}, где State - начальное внутреннее состояние созданного обработчика событий.



Module:handle_event(Event, State) -> Result
Типы

Event = term()
State = term()
Result = {ok, NewState}
| {swap_handler, Args1, NewState, Handler2, Args2} | remove_handler
NewState = term()
Args1 = Args2 = term()
Handler2 = Module2 | {Module2, Id}
Module2 = atom()
Id = term()




Когда менеджер событий получает событие посланное при помощи фукнций gen_event:notify/2 или gen_event:sync_notify/2, в каждом установленном обработчике событий вызывается эта функция для обработки полученного события.



Терм Event является одноименным термом Event, переданным в качестве аргумента функциям notify/sync_notify.

State - внутренее состояние данного обработчика событий.

Если функция вернет {ok, NewState}, обработчик событий останется в менеджере событий с обновленным внутренним состоянием NewState.

Также функция может вернуть swap-кортеж {swap_handler, Args1, NewState, Handler2, Args2}. В таком случае данный обработчик событий будет замещен новым обработчиком Handler2 при помощи вызова callback-функции Module:terminate(Args1, NewState) данного обработчика, а затем вызова callback-функции Module2:init({Args2, Term}) нового, где Term - результат вызова Module:terminate/2. Обратитесь к gen_event:swap_handler/3 за подробностями.

Если же функция вернет атом remove_handler, данный обработчик событий будет удален при помощи вызова callback-функции Module:terminate(remove_handler, State).



Module:handle_call(Request, State) -> Result
Типы

Request = term()
State = term()
Result = {ok, Reply, NewState}
| {swap_handler, Reply, Args1, NewState, Handler2, Args2}
| {remove_handler, Reply}
Reply = term()
NewState = term()
Args1 = Args2 = term()
Handler2 = Module2 | {Module2, Id}
Module2 = atom()
Id = term()




Когда менджер событий получает запрос посланный при помощи функций gen_event:call/3, 4, для его обработки в запрошенном обработчике событий вызывается эта фукнция.



Терм Request является одноименным термом Request, переданным в виде аргумента функции call.

State - внутренее состояние данного обработчика событий.

Возвращаемые значения аналогичны возврату handle_event/2 за исключением того, что они также включают в себя терм Reply, который возвращается функцией call. (Предположительно имелось ввиду, что все возможные возвратные значения (а они все являются кортежами) в дополнение получают еще один элемент в конце - терм Reply, который-то и возвращается клиенту. Этот вывод сделан на основе того, что в описании фукнций gen_event:call/3, 4 нигде не сказано, что терма Reply может и не быть, а значит он должен быть всегда, кроме случая со сбоем и ненайденным обработчиком. прим. пер.)



Module:handle_info(Info, State) -> Result
Типы

Info = term()
State = term()
Result = {ok, NewState}
| {swap_handler, Args1, NewState, Handler2, Args2} | remove_handler
NewState = term()
Args1 = Args2 = term()
Handler2 = Module2 | {Module2, Id}
Module2 = atom()
Id = term()




Эта функция вызывается в каждом установленном обработчике событий, когда менджер событий получает любое сообщение отличное от сообщений события или синхронихорованного запроса (или же от некого системного сообщения).



Терм Info является полученным сообщением.

Обратитесь к Module:handle_event/2 за описанием аргумента State и перечислением возможных возвратных значений.



Module:terminate(Arg, State) -> term()
Типы

Arg = Args | {stop, Reason} | stop | remove_handler
| {error, {\&'EXIT\&', Reason}} | {error, Term}
Args = Reason = Term = term()




Эта функция вызывается при удалении обработчика событий из менеджера событий. Ее действия должны быть противоположны действиям callback-функции Module:init/1 и заключаться в проведении необходой перед завершением очистки.



Если обработчик событий удаляется ввиду вызова одной из функций gen_event:delete_handler, gen_event:swap_handler/3 или gen_event:swap_sup_handler/3, терм Arg является аргументом Args, передаваемым в эти функции. В противном случае Arg принимет одно из нижеперечисленных значений:

  • {stop, Reason}, в случае если обработчик событий был связан с другим процессом, завершившимся по причине Reason.
  • stop, в случае завершения менеджера событий.
  • remove_handler, в случае если какая-либо другая callback-функция этого обработчика вернула атом remove_handler или же кортеж {remove_handler, Reply}.
  • {error, Term}, в случае если какая-либо callback-функция данного обработчика вернула неверное значение Term, или же
  • {error, {\&'EXIT\&', Reason}}, в случае если какая-либо callback-функция данного обработчика дала сбой.


State - внутренее состояние данного обработчика событий.

Эта фукнция может вернуть любой терм. Если удаление было инициализированно вызовом функции gen_event:delete_handler, она вернет этот терм по заверении. Если же данный обработчик событий заменяется другим, то этот терм будет передан в качесиве аргумента callback-функции init нового обработчика событий. В противном случае возвращаемое значение игнорирутся.


Module:code_change(OldVsn, State, Extra) -> {ok, NewState}
Типы

OldVsn = Vsn | {down, Vsn}
Vsn = term()
State = NewState = term()
Extra = term()




Эта функция вызываеся во всех установленных обработчиках событий, которые должны обновить свое внутренее состояние ввиду обновления/отката кода своих callback-модулей, т.е. когда в файле .appup задана инструкция {update, Module, Change, ...}, где Change={advanced, Extra}. Обратитесь к Принципам структуры OTP (OTP Design Principles) за подробностями.



В случае обновления кода, OldVsn равняется Vsn, а в случае отката, OldVsn равняется {down, Vsn}. Vsn определяется атрибутом(ами) vsn callback-модуля Module замещаемой версии. Если таковой атрибут не задан, версия Vsn равняется контрольной сумме BEAM файла.

State - нынешнее внутренее состояние данного обработчика событий.

Терм Extra передаетя без изменений из {advanced, Extra} части инструкции на обновление.

Функция должна вернуть обновленное внутренее состояние.

ВНИМАНИЕ!



Данный текст не является официальной документацией, а лишь ее переводом и может содержать устаревшие, неточные или даже неправильные данные. В случае если какая-то функция работает на так как ожидалось после прочтения этой документации обратитесь к оригинальной, и, если обнаружена ошибка, пожалуйста, сообщите о ней переводчикам для ее исправления.

СВЯЗАННАЯ ДОКУМЕНТАЦИЯ



supervisor(3), sys(3)

АВТОР

Gunilla Arendt - support@erlang.ericsson.se

ПЕРЕВОД

Полежаев "Night Nord" Петр - NightNord@gmail.com
 

так же



 

 

Навигация

документация

внешние ссылки

друзья

прочее

Инструменты