forked from mirror/redis
73 lines
1.1 KiB
Go
73 lines
1.1 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(timeout time.Duration) *Conn {
|
||
|
select {
|
||
|
case <-s.free:
|
||
|
s.mu.Lock()
|
||
|
defer s.mu.Unlock()
|
||
|
|
||
|
if cn := s.cns[0]; cn.IsStale(timeout) {
|
||
|
copy(s.cns, s.cns[1:])
|
||
|
s.cns = s.cns[:len(s.cns)-1]
|
||
|
return cn
|
||
|
}
|
||
|
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
|
||
|
}
|