/
atomic.go
80 lines (66 loc) · 1.35 KB
/
atomic.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
package gensync
import (
"sync"
"github.com/Invicton-Labs/go-common/constraints"
)
type Atomic[T any] struct {
l sync.Mutex
v T
}
func NewAtomic[T any](val T) Atomic[T] {
return Atomic[T]{
v: val,
}
}
func (a *Atomic[T]) Load() T {
a.l.Lock()
defer a.l.Unlock()
return a.v
}
func (a *Atomic[T]) Store(val T) {
a.l.Lock()
defer a.l.Unlock()
a.v = val
}
func (a *Atomic[T]) StoreIf(val T, condition func(old T, new T) bool) (stored bool) {
a.l.Lock()
defer a.l.Unlock()
if condition(a.v, val) {
a.v = val
return true
}
return false
}
type AtomicComparable[T comparable] Atomic[T]
func NewAtomicComparable[T comparable](val T) AtomicComparable[T] {
return AtomicComparable[T]{
v: val,
}
}
func (a *AtomicComparable[T]) CompareAndSwap(old T, new T) (swapped bool) {
a.l.Lock()
defer a.l.Unlock()
if a.v == old {
a.v = new
return true
}
return false
}
type AtomicNumeric[T constraints.Numeric] AtomicComparable[T]
func NewAtomicNumeric[T constraints.Numeric](val T) AtomicNumeric[T] {
return AtomicNumeric[T]{
v: val,
}
}
func (a *AtomicNumeric[T]) Add(delta T) (new T) {
a.l.Lock()
defer a.l.Unlock()
a.v += delta
return a.v
}
func (a *AtomicNumeric[T]) Subtract(delta T) (new T) {
a.l.Lock()
defer a.l.Unlock()
a.v = a.v - delta
return a.v
}