...
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
103 runtime_procPin()
104 if !CompareAndSwapPointer(&vp.typ, nil, unsafe.Pointer(&firstStoreInProgress)) {
105 runtime_procUnpin()
106 continue
107 }
108
109 StorePointer(&vp.data, np.data)
110 StorePointer(&vp.typ, np.typ)
111 runtime_procUnpin()
112 return nil
113 }
114 if typ == unsafe.Pointer(&firstStoreInProgress) {
115
116
117
118 continue
119 }
120
121 if typ != np.typ {
122 panic("sync/atomic: swap of inconsistently typed value into Value")
123 }
124 op := (*efaceWords)(unsafe.Pointer(&old))
125 op.typ, op.data = np.typ, SwapPointer(&vp.data, np.data)
126 return old
127 }
128 }
129
130
131
132
133
134
135 func (v *Value) CompareAndSwap(old, new any) (swapped bool) {
136 if new == nil {
137 panic("sync/atomic: compare and swap of nil value into Value")
138 }
139 vp := (*efaceWords)(unsafe.Pointer(v))
140 np := (*efaceWords)(unsafe.Pointer(&new))
141 op := (*efaceWords)(unsafe.Pointer(&old))
142 if op.typ != nil && np.typ != op.typ {
143 panic("sync/atomic: compare and swap of inconsistently typed values")
144 }
145 for {
146 typ := LoadPointer(&vp.typ)
147 if typ == nil {
148 if old != nil {
149 return false
150 }
151
152
153
154
155 runtime_procPin()
156 if !CompareAndSwapPointer(&vp.typ, nil, unsafe.Pointer(&firstStoreInProgress)) {
157 runtime_procUnpin()
158 continue
159 }
160
161 StorePointer(&vp.data, np.data)
162 StorePointer(&vp.typ, np.typ)
163 runtime_procUnpin()
164 return true
165 }
166 if typ == unsafe.Pointer(&firstStoreInProgress) {
167
168
169
170 continue
171 }
172
173 if typ != np.typ {
174 panic("sync/atomic: compare and swap of inconsistently typed value into Value")
175 }
176
177
178
179
180
181 data := LoadPointer(&vp.data)
182 var i any
183 (*efaceWords)(unsafe.Pointer(&i)).typ = typ
184 (*efaceWords)(unsafe.Pointer(&i)).data = data
185 if i != old {
186 return false
187 }
188 return CompareAndSwapPointer(&vp.data, data, np.data)
189 }
190 }
191
192
193 func runtime_procPin() int
194 func runtime_procUnpin()
195
View as plain text