github.com/pharosnet/flyline@v1.0.2/array_buffer.go (about) 1 package flyline 2 3 import ( 4 "context" 5 "runtime" 6 "sync" 7 "time" 8 ) 9 10 // Note: The array capacity must be a power of two, e.g. 2, 4, 8, 16, 32, 64, etc. 11 func NewArrayBuffer(capacity int64) Buffer { 12 b := &arrayBuffer{ 13 capacity: capacity, 14 buffer: newArray(capacity), 15 wdSeq: NewSequence(), 16 wpSeq: NewSequence(), 17 rdSeq: NewSequence(), 18 rpSeq: NewSequence(), 19 sts: &status{}, 20 mutex: &sync.Mutex{}, 21 } 22 b.sts.setRunning() 23 return b 24 } 25 26 type arrayBuffer struct { 27 capacity int64 28 buffer *array 29 wpSeq *Sequence 30 wdSeq *Sequence 31 rpSeq *Sequence 32 rdSeq *Sequence 33 sts *status 34 mutex *sync.Mutex 35 } 36 37 func (b *arrayBuffer) Send(i interface{}) (err error) { 38 if b.sts.isClosed() { 39 err = ErrBufSendClosed 40 return 41 } 42 next := b.wpSeq.Incr() 43 times := 10 44 for { 45 times-- 46 if next-b.capacity-b.rdSeq.Get() <= 0 && next-(b.wdSeq.Get()+1) == 0 { 47 b.buffer.set(next, i) 48 b.wdSeq.Incr() 49 break 50 } 51 time.Sleep(ns1) 52 if times <= 0 { 53 runtime.Gosched() 54 times = 10 55 } 56 } 57 return 58 } 59 60 func (b *arrayBuffer) Recv() (value interface{}, active bool) { 61 active = true 62 if b.sts.isClosed() && b.Len() == int64(0) { 63 active = false 64 return 65 } 66 times := 10 67 next := b.rpSeq.Incr() 68 for { 69 if next-b.wdSeq.Get() <= 0 && next-(b.rdSeq.Get()+1) == 0 { 70 value = b.buffer.get(next) 71 b.rdSeq.Incr() 72 break 73 } 74 time.Sleep(ns1) 75 if times <= 0 { 76 runtime.Gosched() 77 times = 10 78 } 79 } 80 return 81 } 82 83 func (b *arrayBuffer) Len() (length int64) { 84 length = b.wpSeq.Get() - b.rdSeq.Get() 85 return 86 } 87 88 func (b *arrayBuffer) Close() (err error) { 89 b.mutex.Lock() 90 defer b.mutex.Unlock() 91 if b.sts.isClosed() { 92 err = ErrBufCloseClosed 93 return 94 } 95 b.sts.setClosed() 96 return 97 } 98 99 func (b *arrayBuffer) Sync(ctx context.Context) (err error) { 100 b.mutex.Lock() 101 defer b.mutex.Unlock() 102 if b.sts.isRunning() { 103 err = ErrBufSyncUnclosed 104 return 105 } 106 for { 107 ok := false 108 select { 109 case <-ctx.Done(): 110 ok = true 111 break 112 default: 113 if b.Len() == int64(0) { 114 ok = true 115 break 116 } 117 time.Sleep(ms500) 118 } 119 if ok { 120 break 121 } 122 } 123 return 124 }