.. _StateModels:

.. raw:: html

   <script>ODSA.SETTINGS.DISP_MOD_COMP = true;ODSA.SETTINGS.MODULE_NAME = "StateModels";ODSA.SETTINGS.MODULE_LONG_NAME = "State Models in UML";ODSA.SETTINGS.MODULE_CHAPTER = "Introduction to Computer Systems"; ODSA.SETTINGS.BUILD_DATE = "2021-06-14 17:15:25"; ODSA.SETTINGS.BUILD_CMAP = false;JSAV_OPTIONS['lang']='en';JSAV_EXERCISE_OPTIONS['code']='java';</script>


.. |--| unicode:: U+2013   .. en dash
.. |---| unicode:: U+2014  .. em dash, trimming surrounding whitespace
   :trim:


.. This file is part of the OpenCSF eTextbook project. It was
.. auto-generated by scripts from the OpenDSA eTextbook project.
.. See https://OpenCSF.org for more details. OpenCSF is distributed
.. under a Creative Commons Attribution-NonCommercial 4.0 International
.. License (see http://creativecommons.org/licenses/by-nc/4.0/),
.. Copyright (c) 2019-2021 by Michael S. Kirkpatrick. OpenDSA is
.. distributed under an MIT open source license, Copyright (c) 2012-2021
.. by the OpenDSA Project Contributors.

.. avmetadata::
   :author: Michael S. Kirkpatrick
   :requires:
   :satisfies: State Models
   :topic: State Models

State Models in UML
===================

:term:`States <state>` are unique and meaningful configurations of the system. In some cases, a
state may be defined by a particular combination of values assigned to certain variables. In others,
several sets of possible values are grouped together within a single state. :term:`Transitions <transition>`
denote changes from one state to another. Transitions are triggered by events and can
have :term:`effects <effect>` that produce some visible behavior.

.. _StateModelsUML:

.. figure:: Images/CSF-Images.1.10.png
   :align: right
   :width: 90%
   :figwidth: 40%
   :alt: A UML state model for a streaming media player

   A UML state model for a streaming media player

UML :term:`state models <state model>` are one way to visualize the behavior of a system from the
perspective of its states and transitions. :num:`Figure #StateModelsUML` shows an example of
a state model for a streaming media player. The player has four states: ``Connecting``,
``Buffering``, ``Playing``, and ``Closing``. The arrows between states denote transitions, with the
following events defined: ``Connected``, ``Ready``, ``Suspended``, ``Cancelled``, and ``Finished``.
These events correspond to both user input, as well as issues such as running out of buffered data
(the infamous *buffering* that frustrates users). Effects of transitions are denoted after the "/"
in the label, so the ``Connected`` event causes the effect ``Start`` Loading to retrieve the first
bytes to buffer.

The solid circle at the top indicates an *initial state* where the system starts, where the
outlined circle in the bottom right denotes a *final state*. Some models may have more than
one initial state or more than one final state. Observe that, in this case, there is no event
labeled for the transitions from the initial state or into the final state. These are considered to
be *empty transitions* and are not associated with any particular event.

State models are effective tools for illustrating the general flow between states and the overall
structure of the system. As is true of any model, state models convey some information while
omitting other details. Specifically, state models omit information relating to the sequence and the
timing of the states or the events. [#f4]_ For instance, in the case of the ``Closing`` state, the
system could remain in that state for 1 ms or 10 hours before proceeding to the final state; both
interpretations would be valid. Additionally, one execution of the system could completely avoid the
``Playing`` state, while another execution switches between ``Playing`` and ``Buffering`` 100 times.
If more precise information is needed about the timing or the sequence of transitions, then other
models will need to be used.


State Space Explosion
---------------------

Interpreting a well-defined state model should be intuitive; the states should be meaningfully
different, and the transitions between them should be logical. However, constructing state models is
not a straightforward process and requires a significant amount of practice to do well. One of the
most intuitive challenges is how to deal with the :term:`state space explosion` problem, which
arises when the number of states in the model increase so dramatically that the model is no longer useful.

.. _StSpExplosion:

.. topic:: Example

   .. figure:: Images/CSF-Images-Example.png
      :align: left
      :width: 100%
      :alt: Decorative example icon

   One technique that can be used to evaluate a program for correctness is known as *model
   checking*, which analyzes a formal specification of a state model. For instance, based on that
   model, can we determine if the program will ever reach a state where a pointer variable is set to
   ``NULL`` and the pointer is dereferenced? If so, we can examine the sequence of steps to get to
   that state to debug the program.

   To start this process, we need a model of the software program. Consider a naïve approach that
   creates a unique state for every possible value of every possible variable. If the system contained
   only a single 8-bit ``char`` (denoted ``ch1``) the state model would consist of :math:`2^8 = 256`
   states. Add a second ``char`` (denoted ``ch2``) and the model increases to :math:`2^{16} = 16,536`
   states. This fact arises from the observation that we must (without further knowledge of the
   program) consider all 256 possible values of ``ch2`` when ``ch1`` is 0, then another 256 values
   when ``ch1`` is 1, and so on. If we convert both variables to the 32-bit ``int`` type and the model
   has :math:`2^{64} = 1.84 * 10^{19}` states, just to represent two variables.


This approach illustrates the dangers of the state space explosion problem. Because every additional
bit of information doubles the number of possible states, state models can easily become unusably
large. As such, it is critical to group configurations into meaningful states (such as positive and
negative values for a key variable. However, determining what is meaningful is inherently
application-specific and requires the judgment of someone with relevant expertise.

Implementing Finite State Machines
----------------------------------

There are multiple ways to turn a state model into an executable *finite state machine (FSM)* [#f5]_
implementation. In fact, this is such a common practice that there are automated tools that will
take a state model specification and generate executable code. The disadvantage with these types of
tools is that the code is not necessarily readable. In this section, we will step through an example
implementation that illustrates some of the key aspects of how these translations
work.

`Code Listing 1.1 <#cl1-1>`_ shows the key declarations of a header file for a generic FSM. Event and state
types are declared as integer types, while the action type is declared as a function pointer that
takes a pointer to a FSM as an instance. The action type can be used for transition effects (as used
in this example), as well as for state entry or exit activities. Lines 15 – 21 declare our FSM
structure. Within the FSM, we will keep track of the current state, the number of events (used for
error checking), and a pointer to a ``transition`` function; this function will take in the current
state and event as arguments, then return the next state and the associated transition effect (if
any) to the caller. (Note that many implementations of FSM do not use this kind of ``struct``, using
global variables for the current state and transition lookup tables. Our struct is meant to
encapsulate this in a way that we support multiple concurrent FSM instances if needed.)

.. _cl1-1:

.. codeinclude:: IntroConcSys/CodeListing-1-1.h
   :linenos: true

Lastly, there is a single ``handle_event()`` function declared that will serve as the interface
between the FSM and the entity controlling it. `Code Listing 1.2 <#cl1-2>`_ shows the structure of this
function. The function starts by confirming that the event number is valid. If so,
``handle_event()`` will call the FSM's ``transition`` function to look up information about the
current event. This function will return -1 if there is no transition defined for that particular
state and event combination. I.e., events that invalid in the current state are ignored. Otherwise,
the effect (if any) will be executed on line 21 and the FSM's state will be updated (line 22).

.. _cl1-2:

.. codeinclude:: IntroConcSys/CodeListing-1-2.c
   :linenos: true

`Code Listing 1.1 <#cl1-1>`_ and `1.2 <#cl1-2>`_ provided a generic structure for any FSM. We now want to turn our
attention to the state model that we used in :num:`Figure #StateModelsUML` to model a simple media
player. The first step is to create a table form of the transitions between states. `Table 1.1 <#tbl1-1>`_ shows
the table of the transitions for :num:`Figure #StateModelsUML`. Each row of the table
corresponds to a possible current state in the model. Each column within that row represents the
next state based on a particular event, as well as any related transition effect. For instance, if
the Suspend event occurs while the FSM is in the ``Playing`` state, the next state would be
``Buffering`` and the ``pause_play()`` effect would be; if the ``Finish`` event had occurred
instead, the next state would be ``Closing`` and there would be no effect. Any of the boxes in this
table that do not have entries indicate that there is no valid transition for that state and event combination.

.. _tbl1-1:

.. raw:: html

   <center>
   <div class="row">
   <div class="col-12">
     <table class="table table-bordered">
       <thead class="jmu-dark-purple-bg text-light">
         <tr>
           <th class="py-0 center" width="17%">&nbsp;</th>
           <th class="py-0 center" width="17%"><code>Connect</code></th>
           <th class="py-0 center" width="17%"><code>Suspend</code></th>
           <th class="py-0 center" width="17%"><code>Ready</code></th>
           <th class="py-0 center" width="17%"><code>Finish</code></th>
           <th class="py-0 center"><code>Cancel</code></th>
         </tr>
       </thead>
       <tbody>
         <tr>
           <td class="bg-light align-middle"><strong><code>Connecting</code></strong></td>
           <td class="center align-middle"><code>Buffering / start_load</code></td>
           <td>&nbsp;</td>
           <td>&nbsp;</td>
           <td>&nbsp;</td>
           <td>&nbsp;</td>
         </tr>
         <tr>
           <td class="bg-light align-middle"><strong><code>Buffering</code></strong></td>
           <td>&nbsp;</td>
           <td>&nbsp;</td>
           <td class="center align-middle"><code>Playing / resume</code></td>
           <td>&nbsp;</td>
           <td><code>Closing</code></td>
         </tr>
         <tr>
           <td class="bg-light align-middle"><strong><code>Playing</code></strong></td>
           <td>&nbsp;</td>
           <td class="center align-middle"><code>Buffering / pause_play</code></td>
           <td>&nbsp;</td>
           <td class="center align-middle"><code>Closing</code></td>
           <td>&nbsp;</td>
         </tr>
         <tr>
           <td class="bg-light align-middle"><strong><code>Closing</code></strong></td>
           <td>&nbsp;</td>
           <td>&nbsp;</td>
           <td>&nbsp;</td>
           <td>&nbsp;</td>
           <td>&nbsp;</td>
         </tr>
       </tbody>
     </table>
     <p>
     Table 1.1: Representing the transitions between states in Figure 1.5.1
     </p>
   </center>

`Code Listing 1.3 <#cl1-3>`_ documents how to turn `Table 1.1 <#tbl1-1>`_ into executable code. To start, line 6 defines an
enum type for the specific states for this FSM instance, and line 7 creates a preprocessor constant
for the number of states. Recall from `Code Listing 1.1 <#cl1-1>`_ that states are, ultimately, integer types.
The advantage of using an ``enum`` is that it allows us to refer to states by names (e.g., ``CONN``
for the ``Connecting`` state) instead of integers, which would be otherwise meaningless and likely
to cause errors. Line 8 defines a constant for the number of events based on similar enum for events
but defined elsewhere.

Lines 11 – 17 encode the transitions defined in `Table 1.1 <#tbl1-1>`_. In the enum defined on line 6, the last
value (``NST``) is used to indicate *no state*, meaning that there is no transition defined. These
values in this two-dimensional array correspond to the blanks in the table. Lines 20 – 26 define a
similar lookup table, but for the transition effects. Since effects are actions that do something,
`Code Listing 1.1 <#cl1-1>`_ defined the ``action_t`` type as a function pointer; as a result, the empty values
in the table are ``NULL`` pointers.

.. _cl1-3:

.. codeinclude:: IntroConcSys/CodeListing-1-3.c
   :linenos: true

Note that `Code Listing 1.3 <#cl1-3>`_ declared both ``_transition`` (the transition table) and ``_effect`` (the
effects table) as ``static``. This design choice helps to create a modular approach, as these tables
will not be accessed directly outside of this file. `Code Listing 1.4 <#cl1-4>`_ shows how these tables will be
accessed through the ``media_transition()`` function, also declared ``static`` in the same file.
Given the FSM's current state, if the entry in the ``_transition`` table for the specified event is
not defined, return -1 to indicate no transition should be taken. Otherwise, set the ``effect``
call-by-reference parameter to the appropriate function and return the next state. Note that, just
like the ``_transition`` and ``_effect`` tables, the ``media_transition()`` function cannot be
accessed outside the current file. The ``media_init()`` function provides the link. When a new
instance of this FSM is needed, the controller can use this function to get a new ``fsm_t``, which
contains a pointer to the ``media_transition()`` function.

.. _cl1-4:

.. codeinclude:: IntroConcSys/CodeListing-1-4.c
   :linenos: true

Finally, `Code Listing 1.5 <#cl1-5>`_ shows how a controlling program would create a FSM instance and send it
events. Since all of the information about the transitions and effects is encapsulated inside the
FSM struct, the controller just needs to focus on the logic of which event to send to the FSM.
Recall from `Code Listing 1.2 <#cl1-2>`_ that ``handle_event()`` passes the event through the FSM's
``fsm->transition`` function pointer to determine the state change and effect function. Since
``handle_event()`` ignores invalid transitions, sending the wrong event (such as on line 7) cannot
cause an error in the FSM.

.. _cl1-5:

.. codeinclude:: IntroConcSys/CodeListing-1-5.c
   :linenos: true

.. [#f4] There are more advanced state models, known as timed automata, that do explicitly
   incorporate time within their representation. However, we will not be using those models in this book.

.. [#f5] The term state model is often used synonymously with finite-state machine or finite-state
   automata. Here, we are using the terms separately just to distinguish between the non-executable
   model and its executable implementation.

.. avembed:: Exercises/IntroConcSys/StateModelSumm.html ka
   :module: StateModels
   :points: 1.0
   :required: True
   :exer_opts: JXOP-debug=true&amp;JOP-lang=en&amp;JXOP-code=java
   :long_name: State model summary questions
   :threshold: 3

