forked from mirror/redis
101 lines
1.7 KiB
Go
101 lines
1.7 KiB
Go
|
package pool
|
||
|
|
||
|
import (
|
||
|
"sync"
|
||
|
"sync/atomic"
|
||
|
)
|
||
|
|
||
|
type connList struct {
|
||
|
cns []*Conn
|
||
|
mx sync.Mutex
|
||
|
len int32 // atomic
|
||
|
size int32
|
||
|
}
|
||
|
|
||
|
func newConnList(size int) *connList {
|
||
|
return &connList{
|
||
|
cns: make([]*Conn, 0, size),
|
||
|
size: int32(size),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (l *connList) Len() int {
|
||
|
return int(atomic.LoadInt32(&l.len))
|
||
|
}
|
||
|
|
||
|
// Reserve reserves place in the list and returns true on success. The
|
||
|
// caller must add or remove connection if place was reserved.
|
||
|
func (l *connList) Reserve() bool {
|
||
|
len := atomic.AddInt32(&l.len, 1)
|
||
|
reserved := len <= l.size
|
||
|
if !reserved {
|
||
|
atomic.AddInt32(&l.len, -1)
|
||
|
}
|
||
|
return reserved
|
||
|
}
|
||
|
|
||
|
// Add adds connection to the list. The caller must reserve place first.
|
||
|
func (l *connList) Add(cn *Conn) {
|
||
|
l.mx.Lock()
|
||
|
l.cns = append(l.cns, cn)
|
||
|
l.mx.Unlock()
|
||
|
}
|
||
|
|
||
|
// Remove closes connection and removes it from the list.
|
||
|
func (l *connList) Remove(cn *Conn) error {
|
||
|
defer l.mx.Unlock()
|
||
|
l.mx.Lock()
|
||
|
|
||
|
if cn == nil {
|
||
|
atomic.AddInt32(&l.len, -1)
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
for i, c := range l.cns {
|
||
|
if c == cn {
|
||
|
l.cns = append(l.cns[:i], l.cns[i+1:]...)
|
||
|
atomic.AddInt32(&l.len, -1)
|
||
|
return cn.Close()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if l.closed() {
|
||
|
return nil
|
||
|
}
|
||
|
panic("conn not found in the list")
|
||
|
}
|
||
|
|
||
|
func (l *connList) Replace(cn, newcn *Conn) error {
|
||
|
defer l.mx.Unlock()
|
||
|
l.mx.Lock()
|
||
|
|
||
|
for i, c := range l.cns {
|
||
|
if c == cn {
|
||
|
l.cns[i] = newcn
|
||
|
return cn.Close()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if l.closed() {
|
||
|
return newcn.Close()
|
||
|
}
|
||
|
panic("conn not found in the list")
|
||
|
}
|
||
|
|
||
|
func (l *connList) Close() (retErr error) {
|
||
|
l.mx.Lock()
|
||
|
for _, c := range l.cns {
|
||
|
if err := c.Close(); err != nil {
|
||
|
retErr = err
|
||
|
}
|
||
|
}
|
||
|
l.cns = nil
|
||
|
atomic.StoreInt32(&l.len, 0)
|
||
|
l.mx.Unlock()
|
||
|
return retErr
|
||
|
}
|
||
|
|
||
|
func (l *connList) closed() bool {
|
||
|
return l.cns == nil
|
||
|
}
|