github.com/tursom/GoCollections@v0.3.10/lang/atomic/Atomic.go (about) 1 /* 2 * Copyright (c) 2022 tursom. All rights reserved. 3 * Use of this source code is governed by a GPL-3 4 * license that can be found in the LICENSE file. 5 */ 6 7 package atomic 8 9 import ( 10 "sync/atomic" 11 "unsafe" 12 13 "github.com/tursom/GoCollections/lang" 14 ) 15 16 type ( 17 Atomic[T any] interface { 18 Swap(new T) (old T) 19 CompareAndSwap(old, new T) (swapped bool) 20 Load() (val T) 21 Store(val T) 22 } 23 24 BitSet interface { 25 lang.BitSet 26 CompareAndSwapBit(bit int, old, new bool) (swapped bool) 27 } 28 29 Atomizer[T any] interface { 30 Swap() func(addr *T, new T) (old T) 31 CompareAndSwap() func(addr *T, old, new T) (swapped bool) 32 Load() func(addr *T) (val T) 33 Store() func(addr *T, val T) 34 } 35 36 atomizerImpl[T any] struct { 37 swap func(addr *T, new T) (old T) 38 compareAndSwap func(addr *T, old, new T) (swapped bool) 39 load func(addr *T) (val T) 40 store func(addr *T, val T) 41 } 42 ) 43 44 var ( 45 int32Atomizer = &atomizerImpl[int32]{ 46 SwapInt32, 47 CompareAndSwapInt32, 48 LoadInt32, 49 StoreInt32, 50 } 51 int64Atomizer = &atomizerImpl[int64]{ 52 SwapInt64, 53 CompareAndSwapInt64, 54 LoadInt64, 55 StoreInt64, 56 } 57 uint32Atomizer = &atomizerImpl[uint32]{ 58 SwapUInt32, 59 CompareAndSwapUInt32, 60 LoadUint32, 61 StoreUInt32, 62 } 63 uint64Atomizer = &atomizerImpl[uint64]{ 64 SwapUInt64, 65 CompareAndSwapUInt64, 66 LoadUint64, 67 StoreUInt64, 68 } 69 pointerAtomizer = &atomizerImpl[unsafe.Pointer]{ 70 atomic.SwapPointer, 71 atomic.CompareAndSwapPointer, 72 atomic.LoadPointer, 73 atomic.StorePointer, 74 } 75 ) 76 77 func Int32Atomizer() Atomizer[int32] { 78 return int32Atomizer 79 } 80 81 func Int64Atomizer() Atomizer[int64] { 82 return int64Atomizer 83 } 84 85 func UInt32Atomizer() Atomizer[uint32] { 86 return uint32Atomizer 87 } 88 89 func UInt64Atomizer() Atomizer[uint64] { 90 return uint64Atomizer 91 } 92 93 func PointerAtomizer() Atomizer[unsafe.Pointer] { 94 return pointerAtomizer 95 } 96 97 func GetAtomizer[T any]() Atomizer[*T] { 98 return (*atomizerImpl[*T])(unsafe.Pointer(pointerAtomizer)) 99 } 100 101 func (a *atomizerImpl[T]) Swap() func(addr *T, new T) (old T) { 102 return a.swap 103 } 104 105 func (a *atomizerImpl[T]) CompareAndSwap() func(addr *T, old T, new T) (swapped bool) { 106 return a.compareAndSwap 107 } 108 109 func (a *atomizerImpl[T]) Load() func(addr *T) (val T) { 110 return a.load 111 } 112 113 func (a *atomizerImpl[T]) Store() func(addr *T, val T) { 114 return a.store 115 } 116 117 func SwapInt32(addr *int32, new int32) (old int32) { 118 return atomic.SwapInt32(addr, new) 119 } 120 121 func SwapInt64(addr *int64, new int64) (old int64) { 122 return atomic.SwapInt64(addr, new) 123 } 124 125 func SwapUInt32(addr *uint32, new uint32) (old uint32) { 126 return atomic.SwapUint32(addr, new) 127 } 128 129 func SwapUInt64(addr *uint64, new uint64) (old uint64) { 130 return atomic.SwapUint64(addr, new) 131 } 132 133 func SwapUintptr(addr *uintptr, new uintptr) (old uintptr) { 134 return atomic.SwapUintptr(addr, new) 135 } 136 137 func SwapUnsafePointer(addr *unsafe.Pointer, new unsafe.Pointer) (old unsafe.Pointer) { 138 return atomic.SwapPointer(addr, new) 139 } 140 141 func CompareAndSwapInt32(addr *int32, old, new int32) (swapped bool) { 142 return atomic.CompareAndSwapInt32(addr, old, new) 143 } 144 145 func CompareAndSwapInt64(addr *int64, old, new int64) (swapped bool) { 146 return atomic.CompareAndSwapInt64(addr, old, new) 147 } 148 149 func CompareAndSwapUInt32(addr *uint32, old, new uint32) (swapped bool) { 150 return atomic.CompareAndSwapUint32(addr, old, new) 151 } 152 153 func CompareAndSwapUInt64(addr *uint64, old, new uint64) (swapped bool) { 154 return atomic.CompareAndSwapUint64(addr, old, new) 155 } 156 157 func CompareAndSwapUintptr(addr *uintptr, old, new uintptr) (swapped bool) { 158 return atomic.CompareAndSwapUintptr(addr, old, new) 159 } 160 161 func CompareAndSwapUnsafePointer(addr *unsafe.Pointer, old, new unsafe.Pointer) (swapped bool) { 162 return atomic.CompareAndSwapPointer(addr, old, new) 163 } 164 165 func AddInt32(addr *int32, delta int32) (new int32) { 166 return atomic.AddInt32(addr, delta) 167 } 168 169 func AddUInt32(addr *uint32, delta uint32) (new uint32) { 170 return atomic.AddUint32(addr, delta) 171 } 172 173 func AddInt64(addr *int64, delta int64) (new int64) { 174 return atomic.AddInt64(addr, delta) 175 } 176 177 func AddUInt64(addr *uint64, delta uint64) (new uint64) { 178 return atomic.AddUint64(addr, delta) 179 } 180 181 func AddUintptr(addr *uintptr, delta uintptr) (new uintptr) { 182 return atomic.AddUintptr(addr, delta) 183 } 184 185 func LoadInt32(addr *int32) (val int32) { 186 return atomic.LoadInt32(addr) 187 } 188 189 func LoadInt64(addr *int64) (val int64) { 190 return atomic.LoadInt64(addr) 191 } 192 193 func LoadUint32(addr *uint32) (val uint32) { 194 return atomic.LoadUint32(addr) 195 } 196 197 func LoadUint64(addr *uint64) (val uint64) { 198 return atomic.LoadUint64(addr) 199 } 200 201 func LoadUintptr(addr *uintptr) (val uintptr) { 202 return atomic.LoadUintptr(addr) 203 } 204 205 func LoadUnsafePointer(addr *unsafe.Pointer) (val unsafe.Pointer) { 206 return atomic.LoadPointer(addr) 207 } 208 209 func StoreInt32(addr *int32, val int32) { 210 atomic.StoreInt32(addr, val) 211 } 212 213 func StoreInt64(addr *int64, val int64) { 214 atomic.StoreInt64(addr, val) 215 } 216 217 func StoreUInt32(addr *uint32, val uint32) { 218 atomic.StoreUint32(addr, val) 219 } 220 221 func StoreUInt64(addr *uint64, val uint64) { 222 atomic.StoreUint64(addr, val) 223 } 224 225 func StoreUintptr(addr *uintptr, val uintptr) { 226 atomic.StoreUintptr(addr, val) 227 } 228 229 func StoreUnsafePointer(addr *unsafe.Pointer, val unsafe.Pointer) { 230 atomic.StorePointer(addr, val) 231 } 232 233 func SetBit[T int32 | int64 | uint32 | uint64](cas func(p *T, old, new T) bool, p *T, bit int, up bool) bool { 234 location := T(1) << bit 235 var old T 236 for { 237 old = *p 238 var newValue T 239 if up { 240 newValue = old | location 241 } else { 242 newValue = old & ^location 243 } 244 if cas(p, old, newValue) { 245 break 246 } 247 } 248 return old&location != 0 249 } 250 251 func SetBitInt32(p *int32, bit int, up bool) bool { 252 return SetBit(CompareAndSwapInt32, p, bit, up) 253 } 254 255 func SetBitInt64(p *int64, bit int, up bool) bool { 256 return SetBit(CompareAndSwapInt64, p, bit, up) 257 } 258 259 func SetBitUInt32(p *uint32, bit int, up bool) bool { 260 return SetBit(CompareAndSwapUInt32, p, bit, up) 261 } 262 263 func SetBitUInt64(p *uint32, bit int, up bool) bool { 264 return SetBit(CompareAndSwapUInt32, p, bit, up) 265 } 266 267 func CompareAndSwapBit[T int32 | int64 | uint32 | uint64](cas func(p *T, old, new T) bool, p *T, bit int, old, new bool) bool { 268 location := T(1) << bit 269 oldValue := *p 270 if old { 271 oldValue = oldValue | location 272 } else { 273 oldValue = oldValue & ^location 274 } 275 var newValue T 276 if new { 277 newValue = oldValue | location 278 } else { 279 newValue = oldValue & ^location 280 } 281 return cas(p, oldValue, newValue) 282 } 283 284 func CompareAndSwapBitInt32(p *int32, bit int, old, new bool) bool { 285 return CompareAndSwapBit(CompareAndSwapInt32, p, bit, old, new) 286 } 287 288 func CompareAndSwapBitInt64(p *int64, bit int, old, new bool) bool { 289 return CompareAndSwapBit(CompareAndSwapInt64, p, bit, old, new) 290 } 291 292 func CompareAndSwapBitUInt32(p *uint32, bit int, old, new bool) bool { 293 return CompareAndSwapBit(CompareAndSwapUInt32, p, bit, old, new) 294 } 295 296 func CompareAndSwapBitUInt64(p *uint64, bit int, old, new bool) bool { 297 return CompareAndSwapBit(CompareAndSwapUInt64, p, bit, old, new) 298 }