Note that there are some explanatory texts on larger screens.

plurals
  1. POImplementing Hierarchical State Machines in C
    primarykey
    data
    text
    <p>I'm a bit confused about how to implement my state machine.<br> I already know it's hierarchical since some states share the same action.<br> I determine what I need to do by these parameters: </p> <ul> <li><strong>Class</strong> (Values are: <em>Base</em>, <em>Derived</em>, <em>Specific</em>)</li> <li><strong>OpCode</strong></li> <li><strong>Parameter 1 - optional</strong></li> <li><strong>Parameter 2 - optional</strong></li> </ul> <p>My hierarchy is determined by the Class and the <strong>OpCode</strong> represents the action.<br> <em>Derived</em> can use the <strong>OpCodes</strong> of <em>Base</em> and <em>Specific</em> can use <strong>OpCodes</strong> of both <em>Base</em> and <em>Derived</em>.<br> The naive implementation is the following: </p> <pre><code>void (*const state_table [MAX_CLASSES][MAX_OPCODES]) (state *) { {base_state1, base_state2, NULL, NULL}, {base_state1, base_state2, derived_state1, NULL}, {base_state1,base_state2, derived_state1, specific_state3}, }; void dispatch(state *s) { if (state_table[s-&gt;Class][s-&gt;OpCode] != NULL) state_table[s-&gt;Class][s-&gt;OpCode](s); } </code></pre> <p>This will turn unmaintainable really quick.<br> Is there another way to map the state to a superclass?</p> <p>EDIT:<br> Further calcualtion leads me to think that I'll probably use most if not all <strong>OpCodes</strong> but I will not use all of the <strong>Classes</strong> available to me.<br> Another clarification:<br> Some <strong>OpCodes</strong> might be shared through multiple derived and base <strong>Classes</strong>.<br> For example: </p> <ul> <li>I have a <strong>Class</strong> called <strong>Any</strong> which is a <em>Base</em> class. It has the <strong>OpCodes</strong>: <strong>STATE_ON</strong>, <strong>STATE_OFF</strong>, <strong>STATE_SET</strong>.</li> <li><p>I have another <strong>Class</strong> called <strong>MyGroup</strong> which is a <em>Derived</em> class. It has the <strong>OpCodes</strong>: <strong>STATE_FLIP</strong>, <strong>STATE_FLOP</strong>.</p></li> <li><p>The third <strong>Class</strong> is a <em>Specific</em> class called <strong>ThingInMyGroup</strong> which has the <strong>OpCode</strong>: <strong>STATE_FLIP_FLOP_AND_FLOOP</strong>.</p></li> </ul> <p>So a message with class <strong>Any</strong> is sent from the server, recieved in all clients and processed. </p> <p>A message with class <strong>MyGroup</strong> is sent from the server, recieved in all clients and processed only on clients that belong to <strong>MyGroup</strong>, any <strong>OpCodes</strong> that are valid for the <strong>Any</strong> class are valid for the <strong>MyGroup</strong> class. </p> <p>A message with class <strong>ThingInMyGroup</strong> is sent from the server, recieved in all clients and processed only on clients that belong to <strong>MyGroup</strong> and are a <strong>ThingInMyGroup*, any **OpCodes</strong> that are valid for the <strong>Any</strong> class and <strong>MyGroup</strong> class are valid for the <strong>ThingInMyGroup</strong> class. </p> <p>After a message is received the client will ACK/NACK accordingly.</p> <p>I prefer not to use switch cases or const arrays as they will become unmaintainable when they get bigger.<br> I need a flexible design that allows me: </p> <ol> <li>To specify which <strong>OpCodes</strong> are available for each <strong>Class</strong>.</li> <li>To specify a superclass for each <strong>Class</strong> and through that specification to allow me to call the function pointer that is represented by the current <strong>OpCode</strong>.</li> </ol>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload