Merge pull request #1 from uber-go/import

Import atomic package
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..a2b5e5d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,11 @@
+.DS_Store
+/vendor
+/cover
+cover.out
+
+
+# Binaries
+*.test
+
+# Profiling output
+*.prof
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..acf2bdb
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,18 @@
+sudo: false
+language: go
+
+go:
+  - 1.5
+  - 1.6
+  - tip
+
+cache:
+  directories:
+    - vendor
+
+install:
+  - make install_ci
+
+script:
+  - make test_ci
+  - travis_retry goveralls -coverprofile=cover.out -service=travis-ci
diff --git a/LICENSE.txt b/LICENSE
similarity index 100%
rename from LICENSE.txt
rename to LICENSE
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..f3e1b3e
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,32 @@
+PACKAGES := $(shell glide novendor)
+
+export GO15VENDOREXPERIMENT=1
+
+
+.PHONY: build
+build:
+	go build -i $(PACKAGES)
+
+
+.PHONY: install
+install:
+	glide --version || go get github.com/Masterminds/glide
+	glide install
+
+
+.PHONY: test
+test:
+	go test -cover -race $(PACKAGES)
+
+
+.PHONY: install_ci
+install_ci: install
+	go get github.com/wadey/gocovmerge
+	go get github.com/mattn/goveralls
+	go get golang.org/x/tools/cmd/cover
+
+
+.PHONY: test_ci
+test_ci: install_ci build
+	./scripts/cover.sh $(shell go list $(PACKAGES))
+
diff --git a/atomic.go b/atomic.go
new file mode 100644
index 0000000..618576a
--- /dev/null
+++ b/atomic.go
@@ -0,0 +1,197 @@
+// 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 provides simple wrappers around numerics to enforce atomic
+// access.
+package atomic
+
+import "sync/atomic"
+
+// Int32 is an atomic wrapper around an int32.
+type Int32 struct{ int32 }
+
+// NewInt32 creates an Int32.
+func NewInt32(i int32) *Int32 {
+	return &Int32{i}
+}
+
+// Load atomically loads the wrapped value.
+func (i *Int32) Load() int32 {
+	return atomic.LoadInt32(&i.int32)
+}
+
+// Add atomically adds to the wrapped int32 and returns the new value.
+func (i *Int32) Add(n int32) int32 {
+	return atomic.AddInt32(&i.int32, n)
+}
+
+// Inc atomically increments the wrapped int32 and returns the new value.
+func (i *Int32) Inc() int32 {
+	return i.Add(1)
+}
+
+// Dec atomically decrements the wrapped int32 and returns the new value.
+func (i *Int32) Dec() int32 {
+	return i.Add(-1)
+}
+
+// CAS is an atomic compare-and-swap.
+func (i *Int32) CAS(old, new int32) bool {
+	return atomic.CompareAndSwapInt32(&i.int32, old, new)
+}
+
+// Store atomically stores the passed value.
+func (i *Int32) Store(n int32) {
+	atomic.StoreInt32(&i.int32, n)
+}
+
+// Swap atomically swaps the wrapped int32 and returns the old value.
+func (i *Int32) Swap(n int32) int32 {
+	return atomic.SwapInt32(&i.int32, n)
+}
+
+// Int64 is an atomic wrapper around an int64.
+type Int64 struct{ int64 }
+
+// NewInt64 creates an Int64.
+func NewInt64(i int64) *Int64 {
+	return &Int64{i}
+}
+
+// Load atomically loads the wrapped value.
+func (i *Int64) Load() int64 {
+	return atomic.LoadInt64(&i.int64)
+}
+
+// Add atomically adds to the wrapped int64 and returns the new value.
+func (i *Int64) Add(n int64) int64 {
+	return atomic.AddInt64(&i.int64, n)
+}
+
+// Inc atomically increments the wrapped int64 and returns the new value.
+func (i *Int64) Inc() int64 {
+	return i.Add(1)
+}
+
+// Dec atomically decrements the wrapped int64 and returns the new value.
+func (i *Int64) Dec() int64 {
+	return i.Add(-1)
+}
+
+// CAS is an atomic compare-and-swap.
+func (i *Int64) CAS(old, new int64) bool {
+	return atomic.CompareAndSwapInt64(&i.int64, old, new)
+}
+
+// Store atomically stores the passed value.
+func (i *Int64) Store(n int64) {
+	atomic.StoreInt64(&i.int64, n)
+}
+
+// Swap atomically swaps the wrapped int64 and returns the old value.
+func (i *Int64) Swap(n int64) int64 {
+	return atomic.SwapInt64(&i.int64, n)
+}
+
+// Uint32 is an atomic wrapper around an uint32.
+type Uint32 struct{ uint32 }
+
+// NewUint32 creates a Uint32.
+func NewUint32(i uint32) *Uint32 {
+	return &Uint32{i}
+}
+
+// Load atomically loads the wrapped value.
+func (i *Uint32) Load() uint32 {
+	return atomic.LoadUint32(&i.uint32)
+}
+
+// Add atomically adds to the wrapped uint32 and returns the new value.
+func (i *Uint32) Add(n uint32) uint32 {
+	return atomic.AddUint32(&i.uint32, n)
+}
+
+// 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 int32 and returns the new value.
+func (i *Uint32) Dec() uint32 {
+	return i.Add(^uint32(0))
+}
+
+// CAS is an atomic compare-and-swap.
+func (i *Uint32) CAS(old, new uint32) bool {
+	return atomic.CompareAndSwapUint32(&i.uint32, old, new)
+}
+
+// Store atomically stores the passed value.
+func (i *Uint32) Store(n uint32) {
+	atomic.StoreUint32(&i.uint32, n)
+}
+
+// Swap atomically swaps the wrapped uint32 and returns the old value.
+func (i *Uint32) Swap(n uint32) uint32 {
+	return atomic.SwapUint32(&i.uint32, n)
+}
+
+// Uint64 is an atomic wrapper around a uint64.
+type Uint64 struct{ uint64 }
+
+// NewUint64 creates a Uint64.
+func NewUint64(i uint64) *Uint64 {
+	return &Uint64{i}
+}
+
+// Load atomically loads the wrapped value.
+func (i *Uint64) Load() uint64 {
+	return atomic.LoadUint64(&i.uint64)
+}
+
+// Add atomically adds to the wrapped uint64 and returns the new value.
+func (i *Uint64) Add(n uint64) uint64 {
+	return atomic.AddUint64(&i.uint64, n)
+}
+
+// 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.Add(^uint64(0))
+}
+
+// CAS is an atomic compare-and-swap.
+func (i *Uint64) CAS(old, new uint64) bool {
+	return atomic.CompareAndSwapUint64(&i.uint64, old, new)
+}
+
+// Store atomically stores the passed value.
+func (i *Uint64) Store(n uint64) {
+	atomic.StoreUint64(&i.uint64, n)
+}
+
+// Swap atomically swaps the wrapped uint64 and returns the old value.
+func (i *Uint64) Swap(n uint64) uint64 {
+	return atomic.SwapUint64(&i.uint64, n)
+}
diff --git a/atomic_test.go b/atomic_test.go
new file mode 100644
index 0000000..f3bc17a
--- /dev/null
+++ b/atomic_test.go
@@ -0,0 +1,99 @@
+// 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 (
+	"testing"
+
+	"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(44), atom.Add(2), "Add 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.")
+}
+
+func TestInt64(t *testing.T) {
+	atom := NewInt64(42)
+
+	require.Equal(t, int64(42), atom.Load(), "Load didn't work.")
+	require.Equal(t, int64(44), atom.Add(2), "Add 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.")
+}
+
+func TestUint32(t *testing.T) {
+	atom := NewUint32(42)
+
+	require.Equal(t, uint32(42), atom.Load(), "Load didn't work.")
+	require.Equal(t, uint32(44), atom.Add(2), "Add 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.")
+}
+
+func TestUint64(t *testing.T) {
+	atom := NewUint64(42)
+
+	require.Equal(t, uint64(42), atom.Load(), "Load didn't work.")
+	require.Equal(t, uint64(44), atom.Add(2), "Add 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.")
+}
diff --git a/glide.lock b/glide.lock
new file mode 100644
index 0000000..914db23
--- /dev/null
+++ b/glide.lock
@@ -0,0 +1,4 @@
+hash: 8413cf7f8e981fc97e0ce202471bf1cab8b935615ae831b98ebc499655acd513
+updated: 2016-05-25T10:54:24.639721239-07:00
+imports: []
+devImports: []
diff --git a/glide.yaml b/glide.yaml
new file mode 100644
index 0000000..07a23a6
--- /dev/null
+++ b/glide.yaml
@@ -0,0 +1,7 @@
+package: github.com/uber-go/atomic
+imports:
+# Test dependencies
+- package: github.com/stretchr/testify
+  subpackages:
+  - assert
+  - require
diff --git a/scripts/cover.sh b/scripts/cover.sh
new file mode 100755
index 0000000..3d6171b
--- /dev/null
+++ b/scripts/cover.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+
+set -e
+
+COVER=cover
+ROOT_PKG=github.com/uber-go/atomic
+
+if [[ -d "$COVER" ]]; then
+	rm -rf "$COVER"
+fi
+mkdir -p "$COVER"
+
+i=0
+for pkg in "$@"; do
+	i=$((i + 1))
+
+	extracoverpkg=""
+	if [[ -f "$GOPATH/src/$pkg/.extra-coverpkg" ]]; then
+		extracoverpkg=$( \
+			sed -e "s|^|$pkg/|g" < "$GOPATH/src/$pkg/.extra-coverpkg" \
+			| tr '\n' ',')
+	fi
+
+	coverpkg=$(go list -json "$pkg" | jq -r '
+		.Deps
+		| map(select(startswith("'"$ROOT_PKG"'")))
+		| map(select(contains("/vendor/") | not))
+		| . + ["'"$pkg"'"]
+		| join(",")
+	')
+	if [[ -n "$extracoverpkg" ]]; then
+		coverpkg="$extracoverpkg$coverpkg"
+	fi
+
+	go test \
+		-coverprofile "$COVER/cover.${i}.out" -coverpkg "$coverpkg" \
+		-v "$pkg"
+done
+
+gocovmerge "$COVER"/*.out > cover.out
diff --git a/stress_test.go b/stress_test.go
new file mode 100644
index 0000000..b41e949
--- /dev/null
+++ b/stress_test.go
@@ -0,0 +1,101 @@
+// 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 (
+	"runtime"
+	"testing"
+)
+
+const _parallelism = 4
+const _iterations = 1000
+
+func TestStressInt32(t *testing.T) {
+	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(_parallelism))
+	atom := &Int32{0}
+	for i := 0; i < _parallelism; i++ {
+		go func() {
+			for j := 0; j < _iterations; j++ {
+				atom.Load()
+				atom.Add(1)
+				atom.Inc()
+				atom.Dec()
+				atom.CAS(1, 0)
+				atom.Swap(5)
+				atom.Store(1)
+			}
+		}()
+	}
+}
+
+func TestStressInt64(t *testing.T) {
+	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(_parallelism))
+	atom := &Int64{0}
+	for i := 0; i < _parallelism; i++ {
+		go func() {
+			for j := 0; j < _iterations; j++ {
+				atom.Load()
+				atom.Add(1)
+				atom.Inc()
+				atom.Dec()
+				atom.CAS(1, 0)
+				atom.Swap(5)
+				atom.Store(1)
+			}
+		}()
+	}
+}
+
+func TestStressUint32(t *testing.T) {
+	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(_parallelism))
+	atom := &Uint32{0}
+	for i := 0; i < _parallelism; i++ {
+		go func() {
+			for j := 0; j < _iterations; j++ {
+				atom.Load()
+				atom.Add(1)
+				atom.Inc()
+				atom.Dec()
+				atom.CAS(1, 0)
+				atom.Swap(5)
+				atom.Store(1)
+			}
+		}()
+	}
+}
+
+func TestStressUint64(t *testing.T) {
+	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(_parallelism))
+	atom := &Uint64{0}
+	for i := 0; i < _parallelism; i++ {
+		go func() {
+			for j := 0; j < _iterations; j++ {
+				atom.Load()
+				atom.Add(1)
+				atom.Inc()
+				atom.Dec()
+				atom.CAS(1, 0)
+				atom.Swap(5)
+				atom.Store(1)
+			}
+		}()
+	}
+}