Redigo is a golang client for the redis database. It uses struct Pool
to maintain a pool of connections. This struct holds a mutex lock for application putting and getting connection parallelly.
type Pool struct {
// ...
IdleTimeout time.Duration
mu sync.Mutex
// Stack of idleConn with most recently used at the front.
idle list.List
}
In its get
method, connection pool removes stale (idle timeout) connections firstly. When finding a stale connection, the pool pops it, releases lock, then closes connection, tries to acquire lock again.
func (p *Pool) get() (Conn, error) {
p.mu.Lock()
// Prune stale connections.
if timeout := p.IdleTimeout; timeout > 0 {
for i, n := 0, p.idle.Len(); i < n; i++ {
e := p.idle.Back()
if e == nil {
break
}
ic := e.Value.(idleConn)
if ic.t.Add(timeout).After(nowFunc()) {
break
}
p.idle.Remove(e)
p.release()
// Why does pool unlock and try to acquire lock again?
p.mu.Unlock()
// Close this stale connection.
ic.c.Close()
p.mu.Lock()
}
}
Why does pool unlock and try to acquire lock again, instead of just unlocking before function returns? I guess closing a connection may cost quite a lot time, which will slow down other goroutine waiting on this mutex.
Here is the whole Pool get method