- 浏览: 571951 次
- 性别:
- 来自: 广州杭州
文章分类
最新评论
-
bohc:
谢谢,搞了两天了,现在才算是找到问题所在,解决了。
文件在使用FileChannel.map后不能被删除(Windows上) -
zhang0000jun:
在jdk1.8中执行正好和楼主的结果相反,请指教
从Java视角理解CPU缓存(CPU Cache) -
在世界的中心呼喚愛:
forenroll 写道请问楼主的那个分析工具cachemis ...
从Java视角理解CPU缓存(CPU Cache) -
xgj1988:
我这里打出的结果是: 0 L1-dcache-load-mis ...
从Java视角理解CPU缓存(CPU Cache) -
thebye85:
请教下大神,为什么频繁的park会导致大量context sw ...
从Java视角理解CPU上下文切换(Context Switch)
3 Gen_Fsm 行为
This chapter should be read in conjunction withgen_fsm(3)
, where all interface functions and callback functions are described in detail.
3.1 Finite State Machines
3.1 有限状态机
A finite state machine, FSM, can be described as a set of relations of the form:java 代码
- State(S) x Event(E) -> Actions(A), State(S')
These relations are interpreted as meaning:
If we are in state
S
and the eventE
occurs, we should perform the actionsA
and make a transition to the stateS'
.
For an FSM implemented using the gen_fsm
behaviour, the state transition rules are written as a number of Erlang functions which conform to the following convention:
java 代码
- StateName(Event, StateData) ->
- .. code for actions here ...
- {next_state, StateName', StateData'}
3.2 Example
A door with a code lock could be viewed as an FSM. Initially, the door is locked. Anytime someone presses a button, this generates an event. Depending on what buttons have been pressed before, the sequence so far may be correct, incomplete or wrong.
If it is correct, the door is unlocked for 30 seconds (30000 ms). If it is incomplete, we wait for another button to be pressed. If it is is wrong, we start all over, waiting for a new button sequence.
Implementing the code lock FSM using gen_fsm
results in this callback module:
java 代码
- -module(code_lock).
- -behaviour(gen_fsm).
- -export([start_link/1]).
- -export([button/1]).
- -export([init/1, locked/2, open/2]).
- start_link(Code) ->
- gen_fsm:start_link({local, code_lock}, code_lock, Code, []).
- button(Digit) ->
- gen_fsm:send_event(code_lock, {button, Digit}).
- init(Code) ->
- {ok, locked, {[], Code}}.
- locked({button, Digit}, {SoFar, Code}) ->
- case [Digit|SoFar] of
- Code ->
- do_unlock(),
- {next_state, open, {[], Code}, 3000};
- Incomplete when length(Incomplete)
- {next_state, locked, {Incomplete, Code}};
- _Wrong ->
- {next_state, locked, {[], Code}};
- end.
- open(timeout, State) ->
- do_lock(),
- {next_state, locked, State}.
The code is explained in the next sections.
3.3 Starting a Gen_Fsm
In the example in the previous section, the gen_fsm is started by calling code_lock:start_link(Code)
:
start_link(Code) ->
gen_fsm:start_link({local, code_lock}, code_lock, Code, []).
start_link
calls the function gen_fsm:start_link/4
. This function spawns and links to a new process, a gen_fsm.
- The first argument
{local, code_lock}
specifies the name. In this case, the gen_fsm will be locally registered ascode_lock
.
If the name is omitted, the gen_fsm is not registered. Instead its pid must be used. The name could also be given as{global, Name}
, in which case the gen_fsm is registered usingglobal:register_name/2
.
- The second argument,
code_lock
, is the name of the callback module, that is the module where the callback functions are located.
In this case, the interface functions (start_link
andbutton
) are located in the same module as the callback functions (init
,locked
andopen
). This is normally good programming practice, to have the code corresponding to one process contained in one module.
- The third argument,
Code
, is a term which is passed as-is to the callback functioninit
. Here,init
gets the correct code for the lock as indata.
- The fourth argument, [], is a list of options. See
gen_fsm(3)
for available options.
If name registration succeeds, the new gen_fsm process calls the callback function code_lock:init(Code)
. This function is expected to return {ok, StateName, StateData}
, where StateName
is the name of the initial state of the gen_fsm. In this case locked
, assuming the door is locked to begin with. StateData
is the internal state of the gen_fsm. (For gen_fsms, the internal state is often referred to 'state data' to distinguish it from the state as in states of a state machine.) In this case, the state data is the button sequence so far (empty to begin with) and the correct code of the lock.
java 代码
- init(Code) ->
- {ok, locked, {[], Code}}.
Note that gen_fsm:start_link
is synchronous. It does not return until the gen_fsm has been initialized and is ready to receive notifications.
gen_fsm:start_link
must be used if the gen_fsm is part of a supervision tree, i.e. is started by a supervisor. There is another function gen_fsm:start
to start a stand-alone gen_fsm, i.e. a gen_fsm which is not part of a supervision tree.
3.4 Notifying About Events
The function notifying the code lock about a button event is implemented using gen_fsm:send_event/2
:
java 代码
- button(Digit) ->
- gen_fsm:send_event(code_lock, {button, Digit}).
code_lock
is the name of the gen_fsm and must agree with the name used to start it. {button, Digit}
is the actual event.
The event is made into a message and sent to the gen_fsm. When the event is received, the gen_fsm calls StateName(Event, StateData)
which is expected to return a tuple {next_state, StateName1, StateData1}
. StateName
is the name of the current state and StateName1
is the name of the next state to go to. StateData1
is a new value for the state data of the gen_fsm.
java 代码
- locked({button, Digit}, {SoFar, Code}) ->
- case [Digit|SoFar] of
- Code ->
- do_unlock(),
- {next_state, open, {[], Code}, 30000};
- Incomplete when length(Incomplete)
- {next_state, locked, {Incomplete, Code}};
- _Wrong ->
- {next_state, locked, {[], Code}};
- end.
- open(timeout, State) ->
- do_lock(),
- {next_state, locked, State}.
If the door is locked and a button is pressed, the complete button sequence so far is compared with the correct code for the lock and, depending on the result, the door is either unlocked and the gen_fsm goes to state open
, or the door remains in state locked
.
3.5 Timeouts
When a correct code has been givened, the door is unlocked and the following tuple is returned from locked/2
:
java 代码
- {next_state, open, {[], Code}, 30000};
30000 is a timeout value in milliseconds. After 30000 ms, i.e. 30 seconds, a timeout occurs. Then StateName(timeout, StateData)
is called. In this case, the timeout occurs when the door has been in state open
for 30 seconds. After that the door is locked again:
java 代码
- open(timeout, State) ->
- do_lock(),
- {next_state, locked, State}.
3.6 All State Events
Sometimes an event can arrive at any state of the gen_fsm. Instead of sending the message with gen_fsm:send_event/2
and writing one clause handling the event for each state function, the message can be sent with gen_fsm:send_all_state_event/2
and handled with Module:handle_event/3
:
java 代码
- -module(code_lock).
- ...
- -export([stop/0]).
- ...
- stop() ->
- gen_fsm:send_all_state_event(code_lock, stop).
- ...
- handle_event(stop, _StateName, StateData) ->
- {stop, normal, StateData}.
3.7 Stopping
3.7.1 In a Supervision Tree
If the gen_fsm is part of a supervision tree, no stop function is needed. The gen_fsm will automatically be terminated by its supervisor. Exactly how this is done is defined by a shutdown strategy set in the supervisor.
If it is necessary to clean up before termination, the shutdown strategy must be a timeout value and the gen_fsm must be set to trap exit signals in the init
function. When ordered to shutdown, the gen_fsm will then call the callback function terminate(shutdown, StateName, StateData)
:
java 代码
- init(Args) ->
- ...,
- process_flag(trap_exit, true),
- ...,
- {ok, StateName, StateData}.
- ...
- terminate(shutdown, StateName, StateData) ->
- ..code for cleaning up here..
- ok.
3.7.2 Stand-Alone Gen_Fsms
If the gen_fsm is not part of a supervision tree, a stop function may be useful, for example:
java 代码
- ...
- -export([stop/0]).
- ...
- stop() ->
- gen_fsm:send_all_state_event(code_lock, stop).
- ...
- handle_event(stop, _StateName, StateData) ->
- {stop, normal, StateData}.
- ...
terminate(normal, _StateName, _StateData) ->
ok.
The callback function handling the stop
event returns a tuple {stop,normal,StateData1}
, where normal
specifies that it is a normal termination and StateData1
is a new value for the state data of the gen_fsm. This will cause the gen_fsm to call terminate(normal,StateName,StateData1)
and then terminate gracefully:
3.8 Handling Other Messages
If the gen_fsm should be able to receive other messages than events, the callback function handle_info(Info, StateName, StateData)
must be implemented to handle them. Examples of other messages are exit messages, if the gen_fsm is linked to other processes (than the supervisor) and trapping exit signals.
java 代码
- handle_info({'EXIT', Pid, Reason}, StateName, StateData) ->
- ..code to handle exits here..
- {next_state, StateName1, StateData1}.
评论
但我还是不大明白,
如我:
{ok,code_lock}
2> code_lock:start(332).
{ok,<0.38.0>}
3> code_lock:button(332).
ok
4>
如果button了正确的代码,应该会有nI am an unlocked lock才对呀!
-behaviour(gen_fsm).
-export([init/1, button/1, locked/2, open/2]).
-export([start/1, handle_event/3, handle_sync_event/4, handle_info/3,
terminate/3, code_change/4]).
handle_event(_Event, StateName, State) ->
{next_state, StateName, State}.
handle_sync_event(_Event, _From, StateName, State) ->
Reply = ok,
{reply, Reply, StateName, State}.
handle_info(_Info, StateName, State) ->
{next_state, StateName, State}.
terminate(_Reason, _StateName, _State) ->
ok.
code_change(_OldVsn, StateName, State, _Extra) ->
{ok, StateName, State}.
start(Code) ->
gen_fsm:start({local, code_lock}, code_lock, Code, []).
button(Digit) ->
gen_fsm:send_event(code_lock, {button, Digit}).
init(Code) ->
{ok, locked, {[], Code}}.
locked({button, 9}, {SoFar, Code}) ->
9/0,
{next_state, locked, {SoFar, Code}};
locked({button, Digit}, {SoFar, Code}) ->
case [Digit|SoFar] of
Code ->
do_unlock(),
{next_state, open, {[], Code}, 3000};
Incomplete when length(Incomplete)<length(Code) ->
{next_state, locked, {Incomplete, Code}};
_Wrong ->
{next_state, locked, {[], Code}}
end.
open(timeout, State) ->
do_lock(),
{next_state, locked, State}.
do_lock() ->
io:format("~nI am a locked lock.~n").
do_unlock() ->
io:format("~nI am an unlocked lock.~n").
发表评论
-
ubuntu安装otp R11B 的一些记录
2007-11-16 12:30 2781新的ubuntu系统会缺少一些工具 和lib. 用apt-ge ... -
emulator调试日志: driver篇
2007-10-08 16:35 2273--------- driver篇 ------------- ... -
修正Programming Erlang中linked driver实例的小问题
2007-10-08 14:50 2445也许很多人碰上过, 用example1_lid:sta ... -
emulator调试日志: port篇
2007-10-06 16:14 2371------------------ port 篇 ----- ... -
supervisor一小技巧
2007-09-04 13:20 1777simple_one_for_one可以让supervisor ... -
gen_server
2007-08-29 21:52 1898State用来存数据, 任何erlang term都行 ge ... -
application
2007-08-29 02:01 1717用pman 可以看出application controlle ... -
epmd源码学习
2007-07-26 10:14 1998注: 此处节点是指分布式中分布在各终端的点, 而结点是指存在数 ... -
Tracing和dbg
2007-07-15 21:49 2532代码不必用特殊的标记(比如debug_info)来编译,也可以 ... -
ets,dets与大数据存储
2007-07-15 12:49 4931ets与dets都是用来存大数据的机制 ets是Erl ... -
用telnet来与ejabberd交互
2007-07-11 15:41 3195看了一篇文章,觉得用telnet来调试ejabberd也是一种 ... -
ejabberd管理页面和客户端
2007-07-11 00:23 9720转战到97机器。在ejabber.config加上这么一行. ... -
ejabberd在linux平台的安装与配置
2007-07-05 21:17 11919这些天捣鼓了下ejabberd,准备研究它的代码,做为榜样~ ... -
mnesia相关笔记
2007-06-29 12:17 2310当前版本OTP 5.5的mensia建表的表名可以和记录名不一 ... -
OTP设计原则:应用
2007-06-27 00:32 19067 Applications This chapter sh ... -
erlang网络编程的几个性能调优和注意点
2007-06-26 09:56 17848前些天给echo_server写了 ... -
erlc
2007-06-24 15:08 3799erlc 命令 erlc 概要 编译器 描述 Th ... -
echo_server
2007-06-23 14:45 2434代码 -module(echo_server ... -
OTP设计原则:Supervisor行为
2007-06-22 12:15 27035 Supervisor Behaviour This s ... -
OTP设计原则:Gen_Event 行为
2007-06-22 11:59 19844 Gen_Event 行为 这一章应该与gen_event ...
相关推荐
otp_win64_24.1.7.exe
OTP 20(及更高版本)中gen_statem的惯用Elixir包装器。 完整文档可。 您可以在在Hex上找到该软件包。 gen_statem和此包装器之间的一个重要区别是,您在此包装器use GenStateMachine回调模式声明为use ...
Flutter软件包,将帮助您生成具有精美设计和动画的PIN码字段。 可用于OTP或Pin码输入 :nerd_face: :nerd_face: 特征 :green_heart: 自动将下一个字段集中在键入上,将上一个字段集中在删除上 游标支持 :high_...
erl最新版本,erl 23版本 和24版本 属于大版本更新了,有些23版本高性能模块已经不适用24版本,我博客有说明,需要的可以去主页看下。
otp_win64_24.3.exe
Erlang是一种通用的面向并发的编程语言,它有瑞典电信设备制造商爱立信所辖的CS-Lab开发, 目的是创造一种可以应对大规模并发活动的编程语言和运行环境。
Erlang/OTP
otp_win64_20.3.exe百度网盘下载(官网下载实在是太慢了),亲测有效!! otp_win64_20.3.exe otp_win64_20.3.exe otp_win64_20.3.exe
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上运行的...
Erlang/OTP
otp_win64_26.0安装包
DX0906VX 显示屏的OTP烧录程序,用来在出厂时设置屏幕的对比度。
Generate & Verify OTP Server
官网下载超级慢,公司网络也有点封锁,这是我用流量下载的,有需要的可以下载,这是适合Centos的版本21.1
可能这个实现代码量相对没那么少,但是这样是比较OTP的做法。 ##Installation 在你的rebar.config添加: {gs_tcp, ".*", {git, "https://github.com/roowe/gs_tcp", "master"}} 之后执行 rebar get-deps接着 rebar ...
erlang_otp_win64_25.0
我主页还有相关的rabbitmq-server-3.8.5.exe可以下载,地址https://download.csdn.net/download/qq_39403734/12570527,如果这两个在安装的过程中有什么不懂得可以私聊我,或者我有空的时候出个博客给大家。
解压后为:otp_src_21.0.tar.gz,附带下载地址
otp_win64_20.2.exe rabbitmq erlang,rabbitmq安装必备之erlang
otp_win64_21.0.1otp_win64_21.0.1otp_win64_21.0.1otp_win64_21.0.1