看看你的状态enter函数为packetsDeliver返回了什么:
packetsDeliver(enter, _OldState, Data) ->
io:format ("Key1", []),
{keep_state, Data}; %% <====== HERE
现在看看你的 State cast 函数为 packetsDeliver 返回了什么:
packetsDeliver(cast, _PacketData, Data) ->
io:format ("Key3", []),
{next_state, allPacketsDelivered, Data}. %% <===== HERE
现在看看你的 State enter 函数为 allPacketsDelivered 返回了什么:
allPacketsDelivered(enter, _OldState, Data) ->
io:format ("Key4", []),
{next_state, packetsDeliver , Data}. %% <==== HERE
allpacketsDelivered 的 State enter 函数应该返回一个类似于 packetsDelivered 的 State enter 函数的元组,例如{keep_state, ...} 不是 {next_state, ...}。
来自the docs,这些是状态enter 函数的允许返回值:
state_callback_result(ActionType) =
{keep_state, NewData :: data()} |
{keep_state,
NewData :: data(),
Actions :: [ActionType] | ActionType} |
keep_state_and_data |
{keep_state_and_data, Actions :: [ActionType] | ActionType} |
{repeat_state, NewData :: data()} |
{repeat_state,
NewData :: data(),
Actions :: [ActionType] | ActionType} |
repeat_state_and_data |
{repeat_state_and_data, Actions :: [ActionType] | ActionType} |
stop |
{stop, Reason :: term()} |
{stop, Reason :: term(), NewData :: data()} |
{stop_and_reply,
Reason :: term(),
Replies :: [reply_action()] | reply_action()} |
{stop_and_reply,
Reason :: term(),
Replies :: [reply_action()] | reply_action(),
NewData :: data()}
请注意,{next_state, ...} 不是允许的返回值之一,这就是您收到错误 bad_return_from_state_function 的原因。 docs 也说:
当 gen_statem 与 state enter 调用一起运行时,这些函数是
在每个状态期间也使用参数(enter, OldState, ...) 调用
改变。在这种情况下,对以下操作有一些限制
可能会返回:由于状态输入调用是不允许的,因此推迟()是不允许的
不是事件,因此没有事件可以推迟,并且
{next_event,_,_} 是不允许的,因为使用状态输入调用应该
不影响事件的消费和生产方式。 您也可能不会
从此调用更改状态。如果你回来
{next_state,NextState, ...} 和 NextState =/= State
gen_statem 崩溃。 请注意,它实际上是允许使用的
{repeat_state, NewData, ...} 虽然这没什么意义,因为你
立即将再次以新状态调用 enter call making
这只是一种奇怪的循环方式,还有更好的循环方式
二郎。如果您不更新 NewData 并且有一些循环终止
条件,或者如果您使用 {repeat_state_and_data, _} 或
repeat_state_and_data 你有一个无限循环!建议您
使用 {keep_state,...}、{keep_state_and_data,_} 或 keep_state_and_data
因为无论如何都无法从状态输入调用更改状态。
======
另一个问题/问题是我不知道为什么状态
packetsDeliver(enter, _OldState, Data) ->
io:format ("Key1", []),
{keep_state, Data};
当我这样做时,正在将我送到 packetDeliver(info, _OldState, Data)
保持状态?
when I do keep_state 是什么意思?我可以告诉你这对任何阅读你的问题的人意味着什么:绝对没有。
当我do keep_state 时,该信息回调不会执行。这样就可以准确地告诉您如何修复代码,对吗?错了。
我是这样做的:
send_event() ->
gen_statem:cast(?MODULE, hello).
如果你这样做:
Pid ! {blah, blah}
然后将执行当前状态的info 回调。
完整示例:
-module(packets).
-behavior(gen_statem).
-compile(export_all).
start_link() ->
gen_statem:start_link({local, ?MODULE}, ?MODULE, [], []).
init([]) ->
io:format ("init~n"),
Data=1,
{ok, packetsDeliver, Data}.
%The initial state will be packetsDeliver.
%And, when you transition to a state, and you
%have specified state_enter, then the function
%State(enter, OldState, Data) will execute, which
%in this case is packetsDeliver(enter, OldState, Data)
callback_mode() ->
[state_functions, state_enter].
packetsDeliver(enter, _OldState, Data) ->
io:format("packetsDeliver enter~n"),
{keep_state, Data};
packetsDeliver(cast, _Msg, Data) ->
io:format ("packetsDeliver cast~n"),
{next_state, allPacketsDelivered, Data};
packetsDeliver(info, _Msg, Data) ->
io:format("packetsDeliver info~n"),
{keep_state, Data}.
allPacketsDelivered(enter, _OldState, _Data) ->
io:format("allPacketsDelivered enter~n"),
%{next_state, packetsDeliver , Data}.
{keep_state_and_data, []}.
send_event() ->
gen_statem:cast(?MODULE, hello).
在外壳中:
~/erlang_programs/gen_statem$ erl
Erlang/OTP 20 [erts-9.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]
Eshell V9.3 (abort with ^G)
1> c(packets).
packets.erl:3: Warning: export_all flag enabled - all functions will be exported
{ok,packets}
2> packets:start_link().
init
packetsDeliver enter
{ok,<0.71.0>}
3> Pid = whereis(packets).
<0.71.0>
4> Pid ! hello.
packetsDeliver info
hello
5> packets:send_event().
packetsDeliver cast
ok
allPacketsDelivered enter
6>