atomically negates boolean value with Toggle method

This commit is contained in:
barryz 2019-07-22 13:04:35 +08:00
parent a8aae64969
commit 42463bd9a0
3 changed files with 20 additions and 24 deletions

View File

@ -18,7 +18,7 @@ cond.IsSet() // Returns true
cond.UnSet() // Set to false cond.UnSet() // Set to false
cond.SetTo(true) // Set to whatever you want cond.SetTo(true) // Set to whatever you want
cond.SetToIf(false, true) // Set to true if it is false, returns false(not set) cond.SetToIf(false, true) // Set to true if it is false, returns false(not set)
cond.Flip() // Flip toggles the value(replaces with its opposite value) cond.Toggle() bool // Toggle the boolean value atomically and returns the previous value.
// embedding // embedding
@ -47,8 +47,8 @@ BenchmarkAtomicBoolWrite-4 200000000 9.87 ns/op # <--- This package
BenchmarkMutexCAS-4 30000000 44.9 ns/op BenchmarkMutexCAS-4 30000000 44.9 ns/op
BenchmarkAtomicBoolCAS-4 100000000 11.7 ns/op # <--- This package BenchmarkAtomicBoolCAS-4 100000000 11.7 ns/op # <--- This package
# Flip # Toggle
BenchmarkMutexFlip-4 50000000 29.7 ns/op BenchmarkMutexToggle-4 50000000 30.7 ns/op
BenchmarkAtomicBoolFlip-4 200000000 8.65 ns/op # <--- This package BenchmarkAtomicBoolToggle-4 300000000 5.27 ns/op # <--- This package
``` ```

10
bool.go
View File

@ -49,13 +49,9 @@ func (ab *AtomicBool) SetTo(yes bool) {
} }
} }
// Flip toggles the Boolean (replaces with its opposite value). // Toggle negates boolean atomically and returns the previous value.
func (ab *AtomicBool) Flip() { func (ab *AtomicBool) Toggle() bool {
var o, n int32 return (atomic.AddInt32((*int32)(ab), 1)-1)&1 == 1
o, n = 0, 1
if !atomic.CompareAndSwapInt32((*int32)(ab), o, n) {
atomic.CompareAndSwapInt32((*int32)(ab), n, o)
}
} }
// 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

View File

@ -50,9 +50,9 @@ func TestBool(t *testing.T) {
t.Fatal("AtomicBool.SetTo(false, true) failed") t.Fatal("AtomicBool.SetTo(false, true) failed")
} }
v.Flip() // expected false _ = v.Toggle() // expected false
if v.IsSet() { if v.IsSet() {
t.Fatal("AtomicBool.Flip() failed") t.Fatal("AtomicBool.Toggle() failed")
} }
} }
@ -90,7 +90,7 @@ func TestRace(t *testing.T) {
// Reader And Writer // Reader And Writer
go func() { go func() {
for i := 0; i < repeat; i++ { for i := 0; i < repeat; i++ {
v.Flip() v.Toggle()
wg.Done() wg.Done()
} }
}() }()
@ -104,7 +104,7 @@ func ExampleAtomicBool() {
cond.IsSet() // returns true cond.IsSet() // returns true
cond.UnSet() // set to false cond.UnSet() // set to false
cond.SetTo(true) // set to whatever you want cond.SetTo(true) // set to whatever you want
cond.Flip() // flips the boolean value cond.Toggle() // toggles the boolean value
} }
// Benchmark Read // Benchmark Read
@ -191,9 +191,9 @@ func BenchmarkAtomicBoolCAS(b *testing.B) {
} }
} }
// Benchmark flip boolean value // Benchmark toggle boolean value
func BenchmarkMutexFlip(b *testing.B) { func BenchmarkMutexToggle(b *testing.B) {
var m sync.RWMutex var m sync.RWMutex
var v bool var v bool
b.ResetTimer() b.ResetTimer()
@ -205,10 +205,10 @@ func BenchmarkMutexFlip(b *testing.B) {
b.StopTimer() b.StopTimer()
} }
func BenchmarkAtomicBoolFlip(b *testing.B) { func BenchmarkAtomicBoolToggle(b *testing.B) {
v := New() v := New()
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
v.Flip() v.Toggle()
} }
} }