From df1d8a392de61f9988b58dbec54d024752254129 Mon Sep 17 00:00:00 2001 From: Tevin Zhang Date: Thu, 2 Jun 2016 11:47:41 +0800 Subject: [PATCH] Add CAS methods --- README.md | 25 +++++++++++++++---------- bool.go | 13 +++++++++++++ bool_test.go | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 87dc2a7..3428a64 100644 --- a/README.md +++ b/README.md @@ -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 ``` diff --git a/bool.go b/bool.go index 985d269..cbd9347 100644 --- a/bool.go +++ b/bool.go @@ -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) +} diff --git a/bool_test.go b/bool_test.go index 81fd636..d63517f 100644 --- a/bool_test.go +++ b/bool_test.go @@ -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) + } +}