-
Notifications
You must be signed in to change notification settings - Fork 28
/
thread_local.go
81 lines (70 loc) · 1.47 KB
/
thread_local.go
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
package routine
import "sync/atomic"
var threadLocalIndex int32 = -1
func nextThreadLocalIndex() int {
index := atomic.AddInt32(&threadLocalIndex, 1)
if index < 0 {
atomic.AddInt32(&threadLocalIndex, -1)
panic("too many thread-local indexed variables")
}
return int(index)
}
type threadLocal[T any] struct {
index int
supplier Supplier[T]
}
func (tls *threadLocal[T]) Get() T {
t := currentThread(true)
mp := tls.getMap(t)
if mp != nil {
v := mp.get(tls.index)
if v != unset {
return entryValue[T](v)
}
}
return tls.setInitialValue(t)
}
func (tls *threadLocal[T]) Set(value T) {
t := currentThread(true)
mp := tls.getMap(t)
if mp != nil {
mp.set(tls.index, entry(value))
} else {
tls.createMap(t, value)
}
}
func (tls *threadLocal[T]) Remove() {
t := currentThread(false)
if t == nil {
return
}
mp := tls.getMap(t)
if mp != nil {
mp.remove(tls.index)
}
}
func (tls *threadLocal[T]) getMap(t *thread) *threadLocalMap {
return t.threadLocals
}
func (tls *threadLocal[T]) createMap(t *thread, firstValue T) {
mp := &threadLocalMap{}
mp.set(tls.index, entry(firstValue))
t.threadLocals = mp
}
func (tls *threadLocal[T]) setInitialValue(t *thread) T {
value := tls.initialValue()
mp := tls.getMap(t)
if mp != nil {
mp.set(tls.index, entry(value))
} else {
tls.createMap(t, value)
}
return value
}
func (tls *threadLocal[T]) initialValue() T {
if tls.supplier == nil {
var defaultValue T
return defaultValue
}
return tls.supplier()
}