github.com/blend/go-sdk@v1.20220411.3/collections/sync_ring_buffer.go (about) 1 /* 2 3 Copyright (c) 2022 - Present. Blend Labs, Inc. All rights reserved 4 Use of this source code is governed by a MIT license that can be found in the LICENSE file. 5 6 */ 7 8 package collections 9 10 import ( 11 "sync" 12 ) 13 14 // NewSyncRingBuffer returns a new synchronized ring buffer. 15 func NewSyncRingBuffer() *SyncRingBuffer { 16 return &SyncRingBuffer{ 17 innerBuffer: NewRingBuffer(), 18 syncRoot: &sync.Mutex{}, 19 } 20 } 21 22 // NewSyncRingBufferWithCapacity returns a new synchronized ring buffer. 23 func NewSyncRingBufferWithCapacity(capacity int) *SyncRingBuffer { 24 return &SyncRingBuffer{ 25 innerBuffer: NewRingBufferWithCapacity(capacity), 26 syncRoot: &sync.Mutex{}, 27 } 28 } 29 30 // SyncRingBuffer is a ring buffer wrapper that adds synchronization. 31 type SyncRingBuffer struct { 32 innerBuffer *RingBuffer 33 syncRoot *sync.Mutex 34 } 35 36 // SyncRoot returns the mutex used to synchronize the collection. 37 func (srb *SyncRingBuffer) SyncRoot() *sync.Mutex { 38 return srb.syncRoot 39 } 40 41 // RingBuffer returns the inner ringbuffer. 42 func (srb *SyncRingBuffer) RingBuffer() *RingBuffer { 43 return srb.innerBuffer 44 } 45 46 // Len returns the length of the ring buffer (as it is currently populated). 47 // Actual memory footprint may be different. 48 func (srb SyncRingBuffer) Len() (val int) { 49 srb.syncRoot.Lock() 50 val = srb.innerBuffer.Len() 51 srb.syncRoot.Unlock() 52 return 53 } 54 55 // Capacity returns the total size of the ring bufffer, including empty elements. 56 func (srb *SyncRingBuffer) Capacity() (val int) { 57 srb.syncRoot.Lock() 58 val = srb.innerBuffer.Capacity() 59 srb.syncRoot.Unlock() 60 return 61 } 62 63 // Enqueue adds an element to the "back" of the RingBuffer. 64 func (srb *SyncRingBuffer) Enqueue(value interface{}) { 65 srb.syncRoot.Lock() 66 srb.innerBuffer.Enqueue(value) 67 srb.syncRoot.Unlock() 68 } 69 70 // Dequeue removes the first (oldest) element from the RingBuffer. 71 func (srb *SyncRingBuffer) Dequeue() (val interface{}) { 72 srb.syncRoot.Lock() 73 val = srb.innerBuffer.Dequeue() 74 srb.syncRoot.Unlock() 75 return 76 } 77 78 // DequeueBack removes the last (newest) element from the RingBuffer. 79 func (srb *SyncRingBuffer) DequeueBack() (val interface{}) { 80 srb.syncRoot.Lock() 81 val = srb.innerBuffer.DequeueBack() 82 srb.syncRoot.Unlock() 83 return 84 } 85 86 // Peek returns but does not remove the first element. 87 func (srb *SyncRingBuffer) Peek() (val interface{}) { 88 srb.syncRoot.Lock() 89 val = srb.innerBuffer.Peek() 90 srb.syncRoot.Unlock() 91 return 92 } 93 94 // PeekBack returns but does not remove the last element. 95 func (srb *SyncRingBuffer) PeekBack() (val interface{}) { 96 srb.syncRoot.Lock() 97 val = srb.innerBuffer.PeekBack() 98 srb.syncRoot.Unlock() 99 return 100 } 101 102 // TrimExcess resizes the buffer to better fit the contents. 103 func (srb *SyncRingBuffer) TrimExcess() { 104 srb.syncRoot.Lock() 105 srb.innerBuffer.trimExcess() 106 srb.syncRoot.Unlock() 107 } 108 109 // Contents returns the ring buffer, in order, as a slice. 110 func (srb *SyncRingBuffer) Contents() (val []interface{}) { 111 srb.syncRoot.Lock() 112 val = srb.innerBuffer.Contents() 113 srb.syncRoot.Unlock() 114 return 115 } 116 117 // Clear removes all objects from the RingBuffer. 118 func (srb *SyncRingBuffer) Clear() { 119 srb.syncRoot.Lock() 120 srb.innerBuffer.Clear() 121 srb.syncRoot.Unlock() 122 } 123 124 // Drain returns the ring buffer, in order, as a slice and empties it. 125 func (srb *SyncRingBuffer) Drain() (val []interface{}) { 126 srb.syncRoot.Lock() 127 val = srb.innerBuffer.Drain() 128 srb.syncRoot.Unlock() 129 return 130 } 131 132 // Each calls the consumer for each element in the buffer. 133 func (srb *SyncRingBuffer) Each(consumer func(value interface{})) { 134 srb.syncRoot.Lock() 135 srb.innerBuffer.Each(consumer) 136 srb.syncRoot.Unlock() 137 } 138 139 // Consume calls the consumer for each element in the buffer, while also dequeueing that entry. 140 func (srb *SyncRingBuffer) Consume(consumer func(value interface{})) { 141 srb.syncRoot.Lock() 142 srb.innerBuffer.Consume(consumer) 143 srb.syncRoot.Unlock() 144 } 145 146 // EachUntil calls the consumer for each element in the buffer with a stopping condition in head=>tail order. 147 func (srb *SyncRingBuffer) EachUntil(consumer func(value interface{}) bool) { 148 srb.syncRoot.Lock() 149 srb.innerBuffer.EachUntil(consumer) 150 srb.syncRoot.Unlock() 151 } 152 153 // ReverseEachUntil calls the consumer for each element in the buffer with a stopping condition in tail=>head order. 154 func (srb *SyncRingBuffer) ReverseEachUntil(consumer func(value interface{}) bool) { 155 srb.syncRoot.Lock() 156 srb.innerBuffer.ReverseEachUntil(consumer) 157 srb.syncRoot.Unlock() 158 }