github.com/blend/go-sdk@v1.20240719.1/collections/sync_ring_buffer.go (about) 1 /* 2 3 Copyright (c) 2024 - 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[T any]() *SyncRingBuffer[T] { 16 return &SyncRingBuffer[T]{ 17 innerBuffer: NewRingBuffer[T](), 18 syncRoot: &sync.Mutex{}, 19 } 20 } 21 22 // NewSyncRingBufferWithCapacity returns a new synchronized ring buffer. 23 func NewSyncRingBufferWithCapacity[T any](capacity int) *SyncRingBuffer[T] { 24 return &SyncRingBuffer[T]{ 25 innerBuffer: NewRingBufferWithCapacity[T](capacity), 26 syncRoot: &sync.Mutex{}, 27 } 28 } 29 30 // SyncRingBuffer is a ring buffer wrapper that adds synchronization. 31 type SyncRingBuffer[T any] struct { 32 innerBuffer *RingBuffer[T] 33 syncRoot *sync.Mutex 34 } 35 36 // SyncRoot returns the mutex used to synchronize the collection. 37 func (srb *SyncRingBuffer[T]) SyncRoot() *sync.Mutex { 38 return srb.syncRoot 39 } 40 41 // RingBuffer returns the inner ring buffer. 42 func (srb *SyncRingBuffer[T]) RingBuffer() *RingBuffer[T] { 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[T]) Len() int { 49 srb.syncRoot.Lock() 50 defer srb.syncRoot.Unlock() 51 return srb.innerBuffer.Len() 52 } 53 54 // Capacity returns the total size of the ring buffer, including empty elements. 55 func (srb *SyncRingBuffer[T]) Capacity() int { 56 srb.syncRoot.Lock() 57 defer srb.syncRoot.Unlock() 58 return srb.innerBuffer.Capacity() 59 } 60 61 // Enqueue adds an element to the "back" of the ring buffer. 62 func (srb *SyncRingBuffer[T]) Enqueue(value T) { 63 srb.syncRoot.Lock() 64 srb.innerBuffer.Enqueue(value) 65 srb.syncRoot.Unlock() 66 } 67 68 // Dequeue removes the first (oldest) element from the ring buffer. 69 func (srb *SyncRingBuffer[T]) Dequeue() T { 70 var val T 71 srb.syncRoot.Lock() 72 val = srb.innerBuffer.Dequeue() 73 srb.syncRoot.Unlock() 74 return val 75 } 76 77 // DequeueBack removes the last (newest) element from the ring buffer. 78 func (srb *SyncRingBuffer[T]) DequeueBack() T { 79 var val T 80 srb.syncRoot.Lock() 81 val = srb.innerBuffer.DequeueBack() 82 srb.syncRoot.Unlock() 83 return val 84 } 85 86 // Peek returns but does not remove the first element. 87 func (srb *SyncRingBuffer[T]) Peek() T { 88 var val T 89 srb.syncRoot.Lock() 90 val = srb.innerBuffer.Peek() 91 srb.syncRoot.Unlock() 92 return val 93 } 94 95 // PeekBack returns but does not remove the last element. 96 func (srb *SyncRingBuffer[T]) PeekBack() T { 97 var val T 98 srb.syncRoot.Lock() 99 val = srb.innerBuffer.PeekBack() 100 srb.syncRoot.Unlock() 101 return val 102 } 103 104 // TrimExcess resizes the buffer to better fit the contents. 105 func (srb *SyncRingBuffer[T]) TrimExcess() { 106 srb.syncRoot.Lock() 107 srb.innerBuffer.trimExcess() 108 srb.syncRoot.Unlock() 109 } 110 111 // Contents returns the ring buffer, in order, as a slice. 112 func (srb *SyncRingBuffer[T]) Contents() []T { 113 var val []T 114 srb.syncRoot.Lock() 115 val = srb.innerBuffer.Contents() 116 srb.syncRoot.Unlock() 117 return val 118 } 119 120 // Clear removes all objects from the ring buffer. 121 func (srb *SyncRingBuffer[T]) Clear() { 122 srb.syncRoot.Lock() 123 srb.innerBuffer.Clear() 124 srb.syncRoot.Unlock() 125 } 126 127 // Drain returns the ring buffer, in order, as a slice and empties it. 128 func (srb *SyncRingBuffer[T]) Drain() []T { 129 var val []T 130 srb.syncRoot.Lock() 131 val = srb.innerBuffer.Drain() 132 srb.syncRoot.Unlock() 133 return val 134 } 135 136 // Each calls the consumer for each element in the buffer. 137 func (srb *SyncRingBuffer[T]) Each(consumer func(value T)) { 138 srb.syncRoot.Lock() 139 srb.innerBuffer.Each(consumer) 140 srb.syncRoot.Unlock() 141 } 142 143 // Consume calls the consumer for each element in the buffer, while also dequeueing that entry. 144 func (srb *SyncRingBuffer[T]) Consume(consumer func(value T)) { 145 srb.syncRoot.Lock() 146 srb.innerBuffer.Consume(consumer) 147 srb.syncRoot.Unlock() 148 } 149 150 // EachUntil calls the consumer for each element in the buffer with a stopping condition in head=>tail order. 151 func (srb *SyncRingBuffer[T]) EachUntil(consumer func(value T) bool) { 152 srb.syncRoot.Lock() 153 srb.innerBuffer.EachUntil(consumer) 154 srb.syncRoot.Unlock() 155 } 156 157 // ReverseEachUntil calls the consumer for each element in the buffer with a stopping condition in tail=>head order. 158 func (srb *SyncRingBuffer[T]) ReverseEachUntil(consumer func(value T) bool) { 159 srb.syncRoot.Lock() 160 srb.innerBuffer.ReverseEachUntil(consumer) 161 srb.syncRoot.Unlock() 162 }