blob: 6dc8df6eea066d806dc6675933efefa8c081c488 [file] [log] [blame]
// Copyright 2014 The Go Authors.
// See https://code.google.com/p/go/source/browse/CONTRIBUTORS
// Licensed under the same terms as Go itself:
// https://code.google.com/p/go/source/browse/LICENSE
// Flow control
package http2
import "sync"
// flow is the flow control window's counting semaphore.
type flow struct {
c *sync.Cond // protects size
size int32
}
func newFlow(n int32) *flow {
return &flow{
c: sync.NewCond(new(sync.Mutex)),
size: n,
}
}
// acquire decrements the flow control window by n bytes, blocking
// until they're available in the window.
// The return value is only interesting for tests.
func (f *flow) acquire(n int32) (waited int) {
if n < 0 {
panic("negative acquire")
}
f.c.L.Lock()
defer f.c.L.Unlock()
for {
if f.size >= n {
f.size -= n
return
}
waited++
f.c.Wait()
}
}
// add adds n bytes (positive or negative) to the flow control window.
// It returns false if the sum would exceed 2^31-1.
func (f *flow) add(n int32) bool {
f.c.L.Lock()
defer f.c.L.Unlock()
remain := (1<<31 - 1) - f.size
if n > remain {
return false
}
f.size += n
f.c.Broadcast()
return true
}