Codebase list golang-github-tevino-abool / 2d463b6
Import upstream version 0.0~git20220531.edeb703+ds Debian Janitor 1 year, 6 months ago
8 changed file(s) with 647 addition(s) and 62 deletion(s). Raw diff Collapse all Expand all
00 # ABool :bulb:
1
12 [![Go Report Card](https://goreportcard.com/badge/github.com/tevino/abool)](https://goreportcard.com/report/github.com/tevino/abool)
23 [![GoDoc](https://godoc.org/github.com/tevino/abool?status.svg)](https://godoc.org/github.com/tevino/abool)
34
4 Atomic Boolean library for Go, optimized for performance yet simple to use.
5 Atomic Boolean package for Go, optimized for performance yet simple to use.
56
6 Use this for cleaner code.
7 Designed for cleaner code.
78
89 ## Usage
910
1011 ```go
11 import "github.com/tevino/abool"
12 import "github.com/tevino/abool/v2"
1213
13 cond := abool.New() // default to false
14 cond := abool.New() // default to false
1415
15 cond.Set() // Set to true
16 cond.IsSet() // Returns true
17 cond.UnSet() // Set to false
18 cond.SetTo(true) // Set to whatever you want
19 cond.SetToIf(false, true) // Set to true if it is false, returns false(not set)
16 cond.Set() // Sets to true
17 cond.IsSet() // Returns true
18 cond.UnSet() // Sets to false
19 cond.IsNotSet() // Returns true
20 cond.SetTo(any) // Sets to whatever you want
21 cond.SetToIf(old, new) // Sets to `new` only if the Boolean matches the `old`, returns whether succeeded
22 cond.Toggle() // Flip the value of `cond`, returns the value before flipping
2023
2124
2225 // embedding
2528 }
2629 ```
2730
28 ## Benchmark:
31 ## Benchmark
2932
30 - Go 1.6.2
31 - OS X 10.11.4
33 ```
34 go: v1.18.2
35 goos: darwin
36 goarch: amd64
37 cpu: Intel(R) Core(TM) i9-8950HK CPU @ 2.90GHz
3238
33 ```shell
3439 # Read
35 BenchmarkMutexRead-4 100000000 21.0 ns/op
36 BenchmarkAtomicValueRead-4 200000000 6.30 ns/op
37 BenchmarkAtomicBoolRead-4 300000000 4.21 ns/op # <--- This package
40 BenchmarkMutexRead-12 100000000 10.24 ns/op
41 BenchmarkAtomicValueRead-12 1000000000 0.4690 ns/op
42 BenchmarkAtomicBoolRead-12 1000000000 0.2345 ns/op # <--- This package
3843
3944 # Write
40 BenchmarkMutexWrite-4 100000000 21.6 ns/op
41 BenchmarkAtomicValueWrite-4 30000000 43.4 ns/op
42 BenchmarkAtomicBoolWrite-4 200000000 9.87 ns/op # <--- This package
45 BenchmarkMutexWrite-12 100000000 10.19 ns/op
46 BenchmarkAtomicValueWrite-12 164918696 7.235 ns/op
47 BenchmarkAtomicBoolWrite-12 278729533 4.341 ns/op # <--- This package
4348
4449 # CAS
45 BenchmarkMutexCAS-4 30000000 44.9 ns/op
46 BenchmarkAtomicBoolCAS-4 100000000 11.7 ns/op # <--- This package
50 BenchmarkMutexCAS-12 57333123 20.26 ns/op
51 BenchmarkAtomicBoolCAS-12 203575494 5.755 ns/op # <--- This package
52
53 # Toggle
54 BenchmarkAtomicBoolToggle-12 145249862 8.196 ns/op # <--- This package
4755 ```
4856
57 ## Special thanks to contributors
58
59 - [barryz](https://github.com/barryz)
60 - Added the `Toggle` method
61 - [Lucas Rouckhout](https://github.com/LucasRouckhout)
62 - Implemented JSON Unmarshal and Marshal interface
63 - [Sebastian Schicho](https://github.com/schicho)
64 - Reported a regression with test case
65 - Hide the underlying `int`
66 - Reintroduced the `Toggle` method
11 // better performance.
22 package abool
33
4 import "sync/atomic"
4 import (
5 "encoding/json"
6 "sync/atomic"
7 )
58
6 // New creates an AtomicBool with default to false
9 // New creates an AtomicBool with default set to false.
710 func New() *AtomicBool {
811 return new(AtomicBool)
912 }
1013
11 // NewBool creates an AtomicBool with given default value
14 // NewBool creates an AtomicBool with given default value.
1215 func NewBool(ok bool) *AtomicBool {
1316 ab := New()
1417 if ok {
1720 return ab
1821 }
1922
20 // AtomicBool is an atomic Boolean
21 // Its methods are all atomic, thus safe to be called by
22 // multiple goroutines simultaneously
23 // Note: When embedding into a struct, one should always use
24 // *AtomicBool to avoid copy
25 type AtomicBool int32
26
27 // Set sets the Boolean to true
28 func (ab *AtomicBool) Set() {
29 atomic.StoreInt32((*int32)(ab), 1)
23 // AtomicBool is an atomic Boolean.
24 // Its methods are all atomic, thus safe to be called by multiple goroutines simultaneously.
25 // Note: When embedding into a struct one should always use *AtomicBool to avoid copy.
26 type AtomicBool struct {
27 boolean int32
3028 }
3129
32 // UnSet sets the Boolean to false
33 func (ab *AtomicBool) UnSet() {
34 atomic.StoreInt32((*int32)(ab), 0)
30 // Set sets the Boolean to true.
31 func (ab *AtomicBool) Set() {
32 atomic.StoreInt32(&ab.boolean, 1)
3533 }
3634
37 // IsSet returns whether the Boolean is true
38 func (ab *AtomicBool) IsSet() bool {
39 return atomic.LoadInt32((*int32)(ab)) == 1
35 // UnSet sets the Boolean to false.
36 func (ab *AtomicBool) UnSet() {
37 atomic.StoreInt32(&ab.boolean, 0)
4038 }
4139
42 // SetTo sets the boolean with given Boolean
40 // IsSet returns whether the Boolean is true.
41 func (ab *AtomicBool) IsSet() bool {
42 return atomic.LoadInt32(&ab.boolean)&1 == 1
43 }
44
45 // IsNotSet returns whether the Boolean is false.
46 func (ab *AtomicBool) IsNotSet() bool {
47 return !ab.IsSet()
48 }
49
50 // SetTo sets the boolean with given Boolean.
4351 func (ab *AtomicBool) SetTo(yes bool) {
4452 if yes {
45 atomic.StoreInt32((*int32)(ab), 1)
53 atomic.StoreInt32(&ab.boolean, 1)
4654 } else {
47 atomic.StoreInt32((*int32)(ab), 0)
55 atomic.StoreInt32(&ab.boolean, 0)
4856 }
4957 }
5058
51 // SetToIf sets the Boolean to new only if the Boolean matches the old
52 // Returns whether the set was done
59 // Toggle inverts the Boolean then returns the value before inverting.
60 // Based on: https://github.com/uber-go/atomic/blob/3504dfaa1fa414923b1c8693f45d2f6931daf229/bool_ext.go#L40
61 func (ab *AtomicBool) Toggle() bool {
62 var old bool
63 for {
64 old = ab.IsSet()
65 if ab.SetToIf(old, !old) {
66 return old
67 }
68 }
69 }
70
71 // SetToIf sets the Boolean to new only if the Boolean matches the old.
72 // Returns whether the set was done.
5373 func (ab *AtomicBool) SetToIf(old, new bool) (set bool) {
5474 var o, n int32
5575 if old {
5878 if new {
5979 n = 1
6080 }
61 return atomic.CompareAndSwapInt32((*int32)(ab), o, n)
81 return atomic.CompareAndSwapInt32(&ab.boolean, o, n)
6282 }
83
84 // MarshalJSON behaves the same as if the AtomicBool is a builtin.bool.
85 // NOTE: There's no lock during the process, usually it shouldn't be called with other methods in parallel.
86 func (ab *AtomicBool) MarshalJSON() ([]byte, error) {
87 return json.Marshal(ab.IsSet())
88 }
89
90 // UnmarshalJSON behaves the same as if the AtomicBool is a builtin.bool.
91 // NOTE: There's no lock during the process, usually it shouldn't be called with other methods in parallel.
92 func (ab *AtomicBool) UnmarshalJSON(b []byte) error {
93 var v bool
94 err := json.Unmarshal(b, &v)
95
96 if err == nil {
97 ab.SetTo(v)
98 }
99 return err
100 }
00 package abool
11
22 import (
3 "encoding/json"
34 "sync"
45 "sync/atomic"
56 "testing"
67 )
78
8 func TestBool(t *testing.T) {
9 v := NewBool(true)
9 func TestDefaultValue(t *testing.T) {
10 t.Parallel()
11 v := New()
12 if v.IsSet() {
13 t.Fatal("Empty value of AtomicBool should be false")
14 }
15
16 v = NewBool(true)
1017 if !v.IsSet() {
11 t.Fatal("NewValue(true) failed")
18 t.Fatal("NewValue(true) should be true")
1219 }
1320
1421 v = NewBool(false)
1522 if v.IsSet() {
16 t.Fatal("NewValue(false) failed")
17 }
18
19 v = New()
20 if v.IsSet() {
21 t.Fatal("Empty value of AtomicBool should be false")
22 }
23 t.Fatal("NewValue(false) should be false")
24 }
25 }
26
27 func TestIsNotSet(t *testing.T) {
28 t.Parallel()
29 v := New()
30
31 if v.IsSet() == v.IsNotSet() {
32 t.Fatal("AtomicBool.IsNotSet() should be the opposite of IsSet()")
33 }
34 }
35
36 func TestSetUnSet(t *testing.T) {
37 t.Parallel()
38 v := New()
2339
2440 v.Set()
2541 if !v.IsSet() {
3046 if v.IsSet() {
3147 t.Fatal("AtomicBool.UnSet() failed")
3248 }
49 }
50
51 func TestSetTo(t *testing.T) {
52 t.Parallel()
53 v := New()
3354
3455 v.SetTo(true)
3556 if !v.IsSet() {
4768
4869 if set := v.SetToIf(false, true); !set || !v.IsSet() {
4970 t.Fatal("AtomicBool.SetTo(false, true) failed")
71 }
72 }
73
74 func TestToggle(t *testing.T) {
75 t.Parallel()
76 v := New()
77
78 _ = v.Toggle()
79 if !v.IsSet() {
80 t.Fatal("AtomicBool.Toggle() to true failed")
81 }
82
83 prev := v.Toggle()
84 if v.IsSet() == prev {
85 t.Fatal("AtomicBool.Toggle() to false failed")
86 }
87 }
88
89 func TestToogleMultipleTimes(t *testing.T) {
90 t.Parallel()
91
92 v := New()
93 pre := !v.IsSet()
94 for i := 0; i < 100; i++ {
95 v.SetTo(false)
96 for j := 0; j < i; j++ {
97 pre = v.Toggle()
98 }
99
100 expected := i%2 != 0
101 if v.IsSet() != expected {
102 t.Fatalf("AtomicBool.Toogle() doesn't work after %d calls, expected: %v, got %v", i, expected, v.IsSet())
103 }
104
105 if pre == v.IsSet() {
106 t.Fatalf("AtomicBool.Toogle() returned wrong value at the %dth calls, expected: %v, got %v", i, !v.IsSet(), pre)
107 }
50108 }
51109 }
52110
82140 wg.Wait()
83141 }
84142
143 func TestSetToIfAfterMultipleToggles(t *testing.T) {
144 v := New() // false
145
146 v.Toggle() // true
147 v.Toggle() // false
148 v.Toggle() // true
149
150 // As v is true, it should now be flipped to false
151 v.SetToIf(true, false)
152 expected := false
153
154 if v.IsSet() != expected {
155 t.Fatalf("Toggling the value atleast 3 times, until it's true, `SetToIf(true, false)` should flip v to false, expected: %v, got %v", expected, v.IsSet())
156 }
157 }
158
159 func TestJSONCompatibleWithBuiltinBool(t *testing.T) {
160 for _, value := range []bool{true, false} {
161 // Test bool -> bytes -> AtomicBool
162
163 // act 1. bool -> bytes
164 buf, err := json.Marshal(value)
165 if err != nil {
166 t.Fatalf("json.Marshal(%t) failed: %s", value, err)
167 }
168
169 // act 2. bytes -> AtomicBool
170 //
171 // Try to unmarshall the JSON byte slice
172 // of a normal boolean into an AtomicBool
173 //
174 // Create an AtomicBool with the oppsite default to ensure the unmarshal process did the work
175 ab := NewBool(!value)
176 err = json.Unmarshal(buf, ab)
177 if err != nil {
178 t.Fatalf(`json.Unmarshal("%s", %T) failed: %s`, buf, ab, err)
179 }
180 // assert
181 if ab.IsSet() != value {
182 t.Fatalf("Expected AtomicBool to represent %t but actual value was %t", value, ab.IsSet())
183 }
184
185 // Test AtomicBool -> bytes -> bool
186
187 // act 3. AtomicBool -> bytes
188 buf, err = json.Marshal(ab)
189 if err != nil {
190 t.Fatalf("json.Marshal(%T) failed: %s", ab, err)
191 }
192
193 // using the opposite value for the same reason as the former case
194 b := ab.IsNotSet()
195 // act 4. bytes -> bool
196 err = json.Unmarshal(buf, &b)
197 if err != nil {
198 t.Fatalf(`json.Unmarshal("%s", %T) failed: %s`, buf, &b, err)
199 }
200 // assert
201 if b != ab.IsSet() {
202 t.Fatalf(`json.Unmarshal("%s", %T) didn't work, expected %t, got %t`, buf, ab, ab.IsSet(), b)
203 }
204 }
205 }
206
207 func TestUnmarshalJSONErrorNoWrite(t *testing.T) {
208 for _, val := range []bool{true, false} {
209 ab := NewBool(val)
210 oldVal := ab.IsSet()
211 buf := []byte("invalid-json")
212 err := json.Unmarshal(buf, ab)
213 if err == nil {
214 t.Fatalf(`Error expected from json.Unmarshal("%s", %T)`, buf, ab)
215 }
216 if oldVal != ab.IsSet() {
217 t.Fatal("Failed json.Unmarshal modified the value of AtomicBool which is not expected")
218 }
219 }
220 }
221
85222 func ExampleAtomicBool() {
86 cond := New() // default to false
87 cond.Set() // set to true
88 cond.IsSet() // returns true
89 cond.UnSet() // set to false
90 cond.SetTo(true) // set to whatever you want
223 cond := New() // default to false
224 any := true
225 old := any
226 new := !any
227
228 cond.Set() // Sets to true
229 cond.IsSet() // Returns true
230 cond.UnSet() // Sets to false
231 cond.IsNotSet() // Returns true
232 cond.SetTo(any) // Sets to whatever you want
233 cond.SetToIf(new, old) // Sets to `new` only if the Boolean matches the `old`, returns whether succeeded
234 }
235
236 func BenchmarkAtomicBoolToggle(b *testing.B) {
237 v := New()
238 b.ResetTimer()
239 for i := 0; i < b.N; i++ {
240 _ = v.Toggle()
241 }
91242 }
92243
93244 // Benchmark Read
163314 }
164315 m.Unlock()
165316 }
166 b.StopTimer()
167317 }
168318
169319 func BenchmarkAtomicBoolCAS(b *testing.B) {
0 module github.com/tevino/abool
1
2 go 1.14
0 The MIT License (MIT)
1
2 Copyright (c) 2016 Tevin Zhang
3
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
10
11 The above copyright notice and this permission notice shall be included in all
12 copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 SOFTWARE.
0 // Package abool provides atomic Boolean type for cleaner code and
1 // better performance.
2 package abool
3
4 import (
5 "encoding/json"
6 "sync/atomic"
7 )
8
9 // New creates an AtomicBool with default set to false.
10 func New() *AtomicBool {
11 return new(AtomicBool)
12 }
13
14 // NewBool creates an AtomicBool with given default value.
15 func NewBool(ok bool) *AtomicBool {
16 ab := New()
17 if ok {
18 ab.Set()
19 }
20 return ab
21 }
22
23 // AtomicBool is an atomic Boolean.
24 // Its methods are all atomic, thus safe to be called by multiple goroutines simultaneously.
25 // Note: When embedding into a struct one should always use *AtomicBool to avoid copy.
26 type AtomicBool int32
27
28 // Set sets the Boolean to true.
29 func (ab *AtomicBool) Set() {
30 atomic.StoreInt32((*int32)(ab), 1)
31 }
32
33 // UnSet sets the Boolean to false.
34 func (ab *AtomicBool) UnSet() {
35 atomic.StoreInt32((*int32)(ab), 0)
36 }
37
38 // IsSet returns whether the Boolean is true.
39 func (ab *AtomicBool) IsSet() bool {
40 return atomic.LoadInt32((*int32)(ab)) == 1
41 }
42
43 // IsNotSet returns whether the Boolean is false.
44 func (ab *AtomicBool) IsNotSet() bool {
45 return !ab.IsSet()
46 }
47
48 // SetTo sets the boolean with given Boolean.
49 func (ab *AtomicBool) SetTo(yes bool) {
50 if yes {
51 atomic.StoreInt32((*int32)(ab), 1)
52 } else {
53 atomic.StoreInt32((*int32)(ab), 0)
54 }
55 }
56
57 // SetToIf sets the Boolean to new only if the Boolean matches the old.
58 // Returns whether the set was done.
59 func (ab *AtomicBool) SetToIf(old, new bool) (set bool) {
60 var o, n int32
61 if old {
62 o = 1
63 }
64 if new {
65 n = 1
66 }
67 return atomic.CompareAndSwapInt32((*int32)(ab), o, n)
68 }
69
70 // MarshalJSON behaves the same as if the AtomicBool is a builtin.bool.
71 // NOTE: There's no lock during the process, usually it shouldn't be called with other methods in parallel.
72 func (ab *AtomicBool) MarshalJSON() ([]byte, error) {
73 return json.Marshal(ab.IsSet())
74 }
75
76 // UnmarshalJSON behaves the same as if the AtomicBool is a builtin.bool.
77 // NOTE: There's no lock during the process, usually it shouldn't be called with other methods in parallel.
78 func (ab *AtomicBool) UnmarshalJSON(b []byte) error {
79 var v bool
80 err := json.Unmarshal(b, &v)
81
82 if err == nil {
83 ab.SetTo(v)
84 }
85 return err
86 }
0 package abool
1
2 import (
3 "encoding/json"
4 "sync"
5 "sync/atomic"
6 "testing"
7 )
8
9 func TestDefaultValue(t *testing.T) {
10 t.Parallel()
11 v := New()
12 if v.IsSet() {
13 t.Fatal("Empty value of AtomicBool should be false")
14 }
15
16 v = NewBool(true)
17 if !v.IsSet() {
18 t.Fatal("NewValue(true) should be true")
19 }
20
21 v = NewBool(false)
22 if v.IsSet() {
23 t.Fatal("NewValue(false) should be false")
24 }
25 }
26
27 func TestIsNotSet(t *testing.T) {
28 t.Parallel()
29 v := New()
30
31 if v.IsSet() == v.IsNotSet() {
32 t.Fatal("AtomicBool.IsNotSet() should be the opposite of IsSet()")
33 }
34 }
35
36 func TestSetUnSet(t *testing.T) {
37 t.Parallel()
38 v := New()
39
40 v.Set()
41 if !v.IsSet() {
42 t.Fatal("AtomicBool.Set() failed")
43 }
44
45 v.UnSet()
46 if v.IsSet() {
47 t.Fatal("AtomicBool.UnSet() failed")
48 }
49 }
50
51 func TestSetTo(t *testing.T) {
52 t.Parallel()
53 v := New()
54
55 v.SetTo(true)
56 if !v.IsSet() {
57 t.Fatal("AtomicBool.SetTo(true) failed")
58 }
59
60 v.SetTo(false)
61 if v.IsSet() {
62 t.Fatal("AtomicBool.SetTo(false) failed")
63 }
64
65 if set := v.SetToIf(true, false); set || v.IsSet() {
66 t.Fatal("AtomicBool.SetTo(true, false) failed")
67 }
68
69 if set := v.SetToIf(false, true); !set || !v.IsSet() {
70 t.Fatal("AtomicBool.SetTo(false, true) failed")
71 }
72 }
73
74 func TestRace(t *testing.T) {
75 repeat := 10000
76 var wg sync.WaitGroup
77 wg.Add(repeat * 3)
78 v := New()
79
80 // Writer
81 go func() {
82 for i := 0; i < repeat; i++ {
83 v.Set()
84 wg.Done()
85 }
86 }()
87
88 // Reader
89 go func() {
90 for i := 0; i < repeat; i++ {
91 v.IsSet()
92 wg.Done()
93 }
94 }()
95
96 // Writer
97 go func() {
98 for i := 0; i < repeat; i++ {
99 v.UnSet()
100 wg.Done()
101 }
102 }()
103 wg.Wait()
104 }
105
106 func TestJSONCompatibleWithBuiltinBool(t *testing.T) {
107 for _, value := range []bool{true, false} {
108 // Test bool -> bytes -> AtomicBool
109
110 // act 1. bool -> bytes
111 buf, err := json.Marshal(value)
112 if err != nil {
113 t.Fatalf("json.Marshal(%t) failed: %s", value, err)
114 }
115
116 // act 2. bytes -> AtomicBool
117 //
118 // Try to unmarshall the JSON byte slice
119 // of a normal boolean into an AtomicBool
120 //
121 // Create an AtomicBool with the oppsite default to ensure the unmarshal process did the work
122 ab := NewBool(!value)
123 err = json.Unmarshal(buf, ab)
124 if err != nil {
125 t.Fatalf(`json.Unmarshal("%s", %T) failed: %s`, buf, ab, err)
126 }
127 // assert
128 if ab.IsSet() != value {
129 t.Fatalf("Expected AtomicBool to represent %t but actual value was %t", value, ab.IsSet())
130 }
131
132 // Test AtomicBool -> bytes -> bool
133
134 // act 3. AtomicBool -> bytes
135 buf, err = json.Marshal(ab)
136 if err != nil {
137 t.Fatalf("json.Marshal(%T) failed: %s", ab, err)
138 }
139
140 // using the opposite value for the same reason as the former case
141 b := ab.IsNotSet()
142 // act 4. bytes -> bool
143 err = json.Unmarshal(buf, &b)
144 if err != nil {
145 t.Fatalf(`json.Unmarshal("%s", %T) failed: %s`, buf, &b, err)
146 }
147 // assert
148 if b != ab.IsSet() {
149 t.Fatalf(`json.Unmarshal("%s", %T) didn't work, expected %t, got %t`, buf, ab, ab.IsSet(), b)
150 }
151 }
152 }
153
154 func TestUnmarshalJSONErrorNoWrite(t *testing.T) {
155 for _, val := range []bool{true, false} {
156 ab := NewBool(val)
157 oldVal := ab.IsSet()
158 buf := []byte("invalid-json")
159 err := json.Unmarshal(buf, ab)
160 if err == nil {
161 t.Fatalf(`Error expected from json.Unmarshal("%s", %T)`, buf, ab)
162 }
163 if oldVal != ab.IsSet() {
164 t.Fatal("Failed json.Unmarshal modified the value of AtomicBool which is not expected")
165 }
166 }
167 }
168
169 func ExampleAtomicBool() {
170 cond := New() // default to false
171 any := true
172 old := any
173 new := !any
174
175 cond.Set() // Sets to true
176 cond.IsSet() // Returns true
177 cond.UnSet() // Sets to false
178 cond.IsNotSet() // Returns true
179 cond.SetTo(any) // Sets to whatever you want
180 cond.SetToIf(new, old) // Sets to `new` only if the Boolean matches the `old`, returns whether succeeded
181 }
182
183 // Benchmark Read
184
185 func BenchmarkMutexRead(b *testing.B) {
186 var m sync.RWMutex
187 var v bool
188 b.ResetTimer()
189 for i := 0; i < b.N; i++ {
190 m.RLock()
191 _ = v
192 m.RUnlock()
193 }
194 }
195
196 func BenchmarkAtomicValueRead(b *testing.B) {
197 var v atomic.Value
198 b.ResetTimer()
199 for i := 0; i < b.N; i++ {
200 _ = v.Load() != nil
201 }
202 }
203
204 func BenchmarkAtomicBoolRead(b *testing.B) {
205 v := New()
206 b.ResetTimer()
207 for i := 0; i < b.N; i++ {
208 _ = v.IsSet()
209 }
210 }
211
212 // Benchmark Write
213
214 func BenchmarkMutexWrite(b *testing.B) {
215 var m sync.RWMutex
216 var v bool
217 b.ResetTimer()
218 for i := 0; i < b.N; i++ {
219 m.RLock()
220 v = true
221 m.RUnlock()
222 }
223 b.StopTimer()
224 _ = v
225 }
226
227 func BenchmarkAtomicValueWrite(b *testing.B) {
228 var v atomic.Value
229 b.ResetTimer()
230 for i := 0; i < b.N; i++ {
231 v.Store(true)
232 }
233 }
234
235 func BenchmarkAtomicBoolWrite(b *testing.B) {
236 v := New()
237 b.ResetTimer()
238 for i := 0; i < b.N; i++ {
239 v.Set()
240 }
241 }
242
243 // Benchmark CAS
244
245 func BenchmarkMutexCAS(b *testing.B) {
246 var m sync.RWMutex
247 var v bool
248 b.ResetTimer()
249 for i := 0; i < b.N; i++ {
250 m.Lock()
251 if !v {
252 v = true
253 }
254 m.Unlock()
255 }
256 }
257
258 func BenchmarkAtomicBoolCAS(b *testing.B) {
259 v := New()
260 b.ResetTimer()
261 for i := 0; i < b.N; i++ {
262 v.SetToIf(false, true)
263 }
264 }
0 module github.com/tevino/abool/v2
1
2 go 1.17