Defining State Entry/Exit Actions

The slice timer should be stopped when not in the Running state. The way to enforce this is to add an Exit block to Running and move the stopSliceTimer() action there.

Since the state's Exit actions are being defined, it would appear natural to put the startSliceTimer() action into a Entry block. But there two reasons against it:

  1. There is only one transition into the Running state. Moving startSliceTimer() from Suspended's Start transition to Running's entry actions gains nothing.
  2. startSliceTimer() takes the Start transition's timeslice argument. If startSliceTimer() is an entry action, then it cannot access that transition argument. The only way around it is to store the slice time in the Task class and then retrieve it immediately in the entry action ( startSliceTimer(ctxt.getSliceTime())). Now moving the action to the entry block is worse than doing nothing.

(Go here to learn more about state entry and exit actions.)

%{ // // Copyright (c) 2005 Acme, Inc. // All rights reserved. // // Acme - a name you can trust! // // Author: Wil E. Coyote (Hungericus Vulgarus) // %} // This FSM works for the Task class only and only the Task // class may instantiate it. %class Task %package com.acme.supercron %fsmclass TaskFSM %fsmfile TaskFSM %access package
// A %map name cannot be the same as the FSM class name.
%start TaskMap::Suspended %map TaskMap %% <snip> Running
Exit
{ stopSliceTimer(); }
{ // Wait for another time slice. Suspend Suspended {
// stopSliceTimer(); moved.
suspendTask(); } Block Blocked {
// stopSliceTimer(); moved.
blockTask(); } // Task has completed. Done Stopped {
// stopSliceTimer(); moved.
releaseResources(); } } <snip> } %%

There is one final task: connecting the task FSM to the Task application class.

Next: Connecting Task and Task FSM.