diff options
author | Raimo Niskanen <raimo@erlang.org> | 2020-02-21 15:30:03 +0100 |
---|---|---|
committer | Raimo Niskanen <raimo@erlang.org> | 2020-02-21 15:30:03 +0100 |
commit | 28f9bd0dac889a532fde4a8b1d534fbdb0593703 (patch) | |
tree | 7d50f609d16b6add2ae249e60aa4bc2139fcc5ee | |
parent | cbe4d292faa540db9a07f6f8659a84d608f05845 (diff) | |
download | erlang-28f9bd0dac889a532fde4a8b1d534fbdb0593703.tar.gz |
Document change|push|pop _callback_module
-rw-r--r-- | lib/stdlib/doc/src/gen_statem.xml | 81 | ||||
-rw-r--r-- | system/doc/design_principles/statem.xml | 45 |
2 files changed, 113 insertions, 13 deletions
diff --git a/lib/stdlib/doc/src/gen_statem.xml b/lib/stdlib/doc/src/gen_statem.xml index 39fc565ff8..c12ad2deef 100644 --- a/lib/stdlib/doc/src/gen_statem.xml +++ b/lib/stdlib/doc/src/gen_statem.xml @@ -101,10 +101,10 @@ </item> <item> In OTP 22.3 the possibility to change the callback module - with action - <seealso marker="#type-action"> - <c>change_callback_module</c> - </seealso> + with actions + <seealso marker="#type-action"><c>change_callback_module</c></seealso>, + <seealso marker="#type-action"><c>push_callback_module</c></seealso> and + <seealso marker="#type-action"><c>pop_callback_module</c></seealso>, was added. </item> </list> @@ -750,8 +750,10 @@ handle_event(_, _, State, Data) -> <seealso marker="#Module:callback_mode/0"><c>Module:callback_mode/0</c></seealso> is called when starting the <c>gen_statem</c>, after code change - and after changing the callback module with action - <seealso marker="#type-action"><c>change_callback_module</c></seealso>. + and after changing the callback module with any of the actions + <seealso marker="#type-action"><c>change_callback_module</c></seealso>, + <seealso marker="#type-action"><c>push_callback_module</c></seealso> or + <seealso marker="#type-action"><c>pop_callback_module</c></seealso>. The result is cached for subsequent calls to <seealso marker="#state callback">state callbacks</seealso>. </p> @@ -1191,7 +1193,9 @@ handle_event(_, _, State, Data) -> an event inserted this way from any external event. </p> </item> - <tag><c>change_callback_module</c></tag> + <tag> + <c>change_callback_module</c> + </tag> <item> <p> Changes the callback module to @@ -1231,6 +1235,32 @@ handle_event(_, _, State, Data) -> from the old module. </p> </item> + <tag> + <c>push_callback_module</c><br /> + </tag> + <item> + <p> + Pushes the current callback module + to the top of an internal stack of callback modules + and changes the callback module to + <c><anno>NewModule</anno></c>. + Otherwise like + <c>{change_callback_module, NewModule}</c> + above. + </p> + </item> + <tag> + <c>pop_callback_module</c> + </tag> + <item> + Pops the top module from the internal stack of + callback modules and changes the callback module + to be the popped module. + If the stack is empty the server fails. + Otherwise like + <c>{change_callback_module, NewModule}</c> + above. + </item> </taglist> </desc> </datatype> @@ -2017,8 +2047,10 @@ handle_event(_, _, State, Data) -> returns. A change of the callback module happens when a <seealso marker="#state callback"><em>state callback</em></seealso> - returns the action - <seealso marker="#type-action"><c>change_callback_module</c></seealso>. + returns any of the actions + <seealso marker="#type-action"><c>change_callback_module</c></seealso>, + <seealso marker="#type-action"><c>push_callback_module</c></seealso> or + <seealso marker="#type-action"><c>pop_callback_module</c></seealso>. </p> <p> The <c>CallbackMode</c> is either just @@ -2125,6 +2157,37 @@ handle_event(_, _, State, Data) -> will not be honoured, most probably causing a server crash. </p> + <p> + If the server changes callback module using any of the actions + <seealso marker="#type-action"><c>change_callback_module</c></seealso>, + <seealso marker="#type-action"><c>push_callback_module</c></seealso> or + <seealso marker="#type-action"><c>pop_callback_module</c></seealso>, + be aware that it is always the current callback module that + will get this callback call. That the current callback module + handles the current state and data update should be no surprise, + but it must be able to handle even parts of + the state and data that it is not familiar with, + somehow. + </p> + <p> + In the supervisor + <seealso marker="doc/design_principles:sup_princ#child-specification">child specification</seealso> + there is a list of modules which is recommended to contain + only the callback module. + For a <c>gen_statem</c> with multiple callback modules + there is no real need to list all of them, + it may not even be possible since the list could change + after code upgrade. + If this list would contain only the start callback module, + as recommended, what is important is to upgrade <em>that</em> module + whenever a <em>synchronized code replacement</em> is done. + Then the release handler concludes that an upgrade + that upgrades <em>that</em> module needs to suspend, + code change, and resume any server whose child specification + declares that it is using <em>that</em> module. + And again; the <em>current</em> callback module will get the + <c>Module:code_change/4</c> call. + </p> </desc> </func> diff --git a/system/doc/design_principles/statem.xml b/system/doc/design_principles/statem.xml index f657e8cb00..d6d907de45 100644 --- a/system/doc/design_principles/statem.xml +++ b/system/doc/design_principles/statem.xml @@ -185,15 +185,17 @@ State(S) x Event(E) -> Actions(A), State(S')</pre> </p> <p> The <em>callback module</em> can be changed for a running server - using the - <seealso marker="#Transition Actions">transition action</seealso> - <seealso marker="stdlib:gen_statem#type-action"><c>{change_callback_module, NewModule}</c></seealso>. + using any of the + <seealso marker="#Transition Actions">transition actions</seealso> + <seealso marker="stdlib:gen_statem#type-action"><c>{change_callback_module, NewModule}</c></seealso>, + <seealso marker="stdlib:gen_statem#type-action"><c>{push_callback_module, NewModule}</c></seealso> or + <seealso marker="stdlib:gen_statem#type-action"><c>pop_callback_module</c></seealso>. Note that this is a pretty esotheric thing to do... The origin for this feature is a protocol that after version negotiation branches off into quite different state machines depending on the protocol version. There <i>might</i> be other use cases. - <i>Beware</i> that the <c>NewModule</c> + <i>Beware</i> that the new callback module completely replaces the previous behaviour module, so all relevant callback functions has to handle the state and data from the previous callback module. @@ -664,6 +666,41 @@ State(S) x Event(E) -> Actions(A), State(S')</pre> but it can <i>not</i> be done from a <seealso marker="#State Enter Calls"><em>state enter call</em></seealso>. </item> + <tag> + <seealso marker="stdlib:gen_statem#type-action"> + <c>{push_callback_module, NewModule}</c> + </seealso> + </tag> + <item> + Push the current <em>callback module</em> + to the top of an internal stack of callback modules + and set the new + <seealso marker="#Callback Module"> + <em>callback module</em> + </seealso> + for the running server. + Otherwise like + <c>{change_callback_module, NewModule}</c> + above. + </item> + <tag> + <seealso marker="stdlib:gen_statem#type-action"> + <c>pop_callback_module</c> + </seealso> + </tag> + <item> + Pop the top module from + the internal stack of callback modules + and set it to be the new + <seealso marker="#Callback Module"> + <em>callback module</em> + </seealso> + for the running server. + If the stack is empty the server fails. + Otherwise like + <c>{change_callback_module, NewModule}</c> + above. + </item> </taglist> <p> For details, see the <c>gen_statem(3)</c> |