Skip to content

Commit

Permalink
Add int wrapper
Browse files Browse the repository at this point in the history
  • Loading branch information
julienschmidt committed Sep 22, 2019
1 parent 296aae0 commit c68a852
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 1 deletion.
37 changes: 37 additions & 0 deletions atom.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,43 @@ func (f *Float64) Value() (value float64) {
return math.Float64frombits(atomic.LoadUint64(&f.value))
}

// Int is a wrapper for atomically accessed int values.
type Int struct {
_noCopy noCopy
value uintptr
}

// Add atomically adds delta to the current value and returns the new value.
func (i *Int) Add(delta int) (new int) {
return int(atomic.AddUintptr(&i.value, uintptr(delta)))
}

// CompareAndSwap atomically sets the new value only if the current value
// matches the given old value and returns whether the new value was set.
func (i *Int) CompareAndSwap(old, new int) (swapped bool) {
return atomic.CompareAndSwapUintptr(&i.value, uintptr(old), uintptr(new))
}

// Set sets the new value regardless of the previous value.
func (i *Int) Set(value int) {
atomic.StoreUintptr(&i.value, uintptr(value))
}

// Sub atomically subtracts delta to the current value and returns the new value.
func (i *Int) Sub(delta int) (new int) {
return i.Add(-delta)
}

// Swap atomically sets the new value and returns the previous value.
func (i *Int) Swap(new int) (old int) {
return int(atomic.SwapUintptr(&i.value, uintptr(new)))
}

// Value returns the current value.
func (i *Int) Value() (value int) {
return int(atomic.LoadUintptr(&i.value))
}

// Int32 is a wrapper for atomically accessed int32 values.
type Int32 struct {
_noCopy noCopy
Expand Down
67 changes: 66 additions & 1 deletion atom_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@ import (
)

const (
minUint = 0
maxUint = ^uint(0)
minUint = 0

maxInt = int(maxUint >> 1)
minInt = -maxInt - 1
)

func TestBool(t *testing.T) {
Expand Down Expand Up @@ -207,6 +210,68 @@ func TestFloat64(t *testing.T) {
}
}

func TestInt(t *testing.T) {
var i Int
if i.Value() != 0 {
t.Fatal("Expected initial value to be 0")
}

var v1 int = 1337
i.Set(v1)
if v := i.Value(); v != v1 {
t.Fatal("Value unchanged")
}

if v := i.Sub(v1); v != 0 {
t.Fatal("New value does not match:", v)
}
if v := i.Add(v1); v != v1 {
t.Fatal("New value does not match:", v)
}

var v2 int = 987654321
if i.CompareAndSwap(v2, v2) {
t.Fatal("CompareAndSwap reported swap when the old value did not match")
}
if v := i.Value(); v != v1 {
t.Fatal("Value changed")
}

if !i.CompareAndSwap(v1, v2) {
t.Fatal("CompareAndSwap did not report a swap")
}
if v := i.Value(); v != v2 {
t.Fatal("Value unchanged")
}

if v := i.Swap(v1); v != v2 {
t.Fatal("Old value does not match:", v)
}
if v := i.Value(); v != v1 {
t.Fatal("Value unchanged")
}

// test underflow behavior
v3 := int(minInt)
i.Set(v3)
if v := i.Value(); v != v3 {
t.Fatal("Value unchanged")
}
if v := i.Sub(1); v != (v3 - 1) {
t.Fatal("New value does not match:", v)
}

// test overflow behavior
v4 := int(maxInt)
i.Set(v4)
if v := i.Value(); v != v4 {
t.Fatal("Value unchanged")
}
if v := i.Add(1); v != (v4 + 1) {
t.Fatal("New value does not match:", v)
}
}

func TestInt32(t *testing.T) {
var i Int32
if i.Value() != 0 {
Expand Down

0 comments on commit c68a852

Please sign in to comment.