buffer.go 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. package kcp
  2. import (
  3. "sync"
  4. "v2ray.com/core/common/alloc"
  5. )
  6. const (
  7. NumDistro = 5
  8. DistroSize = 1600
  9. )
  10. type Buffer struct {
  11. sync.Mutex
  12. buffer *alloc.Buffer
  13. next int
  14. released int
  15. hold bool
  16. distro [NumDistro]*alloc.Buffer
  17. }
  18. func NewBuffer() *Buffer {
  19. b := &Buffer{
  20. next: 0,
  21. released: 0,
  22. hold: true,
  23. buffer: alloc.NewBuffer(),
  24. }
  25. for idx := range b.distro {
  26. content := b.buffer.Value[idx*DistroSize : (idx+1)*DistroSize]
  27. b.distro[idx] = alloc.CreateBuffer(content, b)
  28. }
  29. return b
  30. }
  31. func (this *Buffer) IsEmpty() bool {
  32. this.Lock()
  33. defer this.Unlock()
  34. return this.next == NumDistro
  35. }
  36. func (this *Buffer) Allocate() *alloc.Buffer {
  37. this.Lock()
  38. defer this.Unlock()
  39. if this.next == NumDistro {
  40. return nil
  41. }
  42. b := this.distro[this.next]
  43. this.next++
  44. return b
  45. }
  46. func (this *Buffer) Free(b *alloc.Buffer) {
  47. this.Lock()
  48. defer this.Unlock()
  49. this.released++
  50. if !this.hold && this.released == this.next {
  51. this.ReleaseBuffer()
  52. }
  53. }
  54. func (this *Buffer) Release() {
  55. this.Lock()
  56. defer this.Unlock()
  57. if this.next == this.released {
  58. this.ReleaseBuffer()
  59. }
  60. this.hold = false
  61. }
  62. func (this *Buffer) ReleaseBuffer() {
  63. this.buffer.Release()
  64. this.buffer = nil
  65. for idx := range this.distro {
  66. this.distro[idx] = nil
  67. }
  68. }
  69. var (
  70. globalBuffer *Buffer
  71. globalBufferAccess sync.Mutex
  72. )
  73. func AllocateBuffer() *alloc.Buffer {
  74. globalBufferAccess.Lock()
  75. defer globalBufferAccess.Unlock()
  76. if globalBuffer == nil {
  77. globalBuffer = NewBuffer()
  78. }
  79. b := globalBuffer.Allocate()
  80. if globalBuffer.IsEmpty() {
  81. globalBuffer.Release()
  82. globalBuffer = nil
  83. }
  84. return b
  85. }