what is the gen_server ?
man 中 gen_server定义是:
引用
A behaviour module for implementing the server of a client-server relation. A generic server process (gen_server) implemented using this module will have a standard set of interface functions and include functionality for tracing and error reporting. It will also fit into an OTP supervision tree.
一个简单的echo gen_server
-module(echo).
-behaviour(gen_server).
%% API
-export([start_link/0]).
-export([echo/1]).
%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).
-record(state, {}).
echo(Msg)->
gen_server:call(?MODULE,{echo , Msg} ).
start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
init([]) ->
{ok, #state{}}.
handle_call({echo , Msg}, _From, State) ->
{reply , Msg , State };
handle_call(_Request, _From, State) ->
Reply = ok,
{reply, Reply, State}.
%%其他自动生成部分省略
echo gen_server代码的主干可以由模板生成,具体请参google。
运行并测试echo gen_server
echo:start_link(),
echo:echo("hello world").
how to start a echo gen_server ?
如上图,在主进程中的调用顺序为:echo:start_link->gen_server:start_link->gen:start->proc_lib:start_link
proc_lib:start_link中通过erlang:spawn_link创建echo进程,新进程中依次回调
gen:init_it->gen_server:init_it->echo:init,从而注入echo自己的初始化逻辑。
在gen_server:init_it中分析回调echo:init的返回值,初始化成功以后则进入循环。
init_it(Starter, Parent, Name, Mod, Args, Options) ->
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} ->
proc_lib:init_ack(Starter, {error, Reason}),
exit(Reason);
ignore ->
proc_lib:init_ack(Starter, ignore),
exit(normal);
{'EXIT', Reason} ->
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.
how to deal with a call ?
gen_server:call({local,echo},{echo,"hello,world"}).
gen_server:call调用gen:call发起一个同步的消息请求,使用标签"$gen_call"作为表示,表示这是应用的消息,不是系统的消息。
call(Name, Request) ->
case catch gen:call(Name, '$gen_call', Request) of
{ok,Res} ->
Res;
{'EXIT',Reason} ->
exit({Reason, {?MODULE, call, [Name, Request]}})
end.
在主循环gen_server:loop中从消息队列中依次取出消息并处理,注意这是串行的,
在一条消息处理完毕之前,不会处理下一条消息。
loop(Parent, Name, State, Mod, Time, Debug) ->
Msg = receive
Input ->
Input
after Time ->
timeout
end,
decode_msg(Msg, Parent, Name, State, Mod, Time, Debug, false).
gen_server:decode_msg区分不同消息类型,分别处理
decode_msg(Msg, Parent, Name, State, Mod, Time, Debug, Hib) ->
case Msg of
{system, From, Req} ->
sys:handle_system_msg(Req, From, Parent, ?MODULE, Debug,
[Name, State, Mod, Time], Hib);
{'EXIT', Parent, Reason} ->
terminate(Reason, Name, Msg, Mod, State, Debug);
_Msg when Debug =:= [] ->
handle_msg(Msg, Parent, Name, State, Mod);
_Msg ->
Debug1 = sys:handle_debug(Debug, {?MODULE, print_event},
Name, {in, Msg}),
handle_msg(Msg, Parent, Name, State, Mod, Debug1)
end.
gen_server:handle_msg回调echo:handle_call处理应用信息,处理成功则返回loop方法。
handle_msg({'$gen_call', From, Msg}, Parent, Name, State, Mod) ->
case catch Mod:handle_call(Msg, From, State) of
{reply, Reply, NState} ->
reply(From, Reply),
loop(Parent, Name, NState, Mod, infinity, []);
{reply, Reply, NState, Time1} ->
reply(From, Reply),
loop(Parent, Name, NState, Mod, Time1, []);
{noreply, NState} ->
loop(Parent, Name, NState, Mod, infinity, []);
{noreply, NState, Time1} ->
loop(Parent, Name, NState, Mod, Time1, []);
{stop, Reason, Reply, NState} ->
{'EXIT', R} =
(catch terminate(Reason, Name, Msg, Mod, NState, [])),
reply(From, Reply),
exit(R);
Other -> handle_common_reply(Other, Parent, Name, Msg, Mod, State)
end;
how to deal with a cast ?
how to deal with a info ?
要注意的地方
- 大小: 20.5 KB
分享到:
相关推荐
可用于OTP或Pin码输入 :nerd_face: :nerd_face: 特征 :green_heart: 自动将下一个字段集中在键入上,将上一个字段集中在删除上 游标支持 :high_voltage: 可以设置为任意长度。 (建议3-6个字段) 文本字段的3种...
OTP 20(及更高版本)中gen_statem的惯用Elixir包装器。 完整文档可。 您可以在在Hex上找到该软件包。 gen_statem和此包装器之间的一个重要区别是,您在此包装器use GenStateMachine回调模式声明为use ...
otp_win64_24.1.7.exe
erl最新版本,erl 23版本 和24版本 属于大版本更新了,有些23版本高性能模块已经不适用24版本,我博客有说明,需要的可以去主页看下。
Erlang是一种通用的面向并发的编程语言,它有瑞典电信设备制造商爱立信所辖的CS-Lab开发, 目的是创造一种可以应对大规模并发活动的编程语言和运行环境。
Generate & Verify OTP Server
可能这个实现代码量相对没那么少,但是这样是比较OTP的做法。 ##Installation 在你的rebar.config添加: {gs_tcp, ".*", {git, "https://github.com/roowe/gs_tcp", "master"}} 之后执行 rebar get-deps接着 rebar ...
自己自学RabbitMQ整理出来的资料,windows环境下的erlang和RabbitMQ安装包,版本分别是otp_22.3_for_windows_64和rabbitmq-server-3.8.5(保证不会出现版本冲突) 在官网上下载简直是龟速,所以分享给大家便于下载,...
Gen_server实现了通用服务器client_server原理,几个不同的客户端去分享服务端管理的资源(如图),gen_server提供标准的接口函数和包含追踪功能以及错误报告来实现通用的服务器,同时可以作为OTP监控树的一部分。...
实现了一次性口令认证系统,采用MD5算法进行加密,得到口令的校验码
otp_win64_26.0安装包
errol:以OTP方式编排RabbitMQ消费者:open_mailbox_with_raised_flag:
Erlang/OTP
rabbitmq-server3.7版本和otp_win64安装包,下载解压后,先安装otp_win64.exe 在安装rabbitmq-server ,具体安装步骤可自行百度
OTP进程池应用程序_Erlang_Makefile_下载.zip
otp_win64_21.0.1otp_win64_21.0.1otp_win64_21.0.1otp_win64_21.0.1
此文件为otp_src_20.2.tar.gz 的二次压缩文件 解压先用unzip otp_src_20.2.zip 出来, 然后就是安装时的 tar -zxvf otp_src_20.2.tar.gz内容了, 此文件为了自己使用是方便找到,请把分数定为1分,谢谢
react-native-otp-fieldReact本机OTP字段 :keycap_1: :keycap_2: :keycap_3: :keycap_4: :keycap_5:安装npm i react-native-otp-fieldRN <0.63 npm i react-native-otp-field@0.0.7一个可在android和iOS上运行的...
BJOTPViewController 一个非常简单且外观整洁的视图控制器,可让您快速方便地键入OTP。技术支持 :check_mark_button: iOS 11.0以上 :check_mark_button: 迅捷4.0+ :check_mark_button: 人像| 风景 :check_mark_...
解压后为:otp_src_21.0.tar.gz,附带下载地址