@@ -7,17 +7,12 @@ import (
77 "github.com/benburkert/pubsub/cursor"
88)
99
10- type Marker byte
10+ type ReaderFunc[T comparable] func(T) bool
1111
12- const (
13- EmptyMarker Marker = iota
14- )
15-
16- type ReaderFunc func(interface{}) bool
17-
18- type Buffer struct {
19- mu sync.RWMutex
20- data []interface{}
12+ type Buffer[T comparable] struct {
13+ mu sync.RWMutex
14+ data []T
15+ empty T
2116
2217 wcond *sync.Cond
2318 wcursor *cursor.Cursor
@@ -26,26 +21,27 @@ type Buffer struct {
2621 rcursors cursor.Slice
2722}
2823
29- func NewBuffer( minSize, maxReaders int) *Buffer {
30- size := calcBufferSize (minSize)
24+ func NewBuffer[T comparable](empty T, minSize, maxReaders int) *Buffer[T] {
25+ size := CalcBufferSize (minSize)
3126 mask := size - 1
3227
33- b := &Buffer{
34- data: make([]interface{}, size),
28+ b := &Buffer[T]{
29+ data: make([]T, size),
30+ empty: empty,
3531 wcursor: cursor.New(0, mask),
3632 rcursors: cursor.MakeSlice(maxReaders, mask),
3733 }
3834
3935 for i := range b.data {
40- b.data[i] = EmptyMarker
36+ b.data[i] = empty
4137 }
4238
4339 b.wcond = sync.NewCond(&b.mu)
4440 b.rcond = sync.NewCond(b.mu.RLocker())
4541 return b
4642}
4743
48- func (b *Buffer) FullReadTo(rfn ReaderFunc) []interface{} {
44+ func (b *Buffer[T] ) FullReadTo(rfn ReaderFunc[T] ) []T {
4945 b.mu.RLock() // unlocked in readTo
5046
5147 c := b.getCursor() // reset in readTo
@@ -55,7 +51,7 @@ func (b *Buffer) FullReadTo(rfn ReaderFunc) []interface{} {
5551 return s
5652}
5753
58- func (b *Buffer) Read() []interface{} {
54+ func (b *Buffer[T] ) Read() []T {
5955 b.mu.RLock()
6056 defer b.mu.RUnlock()
6157
@@ -65,20 +61,20 @@ func (b *Buffer) Read() []interface{} {
6561 return b.read(c)
6662}
6763
68- func (b *Buffer) ReadTo(rfn ReaderFunc) {
64+ func (b *Buffer[T] ) ReadTo(rfn ReaderFunc[T] ) {
6965 b.mu.RLock() // unlocked in readTo
7066
7167 go b.readTo(b.getCursor(), rfn)
7268}
7369
74- func (b *Buffer) Write(v interface{} ) {
70+ func (b *Buffer[T] ) Write(v T ) {
7571 b.mu.Lock()
7672 defer b.mu.Unlock()
7773
7874 b.write(v)
7975}
8076
81- func (b *Buffer) WriteSlice(vs []interface{} ) {
77+ func (b *Buffer[T] ) WriteSlice(vs []T ) {
8278 b.mu.Lock()
8379 defer b.mu.Unlock()
8480
@@ -88,33 +84,33 @@ func (b *Buffer) WriteSlice(vs []interface{}) {
8884}
8985
9086// assumes b.mu RLock held
91- func (b *Buffer) getCursor() *cursor.Cursor {
87+ func (b *Buffer[T] ) getCursor() *cursor.Cursor {
9288 return b.rcursors.Alloc(b.wcursor.Pos())
9389}
9490
9591// assumes b.mu Rlock held
96- func (b *Buffer) read(c *cursor.Cursor) []interface{} {
92+ func (b *Buffer[T] ) read(c *cursor.Cursor) []T {
9793 rpos := c.Pos()
98- if b.data[rpos] == EmptyMarker {
99- s := make([]interface{} , rpos)
94+ if b.data[rpos] == b.empty {
95+ s := make([]T , rpos)
10096 copy(s, b.data[:rpos])
10197 return s
10298 }
10399
104100 size := int(len(b.data))
105- s := make([]interface{} , size)
101+ s := make([]T , size)
106102 copy(s[:(size-rpos)], b.data[rpos:])
107103 copy(s[(size-rpos):], b.data[:rpos])
108104 return s
109105}
110106
111107// assumes b.mu RLock held
112- func (b *Buffer) readBarrier(c *cursor.Cursor) bool {
108+ func (b *Buffer[T] ) readBarrier(c *cursor.Cursor) bool {
113109 return c.Pos() == b.wcursor.Pos()
114110}
115111
116112// asumes b.mu RLock held
117- func (b *Buffer) readTo(c *cursor.Cursor, rfn ReaderFunc) {
113+ func (b *Buffer[T] ) readTo(c *cursor.Cursor, rfn ReaderFunc[T] ) {
118114 defer b.mu.RUnlock()
119115 defer b.wcond.Signal()
120116 defer c.Reset()
@@ -136,7 +132,7 @@ func (b *Buffer) readTo(c *cursor.Cursor, rfn ReaderFunc) {
136132}
137133
138134// asumes b.mu Lock held
139- func (b *Buffer) write(v interface{} ) {
135+ func (b *Buffer[T] ) write(v T ) {
140136 for b.writeBarrier() {
141137 b.wcond.Wait()
142138 }
@@ -149,7 +145,7 @@ func (b *Buffer) write(v interface{}) {
149145}
150146
151147// assumes b.mu Lock held
152- func (b *Buffer) writeBarrier() bool {
148+ func (b *Buffer[T] ) writeBarrier() bool {
153149 npos := b.wcursor.Next()
154150 for _, c := range b.rcursors {
155151 if npos == c.Pos() {
@@ -159,6 +155,6 @@ func (b *Buffer) writeBarrier() bool {
159155 return false
160156}
161157
162- func calcBufferSize (minSize int) int {
158+ func CalcBufferSize (minSize int) int {
163159 return int(math.Pow(2, math.Ceil(math.Log2(float64(minSize)))))
164160}
0 commit comments