Skip to content

Commit 9f6089c

Browse files
committed
part: options as bitfield
Signed-off-by: Jussi Maki <[email protected]>
1 parent db2bd06 commit 9f6089c

File tree

5 files changed

+53
-27
lines changed

5 files changed

+53
-27
lines changed

part/node.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -444,12 +444,12 @@ type leaf[T any] struct {
444444
key []byte
445445
}
446446

447-
func newLeaf[T any](o *options, prefix, key []byte, value T) *leaf[T] {
447+
func newLeaf[T any](o options, prefix, key []byte, value T) *leaf[T] {
448448
leaf := &leaf[T]{key: key, value: value}
449449
leaf.setPrefix(prefix)
450450
leaf.setKind(nodeKindLeaf)
451451

452-
if !o.rootOnlyWatch {
452+
if !o.rootOnlyWatch() {
453453
leaf.watch = make(chan struct{})
454454
}
455455

part/options.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
// Copyright Authors of Cilium
3+
4+
package part
5+
6+
type options uint8
7+
8+
const (
9+
rootOnlyWatchOpt = options(1 << 1)
10+
noCacheOpt = options(1 << 2)
11+
)
12+
13+
func (o *options) setRootOnlyWatch() {
14+
*o |= rootOnlyWatchOpt
15+
}
16+
17+
func (o *options) setNoCache() {
18+
*o |= noCacheOpt
19+
20+
}
21+
func (o options) rootOnlyWatch() bool {
22+
return o&rootOnlyWatchOpt != 0
23+
}
24+
25+
func (o options) noCache() bool {
26+
return o&noCacheOpt != 0
27+
}

part/part_test.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1066,7 +1066,11 @@ func Benchmark_Replace_RootOnlyWatch(b *testing.B) {
10661066
}
10671067

10681068
func benchmark_Replace(b *testing.B, watching bool) {
1069-
tree := New[int](RootOnlyWatch)
1069+
var opts []Option
1070+
if watching {
1071+
opts = append(opts, RootOnlyWatch)
1072+
}
1073+
tree := New[int](opts...)
10701074
txn := tree.Txn()
10711075
for i := range numObjectsToInsert {
10721076
key := binary.BigEndian.AppendUint32(nil, uint32(numObjectsToInsert+i))

part/tree.go

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ package part
99
// has an associated channel that is closed when that node is mutated.
1010
// This allows watching any part of the tree (any prefix) for changes.
1111
type Tree[T any] struct {
12-
opts *options
1312
root *header[T]
1413
txn *Txn[T]
1514
size int // the number of objects in the tree
15+
opts options
1616
}
1717

1818
// New constructs a new tree.
@@ -24,10 +24,10 @@ func New[T any](opts ...Option) *Tree[T] {
2424
t := &Tree[T]{
2525
root: newNode4[T](),
2626
size: 0,
27-
opts: &o,
27+
opts: o,
2828
}
29-
if !o.noCache {
30-
t.txn = newTxn[T](&o)
29+
if !o.noCache() {
30+
t.txn = newTxn[T](o)
3131
}
3232
return t
3333
}
@@ -37,16 +37,16 @@ type Option func(*options)
3737
// RootOnlyWatch sets the tree to only have a watch channel on the root
3838
// node. This improves the speed at the cost of having a much more coarse
3939
// grained notifications.
40-
func RootOnlyWatch(o *options) { o.rootOnlyWatch = true }
40+
var RootOnlyWatch = (*options).setRootOnlyWatch
4141

4242
// NoCache disables the mutated node cache
43-
func NoCache(o *options) { o.noCache = true }
43+
var NoCache = (*options).setNoCache
4444

45-
func newTxn[T any](o *options) *Txn[T] {
45+
func newTxn[T any](o options) *Txn[T] {
4646
txn := &Txn[T]{
4747
watches: make(map[chan struct{}]struct{}),
4848
}
49-
if !o.noCache {
49+
if !o.noCache() {
5050
txn.mutated = &nodeMutated{}
5151
txn.deleteParentsCache = make([]deleteParent[T], 0, 32)
5252
}
@@ -83,7 +83,7 @@ func (t *Tree[T]) Len() int {
8383
// value was found.
8484
func (t *Tree[T]) Get(key []byte) (T, <-chan struct{}, bool) {
8585
value, watch, ok := search(t.root, key)
86-
if t.opts.rootOnlyWatch {
86+
if t.opts.rootOnlyWatch() {
8787
watch = t.root.watch
8888
}
8989
return value, watch, ok
@@ -94,7 +94,7 @@ func (t *Tree[T]) Get(key []byte) (T, <-chan struct{}, bool) {
9494
// the given prefix are upserted or deleted.
9595
func (t *Tree[T]) Prefix(prefix []byte) (*Iterator[T], <-chan struct{}) {
9696
iter, watch := prefixSearch(t.root, prefix)
97-
if t.opts.rootOnlyWatch {
97+
if t.opts.rootOnlyWatch() {
9898
watch = t.root.watch
9999
}
100100
return iter, watch
@@ -151,8 +151,3 @@ func (t *Tree[T]) Iterator() *Iterator[T] {
151151
func (t *Tree[T]) PrintTree() {
152152
t.root.printTree(0)
153153
}
154-
155-
type options struct {
156-
rootOnlyWatch bool
157-
noCache bool
158-
}

part/txn.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ import (
1010
// Txn is a transaction against a tree. It allows doing efficient
1111
// modifications to a tree by caching and reusing cloned nodes.
1212
type Txn[T any] struct {
13-
opts *options
1413
root *header[T]
14+
opts options
1515
size int // the number of objects in the tree
1616

1717
// mutated is the set of nodes mutated in this transaction
@@ -63,7 +63,7 @@ func (txn *Txn[T]) InsertWatch(key []byte, value T) (old T, hadOld bool, watch <
6363
if !hadOld {
6464
txn.size++
6565
}
66-
if txn.opts.rootOnlyWatch {
66+
if txn.opts.rootOnlyWatch() {
6767
watch = txn.root.watch
6868
}
6969
return
@@ -88,7 +88,7 @@ func (txn *Txn[T]) ModifyWatch(key []byte, mod func(T) T) (old T, hadOld bool, w
8888
if !hadOld {
8989
txn.size++
9090
}
91-
if txn.opts.rootOnlyWatch {
91+
if txn.opts.rootOnlyWatch() {
9292
watch = txn.root.watch
9393
}
9494
return
@@ -117,7 +117,7 @@ func (txn *Txn[T]) RootWatch() <-chan struct{} {
117117
// value was found.
118118
func (txn *Txn[T]) Get(key []byte) (T, <-chan struct{}, bool) {
119119
value, watch, ok := search(txn.root, key)
120-
if txn.opts.rootOnlyWatch {
120+
if txn.opts.rootOnlyWatch() {
121121
watch = txn.root.watch
122122
}
123123
return value, watch, ok
@@ -129,7 +129,7 @@ func (txn *Txn[T]) Get(key []byte) (T, <-chan struct{}, bool) {
129129
func (txn *Txn[T]) Prefix(key []byte) (*Iterator[T], <-chan struct{}) {
130130
txn.mutated.clear()
131131
iter, watch := prefixSearch(txn.root, key)
132-
if txn.opts.rootOnlyWatch {
132+
if txn.opts.rootOnlyWatch() {
133133
watch = txn.root.watch
134134
}
135135
return iter, watch
@@ -160,7 +160,7 @@ func (txn *Txn[T]) Commit() *Tree[T] {
160160
// Tree.Txn().
161161
func (txn *Txn[T]) CommitOnly() *Tree[T] {
162162
t := &Tree[T]{opts: txn.opts, root: txn.root, size: txn.size}
163-
if !txn.opts.noCache {
163+
if !txn.opts.noCache() {
164164
t.txn = txn
165165
}
166166
return t
@@ -188,7 +188,7 @@ func (txn *Txn[T]) cloneNode(n *header[T]) *header[T] {
188188
if n.watch != nil {
189189
txn.watches[n.watch] = struct{}{}
190190
}
191-
n = n.clone(!txn.opts.rootOnlyWatch || n == txn.root)
191+
n = n.clone(!txn.opts.rootOnlyWatch() || n == txn.root)
192192
nodeMutatedSet(txn.mutated, n)
193193
return n
194194
}
@@ -225,7 +225,7 @@ func (txn *Txn[T]) modify(root *header[T], key []byte, mod func(T) T) (oldValue
225225
if this.watch != nil {
226226
txn.watches[this.watch] = struct{}{}
227227
}
228-
this = this.promote(!txn.opts.rootOnlyWatch || this == root)
228+
this = this.promote(!txn.opts.rootOnlyWatch() || this == root)
229229
nodeMutatedSet(txn.mutated, this)
230230
} else {
231231
// Node is big enough, clone it so we can mutate it
@@ -298,7 +298,7 @@ func (txn *Txn[T]) modify(root *header[T], key []byte, mod func(T) T) (oldValue
298298
newNode := &node4[T]{}
299299
newNode.setPrefix(common)
300300
newNode.setKind(nodeKind4)
301-
if !txn.opts.rootOnlyWatch {
301+
if !txn.opts.rootOnlyWatch() {
302302
newNode.watch = make(chan struct{})
303303
}
304304

0 commit comments

Comments
 (0)