flow.go 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  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. // cur returns the current number of bytes allow to write. Obviously
  20. // it's not safe to call this and assume acquiring that number of
  21. // bytes from the acquire method won't be block in the presence of
  22. // concurrent acquisitions.
  23. func (f *flow) cur() int32 {
  24. f.c.L.Lock()
  25. defer f.c.L.Unlock()
  26. return f.size
  27. }
  28. // acquire decrements the flow control window by n bytes, blocking
  29. // until they're available in the window.
  30. // The return value is only interesting for tests.
  31. func (f *flow) acquire(n int32) (waited int) {
  32. if n < 0 {
  33. panic("negative acquire")
  34. }
  35. f.c.L.Lock()
  36. defer f.c.L.Unlock()
  37. for {
  38. if f.size >= n {
  39. f.size -= n
  40. return
  41. }
  42. waited++
  43. f.c.Wait()
  44. }
  45. }
  46. // add adds n bytes (positive or negative) to the flow control window.
  47. // It returns false if the sum would exceed 2^31-1.
  48. func (f *flow) add(n int32) bool {
  49. f.c.L.Lock()
  50. defer f.c.L.Unlock()
  51. remain := (1<<31 - 1) - f.size
  52. if n > remain {
  53. return false
  54. }
  55. f.size += n
  56. f.c.Broadcast()
  57. return true
  58. }