pax_global_header00006660000000000000000000000064144245143570014523gustar00rootroot0000000000000052 comment=76f817c8b7e771cdffc2b9f11a7ebb80333ca92b atomic-1.11.0/000077500000000000000000000000001442451435700130575ustar00rootroot00000000000000atomic-1.11.0/.codecov.yml000066400000000000000000000015611442451435700153050ustar00rootroot00000000000000coverage: 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.11.0/.github/000077500000000000000000000000001442451435700144175ustar00rootroot00000000000000atomic-1.11.0/.github/PULL_REQUEST_TEMPLATE.md000066400000000000000000000004551442451435700202240ustar00rootroot00000000000000Before 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.11.0/.github/workflows/000077500000000000000000000000001442451435700164545ustar00rootroot00000000000000atomic-1.11.0/.github/workflows/fossa.yaml000066400000000000000000000005411442451435700204530ustar00rootroot00000000000000name: FOSSA Analysis on: push permissions: contents: read 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.11.0/.github/workflows/go.yml000066400000000000000000000015631442451435700176110ustar00rootroot00000000000000name: Go on: push: branches: ['*'] tags: ['v*'] pull_request: branches: ['*'] permissions: contents: read jobs: build: runs-on: ubuntu-latest strategy: matrix: go: ["1.17.x", "1.18.x", "1.19.x"] include: - go: 1.19.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.11.0/.gitignore000066400000000000000000000002061442451435700150450ustar00rootroot00000000000000/bin .DS_Store /vendor cover.html cover.out lint.log # Binaries *.test # Profiling output *.prof # Output of fossa analyzer /fossa atomic-1.11.0/CHANGELOG.md000066400000000000000000000075701442451435700147010ustar00rootroot00000000000000# 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.11.0] - 2023-05-02 ### Fixed - Fix initialization of `Value` wrappers. ### Added - Add `String` method to `atomic.Pointer[T]` type allowing users to safely print underlying values of pointers. [1.11.0]: https://github.com/uber-go/atomic/compare/v1.10.0...v1.11.0 ## [1.10.0] - 2022-08-11 ### Added - Add `atomic.Float32` type for atomic operations on `float32`. - Add `CompareAndSwap` and `Swap` methods to `atomic.String`, `atomic.Error`, and `atomic.Value`. - Add generic `atomic.Pointer[T]` type for atomic operations on pointers of any type. This is present only for Go 1.18 or higher, and is a drop-in for replacement for the standard library's `sync/atomic.Pointer` type. ### Changed - Deprecate `CAS` methods on all types in favor of corresponding `CompareAndSwap` methods. Thanks to @eNV25 and @icpd for their contributions to this release. [1.10.0]: https://github.com/uber-go/atomic/compare/v1.9.0...v1.10.0 ## [1.9.0] - 2021-07-15 ### Added - Add `Float64.Swap` to match int atomic operations. - Add `atomic.Time` type for atomic operations on `time.Time` values. [1.9.0]: https://github.com/uber-go/atomic/compare/v1.8.0...v1.9.0 ## [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.8.0]: https://github.com/uber-go/atomic/compare/v1.7.0...v1.8.0 ## [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.7.0]: https://github.com/uber-go/atomic/compare/v1.6.0...v1.7.0 ## [1.6.0] - 2020-02-24 ### Changed - Drop library dependency on `golang.org/x/{lint, tools}`. [1.6.0]: https://github.com/uber-go/atomic/compare/v1.5.1...v1.6.0 ## [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.1]: https://github.com/uber-go/atomic/compare/v1.5.0...v1.5.1 ## [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.5.0]: https://github.com/uber-go/atomic/compare/v1.4.0...v1.5.0 ## [1.4.0] - 2019-05-01 ### Added - Add `atomic.Error` type for atomic operations on `error` values. [1.4.0]: https://github.com/uber-go/atomic/compare/v1.3.2...v1.4.0 ## [1.3.2] - 2018-05-02 ### Added - Add `atomic.Duration` type for atomic operations on `time.Duration` values. [1.3.2]: https://github.com/uber-go/atomic/compare/v1.3.1...v1.3.2 ## [1.3.1] - 2017-11-14 ### Fixed - Revert optimization for `atomic.String.Store("")` which caused data races. [1.3.1]: https://github.com/uber-go/atomic/compare/v1.3.0...v1.3.1 ## [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.3.0]: https://github.com/uber-go/atomic/compare/v1.2.0...v1.3.0 ## [1.2.0] - 2017-04-12 ### Added - Shadow `atomic.Value` from `sync/atomic`. [1.2.0]: https://github.com/uber-go/atomic/compare/v1.1.0...v1.2.0 ## [1.1.0] - 2017-03-10 ### Added - Add atomic `Float64` type. ### Changed - Support new `go.uber.org/atomic` import path. [1.1.0]: https://github.com/uber-go/atomic/compare/v1.0.0...v1.1.0 ## [1.0.0] - 2016-07-18 - Initial release. [1.0.0]: https://github.com/uber-go/atomic/releases/tag/v1.0.0 atomic-1.11.0/LICENSE.txt000066400000000000000000000020531442451435700147020ustar00rootroot00000000000000Copyright (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.11.0/Makefile000066400000000000000000000040711442451435700145210ustar00rootroot00000000000000# 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.11.0/README.md000066400000000000000000000040011442451435700143310ustar00rootroot00000000000000# 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.11.0/assert_test.go000066400000000000000000000033041442451435700157460ustar00rootroot00000000000000// 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.11.0/bool.go000066400000000000000000000050061442451435700143420ustar00rootroot00000000000000// @generated Code generated by gen-atomicwrapper. // Copyright (c) 2020-2023 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(val bool) *Bool { x := &Bool{} if val != _zeroBool { x.Store(val) } 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(val bool) { x.v.Store(boolToInt(val)) } // CAS is an atomic compare-and-swap for bool values. // // Deprecated: Use CompareAndSwap. func (x *Bool) CAS(old, new bool) (swapped bool) { return x.CompareAndSwap(old, new) } // CompareAndSwap is an atomic compare-and-swap for bool values. func (x *Bool) CompareAndSwap(old, new bool) (swapped bool) { return x.v.CompareAndSwap(boolToInt(old), boolToInt(new)) } // Swap atomically stores the given bool and returns the old // value. func (x *Bool) Swap(val bool) (old bool) { return truthy(x.v.Swap(boolToInt(val))) } // 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.11.0/bool_ext.go000066400000000000000000000032641442451435700152260ustar00rootroot00000000000000// 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() (old 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.11.0/bool_test.go000066400000000000000000000110651442451435700154030ustar00rootroot00000000000000// 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.") }) }) } func TestBool_InitializeDefaults(t *testing.T) { tests := []struct { msg string newBool func() *Bool }{ { msg: "Uninitialized", newBool: func() *Bool { var b Bool return &b }, }, { msg: "NewBool with default", newBool: func() *Bool { return NewBool(false) }, }, { msg: "Bool swapped with default", newBool: func() *Bool { b := NewBool(true) b.Swap(false) return b }, }, { msg: "Bool CAS'd with default", newBool: func() *Bool { b := NewBool(true) b.CompareAndSwap(true, false) return b }, }, } for _, tt := range tests { t.Run(tt.msg, func(t *testing.T) { t.Run("MarshalJSON", func(t *testing.T) { b := tt.newBool() marshalled, err := b.MarshalJSON() require.NoError(t, err) assert.Equal(t, "false", string(marshalled)) }) t.Run("String", func(t *testing.T) { b := tt.newBool() assert.Equal(t, "false", b.String()) }) t.Run("CompareAndSwap", func(t *testing.T) { b := tt.newBool() require.True(t, b.CompareAndSwap(false, true)) assert.Equal(t, true, b.Load()) }) t.Run("Swap", func(t *testing.T) { b := tt.newBool() assert.Equal(t, false, b.Swap(true)) }) }) } } atomic-1.11.0/doc.go000066400000000000000000000023111442451435700141500ustar00rootroot00000000000000// 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.11.0/duration.go000066400000000000000000000053441442451435700152410ustar00rootroot00000000000000// @generated Code generated by gen-atomicwrapper. // Copyright (c) 2020-2023 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(val time.Duration) *Duration { x := &Duration{} if val != _zeroDuration { x.Store(val) } 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(val time.Duration) { x.v.Store(int64(val)) } // CAS is an atomic compare-and-swap for time.Duration values. // // Deprecated: Use CompareAndSwap. func (x *Duration) CAS(old, new time.Duration) (swapped bool) { return x.CompareAndSwap(old, new) } // CompareAndSwap is an atomic compare-and-swap for time.Duration values. func (x *Duration) CompareAndSwap(old, new time.Duration) (swapped bool) { return x.v.CompareAndSwap(int64(old), int64(new)) } // Swap atomically stores the given time.Duration and returns the old // value. func (x *Duration) Swap(val time.Duration) (old time.Duration) { return time.Duration(x.v.Swap(int64(val))) } // 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.11.0/duration_ext.go000066400000000000000000000034321442451435700161150ustar00rootroot00000000000000// 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(delta time.Duration) time.Duration { return time.Duration(d.v.Add(int64(delta))) } // Sub atomically subtracts from the wrapped time.Duration and returns the new value. func (d *Duration) Sub(delta time.Duration) time.Duration { return time.Duration(d.v.Sub(int64(delta))) } // String encodes the wrapped value as a string. func (d *Duration) String() string { return d.Load().String() } atomic-1.11.0/duration_test.go000066400000000000000000000056741442451435700163060ustar00rootroot00000000000000// 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.11.0/error.go000066400000000000000000000044031442451435700145400ustar00rootroot00000000000000// @generated Code generated by gen-atomicwrapper. // Copyright (c) 2020-2023 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(val error) *Error { x := &Error{} if val != _zeroError { x.Store(val) } 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(val error) { x.v.Store(packError(val)) } // CompareAndSwap is an atomic compare-and-swap for error values. func (x *Error) CompareAndSwap(old, new error) (swapped bool) { if x.v.CompareAndSwap(packError(old), packError(new)) { return true } if old == _zeroError { // If the old value is the empty value, then it's possible the // underlying Value hasn't been set and is nil, so retry with nil. return x.v.CompareAndSwap(nil, packError(new)) } return false } // Swap atomically stores the given error and returns the old // value. func (x *Error) Swap(val error) (old error) { return unpackError(x.v.Swap(packError(val))) } atomic-1.11.0/error_ext.go000066400000000000000000000031571442451435700154250ustar00rootroot00000000000000// Copyright (c) 2020-2022 Uber Technologies, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // 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 -compareandswap -swap -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.11.0/error_test.go000066400000000000000000000075341442451435700156070ustar00rootroot00000000000000// 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/assert" "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") } func TestErrorSwap(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") old := atom.Swap(err2) require.Equal(t, err2, atom.Load(), "Expected Load to return overridden value") require.Equal(t, err1, old, "Expected old to be initial value") } func TestErrorCompareAndSwap(t *testing.T) { err1 := errors.New("hello1") err2 := errors.New("hello2") atom := NewError(err1) require.Equal(t, err1, atom.Load(), "Expected Load to return initialized value") swapped := atom.CompareAndSwap(err2, err2) require.False(t, swapped, "Expected swapped to be false") require.Equal(t, err1, atom.Load(), "Expected Load to return initial value") swapped = atom.CompareAndSwap(err1, err2) require.True(t, swapped, "Expected swapped to be true") require.Equal(t, err2, atom.Load(), "Expected Load to return overridden value") } func TestError_InitializeDefaults(t *testing.T) { tests := []struct { msg string newError func() *Error }{ { msg: "Uninitialized", newError: func() *Error { var e Error return &e }, }, { msg: "NewError with default", newError: func() *Error { return NewError(nil) }, }, { msg: "Error swapped with default", newError: func() *Error { e := NewError(assert.AnError) e.Swap(nil) return e }, }, { msg: "Error CAS'd with default", newError: func() *Error { e := NewError(assert.AnError) e.CompareAndSwap(assert.AnError, nil) return e }, }, } for _, tt := range tests { t.Run(tt.msg, func(t *testing.T) { t.Run("CompareAndSwap", func(t *testing.T) { e := tt.newError() require.True(t, e.CompareAndSwap(nil, assert.AnError)) assert.Equal(t, assert.AnError, e.Load()) }) t.Run("Swap", func(t *testing.T) { e := tt.newError() assert.Equal(t, nil, e.Swap(assert.AnError)) }) }) } } atomic-1.11.0/example_test.go000066400000000000000000000027101442451435700161000ustar00rootroot00000000000000// 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.11.0/float32.go000066400000000000000000000044271442451435700146670ustar00rootroot00000000000000// @generated Code generated by gen-atomicwrapper. // Copyright (c) 2020-2023 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" ) // Float32 is an atomic type-safe wrapper for float32 values. type Float32 struct { _ nocmp // disallow non-atomic comparison v Uint32 } var _zeroFloat32 float32 // NewFloat32 creates a new Float32. func NewFloat32(val float32) *Float32 { x := &Float32{} if val != _zeroFloat32 { x.Store(val) } return x } // Load atomically loads the wrapped float32. func (x *Float32) Load() float32 { return math.Float32frombits(x.v.Load()) } // Store atomically stores the passed float32. func (x *Float32) Store(val float32) { x.v.Store(math.Float32bits(val)) } // Swap atomically stores the given float32 and returns the old // value. func (x *Float32) Swap(val float32) (old float32) { return math.Float32frombits(x.v.Swap(math.Float32bits(val))) } // MarshalJSON encodes the wrapped float32 into JSON. func (x *Float32) MarshalJSON() ([]byte, error) { return json.Marshal(x.Load()) } // UnmarshalJSON decodes a float32 from JSON. func (x *Float32) UnmarshalJSON(b []byte) error { var v float32 if err := json.Unmarshal(b, &v); err != nil { return err } x.Store(v) return nil } atomic-1.11.0/float32_ext.go000066400000000000000000000053051442451435700155430ustar00rootroot00000000000000// Copyright (c) 2020-2022 Uber Technologies, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // 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 ( "math" "strconv" ) //go:generate bin/gen-atomicwrapper -name=Float32 -type=float32 -wrapped=Uint32 -pack=math.Float32bits -unpack=math.Float32frombits -swap -json -imports math -file=float32.go // Add atomically adds to the wrapped float32 and returns the new value. func (f *Float32) Add(delta float32) float32 { for { old := f.Load() new := old + delta if f.CAS(old, new) { return new } } } // Sub atomically subtracts from the wrapped float32 and returns the new value. func (f *Float32) Sub(delta float32) float32 { return f.Add(-delta) } // CAS is an atomic compare-and-swap for float32 values. // // Deprecated: Use CompareAndSwap func (f *Float32) CAS(old, new float32) (swapped bool) { return f.CompareAndSwap(old, new) } // CompareAndSwap is an atomic compare-and-swap for float32 values. // // Note: CompareAndSwap handles NaN incorrectly. NaN != NaN using Go's inbuilt operators // but CompareAndSwap allows a stored NaN to compare equal to a passed in NaN. // This avoids typical CompareAndSwap loops from blocking forever, e.g., // // for { // old := atom.Load() // new = f(old) // if atom.CompareAndSwap(old, new) { // break // } // } // // If CompareAndSwap did not match NaN to match, then the above would loop forever. func (f *Float32) CompareAndSwap(old, new float32) (swapped bool) { return f.v.CompareAndSwap(math.Float32bits(old), math.Float32bits(new)) } // String encodes the wrapped value as a string. func (f *Float32) String() string { // 'g' is the behavior for floats with %v. return strconv.FormatFloat(float64(f.Load()), 'g', -1, 32) } atomic-1.11.0/float32_test.go000066400000000000000000000056131442451435700157240ustar00rootroot00000000000000// 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 TestFloat32(t *testing.T) { atom := NewFloat32(4.2) require.Equal(t, float32(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, float32(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, float32(42.0), atom.Load(), "Store didn't set the correct value.") require.Equal(t, float32(42.5), atom.Add(0.5), "Add didn't work.") require.Equal(t, float32(42.0), atom.Sub(0.5), "Sub didn't work.") require.Equal(t, float32(42.0), atom.Swap(45.0), "Swap didn't return the old value.") require.Equal(t, float32(45.0), atom.Load(), "Swap didn't set the correct value.") 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, float32(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", NewFloat32(42.5).String(), "String() returned an unexpected value.") }) } atomic-1.11.0/float64.go000066400000000000000000000044271442451435700146740ustar00rootroot00000000000000// @generated Code generated by gen-atomicwrapper. // Copyright (c) 2020-2023 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(val float64) *Float64 { x := &Float64{} if val != _zeroFloat64 { x.Store(val) } 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(val float64) { x.v.Store(math.Float64bits(val)) } // Swap atomically stores the given float64 and returns the old // value. func (x *Float64) Swap(val float64) (old float64) { return math.Float64frombits(x.v.Swap(math.Float64bits(val))) } // 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.11.0/float64_ext.go000066400000000000000000000052741442451435700155550ustar00rootroot00000000000000// Copyright (c) 2020-2022 Uber Technologies, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // 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 ( "math" "strconv" ) //go:generate bin/gen-atomicwrapper -name=Float64 -type=float64 -wrapped=Uint64 -pack=math.Float64bits -unpack=math.Float64frombits -swap -json -imports math -file=float64.go // Add atomically adds to the wrapped float64 and returns the new value. func (f *Float64) Add(delta float64) float64 { for { old := f.Load() new := old + delta if f.CAS(old, new) { return new } } } // Sub atomically subtracts from the wrapped float64 and returns the new value. func (f *Float64) Sub(delta float64) float64 { return f.Add(-delta) } // CAS is an atomic compare-and-swap for float64 values. // // Deprecated: Use CompareAndSwap func (f *Float64) CAS(old, new float64) (swapped bool) { return f.CompareAndSwap(old, new) } // CompareAndSwap is an atomic compare-and-swap for float64 values. // // Note: CompareAndSwap handles NaN incorrectly. NaN != NaN using Go's inbuilt operators // but CompareAndSwap allows a stored NaN to compare equal to a passed in NaN. // This avoids typical CompareAndSwap loops from blocking forever, e.g., // // for { // old := atom.Load() // new = f(old) // if atom.CompareAndSwap(old, new) { // break // } // } // // If CompareAndSwap did not match NaN to match, then the above would loop forever. func (f *Float64) CompareAndSwap(old, new float64) (swapped bool) { return f.v.CompareAndSwap(math.Float64bits(old), math.Float64bits(new)) } // String encodes the wrapped value as a string. func (f *Float64) String() string { // 'g' is the behavior for floats with %v. return strconv.FormatFloat(f.Load(), 'g', -1, 64) } atomic-1.11.0/float64_test.go000066400000000000000000000056131442451435700157310ustar00rootroot00000000000000// 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.") require.Equal(t, float64(42.0), atom.Swap(45.0), "Swap didn't return the old value.") require.Equal(t, float64(45.0), atom.Load(), "Swap didn't set the correct value.") 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.11.0/gen.go000066400000000000000000000030161442451435700141570ustar00rootroot00000000000000// 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.11.0/go.mod000066400000000000000000000002751442451435700141710ustar00rootroot00000000000000module go.uber.org/atomic require github.com/stretchr/testify v1.3.0 require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect ) go 1.18 atomic-1.11.0/go.sum000066400000000000000000000012711442451435700142130ustar00rootroot00000000000000github.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.11.0/int32.go000066400000000000000000000062111442451435700143450ustar00rootroot00000000000000// @generated Code generated by gen-atomicint. // Copyright (c) 2020-2023 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(val int32) *Int32 { return &Int32{v: val} } // 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(delta int32) int32 { return atomic.AddInt32(&i.v, delta) } // Sub atomically subtracts from the wrapped int32 and returns the new value. func (i *Int32) Sub(delta int32) int32 { return atomic.AddInt32(&i.v, -delta) } // 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. // // Deprecated: Use CompareAndSwap. func (i *Int32) CAS(old, new int32) (swapped bool) { return i.CompareAndSwap(old, new) } // CompareAndSwap is an atomic compare-and-swap. func (i *Int32) CompareAndSwap(old, new int32) (swapped bool) { return atomic.CompareAndSwapInt32(&i.v, old, new) } // Store atomically stores the passed value. func (i *Int32) Store(val int32) { atomic.StoreInt32(&i.v, val) } // Swap atomically swaps the wrapped int32 and returns the old value. func (i *Int32) Swap(val int32) (old int32) { return atomic.SwapInt32(&i.v, val) } // 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.11.0/int32_test.go000066400000000000000000000062001442451435700154020ustar00rootroot00000000000000// 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.11.0/int64.go000066400000000000000000000062111442451435700143520ustar00rootroot00000000000000// @generated Code generated by gen-atomicint. // Copyright (c) 2020-2023 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(val int64) *Int64 { return &Int64{v: val} } // 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(delta int64) int64 { return atomic.AddInt64(&i.v, delta) } // Sub atomically subtracts from the wrapped int64 and returns the new value. func (i *Int64) Sub(delta int64) int64 { return atomic.AddInt64(&i.v, -delta) } // 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. // // Deprecated: Use CompareAndSwap. func (i *Int64) CAS(old, new int64) (swapped bool) { return i.CompareAndSwap(old, new) } // CompareAndSwap is an atomic compare-and-swap. func (i *Int64) CompareAndSwap(old, new int64) (swapped bool) { return atomic.CompareAndSwapInt64(&i.v, old, new) } // Store atomically stores the passed value. func (i *Int64) Store(val int64) { atomic.StoreInt64(&i.v, val) } // Swap atomically swaps the wrapped int64 and returns the old value. func (i *Int64) Swap(val int64) (old int64) { return atomic.SwapInt64(&i.v, val) } // 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.11.0/int64_test.go000066400000000000000000000062221442451435700154130ustar00rootroot00000000000000// 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.11.0/internal/000077500000000000000000000000001442451435700146735ustar00rootroot00000000000000atomic-1.11.0/internal/gen-atomicint/000077500000000000000000000000001442451435700174315ustar00rootroot00000000000000atomic-1.11.0/internal/gen-atomicint/main.go000066400000000000000000000061621442451435700207110ustar00rootroot00000000000000// Copyright (c) 2020-2022 Uber Technologies, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // 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" "embed" "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.ExecuteTemplate(&buff, "wrapper.tmpl", 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) } io.WriteString(w, "// @generated Code generated by gen-atomicint.\n\n") _, err = w.Write(bs) return err } var ( //go:embed *.tmpl _tmplFS embed.FS _tmpl = template.Must(template.New("atomicint").ParseFS(_tmplFS, "*.tmpl")) ) atomic-1.11.0/internal/gen-atomicint/wrapper.tmpl000066400000000000000000000071511442451435700220130ustar00rootroot00000000000000// 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 }}(val {{ .Wrapped }}) *{{ .Name }} { return &{{ .Name }}{v: val} } // 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(delta {{ .Wrapped }}) {{ .Wrapped }} { return atomic.Add{{ .Name }}(&i.v, delta) } // Sub atomically subtracts from the wrapped {{ .Wrapped }} and returns the new value. func (i *{{ .Name }}) Sub(delta {{ .Wrapped }}) {{ .Wrapped }} { return atomic.Add{{ .Name }}(&i.v, {{- if .Unsigned -}} ^(delta - 1) {{- else -}} -delta {{- 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. // // Deprecated: Use CompareAndSwap. func (i *{{ .Name }}) CAS(old, new {{ .Wrapped }}) (swapped bool) { return i.CompareAndSwap(old, new) } // CompareAndSwap is an atomic compare-and-swap. func (i *{{ .Name }}) CompareAndSwap(old, new {{ .Wrapped }}) (swapped bool) { return atomic.CompareAndSwap{{ .Name }}(&i.v, old, new) } // Store atomically stores the passed value. func (i *{{ .Name }}) Store(val {{ .Wrapped }}) { atomic.Store{{ .Name }}(&i.v, val) } // Swap atomically swaps the wrapped {{ .Wrapped }} and returns the old value. func (i *{{ .Name }}) Swap(val {{ .Wrapped }}) (old {{ .Wrapped }}) { return atomic.Swap{{ .Name }}(&i.v, val) } // 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.11.0/internal/gen-atomicwrapper/000077500000000000000000000000001442451435700203175ustar00rootroot00000000000000atomic-1.11.0/internal/gen-atomicwrapper/main.go000066400000000000000000000123071442451435700215750ustar00rootroot00000000000000// Copyright (c) 2020-2022 Uber Technologies, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // 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. package main import ( "bytes" "embed" "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 CompareAndSwap 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 deprecated `CAS(old, new) bool` method; requires -pack") flag.BoolVar(&opts.CompareAndSwap, "compareandswap", false, "generate a `CompareAndSwap(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 || len(opts.Pack) == 0 || len(opts.Unpack) == 0 { return errors.New("flags -name, -wrapped, -pack, -unpack and -type are required") } if opts.CAS { opts.CompareAndSwap = true } 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.ExecuteTemplate(&buff, "wrapper.tmpl", 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) } io.WriteString(w, "// @generated Code generated by gen-atomicwrapper.\n\n") _, err = w.Write(bs) return err } var ( //go:embed *.tmpl _tmplFS embed.FS _tmpl = template.Must(template.New("atomicwrapper").ParseFS(_tmplFS, "*.tmpl")) ) atomic-1.11.0/internal/gen-atomicwrapper/wrapper.tmpl000066400000000000000000000066751442451435700227130ustar00rootroot00000000000000// 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 }}(val {{ .Type }}) *{{ .Name }} { x := &{{ .Name }}{} if val != _zero{{ .Name }} { x.Store(val) } 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(val {{ .Type }}) { x.v.Store({{ .Pack }}(val)) } {{ if .CAS -}} // CAS is an atomic compare-and-swap for {{ .Type }} values. // // Deprecated: Use CompareAndSwap. func (x *{{ .Name }}) CAS(old, new {{ .Type }}) (swapped bool) { return x.CompareAndSwap(old, new) } {{- end }} {{ if .CompareAndSwap -}} // CompareAndSwap is an atomic compare-and-swap for {{ .Type }} values. func (x *{{ .Name }}) CompareAndSwap(old, new {{ .Type }}) (swapped bool) { {{ if eq .Wrapped "Value" -}} if x.v.CompareAndSwap({{ .Pack }}(old), {{ .Pack }}(new)) { return true } if old == _zero{{ .Name }} { // If the old value is the empty value, then it's possible the // underlying Value hasn't been set and is nil, so retry with nil. return x.v.CompareAndSwap(nil, {{ .Pack }}(new)) } return false {{- else -}} return x.v.CompareAndSwap({{ .Pack }}(old), {{ .Pack }}(new)) {{- end }} } {{- end }} {{ if .Swap -}} // Swap atomically stores the given {{ .Type }} and returns the old // value. func (x *{{ .Name }}) Swap(val {{ .Type }}) (old {{ .Type }}) { return {{ .Unpack }}(x.v.Swap({{ .Pack }}(val))) } {{- 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.11.0/nocmp.go000066400000000000000000000026351442451435700145300ustar00rootroot00000000000000// 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.11.0/nocmp_test.go000066400000000000000000000102101442451435700155530ustar00rootroot00000000000000// 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" "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 := t.TempDir() nocmp, err := os.ReadFile("nocmp.go") require.NoError(t, err, "unable to read nocmp.go") require.NoError(t, os.WriteFile(filepath.Join(tempdir, "go.mod"), []byte(_exampleGoMod), 0o644), "unable to write go.mod") require.NoError(t, os.WriteFile(filepath.Join(tempdir, "nocmp.go"), nocmp, 0o644), "unable to write nocmp.go") require.NoError(t, os.WriteFile(filepath.Join(tempdir, "bad.go"), []byte(_badFile), 0o644), "unable to write bad.go") var stderr bytes.Buffer cmd := exec.Command("go", "build") cmd.Dir = tempdir // Create a minimal build environment 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.11.0/pointer_go118.go000066400000000000000000000024751442451435700160150ustar00rootroot00000000000000// Copyright (c) 2022 Uber Technologies, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // 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. //go:build go1.18 // +build go1.18 package atomic import "fmt" // String returns a human readable representation of a Pointer's underlying value. func (p *Pointer[T]) String() string { return fmt.Sprint(p.Load()) } atomic-1.11.0/pointer_go118_pre119.go000066400000000000000000000037631442451435700171170ustar00rootroot00000000000000// Copyright (c) 2022 Uber Technologies, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // 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. //go:build go1.18 && !go1.19 // +build go1.18,!go1.19 package atomic import "unsafe" type Pointer[T any] struct { _ nocmp // disallow non-atomic comparison p UnsafePointer } // NewPointer creates a new Pointer. func NewPointer[T any](v *T) *Pointer[T] { var p Pointer[T] if v != nil { p.p.Store(unsafe.Pointer(v)) } return &p } // Load atomically loads the wrapped value. func (p *Pointer[T]) Load() *T { return (*T)(p.p.Load()) } // Store atomically stores the passed value. func (p *Pointer[T]) Store(val *T) { p.p.Store(unsafe.Pointer(val)) } // Swap atomically swaps the wrapped pointer and returns the old value. func (p *Pointer[T]) Swap(val *T) (old *T) { return (*T)(p.p.Swap(unsafe.Pointer(val))) } // CompareAndSwap is an atomic compare-and-swap. func (p *Pointer[T]) CompareAndSwap(old, new *T) (swapped bool) { return p.p.CompareAndSwap(unsafe.Pointer(old), unsafe.Pointer(new)) } atomic-1.11.0/pointer_go119.go000066400000000000000000000036711442451435700160150ustar00rootroot00000000000000// Copyright (c) 2022 Uber Technologies, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // 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. //go:build go1.19 // +build go1.19 package atomic import "sync/atomic" // Pointer is an atomic pointer of type *T. type Pointer[T any] struct { _ nocmp // disallow non-atomic comparison p atomic.Pointer[T] } // NewPointer creates a new Pointer. func NewPointer[T any](v *T) *Pointer[T] { var p Pointer[T] if v != nil { p.p.Store(v) } return &p } // Load atomically loads the wrapped value. func (p *Pointer[T]) Load() *T { return p.p.Load() } // Store atomically stores the passed value. func (p *Pointer[T]) Store(val *T) { p.p.Store(val) } // Swap atomically swaps the wrapped pointer and returns the old value. func (p *Pointer[T]) Swap(val *T) (old *T) { return p.p.Swap(val) } // CompareAndSwap is an atomic compare-and-swap. func (p *Pointer[T]) CompareAndSwap(old, new *T) (swapped bool) { return p.p.CompareAndSwap(old, new) } atomic-1.11.0/pointer_test.go000066400000000000000000000054221442451435700161300ustar00rootroot00000000000000// Copyright (c) 2022 Uber Technologies, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // 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. //go:build go1.18 // +build go1.18 package atomic import ( "fmt" "testing" "github.com/stretchr/testify/require" ) func TestPointer(t *testing.T) { type foo struct{ v int } i := foo{42} j := foo{0} k := foo{1} tests := []struct { desc string newAtomic func() *Pointer[foo] initial *foo }{ { desc: "New", newAtomic: func() *Pointer[foo] { return NewPointer(&i) }, initial: &i, }, { desc: "New/nil", newAtomic: func() *Pointer[foo] { return NewPointer[foo](nil) }, initial: nil, }, { desc: "zero value", newAtomic: func() *Pointer[foo] { var p Pointer[foo] return &p }, initial: 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(&k), "Swap didn't return the old value.") require.Equal(t, &k, atom.Load(), "Swap didn't set the correct value.") }) t.Run("CAS", func(t *testing.T) { atom := tt.newAtomic() require.True(t, atom.CompareAndSwap(tt.initial, &j), "CAS didn't report a swap.") require.Equal(t, &j, atom.Load(), "CAS didn't set the correct value.") }) t.Run("Store", func(t *testing.T) { atom := tt.newAtomic() atom.Store(&i) require.Equal(t, &i, atom.Load(), "Store didn't set the correct value.") }) t.Run("String", func(t *testing.T) { atom := tt.newAtomic() require.Equal(t, fmt.Sprint(tt.initial), atom.String(), "String did not return the correct value.") }) }) } } atomic-1.11.0/stress_test.go000066400000000000000000000135061442451435700157750ustar00rootroot00000000000000// 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" "time" ) 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, "time": stressTime, } 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) } } func stressTime() func() { var atom = NewTime(time.Date(2021, 6, 17, 9, 0, 0, 0, time.UTC)) var dayAgo = time.Date(2021, 6, 16, 9, 0, 0, 0, time.UTC) var weekAgo = time.Date(2021, 6, 10, 9, 0, 0, 0, time.UTC) return func() { atom.Load() atom.Store(dayAgo) atom.Load() atom.Store(weekAgo) atom.Store(time.Time{}) } } atomic-1.11.0/string.go000066400000000000000000000044441442451435700147220ustar00rootroot00000000000000// @generated Code generated by gen-atomicwrapper. // Copyright (c) 2020-2023 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(val string) *String { x := &String{} if val != _zeroString { x.Store(val) } return x } // Load atomically loads the wrapped string. func (x *String) Load() string { return unpackString(x.v.Load()) } // Store atomically stores the passed string. func (x *String) Store(val string) { x.v.Store(packString(val)) } // CompareAndSwap is an atomic compare-and-swap for string values. func (x *String) CompareAndSwap(old, new string) (swapped bool) { if x.v.CompareAndSwap(packString(old), packString(new)) { return true } if old == _zeroString { // If the old value is the empty value, then it's possible the // underlying Value hasn't been set and is nil, so retry with nil. return x.v.CompareAndSwap(nil, packString(new)) } return false } // Swap atomically stores the given string and returns the old // value. func (x *String) Swap(val string) (old string) { return unpackString(x.v.Swap(packString(val))) } atomic-1.11.0/string_ext.go000066400000000000000000000036531442451435700156030ustar00rootroot00000000000000// Copyright (c) 2020-2023 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 -pack packString -unpack unpackString -compareandswap -swap -file=string.go func packString(s string) interface{} { return s } func unpackString(v interface{}) string { if s, ok := v.(string); ok { return s } return "" } // 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.11.0/string_test.go000066400000000000000000000117671442451435700157670ustar00rootroot00000000000000// 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.") }) t.Run("CompareAndSwap", func(t *testing.T) { atom := NewString("foo") swapped := atom.CompareAndSwap("bar", "bar") require.False(t, swapped, "swapped isn't false") require.Equal(t, atom.Load(), "foo", "Load returned wrong value") swapped = atom.CompareAndSwap("foo", "bar") require.True(t, swapped, "swapped isn't true") require.Equal(t, atom.Load(), "bar", "Load returned wrong value") }) t.Run("Swap", func(t *testing.T) { atom := NewString("foo") old := atom.Swap("bar") require.Equal(t, old, "foo", "Swap returned wrong value") require.Equal(t, atom.Load(), "bar", "Load returned wrong value") }) } func TestString_InitializeDefault(t *testing.T) { tests := []struct { msg string newStr func() *String }{ { msg: "Uninitialized", newStr: func() *String { var s String return &s }, }, { msg: "NewString with default", newStr: func() *String { return NewString("") }, }, { msg: "String swapped with default", newStr: func() *String { s := NewString("initial") s.Swap("") return s }, }, { msg: "String CAS'd with default", newStr: func() *String { s := NewString("initial") s.CompareAndSwap("initial", "") return s }, }, } for _, tt := range tests { t.Run(tt.msg, func(t *testing.T) { t.Run("MarshalText", func(t *testing.T) { str := tt.newStr() text, err := str.MarshalText() require.NoError(t, err) assert.Equal(t, "", string(text), "") }) t.Run("String", func(t *testing.T) { str := tt.newStr() assert.Equal(t, "", str.String()) }) t.Run("CompareAndSwap", func(t *testing.T) { str := tt.newStr() require.True(t, str.CompareAndSwap("", "new")) assert.Equal(t, "new", str.Load()) }) t.Run("Swap", func(t *testing.T) { str := tt.newStr() assert.Equal(t, "", str.Swap("new")) }) }) } } atomic-1.11.0/time.go000066400000000000000000000033161442451435700143470ustar00rootroot00000000000000// @generated Code generated by gen-atomicwrapper. // Copyright (c) 2020-2023 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" ) // Time is an atomic type-safe wrapper for time.Time values. type Time struct { _ nocmp // disallow non-atomic comparison v Value } var _zeroTime time.Time // NewTime creates a new Time. func NewTime(val time.Time) *Time { x := &Time{} if val != _zeroTime { x.Store(val) } return x } // Load atomically loads the wrapped time.Time. func (x *Time) Load() time.Time { return unpackTime(x.v.Load()) } // Store atomically stores the passed time.Time. func (x *Time) Store(val time.Time) { x.v.Store(packTime(val)) } atomic-1.11.0/time_ext.go000066400000000000000000000026651442451435700152350ustar00rootroot00000000000000// 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 "time" //go:generate bin/gen-atomicwrapper -name=Time -type=time.Time -wrapped=Value -pack=packTime -unpack=unpackTime -imports time -file=time.go func packTime(t time.Time) interface{} { return t } func unpackTime(v interface{}) time.Time { if t, ok := v.(time.Time); ok { return t } return time.Time{} } atomic-1.11.0/time_test.go000066400000000000000000000055171442451435700154130ustar00rootroot00000000000000// 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" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestTime(t *testing.T) { start := time.Date(2021, 6, 17, 9, 10, 0, 0, time.UTC) atom := NewTime(start) require.Equal(t, start, atom.Load(), "Load didn't work") require.Equal(t, time.Time{}, NewTime(time.Time{}).Load(), "Default time value is wrong") } func TestTimeLocation(t *testing.T) { // Check TZ data hasn't been lost from load/store. ny, err := time.LoadLocation("America/New_York") require.NoError(t, err, "Failed to load location") nyTime := NewTime(time.Date(2021, 1, 1, 0, 0, 0, 0, ny)) var atom Time atom.Store(nyTime.Load()) assert.Equal(t, ny, atom.Load().Location(), "Location information is wrong") } func TestLargeTime(t *testing.T) { // Check "large/small" time that are beyond int64 ns // representation (< year 1678 or > year 2262) can be // correctly load/store'd. t.Parallel() t.Run("future", func(t *testing.T) { future := time.Date(2262, 12, 31, 0, 0, 0, 0, time.UTC) atom := NewTime(future) dayAfterFuture := atom.Load().AddDate(0, 1, 0) atom.Store(dayAfterFuture) assert.Equal(t, 2263, atom.Load().Year()) }) t.Run("past", func(t *testing.T) { past := time.Date(1678, 1, 1, 0, 0, 0, 0, time.UTC) atom := NewTime(past) dayBeforePast := atom.Load().AddDate(0, -1, 0) atom.Store(dayBeforePast) assert.Equal(t, 1677, atom.Load().Year()) }) } func TestMonotonic(t *testing.T) { before := NewTime(time.Now()) time.Sleep(15 * time.Millisecond) after := NewTime(time.Now()) // try loading/storing before and test monotonic clock value hasn't been lost bt := before.Load() before.Store(bt) d := after.Load().Sub(before.Load()) assert.True(t, 15 <= d.Milliseconds()) } atomic-1.11.0/tools/000077500000000000000000000000001442451435700142175ustar00rootroot00000000000000atomic-1.11.0/tools/go.mod000066400000000000000000000006771442451435700153370ustar00rootroot00000000000000module go.uber.org/atomic/tools go 1.18 require ( golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 honnef.co/go/tools v0.3.3 ) require ( github.com/BurntSushi/toml v1.2.0 // indirect golang.org/x/exp/typeparams v0.0.0-20220722155223-a9213eeb770e // indirect golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect golang.org/x/sys v0.0.0-20220808155132-1c4a2a72c664 // indirect golang.org/x/tools v0.1.12 // indirect ) atomic-1.11.0/tools/go.sum000066400000000000000000000047201442451435700153550ustar00rootroot00000000000000github.com/BurntSushi/toml v1.2.0 h1:Rt8g24XnyGTyglgET/PRUNlrUeu9F5L+7FilkXfZgs0= github.com/BurntSushi/toml v1.2.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/exp/typeparams v0.0.0-20220722155223-a9213eeb770e h1:7Xs2YCOpMlNqSQSmrrnhlzBXIE/bpMecZplbLePTJvE= golang.org/x/exp/typeparams v0.0.0-20220722155223-a9213eeb770e/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug= golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= 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/sys v0.0.0-20220808155132-1c4a2a72c664 h1:v1W7bwXHsnLLloWYTVEdvGvA7BHMeBYsPcF0GLDxIRs= golang.org/x/sys v0.0.0-20220808155132-1c4a2a72c664/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= honnef.co/go/tools v0.3.3 h1:oDx7VAwstgpYpb3wv0oxiZlxY+foCpRAwY7Vk6XpAgA= honnef.co/go/tools v0.3.3/go.mod h1:jzwdWgg7Jdq75wlfblQxO4neNaFFSvgc1tD5Wv8U0Yw= atomic-1.11.0/tools/tools.go000066400000000000000000000024071442451435700157110ustar00rootroot00000000000000// 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. //go:build tools // +build tools package tools import ( // Tools used during development. _ "golang.org/x/lint/golint" _ "honnef.co/go/tools/cmd/staticcheck" ) atomic-1.11.0/uint32.go000066400000000000000000000063011442451435700145320ustar00rootroot00000000000000// @generated Code generated by gen-atomicint. // Copyright (c) 2020-2023 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(val uint32) *Uint32 { return &Uint32{v: val} } // 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(delta uint32) uint32 { return atomic.AddUint32(&i.v, delta) } // Sub atomically subtracts from the wrapped uint32 and returns the new value. func (i *Uint32) Sub(delta uint32) uint32 { return atomic.AddUint32(&i.v, ^(delta - 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. // // Deprecated: Use CompareAndSwap. func (i *Uint32) CAS(old, new uint32) (swapped bool) { return i.CompareAndSwap(old, new) } // CompareAndSwap is an atomic compare-and-swap. func (i *Uint32) CompareAndSwap(old, new uint32) (swapped bool) { return atomic.CompareAndSwapUint32(&i.v, old, new) } // Store atomically stores the passed value. func (i *Uint32) Store(val uint32) { atomic.StoreUint32(&i.v, val) } // Swap atomically swaps the wrapped uint32 and returns the old value. func (i *Uint32) Swap(val uint32) (old uint32) { return atomic.SwapUint32(&i.v, val) } // 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.11.0/uint32_test.go000066400000000000000000000060401442451435700155710ustar00rootroot00000000000000// 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.11.0/uint64.go000066400000000000000000000063011442451435700145370ustar00rootroot00000000000000// @generated Code generated by gen-atomicint. // Copyright (c) 2020-2023 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(val uint64) *Uint64 { return &Uint64{v: val} } // 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(delta uint64) uint64 { return atomic.AddUint64(&i.v, delta) } // Sub atomically subtracts from the wrapped uint64 and returns the new value. func (i *Uint64) Sub(delta uint64) uint64 { return atomic.AddUint64(&i.v, ^(delta - 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. // // Deprecated: Use CompareAndSwap. func (i *Uint64) CAS(old, new uint64) (swapped bool) { return i.CompareAndSwap(old, new) } // CompareAndSwap is an atomic compare-and-swap. func (i *Uint64) CompareAndSwap(old, new uint64) (swapped bool) { return atomic.CompareAndSwapUint64(&i.v, old, new) } // Store atomically stores the passed value. func (i *Uint64) Store(val uint64) { atomic.StoreUint64(&i.v, val) } // Swap atomically swaps the wrapped uint64 and returns the old value. func (i *Uint64) Swap(val uint64) (old uint64) { return atomic.SwapUint64(&i.v, val) } // 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.11.0/uint64_test.go000066400000000000000000000060521442451435700156010ustar00rootroot00000000000000// 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.11.0/uintptr.go000066400000000000000000000063611442451435700151210ustar00rootroot00000000000000// @generated Code generated by gen-atomicint. // Copyright (c) 2020-2023 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(val uintptr) *Uintptr { return &Uintptr{v: val} } // 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(delta uintptr) uintptr { return atomic.AddUintptr(&i.v, delta) } // Sub atomically subtracts from the wrapped uintptr and returns the new value. func (i *Uintptr) Sub(delta uintptr) uintptr { return atomic.AddUintptr(&i.v, ^(delta - 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. // // Deprecated: Use CompareAndSwap. func (i *Uintptr) CAS(old, new uintptr) (swapped bool) { return i.CompareAndSwap(old, new) } // CompareAndSwap is an atomic compare-and-swap. func (i *Uintptr) CompareAndSwap(old, new uintptr) (swapped bool) { return atomic.CompareAndSwapUintptr(&i.v, old, new) } // Store atomically stores the passed value. func (i *Uintptr) Store(val uintptr) { atomic.StoreUintptr(&i.v, val) } // Swap atomically swaps the wrapped uintptr and returns the old value. func (i *Uintptr) Swap(val uintptr) (old uintptr) { return atomic.SwapUintptr(&i.v, val) } // 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.11.0/uintptr_test.go000066400000000000000000000062451442451435700161610ustar00rootroot00000000000000// 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" "fmt" "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. // Use an int variable, as constants cause compile-time overflows. negative := -1 atom := NewUintptr(uintptr(negative)) want := fmt.Sprint(uintptr(negative)) assert.Equal(t, want, atom.String(), "String() returned an unexpected value.") }) } atomic-1.11.0/unsafe_pointer.go000066400000000000000000000043701442451435700164330ustar00rootroot00000000000000// Copyright (c) 2021-2022 Uber Technologies, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // 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(val unsafe.Pointer) *UnsafePointer { return &UnsafePointer{v: val} } // 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(val unsafe.Pointer) { atomic.StorePointer(&p.v, val) } // Swap atomically swaps the wrapped unsafe.Pointer and returns the old value. func (p *UnsafePointer) Swap(val unsafe.Pointer) (old unsafe.Pointer) { return atomic.SwapPointer(&p.v, val) } // CAS is an atomic compare-and-swap. // // Deprecated: Use CompareAndSwap func (p *UnsafePointer) CAS(old, new unsafe.Pointer) (swapped bool) { return p.CompareAndSwap(old, new) } // CompareAndSwap is an atomic compare-and-swap. func (p *UnsafePointer) CompareAndSwap(old, new unsafe.Pointer) (swapped bool) { return atomic.CompareAndSwapPointer(&p.v, old, new) } atomic-1.11.0/unsafe_pointer_test.go000066400000000000000000000051201442451435700174640ustar00rootroot00000000000000// 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.11.0/value.go000066400000000000000000000024731442451435700145300ustar00rootroot00000000000000// 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 { _ nocmp // disallow non-atomic comparison atomic.Value } atomic-1.11.0/value_test.go000066400000000000000000000026331442451435700155650ustar00rootroot00000000000000// 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") }) }