Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/add_flip_method'
Browse files Browse the repository at this point in the history
  • Loading branch information
Leo Chen committed Jun 29, 2020
2 parents b1f26cf + 9e538c6 commit 8067d84
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 13 deletions.
26 changes: 15 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,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.Toggle() *AtomicBool // Negates boolean atomically and returns a new AtomicBool object which holds previous boolean value.


// embedding
Expand All @@ -30,22 +31,25 @@ type Foo struct {

## Benchmark:

- Go 1.11.0
- OS X 10.12.2
- Go 1.11.5
- OS X 10.14.5

```shell
# Read
BenchmarkMutexRead-4 100000000 21.0 ns/op
BenchmarkAtomicValueRead-4 200000000 6.30 ns/op
BenchmarkAtomicBoolRead-4 300000000 4.21 ns/op # <--- This package
BenchmarkMutexRead-4 100000000 14.7 ns/op
BenchmarkAtomicValueRead-4 2000000000 0.45 ns/op
BenchmarkAtomicBoolRead-4 2000000000 0.35 ns/op # <--- This package

# Write
BenchmarkMutexWrite-4 100000000 21.6 ns/op
BenchmarkAtomicValueWrite-4 30000000 43.4 ns/op
BenchmarkAtomicBoolWrite-4 200000000 9.87 ns/op # <--- This package
BenchmarkMutexWrite-4 100000000 14.5 ns/op
BenchmarkAtomicValueWrite-4 100000000 10.5 ns/op
BenchmarkAtomicBoolWrite-4 300000000 5.21 ns/op # <--- This package

# CAS
BenchmarkMutexCAS-4 30000000 44.9 ns/op
BenchmarkAtomicBoolCAS-4 100000000 11.7 ns/op # <--- This package
```
BenchmarkMutexCAS-4 50000000 31.3 ns/op
BenchmarkAtomicBoolCAS-4 200000000 7.18 ns/op # <--- This package

# Toggle
BenchmarkMutexToggle-4 50000000 32.6 ns/op
BenchmarkAtomicBoolToggle-4 300000000 5.21 ns/op # <--- This package
```
7 changes: 6 additions & 1 deletion bool.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func (ab *AtomicBool) IsSet() bool {
return atomic.LoadInt32((*int32)(ab)) == 1
}

// SetTo sets the boolean with given Boolean
// SetTo sets the boolean with given Boolean.
func (ab *AtomicBool) SetTo(yes bool) {
if yes {
atomic.StoreInt32((*int32)(ab), 1)
Expand All @@ -49,6 +49,11 @@ func (ab *AtomicBool) SetTo(yes bool) {
}
}

// Toggle negates boolean atomically and returns a new AtomicBool object which holds previous boolean value.
func (ab *AtomicBool) Toggle() *AtomicBool {
return NewBool(atomic.AddInt32((*int32)(ab), 1)&1 == 0)
}

// 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) {
Expand Down
49 changes: 48 additions & 1 deletion bool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,27 @@ func TestBool(t *testing.T) {
if set := v.SetToIf(false, true); !set || !v.IsSet() {
t.Fatal("AtomicBool.SetTo(false, true) failed")
}

v = New()
if v.IsSet() {
t.Fatal("Empty value of AtomicBool should be false")
}

_ = v.Toggle()
if !v.IsSet() {
t.Fatal("AtomicBool.Toggle() to true failed")
}

prev := v.Toggle()
if v.IsSet() == prev.IsSet() {
t.Fatal("AtomicBool.Toggle() to false failed")
}
}

func TestRace(t *testing.T) {
repeat := 10000
var wg sync.WaitGroup
wg.Add(repeat * 3)
wg.Add(repeat * 4)
v := New()

// Writer
Expand All @@ -80,6 +95,15 @@ func TestRace(t *testing.T) {
wg.Done()
}
}()

// Reader And Writer
go func() {
for i := 0; i < repeat; i++ {
v.Toggle()
wg.Done()
}
}()

wg.Wait()
}

Expand All @@ -89,6 +113,7 @@ func ExampleAtomicBool() {
cond.IsSet() // returns true
cond.UnSet() // set to false
cond.SetTo(true) // set to whatever you want
cond.Toggle() // toggles the boolean value
}

// Benchmark Read
Expand Down Expand Up @@ -174,3 +199,25 @@ func BenchmarkAtomicBoolCAS(b *testing.B) {
v.SetToIf(false, true)
}
}

// Benchmark toggle boolean value

func BenchmarkMutexToggle(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 BenchmarkAtomicBoolToggle(b *testing.B) {
v := New()
b.ResetTimer()
for i := 0; i < b.N; i++ {
v.Toggle()
}
}

0 comments on commit 8067d84

Please sign in to comment.