gen_tcserver это behaviour, который реализован на основе gen server-a. Он расширяет возможности gen server-а, добавляя возможность работы с таймерами и соответствующи на них реагировать.
Для работы с gen_tcserver нужно указать:
-behaviour(gen_tcserver).
Добавить реализацию методов:
-callback init(Args :: term()) ->
{ok, State :: term()} |
{ok, State :: term(), timeout() | hibernate | {timer_container, term()}} |
{stop, Reason :: term()} | ignore.
-callback handle_call(Request :: term(), From :: {pid(), Tag :: term()}, TCState :: term(), State :: term()) ->
{reply, Reply :: term(), NewTCState :: term(), NewState :: term()} |
{reply, Reply :: term(), NewTCState :: term(), NewState :: term(), hibernate} |
{noreply, NewTCState :: term(), NewState :: term()} |
{noreply, NewTCState :: term(), NewState :: term(), hibernate} |
{stop, Reason :: term(), Reply :: term(), NewTCState :: term(), NewState :: term()} |
{stop, Reason :: term(), NewTCState :: term(), NewState :: term()}.
-callback handle_cast(Request :: term(), TCState :: term(), State :: term()) ->
{noreply, NewTCState :: term(), NewState :: term()} |
{noreply, NewTCState :: term(), NewState :: term(), hibernate} |
{stop, Reason :: term(), NewState :: term()} |
{stop, Reason :: term(), NewTCState :: term(), NewState :: term()}.
-callback handle_info(Info :: timeout() | term(), TCState :: term(), State :: term()) ->
{noreply, NewTCState :: term(), NewState :: term()} |
{noreply, NewTCState :: term(), NewState :: term(), hibernate} |
{stop, Reason :: term(), NewTCState :: term(), NewState :: term()}.
-callback handle_timeout(TCID :: term(), TID :: term(), Arg :: term(), TTime :: term(), TCState :: term(), State :: term()) ->
{noreply, NewTCState :: term(), NewState :: term()} |
{noreply, NewTCState :: term(), NewState :: term(), hibernate} |
{stop, Reason :: term(), NewTCState :: term(), NewState :: term()}.
-callback terminate(Reason :: (normal | shutdown | {shutdown, term()} | term()), State :: term()) ->
term().
-callback code_change(OldVsn :: (term() | {down, term()}), TCState :: term(), State :: term(), Extra :: term()) ->
{ok, NewTCState :: term(), NewState :: term()} | {error, Reason :: term()}.
TID :: term() = Уникальное имя таймера
Duration :: non_neg_integer() = Время жизни таймера
Args :: [{Key :: term(), Val :: term()}] = Данные устонавливаемые при инициализации хранилища таймеров
Arg :: term() = Данные получаемые по истечению таймера
Time1 :: non_neg_integer() = Время старта
Time2 :: non_neg_integer() = Время срабатывания
Cont = ImpCont :: timer_container() = Хранилище таймеров
NowTime :: non_neg_integer() = Собственное время, когда стартовал таймер
TCID :: term() = Уникальная группа, по которой объединяются таймера
Таймер идентифицируется на таймер сервере идентификатором TID, задаваемым пользователем. Введение системы идентификации таймеров полностью перекладывается на плечи пользователя. Забота о том, чтобы у разных пользовательских таймеров не совпали TID, так же целиком и полностью возлагается на пользователя.
Таймера могут быть локальными или глобальными. Когда таймер локальный, на него действует дополнительный ряд функций по очистке таймеров.
Таймер сервер запускается и работает в отдельном процессе, фактически является реализацией gen_fsm из 2х состояний: active, wait.
- В состоянии active производится ожидание истечения очередного таймера. Таймера могут запускаться, останавливаться, рестартоваться.
- В состоянии wait процесс находится при истечении очередного таймера, когда для него был вызван timer_fun и пользователь выполняет действия по обработке таймера. В этом состоянии таймера могут запускаться, останавливаться, рестартоваться. Переход из этого состояния в active осуществляется по событию timer_ack.
Замечания:
- Хранилице таймеров инициализируется в init.
- Сами таймера взводятся в handle_call, handle_cast, handle_info.
- Результат их завершения обрабатывается handle_timeout.
- На завершение таймеров нужно реагировать с помощью timer_ack.
- Длительность таймера задается в миллисекундах.
Для работы с таймерами существует следующее API:
Инициализирует хранилище таймеров.
init(Cont | [])
init(Cont, Args)
retutn NewCont
Взводит таймер.
start_timer(TID, Duration, Arg, Cont)
start_timer(NowTime, TID, Duration, Arg, Cont)
cont_start_timer(TCID, TID, Duration, Arg, Cont)
cont_start_timer(NowTime, TCID, TID, Duration, Arg, Cont)
retutn NewCont
Взводит локальный таймер.
start_timer_local(TID, Duration, Arg, Cont)
start_timer_local(NowTime, TID, Duration, Arg, Cont)
cont_start_timer_local(TCID, TID, Duration, Arg, Cont)
cont_start_timer_local(NowTime, TCID, TID, Duration, Arg, Cont)
retutn NewCont
Отменяет таймер или группу таймеров.
cancel_timer(TID, Cont)
cont_cancel_timer(TCID, TID, Cont)
cont_cancel_timers(TCID, Cont)
retutn NewCont
Если таймер сработал, то его требуется подтвердить. Данный метод подтверждает его. Если таймер не сработал, ничего не делает.
timer_ack(Cont) - подтверждает первый сработавший
cont_timer_ack(TCID, Cont) - подтверждает первый сработавший в группе
cont_timer_ack(TCID, TID, Cont) - подтверждает определенный таймер
retutn NewCont
Проверяет на существование таймера.
is_exist(TID, Cont)
cont_is_exist(TCID, TID, Cont)
retutn boolean()
Удаляет таймера, которые не соответствуют фильтрующей функции.
filter_cont(FilterFun, Cont)
retutn NewCont
Отменяет таймера, которые соответствуют фильтрующей функции.
filter_timers(TCID, FTID, Cont)
retutn NewCont
Возвращает информацию о таймере.
get_timer_info(TID, Cont)
cont_get_timer_info(TCID, TID, Cont)
retutn undefined | {Time2, Args, Type :: local | global}
Возвращает состояние таймера.
process_timeout(Cont)
return {none, timer_container()} |
{wait_timeout, TCID, TID, Arg, TTime1, NewCont} |
{TCID, TID, Arg, TTime1, NewCont}.
Возвращает время до срабатывания таймера.
get_actual_timeout(Cont)
get_actual_timeout(NowTime, Cont)
return infinity | non_neg_integer()
Возвращает таймер сработавший, но не получивший timer_ack.
get_waiting_timeout(Cont)
return {TCID, TID, Arg, TTime2, NewCont} | none.
Удаляет локальные таймера.
flush(Cont)
return NewCont
Реактивирует таймер, который находится в режиме ожидания timer_ack.
reactivate(Cont)
return NewCont
Проверяет что это хранилище таймеров.
is_container(Data :: term())
return boolean()
Удаляет локальные таймера.
export(Cont)
cont_export(TCID, Cont)
return NewCont
import(ImpCont, Cont)
cont_import(ImpCont, Cont)
cont_import(TCID, ImpCont, Cont)
return NewCont
cont_cleanup(TCID, Cont)
return NewCont