multi: replace manual CAS with sync.Once in component start/stop
This guarantees callers that the method will not return until it has executed completely at least once.
This commit is contained in:
1 parent
f802ebddba
commit
aea52f4bef
5 files changed
+68
-70
No files matched your search
+16
-10
@@ -6,7 +6,6 @@ import (
|
||||
"math/rand"
|
||||
"net"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec"
|
||||
@@ -105,9 +104,8 @@ func (c channelState) ConnectedNodes() map[NodeID]struct{} {
|
||||
//
|
||||
// TODO(roasbeef): prob re-word
|
||||
type Agent struct {
|
||||
// Only to be used atomically.
|
||||
started uint32
|
||||
stopped uint32
|
||||
started sync.Once
|
||||
stopped sync.Once
|
||||
|
||||
// cfg houses the configuration state of the Ant.
|
||||
cfg Config
|
||||
@@ -197,10 +195,14 @@ func New(cfg Config, initialState []Channel) (*Agent, error) {
|
||||
// Start starts the agent along with any goroutines it needs to perform its
|
||||
// normal duties.
|
||||
func (a *Agent) Start() error {
|
||||
if !atomic.CompareAndSwapUint32(&a.started, 0, 1) {
|
||||
return nil
|
||||
}
|
||||
var err error
|
||||
a.started.Do(func() {
|
||||
err = a.start()
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *Agent) start() error {
|
||||
rand.Seed(time.Now().Unix())
|
||||
log.Infof("Autopilot Agent starting")
|
||||
|
||||
@@ -213,10 +215,14 @@ func (a *Agent) Start() error {
|
||||
// Stop signals the Agent to gracefully shutdown. This function will block
|
||||
// until all goroutines have exited.
|
||||
func (a *Agent) Stop() error {
|
||||
if !atomic.CompareAndSwapUint32(&a.stopped, 0, 1) {
|
||||
return nil
|
||||
}
|
||||
var err error
|
||||
a.stopped.Do(func() {
|
||||
err = a.stop()
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *Agent) stop() error {
|
||||
log.Infof("Autopilot Agent stopping")
|
||||
|
||||
close(a.quit)
|
||||
|
||||
+10
-17
@@ -3,7 +3,6 @@ package autopilot
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec"
|
||||
"github.com/lightningnetwork/lnd/lnwallet"
|
||||
@@ -40,8 +39,8 @@ type ManagerCfg struct {
|
||||
// It implements the autopilot grpc service, which is used to get data about
|
||||
// the running autopilot, and give it relevant information.
|
||||
type Manager struct {
|
||||
started uint32 // To be used atomically.
|
||||
stopped uint32 // To be used atomically.
|
||||
started sync.Once
|
||||
stopped sync.Once
|
||||
|
||||
cfg *ManagerCfg
|
||||
|
||||
@@ -64,27 +63,21 @@ func NewManager(cfg *ManagerCfg) (*Manager, error) {
|
||||
|
||||
// Start starts the Manager.
|
||||
func (m *Manager) Start() error {
|
||||
if !atomic.CompareAndSwapUint32(&m.started, 0, 1) {
|
||||
return nil
|
||||
}
|
||||
|
||||
m.started.Do(func() {})
|
||||
return nil
|
||||
}
|
||||
|
||||
// Stop stops the Manager. If an autopilot agent is active, it will also be
|
||||
// stopped.
|
||||
func (m *Manager) Stop() error {
|
||||
if !atomic.CompareAndSwapUint32(&m.stopped, 0, 1) {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := m.StopAgent(); err != nil {
|
||||
log.Errorf("Unable to stop pilot: %v", err)
|
||||
}
|
||||
|
||||
close(m.quit)
|
||||
m.wg.Wait()
|
||||
m.stopped.Do(func() {
|
||||
if err := m.StopAgent(); err != nil {
|
||||
log.Errorf("Unable to stop pilot: %v", err)
|
||||
}
|
||||
|
||||
close(m.quit)
|
||||
m.wg.Wait()
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user