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  }