split read and write signal

pull/298/merge v2.27.1
Darien Raymond 2017-05-15 20:42:10 +02:00
parent 642a630912
commit ad35fc7028
No known key found for this signature in database
GPG Key ID: 7251FFA14BB18169
1 changed files with 39 additions and 22 deletions

View File

@ -54,20 +54,22 @@ func init() {
} }
type Stream struct { type Stream struct {
access sync.RWMutex access sync.RWMutex
data buf.MultiBuffer data buf.MultiBuffer
size uint64 size uint64
ctx context.Context ctx context.Context
wakeup chan bool readSignal chan bool
close bool writeSignal chan bool
err bool close bool
err bool
} }
func NewStream(ctx context.Context) *Stream { func NewStream(ctx context.Context) *Stream {
return &Stream{ return &Stream{
ctx: ctx, ctx: ctx,
wakeup: make(chan bool, 1), readSignal: make(chan bool, 1),
size: 0, writeSignal: make(chan bool, 1),
size: 0,
} }
} }
@ -110,14 +112,14 @@ func (s *Stream) Read() (buf.MultiBuffer, error) {
} }
if mb != nil { if mb != nil {
s.wakeUp() s.notifyRead()
return mb, nil return mb, nil
} }
select { select {
case <-s.ctx.Done(): case <-s.ctx.Done():
return nil, io.EOF return nil, io.EOF
case <-s.wakeup: case <-s.writeSignal:
} }
} }
} }
@ -130,7 +132,7 @@ func (s *Stream) ReadTimeout(timeout time.Duration) (buf.MultiBuffer, error) {
} }
if mb != nil { if mb != nil {
s.wakeUp() s.notifyRead()
return mb, nil return mb, nil
} }
@ -139,7 +141,7 @@ func (s *Stream) ReadTimeout(timeout time.Duration) (buf.MultiBuffer, error) {
return nil, io.EOF return nil, io.EOF
case <-time.After(timeout): case <-time.After(timeout):
return nil, buf.ErrReadTimeout return nil, buf.ErrReadTimeout
case <-s.wakeup: case <-s.writeSignal:
} }
} }
} }
@ -149,13 +151,18 @@ func (s *Stream) Write(data buf.MultiBuffer) error {
return nil return nil
} }
L:
for streamSizeLimit > 0 && s.size >= streamSizeLimit { for streamSizeLimit > 0 && s.size >= streamSizeLimit {
select { select {
case <-s.ctx.Done(): case <-s.ctx.Done():
return io.ErrClosedPipe return io.ErrClosedPipe
case <-s.wakeup: case <-s.readSignal:
break L s.access.RLock()
if s.err || s.close {
data.Release()
s.access.RUnlock()
return io.ErrClosedPipe
}
s.access.RUnlock()
} }
} }
@ -173,14 +180,21 @@ L:
s.data.AppendMulti(data) s.data.AppendMulti(data)
} }
s.size += uint64(data.Len()) s.size += uint64(data.Len())
s.wakeUp() s.notifyWrite()
return nil return nil
} }
func (s *Stream) wakeUp() { func (s *Stream) notifyRead() {
select { select {
case s.wakeup <- true: case s.readSignal <- true:
default:
}
}
func (s *Stream) notifyWrite() {
select {
case s.writeSignal <- true:
default: default:
} }
} }
@ -188,7 +202,8 @@ func (s *Stream) wakeUp() {
func (s *Stream) Close() { func (s *Stream) Close() {
s.access.Lock() s.access.Lock()
s.close = true s.close = true
s.wakeUp() s.notifyRead()
s.notifyWrite()
s.access.Unlock() s.access.Unlock()
} }
@ -198,7 +213,9 @@ func (s *Stream) CloseError() {
if s.data != nil { if s.data != nil {
s.data.Release() s.data.Release()
s.data = nil s.data = nil
s.size = 0
} }
s.wakeUp() s.notifyRead()
s.notifyWrite()
s.access.Unlock() s.access.Unlock()
} }