From 4f70db6849bddad83a01f1d77af70346491694bf Mon Sep 17 00:00:00 2001 From: Yuxuan 'fishy' Wang Date: Mon, 13 Jul 2020 15:38:11 -0700 Subject: [PATCH] Use atomic.Value instead of lock for ConnPool.lastDialError This makes the reading and writing of lastDialError from the pool faster, as atomic.Value is much more lightweight than the mutex. Note that using error in atomic.Value directly could cause panics, because errors could have inconsistent types. Thus wrap them with a simple struct. --- internal/pool/pool.go | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/internal/pool/pool.go b/internal/pool/pool.go index cabcba1..f0cb519 100644 --- a/internal/pool/pool.go +++ b/internal/pool/pool.go @@ -60,13 +60,16 @@ type Options struct { IdleCheckFrequency time.Duration } +type lastDialErrorWrap struct { + err error +} + type ConnPool struct { opt *Options dialErrorsNum uint32 // atomic - lastDialErrorMu sync.RWMutex - lastDialError error + lastDialError atomic.Value queue chan struct{} @@ -204,16 +207,15 @@ func (p *ConnPool) tryDial() { } func (p *ConnPool) setLastDialError(err error) { - p.lastDialErrorMu.Lock() - p.lastDialError = err - p.lastDialErrorMu.Unlock() + p.lastDialError.Store(&lastDialErrorWrap{err: err}) } func (p *ConnPool) getLastDialError() error { - p.lastDialErrorMu.RLock() - err := p.lastDialError - p.lastDialErrorMu.RUnlock() - return err + err, _ := p.lastDialError.Load().(*lastDialErrorWrap) + if err != nil { + return err.err + } + return nil } // Get returns existed connection from the pool or creates a new one.