github.com/pharosnet/flyline@v1.0.2/queue_buffer.go (about) 1 package flyline 2 3 import ( 4 "context" 5 "sync" 6 "time" 7 ) 8 9 func NewQueueBuffer() Buffer { 10 b := new(queueBuffer) 11 b.seq = NewSequence() 12 b.sts = new(status) 13 b.queue = new(queue) 14 b.mutex = new(sync.Mutex) 15 b.sts.setRunning() 16 return b 17 } 18 19 // Queue Buffer implements Buffer. 20 type queueBuffer struct { 21 sts *status 22 queue *queue 23 seq *Sequence 24 mutex *sync.Mutex 25 } 26 27 func (b *queueBuffer) Send(i interface{}) (err error) { 28 if b.sts.isClosed() { 29 err = ErrBufSendClosed 30 return 31 } 32 b.seq.Incr() 33 b.queue.add(i) 34 return 35 } 36 37 func (b *queueBuffer) Recv() (value interface{}, active bool) { 38 active = true 39 if b.sts.isClosed() && b.Len() == int64(0) { 40 active = false 41 return 42 } 43 value = b.queue.poll() 44 b.seq.Decr() 45 return 46 } 47 48 func (b *queueBuffer) Len() (length int64) { 49 length = b.seq.Get() + 1 50 return 51 } 52 53 func (b *queueBuffer) Close() (err error) { 54 b.mutex.Lock() 55 defer b.mutex.Unlock() 56 if b.sts.isClosed() { 57 err = ErrBufCloseClosed 58 return 59 } 60 b.sts.setClosed() 61 return 62 } 63 64 func (b *queueBuffer) Sync(ctx context.Context) (err error) { 65 b.mutex.Lock() 66 defer b.mutex.Unlock() 67 if b.sts.isRunning() { 68 err = ErrBufSyncUnclosed 69 return 70 } 71 for { 72 ok := false 73 select { 74 case <-ctx.Done(): 75 ok = true 76 break 77 default: 78 if b.Len() == int64(0) { 79 ok = true 80 break 81 } 82 time.Sleep(ms500) 83 } 84 if ok { 85 break 86 } 87 } 88 return 89 }