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:
39
atomic.go
39
atomic.go
@@ -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
|
||||
}
|
||||
|
||||
@@ -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.")
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user