@@ -58,21 +58,23 @@ type checkOutResult struct {
58
58
59
59
// pool is a wrapper of resource pool that follows the CMAP spec for connection pools
60
60
type pool struct {
61
- address address.Address
62
- opts []ConnectionOption
63
- conns * resourcePool // pool for non-checked out connections
64
- generation * poolGenerationMap
65
- monitor * event.PoolMonitor
66
-
67
- // Must be accessed using the atomic package.
68
- connected int32
61
+ // These fields must be accessed using the atomic package and should be at the beginning of the struct.
62
+ // - atomic bug: https://pkg.go.dev/sync/atomic#pkg-note-BUG
63
+ // - suggested layout: https://go101.org/article/memory-layout.html
64
+ connected int64
69
65
pinnedCursorConnections uint64
70
66
pinnedTransactionConnections uint64
71
67
72
68
nextid uint64
73
69
opened map [uint64 ]* connection // opened holds all of the currently open connections.
74
70
sem * semaphore.Weighted
75
71
sync.Mutex
72
+
73
+ address address.Address
74
+ opts []ConnectionOption
75
+ conns * resourcePool // pool for non-checked out connections
76
+ generation * poolGenerationMap
77
+ monitor * event.PoolMonitor
76
78
}
77
79
78
80
// connectionExpiredFunc checks if a given connection is stale and should be removed from the resource pool
@@ -87,7 +89,7 @@ func connectionExpiredFunc(v interface{}) bool {
87
89
}
88
90
89
91
switch {
90
- case atomic .LoadInt32 (& c .pool .connected ) != connected :
92
+ case atomic .LoadInt64 (& c .pool .connected ) != connected :
91
93
c .expireReason = event .ReasonPoolClosed
92
94
case c .closed ():
93
95
// A connection would only be closed if it encountered a network error during an operation and closed itself.
@@ -208,7 +210,7 @@ func (p *pool) stale(c *connection) bool {
208
210
209
211
// connect puts the pool into the connected state, allowing it to be used and will allow items to begin being processed from the wait queue
210
212
func (p * pool ) connect () error {
211
- if ! atomic .CompareAndSwapInt32 (& p .connected , disconnected , connected ) {
213
+ if ! atomic .CompareAndSwapInt64 (& p .connected , disconnected , connected ) {
212
214
return ErrPoolConnected
213
215
}
214
216
p .generation .connect ()
@@ -218,7 +220,7 @@ func (p *pool) connect() error {
218
220
219
221
// disconnect disconnects the pool and closes all connections including those both in and out of the pool
220
222
func (p * pool ) disconnect (ctx context.Context ) error {
221
- if ! atomic .CompareAndSwapInt32 (& p .connected , connected , disconnecting ) {
223
+ if ! atomic .CompareAndSwapInt64 (& p .connected , connected , disconnecting ) {
222
224
return ErrPoolDisconnected
223
225
}
224
226
@@ -267,7 +269,7 @@ func (p *pool) disconnect(ctx context.Context) error {
267
269
_ = p .removeConnection (pc , event .ReasonPoolClosed )
268
270
_ = p .closeConnection (pc ) // We don't care about errors while closing the connection.
269
271
}
270
- atomic .StoreInt32 (& p .connected , disconnected )
272
+ atomic .StoreInt64 (& p .connected , disconnected )
271
273
p .conns .clearTotal ()
272
274
273
275
if p .monitor != nil {
@@ -301,7 +303,7 @@ func (p *pool) makeNewConnection() (*connection, string, error) {
301
303
})
302
304
}
303
305
304
- if atomic .LoadInt32 (& p .connected ) != connected {
306
+ if atomic .LoadInt64 (& p .connected ) != connected {
305
307
// Manually publish a ConnectionClosed event here because the connection reference hasn't been stored and we
306
308
// need to ensure each ConnectionCreated event has a corresponding ConnectionClosed event.
307
309
if p .monitor != nil {
@@ -348,7 +350,7 @@ func (p *pool) get(ctx context.Context) (*connection, error) {
348
350
ctx = context .Background ()
349
351
}
350
352
351
- if atomic .LoadInt32 (& p .connected ) != connected {
353
+ if atomic .LoadInt64 (& p .connected ) != connected {
352
354
if p .monitor != nil {
353
355
p .monitor .Event (& event.PoolEvent {
354
356
Type : event .GetFailed ,
@@ -380,7 +382,7 @@ func (p *pool) get(ctx context.Context) (*connection, error) {
380
382
// This loop is so that we don't end up with more than maxPoolSize connections if p.conns.Maintain runs between
381
383
// calling p.conns.Get() and making the new connection
382
384
for {
383
- if atomic .LoadInt32 (& p .connected ) != connected {
385
+ if atomic .LoadInt64 (& p .connected ) != connected {
384
386
if p .monitor != nil {
385
387
p .monitor .Event (& event.PoolEvent {
386
388
Type : event .GetFailed ,
@@ -395,7 +397,7 @@ func (p *pool) get(ctx context.Context) (*connection, error) {
395
397
connVal := p .conns .Get ()
396
398
if c , ok := connVal .(* connection ); ok && connVal != nil {
397
399
// call connect if not connected
398
- if atomic .LoadInt32 (& c .connected ) == initialized {
400
+ if atomic .LoadInt64 (& c .connected ) == initialized {
399
401
c .connect (ctx )
400
402
}
401
403
@@ -499,12 +501,12 @@ func (p *pool) closeConnection(c *connection) error {
499
501
return ErrWrongPool
500
502
}
501
503
502
- if atomic .LoadInt32 (& c .connected ) == connected {
504
+ if atomic .LoadInt64 (& c .connected ) == connected {
503
505
c .closeConnectContext ()
504
506
_ = c .wait () // Make sure that the connection has finished connecting
505
507
}
506
508
507
- if ! atomic .CompareAndSwapInt32 (& c .connected , connected , disconnected ) {
509
+ if ! atomic .CompareAndSwapInt64 (& c .connected , connected , disconnected ) {
508
510
return nil // We're closing an already closed connection
509
511
}
510
512
0 commit comments