...
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 interface{}
18 }
19
20
21 type ifaceWords struct {
22 typ unsafe.Pointer
23 data unsafe.Pointer
24 }
25
26
27
28 func (v *Value) Load() (val interface{}) {
29 vp := (*ifaceWords)(unsafe.Pointer(v))
30 typ := LoadPointer(&vp.typ)
31 if typ == nil || uintptr(typ) == ^uintptr(0) {
32
33 return nil
34 }
35 data := LoadPointer(&vp.data)
36 vlp := (*ifaceWords)(unsafe.Pointer(&val))
37 vlp.typ = typ
38 vlp.data = data
39 return
40 }
41
42
43
44
45 func (v *Value) Store(val interface{}) {
46 if val == nil {
47 panic("sync/atomic: store of nil value into Value")
48 }
49 vp := (*ifaceWords)(unsafe.Pointer(v))
50 vlp := (*ifaceWords)(unsafe.Pointer(&val))
51 for {
52 typ := LoadPointer(&vp.typ)
53 if typ == nil {
54
55
56
57
58 runtime_procPin()
59 if !CompareAndSwapPointer(&vp.typ, nil, unsafe.Pointer(^uintptr(0))) {
60 runtime_procUnpin()
61 continue
62 }
63
64 StorePointer(&vp.data, vlp.data)
65 StorePointer(&vp.typ, vlp.typ)
66 runtime_procUnpin()
67 return
68 }
69 if uintptr(typ) == ^uintptr(0) {
70
71
72
73 continue
74 }
75
76 if typ != vlp.typ {
77 panic("sync/atomic: store of inconsistently typed value into Value")
78 }
79 StorePointer(&vp.data, vlp.data)
80 return
81 }
82 }
83
84
85
86
87
88
89 func (v *Value) Swap(new interface{}) (old interface{}) {
90 if new == nil {
91 panic("sync/atomic: swap of nil value into Value")
92 }
93 vp := (*ifaceWords)(unsafe.Pointer(v))
94 np := (*ifaceWords)(unsafe.Pointer(&new))
95 for {
96 typ := LoadPointer(&vp.typ)
97 if typ == nil {
98
99
100
101
102 runtime_procPin()
103 if !CompareAndSwapPointer(&vp.typ, nil, unsafe.Pointer(^uintptr(0))) {
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 uintptr(typ) == ^uintptr(0) {
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 := (*ifaceWords)(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 interface{}) (swapped bool) {
135 if new == nil {
136 panic("sync/atomic: compare and swap of nil value into Value")
137 }
138 vp := (*ifaceWords)(unsafe.Pointer(v))
139 np := (*ifaceWords)(unsafe.Pointer(&new))
140 op := (*ifaceWords)(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
154 runtime_procPin()
155 if !CompareAndSwapPointer(&vp.typ, nil, unsafe.Pointer(^uintptr(0))) {
156 runtime_procUnpin()
157 continue
158 }
159
160 StorePointer(&vp.data, np.data)
161 StorePointer(&vp.typ, np.typ)
162 runtime_procUnpin()
163 return true
164 }
165 if uintptr(typ) == ^uintptr(0) {
166
167
168
169 continue
170 }
171
172 if typ != np.typ {
173 panic("sync/atomic: compare and swap of inconsistently typed value into Value")
174 }
175
176
177
178
179
180 data := LoadPointer(&vp.data)
181 var i interface{}
182 (*ifaceWords)(unsafe.Pointer(&i)).typ = typ
183 (*ifaceWords)(unsafe.Pointer(&i)).data = data
184 if i != old {
185 return false
186 }
187 return CompareAndSwapPointer(&vp.data, data, np.data)
188 }
189 }
190
191
192 func runtime_procPin()
193 func runtime_procUnpin()
194
View as plain text