Add CAS methods

This commit is contained in:
Tevin Zhang 2016-06-02 11:47:41 +08:00
parent 3bdfbdf06a
commit df1d8a392d
3 changed files with 60 additions and 10 deletions

View File

@ -12,10 +12,11 @@ import "github.com/tevino/abool"
cond := abool.New() // default to false
cond.Set() // set to true
cond.IsSet() // returns true
cond.UnSet() // set to false
cond.SetTo(true) // set to whatever you want
cond.Set() // Set to true
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)
// embedding
@ -31,13 +32,17 @@ type Foo struct {
```shell
# Read
BenchmarkMutexRead-4 100000000 21.1 ns/op
BenchmarkAtomicValueRead-4 200000000 6.33 ns/op
BenchmarkAtomicBoolRead-4 300000000 4.28 ns/op # <--- This package
BenchmarkMutexRead-4 100000000 21.0 ns/op
BenchmarkAtomicValueRead-4 200000000 6.30 ns/op
BenchmarkAtomicBoolRead-4 300000000 4.21 ns/op # <--- This package
# Write
BenchmarkMutexWrite-4 100000000 21.7 ns/op
BenchmarkAtomicValueWrite-4 30000000 47.8 ns/op
BenchmarkAtomicBoolWrite-4 200000000 9.83 ns/op # <--- This package
BenchmarkMutexWrite-4 100000000 21.6 ns/op
BenchmarkAtomicValueWrite-4 30000000 43.4 ns/op
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
```

13
bool.go
View File

@ -46,3 +46,16 @@ func (ab *AtomicBool) SetTo(yes bool) {
atomic.StoreInt32((*int32)(ab), 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) {
var o, n int32
if old {
o = 1
}
if new {
n = 1
}
return atomic.CompareAndSwapInt32((*int32)(ab), o, n)
}

View File

@ -41,6 +41,14 @@ func TestBool(t *testing.T) {
if v.IsSet() {
t.Fatal("AtomicBool.SetTo(false) failed")
}
if set := v.SetToIf(true, false); set || v.IsSet() {
t.Fatal("AtomicBool.SetTo(true, false) failed")
}
if set := v.SetToIf(false, true); !set || !v.IsSet() {
t.Fatal("AtomicBool.SetTo(false, true) failed")
}
}
func TestRace(t *testing.T) {
@ -142,3 +150,27 @@ func BenchmarkAtomicBoolWrite(b *testing.B) {
v.Set()
}
}
// Benchmark CAS
func BenchmarkMutexCAS(b *testing.B) {
var m sync.RWMutex
var v bool
b.ResetTimer()
for i := 0; i < b.N; i++ {
m.Lock()
if !v {
v = true
}
m.Unlock()
}
b.StopTimer()
}
func BenchmarkAtomicBoolCAS(b *testing.B) {
v := New()
b.ResetTimer()
for i := 0; i < b.N; i++ {
v.SetToIf(false, true)
}
}