Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

upgrade go version #47

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,5 @@ _testmain.go

.DS_Store
.wercker

.idea/
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
language: go

go:
- "1.11"
- "1.13"

services:
- docker
Expand Down
4 changes: 2 additions & 2 deletions event.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ type Event struct {
Event string

// Src is the state before the transition.
Src string
Src State

// Dst is the state after the transition.
Dst string
Dst State

// Err is an optional error that can be returned from a callback.
Err error
Expand Down
66 changes: 20 additions & 46 deletions fsm.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ package fsm

import (
"strings"
"sync"
)

// transitioner is an interface for the FSM's transition function.
Expand All @@ -39,10 +38,10 @@ type transitioner interface {
// It has to be created with NewFSM to function properly.
type FSM struct {
// current is the state that the FSM is currently in.
current string
current State

// transitions maps events and source states to destination states.
transitions map[eKey]string
transitions map[eKey]State

// callbacks maps events and targers to callback functions.
callbacks map[cKey]Callback
Expand All @@ -53,10 +52,6 @@ type FSM struct {
// transitionerObj calls the FSM's transition() function.
transitionerObj transitioner

// stateMu guards access to the current state.
stateMu sync.RWMutex
// eventMu guards access to Event() and Transition().
eventMu sync.Mutex
}

// EventDesc represents an event when initializing the FSM.
Expand All @@ -70,11 +65,11 @@ type EventDesc struct {

// Src is a slice of source states that the FSM must be in to perform a
// state transition.
Src []string
Src []State

// Dst is the destination state that the FSM will be in if the transition
// succeds.
Dst string
Dst State
}

// Callback is a function type that callbacks should use. Event is the current
Expand Down Expand Up @@ -123,11 +118,11 @@ type Callbacks map[string]Callback
// which version of the callback will end up in the internal map. This is due
// to the psuedo random nature of Go maps. No checking for multiple keys is
// currently performed.
func NewFSM(initial string, events []EventDesc, callbacks map[string]Callback) *FSM {
func NewFSM(initial State, events []EventDesc, callbacks map[string]Callback) *FSM {
f := &FSM{
transitionerObj: &transitionerStruct{},
current: initial,
transitions: make(map[eKey]string),
transitions: make(map[eKey]State),
callbacks: make(map[cKey]Callback),
}

Expand All @@ -136,9 +131,9 @@ func NewFSM(initial string, events []EventDesc, callbacks map[string]Callback) *
allStates := make(map[string]bool)
for _, e := range events {
for _, src := range e.Src {
f.transitions[eKey{e.Name, src}] = e.Dst
allStates[src] = true
allStates[e.Dst] = true
f.transitions[eKey{e.Name, src.GetName()}] = e.Dst
allStates[src.GetName()] = true
allStates[e.Dst.GetName()] = true
}
allEvents[e.Name] = true
}
Expand Down Expand Up @@ -199,44 +194,34 @@ func NewFSM(initial string, events []EventDesc, callbacks map[string]Callback) *
}

// Current returns the current state of the FSM.
func (f *FSM) Current() string {
f.stateMu.RLock()
defer f.stateMu.RUnlock()
func (f *FSM) Current() State {
return f.current
}

// Is returns true if state is the current state.
func (f *FSM) Is(state string) bool {
f.stateMu.RLock()
defer f.stateMu.RUnlock()
return state == f.current
func (f *FSM) Is(state State) bool {
return f.current.Equal(state)
}

// SetState allows the user to move to the given state from current state.
// The call does not trigger any callbacks, if defined.
func (f *FSM) SetState(state string) {
f.stateMu.Lock()
defer f.stateMu.Unlock()
func (f *FSM) SetState(state State) {
f.current = state
return
}

// Can returns true if event can occur in the current state.
func (f *FSM) Can(event string) bool {
f.stateMu.RLock()
defer f.stateMu.RUnlock()
_, ok := f.transitions[eKey{event, f.current}]
_, ok := f.transitions[eKey{event, f.current.GetName()}]
return ok && (f.transition == nil)
}

// AvailableTransitions returns a list of transitions avilable in the
// current state.
func (f *FSM) AvailableTransitions() []string {
f.stateMu.RLock()
defer f.stateMu.RUnlock()
var transitions []string
for key := range f.transitions {
if key.src == f.current {
if f.current.IsNamed(key.src) {
transitions = append(transitions, key.event)
}
}
Expand Down Expand Up @@ -267,21 +252,16 @@ func (f *FSM) Cannot(event string) bool {
// The last error should never occur in this situation and is a sign of an
// internal bug.
func (f *FSM) Event(event string, args ...interface{}) error {
f.eventMu.Lock()
defer f.eventMu.Unlock()

f.stateMu.RLock()
defer f.stateMu.RUnlock()

if f.transition != nil {
return InTransitionError{event}
}

dst, ok := f.transitions[eKey{event, f.current}]
dst, ok := f.transitions[eKey{event, f.current.GetName()}]
if !ok {
for ekey := range f.transitions {
if ekey.event == event {
return InvalidEventError{event, f.current}
return InvalidEventError{event, f.current.GetName()}
}
}
return UnknownEventError{event}
Expand All @@ -294,16 +274,14 @@ func (f *FSM) Event(event string, args ...interface{}) error {
return err
}

if f.current == dst {
if f.current.Equal(dst) {
f.afterEventCallbacks(e)
return NoTransitionError{e.Err}
}

// Setup the transition, call it later.
f.transition = func() {
f.stateMu.Lock()
f.current = dst
f.stateMu.Unlock()

f.enterStateCallbacks(e)
f.afterEventCallbacks(e)
Expand All @@ -317,9 +295,7 @@ func (f *FSM) Event(event string, args ...interface{}) error {
}

// Perform the rest of the transition, if not asynchronous.
f.stateMu.RUnlock()
err = f.doTransition()
f.stateMu.RLock()
if err != nil {
return InternalError{}
}
Expand All @@ -329,8 +305,6 @@ func (f *FSM) Event(event string, args ...interface{}) error {

// Transition wraps transitioner.transition.
func (f *FSM) Transition() error {
f.eventMu.Lock()
defer f.eventMu.Unlock()
return f.doTransition()
}

Expand Down Expand Up @@ -377,7 +351,7 @@ func (f *FSM) beforeEventCallbacks(e *Event) error {
// leaveStateCallbacks calls the leave_ callbacks, first the named then the
// general version.
func (f *FSM) leaveStateCallbacks(e *Event) error {
if fn, ok := f.callbacks[cKey{f.current, callbackLeaveState}]; ok {
if fn, ok := f.callbacks[cKey{f.current.GetName(), callbackLeaveState}]; ok {
fn(e)
if e.canceled {
return CanceledError{e.Err}
Expand All @@ -399,7 +373,7 @@ func (f *FSM) leaveStateCallbacks(e *Event) error {
// enterStateCallbacks calls the enter_ callbacks, first the named then the
// general version.
func (f *FSM) enterStateCallbacks(e *Event) {
if fn, ok := f.callbacks[cKey{f.current, callbackEnterState}]; ok {
if fn, ok := f.callbacks[cKey{f.current.GetName(), callbackEnterState}]; ok {
fn(e)
}
if fn, ok := f.callbacks[cKey{"", callbackEnterState}]; ok {
Expand Down
Loading