Documentation ¶
Overview ¶
Package `stepper` allows you to set StepPoints in simulation code that will pause if some condition is satisfied. While paused, the simulation waits for the top-level process (the user interface) to tell it to continue. Once a continue notification is received, the simulation continues on its way, with all internal state exactly as it was when the StepPoint was hit, without having to explicitly save anything.
There are two "running" states, Stepping and Running. The difference is that in the Running state, unless there is a Stop request, the application will forego the possibly-complex checking for a pause. The actual StepPoint function is written to make checking as quick as possible. Although the program will not stop at StepPoints without interaction, it will pause if RunState is Paused. The main difference between Paused and Stopped is that in the Paused state, the application waits for a state change, whereas in the Stopped state, the Stepper exits, and no application state is preserved. After entering Stopped, the controlling program (i.e., the user interface) should make sure that everything is properly reinitialized before running again.
Usage Basics ¶
The Stepper struct includes an integer field, "StepGrain", which controls whether it will actually pause. The StepPoint function checks that its argument is equal to the current StepGrain, and if so, calls the PauseNotifyFn callback with whatever state information was set up when the PauseNotifyFn was registered. It then enters a loop, waiting for a change in the RunState field of the Stepper. If it sees that RunState has become Stopped, it return true, and the caller (i.e., the simulation) should exit the current run. If it sees that RunState has changed to either Running or Stepping, it returns false, and the caller should continue.
Before running, the caller should call Stepper.New() to get a fresh, initialized Stepper, and must also call RegisterPauseNotifyFn to designate a callback to be invoked when StepPoint is called with a value of grain that matches the value of StepGrain set in the struct. Internally, StepGrain is just an integer, but the intention is that callers will define a StepGrain enumerated type to designate meaningful points at which to pause. Note that the current implementation makes no use of the actual values of StepGrain, i.e., the fact that one value is greater than another has no effect. This might change in a future version.
In addition to the required PauseNotifyFn callback, there is an optional StopCheckFn callback. This callback can check any state information that it likes, and if it returns true, the PauseNotifyFn will be invoked.
Whether or not a StopCheckFn has been set, if RunState is Stepping and the grain argument matches StepGrain, StepPoint decrements the value of StepsPer. If stepsLeft goes to zero, PauseNotifyFn is called, and the Stepper goes into a wait loop, waiting for RunState to be something other than Paused. If RunState becomes Stopped, StepPoint exits with a value of true, indicating that the caller should end the current run. If the new state is either Running or Stepping, StepPoint returns false, indicating that the caller should continue.
Index ¶
- Variables
- type PauseNotifyFn
- type RunState
- type Stepper
- func (st *Stepper) Active() bool
- func (st *Stepper) Enter(state RunState)
- func (st *Stepper) Init() *Stepper
- func (st *Stepper) Pause()
- func (st *Stepper) ResetParams(nSteps int, grain int)
- func (st *Stepper) Start(grain int, nSteps int)
- func (st *Stepper) StepPoint(grain int) (stop bool)
- func (st *Stepper) Stop()
- type StopCheckFn
Constants ¶
This section is empty.
Variables ¶
var KiT_RunState = kit.Enums.AddEnum(RunStateN, kit.NotBitFlag, nil)
Functions ¶
This section is empty.
Types ¶
type PauseNotifyFn ¶
type PauseNotifyFn func()
A PauseNotifyFn is a callback that will be invoked if the program enters the Paused state. NOTE! The PauseNotifyFn is called with the Stepper's lock held, so it must not call any Stepper methods that try to take the lock on entry, or a deadlock will result.
type RunState ¶
type RunState int
const ( Stopped RunState = iota // execution is stopped. The Stepper is NOT waiting, so running again is basically a restart. The only way to go from Running or Stepping to Stopped is to explicitly call Stop(). Program state will not be preserved once the Stopped state is entered. Paused // execution is paused. The sim is waiting for further instructions, and can continue, or stop. Stepping // the application is running, but will pause if it hits a StepPoint that matches the current StepGrain. Running // the application is running, and will NOT pause at StepPoints. It will pause if a stop has been requested. RunStateN )
type Stepper ¶
type Stepper struct { RunState RunState `desc:"current run state"` StepGrain int `desc:"granularity of one step. No enum type here so clients can define their own"` StepsPer int `desc:"number of steps to execute before returning"` PauseNotifyFn PauseNotifyFn `view:"-" desc:"function to deal with any changes on client side when paused after stepping"` StopCheckFn StopCheckFn `view:"-" desc:"function to test for special stopping conditions"` // contains filtered or unexported fields }
The Stepper struct contains all of the state info for stepping a program, enabling step points. where the running application can be suspended with no loss of state.
func New ¶
func New() *Stepper
New makes a new Stepper. Always call this to create a Stepper, so that initialization will be run correctly.
func (*Stepper) Active ¶
Active checks that the application is either Running or Stepping (neither Paused nor Stopped). This needs to use the State mutex because it checks two different fields.
func (*Stepper) Enter ¶
Enter unconditionally enters the specified RunState. It broadcasts a stateChange, which should be picked up by a paused application.
func (*Stepper) Init ¶
Init puts everything into a good state before starting a run Init is called automatically by New, and should be called before running again after calling Stop (not Pause). Init should not be called explicitly when creating a new Stepper--the preferred way to initialize is to call New.
func (*Stepper) Pause ¶
func (st *Stepper) Pause()
Pause sets RunState to Paused. The running program will actually pause at the next StepPoint call.
func (*Stepper) ResetParams ¶
Reset StepsPer and StepGrain parameters
func (*Stepper) Start ¶
Start enters the Stepping run state. This should be called at the start of a run only.
func (*Stepper) StepPoint ¶
StepPoint checks for possible pause or stop. If the application is: Running: keep going with no further examination of state. Stopped: return true, and the application should return (i.e., stop completely). Stepping: check to see if we should pause (if StepGrain matches, decrement stepsLeft, stop if <= 0). Paused: wait for state change.
type StopCheckFn ¶
A StopCheckFn is a callback to check whether an arbitrary condition has been matched. If a StopCheckFn returns true, the program is suspended with a RunState of Paused, and will remain so until the RunState changes to Stepping, Running, or Stopped. As noted below for the PauseNotifyFn, the StopCheckFn is called with the Stepper's lock held.