Revert "Prevent time.Timer memory leak by using a singleton timer in bufferedPipes. Fix #137"

This reverts commit 4baca256
This commit is contained in:
Andy Wang 2020-12-05 21:26:41 +00:00
parent 4baca256f7
commit a3520c1018
No known key found for this signature in database
GPG Key ID: 181B49F9F38F3374
2 changed files with 6 additions and 36 deletions

View File

@ -20,14 +20,11 @@ type datagramBufferedPipe struct {
rwCond *sync.Cond rwCond *sync.Cond
wtTimeout time.Duration wtTimeout time.Duration
rDeadline time.Time rDeadline time.Time
timer *time.Timer
} }
func NewDatagramBufferedPipe() *datagramBufferedPipe { func NewDatagramBufferedPipe() *datagramBufferedPipe {
d := &datagramBufferedPipe{ d := &datagramBufferedPipe{
rwCond: sync.NewCond(&sync.Mutex{}), rwCond: sync.NewCond(&sync.Mutex{}),
timer: time.NewTimer(0),
} }
return d return d
} }
@ -48,7 +45,7 @@ func (d *datagramBufferedPipe) Read(target []byte) (int, error) {
if delta <= 0 { if delta <= 0 {
return 0, ErrTimeout return 0, ErrTimeout
} }
d.broadcastAfter(delta) time.AfterFunc(delta, d.rwCond.Broadcast)
} }
if len(d.pLens) > 0 { if len(d.pLens) > 0 {
@ -84,12 +81,12 @@ func (d *datagramBufferedPipe) WriteTo(w io.Writer) (n int64, err error) {
} }
if d.wtTimeout == 0 { if d.wtTimeout == 0 {
// if there hasn't been a scheduled broadcast // if there hasn't been a scheduled broadcast
d.broadcastAfter(delta) time.AfterFunc(delta, d.rwCond.Broadcast)
} }
} }
if d.wtTimeout != 0 { if d.wtTimeout != 0 {
d.rDeadline = time.Now().Add(d.wtTimeout) d.rDeadline = time.Now().Add(d.wtTimeout)
d.broadcastAfter(d.wtTimeout) time.AfterFunc(d.wtTimeout, d.rwCond.Broadcast)
} }
if len(d.pLens) > 0 { if len(d.pLens) > 0 {
@ -163,15 +160,3 @@ func (d *datagramBufferedPipe) SetWriteToTimeout(t time.Duration) {
d.wtTimeout = t d.wtTimeout = t
d.rwCond.Broadcast() d.rwCond.Broadcast()
} }
func (d *datagramBufferedPipe) broadcastAfter(delta time.Duration) {
// d.rwCond.L must be held, otherwise the following timer operations will race
if !d.timer.Stop() {
<-d.timer.C
}
d.timer.Reset(delta)
go func() {
<-d.timer.C
d.rwCond.Broadcast()
}()
}

View File

@ -18,14 +18,11 @@ type streamBufferedPipe struct {
rwCond *sync.Cond rwCond *sync.Cond
rDeadline time.Time rDeadline time.Time
wtTimeout time.Duration wtTimeout time.Duration
timer *time.Timer
} }
func NewStreamBufferedPipe() *streamBufferedPipe { func NewStreamBufferedPipe() *streamBufferedPipe {
p := &streamBufferedPipe{ p := &streamBufferedPipe{
rwCond: sync.NewCond(&sync.Mutex{}), rwCond: sync.NewCond(&sync.Mutex{}),
timer: time.NewTimer(0),
} }
return p return p
} }
@ -45,7 +42,7 @@ func (p *streamBufferedPipe) Read(target []byte) (int, error) {
if d <= 0 { if d <= 0 {
return 0, ErrTimeout return 0, ErrTimeout
} }
p.broadcastAfter(d) time.AfterFunc(d, p.rwCond.Broadcast)
} }
if p.buf.Len() > 0 { if p.buf.Len() > 0 {
break break
@ -75,12 +72,12 @@ func (p *streamBufferedPipe) WriteTo(w io.Writer) (n int64, err error) {
} }
if p.wtTimeout == 0 { if p.wtTimeout == 0 {
// if there hasn't been a scheduled broadcast // if there hasn't been a scheduled broadcast
p.broadcastAfter(d) time.AfterFunc(d, p.rwCond.Broadcast)
} }
} }
if p.wtTimeout != 0 { if p.wtTimeout != 0 {
p.rDeadline = time.Now().Add(p.wtTimeout) p.rDeadline = time.Now().Add(p.wtTimeout)
p.broadcastAfter(p.wtTimeout) time.AfterFunc(p.wtTimeout, p.rwCond.Broadcast)
} }
if p.buf.Len() > 0 { if p.buf.Len() > 0 {
written, er := p.buf.WriteTo(w) written, er := p.buf.WriteTo(w)
@ -142,15 +139,3 @@ func (p *streamBufferedPipe) SetWriteToTimeout(d time.Duration) {
p.wtTimeout = d p.wtTimeout = d
p.rwCond.Broadcast() p.rwCond.Broadcast()
} }
func (p *streamBufferedPipe) broadcastAfter(d time.Duration) {
// p.rwCond.L must be held, otherwise the following timer operations will race
if !p.timer.Stop() {
<-p.timer.C
}
p.timer.Reset(d)
go func() {
<-p.timer.C
p.rwCond.Broadcast()
}()
}