From f4de3f5887be010db178a178e1f20027f3e5d22b Mon Sep 17 00:00:00 2001 From: Raimo Niskanen Date: Wed, 12 Oct 2016 17:49:26 +0200 Subject: Use parameterized types --- lib/stdlib/doc/src/gen_statem.xml | 216 ++++++++++++++------------------------ lib/stdlib/src/gen_statem.erl | 94 ++++++----------- lib/tools/emacs/erlang-skels.el | 40 ++++--- 3 files changed, 131 insertions(+), 219 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/doc/src/gen_statem.xml b/lib/stdlib/doc/src/gen_statem.xml index c0631c8448..64267c2af5 100644 --- a/lib/stdlib/doc/src/gen_statem.xml +++ b/lib/stdlib/doc/src/gen_statem.xml @@ -127,9 +127,9 @@ erlang:'!' -----> Module:StateName/3 is not regarded as an error but as a valid return from all callback functions.

- +

- The "state function" for a specific + The "state callback" for a specific state in a gen_statem is the callback function that is called for all events in this state. It is selected depending on which @@ -141,7 +141,7 @@ erlang:'!' -----> Module:StateName/3 When the callback mode is state_functions, the state must be an atom and - is used as the state function name; see + is used as the state callback name; see Module:StateName/3. This gathers all code for a specific state in one function as the gen_statem engine @@ -154,7 +154,7 @@ erlang:'!' -----> Module:StateName/3 When the callback mode is handle_event_function, the state can be any term - and the state function name is + and the state callback name is Module:handle_event/4. This makes it easy to branch depending on state or event as you desire. Be careful about which events you handle in which @@ -164,8 +164,8 @@ erlang:'!' -----> Module:StateName/3

The gen_statem enqueues incoming events in order of arrival and presents these to the - state function - in that order. The state function can postpone an event + state callback + in that order. The state callback can postpone an event so it is not retried in the current state. After a state change the queue restarts with the postponed events.

@@ -177,12 +177,12 @@ erlang:'!' -----> Module:StateName/3 to entering a new receive statement.

- The state function + The state callback can insert events using the action() next_event and such an event is inserted as the next to present - to the state function. That is, as if it is + to the state callback. That is, as if it is the oldest incoming event. A dedicated event_type() internal can be used for such events making them impossible @@ -198,7 +198,7 @@ erlang:'!' -----> Module:StateName/3

The gen_statem engine can automatically make a specialized call to the - state function + state callback whenever a new state is entered; see state_enter(). This is for writing code common to all state entries. @@ -207,7 +207,7 @@ erlang:'!' -----> Module:StateName/3

If you in gen_statem, for example, postpone - an event in one state and then call another state function + an event in one state and then call another state callback of yours, you have not changed states and hence the postponed event is not retried, which is logical but can be confusing.

@@ -236,7 +236,7 @@ erlang:'!' -----> Module:StateName/3 The gen_statem process can go into hibernation; see proc_lib:hibernate/3. It is done when a - state function or + state callback or Module:init/1 specifies hibernate in the returned Actions @@ -294,7 +294,7 @@ init([]) -> {ok,State,Data}. callback_mode() -> state_functions. -%%% State function(s) +%%% state callback(s) off({call,From}, push, Data) -> %% Go to 'on', increment count and reply @@ -348,7 +348,7 @@ ok callback_mode() -> handle_event_function. -%%% State function(s) +%%% state callback(s) handle_event({call,From}, push, off, Data) -> %% Go to 'on', increment count and reply @@ -482,6 +482,10 @@ handle_event(_, _, State, Data) ->

+ If the + callback mode + is handle_event_function, + the state can be any term. After a state change (NextState =/= State), all postponed events are retried.

@@ -495,6 +499,8 @@ handle_event(_, _, State, Data) -> callback mode is state_functions, the state must be of this type. + After a state change (NextState =/= State), + all postponed events are retried.

@@ -592,11 +598,11 @@ handle_event(_, _, State, Data) -> returns a list containing state_enter, the gen_statem engine will, at every state change, call the - state function + state callback with arguments (enter, OldState, Data). This may look like an event but is really a call - performed after the previous state function returned - and before any event is delivered to the new state function. + performed after the previous state callback returned + and before any event is delivered to the new state callback. See Module:StateName/3 and @@ -666,19 +672,19 @@ handle_event(_, _, State, Data) -> If the state changes or is the initial state, and state enter calls are used, the gen_statem calls - the new state function with arguments + the new state callback with arguments (enter, OldState, Data). Any actions returned from this call are handled as if they were appended to the actions - returned by the state function that changed states. + returned by the state callback that changed states.

If there are enqueued events the (possibly new) - state function + state callback is called with the oldest enqueued event, and we start again from the top of this list.

@@ -691,7 +697,7 @@ handle_event(_, _, State, Data) -> event_timeout() are handled. This may lead to a time-out zero event being generated to the - state function + state callback and we start again from the top of this list.

@@ -707,7 +713,7 @@ handle_event(_, _, State, Data) -> the next incoming message awakens the gen_statem, but if it is a system event it goes right back into hibernation. When a new message arrives the - state function + state callback is called with the corresponding event, and we start again from the top of this list.

@@ -806,7 +812,7 @@ handle_event(_, _, State, Data) ->

These state transition actions can be invoked by returning them from the - state function + state callback when it is called with an event, from @@ -870,7 +876,7 @@ handle_event(_, _, State, Data) ->

These state transition actions can be invoked by returning them from the - state function, from + state callback, from Module:init/1 or by giving them to enter_loop/5,6. @@ -903,7 +909,7 @@ handle_event(_, _, State, Data) -> Short for {timeout,Timeout,Timeout}, that is, the time-out message is the time-out time. This form exists to make the - state function + state callback return value {next_state,NextState,NewData,Timeout} allowed like for gen_fsm's Module:StateName/2. @@ -936,7 +942,7 @@ handle_event(_, _, State, Data) ->

This state transition action can be invoked by returning it from the - state function, from + state callback, from Module:init/1 or by giving it to enter_loop/5,6. @@ -947,7 +953,7 @@ handle_event(_, _, State, Data) -> From must be the term from argument {call,From} in a call to a - state function. + state callback.

Note that using this action from @@ -956,77 +962,48 @@ handle_event(_, _, State, Data) -> enter_loop/5,6 would be weird on the border of whichcraft since there has been no earlier call to a - state function + state callback in this server.

- + - - next_state - -

- The gen_statem does a state transition to - NextStateName - (which can be the same as the current state), - sets NewData, - and executes all Actions. -

-
-

- All these terms are tuples or atoms and this property - will hold in any future version of gen_statem. + State is the current state + and it can not be changed since the state callback + was called with a + state enter call.

-
-
- - - next_state

The gen_statem does a state transition to - NextStateName - (which can be the same as the current state), + State, which has to be + the current state, sets NewData, and executes all Actions.

-

- All these terms are tuples or atoms and this property - will hold in any future version of gen_statem. -

- + - - next_state - -

- The gen_statem does a state transition to - NextState - (which can be the same as the current state), - sets NewData, - and executes all Actions. -

-
-

- All these terms are tuples or atoms and this property - will hold in any future version of gen_statem. + StateType is + state_name() + if + callback mode + is state_functions, or + state() + if + callback mode + is handle_event_function.

-
-
- - - next_state @@ -1039,48 +1016,20 @@ handle_event(_, _, State, Data) ->

-

- All these terms are tuples or atoms and this property - will hold in any future version of gen_statem. -

- + - - keep_state - -

- The gen_statem keeps the current state, or - does a state transition to the current state if you like, - sets NewData, - and executes all Actions. - This is the same as - {next_state,CurrentState,NewData,Actions}. -

-
- keep_state_and_data - -

- The gen_statem keeps the current state or - does a state transition to the current state if you like, - keeps the current server data, - and executes all Actions. - This is the same as - {next_state,CurrentState,CurrentData,Actions}. -

-
-

- All these terms are tuples or atoms and this property - will hold in any future version of gen_statem. + ActionType is + enter_action() + if the state callback was called with a + state enter call + and + action() + if the state callback was called with an event.

-
-
- - - keep_state @@ -1104,17 +1053,6 @@ handle_event(_, _, State, Data) -> {next_state,CurrentState,CurrentData,Actions}.

-
-

- All these terms are tuples or atoms and this property - will hold in any future version of gen_statem. -

-
-
- - - - stop

@@ -1155,14 +1093,14 @@ handle_event(_, _, State, Data) -> by sending a request and waiting until its reply arrives. The gen_statem calls the - state function with + state callback with event_type() {call,From} and event content Request.

A Reply is generated when a - state function + state callback returns with {reply,From,Reply} as one action(), @@ -1227,7 +1165,7 @@ handle_event(_, _, State, Data) -> ignoring if the destination node or gen_statem does not exist. The gen_statem calls the - state function with + state callback with event_type() cast and event content Msg. @@ -1341,18 +1279,18 @@ handle_event(_, _, State, Data) -> call/2 when the reply cannot be defined in the return value of a - state function. + state callback.

From must be the term from argument {call,From} to the - state function. + state callback. A reply or multiple replies canalso be sent using one or several reply_action()s from a - state function. + state callback.

@@ -1562,7 +1500,7 @@ handle_event(_, _, State, Data) -> for efficiency reasons, so this function is only called once after server start and after code change, but before the first - state function + state callback in the current code version is called. More occasions may be added in future versions of gen_statem. @@ -1707,7 +1645,7 @@ handle_event(_, _, State, Data) -> The Actions are executed when entering the first state just as for a - state function. + state callback.

If the initialization fails, @@ -1829,13 +1767,13 @@ handle_event(_, _, State, Data) -> Module:StateName(enter, OldState, Data) -> - StateFunctionEnterResult + StateEnterResult(StateName) Module:StateName(EventType, EventContent, Data) -> StateFunctionResult Module:handle_event(enter, OldState, State, Data) -> - HandleEventResult + StateEnterResult Module:handle_event(EventType, EventContent, State, Data) -> HandleEventResult @@ -1856,20 +1794,20 @@ handle_event(_, _, State, Data) -> data() - StateFunctionResult = - state_function_result() + StateEnterResult(StateName) = + state_enter_result(StateName) - StateFunctionEnterResult = - state_function_enter_result() + StateFunctionResult = + event_handler_result(state_name()) - HandleEventResult = - handle_event_result() + StateEnterResult = + state_enter_result(state()) - HandleEventEnterResult = - handle_event_enter_result() + HandleEventResult = + event_handler_result(state()) @@ -1888,7 +1826,7 @@ handle_event(_, _, State, Data) -> {call,From}, the caller waits for a reply. The reply can be sent from this or from any other - state function + state callback by returning with {reply,From,Reply} in Actions, in Replies, diff --git a/lib/stdlib/src/gen_statem.erl b/lib/stdlib/src/gen_statem.erl index bc33be22a2..5c750cb93d 100644 --- a/lib/stdlib/src/gen_statem.erl +++ b/lib/stdlib/src/gen_statem.erl @@ -44,18 +44,20 @@ -export( [wakeup_from_hibernate/3]). -%% Type exports for templates +%% Type exports for templates and callback modules -export_type( [event_type/0, - state_name/0, + init_result/0, callback_mode_result/0, state_function_result/0, - state_function_enter_result/0, handle_event_result/0, - handle_event_enter_result/0, + state_enter_result/1, + event_handler_result/1, + reply_action/0, + enter_action/0, action/0]). -%% Fix problem for doc build +%% Type that is exported just to be documented -export_type([transition_option/0]). %%%========================================================================== @@ -66,7 +68,7 @@ {To :: pid(), Tag :: term()}. % Reply-to specifier for call -type state() :: - state_name() | % For StateName/3 callback functios + state_name() | % For StateName/3 callback functions term(). % For handle_event/4 callback function -type state_name() :: atom(). @@ -140,67 +142,45 @@ {'reply', % Reply to a caller From :: from(), Reply :: term()}. --type state_function_result() :: - {'next_state', % {next_state,NextStateName,NewData,[]} - NextStateName :: state_name(), - NewData :: data()} | - {'next_state', % State transition, maybe to the same state - NextStateName :: state_name(), - NewData :: data(), - Actions :: [action()] | action()} | - keep_state_callback_result(). --type state_function_enter_result() :: - {'next_state', % {next_state,NextStateName,NewData,[]} - NextStateName :: state_name(), - NewData :: data()} | - {'next_state', % State transition, maybe to the same state - NextStateName :: state_name(), - NewData :: data(), - Actions :: [enter_action()] | enter_action()} | - keep_state_callback_enter_result(). +-type init_result() :: + {ok, state(), data()} | + {ok, state(), data(), [action()] | action()} | + 'ignore' | + {'stop', Reason :: term()}. +%% Old, not advertised +-type state_function_result() :: + event_handler_result(state_name()). -type handle_event_result() :: + event_handler_result(state()). +%% +-type state_enter_result(StateType) :: {'next_state', % {next_state,NextState,NewData,[]} - NextState :: state(), + State :: StateType, NewData :: data()} | {'next_state', % State transition, maybe to the same state - NextState :: state(), + State :: StateType, NewData :: data(), - Actions :: [action()] | action()} | - keep_state_callback_result(). --type handle_event_enter_result() :: + Actions :: [enter_action()] | enter_action()} | + state_callback_result(enter_action()). +-type event_handler_result(StateType) :: {'next_state', % {next_state,NextState,NewData,[]} - NextState :: state(), + NextState :: StateType, NewData :: data()} | {'next_state', % State transition, maybe to the same state - NextState :: state(), + NextState :: StateType, NewData :: data(), - Actions :: [enter_action()] | enter_action()} | - keep_state_callback_enter_result(). - --type keep_state_callback_result() :: - {'keep_state', % {keep_state,NewData,[]} - NewData :: data()} | - {'keep_state', % Keep state, change data - NewData :: data(), - Actions :: [action()] | action()} | - 'keep_state_and_data' | % {keep_state_and_data,[]} - {'keep_state_and_data', % Keep state and data -> only actions Actions :: [action()] | action()} | - common_state_callback_result(). - --type keep_state_callback_enter_result() :: + state_callback_result(action()). +-type state_callback_result(ActionType) :: {'keep_state', % {keep_state,NewData,[]} NewData :: data()} | {'keep_state', % Keep state, change data NewData :: data(), - Actions :: [enter_action()] | enter_action()} | + Actions :: [ActionType] | ActionType} | 'keep_state_and_data' | % {keep_state_and_data,[]} {'keep_state_and_data', % Keep state and data -> only actions - Actions :: [enter_action()] | enter_action()} | - common_state_callback_result(). - --type common_state_callback_result() :: + Actions :: [ActionType] | ActionType} | 'stop' | % {stop,normal} {'stop', % Stop the server Reason :: term()} | @@ -220,11 +200,7 @@ %% the server is not running until this function has returned %% an {ok, ...} tuple. Thereafter the state callbacks are called %% for all events to this server. --callback init(Args :: term()) -> - {ok, state(), data()} | - {ok, state(), data(), [action()] | action()} | - 'ignore' | - {'stop', Reason :: term()}. +-callback init(Args :: term()) -> init_result(). %% This callback shall return the callback mode of the callback module. %% @@ -244,11 +220,11 @@ 'enter', OldStateName :: state_name(), Data :: data()) -> - state_function_enter_result(); + state_enter_result('state_name'); (event_type(), EventContent :: term(), Data :: data()) -> - state_function_result(). + event_handler_result(state_name()). %% %% State callback for all states %% when callback_mode() =:= handle_event_function. @@ -257,12 +233,12 @@ OldState :: state(), State :: state(), % Current state Data :: data()) -> - handle_event_enter_result(); + state_enter_result(state()); (event_type(), EventContent :: term(), State :: state(), % Current state Data :: data()) -> - handle_event_result(). + event_handler_result(state()). %% Clean up before the server terminates. -callback terminate( diff --git a/lib/tools/emacs/erlang-skels.el b/lib/tools/emacs/erlang-skels.el index 95cc989c73..eeba7f34e9 100644 --- a/lib/tools/emacs/erlang-skels.el +++ b/lib/tools/emacs/erlang-skels.el @@ -931,18 +931,16 @@ Please see the function `tempo-define-template'.") "%% Whenever a gen_statem receives an event, the function " n "%% with the name of the current state (StateName) " n "%% is called to handle the event." n - "%%" n - "%% NOTE: If there is an exported function handle_event/4, it is called" n - "%% instead of StateName/3 functions like this!" n (erlang-skel-separator-end 2) - "-spec state_name(" n> - "'enter', OldState :: gen_statem:state_name()," n> + "-spec state_name('enter'," n> + "OldState :: atom()," n> "Data :: term()) ->" n> - "gen_statem:state_function_enter_result();" n - " (" n> - "gen_statem:event_type(), Msg :: term()," n> + "gen_statem:state_enter_result('state_name');" n> + "(gen_statem:event_type()," n> + "Msg :: term()," n> "Data :: term()) ->" n> - "gen_statem:state_function_result()." n + "gen_statem:event_handler_result(atom())." n + ;; "state_name({call,Caller}, _Msg, Data) ->" n> "{next_state, state_name, Data, [{reply,Caller,ok}]}." n n @@ -1043,18 +1041,18 @@ Please see the function `tempo-define-template'.") "%% @private" n "%% @doc" n "%% This function is called for every event a gen_statem receives." n - "%%" n - "%% NOTE: If there is no exported function handle_event/4," n - "%% StateName/3 functions are called instead!" n - (erlang-skel-separator-end 2) - "-spec handle_event(" n> - "'enter', OldState :: term()," n> - "State :: term(), Data :: term()) ->" n> - "gen_statem:handle_event_enter_result();" n - " (" n> - "gen_statem:event_type(), Msg :: term()," n> - "State :: term(), Data :: term()) ->" n> - "gen_statem:handle_event_result()." n + (erlang-skel-separator-end 2) + "-spec handle_event('enter'," n> + "OldState :: term()," n> + "State :: term()," n> + "Data :: term()) ->" n> + "gen_statem:state_enter_result(term());" n> + "(gen_statem:event_type()," n> + "Msg :: term()," n> + "State :: term()," n> + "Data :: term()) ->" n> + "gen_statem:event_handler_result(term())." n + ;; "handle_event({call,From}, _Msg, State, Data) ->" n> "{next_state, State, Data, [{reply,From,ok}]}." n n -- cgit v1.2.3