@ -17,8 +17,8 @@ var (
)
const (
// Default represents the default state of the system.
Default StateType = ""
// EmptyState represents the default state of the system.
EmptyState StateType = ""
// NoOp represents a no-op event.
NoOp EventType = "NoOp"
@ -88,19 +88,19 @@ type StateMachine struct {
// ActionEntryFunc is a function that is called before an action is
// executed.
ActionEntryFunc func ( )
ActionEntryFunc func ( Notification )
// ActionExitFunc is a function that is called after an action is
// executed.
ActionExitFunc func ( )
// mutex ensures that only 1 event is processed by the state machine at
// any given time.
mutex sync . Mutex
// executed, it is called with the EventType returned by the action.
ActionExitFunc func ( NextEvent EventType )
// LastActionError is an error set by the last action executed.
LastActionError error
// DefaultObserver is the default observer that is notified when the
// state machine transitions between states.
DefaultObserver * CachedObserver
// previous represents the previous state.
previous StateType
@ -114,13 +114,35 @@ type StateMachine struct {
// observerMutex ensures that observers are only added or removed
// safely.
observerMutex sync . Mutex
// mutex ensures that only 1 event is processed by the state machine at
// any given time.
mutex sync . Mutex
}
// NewStateMachine creates a new state machine.
func NewStateMachine ( states States ) * StateMachine {
func NewStateMachine ( states States , observerSize int ) * StateMachine {
return NewStateMachineWithState ( states , EmptyState , observerSize )
}
// NewStateMachineWithState creates a new state machine and sets the initial
// state.
func NewStateMachineWithState ( states States , current StateType ,
observerSize int ) * StateMachine {
observers := [ ] Observer { }
var defaultObserver * CachedObserver
if observerSize > 0 {
defaultObserver = NewCachedObserver ( observerSize )
observers = append ( observers , defaultObserver )
}
return & StateMachine {
States : states ,
observers : make ( [ ] Observer , 0 ) ,
current : current ,
DefaultObserver : defaultObserver ,
observers : observers ,
}
}
@ -189,18 +211,20 @@ func (s *StateMachine) SendEvent(event EventType, eventCtx EventContext) error {
// Notify the state machine's observers.
s . observerMutex . Lock ( )
for _ , observer := range s . observers {
observer . Notify ( Notification {
notification := Notification {
PreviousState : s . previous ,
NextState : s . current ,
Event : event ,
} )
}
for _ , observer := range s . observers {
observer . Notify ( notification )
}
s . observerMutex . Unlock ( )
// Execute the state machines ActionEntryFunc.
if s . ActionEntryFunc != nil {
s . ActionEntryFunc ( )
s . ActionEntryFunc ( notification )
}
// Execute the current state's entry function
@ -219,7 +243,7 @@ func (s *StateMachine) SendEvent(event EventType, eventCtx EventContext) error {
// Execute the state machines ActionExitFunc.
if s . ActionExitFunc != nil {
s . ActionExitFunc ( )
s . ActionExitFunc ( nextEvent )
}
// If the next event is a no-op, we're done.