1
2
3
4
5 package atomic
6
7 import (
8 "unsafe"
9 )
10
11
12
13
14
15
16 type Value struct {
17 v any
18 }
19
20
21 type efaceWords struct {
22 typ unsafe.Pointer
23 data unsafe.Pointer
24 }
25
26
27
28 func (v *Value) Load() (val any) {
29 vp := (*efaceWords)(unsafe.Pointer(v))
30 typ := LoadPointer(&vp.typ)
31 if typ == nil || typ == unsafe.Pointer(&firstStoreInProgress) {
32
33 return nil
34 }
35 data := LoadPointer(&vp.data)
36 vlp := (*efaceWords)(unsafe.Pointer(&val))
37 vlp.typ = typ
38 vlp.data = data
39 return
40 }
41
42 var firstStoreInProgress byte
43
44
45
46
47 func (v *Value) Store(val any) {
48 if val == nil {
49 panic("sync/atomic: store of nil value into Value")
50 }
51 vp := (*efaceWords)(unsafe.Pointer(v))
52 vlp := (*efaceWords)(unsafe.Pointer(&val))
53 for {
54 typ := LoadPointer(&vp.typ)
55 if typ == nil {
56
57
58
59 runtime_procPin()
60 if !CompareAndSwapPointer(&vp.typ, nil, unsafe.Pointer(&firstStoreInProgress)) {
61 runtime_procUnpin()
62 continue
63 }
64
65 StorePointer(&vp.data, vlp.data)
66 StorePointer(&vp.typ, vlp.typ)
67 runtime_procUnpin()
68 return
69 }
70 if typ == unsafe.Pointer(&firstStoreInProgress) {
71
72
73
74 continue
75 }
76
77 if typ != vlp.typ {
78 panic("sync/atomic: store of inconsistently typed value into Value")
79 }
80 StorePointer(&vp.data, vlp.data)
81 return
82 }
83 }
84
85
86
87
88
89
90 func (v *Value) Swap(new any) (old any) {
91 if new == nil {
92 panic("sync/atomic: swap of nil value into Value")
93 }
94 vp := (*efaceWords)(unsafe.Pointer(v))
95 np := (*efaceWords)(unsafe.Pointer(&new))
96 for {
97 typ := LoadPointer(&vp.typ)
98 if typ == nil {
99
100
101
102 runtime_procPin()
103 if !CompareAndSwapPointer(&vp.typ, nil, unsafe.Pointer(&firstStoreInProgress)) {
104 runtime_procUnpin()
105 continue
106 }
107
108 StorePointer(&vp.data, np.data)
109 StorePointer(&vp.typ, np.typ)
110 runtime_procUnpin()
111 return nil
112 }
113 if typ == unsafe.Pointer(&firstStoreInProgress) {
114
115
116
117 continue
118 }
119
120 if typ != np.typ {
121 panic("sync/atomic: swap of inconsistently typed value into Value")
122 }
123 op := (*efaceWords)(unsafe.Pointer(&old))
124 op.typ, op.data = np.typ, SwapPointer(&vp.data, np.data)
125 return old
126 }
127 }
128
129
130
131
132
133
134 func (v *Value) CompareAndSwap(old, new any) (swapped bool) {
135 if new == nil {
136 panic("sync/atomic: compare and swap of nil value into Value")
137 }
138 vp := (*efaceWords)(unsafe.Pointer(v))
139 np := (*efaceWords)(unsafe.Pointer(&new))
140 op := (*efaceWords)(unsafe.Pointer(&old))
141 if op.typ != nil && np.typ != op.typ {
142 panic("sync/atomic: compare and swap of inconsistently typed values")
143 }
144 for {
145 typ := LoadPointer(&vp.typ)
146 if typ == nil {
147 if old != nil {
148 return false
149 }
150
151
152
153 runtime_procPin()
154 if !CompareAndSwapPointer(&vp.typ, nil, unsafe.Pointer(&firstStoreInProgress)) {
155 runtime_procUnpin()
156 continue
157 }
158
159 StorePointer(&vp.data, np.data)
160 StorePointer(&vp.typ, np.typ)
161 runtime_procUnpin()
162 return true
163 }
164 if typ == unsafe.Pointer(&firstStoreInProgress) {
165
166
167
168 continue
169 }
170
171 if typ != np.typ {
172 panic("sync/atomic: compare and swap of inconsistently typed value into Value")
173 }
174
175
176
177
178
179 data := LoadPointer(&vp.data)
180 var i any
181 (*efaceWords)(unsafe.Pointer(&i)).typ = typ
182 (*efaceWords)(unsafe.Pointer(&i)).data = data
183 if i != old {
184 return false
185 }
186 return CompareAndSwapPointer(&vp.data, data, np.data)
187 }
188 }
189
190
191 func runtime_procPin() int
192 func runtime_procUnpin()
193
View as plain text