AdGuardHome/internal/aghalg/ringbuffer.go
Stanislav Chzhen 1e0ff4d437 Pull request 2119: 6570-querylog-size-memory
Updates #6570.

Squashed commit of the following:

commit 92b2723ac1b2a78138a55cb82a3222f66119bbda
Merge: 2da12283b 0143c3aac
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Tue Jan 9 17:07:23 2024 +0300

    Merge branch 'master' into 6570-querylog-size-memory

commit 2da12283b5f504fa77f08fa6026fa9a57b806b38
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Tue Jan 9 17:04:54 2024 +0300

    all: imp tests

commit 1cb404c65d4e9981b709d689fd281253eca01f82
Merge: 5f7d20516 94d437d40
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Thu Dec 28 20:18:00 2023 +0300

    Merge branch 'master' into 6570-querylog-size-memory

commit 5f7d20516934867e1a141c19a97edb49407884ee
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Wed Dec 27 15:07:54 2023 +0300

    all: imp docs

commit 0b17cfc4243a88606c62e4b1ae893a09149655b5
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Mon Dec 25 20:06:09 2023 +0300

    all: querylog size memory
2024-01-11 18:38:30 +03:00

94 lines
1.8 KiB
Go

package aghalg
// RingBuffer is the implementation of ring buffer data structure.
type RingBuffer[T any] struct {
buf []T
cur uint
full bool
}
// NewRingBuffer initializes the new instance of ring buffer. size must be
// greater or equal to zero.
func NewRingBuffer[T any](size uint) (rb *RingBuffer[T]) {
return &RingBuffer[T]{
buf: make([]T, size),
}
}
// Append appends an element to the buffer.
func (rb *RingBuffer[T]) Append(e T) {
if len(rb.buf) == 0 {
return
}
rb.buf[rb.cur] = e
rb.cur = (rb.cur + 1) % uint(cap(rb.buf))
if rb.cur == 0 {
rb.full = true
}
}
// Range calls cb for each element of the buffer. If cb returns false it stops.
func (rb *RingBuffer[T]) Range(cb func(T) (cont bool)) {
before, after := rb.splitCur()
for _, e := range before {
if !cb(e) {
return
}
}
for _, e := range after {
if !cb(e) {
return
}
}
}
// ReverseRange calls cb for each element of the buffer in reverse order. If
// cb returns false it stops.
func (rb *RingBuffer[T]) ReverseRange(cb func(T) (cont bool)) {
before, after := rb.splitCur()
for i := len(after) - 1; i >= 0; i-- {
if !cb(after[i]) {
return
}
}
for i := len(before) - 1; i >= 0; i-- {
if !cb(before[i]) {
return
}
}
}
// splitCur splits the buffer in two, before and after current position in
// chronological order. If buffer is not full, after is nil.
func (rb *RingBuffer[T]) splitCur() (before, after []T) {
if len(rb.buf) == 0 {
return nil, nil
}
cur := rb.cur
if !rb.full {
return rb.buf[:cur], nil
}
return rb.buf[cur:], rb.buf[:cur]
}
// Len returns a length of the buffer.
func (rb *RingBuffer[T]) Len() (l uint) {
if !rb.full {
return rb.cur
}
return uint(cap(rb.buf))
}
// Clear clears the buffer.
func (rb *RingBuffer[T]) Clear() {
rb.full = false
rb.cur = 0
}