• erlang OTP中的四大behaviour fsm的例子


    下面是一个fsm的例子,代码如下:

     1 -module(code_lock2).
     2 
     3 -behaviour(gen_fsm).
     4 -export([start_link/1]).
     5 -export([button/1]).
     6 -export([init/1, locked/2, open/2]).
     7 -export([code_change/4, handle_event/3, handle_info/3, handle_sync_event/4, terminate/3]).
     8 
     9 -spec(start_link(Code::string()) -> {ok,pid()} | ignore | {error,term()}).
    10 start_link(Code) ->
    11     gen_fsm:start_link({local, code_lock2}, code_lock2, Code, []).
    12 
    13 -spec(button(Digit::string()) -> ok).
    14 button(Digit) ->
    15     gen_fsm:send_event(code_lock2, {button, Digit}).
    16 
    17 init(LockCode) ->
    18     io:format("init: ~p~n", [LockCode]),
    19     {ok, locked, {[], LockCode}}.
    20 
    21 locked({button, Digit}, {SoFar, Code}) ->
    22     io:format("buttion: ~p, So far: ~p, Code: ~p~n", [Digit, [SoFar|Digit], Code]),
    23     InputDigits = lists:append(SoFar, Digit),
    24     io:format("Right now the password is ~p~n", [InputDigits]),
    25     case InputDigits of
    26         Code ->
    27             do_unlock(),
    28             {next_state, open, {[], Code}, 10000};
    29         Incomplete when length(Incomplete)<length(Code) ->
    30             {next_state, locked, {Incomplete, Code}, 5000};
    31         Wrong ->
    32             io:format("wrong passwd: ~p~n", [Wrong]),
    33             {next_state, locked, {[], Code}}
    34     end;
    35 locked(timeout, {_SoFar, Code}) ->
    36     io:format("timout when waiting button inputting, clean the input, button again plz~n"),
    37     {next_state, locked, {[], Code}}.
    38 
    39 open(timeout, State) ->
    40     do_lock(),
    41     {next_state, locked, State}.
    42 
    43 code_change(_OldVsn, StateName, Data, _Extra) ->
    44     {ok, StateName, Data}.
    45 
    46 terminate(normal, _StateName, _Data) ->
    47     ok.
    48 
    49 handle_event(Event, StateName, Data) ->
    50     io:format("handle_event... ~n"),
    51     unexpected(Event, StateName),
    52     {next_state, StateName, Data}.
    53 
    54 handle_sync_event(Event, From, StateName, Data) ->
    55     io:format("handle_sync_event, for process: ~p... ~n", [From]),
    56     unexpected(Event, StateName),
    57     {next_state, StateName, Data}.
    58 
    59 handle_info(Info, StateName, Data) ->
    60     io:format("handle_info...~n"),
    61     unexpected(Info, StateName),
    62     {next_state, StateName, Data}.
    63 
    64 %% Unexpected allows to log unexpected messages
    65 unexpected(Msg, State) ->
    66     io:format("~p RECEIVED UNKNOWN EVENT: ~p, while FSM process in state: ~p~n",
    67               [self(), Msg, State]).
    68 %%
    69 %% actions
    70 do_unlock() ->
    71     io:format("passwd is right, open the DOOR.~n").
    72 
    73 do_lock() ->
    74     io:format("over, close the DOOR.~n").

    开锁过程如下:

     1 3> code_lock2:button([1]).
     2 buttion: [1], So far: [], Code: [1,3,5,3,1,7]
     3 Right now the password is [1]
     4 ok
     5 4> code_lock2:button([3]).
     6 buttion: [3], So far: [1], Code: [1,3,5,3,1,7]
     7 Right now the password is [1,3]
     8 ok
     9 5> code_lock2:button([5]).
    10 buttion: [5], So far: [1,3], Code: [1,3,5,3,1,7]
    11 Right now the password is [1,3,5]
    12 ok
    13 timout when waiting button inputting, clean the input, button again plz
    14 6> code_lock2:button([3]).
    15 buttion: [3], So far: [], Code: [1,3,5,3,1,7]
    16 Right now the password is [3]
    17 ok
    18 timout when waiting button inputting, clean the input, button again plz
    19 7> code_lock2:button([1]).
    20 buttion: [1], So far: [], Code: [1,3,5,3,1,7]
    21 Right now the password is [1]
    22 ok
    23 8> code_lock2:button([3]).
    24 buttion: [3], So far: [[1],3], Code: [1,3,5,3,1,7]
    25 Right now the password is [1,3]
    26 ok
    27 9> code_lock2:button([5]).
    28 buttion: [5], So far: [[1,3],5], Code: [1,3,5,3,1,7]
    29 Right now the password is [1,3,5]
    30 ok
    31 10> code_lock2:button([3]).
    32 buttion: [3], So far: [1,3,5], Code: [1,3,5,3,1,7]
    33 Right now the password is [1,3,5,3]
    34 ok
    35 11> code_lock2:button([1]).
    36 buttion: [1], So far: [1,3,5,3], Code: [1,3,5,3,1,7]
    37 Right now the password is [1,3,5,3,1]
    38 ok
    39 12> code_lock2:button([7]).
    40 buttion: [7], So far: [1,3,5,3,1], Code: [1,3,5,3,1,7]
    41 Right now the password is [1,3,5,3,1,7]
    42 ok
    43 passwd is right, open the DOOR.
    44 over, close the DOOR.
    45 13>

    有一个地方解释一下,使用fsm:send_event(code_lock2, {button, Digit})相当于发送了一个消息,这个消息怎么处理呢?

    如果没有fsm,这样的一个问题几乎没法回答!

    这个消息先交给fsm,由fsm判断该交给谁去处理?众所周知,fsm是有限状态机的那种behaviour,当然有多个不同状态,按照fsm的约定这个消息会交给“当前的状态”。

    因为start_link启动fsm,然后init执行后的状态是locked,所以,上面的消息就交道locked函数!

    其他的代码,看起来就很明白,不说了。

    抄代码,执行一下,纯玩。

  • 相关阅读:
    线程基础知识06 synchronized使用javap查看相关指令
    线程基础知识10volatile
    CSDN文章和博客园文章正确的转载方法
    记一次愚蠢的内存泄漏问题的排查
    常用五种排序方法 冒泡排序、快速排序、插入排序、希尔排序、归并排序
    virtualbox虚拟机使用
    itextsharp读取pdf时报错PdfReader not opened with owner password
    Python自动批量修改服务器密码
    Java设计模式——建造者模式
    Java设计模式——迭代器模式
  • 原文地址:https://www.cnblogs.com/andypeker/p/4807523.html
Copyright © 2020-2023  润新知