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

multi: switch to Go atomic types #3218

Closed
wants to merge 5 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
13 changes: 6 additions & 7 deletions addrmgr/addrmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,12 @@ type AddrManager struct {
// serialized and saved to the file system.
addrChanged bool

// started signals whether the address manager has been started. Its value
// is 1 or more if started.
started int32
// started signals whether the address manager has been started.
started atomic.Bool

// shutdown signals whether a shutdown of the address manager has been
// initiated. Its value is 1 or more if a shutdown is done or in progress.
shutdown int32
// initiated.
shutdown atomic.Bool

// The following fields are used for lifecycle management of the
// address manager.
Expand Down Expand Up @@ -623,7 +622,7 @@ func (a *AddrManager) deserializePeers(filePath string) error {
// This function is safe for concurrent access.
func (a *AddrManager) Start() {
// Return early if the address manager has already been started.
if atomic.AddInt32(&a.started, 1) != 1 {
if !a.started.CompareAndSwap(false, true) {
return
}

Expand All @@ -642,7 +641,7 @@ func (a *AddrManager) Start() {
// This function is safe for concurrent access.
func (a *AddrManager) Stop() error {
// Return early if the address manager has already been stopped.
if atomic.AddInt32(&a.shutdown, 1) != 1 {
if !a.shutdown.CompareAndSwap(false, true) {
log.Warnf("Address manager is already in the process of shutting down")
return nil
}
Expand Down
2 changes: 1 addition & 1 deletion addrmgr/go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/decred/dcrd/addrmgr/v2

go 1.17
go 1.19

require (
github.com/decred/dcrd/chaincfg/chainhash v1.0.4
Expand Down
1 change: 0 additions & 1 deletion addrmgr/go.sum
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/decred/dcrd/chaincfg/chainhash v1.0.4 h1:zRCv6tdncLfLTKYqu7hrXvs7hW+8FO/NvwoFvGsrluU=
github.com/decred/dcrd/chaincfg/chainhash v1.0.4/go.mod h1:hA86XxlBWwHivMvxzXTSD0ZCG/LoYsFdWnCekkTMCqY=
github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y=
Expand Down
23 changes: 10 additions & 13 deletions connmgr/connmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,11 @@ const (
// ConnReq is the connection request to a network address. If permanent, the
// connection will be retried on disconnection.
type ConnReq struct {
// The following variables must only be used atomically.
//
// id is the unique identifier for this connection request.
//
// state is the current connection state for this connection request.
id uint64
state uint32
id atomic.Uint64
state atomic.Uint32

// The following fields are owned by the connection handler and must not
// be accessed outside of it.
Expand All @@ -87,17 +85,17 @@ type ConnReq struct {

// updateState updates the state of the connection request.
func (c *ConnReq) updateState(state ConnState) {
atomic.StoreUint32(&c.state, uint32(state))
c.state.Store(uint32(state))
}

// ID returns a unique identifier for the connection request.
func (c *ConnReq) ID() uint64 {
return atomic.LoadUint64(&c.id)
return c.id.Load()
}

// State is the connection state of the requested connection.
func (c *ConnReq) State() ConnState {
return ConnState(atomic.LoadUint32(&c.state))
return ConnState(c.state.Load())
}

// String returns a human-readable string for the connection request.
Expand Down Expand Up @@ -209,11 +207,9 @@ type handleForEachConnReq struct {

// ConnManager provides a manager to handle network connections.
type ConnManager struct {
// The following variables must only be used atomically.
//
// connReqCount is the number of connection requests that have been made and
// is primarily used to assign unique connection request IDs.
connReqCount uint64
connReqCount atomic.Uint64

// assignIDMtx synchronizes the assignment of an ID to a connection request
// with overall connection request count above.
Expand Down Expand Up @@ -467,7 +463,8 @@ func (cm *ConnManager) newConnReq(ctx context.Context) {
return
}

c := &ConnReq{id: atomic.AddUint64(&cm.connReqCount, 1)}
c := &ConnReq{}
c.id.Store(cm.connReqCount.Add(1))

// Submit a request of a pending connection attempt to the connection
// manager. By registering the id before the connection is even
Expand Down Expand Up @@ -545,7 +542,7 @@ func (cm *ConnManager) Connect(ctx context.Context, c *ConnReq) {
var doRegisterPending bool
cm.assignIDMtx.Lock()
if c.ID() == 0 {
atomic.StoreUint64(&c.id, atomic.AddUint64(&cm.connReqCount, 1))
c.id.Store(cm.connReqCount.Add(1))
doRegisterPending = true
}
cm.assignIDMtx.Unlock()
Expand Down Expand Up @@ -716,7 +713,7 @@ func (cm *ConnManager) Run(ctx context.Context) {
// Start enough outbound connections to reach the target number when not
// in manual connect mode.
if cm.cfg.GetNewAddress != nil {
curConnReqCount := atomic.LoadUint64(&cm.connReqCount)
curConnReqCount := cm.connReqCount.Load()
for i := curConnReqCount; i < uint64(cm.cfg.TargetOutbound); i++ {
go cm.newConnReq(ctx)
}
Expand Down
10 changes: 5 additions & 5 deletions connmgr/connmanager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -405,11 +405,11 @@ func TestNetworkFailure(t *testing.T) {
var closeOnce sync.Once
const targetOutbound = 5
const retryTimeout = time.Millisecond * 5
var dials uint32
var dials atomic.Uint32
reachedMaxFailedAttempts := make(chan struct{})
connMgrDone := make(chan struct{})
errDialer := func(ctx context.Context, network, addr string) (net.Conn, error) {
totalDials := atomic.AddUint32(&dials, 1)
totalDials := dials.Add(1)
if totalDials >= maxFailedAttempts {
closeOnce.Do(func() { close(reachedMaxFailedAttempts) })
<-connMgrDone
Expand Down Expand Up @@ -447,7 +447,7 @@ func TestNetworkFailure(t *testing.T) {
// Ensure the number of dial attempts does not exceed the max number of
// failed attempts plus the number of potential retries during the
// additional waiting period.
gotDials := atomic.LoadUint32(&dials)
gotDials := dials.Load()
wantMaxDials := uint32(maxFailedAttempts + targetOutbound)
if gotDials > wantMaxDials {
t.Fatalf("unexpected number of dials - got %v, want <= %v", gotDials,
Expand All @@ -468,11 +468,11 @@ func TestMultipleFailedConns(t *testing.T) {
}()

const targetFailed = 5
var dials uint32
var dials atomic.Uint32
var closeOnce sync.Once
hitTargetFailed := make(chan struct{})
errDialer := func(ctx context.Context, network, addr string) (net.Conn, error) {
totalDials := atomic.AddUint32(&dials, 1)
totalDials := dials.Add(1)
if totalDials >= targetFailed {
closeOnce.Do(func() { close(hitTargetFailed) })
}
Expand Down
2 changes: 1 addition & 1 deletion connmgr/go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/decred/dcrd/connmgr/v3

go 1.17
go 1.19

require (
github.com/decred/dcrd/wire v1.6.0
Expand Down
1 change: 0 additions & 1 deletion connmgr/go.sum
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/decred/dcrd/chaincfg/chainhash v1.0.4 h1:zRCv6tdncLfLTKYqu7hrXvs7hW+8FO/NvwoFvGsrluU=
github.com/decred/dcrd/chaincfg/chainhash v1.0.4/go.mod h1:hA86XxlBWwHivMvxzXTSD0ZCG/LoYsFdWnCekkTMCqY=
github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y=
Expand Down
8 changes: 4 additions & 4 deletions database/ffldb/interface_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2163,17 +2163,17 @@ func testConcurrentClose(tc *testContext) bool {
// Start up a few readers and wait for them to acquire views. Each
// reader waits for a signal to complete to ensure the transactions stay
// open until they are explicitly signalled to be closed.
var activeReaders int32
var activeReaders atomic.Int32
numReaders := 3
started := make(chan struct{})
finishReaders := make(chan struct{})
resultChan := make(chan bool, numReaders+1)
reader := func() {
err := tc.db.View(func(tx database.Tx) error {
atomic.AddInt32(&activeReaders, 1)
activeReaders.Add(1)
started <- struct{}{}
<-finishReaders
atomic.AddInt32(&activeReaders, -1)
activeReaders.Add(-1)
return nil
})
if err != nil {
Expand Down Expand Up @@ -2212,7 +2212,7 @@ func testConcurrentClose(tc *testContext) bool {
// active readers open.
time.AfterFunc(time.Millisecond*250, func() { close(finishReaders) })
<-dbClosed
if nr := atomic.LoadInt32(&activeReaders); nr != 0 {
if nr := activeReaders.Load(); nr != 0 {
tc.t.Errorf("Close did not appear to block with active "+
"readers: %d active", nr)
return false
Expand Down
2 changes: 1 addition & 1 deletion database/go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/decred/dcrd/database/v3

go 1.17
go 1.19

require (
github.com/decred/dcrd/chaincfg/chainhash v1.0.4
Expand Down
1 change: 0 additions & 1 deletion database/go.sum
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412 h1:w1UutsfOrms1J05zt7ISrnJIXKzwaspym5BTKGx93EI=
github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412/go.mod h1:WPjqKcmVOxf0XSf3YxCJs6N6AOSrOx3obionmG7T0y0=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dchest/siphash v1.2.3 h1:QXwFc8cFOR2dSa/gE6o/HokBMWtLUaNDVd+22aKHeEA=
github.com/dchest/siphash v1.2.3/go.mod h1:0NvQU092bT0ipiFN++/rXm69QG9tVxLAlQHIXMPAkHc=
github.com/decred/base58 v1.0.5 h1:hwcieUM3pfPnE/6p3J100zoRfGkQxBulZHo7GZfOqic=
Expand Down
2 changes: 1 addition & 1 deletion peer/go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/decred/dcrd/peer/v3

go 1.17
go 1.19

require (
github.com/davecgh/go-spew v1.1.1
Expand Down
2 changes: 0 additions & 2 deletions peer/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,8 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/dchest/siphash v1.2.3 h1:QXwFc8cFOR2dSa/gE6o/HokBMWtLUaNDVd+22aKHeEA=
github.com/dchest/siphash v1.2.3/go.mod h1:0NvQU092bT0ipiFN++/rXm69QG9tVxLAlQHIXMPAkHc=
github.com/decred/base58 v1.0.5 h1:hwcieUM3pfPnE/6p3J100zoRfGkQxBulZHo7GZfOqic=
github.com/decred/base58 v1.0.5/go.mod h1:s/8lukEHFA6bUQQb/v3rjUySJ2hu+RioCzLukAVkrfw=
github.com/decred/dcrd/chaincfg/chainhash v1.0.4 h1:zRCv6tdncLfLTKYqu7hrXvs7hW+8FO/NvwoFvGsrluU=
github.com/decred/dcrd/chaincfg/chainhash v1.0.4/go.mod h1:hA86XxlBWwHivMvxzXTSD0ZCG/LoYsFdWnCekkTMCqY=
github.com/decred/dcrd/chaincfg/v3 v3.2.0/go.mod h1:2rHW1TKyFmwZTVBLoU/Cmf0oxcpBjUEegbSlBfrsriI=
github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y=
github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
github.com/decred/dcrd/crypto/ripemd160 v1.0.2 h1:TvGTmUBHDU75OHro9ojPLK+Yv7gDl2hnUvRocRCjsys=
Expand Down
Loading