diff options
-rw-r--r-- | lib/stdlib/doc/src/gen_statem.xml | 15 | ||||
-rw-r--r-- | lib/stdlib/src/gen_statem.erl | 42 | ||||
-rw-r--r-- | lib/stdlib/test/gen_statem_SUITE.erl | 11 |
3 files changed, 39 insertions, 29 deletions
diff --git a/lib/stdlib/doc/src/gen_statem.xml b/lib/stdlib/doc/src/gen_statem.xml index 5de1812b41..aeab09615c 100644 --- a/lib/stdlib/doc/src/gen_statem.xml +++ b/lib/stdlib/doc/src/gen_statem.xml @@ -369,7 +369,7 @@ erlang:'!' -----> Module:StateName/5 </p> <p>The processing order for a state change is:</p> <list type="ordered"> - <item>If the option <c>retry</c> is <c>true</c> + <item>If the option <c>postpone</c> is <c>true</c> the current event is postponed. </item> <item>If the state changes the queue of incoming events @@ -402,10 +402,10 @@ erlang:'!' -----> Module:StateName/5 and the last value is kept. </p> <taglist> - <tag><c>retry</c></tag> - <tag><c>{retry,<anno>Retry</anno>}</c></tag> - <item>If <c><anno>Retry</anno> =:= true</c> - or plain <c>retry</c> postpone the current event + <tag><c>postpone</c></tag> + <tag><c>{postpone,<anno>Postpone</anno>}</c></tag> + <item>If <c><anno>Postpone</anno> =:= true</c> + or plain <c>postpone</c> postpone the current event to be retried after a state change. This option is ignored when returned from <seealso marker="#Module:init/1">Module:init/1</seealso> @@ -434,9 +434,8 @@ erlang:'!' -----> Module:StateName/5 event counts just like a new in this respect. If <c>Time =:= infinity</c> or <c>Time =:= 0</c> no timer is started but for zero time the timeout - event is enqued as just received after all - other already received events. - Also note that it is not possible + event is immediately enqueued as the newest received. + Also note that it is not possible nor needed to cancel this timeout using the <seealso marker="#type-state_operation"> <c>state_operation()</c> diff --git a/lib/stdlib/src/gen_statem.erl b/lib/stdlib/src/gen_statem.erl index 52fde7df7b..32174687cf 100644 --- a/lib/stdlib/src/gen_statem.erl +++ b/lib/stdlib/src/gen_statem.erl @@ -70,15 +70,15 @@ %% First NewState and NewStateData are set, %% then all state_operations() are executed in order of %% apperance. Postponing the current event is performed - %% (iff state_option() 'retry' is 'true'). + %% (iff state_option() 'postpone' is 'true'). %% Lastly pending events are processed or if there are %% no pending events the server goes into receive %% or hibernate (iff state_option() 'hibernate' is 'true') state_option() | state_operation(). -type state_option() :: %% The first of each kind in the state_op() list takes precedence - 'retry' | % Postpone the current event to a different (=/=) state - {'retry', Retry :: boolean()} | + 'postpone' | % Postpone the current event to a different (=/=) state + {'postpone', Postpone :: boolean()} | 'hibernate' | % Hibernate the server instead of going into receive {'hibernate', Hibernate :: boolean()} | (Timeout :: timeout()) | % {timeout,Timeout} @@ -469,7 +469,7 @@ enter(Module, Options, State, StateData, Server, InitOps, Parent) -> S#{callback_mode := CallbackMode}, [], {event,undefined}, State, StateData, - StateOps++[{retry,false}]); + StateOps++[{postpone,false}]); [Reason] -> ?TERMINATE(Reason, Debug, S, []) end. @@ -782,9 +782,9 @@ loop_event_state_ops( Parent, Debug0, #{state := State, postponed := P0} = S, Events, Event, NewState, NewStateData, StateOps) -> case collect_state_options(StateOps) of - {Retry,Hibernate,Timeout,Operations} -> - P1 = % Move current event to postponed if Retry - case Retry of + {Postpone,Hibernate,Timeout,Operations} -> + P1 = % Move current event to postponed if Postpone + case Postpone of true -> [Event|P0]; false -> @@ -804,9 +804,9 @@ loop_event_state_ops( NewDebug = sys_debug( Debug, S, - case Retry of + case Postpone of true -> - {retry,Event,NewState}; + {postpone,Event,NewState}; false -> {consume,Event,NewState} end), @@ -867,38 +867,38 @@ collect_state_options(StateOps) -> collect_state_options(StateOps, false, false, undefined, []). %% Keep the last of each kind collect_state_options( - [], Retry, Hibernate, Timeout, Operations) -> - {Retry,Hibernate,Timeout,lists:reverse(Operations)}; + [], Postpone, Hibernate, Timeout, Operations) -> + {Postpone,Hibernate,Timeout,lists:reverse(Operations)}; collect_state_options( - [StateOp|StateOps] = SOSOs, Retry, Hibernate, Timeout, Operations) -> + [StateOp|StateOps] = SOSOs, Postpone, Hibernate, Timeout, Operations) -> case StateOp of - retry -> + postpone -> collect_state_options( StateOps, true, Hibernate, Timeout, Operations); - {retry,NewRetry} when is_boolean(NewRetry) -> + {postpone,NewPostpone} when is_boolean(NewPostpone) -> collect_state_options( - StateOps, NewRetry, Hibernate, Timeout, Operations); - {retry,_} -> + StateOps, NewPostpone, Hibernate, Timeout, Operations); + {postpone,_} -> [{bad_state_ops,SOSOs}]; hibernate -> collect_state_options( - StateOps, Retry, true, Timeout, Operations); + StateOps, Postpone, true, Timeout, Operations); {hibernate,NewHibernate} when is_boolean(NewHibernate) -> collect_state_options( - StateOps, Retry, NewHibernate, Timeout, Operations); + StateOps, Postpone, NewHibernate, Timeout, Operations); {hibernate,_} -> [{bad_state_ops,SOSOs}]; {timeout,infinity,_} -> % Ignore since it will never time out collect_state_options( - StateOps, Retry, Hibernate, undefined, Operations); + StateOps, Postpone, Hibernate, undefined, Operations); {timeout,Time,_} = NewTimeout when is_integer(Time), Time >= 0 -> collect_state_options( - StateOps, Retry, Hibernate, NewTimeout, Operations); + StateOps, Postpone, Hibernate, NewTimeout, Operations); {timeout,_,_} -> [{bad_state_ops,SOSOs}]; _ -> % Collect others as operations collect_state_options( - StateOps, Retry, Hibernate, Timeout, [StateOp|Operations]) + StateOps, Postpone, Hibernate, Timeout, [StateOp|Operations]) end. process_state_operations([], Debug, _S, Q, P) -> diff --git a/lib/stdlib/test/gen_statem_SUITE.erl b/lib/stdlib/test/gen_statem_SUITE.erl index facc36fb9f..8b619b6a60 100644 --- a/lib/stdlib/test/gen_statem_SUITE.erl +++ b/lib/stdlib/test/gen_statem_SUITE.erl @@ -1032,7 +1032,10 @@ do_connect(STM) -> gen_statem:cast(STM, {connect,self()}), wfor(accept), check_state(STM, wfor_conf), + Tag = make_ref(), + gen_statem:cast(STM, {ping,self(),Tag}), gen_statem:cast(STM, confirm), + wfor({pong,Tag}), check_state(STM, connected), ok. @@ -1071,7 +1074,10 @@ do_sync_connect(STM) -> check_state(STM, idle), accept = gen_statem:call(STM, connect), check_state(STM, wfor_conf), + Tag = make_ref(), + gen_statem:cast(STM, {ping,self(),Tag}), yes = gen_statem:call(STM, confirm), + wfor({pong,Tag}), check_state(STM, connected), ok. @@ -1202,6 +1208,8 @@ timeout3(_, _, _, State, Data) -> wfor_conf({call,From}, confirm, _, _, Data) -> {next_state,connected,Data, [{reply,From,yes}]}; +wfor_conf(cast, {ping,_,_}, _, State, Data) -> + {next_state,State,Data,[postpone]}; wfor_conf(cast, confirm, _, _, Data) -> {next_state,connected,Data}; wfor_conf(Type, Content, PrevState, State, Data) -> @@ -1229,6 +1237,9 @@ connected({call,From}, disconnect, _, _, Data) -> [{reply,From,yes}]}; connected(cast, disconnect, _, _, Data) -> {next_state,idle,Data}; +connected(cast, {ping,Pid,Tag}, _, State, Data) -> + Pid ! {pong,Tag}, + {next_state,State,Data}; connected(Type, Content, PrevState, State, Data) -> case handle_common_events(Type, Content, PrevState, State, Data) of undefined -> |