summaryrefslogtreecommitdiffstats
path: root/vendor/maunium.net/go/mautrix/util/ringbuffer.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/maunium.net/go/mautrix/util/ringbuffer.go')
-rw-r--r--vendor/maunium.net/go/mautrix/util/ringbuffer.go77
1 files changed, 77 insertions, 0 deletions
diff --git a/vendor/maunium.net/go/mautrix/util/ringbuffer.go b/vendor/maunium.net/go/mautrix/util/ringbuffer.go
new file mode 100644
index 00000000..ddb4c79f
--- /dev/null
+++ b/vendor/maunium.net/go/mautrix/util/ringbuffer.go
@@ -0,0 +1,77 @@
+// Copyright (c) 2023 Tulir Asokan
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+package util
+
+import (
+ "sync"
+)
+
+type pair[Key comparable, Value any] struct {
+ Key Key
+ Value Value
+}
+
+type RingBuffer[Key comparable, Value any] struct {
+ ptr int
+ data []pair[Key, Value]
+ lock sync.RWMutex
+}
+
+func NewRingBuffer[Key comparable, Value any](size int) *RingBuffer[Key, Value] {
+ return &RingBuffer[Key, Value]{
+ data: make([]pair[Key, Value], size),
+ }
+}
+
+func (rb *RingBuffer[Key, Value]) Contains(val Key) bool {
+ _, ok := rb.Get(val)
+ return ok
+}
+
+func (rb *RingBuffer[Key, Value]) Get(key Key) (val Value, found bool) {
+ rb.lock.RLock()
+ end := rb.ptr
+ for i := clamp(end-1, len(rb.data)); i != end; i = clamp(i-1, len(rb.data)) {
+ if rb.data[i].Key == key {
+ val = rb.data[i].Value
+ found = true
+ break
+ }
+ }
+ rb.lock.RUnlock()
+ return
+}
+
+func (rb *RingBuffer[Key, Value]) Replace(key Key, val Value) bool {
+ rb.lock.Lock()
+ defer rb.lock.Unlock()
+ end := rb.ptr
+ for i := clamp(end-1, len(rb.data)); i != end; i = clamp(i-1, len(rb.data)) {
+ if rb.data[i].Key == key {
+ rb.data[i].Value = val
+ return true
+ }
+ }
+ return false
+}
+
+func (rb *RingBuffer[Key, Value]) Push(key Key, val Value) {
+ rb.lock.Lock()
+ rb.data[rb.ptr] = pair[Key, Value]{Key: key, Value: val}
+ rb.ptr = (rb.ptr + 1) % len(rb.data)
+ rb.lock.Unlock()
+}
+
+func clamp(index, len int) int {
+ if index < 0 {
+ return len + index
+ } else if index >= len {
+ return len - index
+ } else {
+ return index
+ }
+}