float32_ext.go 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. // Copyright (c) 2020-2022 Uber Technologies, Inc.
  2. //
  3. // Permission is hereby granted, free of charge, to any person obtaining a copy
  4. // of this software and associated documentation files (the "Software"), to deal
  5. // in the Software without restriction, including without limitation the rights
  6. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. // copies of the Software, and to permit persons to whom the Software is
  8. // furnished to do so, subject to the following conditions:
  9. //
  10. // The above copyright notice and this permission notice shall be included in
  11. // all copies or substantial portions of the Software.
  12. //
  13. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  19. // THE SOFTWARE.
  20. package atomic
  21. import (
  22. "math"
  23. "strconv"
  24. )
  25. //go:generate bin/gen-atomicwrapper -name=Float32 -type=float32 -wrapped=Uint32 -pack=math.Float32bits -unpack=math.Float32frombits -swap -json -imports math -file=float32.go
  26. // Add atomically adds to the wrapped float32 and returns the new value.
  27. func (f *Float32) Add(delta float32) float32 {
  28. for {
  29. old := f.Load()
  30. new := old + delta
  31. if f.CAS(old, new) {
  32. return new
  33. }
  34. }
  35. }
  36. // Sub atomically subtracts from the wrapped float32 and returns the new value.
  37. func (f *Float32) Sub(delta float32) float32 {
  38. return f.Add(-delta)
  39. }
  40. // CAS is an atomic compare-and-swap for float32 values.
  41. //
  42. // Deprecated: Use CompareAndSwap
  43. func (f *Float32) CAS(old, new float32) (swapped bool) {
  44. return f.CompareAndSwap(old, new)
  45. }
  46. // CompareAndSwap is an atomic compare-and-swap for float32 values.
  47. //
  48. // Note: CompareAndSwap handles NaN incorrectly. NaN != NaN using Go's inbuilt operators
  49. // but CompareAndSwap allows a stored NaN to compare equal to a passed in NaN.
  50. // This avoids typical CompareAndSwap loops from blocking forever, e.g.,
  51. //
  52. // for {
  53. // old := atom.Load()
  54. // new = f(old)
  55. // if atom.CompareAndSwap(old, new) {
  56. // break
  57. // }
  58. // }
  59. //
  60. // If CompareAndSwap did not match NaN to match, then the above would loop forever.
  61. func (f *Float32) CompareAndSwap(old, new float32) (swapped bool) {
  62. return f.v.CompareAndSwap(math.Float32bits(old), math.Float32bits(new))
  63. }
  64. // String encodes the wrapped value as a string.
  65. func (f *Float32) String() string {
  66. // 'g' is the behavior for floats with %v.
  67. return strconv.FormatFloat(float64(f.Load()), 'g', -1, 32)
  68. }