You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
While writing a fix + tests for #126, I realized where was a larger issue with how we're handling default values for wrapper-types. We have 2 representations for a default value: the underlying atomic Value is nil, or the atomic Value has the default value. However, having 2 representations causes issues for CompareAndSwap, since we only ever compare against the default value, so we'll never match the nil value.
This simple test shows the issue:
vars atomic.Stringfmt.Println(s.CompareAndSwap("", "foo"))
// Prints: false. Expect true.
This can be worse if there's a loop using CompareAndSwap (typical way to use CompareAndSwap), since it will never succeed when the old value is read from Load(),
// s is an atomic.String.
// If s has never been set, the following loop will never end
for {
old := s.Load()
new := transform(old)
if s.CompareAndSwap(old, new) {
return nil
}
}
The same above code will work for atomic.Int32 and other wrappers around int primitives. This is only an issue with Value primitives. From my testing, this affects String and Error, added in #111.
The text was updated successfully, but these errors were encountered:
* Regenerate code to update copyright end year to 2023
* Test behaviour of default values initialized in different ways
This adds repro tests for #126 and #129
* Fix Swap and CompareAndSwap for Value wrappers
Fixes#126, #129
All atomic types can be used without initialization, e.g., `var v
<AtomicType>`. This works fine for integer types as the initialized
value of 0 matches the default value for the user-facing type. However,
for Value wrappers, they are initialized to `nil`, which is a value that
can't be set (triggers a panic) so the default value for the user-facing
type is forced to be stored as a different value. This leads to multiple
possible values representing the default user-facing type.
E.g., an `atomic.String` with value `""` may be represented by the
underlying atomic as either `nil`, or `""`. This causes issues when we
don't handle the `nil` value correctly, causing to panics in `Swap` and
incorrectly not swapping values in `CompareAndSwap`.
This change fixes the above issues by:
* Requiring `pack` and `unpack` function in gen-atomicwrapper as the
only place we weren't supplying them was for `String`, and the
branching adds unnecessary complexity, especially with added `nil`
handling.
* Extending `CompareAndSwap` for `Value` wrappers to try an additional
`CompareAndSwap(nil, <new>)` only if the original `CompareAndSwap`
fails and the old value is the zero value.
While writing a fix + tests for #126, I realized where was a larger issue with how we're handling default values for wrapper-types. We have 2 representations for a default value: the underlying atomic Value is
nil
, or the atomic Value has the default value. However, having 2 representations causes issues forCompareAndSwap
, since we only ever compare against the default value, so we'll never match thenil
value.This simple test shows the issue:
This can be worse if there's a loop using
CompareAndSwap
(typical way to useCompareAndSwap
), since it will never succeed when the old value is read fromLoad()
,The same above code will work for
atomic.Int32
and other wrappers around int primitives. This is only an issue withValue
primitives. From my testing, this affects String and Error, added in #111.The text was updated successfully, but these errors were encountered: