diff --git a/atomic.go b/atomic.go index 618576a..2282e7e 100644 --- a/atomic.go +++ b/atomic.go @@ -42,6 +42,11 @@ func (i *Int32) Add(n int32) int32 { return atomic.AddInt32(&i.int32, n) } +// Sub atomically subtracts from the wrapped int32 and returns the new value. +func (i *Int32) Sub(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) @@ -49,7 +54,7 @@ func (i *Int32) Inc() int32 { // Dec atomically decrements the wrapped int32 and returns the new value. func (i *Int32) Dec() int32 { - return i.Add(-1) + return i.Sub(1) } // CAS is an atomic compare-and-swap. @@ -85,6 +90,11 @@ func (i *Int64) Add(n int64) int64 { return atomic.AddInt64(&i.int64, n) } +// Sub atomically subtracts from the wrapped int64 and returns the new value. +func (i *Int64) Sub(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) @@ -92,7 +102,7 @@ func (i *Int64) Inc() int64 { // Dec atomically decrements the wrapped int64 and returns the new value. func (i *Int64) Dec() int64 { - return i.Add(-1) + return i.Sub(1) } // CAS is an atomic compare-and-swap. @@ -128,6 +138,11 @@ func (i *Uint32) Add(n uint32) uint32 { return atomic.AddUint32(&i.uint32, n) } +// Sub atomically subtracts from the wrapped uint32 and returns the new value. +func (i *Uint32) Sub(n uint32) uint32 { + return atomic.AddUint32(&i.uint32, ^(n - 1)) +} + // Inc atomically increments the wrapped uint32 and returns the new value. func (i *Uint32) Inc() uint32 { return i.Add(1) @@ -135,7 +150,7 @@ func (i *Uint32) Inc() uint32 { // Dec atomically decrements the wrapped int32 and returns the new value. func (i *Uint32) Dec() uint32 { - return i.Add(^uint32(0)) + return i.Sub(1) } // CAS is an atomic compare-and-swap. @@ -171,6 +186,11 @@ func (i *Uint64) Add(n uint64) uint64 { return atomic.AddUint64(&i.uint64, n) } +// Sub atomically subtracts from the wrapped uint64 and returns the new value. +func (i *Uint64) Sub(n uint64) uint64 { + return atomic.AddUint64(&i.uint64, ^(n - 1)) +} + // Inc atomically increments the wrapped uint64 and returns the new value. func (i *Uint64) Inc() uint64 { return i.Add(1) @@ -178,7 +198,7 @@ func (i *Uint64) Inc() uint64 { // Dec atomically decrements the wrapped uint64 and returns the new value. func (i *Uint64) Dec() uint64 { - return i.Add(^uint64(0)) + return i.Sub(1) } // CAS is an atomic compare-and-swap. diff --git a/atomic_test.go b/atomic_test.go index f3bc17a..24d6576 100644 --- a/atomic_test.go +++ b/atomic_test.go @@ -30,7 +30,8 @@ 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(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.") @@ -48,7 +49,8 @@ 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(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.") @@ -66,7 +68,8 @@ 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(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.") @@ -84,7 +87,8 @@ 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(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.") diff --git a/stress_test.go b/stress_test.go index b41e949..5703067 100644 --- a/stress_test.go +++ b/stress_test.go @@ -36,6 +36,7 @@ func TestStressInt32(t *testing.T) { for j := 0; j < _iterations; j++ { atom.Load() atom.Add(1) + atom.Sub(2) atom.Inc() atom.Dec() atom.CAS(1, 0) @@ -54,6 +55,7 @@ func TestStressInt64(t *testing.T) { for j := 0; j < _iterations; j++ { atom.Load() atom.Add(1) + atom.Sub(2) atom.Inc() atom.Dec() atom.CAS(1, 0) @@ -72,6 +74,7 @@ func TestStressUint32(t *testing.T) { for j := 0; j < _iterations; j++ { atom.Load() atom.Add(1) + atom.Sub(2) atom.Inc() atom.Dec() atom.CAS(1, 0) @@ -90,6 +93,7 @@ func TestStressUint64(t *testing.T) { for j := 0; j < _iterations; j++ { atom.Load() atom.Add(1) + atom.Sub(2) atom.Inc() atom.Dec() atom.CAS(1, 0)