protofsm: add thread-safe IsRunning method to StateMachine

This commit introduces a new `IsRunning()` method to the `StateMachine`.
This method allows callers to safely query whether the state machine
is currently active after it has been started and before it has been
stopped.

To ensure thread-safety, the internal `running` status flag is
implemented using `atomic.Bool` (from `sync/atomic`). Without atomic
operations, concurrent accesses to a simple boolean flag from different
goroutines (e.g., one goroutine calling `IsRunning()` while another
executes `Start()` or `Stop()`) could lead to stale reads or data races.
This commit is contained in:
ffranr
2025-06-02 01:03:26 +01:00
committed by Oliver Gugger
parent 19b2e42e18
commit 6f4811fc14

View File

@@ -4,6 +4,7 @@ import (
"context"
"fmt"
"sync"
"sync/atomic"
"time"
"github.com/btcsuite/btcd/btcec/v2"
@@ -150,8 +151,14 @@ type StateMachine[Event any, Env Environment] struct {
gm fn.GoroutineManager
quit chan struct{}
// startOnce and stopOnce are used to ensure that the state machine is
// only started and stopped once.
startOnce sync.Once
stopOnce sync.Once
// running is a flag that indicates if the state machine is currently
// running.
running atomic.Bool
}
// ErrorReporter is an interface that's used to report errors that occur during
@@ -221,6 +228,8 @@ func (s *StateMachine[Event, Env]) Start(ctx context.Context) {
_ = s.gm.Go(ctx, func(ctx context.Context) {
s.driveMachine(ctx)
})
s.running.Store(true)
})
}
@@ -230,6 +239,8 @@ func (s *StateMachine[Event, Env]) Stop() {
s.stopOnce.Do(func() {
close(s.quit)
s.gm.Stop()
s.running.Store(false)
})
}
@@ -333,6 +344,11 @@ func (s *StateMachine[Event, Env]) RemoveStateSub(sub StateSubscriber[
_ = s.newStateEvents.RemoveSubscriber(sub)
}
// IsRunning returns true if the state machine is currently running.
func (s *StateMachine[Event, Env]) IsRunning() bool {
return s.running.Load()
}
// executeDaemonEvent executes a daemon event, which is a special type of event
// that can be emitted as part of the state transition function of the state
// machine. An error is returned if the type of event is unknown.