Skip to content

Commit

Permalink
Fixed data race between Can() and Event() (#107)
Browse files Browse the repository at this point in the history
  • Loading branch information
denisvaloha authored Aug 9, 2024
1 parent b2f0ab5 commit 5a8ac86
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 0 deletions.
2 changes: 2 additions & 0 deletions fsm.go
Original file line number Diff line number Diff line change
Expand Up @@ -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}]
Expand Down
28 changes: 28 additions & 0 deletions fsm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}

0 comments on commit 5a8ac86

Please sign in to comment.