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 {
|
func (i *Uint64) Swap(n uint64) uint64 {
|
||||||
return atomic.SwapUint64(&i.uint64, n)
|
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)
|
atom.Store(42)
|
||||||
require.Equal(t, uint64(42), atom.Load(), "Store didn't set the correct value.")
|
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