flow.go 1.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. // Copyright 2014 The Go Authors.
  2. // See https://code.google.com/p/go/source/browse/CONTRIBUTORS
  3. // Licensed under the same terms as Go itself:
  4. // https://code.google.com/p/go/source/browse/LICENSE
  5. // Flow control
  6. package http2
  7. import "sync"
  8. // flow is the flow control window's counting semaphore.
  9. type flow struct {
  10. c *sync.Cond // protects size
  11. size int32
  12. }
  13. func newFlow(n int32) *flow {
  14. return &flow{
  15. c: sync.NewCond(new(sync.Mutex)),
  16. size: n,
  17. }
  18. }
  19. // acquire decrements the flow control window by n bytes, blocking
  20. // until they're available in the window.
  21. // The return value is only interesting for tests.
  22. func (f *flow) acquire(n int32) (waited int) {
  23. if n < 0 {
  24. panic("negative acquire")
  25. }
  26. f.c.L.Lock()
  27. defer f.c.L.Unlock()
  28. for {
  29. if f.size >= n {
  30. f.size -= n
  31. return
  32. }
  33. waited++
  34. f.c.Wait()
  35. }
  36. }
  37. // add adds n bytes (positive or negative) to the flow control window.
  38. // It returns false if the sum would exceed 2^31-1.
  39. func (f *flow) add(n int32) bool {
  40. f.c.L.Lock()
  41. defer f.c.L.Unlock()
  42. remain := (1<<31 - 1) - f.size
  43. if n > remain {
  44. return false
  45. }
  46. f.size += n
  47. f.c.Broadcast()
  48. return true
  49. }