Commit Graph

11 Commits

Author SHA1 Message Date
Prashant Varanasi
1505d282ac Fix Swap and CompareAndSwap for Value wrappers (#130)
* 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.
2023-02-06 01:17:57 -08:00
eNV25
d4bbbc828d Add CompareAndSwap and Swap, Deprecate CAS (#111)
Adds CompareAndSwap and Swap methods to String, Error, and Value,
implemented by making use of Value.CompareAndSwap and Value.Swap
added in Go 1.17.

Following that, add CompareAndSwap to all other types with "CAS" methods
and deprecate CAS in favor of CompareAndSwap, since that's the convention
the standard library chose for these in Go 1.19.
2022-08-06 11:12:19 -07:00
Abhinav Gupta
122c956c5a all: Update copyright notices (#112)
This will reduce noise in other PRs.
2022-08-05 09:19:12 -07:00
Prashant Varanasi
d8a8972198 Improve argument/return names for better docs (#96)
This change is a renaming with no functional changes.

It includes the following renames:
 * `val` for arguments that replace the atomic value (e.g., `Store`).
 * `delta` for arguments that offset the atomic value (e.g., `Add`).
 * `old`, `new` for arguments to `CAS`.
 * `old` named return from `Swap`.
 * `swapped` for named return from `CAS`.

This also matches the names used in the stdlib atomic interface:
https://golang.org/pkg/sync/atomic/
2021-06-11 10:20:12 -07:00
Abhinav Gupta
2a929df6c0 generate: Use year range for license (#92)
The generators gen-atomicint and gen-atomicwrapper hard-coded the year
into the licenses of the generated files.

Update to generate year ranges for the licenses, starting at 2020, going
to whatever today's year is.
2021-06-08 11:27:37 -07:00
Abhinav Gupta
f64e592f7f staticcheck: Fix unused fields
The embedded `nocmp` field and other similar fields are unused in tests
and the rest of our code.

We can get the effect of `nocmp` without embedding the fields by using
`_ nocmp` as a field.
2020-09-11 11:24:56 -07:00
Abhinav Gupta
ddc304d531 Implement fmt.Stringer for atomic types (#76)
Add safe `String()` methods for atomic types that replicate the same
behavior as `fmt.Sprintf("%v", x.Load())` without the allocations.

As with json.Marshaler/Unmarshaler, we've omitted the `atomic.Value`
type for now.

Resolves #50
2020-05-14 16:26:08 -07:00
Abhinav Gupta
982a2dde23 Disallow non-atomic comparisons of atomics (#74)
It is currently possible to make non-atomic comparisons of atomic
values:

    x := atomic.NewInt32(1)
    y := atomic.NewInt32(1)
    fmt.Println(*x == *y)

This is undesirable because it loads the value in a non-atomic way. The
correct method is,

    x := atomic.NewInt32(1)
    y := atomic.NewInt32(1)
    fmt.Println(x.Load() == y.Load())

To prevent this, disallow comparison of atomic values by embedding an
uncomparable array into atomics. The empty array adds no runtime cost,
and does not increase the in-memory size of the structs. Inspired by
[go4.org/mem#RO][1].

  [1]: 3dbcd07079/mem.go (L42)

Note that the Value struct, which embeds `"sync/atomic".Value` was also
changed. This will break usages in the following form, but that's
acceptable because unkeyed struct literals are among the exceptions
stated in the [Go 1 compatibility expectations][2].

    import (
      syncatomic "sync/atomic"
      "go.uber.org/atomic"
    )

    atomic.Value{syncatomic.Value{..}}

  [2]: https://golang.org/doc/go1compat#expectations

Resolves #72
2020-05-12 13:57:19 -07:00
Abhinav Gupta
5ed3279fd8 Mark generated files as such (#75)
Generated files should contain the following comment in the first few
lines for them to be considered generated by GitHub.

    Code generated by <executable>

The additional `@generated` tag does the same for Phabricator.
2020-05-12 13:49:16 -07:00
Abhinav Gupta
d9a13c26a5 Generate atomic integers automatically
Rather than hand-writing the atomic integers, generate them
automatically from the same template. The generator is at
internal/gen-atomicint.

To ensure these are never out of date, add another `make` target which
verifies that the working tree is left unchanged after regenerating
code.
2020-05-12 11:30:09 -07:00
Abhinav Gupta
530718eef1 ints: Pull types into independent files
In anticipation of automatically generating these definitions, pull the
definitions of the various integer types into their own files as well as
their tests.

This will make it easier to review the changes when each of these files
is generated independently and automatically.
2020-05-11 16:15:06 -07:00