readv_reader.go 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. package buf
  2. import (
  3. "io"
  4. "syscall"
  5. "unsafe"
  6. )
  7. type ReadVReader struct {
  8. io.Reader
  9. rawConn syscall.RawConn
  10. iovects []syscall.Iovec
  11. nBuf int32
  12. }
  13. func NewReadVReader(reader io.Reader, rawConn syscall.RawConn) *ReadVReader {
  14. return &ReadVReader{
  15. Reader: reader,
  16. rawConn: rawConn,
  17. nBuf: 1,
  18. }
  19. }
  20. func allocN(n int32) []*Buffer {
  21. bs := make([]*Buffer, 0, n)
  22. for i := int32(0); i < n; i++ {
  23. bs = append(bs, New())
  24. }
  25. return bs
  26. }
  27. func (r *ReadVReader) ReadMultiBuffer() (MultiBuffer, error) {
  28. bs := allocN(r.nBuf)
  29. var iovecs []syscall.Iovec
  30. if r.iovects != nil {
  31. iovecs = r.iovects
  32. }
  33. for idx, b := range bs {
  34. iovecs = append(iovecs, syscall.Iovec{
  35. Base: &(b.v[0]),
  36. })
  37. iovecs[idx].SetLen(int(Size))
  38. }
  39. r.iovects = iovecs[:0]
  40. var nBytes int
  41. err := r.rawConn.Read(func(fd uintptr) bool {
  42. n, _, e := syscall.Syscall(syscall.SYS_READV, fd, uintptr(unsafe.Pointer(&iovecs[0])), uintptr(len(iovecs)))
  43. if e != 0 {
  44. return false
  45. }
  46. nBytes = int(n)
  47. return true
  48. })
  49. if err != nil {
  50. mb := MultiBuffer(bs)
  51. mb.Release()
  52. return nil, err
  53. }
  54. if nBytes == 0 {
  55. mb := MultiBuffer(bs)
  56. mb.Release()
  57. return nil, io.EOF
  58. }
  59. var isFull bool = (nBytes == int(r.nBuf)*Size)
  60. nBuf := 0
  61. for nBuf < len(bs) {
  62. if nBytes <= 0 {
  63. break
  64. }
  65. end := int32(nBytes)
  66. if end > Size {
  67. end = Size
  68. }
  69. bs[nBuf].end = end
  70. nBytes -= int(end)
  71. nBuf++
  72. }
  73. for i := nBuf; i < len(bs); i++ {
  74. bs[i].Release()
  75. bs[i] = nil
  76. }
  77. if isFull && nBuf < 128 {
  78. r.nBuf *= 4
  79. } else {
  80. r.nBuf = int32(nBuf)
  81. }
  82. return MultiBuffer(bs[:nBuf]), nil
  83. }