forked from mirror/abool
reintroduce Toggle()
This commit is contained in:
parent
00beeaa184
commit
6ded1b6f08
9
bool.go
9
bool.go
|
@ -58,8 +58,15 @@ func (ab *AtomicBool) SetTo(yes bool) {
|
|||
}
|
||||
|
||||
// Toggle inverts the Boolean then returns the value before inverting.
|
||||
// Based on: https://github.com/uber-go/atomic/blob/3504dfaa1fa414923b1c8693f45d2f6931daf229/bool_ext.go#L40
|
||||
func (ab *AtomicBool) Toggle() bool {
|
||||
return atomic.AddInt32((*int32)(&ab.boolean), 1)&1 == 0
|
||||
var old bool
|
||||
for {
|
||||
old = ab.IsSet()
|
||||
if ab.SetToIf(old, !old) {
|
||||
return old
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SetToIf sets the Boolean to new only if the Boolean matches the old.
|
||||
|
|
54
bool_test.go
54
bool_test.go
|
@ -2,7 +2,6 @@ package abool
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"math"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
|
@ -110,35 +109,6 @@ func TestToogleMultipleTimes(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestToogleAfterOverflow(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var value int32 = math.MaxInt32
|
||||
v := &AtomicBool{value}
|
||||
|
||||
valueBeforeToggle := v.boolean
|
||||
|
||||
// test first toggle after overflow
|
||||
v.Toggle()
|
||||
expected := math.MaxInt32%2 == 0
|
||||
if v.IsSet() != expected {
|
||||
t.Fatalf("AtomicBool.Toogle() doesn't work after overflow, expected: %v, got %v", expected, v.IsSet())
|
||||
}
|
||||
|
||||
// make sure overflow happened
|
||||
var valueAfterToggle int32 = v.boolean
|
||||
if valueAfterToggle >= valueBeforeToggle {
|
||||
t.Fatalf("Overflow does not happen as expected, before %d, after: %d", valueBeforeToggle, valueAfterToggle)
|
||||
}
|
||||
|
||||
// test second toggle after overflow
|
||||
v.Toggle()
|
||||
expected = !expected
|
||||
if v.IsSet() != expected {
|
||||
t.Fatalf("AtomicBool.Toogle() doesn't work after the second call after overflow, expected: %v, got %v", expected, v.IsSet())
|
||||
}
|
||||
}
|
||||
|
||||
func TestRace(t *testing.T) {
|
||||
repeat := 10000
|
||||
var wg sync.WaitGroup
|
||||
|
@ -171,6 +141,22 @@ func TestRace(t *testing.T) {
|
|||
wg.Wait()
|
||||
}
|
||||
|
||||
func TestSetToIfAfterMultipleToggles(t *testing.T) {
|
||||
v := New() // false
|
||||
|
||||
v.Toggle() // true
|
||||
v.Toggle() // false
|
||||
v.Toggle() // true
|
||||
|
||||
// As v is true, it should now be flipped to false
|
||||
v.SetToIf(true, false)
|
||||
expected := false
|
||||
|
||||
if v.IsSet() != expected {
|
||||
t.Fatalf("Toggling the value atleast 3 times, until it's true, `SetToIf(true, false)` should flip v to false, expected: %v, got %v", expected, v.IsSet())
|
||||
}
|
||||
}
|
||||
|
||||
func TestJSONCompatibleWithBuiltinBool(t *testing.T) {
|
||||
for _, value := range []bool{true, false} {
|
||||
// Test bool -> bytes -> AtomicBool
|
||||
|
@ -248,6 +234,14 @@ func ExampleAtomicBool() {
|
|||
cond.SetToIf(new, old) // Sets to `new` only if the Boolean matches the `old`, returns whether succeeded
|
||||
}
|
||||
|
||||
func BenchmarkAtomicBoolToggle(b *testing.B) {
|
||||
v := New()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = v.Toggle()
|
||||
}
|
||||
}
|
||||
|
||||
// Benchmark Read
|
||||
|
||||
func BenchmarkMutexRead(b *testing.B) {
|
||||
|
|
Loading…
Reference in New Issue