Skip to content

Commit 0fe67fa

Browse files
committed
added tests and docs
1 parent c415859 commit 0fe67fa

File tree

2 files changed

+109
-21
lines changed

2 files changed

+109
-21
lines changed

mpmc/rb.go

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ import (
1111

1212
// New returns the RingBuffer object.
1313
//
14-
// It returns ErrQueueFull when the queue is full and
15-
// putting a new element.
14+
// It returns [ErrQueueFull] when you're trying to put a new
15+
// element into a full ring buffer.
1616
func New[T any](capacity uint32, opts ...Opt[T]) (ringBuffer RingBuffer[T]) {
1717
return newRingBuffer(func(capacity uint32, opts ...Opt[T]) (ringBuffer RingBuffer[T]) {
1818
size := roundUpToPower2(capacity)
@@ -29,8 +29,17 @@ func New[T any](capacity uint32, opts ...Opt[T]) (ringBuffer RingBuffer[T]) {
2929
}, capacity, opts...)
3030
}
3131

32-
// NewOverlappedRingBuffer initials a ring buffer, which overwrites
33-
// its head element if it's full.
32+
// NewOverlappedRingBuffer make a new instance of the overlapped ring
33+
// buffer, which overwrites its head element if it's full.
34+
//
35+
// When an unexpected state occurred, the returned value could be nil.
36+
//
37+
// In this case, checking it for unavailable value is recommended.
38+
// This could happen if a physical core fault detected in high-freq,
39+
// high-pressure, and high-temperature place.
40+
//
41+
// For the normal runtime environment, unexpected state should be
42+
// impossible, so ignore it is safe.
3443
func NewOverlappedRingBuffer[T any](capacity uint32, opts ...Opt[T]) (ringBuffer RingBuffer[T]) {
3544
return newRingBuffer(func(capacity uint32, opts ...Opt[T]) (ringBuffer RingBuffer[T]) {
3645
size := roundUpToPower2(capacity)
@@ -49,28 +58,12 @@ func NewOverlappedRingBuffer[T any](capacity uint32, opts ...Opt[T]) (ringBuffer
4958
}, capacity, opts...)
5059
}
5160

61+
// Creator _
5262
type Creator[T any] func(capacity uint32, opts ...Opt[T]) (ringBuffer RingBuffer[T])
5363

5464
func newRingBuffer[T any](creator Creator[T], capacity uint32, opts ...Opt[T]) (ringBuffer RingBuffer[T]) {
5565
if isInitialized() {
5666
ringBuffer = creator(capacity, opts...)
57-
58-
// ringBuffer = rb
59-
60-
// for _, opt := range opts {
61-
// opt(rb)
62-
// }
63-
64-
// // if rb.debugMode && rb.logger != nil {
65-
// // // rb.logger.Debug("[ringbuf][INI] ", zap.Uint32("cap", rb.cap), zap.Uint32("capModMask", rb.capModMask))
66-
// // }
67-
68-
// for i := 0; i < int(size); i++ {
69-
// rb.data[i].readWrite &= 0 // bit 0: readable, bit 1: writable
70-
// if rb.initializer != nil {
71-
// rb.data[i].value = rb.initializer.PreAlloc(i)
72-
// }
73-
// }
7467
}
7568
return
7669
}

mpmc/rb2_test.go

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,98 @@ func TestOverlappedRingBuf_Put_OneByOne(t *testing.T) { //nolint:revive
7777
t.Fatalf("faild: Dequeue on an empty ringbuf should return an ErrQueueEmpty object.")
7878
}
7979
}
80+
81+
func TestOverlappedRingBuf_Random(t *testing.T) { //nolint:revive
82+
var err error
83+
var i uint32
84+
rb := NewOverlappedRingBuffer(NLtd, WithDebugMode[uint32](true))
85+
size := rb.Cap() - 1
86+
// t.Logf("Ring Buffer created, capacity = %v, real size: %v", size+1, size)
87+
defer rb.Close()
88+
89+
for ; i < size; i++ {
90+
err = rb.Enqueue(i)
91+
if err != nil {
92+
t.Fatalf("faild on i=%v. err: %+v", i, err)
93+
// } else {
94+
// t.Logf("%5d. '%v' put, quantity = %v.", i, i, fast.Quantity())
95+
}
96+
t.Logf(" %3d. ringbuf elements -> %v", i, rb)
97+
}
98+
99+
for ; i < size+size; i++ {
100+
err = rb.Put(i)
101+
if errors.Is(err, ErrQueueFull) {
102+
t.Fatalf("> %3d. expect ErrQueueFull but no error raised. err: %+v", i, err)
103+
}
104+
t.Logf(" %3d. ringbuf elements -> %v", i, rb)
105+
}
106+
107+
t.Log("remove 2 elems.")
108+
109+
var it any
110+
it, err = rb.Dequeue()
111+
_, _ = it, err
112+
t.Logf(" %3d. ringbuf elements -> %v", i, rb)
113+
i++
114+
it, err = rb.Dequeue()
115+
_, _ = it, err
116+
t.Logf(" %3d. ringbuf elements -> %v", i, rb)
117+
i++
118+
if fmt.Sprintf("%v", rb) != "[17,18,19,20,21,22,23,24,25,26,27,28,29,]/13" {
119+
t.Fatalf("faild: expecting elements are: [17,18,19,20,21,22,23,24,25,26,27,28,29,]/13")
120+
}
121+
122+
t.Logf("removed 2 elems, and inserting some new...")
123+
124+
for ; i < size*2+8; i++ {
125+
err = rb.Put(i)
126+
if errors.Is(err, ErrQueueFull) {
127+
t.Fatalf("> %3d. expect ErrQueueFull but no error raised. err: %+v", i, err)
128+
}
129+
t.Logf(" %3d. ringbuf elements -> %v", i, rb)
130+
}
131+
132+
it, err = rb.Dequeue()
133+
_, _ = it, err
134+
t.Logf("removed 1 elem: %v", it)
135+
t.Logf(" %3d. ringbuf elements -> %v", i, rb)
136+
i++
137+
138+
for ; i < size*3+3; i++ {
139+
err = rb.Put(i)
140+
if errors.Is(err, ErrQueueFull) {
141+
t.Fatalf("> %3d. expect ErrQueueFull but no error raised. err: %+v", i, err)
142+
}
143+
t.Logf(" %3d. ringbuf elements -> %v", i, rb)
144+
}
145+
if fmt.Sprintf("%v", rb) != "[32,33,34,35,36,37,39,40,41,42,43,44,45,46,47,]/15" {
146+
t.Fatalf("faild: expecting elements are: [32,33,34,35,36,37,39,40,41,42,43,44,45,46,47,]/15")
147+
}
148+
149+
// cleanup
150+
151+
for i := 0; ; i++ {
152+
it, err = rb.Dequeue()
153+
if err != nil {
154+
if errors.Is(err, ErrQueueEmpty) {
155+
break
156+
}
157+
t.Fatalf("faild on i=%v. err: %+v. item: %v", i, err, it)
158+
// } else {
159+
// t.Logf("< %3d. '%v' GOT, quantity = %v.", i, it, fast.Quantity())
160+
}
161+
if rb.Size() == 0 {
162+
// t.Log("empty ring buffer elements")
163+
if fmt.Sprintf("%v", rb) != "[]/0" {
164+
t.Fatalf("faild: expecting elements are: []/0")
165+
}
166+
}
167+
t.Logf(" %3d. ringbuf elements -> %v", i, rb)
168+
}
169+
170+
it, err = rb.Dequeue()
171+
if err == nil {
172+
t.Fatalf("faild: Dequeue on an empty ringbuf should return an ErrQueueEmpty object.")
173+
}
174+
}

0 commit comments

Comments
 (0)