github.com/cockroachdb/cockroachdb-parser@v0.23.3-0.20240213214944-911057d40c9a/pkg/util/syncutil/atomic.go (about) 1 // Copyright 2017 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package syncutil 12 13 import ( 14 "math" 15 "sync/atomic" 16 ) 17 18 // AtomicFloat64 mimics the atomic types in the sync/atomic standard library, 19 // but for the float64 type. If you'd like to implement additional methods, 20 // consider checking out the expvar Float type for guidance: 21 // https://golang.org/src/expvar/expvar.go?s=2188:2222#L69 22 type AtomicFloat64 uint64 23 24 // StoreFloat64 atomically stores a float64 value into the provided address. 25 func StoreFloat64(addr *AtomicFloat64, val float64) { 26 atomic.StoreUint64((*uint64)(addr), math.Float64bits(val)) 27 } 28 29 // LoadFloat64 atomically loads tha float64 value from the provided address. 30 func LoadFloat64(addr *AtomicFloat64) (val float64) { 31 return math.Float64frombits(atomic.LoadUint64((*uint64)(addr))) 32 } 33 34 func AddFloat64(addr *AtomicFloat64, add float64) (val float64) { 35 for { 36 oldFloat := LoadFloat64(addr) 37 oldInt := math.Float64bits(oldFloat) 38 newFloat := oldFloat + add 39 newInt := math.Float64bits(newFloat) 40 if atomic.CompareAndSwapUint64((*uint64)(addr), oldInt, newInt) { 41 return 42 } 43 } 44 } 45 46 func StoreFloat64IfHigher(addr *AtomicFloat64, new float64) (val float64) { 47 for { 48 oldFloat := LoadFloat64(addr) 49 if oldFloat > new { 50 return 51 } 52 oldInt := math.Float64bits(oldFloat) 53 newInt := math.Float64bits(new) 54 if atomic.CompareAndSwapUint64((*uint64)(addr), oldInt, newInt) { 55 return 56 } 57 } 58 } 59 60 // AtomicBool mimics an atomic boolean. 61 type AtomicBool uint32 62 63 // Set atomically sets the boolean. 64 func (b *AtomicBool) Set(v bool) { 65 s := uint32(0) 66 if v { 67 s = 1 68 } 69 atomic.StoreUint32((*uint32)(b), s) 70 } 71 72 // Get atomically gets the boolean. 73 func (b *AtomicBool) Get() bool { 74 return atomic.LoadUint32((*uint32)(b)) != 0 75 } 76 77 // Swap atomically swaps the value. 78 func (b *AtomicBool) Swap(v bool) bool { 79 wanted := uint32(0) 80 if v { 81 wanted = 1 82 } 83 return atomic.SwapUint32((*uint32)(b), wanted) != 0 84 } 85 86 // AtomicString gives you atomic-style APIs for string. 87 type AtomicString struct { 88 s atomic.Value 89 } 90 91 // Set atomically sets str as new value. 92 func (s *AtomicString) Set(val string) { 93 s.s.Store(val) 94 } 95 96 // Get atomically returns the current value. 97 func (s *AtomicString) Get() string { 98 val := s.s.Load() 99 if val == nil { 100 return "" 101 } 102 return val.(string) 103 }