summaryrefslogtreecommitdiffhomepage
path: root/syncs/shardvalue.go
blob: fcb5d3c73207ef2e3e37e80bed5fabb01dee3076 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// Copyright (c) Tailscale Inc & contributors
// SPDX-License-Identifier: BSD-3-Clause

package syncs

// TODO(raggi): this implementation is still imperfect as it will still result
// in cross CPU sharing periodically, we instead really want a per-CPU shard
// key, but the limitations of calling platform code make reaching for even the
// getcpu vdso very painful. See https://github.com/golang/go/issues/18802, and
// hopefully one day we can replace with a primitive that falls out of that
// work.

// ShardValue contains a value sharded over a set of shards.
// In order to be useful, T should be aligned to cache lines.
// Users must organize that usage in One and All is concurrency safe.
// The zero value is not safe for use; use [NewShardValue].
type ShardValue[T any] struct {
	shards []T

	//lint:ignore U1000 unused under tailscale_go builds.
	pool shardValuePool
}

// Len returns the number of shards.
func (sp *ShardValue[T]) Len() int {
	return len(sp.shards)
}

// All yields a pointer to the value in each shard.
func (sp *ShardValue[T]) All(yield func(*T) bool) {
	for i := range sp.shards {
		if !yield(&sp.shards[i]) {
			return
		}
	}
}