diff --git a/fsm.go b/fsm.go index 4465867..f3af5f2 100644 --- a/fsm.go +++ b/fsm.go @@ -228,6 +228,8 @@ func (f *FSM) SetState(state string) { // Can returns true if event can occur in the current state. func (f *FSM) Can(event string) bool { + f.eventMu.Lock() + defer f.eventMu.Unlock() f.stateMu.RLock() defer f.stateMu.RUnlock() _, ok := f.transitions[eKey{event, f.current}] diff --git a/fsm_test.go b/fsm_test.go index 4d4479a..6a8dadf 100644 --- a/fsm_test.go +++ b/fsm_test.go @@ -1038,3 +1038,31 @@ func ExampleFSM_Transition() { // closed // open } + +func TestEventAndCanInGoroutines(t *testing.T) { + fsm := NewFSM( + "closed", + Events{ + {Name: "open", Src: []string{"closed"}, Dst: "open"}, + {Name: "close", Src: []string{"open"}, Dst: "closed"}, + }, + Callbacks{}, + ) + wg := sync.WaitGroup{} + for i := 0; i < 10; i++ { + wg.Add(2) + go func(n int) { + defer wg.Done() + if n%2 == 0 { + _ = fsm.Event(context.Background(), "open") + } else { + _ = fsm.Event(context.Background(), "close") + } + }(i) + go func() { + defer wg.Done() + fsm.Can("close") + }() + } + wg.Wait() +}