Pull request 2020: AG-26236-ring-buffer
Squashed commit of the following:
commit 4b9cc9ddf52739fc5f918babedc99ac7ac0e2415
Merge: a6259ed57 39aeaf891
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date: Tue Oct 3 20:39:58 2023 +0300
Merge branch 'master' into AG-26236-ring-buffer
commit a6259ed5758156e4110ee3ea6a49760d2880ade3
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date: Tue Oct 3 20:30:20 2023 +0300
querylog: imp code
commit 40f9f7cd5a1cff22bcb858020f2cfa9be8399671
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date: Tue Oct 3 20:11:49 2023 +0300
querylog: fix typo
commit 1aabbadcb5fcbe6a95945c5bd1455b956b85a8d0
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date: Tue Oct 3 20:05:22 2023 +0300
querylog: imp err msg
commit 02913d35b43e190e42765823ccfcdd332839e984
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date: Tue Oct 3 19:37:47 2023 +0300
aghalg: imp tests
commit 98a7909088d2a65b78afa9fa3113545c94429e65
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date: Tue Oct 3 19:23:10 2023 +0300
all: imp tests
commit e147804eeafe89e5020cd917784eef3ff2b310d0
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date: Tue Oct 3 18:49:49 2023 +0300
all: imp code
commit 5f21f2f63b7bce89f2bc79c97c7350cd693c956b
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date: Tue Oct 3 14:39:43 2023 +0300
all: add tests
commit 35a45c7dc5d5961f6987da7c69249c56e54e97f5
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date: Mon Oct 2 17:43:09 2023 +0300
all: imp code
commit 21e51fcbe411258eaf830825df9d05b7ddcc187a
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date: Fri Sep 29 18:21:00 2023 +0300
all: add ring buffer
This commit is contained in:
102
internal/aghalg/ringbuffer.go
Normal file
102
internal/aghalg/ringbuffer.go
Normal file
@@ -0,0 +1,102 @@
|
||||
package aghalg
|
||||
|
||||
import (
|
||||
"github.com/AdguardTeam/golibs/errors"
|
||||
)
|
||||
|
||||
// RingBuffer is the implementation of ring buffer data structure.
|
||||
type RingBuffer[T any] struct {
|
||||
buf []T
|
||||
cur int
|
||||
full bool
|
||||
}
|
||||
|
||||
// NewRingBuffer initializes the new instance of ring buffer. size must be
|
||||
// greater or equal to zero.
|
||||
func NewRingBuffer[T any](size int) (rb *RingBuffer[T]) {
|
||||
if size < 0 {
|
||||
panic(errors.Error("ring buffer: size must be greater or equal to zero"))
|
||||
}
|
||||
|
||||
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) % 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 int) {
|
||||
if !rb.full {
|
||||
return rb.cur
|
||||
}
|
||||
|
||||
return cap(rb.buf)
|
||||
}
|
||||
|
||||
// Clear clears the buffer.
|
||||
func (rb *RingBuffer[T]) Clear() {
|
||||
rb.full = false
|
||||
rb.cur = 0
|
||||
}
|
||||
Reference in New Issue
Block a user