Add an atomic Boolean type (#4)

* Add an atomic Boolean type

Fixes #2.

* Feedback from CR

- Rename Swap to Toggle
- Add a more Swap-like Swap

* Add boolToInt helper
This commit is contained in:
Akshay Shah
2016-05-30 11:10:24 -07:00
parent e1b75a466a
commit 7afff28c37
3 changed files with 71 additions and 0 deletions

View File

@@ -215,3 +215,42 @@ func (i *Uint64) Store(n uint64) {
func (i *Uint64) Swap(n uint64) uint64 {
return atomic.SwapUint64(&i.uint64, n)
}
// Bool is an atomic Boolean.
type Bool struct{ uint32 }
// NewBool creates a Bool.
func NewBool(initial bool) *Bool {
return &Bool{boolToInt(initial)}
}
// Load atomically loads the Boolean.
func (b *Bool) Load() bool {
return truthy(atomic.LoadUint32(&b.uint32))
}
// Store atomically stores the passed value.
func (b *Bool) Store(new bool) {
atomic.StoreUint32(&b.uint32, boolToInt(new))
}
// Swap sets the given value and returns the previous value.
func (b *Bool) Swap(new bool) bool {
return truthy(atomic.SwapUint32(&b.uint32, boolToInt(new)))
}
// Toggle atomically negates the Boolean and returns the previous value.
func (b *Bool) Toggle() bool {
return truthy(atomic.AddUint32(&b.uint32, 1) - 1)
}
func truthy(n uint32) bool {
return n&1 == 1
}
func boolToInt(b bool) uint32 {
if b {
return 1
}
return 0
}

View File

@@ -101,3 +101,18 @@ func TestUint64(t *testing.T) {
atom.Store(42)
require.Equal(t, uint64(42), atom.Load(), "Store didn't set the correct value.")
}
func TestBool(t *testing.T) {
atom := NewBool(false)
require.False(t, atom.Toggle(), "Expected swap to return previous value.")
require.True(t, atom.Load(), "Unexpected state after swap.")
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.")
}

View File

@@ -103,3 +103,20 @@ func TestStressUint64(t *testing.T) {
}()
}
}
func TestStressBool(t *testing.T) {
defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(_parallelism))
atom := NewBool(false)
for i := 0; i < _parallelism; i++ {
go func() {
for j := 0; j < _iterations; j++ {
atom.Load()
atom.Store(false)
atom.Swap(true)
atom.Load()
atom.Toggle()
atom.Toggle()
}
}()
}
}