diff --git a/bool.go b/bool.go index caa373e..ebfc47b 100644 --- a/bool.go +++ b/bool.go @@ -55,8 +55,15 @@ func (x *Bool) Store(val bool) { } // CAS is an atomic compare-and-swap for bool values. +// +// Deprecated: Use CompareAndSwap func (x *Bool) CAS(old, new bool) (swapped bool) { - return x.v.CAS(boolToInt(old), boolToInt(new)) + return x.CompareAndSwap(old, new) +} + +// CompareAndSwap is an atomic compare-and-swap for bool values. +func (x *Bool) CompareAndSwap(old, new bool) (swapped bool) { + return x.v.CompareAndSwap(boolToInt(old), boolToInt(new)) } // Swap atomically stores the given bool and returns the old diff --git a/duration.go b/duration.go index 113f8fb..42a5a72 100644 --- a/duration.go +++ b/duration.go @@ -56,8 +56,15 @@ func (x *Duration) Store(val time.Duration) { } // CAS is an atomic compare-and-swap for time.Duration values. +// +// Deprecated: Use CompareAndSwap func (x *Duration) CAS(old, new time.Duration) (swapped bool) { - return x.v.CAS(int64(old), int64(new)) + return x.CompareAndSwap(old, new) +} + +// CompareAndSwap is an atomic compare-and-swap for time.Duration values. +func (x *Duration) CompareAndSwap(old, new time.Duration) (swapped bool) { + return x.v.CompareAndSwap(int64(old), int64(new)) } // Swap atomically stores the given time.Duration and returns the old diff --git a/error.go b/error.go index d5cdf66..b0db175 100644 --- a/error.go +++ b/error.go @@ -51,8 +51,15 @@ func (x *Error) Store(val error) { } // CAS is an atomic compare-and-swap for error values. +// +// Deprecated: Use CompareAndSwap func (x *Error) CAS(old, new error) (swapped bool) { - return x.v.CAS(packError(old), packError(new)) + return x.CompareAndSwap(old, new) +} + +// CompareAndSwap is an atomic compare-and-swap for error values. +func (x *Error) CompareAndSwap(old, new error) (swapped bool) { + return x.v.CompareAndSwap(packError(old), packError(new)) } // Swap atomically stores the given error and returns the old diff --git a/error_test.go b/error_test.go index 2535658..49d2e2b 100644 --- a/error_test.go +++ b/error_test.go @@ -66,6 +66,22 @@ func TestErrorSwap(t *testing.T) { require.Equal(t, err1, old, "Expected old to be initial value") } +func TestErrorCompareAndSwap(t *testing.T) { + err1 := errors.New("hello1") + err2 := errors.New("hello2") + + atom := NewError(err1) + require.Equal(t, err1, atom.Load(), "Expected Load to return initialized value") + + swapped := atom.CompareAndSwap(err2, err2) + require.Equal(t, swapped, false, "Expected swapped to be false") + require.Equal(t, err1, atom.Load(), "Expected Load to return initial value") + + swapped = atom.CompareAndSwap(err1, err2) + require.Equal(t, swapped, true, "Expected swapped to be true") + require.Equal(t, err2, atom.Load(), "Expected Load to return overridden value") +} + func TestErrorCAS(t *testing.T) { err1 := errors.New("hello1") err2 := errors.New("hello2") diff --git a/float32_ext.go b/float32_ext.go index 39034d2..b0cd8d9 100644 --- a/float32_ext.go +++ b/float32_ext.go @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Uber Technologies, Inc. +// Copyright (c) 2020-2022 Uber Technologies, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -45,21 +45,28 @@ func (f *Float32) Sub(delta float32) float32 { // CAS is an atomic compare-and-swap for float32 values. // -// Note: CAS handles NaN incorrectly. NaN != NaN using Go's inbuilt operators -// but CAS allows a stored NaN to compare equal to a passed in NaN. -// This avoids typical CAS loops from blocking forever, e.g., +// Deprecated: Use CompareAndSwap +func (f *Float32) CAS(old, new float32) (swapped bool) { + return f.CompareAndSwap(old, new) +} + +// CompareAndSwap is an atomic compare-and-swap for float32 values. +// +// Note: CompareAndSwap handles NaN incorrectly. NaN != NaN using Go's inbuilt operators +// but CompareAndSwap allows a stored NaN to compare equal to a passed in NaN. +// This avoids typical CompareAndSwap loops from blocking forever, e.g., // // for { // old := atom.Load() // new = f(old) -// if atom.CAS(old, new) { +// if atom.CompareAndSwap(old, new) { // break // } // } // -// If CAS did not match NaN to match, then the above would loop forever. -func (f *Float32) CAS(old, new float32) (swapped bool) { - return f.v.CAS(math.Float32bits(old), math.Float32bits(new)) +// If CompareAndSwap did not match NaN to match, then the above would loop forever. +func (f *Float32) CompareAndSwap(old, new float32) (swapped bool) { + return f.v.CompareAndSwap(math.Float32bits(old), math.Float32bits(new)) } // String encodes the wrapped value as a string. diff --git a/float64_ext.go b/float64_ext.go index 0bcaaed..48c52b0 100644 --- a/float64_ext.go +++ b/float64_ext.go @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Uber Technologies, Inc. +// Copyright (c) 2020-2022 Uber Technologies, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -45,21 +45,28 @@ func (f *Float64) Sub(delta float64) float64 { // CAS is an atomic compare-and-swap for float64 values. // -// Note: CAS handles NaN incorrectly. NaN != NaN using Go's inbuilt operators -// but CAS allows a stored NaN to compare equal to a passed in NaN. -// This avoids typical CAS loops from blocking forever, e.g., +// Deprecated: Use CompareAndSwap +func (f *Float64) CAS(old, new float64) (swapped bool) { + return f.CompareAndSwap(old, new) +} + +// CompareAndSwap is an atomic compare-and-swap for float64 values. +// +// Note: CompareAndSwap handles NaN incorrectly. NaN != NaN using Go's inbuilt operators +// but CompareAndSwap allows a stored NaN to compare equal to a passed in NaN. +// This avoids typical CompareAndSwap loops from blocking forever, e.g., // // for { // old := atom.Load() // new = f(old) -// if atom.CAS(old, new) { +// if atom.CompareAndSwap(old, new) { // break // } // } // -// If CAS did not match NaN to match, then the above would loop forever. -func (f *Float64) CAS(old, new float64) (swapped bool) { - return f.v.CAS(math.Float64bits(old), math.Float64bits(new)) +// If CompareAndSwap did not match NaN to match, then the above would loop forever. +func (f *Float64) CompareAndSwap(old, new float64) (swapped bool) { + return f.v.CompareAndSwap(math.Float64bits(old), math.Float64bits(new)) } // String encodes the wrapped value as a string. diff --git a/int32.go b/int32.go index b513810..6630c88 100644 --- a/int32.go +++ b/int32.go @@ -66,7 +66,14 @@ func (i *Int32) Dec() int32 { } // CAS is an atomic compare-and-swap. +// +// Deprecated: Use CompareAndSwap func (i *Int32) CAS(old, new int32) (swapped bool) { + return i.CompareAndSwap(old, new) +} + +// CompareAndSwap is an atomic compare-and-swap. +func (i *Int32) CompareAndSwap(old, new int32) (swapped bool) { return atomic.CompareAndSwapInt32(&i.v, old, new) } diff --git a/int64.go b/int64.go index e11a568..db12afd 100644 --- a/int64.go +++ b/int64.go @@ -66,7 +66,14 @@ func (i *Int64) Dec() int64 { } // CAS is an atomic compare-and-swap. +// +// Deprecated: Use CompareAndSwap func (i *Int64) CAS(old, new int64) (swapped bool) { + return i.CompareAndSwap(old, new) +} + +// CompareAndSwap is an atomic compare-and-swap. +func (i *Int64) CompareAndSwap(old, new int64) (swapped bool) { return atomic.CompareAndSwapInt64(&i.v, old, new) } diff --git a/internal/gen-atomicint/main.go b/internal/gen-atomicint/main.go index b00a208..07c8940 100644 --- a/internal/gen-atomicint/main.go +++ b/internal/gen-atomicint/main.go @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Uber Technologies, Inc. +// Copyright (c) 2020-2022 Uber Technologies, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -180,7 +180,14 @@ func (i *{{ .Name }}) Dec() {{ .Wrapped }} { } // CAS is an atomic compare-and-swap. +// +// Deprecated: Use CompareAndSwap func (i *{{ .Name }}) CAS(old, new {{ .Wrapped }}) (swapped bool) { + return i.CompareAndSwap(old, new) +} + +// CompareAndSwap is an atomic compare-and-swap. +func (i *{{ .Name }}) CompareAndSwap(old, new {{ .Wrapped }}) (swapped bool) { return atomic.CompareAndSwap{{ .Name }}(&i.v, old, new) } diff --git a/internal/gen-atomicwrapper/main.go b/internal/gen-atomicwrapper/main.go index 93f09dd..4a01dca 100644 --- a/internal/gen-atomicwrapper/main.go +++ b/internal/gen-atomicwrapper/main.go @@ -263,11 +263,18 @@ func (x *{{ .Name }}) Store(val {{ .Type }}) { {{ if .CAS -}} // CAS is an atomic compare-and-swap for {{ .Type }} values. + // + // Deprecated: Use CompareAndSwap func (x *{{ .Name }}) CAS(old, new {{ .Type }}) (swapped bool) { + return x.CompareAndSwap(old, new) + } + + // CompareAndSwap is an atomic compare-and-swap for {{ .Type }} values. + func (x *{{ .Name }}) CompareAndSwap(old, new {{ .Type }}) (swapped bool) { {{ if .Pack -}} - return x.v.CAS({{ .Pack }}(old), {{ .Pack }}(new)) + return x.v.CompareAndSwap({{ .Pack }}(old), {{ .Pack }}(new)) {{- else -}}{{- /* assume go.uber.org/atomic.Value */ -}} - return x.v.CAS(old, new) + return x.v.CompareAndSwap(old, new) {{- end }} } {{- end }} diff --git a/string.go b/string.go index 410f304..9470a9e 100644 --- a/string.go +++ b/string.go @@ -54,8 +54,15 @@ func (x *String) Store(val string) { } // CAS is an atomic compare-and-swap for string values. +// +// Deprecated: Use CompareAndSwap func (x *String) CAS(old, new string) (swapped bool) { - return x.v.CAS(old, new) + return x.CompareAndSwap(old, new) +} + +// CompareAndSwap is an atomic compare-and-swap for string values. +func (x *String) CompareAndSwap(old, new string) (swapped bool) { + return x.v.CompareAndSwap(old, new) } // Swap atomically stores the given string and returns the old diff --git a/string_test.go b/string_test.go index 82d2024..d0b1e7b 100644 --- a/string_test.go +++ b/string_test.go @@ -83,6 +83,18 @@ func TestString(t *testing.T) { "String() returned an unexpected value.") }) + t.Run("CompareAndSwap", func(t *testing.T) { + atom := NewString("foo") + + swapped := atom.CompareAndSwap("bar", "bar") + require.Equal(t, swapped, false, "swapped isn't false") + require.Equal(t, atom.Load(), "foo", "Load returned wrong value") + + swapped = atom.CompareAndSwap("foo", "bar") + require.Equal(t, swapped, true, "swapped isn't true") + require.Equal(t, atom.Load(), "bar", "Load returned wrong value") + }) + t.Run("CAS", func(t *testing.T) { atom := NewString("foo") diff --git a/uint32.go b/uint32.go index 60e832d..95d92c1 100644 --- a/uint32.go +++ b/uint32.go @@ -66,7 +66,14 @@ func (i *Uint32) Dec() uint32 { } // CAS is an atomic compare-and-swap. +// +// Deprecated: Use CompareAndSwap func (i *Uint32) CAS(old, new uint32) (swapped bool) { + return i.CompareAndSwap(old, new) +} + +// CompareAndSwap is an atomic compare-and-swap. +func (i *Uint32) CompareAndSwap(old, new uint32) (swapped bool) { return atomic.CompareAndSwapUint32(&i.v, old, new) } diff --git a/uint64.go b/uint64.go index 115b3db..36183d5 100644 --- a/uint64.go +++ b/uint64.go @@ -66,7 +66,14 @@ func (i *Uint64) Dec() uint64 { } // CAS is an atomic compare-and-swap. +// +// Deprecated: Use CompareAndSwap func (i *Uint64) CAS(old, new uint64) (swapped bool) { + return i.CompareAndSwap(old, new) +} + +// CompareAndSwap is an atomic compare-and-swap. +func (i *Uint64) CompareAndSwap(old, new uint64) (swapped bool) { return atomic.CompareAndSwapUint64(&i.v, old, new) } diff --git a/uintptr.go b/uintptr.go index e4a361c..2976f05 100644 --- a/uintptr.go +++ b/uintptr.go @@ -66,7 +66,14 @@ func (i *Uintptr) Dec() uintptr { } // CAS is an atomic compare-and-swap. +// +// Deprecated: Use CompareAndSwap func (i *Uintptr) CAS(old, new uintptr) (swapped bool) { + return i.CompareAndSwap(old, new) +} + +// CompareAndSwap is an atomic compare-and-swap. +func (i *Uintptr) CompareAndSwap(old, new uintptr) (swapped bool) { return atomic.CompareAndSwapUintptr(&i.v, old, new) } diff --git a/unsafe_pointer.go b/unsafe_pointer.go index 169f793..34868ba 100644 --- a/unsafe_pointer.go +++ b/unsafe_pointer.go @@ -1,4 +1,4 @@ -// Copyright (c) 2021 Uber Technologies, Inc. +// Copyright (c) 2021-2022 Uber Technologies, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -53,6 +53,13 @@ func (p *UnsafePointer) Swap(val unsafe.Pointer) (old unsafe.Pointer) { } // CAS is an atomic compare-and-swap. +// +// Deprecated: Use CompareAndSwap func (p *UnsafePointer) CAS(old, new unsafe.Pointer) (swapped bool) { + return p.CompareAndSwap(old, new) +} + +// CompareAndSwap is an atomic compare-and-swap. +func (p *UnsafePointer) CompareAndSwap(old, new unsafe.Pointer) (swapped bool) { return atomic.CompareAndSwapPointer(&p.v, old, new) } diff --git a/value.go b/value.go index bb1f40a..d6e32c1 100644 --- a/value.go +++ b/value.go @@ -31,6 +31,8 @@ type Value struct { } // CAS is an atomic compare-and-swap for Value +// +// Deprecated: Use CompareAndSwap func (v *Value) CAS(old, new interface{}) (swapped bool) { return v.CompareAndSwap(old, new) }