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.
|
// 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 {
|
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.
|
// 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 (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"math"
|
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"testing"
|
"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) {
|
func TestRace(t *testing.T) {
|
||||||
repeat := 10000
|
repeat := 10000
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
|
@ -171,6 +141,22 @@ func TestRace(t *testing.T) {
|
||||||
wg.Wait()
|
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) {
|
func TestJSONCompatibleWithBuiltinBool(t *testing.T) {
|
||||||
for _, value := range []bool{true, false} {
|
for _, value := range []bool{true, false} {
|
||||||
// Test bool -> bytes -> AtomicBool
|
// 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
|
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
|
// Benchmark Read
|
||||||
|
|
||||||
func BenchmarkMutexRead(b *testing.B) {
|
func BenchmarkMutexRead(b *testing.B) {
|
||||||
|
|
Loading…
Reference in New Issue