forked from mirror/redis
75 lines
1.2 KiB
Go
75 lines
1.2 KiB
Go
package pool
|
|
|
|
import (
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
// connStack is used as a LIFO to maintain free connections
|
|
type connStack struct {
|
|
cns []*Conn
|
|
free chan struct{}
|
|
mu sync.Mutex
|
|
}
|
|
|
|
func newConnStack(max int) *connStack {
|
|
return &connStack{
|
|
cns: make([]*Conn, 0, max),
|
|
free: make(chan struct{}, max),
|
|
}
|
|
}
|
|
|
|
func (s *connStack) Len() int { return len(s.free) }
|
|
|
|
func (s *connStack) Push(cn *Conn) {
|
|
s.mu.Lock()
|
|
s.cns = append(s.cns, cn)
|
|
s.mu.Unlock()
|
|
s.free <- struct{}{}
|
|
}
|
|
|
|
func (s *connStack) ShiftStale(idleTimeout time.Duration) *Conn {
|
|
select {
|
|
case <-s.free:
|
|
s.mu.Lock()
|
|
defer s.mu.Unlock()
|
|
|
|
if cn := s.cns[0]; cn.IsStale(idleTimeout) {
|
|
copy(s.cns, s.cns[1:])
|
|
s.cns = s.cns[:len(s.cns)-1]
|
|
return cn
|
|
}
|
|
|
|
s.free <- struct{}{}
|
|
return nil
|
|
default:
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func (s *connStack) Pop() *Conn {
|
|
select {
|
|
case <-s.free:
|
|
return s.pop()
|
|
default:
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func (s *connStack) PopWithTimeout(d time.Duration) *Conn {
|
|
select {
|
|
case <-s.free:
|
|
return s.pop()
|
|
case <-time.After(d):
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func (s *connStack) pop() (cn *Conn) {
|
|
s.mu.Lock()
|
|
ci := len(s.cns) - 1
|
|
cn, s.cns = s.cns[ci], s.cns[:ci]
|
|
s.mu.Unlock()
|
|
return
|
|
}
|