浏览 2732 次
锁定老帖子 主题:gen_server源码杂记
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2009-09-17
最后修改:2009-09-17
gen_server :start_link ( { local, ?MODULE } , ?MODULE , [ ] , [ ] ) . 参数分别是Name,Mod,Arg,Options Options里可以设置timeout gen.erl里的简单小函数取得timeout timeout(Options) -> case opt(timeout, Options) of {ok, Time} -> Time; _ -> infinity end. spawn_opts(Options) -> case opt(spawn_opt, Options) of {ok, Opts} -> Opts; _ -> [] end. opt(Op, [{Op, Value}|_]) -> {ok, Value}; opt(Op, [_|Options]) -> opt(Op, Options); opt(_, []) -> false. gen_server启动流程大体如下: 在我们的程序里启动一般调用如下: gen_server :start_link ( { local, ?MODULE } , ?MODULE , [ ] , [ ] ) . gen_server.erl 里 start_link(Name, Mod, Args, Options) -> gen:start(?MODULE, link, Name, Mod, Args, Options). gen.erl里基本是这样 do_spawn(GenMod, link, Mod, Args, Options) -> Time = timeout(Options), proc_lib:start_link(?MODULE, init_it, [GenMod, self(), self(), Mod, Args, Options], Time,... proc_lib是一个关于进程的工具类,提供了同步启动进程的机制 start_link(M,F,A,Timeout,SpawnOpts) when is_atom(M), is_atom(F), is_list(A) -> Pid = proc_lib:spawn_opt(M, F, A, ensure_link(SpawnOpts)), sync_wait(Pid, Timeout). sync_wait(Pid, Timeout) -> receive {ack, Pid, Return} -> Return; {'EXIT', Pid, Reason} -> {error, Reason} after Timeout -> unlink(Pid), exit(Pid, kill), flush(Pid), {error, timeout} end. spawn_opt系列大体就是erlang:spawn系里的一个,是异步的,先调用了本模块的init_p,存放些上下文信息到进程字典,最终会回调gen_server,一会再说 同步的关键在sync_wait这句,一看就懂了 上面的spawn经过fun的传来传去最终回到了gen_server.erl init_it(Starter, self, Name, Mod, Args, Options) -> init_it(Starter, self(), Name, Mod, Args, Options); init_it(Starter, Parent, Name0, Mod, Args, Options) -> Name = name(Name0), Debug = debug_options(Name, Options), case catch Mod:init(Args) of {ok, State} -> proc_lib:init_ack(Starter, {ok, self()}), loop(Parent, Name, State, Mod, infinity, Debug); {ok, State, Timeout} -> proc_lib:init_ack(Starter, {ok, self()}), loop(Parent, Name, State, Mod, Timeout, Debug); {stop, Reason} -> %% For consistency, we must make sure that the %% registered name (if any) is unregistered before %% the parent process is notified about the failure. %% (Otherwise, the parent process could get %% an 'already_started' error if it immediately %% tried starting the process again.) unregister_name(Name0), proc_lib:init_ack(Starter, {error, Reason}), exit(Reason); ignore -> unregister_name(Name0), proc_lib:init_ack(Starter, ignore), exit(normal); {'EXIT', Reason} -> unregister_name(Name0), proc_lib:init_ack(Starter, {error, Reason}), exit(Reason); Else -> Error = {bad_return_value, Else}, proc_lib:init_ack(Starter, {error, Error}), exit(Error) end. 看见这句了吧 catch Mod:init(Args) 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2009-09-17
写完了才发现右上角,已经有一篇阿里的一位同学做出的深入分析,学习下
|
|
返回顶楼 | |
发表时间:2009-09-17
gen_server是个很复杂的模块 能挖掘的不止上面那么多
|
|
返回顶楼 | |
发表时间:2009-09-18
mryufeng 写道 gen_server是个很复杂的模块 能挖掘的不止上面那么多
哈哈,慢慢挖掘,不着急 |
|
返回顶楼 | |