pax_global_header 0000666 0000000 0000000 00000000064 14060164306 0014512 g ustar 00root root 0000000 0000000 52 comment=0c8e1ec21d9540a9a6b0faea5d750a74a3e002d1
atomic-1.8.0/ 0000775 0000000 0000000 00000000000 14060164306 0012774 5 ustar 00root root 0000000 0000000 atomic-1.8.0/.codecov.yml 0000664 0000000 0000000 00000001561 14060164306 0015222 0 ustar 00root root 0000000 0000000 coverage:
range: 80..100
round: down
precision: 2
status:
project: # measuring the overall project coverage
default: # context, you can create multiple ones with custom titles
enabled: yes # must be yes|true to enable this status
target: 100 # specify the target coverage for each commit status
# option: "auto" (must increase from parent commit or pull request base)
# option: "X%" a static target percentage to hit
if_not_found: success # if parent is not found report status as success, error, or failure
if_ci_failed: error # if ci fails report status as success, error, or failure
# Also update COVER_IGNORE_PKGS in the Makefile.
ignore:
- /internal/gen-atomicint/
- /internal/gen-valuewrapper/
atomic-1.8.0/.github/ 0000775 0000000 0000000 00000000000 14060164306 0014334 5 ustar 00root root 0000000 0000000 atomic-1.8.0/.github/PULL_REQUEST_TEMPLATE.md 0000664 0000000 0000000 00000000455 14060164306 0020141 0 ustar 00root root 0000000 0000000 Before opening your pull request, please make sure that you've:
- [ ] updated the changelog if the change is user-facing;
- [ ] added tests to cover your changes;
- [ ] run the test suite locally (`make test`); and finally,
- [ ] run the linters locally (`make lint`).
Thanks for your contribution!
atomic-1.8.0/.github/workflows/ 0000775 0000000 0000000 00000000000 14060164306 0016371 5 ustar 00root root 0000000 0000000 atomic-1.8.0/.github/workflows/fossa.yaml 0000664 0000000 0000000 00000000502 14060164306 0020365 0 ustar 00root root 0000000 0000000 name: FOSSA Analysis
on: push
jobs:
build:
runs-on: ubuntu-latest
if: github.repository_owner == 'uber-go'
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: FOSSA analysis
uses: fossas/fossa-action@v1
with:
api-key: ${{ secrets.FOSSA_API_KEY }}
atomic-1.8.0/.github/workflows/go.yml 0000664 0000000 0000000 00000001512 14060164306 0017520 0 ustar 00root root 0000000 0000000 name: Go
on:
push:
branches: ['*']
tags: ['v*']
pull_request:
branches: ['*']
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
go: ["1.15.x", "1.16.x"]
include:
- go: 1.16.x
latest: true
steps:
- name: Setup Go
uses: actions/setup-go@v2
with:
go-version: ${{ matrix.go }}
- name: Checkout code
uses: actions/checkout@v2
- name: Load cached dependencies
uses: actions/cache@v1
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
- name: Lint
if: matrix.latest
run: make lint
- name: Test
run: make cover
- name: Upload coverage to codecov.io
uses: codecov/codecov-action@v1
atomic-1.8.0/.gitignore 0000664 0000000 0000000 00000000206 14060164306 0014762 0 ustar 00root root 0000000 0000000 /bin
.DS_Store
/vendor
cover.html
cover.out
lint.log
# Binaries
*.test
# Profiling output
*.prof
# Output of fossa analyzer
/fossa
atomic-1.8.0/CHANGELOG.md 0000664 0000000 0000000 00000005340 14060164306 0014607 0 ustar 00root root 0000000 0000000 # Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [1.8.0] - 2021-06-09
### Added
- Add `atomic.Uintptr` type for atomic operations on `uintptr` values.
- Add `atomic.UnsafePointer` type for atomic operations on `unsafe.Pointer` values.
## [1.7.0] - 2020-09-14
### Added
- Support JSON serialization and deserialization of primitive atomic types.
- Support Text marshalling and unmarshalling for string atomics.
### Changed
- Disallow incorrect comparison of atomic values in a non-atomic way.
### Removed
- Remove dependency on `golang.org/x/{lint, tools}`.
## [1.6.0] - 2020-02-24
### Changed
- Drop library dependency on `golang.org/x/{lint, tools}`.
## [1.5.1] - 2019-11-19
- Fix bug where `Bool.CAS` and `Bool.Toggle` do work correctly together
causing `CAS` to fail even though the old value matches.
## [1.5.0] - 2019-10-29
### Changed
- With Go modules, only the `go.uber.org/atomic` import path is supported now.
If you need to use the old import path, please add a `replace` directive to
your `go.mod`.
## [1.4.0] - 2019-05-01
### Added
- Add `atomic.Error` type for atomic operations on `error` values.
## [1.3.2] - 2018-05-02
### Added
- Add `atomic.Duration` type for atomic operations on `time.Duration` values.
## [1.3.1] - 2017-11-14
### Fixed
- Revert optimization for `atomic.String.Store("")` which caused data races.
## [1.3.0] - 2017-11-13
### Added
- Add `atomic.Bool.CAS` for compare-and-swap semantics on bools.
### Changed
- Optimize `atomic.String.Store("")` by avoiding an allocation.
## [1.2.0] - 2017-04-12
### Added
- Shadow `atomic.Value` from `sync/atomic`.
## [1.1.0] - 2017-03-10
### Added
- Add atomic `Float64` type.
### Changed
- Support new `go.uber.org/atomic` import path.
## [1.0.0] - 2016-07-18
- Initial release.
[1.8.0]: https://github.com/uber-go/atomic/compare/v1.7.0...v1.8.0
[1.7.0]: https://github.com/uber-go/atomic/compare/v1.6.0...v1.7.0
[1.6.0]: https://github.com/uber-go/atomic/compare/v1.5.1...v1.6.0
[1.5.1]: https://github.com/uber-go/atomic/compare/v1.5.0...v1.5.1
[1.5.0]: https://github.com/uber-go/atomic/compare/v1.4.0...v1.5.0
[1.4.0]: https://github.com/uber-go/atomic/compare/v1.3.2...v1.4.0
[1.3.2]: https://github.com/uber-go/atomic/compare/v1.3.1...v1.3.2
[1.3.1]: https://github.com/uber-go/atomic/compare/v1.3.0...v1.3.1
[1.3.0]: https://github.com/uber-go/atomic/compare/v1.2.0...v1.3.0
[1.2.0]: https://github.com/uber-go/atomic/compare/v1.1.0...v1.2.0
[1.1.0]: https://github.com/uber-go/atomic/compare/v1.0.0...v1.1.0
[1.0.0]: https://github.com/uber-go/atomic/releases/tag/v1.0.0
atomic-1.8.0/LICENSE.txt 0000664 0000000 0000000 00000002053 14060164306 0014617 0 ustar 00root root 0000000 0000000 Copyright (c) 2016 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
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
atomic-1.8.0/Makefile 0000664 0000000 0000000 00000004071 14060164306 0014436 0 ustar 00root root 0000000 0000000 # Directory to place `go install`ed binaries into.
export GOBIN ?= $(shell pwd)/bin
GOLINT = $(GOBIN)/golint
GEN_ATOMICINT = $(GOBIN)/gen-atomicint
GEN_ATOMICWRAPPER = $(GOBIN)/gen-atomicwrapper
STATICCHECK = $(GOBIN)/staticcheck
GO_FILES ?= $(shell find . '(' -path .git -o -path vendor ')' -prune -o -name '*.go' -print)
# Also update ignore section in .codecov.yml.
COVER_IGNORE_PKGS = \
go.uber.org/atomic/internal/gen-atomicint \
go.uber.org/atomic/internal/gen-atomicwrapper
.PHONY: build
build:
go build ./...
.PHONY: test
test:
go test -race ./...
.PHONY: gofmt
gofmt:
$(eval FMT_LOG := $(shell mktemp -t gofmt.XXXXX))
gofmt -e -s -l $(GO_FILES) > $(FMT_LOG) || true
@[ ! -s "$(FMT_LOG)" ] || (echo "gofmt failed:" && cat $(FMT_LOG) && false)
$(GOLINT):
cd tools && go install golang.org/x/lint/golint
$(STATICCHECK):
cd tools && go install honnef.co/go/tools/cmd/staticcheck
$(GEN_ATOMICWRAPPER): $(wildcard ./internal/gen-atomicwrapper/*)
go build -o $@ ./internal/gen-atomicwrapper
$(GEN_ATOMICINT): $(wildcard ./internal/gen-atomicint/*)
go build -o $@ ./internal/gen-atomicint
.PHONY: golint
golint: $(GOLINT)
$(GOLINT) ./...
.PHONY: staticcheck
staticcheck: $(STATICCHECK)
$(STATICCHECK) ./...
.PHONY: lint
lint: gofmt golint staticcheck generatenodirty
# comma separated list of packages to consider for code coverage.
COVER_PKG = $(shell \
go list -find ./... | \
grep -v $(foreach pkg,$(COVER_IGNORE_PKGS),-e "^$(pkg)$$") | \
paste -sd, -)
.PHONY: cover
cover:
go test -coverprofile=cover.out -coverpkg $(COVER_PKG) -v ./...
go tool cover -html=cover.out -o cover.html
.PHONY: generate
generate: $(GEN_ATOMICINT) $(GEN_ATOMICWRAPPER)
go generate ./...
.PHONY: generatenodirty
generatenodirty:
@[ -z "$$(git status --porcelain)" ] || ( \
echo "Working tree is dirty. Commit your changes first."; \
git status; \
exit 1 )
@make generate
@status=$$(git status --porcelain); \
[ -z "$$status" ] || ( \
echo "Working tree is dirty after `make generate`:"; \
echo "$$status"; \
echo "Please ensure that the generated code is up-to-date." )
atomic-1.8.0/README.md 0000664 0000000 0000000 00000004001 14060164306 0014246 0 ustar 00root root 0000000 0000000 # atomic [![GoDoc][doc-img]][doc] [![Build Status][ci-img]][ci] [![Coverage Status][cov-img]][cov] [![Go Report Card][reportcard-img]][reportcard]
Simple wrappers for primitive types to enforce atomic access.
## Installation
```shell
$ go get -u go.uber.org/atomic@v1
```
### Legacy Import Path
As of v1.5.0, the import path `go.uber.org/atomic` is the only supported way
of using this package. If you are using Go modules, this package will fail to
compile with the legacy import path path `github.com/uber-go/atomic`.
We recommend migrating your code to the new import path but if you're unable
to do so, or if your dependencies are still using the old import path, you
will have to add a `replace` directive to your `go.mod` file downgrading the
legacy import path to an older version.
```
replace github.com/uber-go/atomic => github.com/uber-go/atomic v1.4.0
```
You can do so automatically by running the following command.
```shell
$ go mod edit -replace github.com/uber-go/atomic=github.com/uber-go/atomic@v1.4.0
```
## Usage
The standard library's `sync/atomic` is powerful, but it's easy to forget which
variables must be accessed atomically. `go.uber.org/atomic` preserves all the
functionality of the standard library, but wraps the primitive types to
provide a safer, more convenient API.
```go
var atom atomic.Uint32
atom.Store(42)
atom.Sub(2)
atom.CAS(40, 11)
```
See the [documentation][doc] for a complete API specification.
## Development Status
Stable.
---
Released under the [MIT License](LICENSE.txt).
[doc-img]: https://godoc.org/github.com/uber-go/atomic?status.svg
[doc]: https://godoc.org/go.uber.org/atomic
[ci-img]: https://github.com/uber-go/atomic/actions/workflows/go.yml/badge.svg
[ci]: https://github.com/uber-go/atomic/actions/workflows/go.yml
[cov-img]: https://codecov.io/gh/uber-go/atomic/branch/master/graph/badge.svg
[cov]: https://codecov.io/gh/uber-go/atomic
[reportcard-img]: https://goreportcard.com/badge/go.uber.org/atomic
[reportcard]: https://goreportcard.com/report/go.uber.org/atomic
atomic-1.8.0/assert_test.go 0000664 0000000 0000000 00000003306 14060164306 0015665 0 ustar 00root root 0000000 0000000 // Copyright (c) 2020 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
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package atomic
import (
"encoding/json"
"errors"
"testing"
"github.com/stretchr/testify/assert"
)
// Marks the test as failed if the error cannot be cast into the provided type
// with errors.As.
//
// assertErrorAsType(t, err, new(ErrFoo))
func assertErrorAsType(t *testing.T, err error, typ interface{}, msgAndArgs ...interface{}) bool {
t.Helper()
return assert.True(t, errors.As(err, typ), msgAndArgs...)
}
func assertErrorJSONUnmarshalType(t *testing.T, err error, msgAndArgs ...interface{}) bool {
t.Helper()
return assertErrorAsType(t, err, new(*json.UnmarshalTypeError), msgAndArgs...)
}
atomic-1.8.0/bool.go 0000664 0000000 0000000 00000004412 14060164306 0014257 0 ustar 00root root 0000000 0000000 // @generated Code generated by gen-atomicwrapper.
// Copyright (c) 2020-2021 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
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package atomic
import (
"encoding/json"
)
// Bool is an atomic type-safe wrapper for bool values.
type Bool struct {
_ nocmp // disallow non-atomic comparison
v Uint32
}
var _zeroBool bool
// NewBool creates a new Bool.
func NewBool(v bool) *Bool {
x := &Bool{}
if v != _zeroBool {
x.Store(v)
}
return x
}
// Load atomically loads the wrapped bool.
func (x *Bool) Load() bool {
return truthy(x.v.Load())
}
// Store atomically stores the passed bool.
func (x *Bool) Store(v bool) {
x.v.Store(boolToInt(v))
}
// CAS is an atomic compare-and-swap for bool values.
func (x *Bool) CAS(o, n bool) bool {
return x.v.CAS(boolToInt(o), boolToInt(n))
}
// Swap atomically stores the given bool and returns the old
// value.
func (x *Bool) Swap(o bool) bool {
return truthy(x.v.Swap(boolToInt(o)))
}
// MarshalJSON encodes the wrapped bool into JSON.
func (x *Bool) MarshalJSON() ([]byte, error) {
return json.Marshal(x.Load())
}
// UnmarshalJSON decodes a bool from JSON.
func (x *Bool) UnmarshalJSON(b []byte) error {
var v bool
if err := json.Unmarshal(b, &v); err != nil {
return err
}
x.Store(v)
return nil
}
atomic-1.8.0/bool_ext.go 0000664 0000000 0000000 00000003256 14060164306 0015144 0 ustar 00root root 0000000 0000000 // Copyright (c) 2020 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
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package atomic
import (
"strconv"
)
//go:generate bin/gen-atomicwrapper -name=Bool -type=bool -wrapped=Uint32 -pack=boolToInt -unpack=truthy -cas -swap -json -file=bool.go
func truthy(n uint32) bool {
return n == 1
}
func boolToInt(b bool) uint32 {
if b {
return 1
}
return 0
}
// Toggle atomically negates the Boolean and returns the previous value.
func (b *Bool) Toggle() bool {
for {
old := b.Load()
if b.CAS(old, !old) {
return old
}
}
}
// String encodes the wrapped value as a string.
func (b *Bool) String() string {
return strconv.FormatBool(b.Load())
}
atomic-1.8.0/bool_test.go 0000664 0000000 0000000 00000006534 14060164306 0015325 0 ustar 00root root 0000000 0000000 // Copyright (c) 2020 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
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package atomic
import (
"encoding/json"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestBool(t *testing.T) {
atom := NewBool(false)
require.False(t, atom.Toggle(), "Expected Toggle to return previous value.")
require.True(t, atom.Toggle(), "Expected Toggle to return previous value.")
require.False(t, atom.Toggle(), "Expected Toggle to return previous value.")
require.True(t, atom.Load(), "Unexpected state after swap.")
require.True(t, atom.CAS(true, true), "CAS should swap when old matches")
require.True(t, atom.Load(), "CAS should have no effect")
require.True(t, atom.CAS(true, false), "CAS should swap when old matches")
require.False(t, atom.Load(), "CAS should have modified the value")
require.False(t, atom.CAS(true, false), "CAS should fail on old mismatch")
require.False(t, atom.Load(), "CAS should not have modified the value")
atom.Store(false)
require.False(t, atom.Load(), "Unexpected state after store.")
prev := atom.Swap(false)
require.False(t, prev, "Expected Swap to return previous value.")
prev = atom.Swap(true)
require.False(t, prev, "Expected Swap to return previous value.")
t.Run("JSON/Marshal", func(t *testing.T) {
atom.Store(true)
bytes, err := json.Marshal(atom)
require.NoError(t, err, "json.Marshal errored unexpectedly.")
require.Equal(t, []byte("true"), bytes, "json.Marshal encoded the wrong bytes.")
})
t.Run("JSON/Unmarshal", func(t *testing.T) {
err := json.Unmarshal([]byte("false"), &atom)
require.NoError(t, err, "json.Unmarshal errored unexpectedly.")
require.False(t, atom.Load(), "json.Unmarshal didn't set the correct value.")
})
t.Run("JSON/Unmarshal/Error", func(t *testing.T) {
err := json.Unmarshal([]byte("42"), &atom)
require.Error(t, err, "json.Unmarshal didn't error as expected.")
assertErrorJSONUnmarshalType(t, err,
"json.Unmarshal failed with unexpected error %v, want UnmarshalTypeError.", err)
})
t.Run("String", func(t *testing.T) {
t.Run("true", func(t *testing.T) {
assert.Equal(t, "true", NewBool(true).String(),
"String() returned an unexpected value.")
})
t.Run("false", func(t *testing.T) {
var b Bool
assert.Equal(t, "false", b.String(),
"String() returned an unexpected value.")
})
})
}
atomic-1.8.0/doc.go 0000664 0000000 0000000 00000002311 14060164306 0014065 0 ustar 00root root 0000000 0000000 // Copyright (c) 2020 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
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// Package atomic provides simple wrappers around numerics to enforce atomic
// access.
package atomic
atomic-1.8.0/duration.go 0000664 0000000 0000000 00000004722 14060164306 0015155 0 ustar 00root root 0000000 0000000 // @generated Code generated by gen-atomicwrapper.
// Copyright (c) 2020-2021 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
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package atomic
import (
"encoding/json"
"time"
)
// Duration is an atomic type-safe wrapper for time.Duration values.
type Duration struct {
_ nocmp // disallow non-atomic comparison
v Int64
}
var _zeroDuration time.Duration
// NewDuration creates a new Duration.
func NewDuration(v time.Duration) *Duration {
x := &Duration{}
if v != _zeroDuration {
x.Store(v)
}
return x
}
// Load atomically loads the wrapped time.Duration.
func (x *Duration) Load() time.Duration {
return time.Duration(x.v.Load())
}
// Store atomically stores the passed time.Duration.
func (x *Duration) Store(v time.Duration) {
x.v.Store(int64(v))
}
// CAS is an atomic compare-and-swap for time.Duration values.
func (x *Duration) CAS(o, n time.Duration) bool {
return x.v.CAS(int64(o), int64(n))
}
// Swap atomically stores the given time.Duration and returns the old
// value.
func (x *Duration) Swap(o time.Duration) time.Duration {
return time.Duration(x.v.Swap(int64(o)))
}
// MarshalJSON encodes the wrapped time.Duration into JSON.
func (x *Duration) MarshalJSON() ([]byte, error) {
return json.Marshal(x.Load())
}
// UnmarshalJSON decodes a time.Duration from JSON.
func (x *Duration) UnmarshalJSON(b []byte) error {
var v time.Duration
if err := json.Unmarshal(b, &v); err != nil {
return err
}
x.Store(v)
return nil
}
atomic-1.8.0/duration_ext.go 0000664 0000000 0000000 00000003412 14060164306 0016030 0 ustar 00root root 0000000 0000000 // Copyright (c) 2020 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
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package atomic
import "time"
//go:generate bin/gen-atomicwrapper -name=Duration -type=time.Duration -wrapped=Int64 -pack=int64 -unpack=time.Duration -cas -swap -json -imports time -file=duration.go
// Add atomically adds to the wrapped time.Duration and returns the new value.
func (d *Duration) Add(n time.Duration) time.Duration {
return time.Duration(d.v.Add(int64(n)))
}
// Sub atomically subtracts from the wrapped time.Duration and returns the new value.
func (d *Duration) Sub(n time.Duration) time.Duration {
return time.Duration(d.v.Sub(int64(n)))
}
// String encodes the wrapped value as a string.
func (d *Duration) String() string {
return d.Load().String()
}
atomic-1.8.0/duration_test.go 0000664 0000000 0000000 00000005674 14060164306 0016223 0 ustar 00root root 0000000 0000000 // Copyright (c) 2020 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
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package atomic
import (
"encoding/json"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestDuration(t *testing.T) {
atom := NewDuration(5 * time.Minute)
require.Equal(t, 5*time.Minute, atom.Load(), "Load didn't work.")
require.Equal(t, 6*time.Minute, atom.Add(time.Minute), "Add didn't work.")
require.Equal(t, 4*time.Minute, atom.Sub(2*time.Minute), "Sub didn't work.")
require.True(t, atom.CAS(4*time.Minute, time.Minute), "CAS didn't report a swap.")
require.Equal(t, time.Minute, atom.Load(), "CAS didn't set the correct value.")
require.Equal(t, time.Minute, atom.Swap(2*time.Minute), "Swap didn't return the old value.")
require.Equal(t, 2*time.Minute, atom.Load(), "Swap didn't set the correct value.")
atom.Store(10 * time.Minute)
require.Equal(t, 10*time.Minute, atom.Load(), "Store didn't set the correct value.")
t.Run("JSON/Marshal", func(t *testing.T) {
atom.Store(time.Second)
bytes, err := json.Marshal(atom)
require.NoError(t, err, "json.Marshal errored unexpectedly.")
require.Equal(t, []byte("1000000000"), bytes, "json.Marshal encoded the wrong bytes.")
})
t.Run("JSON/Unmarshal", func(t *testing.T) {
err := json.Unmarshal([]byte("1000000000"), &atom)
require.NoError(t, err, "json.Unmarshal errored unexpectedly.")
require.Equal(t, time.Second, atom.Load(), "json.Unmarshal didn't set the correct value.")
})
t.Run("JSON/Unmarshal/Error", func(t *testing.T) {
err := json.Unmarshal([]byte("\"1000000000\""), &atom)
require.Error(t, err, "json.Unmarshal didn't error as expected.")
assertErrorJSONUnmarshalType(t, err,
"json.Unmarshal failed with unexpected error %v, want UnmarshalTypeError.", err)
})
t.Run("String", func(t *testing.T) {
assert.Equal(t, "42s", NewDuration(42*time.Second).String(),
"String() returned an unexpected value.")
})
}
atomic-1.8.0/error.go 0000664 0000000 0000000 00000003241 14060164306 0014454 0 ustar 00root root 0000000 0000000 // @generated Code generated by gen-atomicwrapper.
// Copyright (c) 2020-2021 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
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package atomic
// Error is an atomic type-safe wrapper for error values.
type Error struct {
_ nocmp // disallow non-atomic comparison
v Value
}
var _zeroError error
// NewError creates a new Error.
func NewError(v error) *Error {
x := &Error{}
if v != _zeroError {
x.Store(v)
}
return x
}
// Load atomically loads the wrapped error.
func (x *Error) Load() error {
return unpackError(x.v.Load())
}
// Store atomically stores the passed error.
func (x *Error) Store(v error) {
x.v.Store(packError(v))
}
atomic-1.8.0/error_ext.go 0000664 0000000 0000000 00000003124 14060164306 0015334 0 ustar 00root root 0000000 0000000 // Copyright (c) 2020 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
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package atomic
// atomic.Value panics on nil inputs, or if the underlying type changes.
// Stabilize by always storing a custom struct that we control.
//go:generate bin/gen-atomicwrapper -name=Error -type=error -wrapped=Value -pack=packError -unpack=unpackError -file=error.go
type packedError struct{ Value error }
func packError(v error) interface{} {
return packedError{v}
}
func unpackError(v interface{}) error {
if err, ok := v.(packedError); ok {
return err.Value
}
return nil
}
atomic-1.8.0/error_test.go 0000664 0000000 0000000 00000003607 14060164306 0015521 0 ustar 00root root 0000000 0000000 // Copyright (c) 2016 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
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package atomic
import (
"errors"
"testing"
"github.com/stretchr/testify/require"
)
func TestErrorByValue(t *testing.T) {
err := &Error{}
require.Nil(t, err.Load(), "Initial value shall be nil")
}
func TestNewErrorWithNilArgument(t *testing.T) {
err := NewError(nil)
require.Nil(t, err.Load(), "Initial value shall be nil")
}
func TestErrorCanStoreNil(t *testing.T) {
err := NewError(errors.New("hello"))
err.Store(nil)
require.Nil(t, err.Load(), "Stored value shall be nil")
}
func TestNewErrorWithError(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")
atom.Store(err2)
require.Equal(t, err2, atom.Load(), "Expected Load to return overridden value")
}
atomic-1.8.0/example_test.go 0000664 0000000 0000000 00000002710 14060164306 0016015 0 ustar 00root root 0000000 0000000 // Copyright (c) 2016 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
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package atomic_test
import (
"fmt"
"go.uber.org/atomic"
)
func Example() {
// Uint32 is a thin wrapper around the primitive uint32 type.
var atom atomic.Uint32
// The wrapper ensures that all operations are atomic.
atom.Store(42)
fmt.Println(atom.Inc())
fmt.Println(atom.CAS(43, 0))
fmt.Println(atom.Load())
// Output:
// 43
// true
// 0
}
atomic-1.8.0/float64.go 0000664 0000000 0000000 00000004357 14060164306 0014613 0 ustar 00root root 0000000 0000000 // @generated Code generated by gen-atomicwrapper.
// Copyright (c) 2020-2021 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
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package atomic
import (
"encoding/json"
"math"
)
// Float64 is an atomic type-safe wrapper for float64 values.
type Float64 struct {
_ nocmp // disallow non-atomic comparison
v Uint64
}
var _zeroFloat64 float64
// NewFloat64 creates a new Float64.
func NewFloat64(v float64) *Float64 {
x := &Float64{}
if v != _zeroFloat64 {
x.Store(v)
}
return x
}
// Load atomically loads the wrapped float64.
func (x *Float64) Load() float64 {
return math.Float64frombits(x.v.Load())
}
// Store atomically stores the passed float64.
func (x *Float64) Store(v float64) {
x.v.Store(math.Float64bits(v))
}
// CAS is an atomic compare-and-swap for float64 values.
func (x *Float64) CAS(o, n float64) bool {
return x.v.CAS(math.Float64bits(o), math.Float64bits(n))
}
// MarshalJSON encodes the wrapped float64 into JSON.
func (x *Float64) MarshalJSON() ([]byte, error) {
return json.Marshal(x.Load())
}
// UnmarshalJSON decodes a float64 from JSON.
func (x *Float64) UnmarshalJSON(b []byte) error {
var v float64
if err := json.Unmarshal(b, &v); err != nil {
return err
}
x.Store(v)
return nil
}
atomic-1.8.0/float64_ext.go 0000664 0000000 0000000 00000003506 14060164306 0015466 0 ustar 00root root 0000000 0000000 // Copyright (c) 2020 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
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package atomic
import "strconv"
//go:generate bin/gen-atomicwrapper -name=Float64 -type=float64 -wrapped=Uint64 -pack=math.Float64bits -unpack=math.Float64frombits -cas -json -imports math -file=float64.go
// Add atomically adds to the wrapped float64 and returns the new value.
func (f *Float64) Add(s float64) float64 {
for {
old := f.Load()
new := old + s
if f.CAS(old, new) {
return new
}
}
}
// Sub atomically subtracts from the wrapped float64 and returns the new value.
func (f *Float64) Sub(s float64) float64 {
return f.Add(-s)
}
// String encodes the wrapped value as a string.
func (f *Float64) String() string {
// 'g' is the behavior for floats with %v.
return strconv.FormatFloat(f.Load(), 'g', -1, 64)
}
atomic-1.8.0/float64_test.go 0000664 0000000 0000000 00000005337 14060164306 0015651 0 ustar 00root root 0000000 0000000 // Copyright (c) 2020 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
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package atomic
import (
"encoding/json"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestFloat64(t *testing.T) {
atom := NewFloat64(4.2)
require.Equal(t, float64(4.2), atom.Load(), "Load didn't work.")
require.True(t, atom.CAS(4.2, 0.5), "CAS didn't report a swap.")
require.Equal(t, float64(0.5), atom.Load(), "CAS didn't set the correct value.")
require.False(t, atom.CAS(0.0, 1.5), "CAS reported a swap.")
atom.Store(42.0)
require.Equal(t, float64(42.0), atom.Load(), "Store didn't set the correct value.")
require.Equal(t, float64(42.5), atom.Add(0.5), "Add didn't work.")
require.Equal(t, float64(42.0), atom.Sub(0.5), "Sub didn't work.")
t.Run("JSON/Marshal", func(t *testing.T) {
atom.Store(42.5)
bytes, err := json.Marshal(atom)
require.NoError(t, err, "json.Marshal errored unexpectedly.")
require.Equal(t, []byte("42.5"), bytes, "json.Marshal encoded the wrong bytes.")
})
t.Run("JSON/Unmarshal", func(t *testing.T) {
err := json.Unmarshal([]byte("40.5"), &atom)
require.NoError(t, err, "json.Unmarshal errored unexpectedly.")
require.Equal(t, float64(40.5), atom.Load(), "json.Unmarshal didn't set the correct value.")
})
t.Run("JSON/Unmarshal/Error", func(t *testing.T) {
err := json.Unmarshal([]byte("\"40.5\""), &atom)
require.Error(t, err, "json.Unmarshal didn't error as expected.")
assertErrorJSONUnmarshalType(t, err,
"json.Unmarshal failed with unexpected error %v, want UnmarshalTypeError.", err)
})
t.Run("String", func(t *testing.T) {
assert.Equal(t, "42.5", NewFloat64(42.5).String(),
"String() returned an unexpected value.")
})
}
atomic-1.8.0/gen.go 0000664 0000000 0000000 00000003016 14060164306 0014074 0 ustar 00root root 0000000 0000000 // Copyright (c) 2020 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
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package atomic
//go:generate bin/gen-atomicint -name=Int32 -wrapped=int32 -file=int32.go
//go:generate bin/gen-atomicint -name=Int64 -wrapped=int64 -file=int64.go
//go:generate bin/gen-atomicint -name=Uint32 -wrapped=uint32 -unsigned -file=uint32.go
//go:generate bin/gen-atomicint -name=Uint64 -wrapped=uint64 -unsigned -file=uint64.go
//go:generate bin/gen-atomicint -name=Uintptr -wrapped=uintptr -unsigned -file=uintptr.go
atomic-1.8.0/go.mod 0000664 0000000 0000000 00000000203 14060164306 0014075 0 ustar 00root root 0000000 0000000 module go.uber.org/atomic
require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/stretchr/testify v1.3.0
)
go 1.13
atomic-1.8.0/go.sum 0000664 0000000 0000000 00000001271 14060164306 0014130 0 ustar 00root root 0000000 0000000 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
atomic-1.8.0/int32.go 0000664 0000000 0000000 00000005640 14060164306 0014267 0 ustar 00root root 0000000 0000000 // @generated Code generated by gen-atomicint.
// Copyright (c) 2020-2021 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
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package atomic
import (
"encoding/json"
"strconv"
"sync/atomic"
)
// Int32 is an atomic wrapper around int32.
type Int32 struct {
_ nocmp // disallow non-atomic comparison
v int32
}
// NewInt32 creates a new Int32.
func NewInt32(i int32) *Int32 {
return &Int32{v: i}
}
// Load atomically loads the wrapped value.
func (i *Int32) Load() int32 {
return atomic.LoadInt32(&i.v)
}
// Add atomically adds to the wrapped int32 and returns the new value.
func (i *Int32) Add(n int32) int32 {
return atomic.AddInt32(&i.v, n)
}
// Sub atomically subtracts from the wrapped int32 and returns the new value.
func (i *Int32) Sub(n int32) int32 {
return atomic.AddInt32(&i.v, -n)
}
// Inc atomically increments the wrapped int32 and returns the new value.
func (i *Int32) Inc() int32 {
return i.Add(1)
}
// Dec atomically decrements the wrapped int32 and returns the new value.
func (i *Int32) Dec() int32 {
return i.Sub(1)
}
// CAS is an atomic compare-and-swap.
func (i *Int32) CAS(old, new int32) bool {
return atomic.CompareAndSwapInt32(&i.v, old, new)
}
// Store atomically stores the passed value.
func (i *Int32) Store(n int32) {
atomic.StoreInt32(&i.v, n)
}
// Swap atomically swaps the wrapped int32 and returns the old value.
func (i *Int32) Swap(n int32) int32 {
return atomic.SwapInt32(&i.v, n)
}
// MarshalJSON encodes the wrapped int32 into JSON.
func (i *Int32) MarshalJSON() ([]byte, error) {
return json.Marshal(i.Load())
}
// UnmarshalJSON decodes JSON into the wrapped int32.
func (i *Int32) UnmarshalJSON(b []byte) error {
var v int32
if err := json.Unmarshal(b, &v); err != nil {
return err
}
i.Store(v)
return nil
}
// String encodes the wrapped value as a string.
func (i *Int32) String() string {
v := i.Load()
return strconv.FormatInt(int64(v), 10)
}
atomic-1.8.0/int32_test.go 0000664 0000000 0000000 00000006200 14060164306 0015317 0 ustar 00root root 0000000 0000000 // Copyright (c) 2020 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
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package atomic
import (
"encoding/json"
"math"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestInt32(t *testing.T) {
atom := NewInt32(42)
require.Equal(t, int32(42), atom.Load(), "Load didn't work.")
require.Equal(t, int32(46), atom.Add(4), "Add didn't work.")
require.Equal(t, int32(44), atom.Sub(2), "Sub didn't work.")
require.Equal(t, int32(45), atom.Inc(), "Inc didn't work.")
require.Equal(t, int32(44), atom.Dec(), "Dec didn't work.")
require.True(t, atom.CAS(44, 0), "CAS didn't report a swap.")
require.Equal(t, int32(0), atom.Load(), "CAS didn't set the correct value.")
require.Equal(t, int32(0), atom.Swap(1), "Swap didn't return the old value.")
require.Equal(t, int32(1), atom.Load(), "Swap didn't set the correct value.")
atom.Store(42)
require.Equal(t, int32(42), atom.Load(), "Store didn't set the correct value.")
t.Run("JSON/Marshal", func(t *testing.T) {
bytes, err := json.Marshal(atom)
require.NoError(t, err, "json.Marshal errored unexpectedly.")
require.Equal(t, []byte("42"), bytes, "json.Marshal encoded the wrong bytes.")
})
t.Run("JSON/Unmarshal", func(t *testing.T) {
err := json.Unmarshal([]byte("40"), &atom)
require.NoError(t, err, "json.Unmarshal errored unexpectedly.")
require.Equal(t, int32(40), atom.Load(), "json.Unmarshal didn't set the correct value.")
})
t.Run("JSON/Unmarshal/Error", func(t *testing.T) {
err := json.Unmarshal([]byte(`"40"`), &atom)
require.Error(t, err, "json.Unmarshal didn't error as expected.")
assertErrorJSONUnmarshalType(t, err,
"json.Unmarshal failed with unexpected error %v, want UnmarshalTypeError.", err)
})
t.Run("String", func(t *testing.T) {
t.Run("positive", func(t *testing.T) {
atom := NewInt32(math.MaxInt32)
assert.Equal(t, "2147483647", atom.String(),
"String() returned an unexpected value.")
})
t.Run("negative", func(t *testing.T) {
atom := NewInt32(math.MinInt32)
assert.Equal(t, "-2147483648", atom.String(),
"String() returned an unexpected value.")
})
})
}
atomic-1.8.0/int64.go 0000664 0000000 0000000 00000005640 14060164306 0014274 0 ustar 00root root 0000000 0000000 // @generated Code generated by gen-atomicint.
// Copyright (c) 2020-2021 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
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package atomic
import (
"encoding/json"
"strconv"
"sync/atomic"
)
// Int64 is an atomic wrapper around int64.
type Int64 struct {
_ nocmp // disallow non-atomic comparison
v int64
}
// NewInt64 creates a new Int64.
func NewInt64(i int64) *Int64 {
return &Int64{v: i}
}
// Load atomically loads the wrapped value.
func (i *Int64) Load() int64 {
return atomic.LoadInt64(&i.v)
}
// Add atomically adds to the wrapped int64 and returns the new value.
func (i *Int64) Add(n int64) int64 {
return atomic.AddInt64(&i.v, n)
}
// Sub atomically subtracts from the wrapped int64 and returns the new value.
func (i *Int64) Sub(n int64) int64 {
return atomic.AddInt64(&i.v, -n)
}
// Inc atomically increments the wrapped int64 and returns the new value.
func (i *Int64) Inc() int64 {
return i.Add(1)
}
// Dec atomically decrements the wrapped int64 and returns the new value.
func (i *Int64) Dec() int64 {
return i.Sub(1)
}
// CAS is an atomic compare-and-swap.
func (i *Int64) CAS(old, new int64) bool {
return atomic.CompareAndSwapInt64(&i.v, old, new)
}
// Store atomically stores the passed value.
func (i *Int64) Store(n int64) {
atomic.StoreInt64(&i.v, n)
}
// Swap atomically swaps the wrapped int64 and returns the old value.
func (i *Int64) Swap(n int64) int64 {
return atomic.SwapInt64(&i.v, n)
}
// MarshalJSON encodes the wrapped int64 into JSON.
func (i *Int64) MarshalJSON() ([]byte, error) {
return json.Marshal(i.Load())
}
// UnmarshalJSON decodes JSON into the wrapped int64.
func (i *Int64) UnmarshalJSON(b []byte) error {
var v int64
if err := json.Unmarshal(b, &v); err != nil {
return err
}
i.Store(v)
return nil
}
// String encodes the wrapped value as a string.
func (i *Int64) String() string {
v := i.Load()
return strconv.FormatInt(int64(v), 10)
}
atomic-1.8.0/int64_test.go 0000664 0000000 0000000 00000006222 14060164306 0015330 0 ustar 00root root 0000000 0000000 // Copyright (c) 2020 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
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package atomic
import (
"encoding/json"
"math"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestInt64(t *testing.T) {
atom := NewInt64(42)
require.Equal(t, int64(42), atom.Load(), "Load didn't work.")
require.Equal(t, int64(46), atom.Add(4), "Add didn't work.")
require.Equal(t, int64(44), atom.Sub(2), "Sub didn't work.")
require.Equal(t, int64(45), atom.Inc(), "Inc didn't work.")
require.Equal(t, int64(44), atom.Dec(), "Dec didn't work.")
require.True(t, atom.CAS(44, 0), "CAS didn't report a swap.")
require.Equal(t, int64(0), atom.Load(), "CAS didn't set the correct value.")
require.Equal(t, int64(0), atom.Swap(1), "Swap didn't return the old value.")
require.Equal(t, int64(1), atom.Load(), "Swap didn't set the correct value.")
atom.Store(42)
require.Equal(t, int64(42), atom.Load(), "Store didn't set the correct value.")
t.Run("JSON/Marshal", func(t *testing.T) {
bytes, err := json.Marshal(atom)
require.NoError(t, err, "json.Marshal errored unexpectedly.")
require.Equal(t, []byte("42"), bytes, "json.Marshal encoded the wrong bytes.")
})
t.Run("JSON/Unmarshal", func(t *testing.T) {
err := json.Unmarshal([]byte("40"), &atom)
require.NoError(t, err, "json.Unmarshal errored unexpectedly.")
require.Equal(t, int64(40), atom.Load(), "json.Unmarshal didn't set the correct value.")
})
t.Run("JSON/Unmarshal/Error", func(t *testing.T) {
err := json.Unmarshal([]byte(`"40"`), &atom)
require.Error(t, err, "json.Unmarshal didn't error as expected.")
assertErrorJSONUnmarshalType(t, err,
"json.Unmarshal failed with unexpected error %v, want UnmarshalTypeError.", err)
})
t.Run("String", func(t *testing.T) {
t.Run("positive", func(t *testing.T) {
atom := NewInt64(math.MaxInt64)
assert.Equal(t, "9223372036854775807", atom.String(),
"String() returned an unexpected value.")
})
t.Run("negative", func(t *testing.T) {
atom := NewInt64(math.MinInt64)
assert.Equal(t, "-9223372036854775808", atom.String(),
"String() returned an unexpected value.")
})
})
}
atomic-1.8.0/internal/ 0000775 0000000 0000000 00000000000 14060164306 0014610 5 ustar 00root root 0000000 0000000 atomic-1.8.0/internal/gen-atomicint/ 0000775 0000000 0000000 00000000000 14060164306 0017346 5 ustar 00root root 0000000 0000000 atomic-1.8.0/internal/gen-atomicint/main.go 0000664 0000000 0000000 00000014544 14060164306 0020631 0 ustar 00root root 0000000 0000000 // Copyright (c) 2020 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
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// gen-atomicint generates an atomic wrapper around an integer type.
//
// gen-atomicint -name Int32 -wrapped int32 -file out.go
//
// The generated wrapper will use the functions in the sync/atomic package
// named after the generated type.
package main
import (
"bytes"
"errors"
"flag"
"fmt"
"go/format"
"io"
"log"
"os"
"text/template"
"time"
)
func main() {
log.SetFlags(0)
if err := run(os.Args[1:]); err != nil {
log.Fatalf("%+v", err)
}
}
func run(args []string) error {
var opts struct {
Name string
Wrapped string
File string
Unsigned bool
}
flag := flag.NewFlagSet("gen-atomicint", flag.ContinueOnError)
flag.StringVar(&opts.Name, "name", "", "name of the generated type (e.g. Int32)")
flag.StringVar(&opts.Wrapped, "wrapped", "", "name of the wrapped type (e.g. int32)")
flag.StringVar(&opts.File, "file", "", "output file path (default: stdout)")
flag.BoolVar(&opts.Unsigned, "unsigned", false, "whether the type is unsigned")
if err := flag.Parse(args); err != nil {
return err
}
if len(opts.Name) == 0 || len(opts.Wrapped) == 0 {
return errors.New("flags -name and -wrapped are required")
}
var w io.Writer = os.Stdout
if file := opts.File; len(file) > 0 {
f, err := os.Create(file)
if err != nil {
return fmt.Errorf("create %q: %v", file, err)
}
defer f.Close()
w = f
}
data := struct {
Name string
Wrapped string
Unsigned bool
ToYear int
}{
Name: opts.Name,
Wrapped: opts.Wrapped,
Unsigned: opts.Unsigned,
ToYear: time.Now().Year(),
}
var buff bytes.Buffer
if err := _tmpl.Execute(&buff, data); err != nil {
return fmt.Errorf("render template: %v", err)
}
bs, err := format.Source(buff.Bytes())
if err != nil {
return fmt.Errorf("reformat source: %v", err)
}
_, err = w.Write(bs)
return err
}
var _tmpl = template.Must(template.New("value.go").Parse(`// @generated Code generated by gen-atomicint.
// Copyright (c) 2020-{{.ToYear}} 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
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package atomic
import (
"encoding/json"
"strconv"
"sync/atomic"
)
// {{ .Name }} is an atomic wrapper around {{ .Wrapped }}.
type {{ .Name }} struct {
_ nocmp // disallow non-atomic comparison
v {{ .Wrapped }}
}
// New{{ .Name }} creates a new {{ .Name }}.
func New{{ .Name }}(i {{ .Wrapped }}) *{{ .Name }} {
return &{{ .Name }}{v: i}
}
// Load atomically loads the wrapped value.
func (i *{{ .Name }}) Load() {{ .Wrapped }} {
return atomic.Load{{ .Name }}(&i.v)
}
// Add atomically adds to the wrapped {{ .Wrapped }} and returns the new value.
func (i *{{ .Name }}) Add(n {{ .Wrapped }}) {{ .Wrapped }} {
return atomic.Add{{ .Name }}(&i.v, n)
}
// Sub atomically subtracts from the wrapped {{ .Wrapped }} and returns the new value.
func (i *{{ .Name }}) Sub(n {{ .Wrapped }}) {{ .Wrapped }} {
return atomic.Add{{ .Name }}(&i.v,
{{- if .Unsigned -}}
^(n - 1)
{{- else -}}
-n
{{- end -}}
)
}
// Inc atomically increments the wrapped {{ .Wrapped }} and returns the new value.
func (i *{{ .Name }}) Inc() {{ .Wrapped }} {
return i.Add(1)
}
// Dec atomically decrements the wrapped {{ .Wrapped }} and returns the new value.
func (i *{{ .Name }}) Dec() {{ .Wrapped }} {
return i.Sub(1)
}
// CAS is an atomic compare-and-swap.
func (i *{{ .Name }}) CAS(old, new {{ .Wrapped }}) bool {
return atomic.CompareAndSwap{{ .Name }}(&i.v, old, new)
}
// Store atomically stores the passed value.
func (i *{{ .Name }}) Store(n {{ .Wrapped }}) {
atomic.Store{{ .Name }}(&i.v, n)
}
// Swap atomically swaps the wrapped {{ .Wrapped }} and returns the old value.
func (i *{{ .Name }}) Swap(n {{ .Wrapped }}) {{ .Wrapped }} {
return atomic.Swap{{ .Name }}(&i.v, n)
}
// MarshalJSON encodes the wrapped {{ .Wrapped }} into JSON.
func (i *{{ .Name }}) MarshalJSON() ([]byte, error) {
return json.Marshal(i.Load())
}
// UnmarshalJSON decodes JSON into the wrapped {{ .Wrapped }}.
func (i *{{ .Name }}) UnmarshalJSON(b []byte) error {
var v {{ .Wrapped }}
if err := json.Unmarshal(b, &v); err != nil {
return err
}
i.Store(v)
return nil
}
// String encodes the wrapped value as a string.
func (i *{{ .Name }}) String() string {
v := i.Load()
{{ if .Unsigned -}}
return strconv.FormatUint(uint64(v), 10)
{{- else -}}
return strconv.FormatInt(int64(v), 10)
{{- end }}
}
`))
atomic-1.8.0/internal/gen-atomicwrapper/ 0000775 0000000 0000000 00000000000 14060164306 0020234 5 ustar 00root root 0000000 0000000 atomic-1.8.0/internal/gen-atomicwrapper/main.go 0000664 0000000 0000000 00000020012 14060164306 0021502 0 ustar 00root root 0000000 0000000 // Copyright (c) 2020 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
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// gen-atomicwrapper generates wrapper types around other atomic types.
//
// It supports plugging in functions which convert the value inside the atomic
// type to the user-facing value. For example,
//
// Given, atomic.Value and the functions,
//
// func packString(string) interface{}
// func unpackString(interface{}) string
//
// We can run the following command:
//
// gen-atomicwrapper -name String -wrapped Value \
// -type string -pack fromString -unpack tostring
//
// This wil generate approximately,
//
// type String struct{ v Value }
//
// func (s *String) Load() string {
// return unpackString(v.Load())
// }
//
// func (s *String) Store(s string) {
// return s.v.Store(packString(s))
// }
//
// The packing/unpacking logic allows the stored value to be different from
// the user-facing value.
//
// Without -pack and -unpack, the output will be cast to the target type,
// defaulting to the zero value.
package main
import (
"bytes"
"errors"
"flag"
"fmt"
"go/format"
"io"
"log"
"os"
"sort"
"strings"
"text/template"
"time"
)
func main() {
log.SetFlags(0)
if err := run(os.Args[1:]); err != nil {
log.Fatalf("%+v", err)
}
}
type stringList []string
func (sl *stringList) String() string {
return strings.Join(*sl, ",")
}
func (sl *stringList) Set(s string) error {
for _, i := range strings.Split(s, ",") {
*sl = append(*sl, strings.TrimSpace(i))
}
return nil
}
func run(args []string) error {
var opts struct {
Name string
Wrapped string
Type string
Imports stringList
Pack, Unpack string
CAS bool
Swap bool
JSON bool
File string
ToYear int
}
opts.ToYear = time.Now().Year()
flag := flag.NewFlagSet("gen-atomicwrapper", flag.ContinueOnError)
// Required flags
flag.StringVar(&opts.Name, "name", "",
"name of the generated type (e.g. Duration)")
flag.StringVar(&opts.Wrapped, "wrapped", "",
"name of the wrapped atomic (e.g. Int64)")
flag.StringVar(&opts.Type, "type", "",
"name of the type exposed by the atomic (e.g. time.Duration)")
// Optional flags
flag.Var(&opts.Imports, "imports",
"comma separated list of imports to add")
flag.StringVar(&opts.Pack, "pack", "",
"function to transform values with before storage")
flag.StringVar(&opts.Unpack, "unpack", "",
"function to reverse packing on loading")
flag.StringVar(&opts.File, "file", "",
"output file path (default: stdout)")
// Switches for individual methods. Underlying atomics must support
// these.
flag.BoolVar(&opts.CAS, "cas", false,
"generate a `CAS(old, new) bool` method; requires -pack")
flag.BoolVar(&opts.Swap, "swap", false,
"generate a `Swap(new) old` method; requires -pack and -unpack")
flag.BoolVar(&opts.JSON, "json", false,
"generate `MarshalJSON/UnmarshJSON` methods")
if err := flag.Parse(args); err != nil {
return err
}
if len(opts.Name) == 0 || len(opts.Wrapped) == 0 || len(opts.Type) == 0 {
return errors.New("flags -name, -wrapped, and -type are required")
}
if (len(opts.Pack) == 0) != (len(opts.Unpack) == 0) {
return errors.New("either both, or neither of -pack and -unpack must be specified")
}
if opts.CAS && len(opts.Pack) == 0 {
return errors.New("flag -cas requires -pack")
}
if opts.Swap && len(opts.Pack) == 0 {
return errors.New("flag -swap requires -pack and -unpack")
}
var w io.Writer = os.Stdout
if file := opts.File; len(file) > 0 {
f, err := os.Create(file)
if err != nil {
return fmt.Errorf("create %q: %v", file, err)
}
defer f.Close()
w = f
}
// Import encoding/json if needed.
if opts.JSON {
found := false
for _, imp := range opts.Imports {
if imp == "encoding/json" {
found = true
break
}
}
if !found {
opts.Imports = append(opts.Imports, "encoding/json")
}
}
sort.Strings([]string(opts.Imports))
var buff bytes.Buffer
if err := _tmpl.Execute(&buff, opts); err != nil {
return fmt.Errorf("render template: %v", err)
}
bs, err := format.Source(buff.Bytes())
if err != nil {
return fmt.Errorf("reformat source: %v", err)
}
_, err = w.Write(bs)
return err
}
var _tmpl = template.Must(template.New("int.go").Parse(`// @generated Code generated by gen-atomicwrapper.
// Copyright (c) 2020-{{.ToYear}} 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
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package atomic
{{ with .Imports }}
import (
{{ range . -}}
{{ printf "%q" . }}
{{ end }}
)
{{ end }}
// {{ .Name }} is an atomic type-safe wrapper for {{ .Type }} values.
type {{ .Name }} struct{
_ nocmp // disallow non-atomic comparison
v {{ .Wrapped }}
}
var _zero{{ .Name }} {{ .Type }}
// New{{ .Name }} creates a new {{ .Name }}.
func New{{ .Name}}(v {{ .Type }}) *{{ .Name }} {
x := &{{ .Name }}{}
if v != _zero{{ .Name }} {
x.Store(v)
}
return x
}
// Load atomically loads the wrapped {{ .Type }}.
func (x *{{ .Name }}) Load() {{ .Type }} {
{{ if .Unpack -}}
return {{ .Unpack }}(x.v.Load())
{{- else -}}
if v := x.v.Load(); v != nil {
return v.({{ .Type }})
}
return _zero{{ .Name }}
{{- end }}
}
// Store atomically stores the passed {{ .Type }}.
func (x *{{ .Name }}) Store(v {{ .Type }}) {
{{ if .Pack -}}
x.v.Store({{ .Pack }}(v))
{{- else -}}
x.v.Store(v)
{{- end }}
}
{{ if .CAS -}}
// CAS is an atomic compare-and-swap for {{ .Type }} values.
func (x *{{ .Name }}) CAS(o, n {{ .Type }}) bool {
return x.v.CAS({{ .Pack }}(o), {{ .Pack }}(n))
}
{{- end }}
{{ if .Swap -}}
// Swap atomically stores the given {{ .Type }} and returns the old
// value.
func (x *{{ .Name }}) Swap(o {{ .Type }}) {{ .Type }} {
return {{ .Unpack }}(x.v.Swap({{ .Pack }}(o)))
}
{{- end }}
{{ if .JSON -}}
// MarshalJSON encodes the wrapped {{ .Type }} into JSON.
func (x *{{ .Name }}) MarshalJSON() ([]byte, error) {
return json.Marshal(x.Load())
}
// UnmarshalJSON decodes a {{ .Type }} from JSON.
func (x *{{ .Name }}) UnmarshalJSON(b []byte) error {
var v {{ .Type }}
if err := json.Unmarshal(b, &v); err != nil {
return err
}
x.Store(v)
return nil
}
{{- end }}
`))
atomic-1.8.0/nocmp.go 0000664 0000000 0000000 00000002637 14060164306 0014447 0 ustar 00root root 0000000 0000000 // Copyright (c) 2020 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
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package atomic
// nocmp is an uncomparable struct. Embed this inside another struct to make
// it uncomparable.
//
// type Foo struct {
// nocmp
// // ...
// }
//
// This DOES NOT:
//
// - Disallow shallow copies of structs
// - Disallow comparison of pointers to uncomparable structs
type nocmp [0]func()
atomic-1.8.0/nocmp_test.go 0000664 0000000 0000000 00000010430 14060164306 0015474 0 ustar 00root root 0000000 0000000 // Copyright (c) 2020 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
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package atomic
import (
"bytes"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"reflect"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestNocmpComparability(t *testing.T) {
tests := []struct {
desc string
give interface{}
comparable bool
}{
{
desc: "nocmp struct",
give: nocmp{},
},
{
desc: "struct with nocmp embedded",
give: struct{ nocmp }{},
},
{
desc: "pointer to struct with nocmp embedded",
give: &struct{ nocmp }{},
comparable: true,
},
// All exported types must be uncomparable.
{desc: "Bool", give: Bool{}},
{desc: "Duration", give: Duration{}},
{desc: "Error", give: Error{}},
{desc: "Float64", give: Float64{}},
{desc: "Int32", give: Int32{}},
{desc: "Int64", give: Int64{}},
{desc: "String", give: String{}},
{desc: "Uint32", give: Uint32{}},
{desc: "Uint64", give: Uint64{}},
{desc: "Value", give: Value{}},
}
for _, tt := range tests {
t.Run(tt.desc, func(t *testing.T) {
typ := reflect.TypeOf(tt.give)
assert.Equalf(t, tt.comparable, typ.Comparable(),
"type %v comparablity mismatch", typ)
})
}
}
// nocmp must not add to the size of a struct in-memory.
func TestNocmpSize(t *testing.T) {
type x struct{ _ int }
before := reflect.TypeOf(x{}).Size()
type y struct {
_ nocmp
_ x
}
after := reflect.TypeOf(y{}).Size()
assert.Equal(t, before, after,
"expected nocmp to have no effect on struct size")
}
// This test will fail to compile if we disallow copying of nocmp.
//
// We need to allow this so that users can do,
//
// var x atomic.Int32
// x = atomic.NewInt32(1)
func TestNocmpCopy(t *testing.T) {
type foo struct{ _ nocmp }
t.Run("struct copy", func(t *testing.T) {
a := foo{}
b := a
_ = b // unused
})
t.Run("pointer copy", func(t *testing.T) {
a := &foo{}
b := *a
_ = b // unused
})
}
// Fake go.mod with no dependencies.
const _exampleGoMod = `module example.com/nocmp`
const _badFile = `package atomic
import "fmt"
type Int64 struct {
nocmp
v int64
}
func shouldNotCompile() {
var x, y Int64
fmt.Println(x == y)
}
`
func TestNocmpIntegration(t *testing.T) {
tempdir, err := ioutil.TempDir("", "nocmp")
require.NoError(t, err, "unable to set up temporary directory")
defer os.RemoveAll(tempdir)
nocmp, err := ioutil.ReadFile("nocmp.go")
require.NoError(t, err, "unable to read nocmp.go")
require.NoError(t,
ioutil.WriteFile(filepath.Join(tempdir, "go.mod"), []byte(_exampleGoMod), 0644),
"unable to write go.mod")
require.NoError(t,
ioutil.WriteFile(filepath.Join(tempdir, "nocmp.go"), nocmp, 0644),
"unable to write nocmp.go")
require.NoError(t,
ioutil.WriteFile(filepath.Join(tempdir, "bad.go"), []byte(_badFile), 0644),
"unable to write bad.go")
var stderr bytes.Buffer
cmd := exec.Command("go", "build")
cmd.Dir = tempdir
// Create a minimal build enviroment with only HOME set so that "go
// build" has somewhere to put the cache and other Go files in.
cmd.Env = []string{"HOME=" + filepath.Join(tempdir, "home")}
cmd.Stderr = &stderr
require.Error(t, cmd.Run(), "bad.go must not compile")
assert.Contains(t, stderr.String(),
"struct containing nocmp cannot be compared")
}
atomic-1.8.0/stress_test.go 0000664 0000000 0000000 00000012731 14060164306 0015711 0 ustar 00root root 0000000 0000000 // Copyright (c) 2016 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
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package atomic
import (
"errors"
"math"
"runtime"
"sync"
"sync/atomic"
"testing"
)
const (
_parallelism = 4
_iterations = 1000
)
var _stressTests = map[string]func() func(){
"i32/std": stressStdInt32,
"i32": stressInt32,
"i64/std": stressStdInt64,
"i64": stressInt64,
"u32/std": stressStdUint32,
"u32": stressUint32,
"u64/std": stressStdUint64,
"u64": stressUint64,
"f64": stressFloat64,
"bool": stressBool,
"string": stressString,
"duration": stressDuration,
"error": stressError,
}
func TestStress(t *testing.T) {
for name, ff := range _stressTests {
t.Run(name, func(t *testing.T) {
defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(_parallelism))
start := make(chan struct{})
var wg sync.WaitGroup
wg.Add(_parallelism)
f := ff()
for i := 0; i < _parallelism; i++ {
go func() {
defer wg.Done()
<-start
for j := 0; j < _iterations; j++ {
f()
}
}()
}
close(start)
wg.Wait()
})
}
}
func BenchmarkStress(b *testing.B) {
for name, ff := range _stressTests {
b.Run(name, func(b *testing.B) {
f := ff()
b.Run("serial", func(b *testing.B) {
for i := 0; i < b.N; i++ {
f()
}
})
b.Run("parallel", func(b *testing.B) {
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
f()
}
})
})
})
}
}
func stressStdInt32() func() {
var atom int32
return func() {
atomic.LoadInt32(&atom)
atomic.AddInt32(&atom, 1)
atomic.AddInt32(&atom, -2)
atomic.AddInt32(&atom, 1)
atomic.AddInt32(&atom, -1)
atomic.CompareAndSwapInt32(&atom, 1, 0)
atomic.SwapInt32(&atom, 5)
atomic.StoreInt32(&atom, 1)
}
}
func stressInt32() func() {
var atom Int32
return func() {
atom.Load()
atom.Add(1)
atom.Sub(2)
atom.Inc()
atom.Dec()
atom.CAS(1, 0)
atom.Swap(5)
atom.Store(1)
}
}
func stressStdInt64() func() {
var atom int64
return func() {
atomic.LoadInt64(&atom)
atomic.AddInt64(&atom, 1)
atomic.AddInt64(&atom, -2)
atomic.AddInt64(&atom, 1)
atomic.AddInt64(&atom, -1)
atomic.CompareAndSwapInt64(&atom, 1, 0)
atomic.SwapInt64(&atom, 5)
atomic.StoreInt64(&atom, 1)
}
}
func stressInt64() func() {
var atom Int64
return func() {
atom.Load()
atom.Add(1)
atom.Sub(2)
atom.Inc()
atom.Dec()
atom.CAS(1, 0)
atom.Swap(5)
atom.Store(1)
}
}
func stressStdUint32() func() {
var atom uint32
return func() {
atomic.LoadUint32(&atom)
atomic.AddUint32(&atom, 1)
// Adding `MaxUint32` is the same as subtracting 1
atomic.AddUint32(&atom, math.MaxUint32-1)
atomic.AddUint32(&atom, 1)
atomic.AddUint32(&atom, math.MaxUint32)
atomic.CompareAndSwapUint32(&atom, 1, 0)
atomic.SwapUint32(&atom, 5)
atomic.StoreUint32(&atom, 1)
}
}
func stressUint32() func() {
var atom Uint32
return func() {
atom.Load()
atom.Add(1)
atom.Sub(2)
atom.Inc()
atom.Dec()
atom.CAS(1, 0)
atom.Swap(5)
atom.Store(1)
}
}
func stressStdUint64() func() {
var atom uint64
return func() {
atomic.LoadUint64(&atom)
atomic.AddUint64(&atom, 1)
// Adding `MaxUint64` is the same as subtracting 1
atomic.AddUint64(&atom, math.MaxUint64-1)
atomic.AddUint64(&atom, 1)
atomic.AddUint64(&atom, math.MaxUint64)
atomic.CompareAndSwapUint64(&atom, 1, 0)
atomic.SwapUint64(&atom, 5)
atomic.StoreUint64(&atom, 1)
}
}
func stressUint64() func() {
var atom Uint64
return func() {
atom.Load()
atom.Add(1)
atom.Sub(2)
atom.Inc()
atom.Dec()
atom.CAS(1, 0)
atom.Swap(5)
atom.Store(1)
}
}
func stressFloat64() func() {
var atom Float64
return func() {
atom.Load()
atom.CAS(1.0, 0.1)
atom.Add(1.1)
atom.Sub(0.2)
atom.Store(1.0)
}
}
func stressBool() func() {
var atom Bool
return func() {
atom.Load()
atom.Store(false)
atom.Swap(true)
atom.CAS(true, false)
atom.CAS(true, false)
atom.Load()
atom.Toggle()
atom.Toggle()
}
}
func stressString() func() {
var atom String
return func() {
atom.Load()
atom.Store("abc")
atom.Load()
atom.Store("def")
atom.Load()
atom.Store("")
}
}
func stressDuration() func() {
var atom = NewDuration(0)
return func() {
atom.Load()
atom.Add(1)
atom.Sub(2)
atom.CAS(1, 0)
atom.Swap(5)
atom.Store(1)
}
}
func stressError() func() {
var atom = NewError(nil)
var err1 = errors.New("err1")
var err2 = errors.New("err2")
return func() {
atom.Load()
atom.Store(err1)
atom.Load()
atom.Store(err2)
atom.Load()
atom.Store(nil)
}
}
atomic-1.8.0/string.go 0000664 0000000 0000000 00000003323 14060164306 0014632 0 ustar 00root root 0000000 0000000 // @generated Code generated by gen-atomicwrapper.
// Copyright (c) 2020-2021 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
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package atomic
// String is an atomic type-safe wrapper for string values.
type String struct {
_ nocmp // disallow non-atomic comparison
v Value
}
var _zeroString string
// NewString creates a new String.
func NewString(v string) *String {
x := &String{}
if v != _zeroString {
x.Store(v)
}
return x
}
// Load atomically loads the wrapped string.
func (x *String) Load() string {
if v := x.v.Load(); v != nil {
return v.(string)
}
return _zeroString
}
// Store atomically stores the passed string.
func (x *String) Store(v string) {
x.v.Store(v)
}
atomic-1.8.0/string_ext.go 0000664 0000000 0000000 00000003321 14060164306 0015510 0 ustar 00root root 0000000 0000000 // Copyright (c) 2020 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
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package atomic
//go:generate bin/gen-atomicwrapper -name=String -type=string -wrapped=Value -file=string.go
// String returns the wrapped value.
func (s *String) String() string {
return s.Load()
}
// MarshalText encodes the wrapped string into a textual form.
//
// This makes it encodable as JSON, YAML, XML, and more.
func (s *String) MarshalText() ([]byte, error) {
return []byte(s.Load()), nil
}
// UnmarshalText decodes text and replaces the wrapped string with it.
//
// This makes it decodable from JSON, YAML, XML, and more.
func (s *String) UnmarshalText(b []byte) error {
s.Store(string(b))
return nil
}
atomic-1.8.0/string_test.go 0000664 0000000 0000000 00000006224 14060164306 0015674 0 ustar 00root root 0000000 0000000 // Copyright (c) 2016-2020 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
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package atomic
import (
"encoding/json"
"encoding/xml"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestStringNoInitialValue(t *testing.T) {
atom := &String{}
require.Equal(t, "", atom.Load(), "Initial value should be blank string")
}
func TestString(t *testing.T) {
atom := NewString("")
require.Equal(t, "", atom.Load(), "Expected Load to return initialized value")
atom.Store("abc")
require.Equal(t, "abc", atom.Load(), "Unexpected value after Store")
atom = NewString("bcd")
require.Equal(t, "bcd", atom.Load(), "Expected Load to return initialized value")
t.Run("JSON/Marshal", func(t *testing.T) {
bytes, err := json.Marshal(atom)
require.NoError(t, err, "json.Marshal errored unexpectedly.")
require.Equal(t, []byte(`"bcd"`), bytes, "json.Marshal encoded the wrong bytes.")
})
t.Run("JSON/Unmarshal", func(t *testing.T) {
err := json.Unmarshal([]byte(`"abc"`), &atom)
require.NoError(t, err, "json.Unmarshal errored unexpectedly.")
require.Equal(t, "abc", atom.Load(), "json.Unmarshal didn't set the correct value.")
})
t.Run("JSON/Unmarshal/Error", func(t *testing.T) {
err := json.Unmarshal([]byte("42"), &atom)
require.Error(t, err, "json.Unmarshal didn't error as expected.")
assertErrorJSONUnmarshalType(t, err,
"json.Unmarshal failed with unexpected error %v, want UnmarshalTypeError.", err)
})
atom = NewString("foo")
t.Run("XML/Marshal", func(t *testing.T) {
bytes, err := xml.Marshal(atom)
require.NoError(t, err, "xml.Marshal errored unexpectedly.")
require.Equal(t, []byte("foo"), bytes, "xml.Marshal encoded the wrong bytes.")
})
t.Run("XML/Unmarshal", func(t *testing.T) {
err := xml.Unmarshal([]byte("bar"), &atom)
require.NoError(t, err, "xml.Unmarshal errored unexpectedly.")
require.Equal(t, "bar", atom.Load(), "xml.Unmarshal didn't set the correct value.")
})
t.Run("String", func(t *testing.T) {
atom := NewString("foo")
assert.Equal(t, "foo", atom.String(),
"String() returned an unexpected value.")
})
}
atomic-1.8.0/tools/ 0000775 0000000 0000000 00000000000 14060164306 0014134 5 ustar 00root root 0000000 0000000 atomic-1.8.0/tools/go.mod 0000664 0000000 0000000 00000000220 14060164306 0015234 0 ustar 00root root 0000000 0000000 module go.uber.org/atomic/tools
require (
golang.org/x/lint v0.0.0-20190930215403-16217165b5de
honnef.co/go/tools v0.0.1-2020.1.5
)
go 1.13
atomic-1.8.0/tools/go.sum 0000664 0000000 0000000 00000005261 14060164306 0015273 0 ustar 00root root 0000000 0000000 github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d h1:/iIZNFGxc/a7C3yWjGcnboV+Tkc7mxr+p6fDztwoxuM=
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
honnef.co/go/tools v0.0.1-2020.1.5 h1:nI5egYTGJakVyOryqLs1cQO5dO0ksin5XXs2pspk75k=
honnef.co/go/tools v0.0.1-2020.1.5/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
atomic-1.8.0/tools/tools.go 0000664 0000000 0000000 00000002366 14060164306 0015632 0 ustar 00root root 0000000 0000000 // Copyright (c) 2019 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
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// +build tools
package tools
import (
// Tools used during development.
_ "golang.org/x/lint/golint"
_ "honnef.co/go/tools/cmd/staticcheck"
)
atomic-1.8.0/uint32.go 0000664 0000000 0000000 00000005726 14060164306 0014461 0 ustar 00root root 0000000 0000000 // @generated Code generated by gen-atomicint.
// Copyright (c) 2020-2021 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
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package atomic
import (
"encoding/json"
"strconv"
"sync/atomic"
)
// Uint32 is an atomic wrapper around uint32.
type Uint32 struct {
_ nocmp // disallow non-atomic comparison
v uint32
}
// NewUint32 creates a new Uint32.
func NewUint32(i uint32) *Uint32 {
return &Uint32{v: i}
}
// Load atomically loads the wrapped value.
func (i *Uint32) Load() uint32 {
return atomic.LoadUint32(&i.v)
}
// Add atomically adds to the wrapped uint32 and returns the new value.
func (i *Uint32) Add(n uint32) uint32 {
return atomic.AddUint32(&i.v, n)
}
// Sub atomically subtracts from the wrapped uint32 and returns the new value.
func (i *Uint32) Sub(n uint32) uint32 {
return atomic.AddUint32(&i.v, ^(n - 1))
}
// Inc atomically increments the wrapped uint32 and returns the new value.
func (i *Uint32) Inc() uint32 {
return i.Add(1)
}
// Dec atomically decrements the wrapped uint32 and returns the new value.
func (i *Uint32) Dec() uint32 {
return i.Sub(1)
}
// CAS is an atomic compare-and-swap.
func (i *Uint32) CAS(old, new uint32) bool {
return atomic.CompareAndSwapUint32(&i.v, old, new)
}
// Store atomically stores the passed value.
func (i *Uint32) Store(n uint32) {
atomic.StoreUint32(&i.v, n)
}
// Swap atomically swaps the wrapped uint32 and returns the old value.
func (i *Uint32) Swap(n uint32) uint32 {
return atomic.SwapUint32(&i.v, n)
}
// MarshalJSON encodes the wrapped uint32 into JSON.
func (i *Uint32) MarshalJSON() ([]byte, error) {
return json.Marshal(i.Load())
}
// UnmarshalJSON decodes JSON into the wrapped uint32.
func (i *Uint32) UnmarshalJSON(b []byte) error {
var v uint32
if err := json.Unmarshal(b, &v); err != nil {
return err
}
i.Store(v)
return nil
}
// String encodes the wrapped value as a string.
func (i *Uint32) String() string {
v := i.Load()
return strconv.FormatUint(uint64(v), 10)
}
atomic-1.8.0/uint32_test.go 0000664 0000000 0000000 00000006040 14060164306 0015506 0 ustar 00root root 0000000 0000000 // Copyright (c) 2020 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
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package atomic
import (
"encoding/json"
"math"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestUint32(t *testing.T) {
atom := NewUint32(42)
require.Equal(t, uint32(42), atom.Load(), "Load didn't work.")
require.Equal(t, uint32(46), atom.Add(4), "Add didn't work.")
require.Equal(t, uint32(44), atom.Sub(2), "Sub didn't work.")
require.Equal(t, uint32(45), atom.Inc(), "Inc didn't work.")
require.Equal(t, uint32(44), atom.Dec(), "Dec didn't work.")
require.True(t, atom.CAS(44, 0), "CAS didn't report a swap.")
require.Equal(t, uint32(0), atom.Load(), "CAS didn't set the correct value.")
require.Equal(t, uint32(0), atom.Swap(1), "Swap didn't return the old value.")
require.Equal(t, uint32(1), atom.Load(), "Swap didn't set the correct value.")
atom.Store(42)
require.Equal(t, uint32(42), atom.Load(), "Store didn't set the correct value.")
t.Run("JSON/Marshal", func(t *testing.T) {
bytes, err := json.Marshal(atom)
require.NoError(t, err, "json.Marshal errored unexpectedly.")
require.Equal(t, []byte("42"), bytes, "json.Marshal encoded the wrong bytes.")
})
t.Run("JSON/Unmarshal", func(t *testing.T) {
err := json.Unmarshal([]byte("40"), &atom)
require.NoError(t, err, "json.Unmarshal errored unexpectedly.")
require.Equal(t, uint32(40), atom.Load(), "json.Unmarshal didn't set the correct value.")
})
t.Run("JSON/Unmarshal/Error", func(t *testing.T) {
err := json.Unmarshal([]byte(`"40"`), &atom)
require.Error(t, err, "json.Unmarshal didn't error as expected.")
assertErrorJSONUnmarshalType(t, err,
"json.Unmarshal failed with unexpected error %v, want UnmarshalTypeError.", err)
})
t.Run("String", func(t *testing.T) {
// Use an integer with the signed bit set. If we're converting
// incorrectly, we'll get a negative value here.
atom := NewUint32(math.MaxUint32)
assert.Equal(t, "4294967295", atom.String(),
"String() returned an unexpected value.")
})
}
atomic-1.8.0/uint64.go 0000664 0000000 0000000 00000005726 14060164306 0014466 0 ustar 00root root 0000000 0000000 // @generated Code generated by gen-atomicint.
// Copyright (c) 2020-2021 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
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package atomic
import (
"encoding/json"
"strconv"
"sync/atomic"
)
// Uint64 is an atomic wrapper around uint64.
type Uint64 struct {
_ nocmp // disallow non-atomic comparison
v uint64
}
// NewUint64 creates a new Uint64.
func NewUint64(i uint64) *Uint64 {
return &Uint64{v: i}
}
// Load atomically loads the wrapped value.
func (i *Uint64) Load() uint64 {
return atomic.LoadUint64(&i.v)
}
// Add atomically adds to the wrapped uint64 and returns the new value.
func (i *Uint64) Add(n uint64) uint64 {
return atomic.AddUint64(&i.v, n)
}
// Sub atomically subtracts from the wrapped uint64 and returns the new value.
func (i *Uint64) Sub(n uint64) uint64 {
return atomic.AddUint64(&i.v, ^(n - 1))
}
// Inc atomically increments the wrapped uint64 and returns the new value.
func (i *Uint64) Inc() uint64 {
return i.Add(1)
}
// Dec atomically decrements the wrapped uint64 and returns the new value.
func (i *Uint64) Dec() uint64 {
return i.Sub(1)
}
// CAS is an atomic compare-and-swap.
func (i *Uint64) CAS(old, new uint64) bool {
return atomic.CompareAndSwapUint64(&i.v, old, new)
}
// Store atomically stores the passed value.
func (i *Uint64) Store(n uint64) {
atomic.StoreUint64(&i.v, n)
}
// Swap atomically swaps the wrapped uint64 and returns the old value.
func (i *Uint64) Swap(n uint64) uint64 {
return atomic.SwapUint64(&i.v, n)
}
// MarshalJSON encodes the wrapped uint64 into JSON.
func (i *Uint64) MarshalJSON() ([]byte, error) {
return json.Marshal(i.Load())
}
// UnmarshalJSON decodes JSON into the wrapped uint64.
func (i *Uint64) UnmarshalJSON(b []byte) error {
var v uint64
if err := json.Unmarshal(b, &v); err != nil {
return err
}
i.Store(v)
return nil
}
// String encodes the wrapped value as a string.
func (i *Uint64) String() string {
v := i.Load()
return strconv.FormatUint(uint64(v), 10)
}
atomic-1.8.0/uint64_test.go 0000664 0000000 0000000 00000006052 14060164306 0015516 0 ustar 00root root 0000000 0000000 // Copyright (c) 2020 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
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package atomic
import (
"encoding/json"
"math"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestUint64(t *testing.T) {
atom := NewUint64(42)
require.Equal(t, uint64(42), atom.Load(), "Load didn't work.")
require.Equal(t, uint64(46), atom.Add(4), "Add didn't work.")
require.Equal(t, uint64(44), atom.Sub(2), "Sub didn't work.")
require.Equal(t, uint64(45), atom.Inc(), "Inc didn't work.")
require.Equal(t, uint64(44), atom.Dec(), "Dec didn't work.")
require.True(t, atom.CAS(44, 0), "CAS didn't report a swap.")
require.Equal(t, uint64(0), atom.Load(), "CAS didn't set the correct value.")
require.Equal(t, uint64(0), atom.Swap(1), "Swap didn't return the old value.")
require.Equal(t, uint64(1), atom.Load(), "Swap didn't set the correct value.")
atom.Store(42)
require.Equal(t, uint64(42), atom.Load(), "Store didn't set the correct value.")
t.Run("JSON/Marshal", func(t *testing.T) {
bytes, err := json.Marshal(atom)
require.NoError(t, err, "json.Marshal errored unexpectedly.")
require.Equal(t, []byte("42"), bytes, "json.Marshal encoded the wrong bytes.")
})
t.Run("JSON/Unmarshal", func(t *testing.T) {
err := json.Unmarshal([]byte("40"), &atom)
require.NoError(t, err, "json.Unmarshal errored unexpectedly.")
require.Equal(t, uint64(40), atom.Load(), "json.Unmarshal didn't set the correct value.")
})
t.Run("JSON/Unmarshal/Error", func(t *testing.T) {
err := json.Unmarshal([]byte(`"40"`), &atom)
require.Error(t, err, "json.Unmarshal didn't error as expected.")
assertErrorJSONUnmarshalType(t, err,
"json.Unmarshal failed with unexpected error %v, want UnmarshalTypeError.", err)
})
t.Run("String", func(t *testing.T) {
// Use an integer with the signed bit set. If we're converting
// incorrectly, we'll get a negative value here.
atom := NewUint64(math.MaxUint64)
assert.Equal(t, "18446744073709551615", atom.String(),
"String() returned an unexpected value.")
})
}
atomic-1.8.0/uintptr.go 0000664 0000000 0000000 00000006004 14060164306 0015030 0 ustar 00root root 0000000 0000000 // @generated Code generated by gen-atomicint.
// Copyright (c) 2020-2021 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
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package atomic
import (
"encoding/json"
"strconv"
"sync/atomic"
)
// Uintptr is an atomic wrapper around uintptr.
type Uintptr struct {
_ nocmp // disallow non-atomic comparison
v uintptr
}
// NewUintptr creates a new Uintptr.
func NewUintptr(i uintptr) *Uintptr {
return &Uintptr{v: i}
}
// Load atomically loads the wrapped value.
func (i *Uintptr) Load() uintptr {
return atomic.LoadUintptr(&i.v)
}
// Add atomically adds to the wrapped uintptr and returns the new value.
func (i *Uintptr) Add(n uintptr) uintptr {
return atomic.AddUintptr(&i.v, n)
}
// Sub atomically subtracts from the wrapped uintptr and returns the new value.
func (i *Uintptr) Sub(n uintptr) uintptr {
return atomic.AddUintptr(&i.v, ^(n - 1))
}
// Inc atomically increments the wrapped uintptr and returns the new value.
func (i *Uintptr) Inc() uintptr {
return i.Add(1)
}
// Dec atomically decrements the wrapped uintptr and returns the new value.
func (i *Uintptr) Dec() uintptr {
return i.Sub(1)
}
// CAS is an atomic compare-and-swap.
func (i *Uintptr) CAS(old, new uintptr) bool {
return atomic.CompareAndSwapUintptr(&i.v, old, new)
}
// Store atomically stores the passed value.
func (i *Uintptr) Store(n uintptr) {
atomic.StoreUintptr(&i.v, n)
}
// Swap atomically swaps the wrapped uintptr and returns the old value.
func (i *Uintptr) Swap(n uintptr) uintptr {
return atomic.SwapUintptr(&i.v, n)
}
// MarshalJSON encodes the wrapped uintptr into JSON.
func (i *Uintptr) MarshalJSON() ([]byte, error) {
return json.Marshal(i.Load())
}
// UnmarshalJSON decodes JSON into the wrapped uintptr.
func (i *Uintptr) UnmarshalJSON(b []byte) error {
var v uintptr
if err := json.Unmarshal(b, &v); err != nil {
return err
}
i.Store(v)
return nil
}
// String encodes the wrapped value as a string.
func (i *Uintptr) String() string {
v := i.Load()
return strconv.FormatUint(uint64(v), 10)
}
atomic-1.8.0/uintptr_test.go 0000664 0000000 0000000 00000006100 14060164306 0016064 0 ustar 00root root 0000000 0000000 // Copyright (c) 2021 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
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package atomic
import (
"encoding/json"
"math"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestUintptr(t *testing.T) {
atom := NewUintptr(42)
require.Equal(t, uintptr(42), atom.Load(), "Load didn't work.")
require.Equal(t, uintptr(46), atom.Add(4), "Add didn't work.")
require.Equal(t, uintptr(44), atom.Sub(2), "Sub didn't work.")
require.Equal(t, uintptr(45), atom.Inc(), "Inc didn't work.")
require.Equal(t, uintptr(44), atom.Dec(), "Dec didn't work.")
require.True(t, atom.CAS(44, 0), "CAS didn't report a swap.")
require.Equal(t, uintptr(0), atom.Load(), "CAS didn't set the correct value.")
require.Equal(t, uintptr(0), atom.Swap(1), "Swap didn't return the old value.")
require.Equal(t, uintptr(1), atom.Load(), "Swap didn't set the correct value.")
atom.Store(42)
require.Equal(t, uintptr(42), atom.Load(), "Store didn't set the correct value.")
t.Run("JSON/Marshal", func(t *testing.T) {
bytes, err := json.Marshal(atom)
require.NoError(t, err, "json.Marshal errored unexpectedly.")
require.Equal(t, []byte("42"), bytes, "json.Marshal encoded the wrong bytes.")
})
t.Run("JSON/Unmarshal", func(t *testing.T) {
err := json.Unmarshal([]byte("40"), &atom)
require.NoError(t, err, "json.Unmarshal errored unexpectedly.")
require.Equal(t, uintptr(40), atom.Load(), "json.Unmarshal didn't set the correct value.")
})
t.Run("JSON/Unmarshal/Error", func(t *testing.T) {
err := json.Unmarshal([]byte(`"40"`), &atom)
require.Error(t, err, "json.Unmarshal didn't error as expected.")
assertErrorJSONUnmarshalType(t, err,
"json.Unmarshal failed with unexpected error %v, want UnmarshalTypeError.", err)
})
t.Run("String", func(t *testing.T) {
// Use an integer with the signed bit set. If we're converting
// incorrectly, we'll get a negative value here.
atom := NewUintptr(uintptr(math.MaxUint64))
assert.Equal(t, "18446744073709551615", atom.String(),
"String() returned an unexpected value.")
})
}
atomic-1.8.0/unsafe_pointer.go 0000664 0000000 0000000 00000004012 14060164306 0016341 0 ustar 00root root 0000000 0000000 // Copyright (c) 2021 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
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package atomic
import (
"sync/atomic"
"unsafe"
)
// UnsafePointer is an atomic wrapper around unsafe.Pointer.
type UnsafePointer struct {
_ nocmp // disallow non-atomic comparison
v unsafe.Pointer
}
// NewUnsafePointer creates a new UnsafePointer.
func NewUnsafePointer(p unsafe.Pointer) *UnsafePointer {
return &UnsafePointer{v: p}
}
// Load atomically loads the wrapped value.
func (p *UnsafePointer) Load() unsafe.Pointer {
return atomic.LoadPointer(&p.v)
}
// Store atomically stores the passed value.
func (p *UnsafePointer) Store(q unsafe.Pointer) {
atomic.StorePointer(&p.v, q)
}
// Swap atomically swaps the wrapped unsafe.Pointer and returns the old value.
func (p *UnsafePointer) Swap(q unsafe.Pointer) unsafe.Pointer {
return atomic.SwapPointer(&p.v, q)
}
// CAS is an atomic compare-and-swap.
func (p *UnsafePointer) CAS(old, new unsafe.Pointer) bool {
return atomic.CompareAndSwapPointer(&p.v, old, new)
}
atomic-1.8.0/unsafe_pointer_test.go 0000664 0000000 0000000 00000005120 14060164306 0017401 0 ustar 00root root 0000000 0000000 // Copyright (c) 2021 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
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package atomic
import (
"testing"
"unsafe"
"github.com/stretchr/testify/require"
)
func TestUnsafePointer(t *testing.T) {
i := int64(42)
j := int64(0)
k := int64(1)
tests := []struct {
desc string
newAtomic func() *UnsafePointer
initial unsafe.Pointer
}{
{
desc: "non-empty",
newAtomic: func() *UnsafePointer {
return NewUnsafePointer(unsafe.Pointer(&i))
},
initial: unsafe.Pointer(&i),
},
{
desc: "nil",
newAtomic: func() *UnsafePointer {
var p UnsafePointer
return &p
},
initial: unsafe.Pointer(nil),
},
}
for _, tt := range tests {
t.Run(tt.desc, func(t *testing.T) {
t.Run("Load", func(t *testing.T) {
atom := tt.newAtomic()
require.Equal(t, tt.initial, atom.Load(), "Load should report nil.")
})
t.Run("Swap", func(t *testing.T) {
atom := tt.newAtomic()
require.Equal(t, tt.initial, atom.Swap(unsafe.Pointer(&k)), "Swap didn't return the old value.")
require.Equal(t, unsafe.Pointer(&k), atom.Load(), "Swap didn't set the correct value.")
})
t.Run("CAS", func(t *testing.T) {
atom := tt.newAtomic()
require.True(t, atom.CAS(tt.initial, unsafe.Pointer(&j)), "CAS didn't report a swap.")
require.Equal(t, unsafe.Pointer(&j), atom.Load(), "CAS didn't set the correct value.")
})
t.Run("Store", func(t *testing.T) {
atom := tt.newAtomic()
atom.Store(unsafe.Pointer(&i))
require.Equal(t, unsafe.Pointer(&i), atom.Load(), "Store didn't set the correct value.")
})
})
}
}
atomic-1.8.0/value.go 0000664 0000000 0000000 00000002473 14060164306 0014445 0 ustar 00root root 0000000 0000000 // Copyright (c) 2020 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
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package atomic
import "sync/atomic"
// Value shadows the type of the same name from sync/atomic
// https://godoc.org/sync/atomic#Value
type Value struct {
atomic.Value
_ nocmp // disallow non-atomic comparison
}
atomic-1.8.0/value_test.go 0000664 0000000 0000000 00000002633 14060164306 0015502 0 ustar 00root root 0000000 0000000 // Copyright (c) 2020 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
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package atomic
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestValue(t *testing.T) {
var v Value
assert.Nil(t, v.Load(), "initial Value is not nil")
v.Store(42)
assert.Equal(t, 42, v.Load())
v.Store(84)
assert.Equal(t, 84, v.Load())
assert.Panics(t, func() { v.Store("foo") })
}