pipe.go 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. // Copyright 2014 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package http2
  5. import (
  6. "errors"
  7. "io"
  8. "sync"
  9. )
  10. // pipe is a goroutine-safe io.Reader/io.Writer pair. It's like
  11. // io.Pipe except there are no PipeReader/PipeWriter halves, and the
  12. // underlying buffer is an interface. (io.Pipe is always unbuffered)
  13. type pipe struct {
  14. mu sync.Mutex
  15. c sync.Cond // c.L must point to
  16. b pipeBuffer
  17. err error // read error once empty. non-nil means closed.
  18. }
  19. type pipeBuffer interface {
  20. Len() int
  21. io.Writer
  22. io.Reader
  23. }
  24. // Read waits until data is available and copies bytes
  25. // from the buffer into p.
  26. func (p *pipe) Read(d []byte) (n int, err error) {
  27. p.mu.Lock()
  28. defer p.mu.Unlock()
  29. if p.c.L == nil {
  30. p.c.L = &p.mu
  31. }
  32. for {
  33. if p.b.Len() > 0 {
  34. return p.b.Read(d)
  35. }
  36. if p.err != nil {
  37. return 0, p.err
  38. }
  39. p.c.Wait()
  40. }
  41. }
  42. var errClosedPipeWrite = errors.New("write on closed buffer")
  43. // Write copies bytes from p into the buffer and wakes a reader.
  44. // It is an error to write more data than the buffer can hold.
  45. func (p *pipe) Write(d []byte) (n int, err error) {
  46. p.mu.Lock()
  47. defer p.mu.Unlock()
  48. if p.c.L == nil {
  49. p.c.L = &p.mu
  50. }
  51. defer p.c.Signal()
  52. if p.err != nil {
  53. return 0, errClosedPipeWrite
  54. }
  55. return p.b.Write(d)
  56. }
  57. // CloseWithError causes Reads to wake up and return the
  58. // provided err after all data has been read.
  59. //
  60. // The error must be non-nil.
  61. func (p *pipe) CloseWithError(err error) {
  62. if err == nil {
  63. panic("CloseWithError must be non-nil")
  64. }
  65. p.mu.Lock()
  66. defer p.mu.Unlock()
  67. if p.c.L == nil {
  68. p.c.L = &p.mu
  69. }
  70. defer p.c.Signal()
  71. if p.err == nil {
  72. p.err = err
  73. }
  74. }