start函数调用gen:start,后者调用do_spawn,然后和gen_server相同,最后都要执行init_it函数,然后该函数执行init函数,并根据返回值执行不同的循环。
start(Mod, Args, Options) ->
gen:start(?MODULE, nolink, Mod, Args, Options).
start(GenMod, LinkP, Name, Mod, Args, Options) ->
casewhere(Name) of
undefined ->
do_spawn(GenMod, LinkP, Name, Mod, Args, Options);
do_spawn(GenMod, link, Mod, Args, Options) ->
Time=timeout(Options),
proc_lib:start_link(?MODULE, init_it,
init_it(Starter, Parent, Name0, Mod, Args, Options) ->
Name=gen:name(Name0),
Debug=gen:debug_options(Name, Options),
HibernateAfterTimeout=gen:hibernate_after(Options),
casecatchMod:init(Args) of
loop循环:对于infinity版本,自身挂起并等待消息,接收到后执行decode_msg将接收到的消息分类,分为系统的,EXIT的,有无debug的其他消息四种。对于后面两种,调用handle_msg函数来处理。该函数也分为debug和非debug版本。
loop(Parent, Name, StateName, StateData, Mod, infinity, HibernateAfterTimeout, Debug) ->
receive
Msg ->
decode_msg(Msg,Parent, Name, StateName, StateData, Mod, infinity, HibernateAfterTimeout, Debug, false)
decode_msg(Msg,Parent, Name, StateName, StateData, Mod, Time, HibernateAfterTimeout, Debug, Hib) ->
caseMsgof
{system, From, Req} ->
sys:handle_system_msg(Req, From, Parent, ?MODULE, Debug,
[Name, StateName, StateData, Mod, Time, HibernateAfterTimeout], Hib);
{'EXIT', Parent, Reason} ->
terminate(Reason, Name, Msg, Mod, StateName, StateData, Debug);
_MsgwhenDebug=:= [] ->
handle_msg(Msg, Parent, Name, StateName, StateData, Mod, Time, HibernateAfterTimeout);
_Msg ->
Debug1=sys:handle_debug(Debug, funprint_event/3,
{Name, StateName}, {in, Msg}),
handle_msg(Msg, Parent, Name, StateName, StateData,
Mod, Time, HibernateAfterTimeout, Debug1)
end.
函数首先调用from函数将消息分类,分为’$gen_sync_event’,$gen_sync_all_state_event’,以及undefined版本请两个直接返回Msg本身,其他的返回undefined,这里是按照From参数的tag进行模式匹配。之后执行dispatch函数将Msg进行模式匹配来将消息分类,同时调用相应的回调函数来处理,根据它们的返回类型执行debug以及执行reply和不同的loop函数循环。
handle_msg(Msg, Parent, Name, StateName, StateData, Mod, _Time, HibernateAfterTimeout) ->%No debug here
From=from(Msg),
casecatchdispatch(Msg, Mod, StateName, StateData) of
{next_state, NStateName, NStateData}->
from({'$gen_sync_event', From, _Event}) ->From;
from({'$gen_sync_all_state_event', From, _Event}) ->From;
from(_) ->undefined.
dispatch({'$gen_event', Event}, Mod, StateName, StateData) ->
Mod:StateName(Event, StateData);
dispatch({'$gen_all_state_event', Event}, Mod, StateName, StateData) ->
Mod:handle_event(Event, StateName, StateData);
dispatch({'$gen_sync_event', From, Event}, Mod, StateName, StateData) ->
Mod:StateName(Event, From, StateData);
dispatch({'$gen_sync_all_state_event', From, Event},
Mod, StateName, StateData) ->
Mod:handle_sync_event(Event, From, StateName, StateData);
dispatch({timeout, Ref, {'$gen_timer', Msg}}, Mod, StateName, StateData) ->
Mod:StateName({timeout, Ref, Msg}, StateData);
dispatch({timeout, _Ref, {'$gen_event', Event}}, Mod, StateName, StateData) ->
Mod:StateName(Event, StateData);
dispatch(Info, Mod, StateName, StateData) ->
Mod:handle_info(Info, StateName, StateData).
导出函数:dispatch执行的函数都是回调模块中定义好的函数。
send_event函数:根据不同的名字进行模式匹配,直接发送{‘$gen_event’,Event}到gen_fsm进程。之后dispatch函数执行StateName(Event, StateData)函数。
sync_send_event函数:分为有Timeout和没有两个版本。调用gen:call函数,第二个参数是’$gen_sync_event’。 gen:call函数之后调用do_for_proc,其参数(gen_fsm名称或Pid,Fun)。其中Fun是一个do_call函数,作用是监督其参数Pid的函数 这里是监督gen_fsm进程(使用erlang:monitor),之后调用erlang:send发送消息到gen_fsm进程,然后挂起自己来接收gen_fsm的回复消息,之后先停止监督,(使用erlang:demonitor),然后将回复({ok, Reply}),之后回到sync_send_event,函数最终返回Reply(整个过程类似gen_server)。dispatch执行StateName(Event, From, StateData)函数。
sync_send_event(Name, Event) ->
casecatchgen:call(Name, '$gen_sync_event', Event) of
send_all_state_event函数:根据不同的名字进行模式匹配,然后发送{‘$gen_all_state_event’, Event}到gen_fsm进程。dispatch函数执行handle_event(Event,StateName, StateData)函数。
sync_send_all_state_event函数:分为有Timeout和没有两个版本。类似sync_send_event,只是第二个参数变成了'$gen_sync_all_state_event'。dispatch执行handle_sync_event(Event,From, StateName, StateData)函数。
reply函数:直接发送到进程。
reply({To, Tag}, Reply) ->
catchTo! {Tag, Reply}.
reply(Name, {To, Tag}, Reply, Debug, StateName) ->
reply({To, Tag}, Reply),
sys:handle_debug(Debug, funprint_event/3, Name,
{out, Reply, To, StateName}).
start_timer函数:直接调用erlang:start_timer(Time, self(), {'$gen_timer', Msg}),在Time毫秒后发送消息到gen_fsm,之后dispatch接收到消息后执行StateName(timeout,Ref, Msg)函数。
start_timer(Time, Msg) ->% 启动一个计时器,在Time毫秒后将发送{timeout, TimerRef, Msg}
erlang:start_timer(Time, self(), {'$gen_timer', Msg}).
send_event_after函数:调用gen:start_timer(Time,self(), {'$gen_event', Event}),跟上面的区别是tag不同。dispatch执行StateName(Event, StateData)函数。
send_event_after(Time, Event) ->
erlang:start_timer(Time, self(), {'$gen_event', Event}).
cancel_timer函数:调用erlang:cancel_timer(Ref)函数,取消一个计时器,后者是通过erlang:send_after或者erlang:start_timer返回的。
cancel_timer(Ref) ->
caseerlang:cancel_timer(Ref) of
enter_loop函数:类似于gen_server,产生新的Name, Parent,Debug和HibernateAfterTimeout来执行新的循环。
gen_fsm行为类似于gen_server。