diff --git a/README.md b/README.md index 042d1ca..1542a83 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ cond.IsSet() // Returns true cond.UnSet() // Set to false cond.SetTo(true) // Set to whatever you want cond.SetToIf(false, true) // Set to true if it is false, returns false(not set) +cond.Flip() // Flip the boolean value, true to false, or false to ture // embedding @@ -45,5 +46,9 @@ BenchmarkAtomicBoolWrite-4 200000000 9.87 ns/op # <--- This package # CAS BenchmarkMutexCAS-4 30000000 44.9 ns/op BenchmarkAtomicBoolCAS-4 100000000 11.7 ns/op # <--- This package + +# Flip +BenchmarkMutexFlip-4 50000000 29.7 ns/op +BenchmarkAtomicBoolFlip-4 200000000 8.65 ns/op # <--- This package ``` diff --git a/bool.go b/bool.go index fdda210..7c8d194 100644 --- a/bool.go +++ b/bool.go @@ -49,6 +49,11 @@ func (ab *AtomicBool) SetTo(yes bool) { } } +// Flip flips the boolean value whether the value is set or not +func (ab *AtomicBool) Flip() { + atomic.StoreInt32((*int32)(ab), atomic.LoadInt32((*int32)(ab))^1) +} + // SetToIf sets the Boolean to new only if the Boolean matches the old // Returns whether the set was done func (ab *AtomicBool) SetToIf(old, new bool) (set bool) { diff --git a/bool_test.go b/bool_test.go index d63517f..6d83431 100644 --- a/bool_test.go +++ b/bool_test.go @@ -49,12 +49,18 @@ func TestBool(t *testing.T) { if set := v.SetToIf(false, true); !set || !v.IsSet() { t.Fatal("AtomicBool.SetTo(false, true) failed") } + + v.Flip() // expected false + if v.IsSet() { + t.Fatal("AtomicBool.Flip() failed") + } + } func TestRace(t *testing.T) { repeat := 10000 var wg sync.WaitGroup - wg.Add(repeat * 3) + wg.Add(repeat * 4) v := New() // Writer @@ -80,6 +86,15 @@ func TestRace(t *testing.T) { wg.Done() } }() + + // Reader And Writer + go func() { + for i := 0; i < repeat; i++ { + v.Flip() + wg.Done() + } + }() + wg.Wait() } @@ -89,6 +104,7 @@ func ExampleAtomicBool() { cond.IsSet() // returns true cond.UnSet() // set to false cond.SetTo(true) // set to whatever you want + cond.Flip() // flips the boolean value } // Benchmark Read @@ -174,3 +190,25 @@ func BenchmarkAtomicBoolCAS(b *testing.B) { v.SetToIf(false, true) } } + +// Benchmark flip boolean value + +func BenchmarkMutexFlip(b *testing.B) { + var m sync.RWMutex + var v bool + b.ResetTimer() + for i := 0; i < b.N; i++ { + m.Lock() + v = !v + m.Unlock() + } + b.StopTimer() +} + +func BenchmarkAtomicBoolFlip(b *testing.B) { + v := New() + b.ResetTimer() + for i := 0; i < b.N; i++ { + v.Flip() + } +}