| 
1 |  | -// Copyright 2022 The Go Authors. All rights reserved.  | 
2 |  | -// Use of this source code is governed by a BSD-style  | 
3 |  | -// license that can be found in the LICENSE file.  | 
4 |  | - | 
5 |  | -//go:build !go1.19  | 
 | 1 | +//go:build !go1.24  | 
6 | 2 | 
 
  | 
7 | 3 | package atomic  | 
8 | 4 | 
 
  | 
9 |  | -import (  | 
10 |  | -	"sync/atomic"  | 
11 |  | -	"unsafe"  | 
12 |  | -)  | 
13 |  | - | 
14 |  | -// A Bool is an atomic boolean value.  | 
15 |  | -// The zero value is false.  | 
16 |  | -type Bool struct {  | 
17 |  | -	_ noCopy  | 
18 |  | -	v uint32  | 
19 |  | -}  | 
20 |  | - | 
21 |  | -// Load atomically loads and returns the value stored in x.  | 
22 |  | -func (x *Bool) Load() bool { return atomic.LoadUint32(&x.v) != 0 }  | 
23 |  | - | 
24 |  | -// Store atomically stores val into x.  | 
25 |  | -func (x *Bool) Store(val bool) { atomic.StoreUint32(&x.v, b32(val)) }  | 
 | 5 | +import "sync/atomic"  | 
26 | 6 | 
 
  | 
27 |  | -// Swap atomically stores new into x and returns the previous value.  | 
28 |  | -func (x *Bool) Swap(new bool) (old bool) { return atomic.SwapUint32(&x.v, b32(new)) != 0 }  | 
29 |  | - | 
30 |  | -// CompareAndSwap executes the compare-and-swap operation for the boolean value x.  | 
31 |  | -func (x *Bool) CompareAndSwap(old, new bool) (swapped bool) {  | 
32 |  | -	return atomic.CompareAndSwapUint32(&x.v, b32(old), b32(new))  | 
33 |  | -}  | 
34 |  | - | 
35 |  | -// b32 returns a uint32 0 or 1 representing b.  | 
36 |  | -func b32(b bool) uint32 {  | 
37 |  | -	if b {  | 
38 |  | -		return 1  | 
39 |  | -	}  | 
40 |  | -	return 0  | 
41 |  | -}  | 
 | 7 | +type (  | 
 | 8 | +	Bool    = atomic.Bool  | 
 | 9 | +	Int32   = atomic.Int32  | 
 | 10 | +	Int64   = atomic.Int64  | 
 | 11 | +	Uint32  = atomic.Uint32  | 
 | 12 | +	Uint64  = atomic.Uint64  | 
 | 13 | +	Uintptr = atomic.Uintptr  | 
 | 14 | +	Value   = atomic.Value  | 
 | 15 | +)  | 
42 | 16 | 
 
  | 
43 |  | -// A Pointer is an atomic pointer of type *T. The zero value is a nil *T.  | 
44 | 17 | type Pointer[T any] struct {  | 
45 |  | -	// Mention *T in a field to disallow conversion between Pointer types.  | 
46 |  | -	// See go.dev/issue/56603 for more details.  | 
47 |  | -	// Use *T, not T, to avoid spurious recursive type definition errors.  | 
48 |  | -	_ [0]*T  | 
49 |  | - | 
50 |  | -	_ noCopy  | 
51 |  | -	v unsafe.Pointer  | 
52 |  | -}  | 
53 |  | - | 
54 |  | -// Load atomically loads and returns the value stored in x.  | 
55 |  | -func (x *Pointer[T]) Load() *T { return (*T)(atomic.LoadPointer(&x.v)) }  | 
56 |  | - | 
57 |  | -// Store atomically stores val into x.  | 
58 |  | -func (x *Pointer[T]) Store(val *T) { atomic.StorePointer(&x.v, unsafe.Pointer(val)) }  | 
59 |  | - | 
60 |  | -// Swap atomically stores new into x and returns the previous value.  | 
61 |  | -func (x *Pointer[T]) Swap(new *T) (old *T) {  | 
62 |  | -	return (*T)(atomic.SwapPointer(&x.v, unsafe.Pointer(new)))  | 
63 |  | -}  | 
64 |  | - | 
65 |  | -// CompareAndSwap executes the compare-and-swap operation for x.  | 
66 |  | -func (x *Pointer[T]) CompareAndSwap(old, new *T) (swapped bool) {  | 
67 |  | -	return atomic.CompareAndSwapPointer(&x.v, unsafe.Pointer(old), unsafe.Pointer(new))  | 
68 |  | -}  | 
69 |  | - | 
70 |  | -// An Int32 is an atomic int32. The zero value is zero.  | 
71 |  | -type Int32 struct {  | 
72 |  | -	_ noCopy  | 
73 |  | -	v int32  | 
 | 18 | +	*atomic.Pointer[T]  | 
74 | 19 | }  | 
75 | 20 | 
 
  | 
76 |  | -// Load atomically loads and returns the value stored in x.  | 
77 |  | -func (x *Int32) Load() int32 { return atomic.LoadInt32(&x.v) }  | 
78 |  | - | 
79 |  | -// Store atomically stores val into x.  | 
80 |  | -func (x *Int32) Store(val int32) { atomic.StoreInt32(&x.v, val) }  | 
81 |  | - | 
82 |  | -// Swap atomically stores new into x and returns the previous value.  | 
83 |  | -func (x *Int32) Swap(new int32) (old int32) { return atomic.SwapInt32(&x.v, new) }  | 
84 |  | - | 
85 |  | -// CompareAndSwap executes the compare-and-swap operation for x.  | 
86 |  | -func (x *Int32) CompareAndSwap(old, new int32) (swapped bool) {  | 
87 |  | -	return atomic.CompareAndSwapInt32(&x.v, old, new)  | 
 | 21 | +func PointerForm[T any](p *atomic.Pointer[T]) *Pointer[T] {  | 
 | 22 | +	return &Pointer[T]{p}  | 
88 | 23 | }  | 
89 |  | - | 
90 |  | -// Add atomically adds delta to x and returns the new value.  | 
91 |  | -func (x *Int32) Add(delta int32) (new int32) { return atomic.AddInt32(&x.v, delta) }  | 
92 |  | - | 
93 |  | -// An Int64 is an atomic int64. The zero value is zero.  | 
94 |  | -type Int64 struct {  | 
95 |  | -	_ noCopy  | 
96 |  | -	v int64  | 
97 |  | -}  | 
98 |  | - | 
99 |  | -// Load atomically loads and returns the value stored in x.  | 
100 |  | -func (x *Int64) Load() int64 { return atomic.LoadInt64(&x.v) }  | 
101 |  | - | 
102 |  | -// Store atomically stores val into x.  | 
103 |  | -func (x *Int64) Store(val int64) { atomic.StoreInt64(&x.v, val) }  | 
104 |  | - | 
105 |  | -// Swap atomically stores new into x and returns the previous value.  | 
106 |  | -func (x *Int64) Swap(new int64) (old int64) { return atomic.SwapInt64(&x.v, new) }  | 
107 |  | - | 
108 |  | -// CompareAndSwap executes the compare-and-swap operation for x.  | 
109 |  | -func (x *Int64) CompareAndSwap(old, new int64) (swapped bool) {  | 
110 |  | -	return atomic.CompareAndSwapInt64(&x.v, old, new)  | 
111 |  | -}  | 
112 |  | - | 
113 |  | -// Add atomically adds delta to x and returns the new value.  | 
114 |  | -func (x *Int64) Add(delta int64) (new int64) { return atomic.AddInt64(&x.v, delta) }  | 
115 |  | - | 
116 |  | -// An Uint32 is an atomic uint32. The zero value is zero.  | 
117 |  | -type Uint32 struct {  | 
118 |  | -	_ noCopy  | 
119 |  | -	v uint32  | 
120 |  | -}  | 
121 |  | - | 
122 |  | -// Load atomically loads and returns the value stored in x.  | 
123 |  | -func (x *Uint32) Load() uint32 { return atomic.LoadUint32(&x.v) }  | 
124 |  | - | 
125 |  | -// Store atomically stores val into x.  | 
126 |  | -func (x *Uint32) Store(val uint32) { atomic.StoreUint32(&x.v, val) }  | 
127 |  | - | 
128 |  | -// Swap atomically stores new into x and returns the previous value.  | 
129 |  | -func (x *Uint32) Swap(new uint32) (old uint32) { return atomic.SwapUint32(&x.v, new) }  | 
130 |  | - | 
131 |  | -// CompareAndSwap executes the compare-and-swap operation for x.  | 
132 |  | -func (x *Uint32) CompareAndSwap(old, new uint32) (swapped bool) {  | 
133 |  | -	return atomic.CompareAndSwapUint32(&x.v, old, new)  | 
134 |  | -}  | 
135 |  | - | 
136 |  | -// Add atomically adds delta to x and returns the new value.  | 
137 |  | -func (x *Uint32) Add(delta uint32) (new uint32) { return atomic.AddUint32(&x.v, delta) }  | 
138 |  | - | 
139 |  | -// An Uint64 is an atomic uint64. The zero value is zero.  | 
140 |  | -type Uint64 struct {  | 
141 |  | -	_ noCopy  | 
142 |  | -	v uint64  | 
143 |  | -}  | 
144 |  | - | 
145 |  | -// Load atomically loads and returns the value stored in x.  | 
146 |  | -func (x *Uint64) Load() uint64 { return atomic.LoadUint64(&x.v) }  | 
147 |  | - | 
148 |  | -// Store atomically stores val into x.  | 
149 |  | -func (x *Uint64) Store(val uint64) { atomic.StoreUint64(&x.v, val) }  | 
150 |  | - | 
151 |  | -// Swap atomically stores new into x and returns the previous value.  | 
152 |  | -func (x *Uint64) Swap(new uint64) (old uint64) { return atomic.SwapUint64(&x.v, new) }  | 
153 |  | - | 
154 |  | -// CompareAndSwap executes the compare-and-swap operation for x.  | 
155 |  | -func (x *Uint64) CompareAndSwap(old, new uint64) (swapped bool) {  | 
156 |  | -	return atomic.CompareAndSwapUint64(&x.v, old, new)  | 
157 |  | -}  | 
158 |  | - | 
159 |  | -// Add atomically adds delta to x and returns the new value.  | 
160 |  | -func (x *Uint64) Add(delta uint64) (new uint64) { return atomic.AddUint64(&x.v, delta) }  | 
161 |  | - | 
162 |  | -// An Uintptr is an atomic uintptr. The zero value is zero.  | 
163 |  | -type Uintptr struct {  | 
164 |  | -	_ noCopy  | 
165 |  | -	v uintptr  | 
166 |  | -}  | 
167 |  | - | 
168 |  | -// Load atomically loads and returns the value stored in x.  | 
169 |  | -func (x *Uintptr) Load() uintptr { return atomic.LoadUintptr(&x.v) }  | 
170 |  | - | 
171 |  | -// Store atomically stores val into x.  | 
172 |  | -func (x *Uintptr) Store(val uintptr) { atomic.StoreUintptr(&x.v, val) }  | 
173 |  | - | 
174 |  | -// Swap atomically stores new into x and returns the previous value.  | 
175 |  | -func (x *Uintptr) Swap(new uintptr) (old uintptr) { return atomic.SwapUintptr(&x.v, new) }  | 
176 |  | - | 
177 |  | -// CompareAndSwap executes the compare-and-swap operation for x.  | 
178 |  | -func (x *Uintptr) CompareAndSwap(old, new uintptr) (swapped bool) {  | 
179 |  | -	return atomic.CompareAndSwapUintptr(&x.v, old, new)  | 
180 |  | -}  | 
181 |  | - | 
182 |  | -// Add atomically adds delta to x and returns the new value.  | 
183 |  | -func (x *Uintptr) Add(delta uintptr) (new uintptr) { return atomic.AddUintptr(&x.v, delta) }  | 
184 |  | - | 
185 |  | -// noCopy may be added to structs which must not be copied  | 
186 |  | -// after the first use.  | 
187 |  | -//  | 
188 |  | -// See https://golang.org/issues/8005#issuecomment-190753527  | 
189 |  | -// for details.  | 
190 |  | -//  | 
191 |  | -// Note that it must not be embedded, due to the Lock and Unlock methods.  | 
192 |  | -type noCopy struct{}  | 
193 |  | - | 
194 |  | -// Lock is a no-op used by -copylocks checker from `go vet`.  | 
195 |  | -func (*noCopy) Lock()   {}  | 
196 |  | -func (*noCopy) Unlock() {}  | 
197 |  | - | 
198 |  | -type Value = atomic.Value  | 
0 commit comments