Erlang — gen_server
2015-06-02 10:55
417 查看
热代码交换:如果要修改一个服务器的行为,不用停止它,只需要发送一个包含新代码的消息,它就会提取新代码,然后用新代码和老代码
的回话数据继续工作。
编写gen_server回调模块的简要步骤:
1、确定回调模块名。
2、编写接口函数。
3、在回调模块里编写六个必需的回调函数。
在回调模块中必须导出六个回调方法:init/1,handle_call/3,handle_cast/2,handle_info/2,terminate/2,code_change/3
简单的回调模板:
-module(gen_server_template).
-behaviour(gen_server).
%% ====================================================================
%% gen_server 回调行数
%% ====================================================================
-export([init/1,handle_call/3,handle_cast/2,handle_info/2,terminate/2,code_change/3]).
-record(state,{}).
init([]) ->
{ok,#state{}}.
handle_call(_Request,_From,State) ->
Replay = ok,
{replay,Replay,State}.
handle_cast(_Msg,State) ->
{noreplay,State}.
handle_info(_Info,State) ->
{ok,State}.
terminate(_Reason,_State) ->
ok.
code_change(_OldVsn,State,_Extra) ->
{ok,State}.
对于通用服务器而言,用户主要完成以下两件事:
1、启动服务器进程
2、向进程发消息(并获取应答)
gen_server提供了三个主要的库函数来实现这些基本功能:
---------------------------------------------------------------------------------------------------------------------------------------
库函数 对应回调函数 描述
---------------------------------------------------------------------------------------------------------------------------------------
gen_server:start_link/4 Module:init/1
启动并链接一个gen_server容器进程
gen_server:call/2 Module:handle_call/3 向gen_server进程发送同步消息并等待应答
gen_server:case/2 Module:handle_cast/2 向gen_server进程发送异步消息
----------------------------------------------------------------------------------------------------------------------------------------
注:gen_server:call/2 函数实现了可靠的同步请求—响应功能,其中默认应答等待超时为5秒,一旦超时便放弃等待应答,
gen_server:call/3 允许以毫秒为单位设置超时,同时也可以通过将超时时间设置为infinity来禁用超时。
handle_info/2 没有对应的gen_server库函数,这个回调是一个重要的特例,所有未经过call或cast库函数发送至gen_server
信箱的消息都由它处理(通常是直接用!运算符发送的裸消息)。
gen_server:start_link({local,?SERVER}?MODULE,[port],[]).执行这个调用的时候,会派生出一个新的gen_server容器
进程,新进程将以SERVER宏展开后对于的名称在本地节点上注册,然后等待行为模式实现模块中的init/1回调函数完成进程
初始化,最后返回。
example:
%%% @author xiaomage
%%% @doc 模拟银行开户、存款、取款操作
%%% @todo Add description to my_banck.
-module(my_banck).
-behaviour(gen_server).
-define(SERVER,?MODULE).
%%-------------------------------
%% gen_server call_back function
%%-------------------------------
-export([init/1,handle_call/3,handle_cast/2,handle_info/2,terminate/2,code_change/3]).
%%-------------------------------
%% API function
%%-------------------------------
-export([start/0,stop/0,new_account/1,deposit/2,withdraw/2]).
start() ->
gen_server:start_link({local,?SERVER}, ?MODULE, [], []).
stop() ->
gen_server:call(?MODULE, stop).
new_account(Who) ->
gen_server:call(?MODULE, {new,Who}).
deposit(Who,Amount) ->
gen_server:call(?MODULE, {add,Who,Amount}).
withdraw(Who,Amount) ->
gen_server:call(?MODULE, {remove,Who,Amount}).
init([]) ->
{ok,ets:new(?MODULE, [])}.
handle_call({new,Who},_From,Tab) ->
Reply = case ets:lookup(Tab, Who) of
[] ->
ets:insert(Tab, {Who,0}),
{welcome,Who};
[_] ->
{Who,you_are_already_a_customer}
end,
{reply,Reply,Tab};
handle_call({add,Who,X},_From,Tab) ->
Reply = case ets:lookup(Tab, Who) of
[] ->
not_a_customer;
[{Who,Amount}] ->
NewAmount = Amount + X,
ets:insert(Tab, {Who,NewAmount}),
{thanks,Who,you_banck_is ,NewAmount}
end,
{reply,Reply,Tab};
handle_call({remove,Who,X},_From,Tab) ->
Reply = case ets:lookup(Tab, Who) of
[] ->
not_a_customer;
[{Who,Amount}] when Amount >= X ->
NewAmount = Amount - X,
ets:insert(Tab, {Who,NewAmount}),
{thanks,Who,you_banck_is,NewAmount};
[{Who,Amount}] ->
{sorry,Who,you_only_hava,Amount,in_the_banck}
end,
{reply,Reply,Tab};
handle_call({stop}, _From, Tab) ->
{stop,normal,stopped,Tab}.
handle_cast(_Msg,State) ->
{noreply,State}.
handle_info(_Info,State) ->
{ok,State}.
terminate(_Reason,_State) ->
ok.
code_change(_OldVsn,State,_Extra) ->
{ok,State}.
的回话数据继续工作。
编写gen_server回调模块的简要步骤:
1、确定回调模块名。
2、编写接口函数。
3、在回调模块里编写六个必需的回调函数。
在回调模块中必须导出六个回调方法:init/1,handle_call/3,handle_cast/2,handle_info/2,terminate/2,code_change/3
简单的回调模板:
-module(gen_server_template).
-behaviour(gen_server).
%% ====================================================================
%% gen_server 回调行数
%% ====================================================================
-export([init/1,handle_call/3,handle_cast/2,handle_info/2,terminate/2,code_change/3]).
-record(state,{}).
init([]) ->
{ok,#state{}}.
handle_call(_Request,_From,State) ->
Replay = ok,
{replay,Replay,State}.
handle_cast(_Msg,State) ->
{noreplay,State}.
handle_info(_Info,State) ->
{ok,State}.
terminate(_Reason,_State) ->
ok.
code_change(_OldVsn,State,_Extra) ->
{ok,State}.
对于通用服务器而言,用户主要完成以下两件事:
1、启动服务器进程
2、向进程发消息(并获取应答)
gen_server提供了三个主要的库函数来实现这些基本功能:
---------------------------------------------------------------------------------------------------------------------------------------
库函数 对应回调函数 描述
---------------------------------------------------------------------------------------------------------------------------------------
gen_server:start_link/4 Module:init/1
启动并链接一个gen_server容器进程
gen_server:call/2 Module:handle_call/3 向gen_server进程发送同步消息并等待应答
gen_server:case/2 Module:handle_cast/2 向gen_server进程发送异步消息
----------------------------------------------------------------------------------------------------------------------------------------
注:gen_server:call/2 函数实现了可靠的同步请求—响应功能,其中默认应答等待超时为5秒,一旦超时便放弃等待应答,
gen_server:call/3 允许以毫秒为单位设置超时,同时也可以通过将超时时间设置为infinity来禁用超时。
handle_info/2 没有对应的gen_server库函数,这个回调是一个重要的特例,所有未经过call或cast库函数发送至gen_server
信箱的消息都由它处理(通常是直接用!运算符发送的裸消息)。
gen_server:start_link({local,?SERVER}?MODULE,[port],[]).执行这个调用的时候,会派生出一个新的gen_server容器
进程,新进程将以SERVER宏展开后对于的名称在本地节点上注册,然后等待行为模式实现模块中的init/1回调函数完成进程
初始化,最后返回。
example:
%%% @author xiaomage
%%% @doc 模拟银行开户、存款、取款操作
%%% @todo Add description to my_banck.
-module(my_banck).
-behaviour(gen_server).
-define(SERVER,?MODULE).
%%-------------------------------
%% gen_server call_back function
%%-------------------------------
-export([init/1,handle_call/3,handle_cast/2,handle_info/2,terminate/2,code_change/3]).
%%-------------------------------
%% API function
%%-------------------------------
-export([start/0,stop/0,new_account/1,deposit/2,withdraw/2]).
start() ->
gen_server:start_link({local,?SERVER}, ?MODULE, [], []).
stop() ->
gen_server:call(?MODULE, stop).
new_account(Who) ->
gen_server:call(?MODULE, {new,Who}).
deposit(Who,Amount) ->
gen_server:call(?MODULE, {add,Who,Amount}).
withdraw(Who,Amount) ->
gen_server:call(?MODULE, {remove,Who,Amount}).
init([]) ->
{ok,ets:new(?MODULE, [])}.
handle_call({new,Who},_From,Tab) ->
Reply = case ets:lookup(Tab, Who) of
[] ->
ets:insert(Tab, {Who,0}),
{welcome,Who};
[_] ->
{Who,you_are_already_a_customer}
end,
{reply,Reply,Tab};
handle_call({add,Who,X},_From,Tab) ->
Reply = case ets:lookup(Tab, Who) of
[] ->
not_a_customer;
[{Who,Amount}] ->
NewAmount = Amount + X,
ets:insert(Tab, {Who,NewAmount}),
{thanks,Who,you_banck_is ,NewAmount}
end,
{reply,Reply,Tab};
handle_call({remove,Who,X},_From,Tab) ->
Reply = case ets:lookup(Tab, Who) of
[] ->
not_a_customer;
[{Who,Amount}] when Amount >= X ->
NewAmount = Amount - X,
ets:insert(Tab, {Who,NewAmount}),
{thanks,Who,you_banck_is,NewAmount};
[{Who,Amount}] ->
{sorry,Who,you_only_hava,Amount,in_the_banck}
end,
{reply,Reply,Tab};
handle_call({stop}, _From, Tab) ->
{stop,normal,stopped,Tab}.
handle_cast(_Msg,State) ->
{noreply,State}.
handle_info(_Info,State) ->
{ok,State}.
terminate(_Reason,_State) ->
ok.
code_change(_OldVsn,State,_Extra) ->
{ok,State}.
相关文章推荐
- 优化UITableViewCell高度计算的那些事
- activiti获取用户任务同时查询流程变量 null pointer问题解决。
- 2015-6-2-提高你的Vim效率
- Pool of Argument Topics 11-20
- sz与rz命令
- Oracle表分区(经典)
- Apache FileUpload详细介绍
- Javascript中正则表达式详解(转载)
- 多余预留清除方法
- ARM GCC中内联汇编语法
- visaul studio 2013部分快捷键
- NoSQL的价值到底在哪里?
- 54. C# -- 泛型(Generic)
- Node.js事件发射器
- C/C++中qsort()以及sort()的用法
- 适配器模式(Adapter)
- 动物怎么叫(2)
- VC开发中HEAP CORRUPTION DETECTED错误
- 黑马程序员-java之可变参数
- qt release打包发布