在刚接触otp gen_server时很多人可能只是对着Erlang程序设计中的案例敲一遍,但对为什么要使用gen_server以及里面各个方法是如何联系和影响进程的估计都不太清楚。
首先讲下行为模式,你可以理解为面向对象中的设计模式(更像是模版方法模式),本质都是为了代码复用,当然你也可以把这些行为理解成为某种应用程序框架。我们往往在创建一个进程执行任务时都会有一下步骤,
1.spawn创建一个进程。2.执行初始化函数。3.初始化后进入循环体函数等待调用 4接受退出(如图下所示)
在上面的流程中我们发现,除了calls(接受信息并处理)方法外,其他都是通用的,这就是gen_server模块所要做的事情,提供除了用户自定义的calls回调函数外的通用的方法。
下面是一个sever的简单框架
-module(my_server).
-export([start/2, start_link/2, call/2, cast/2, reply/2]).
%%% Public API
start(Module, InitialState) ->
spawn(fun() -> init(Module, InitialState) end).
start_link(Module, InitialState) ->
spawn_link(fun() -> init(Module, InitialState) end).
%%同步调用
call(Pid, Msg) ->
Ref = erlang:monitor(process, Pid),
Pid ! {sync, self(), Ref, Msg},
receive
{Ref, Reply} ->
erlang:demonitor(Ref, [flush]),
Reply;
{'DOWN', Ref, process, Pid, Reason} ->
erlang:error(Reason)
after 5000 ->
erlang:error(timeout)
end.
%%异步调用
cast(Pid, Msg) ->
Pid