@@ -2,16 +2,17 @@ package ringbuffer
2
2
3
3
import (
4
4
"fmt"
5
+ "sync/atomic"
5
6
6
7
armath "github.com/asymmetric-research/go-commons/math"
7
8
)
8
9
9
10
type T [C any ] struct {
10
- buflen uint
11
+ buflen uint64
11
12
buf []C
12
13
13
14
// head points to the next free slot
14
- head uint
15
+ head atomic. Uint64
15
16
}
16
17
17
18
func New [C any ](size int ) (* T [C ], error ) {
@@ -26,29 +27,29 @@ func NewInto[C any](dst *T[C], buf []C) error {
26
27
return fmt .Errorf ("backing buffer must have a greater than zero" )
27
28
}
28
29
* dst = T [C ]{
29
- buflen : uint (len (buf )),
30
+ buflen : uint64 (len (buf )),
30
31
buf : buf ,
31
- head : 0 ,
32
32
}
33
+ dst .head .Store (0 )
33
34
return nil
34
35
}
35
36
36
37
func (r * T [C ]) Push (item C ) {
37
- r . buf [ r . head % r . buflen ] = item
38
- r .head += 1
38
+ nextSlot := r . head . Add ( 1 )
39
+ r .buf [( nextSlot - 1 ) % r . buflen ] = item
39
40
}
40
41
41
42
func (r * T [C ]) Last (dst []C ) int {
42
43
// how many entries can we write?
43
- maxWritable := armath .Min (r .head , r .buflen )
44
+ maxWritable := armath .Min (r .head . Load () , r .buflen )
44
45
45
46
// if the dst is larger than the amount of entries we can write, let's clamp it.
46
47
if len (dst ) > int (maxWritable ) {
47
48
// only consider the first available slots of dst
48
49
dst = dst [:maxWritable ]
49
50
}
50
51
51
- headmod := int (r .head % r .buflen )
52
+ headmod := int (r .head . Load () % r .buflen )
52
53
53
54
// we must do at most 2 copies
54
55
n := 0
@@ -80,8 +81,8 @@ func (r *T[C]) Last(dst []C) int {
80
81
return n
81
82
}
82
83
83
- func (r * T [C ]) Len () uint {
84
- used := armath .Min (r .buflen , r .head )
84
+ func (r * T [C ]) Len () uint64 {
85
+ used := armath .Min (r .buflen , r .head . Load () )
85
86
return used
86
87
}
87
88
@@ -92,17 +93,19 @@ const (
92
93
SEQ_MODE_FILO
93
94
)
94
95
95
- func (r * T [C ]) Seq (seqMode SeqMode ) func (yield func (uint , C ) bool ) {
96
- return func (yield func (uint , C ) bool ) {
96
+ func (r * T [C ]) Seq (seqMode SeqMode ) func (yield func (uint64 , C ) bool ) {
97
+ return func (yield func (uint64 , C ) bool ) {
97
98
if r .buflen == 0 {
98
99
return
99
100
}
100
101
102
+ head := r .head .Load ()
103
+
101
104
// how many entries can we write?
102
- maxWritable := armath .Min (r . head , r .buflen )
105
+ maxWritable := armath .Min (head , r .buflen )
103
106
104
107
if seqMode == SEQ_MODE_FIFO {
105
- start := (((r . head - 1 ) % r .buflen ) - maxWritable ) % r .buflen
108
+ start := (((head - 1 ) % r .buflen ) - maxWritable ) % r .buflen
106
109
107
110
for i := range maxWritable {
108
111
idx := (start + i ) % r .buflen
@@ -113,7 +116,7 @@ func (r *T[C]) Seq(seqMode SeqMode) func(yield func(uint, C) bool) {
113
116
return
114
117
}
115
118
if seqMode == SEQ_MODE_FILO {
116
- start := r . head - 1
119
+ start := head - 1
117
120
for i := range maxWritable {
118
121
idx := (start - i ) % r .buflen
119
122
if ! yield (i , r .buf [idx ]) {
0 commit comments