Skip to content

Commit c39a7ef

Browse files
committed
De-gyb HighLevelTypes.swift and AtomicLazyReference.swift
1 parent 1f6a86f commit c39a7ef

10 files changed

+994
-1479
lines changed

Sources/Atomics/AtomicBool.swift.gyb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ extension ${construct} where Value == Bool {
232232
ordering: ordering)
233233
return original ${op} operand
234234
}
235+
235236
% end
236237
}
237238
% end
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift Atomics open source project
4+
//
5+
// Copyright (c) 2020 - 2023 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
%{
13+
from gyb_utils import (
14+
autogenerated_warning, integerOperations, lowerFirst, argLabel)
15+
}%
16+
${autogenerated_warning()}
17+
18+
% for construct in ["UnsafeAtomic", "ManagedAtomic"]:
19+
extension ${construct} where Value: AtomicInteger {
20+
% for (name, _, op, label, doc) in integerOperations:
21+
/// Perform an atomic ${doc} operation and return the original value, applying
22+
/// the specified memory ordering.
23+
///
24+
% if "Wrapping" in name:
25+
/// Note: This operation silently wraps around on overflow, like the
26+
/// `${op}` operator does on `Int` values.
27+
///
28+
% end
29+
/// - Parameter operand: An integer value.
30+
/// - Parameter ordering: The memory ordering to apply on this operation.
31+
/// - Returns: The original value before the operation.
32+
@_semantics("atomics.requires_constant_orderings")
33+
@_transparent @_alwaysEmitIntoClient
34+
public func loadThen${name}(
35+
${label} operand: Value${" = 1" if "crement" in name else ""},
36+
ordering: AtomicUpdateOrdering
37+
) -> Value {
38+
_Storage.atomicLoadThen${name}(
39+
${argLabel(label)}operand,
40+
at: _ptr,
41+
ordering: ordering)
42+
}
43+
44+
% end
45+
% for (name, _, op, label, doc) in integerOperations:
46+
/// Perform an atomic ${doc} operation and return the new value, applying
47+
/// the specified memory ordering.
48+
///
49+
% if "Wrapping" in name:
50+
/// Note: This operation silently wraps around on overflow, like the
51+
/// `${op}` operator does on `Int` values.
52+
///
53+
% end
54+
/// - Parameter operand: An integer value.
55+
/// - Parameter ordering: The memory ordering to apply on this operation.
56+
/// - Returns: The new value after the operation.
57+
@_semantics("atomics.requires_constant_orderings")
58+
@_transparent @_alwaysEmitIntoClient
59+
public func ${lowerFirst(name)}ThenLoad(
60+
${label} operand: Value${" = 1" if "crement" in name else ""},
61+
ordering: AtomicUpdateOrdering
62+
) -> Value {
63+
let original = _Storage.atomicLoadThen${name}(
64+
${argLabel(label)}operand,
65+
at: _ptr,
66+
ordering: ordering)
67+
return original ${op} operand
68+
}
69+
70+
% end
71+
72+
/// Perform an atomic wrapping increment operation applying the
73+
/// specified memory ordering.
74+
///
75+
/// Note: This operation silently wraps around on overflow, like the
76+
/// `&+=` operator does on `Int` values.
77+
///
78+
/// - Parameter operand: The value to add to the current value.
79+
/// - Parameter ordering: The memory ordering to apply on this operation.
80+
@_semantics("atomics.requires_constant_orderings")
81+
@_transparent @_alwaysEmitIntoClient
82+
public func wrappingIncrement(
83+
by operand: Value = 1,
84+
ordering: AtomicUpdateOrdering
85+
) {
86+
_ = _Storage.atomicLoadThenWrappingIncrement(
87+
by: operand,
88+
at: _ptr,
89+
ordering: ordering)
90+
}
91+
92+
/// Perform an atomic wrapping decrement operation applying the
93+
/// specified memory ordering.
94+
///
95+
/// Note: This operation silently wraps around on overflow, like the
96+
/// `&-=` operator does on `Int` values.
97+
///
98+
/// - Parameter operand: The value to subtract from the current value.
99+
/// - Parameter ordering: The memory ordering to apply on this operation.
100+
@_semantics("atomics.requires_constant_orderings")
101+
@_transparent @_alwaysEmitIntoClient
102+
public func wrappingDecrement(
103+
by operand: Value = 1,
104+
ordering: AtomicUpdateOrdering
105+
) {
106+
_ = _Storage.atomicLoadThenWrappingDecrement(
107+
by: operand,
108+
at: _ptr,
109+
ordering: ordering)
110+
}
111+
}
Lines changed: 266 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,266 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift Atomics open source project
4+
//
5+
// Copyright (c) 2020 - 2023 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
/// A reference type holding an atomic value, with automatic memory management.
14+
@_fixed_layout
15+
public class ManagedAtomic<Value: AtomicValue>
16+
where Value.AtomicRepresentation.Value == Value {
17+
// Note: the Value.AtomicRepresentation.Value == Value requirement could be relaxed,
18+
// at the cost of adding a bunch of potentially ambiguous overloads.
19+
// (We'd need one set of implementations for the type equality condition,
20+
// and another for `Value: AtomicReference`.)
21+
22+
@usableFromInline
23+
internal typealias _Storage = Value.AtomicRepresentation
24+
25+
/// The atomic representation of the value stored inside.
26+
///
27+
/// Warning: This ivar must only ever be accessed via `_ptr` after
28+
/// its initialization.
29+
@usableFromInline
30+
internal var __storage: _Storage
31+
32+
/// Initialize a new managed atomic instance holding the specified initial
33+
/// value.
34+
@inline(__always) @_alwaysEmitIntoClient
35+
public init(_ value: Value) {
36+
__storage = _Storage(value)
37+
}
38+
39+
deinit {
40+
_ = _ptr.pointee.dispose()
41+
}
42+
43+
@_alwaysEmitIntoClient @inline(__always)
44+
internal var _ptr: UnsafeMutablePointer<_Storage> {
45+
_getUnsafePointerToStoredProperties(self)
46+
.assumingMemoryBound(to: _Storage.self)
47+
}
48+
}
49+
50+
extension ManagedAtomic: @unchecked Sendable where Value: Sendable {}
51+
52+
extension ManagedAtomic {
53+
/// Atomically loads and returns the current value, applying the specified
54+
/// memory ordering.
55+
///
56+
/// - Parameter ordering: The memory ordering to apply on this operation.
57+
/// - Returns: The current value.
58+
@_semantics("atomics.requires_constant_orderings")
59+
@_transparent @_alwaysEmitIntoClient
60+
public func load(
61+
ordering: AtomicLoadOrdering
62+
) -> Value {
63+
_Storage.atomicLoad(at: _ptr, ordering: ordering)
64+
}
65+
66+
/// Atomically sets the current value to `desired`, applying the specified
67+
/// memory ordering.
68+
///
69+
/// - Parameter desired: The desired new value.
70+
/// - Parameter ordering: The memory ordering to apply on this operation.
71+
@_semantics("atomics.requires_constant_orderings")
72+
@_transparent @_alwaysEmitIntoClient
73+
public func store(
74+
_ desired: __owned Value,
75+
ordering: AtomicStoreOrdering
76+
) {
77+
_Storage.atomicStore(desired, at: _ptr, ordering: ordering)
78+
}
79+
80+
/// Atomically sets the current value to `desired` and returns the original
81+
/// value, applying the specified memory ordering.
82+
///
83+
/// - Parameter desired: The desired new value.
84+
/// - Parameter ordering: The memory ordering to apply on this operation.
85+
/// - Returns: The original value.
86+
@_semantics("atomics.requires_constant_orderings")
87+
@_transparent @_alwaysEmitIntoClient
88+
public func exchange(
89+
_ desired: __owned Value,
90+
ordering: AtomicUpdateOrdering
91+
) -> Value {
92+
_Storage.atomicExchange(desired, at: _ptr, ordering: ordering)
93+
}
94+
95+
/// Perform an atomic compare and exchange operation on the current value,
96+
/// applying the specified memory ordering.
97+
///
98+
/// This operation performs the following algorithm as a single atomic
99+
/// transaction:
100+
///
101+
/// ```
102+
/// atomic(self) { currentValue in
103+
/// let original = currentValue
104+
/// guard original == expected else { return (false, original) }
105+
/// currentValue = desired
106+
/// return (true, original)
107+
/// }
108+
/// ```
109+
///
110+
/// This method implements a "strong" compare and exchange operation
111+
/// that does not permit spurious failures.
112+
///
113+
/// - Parameter expected: The expected current value.
114+
/// - Parameter desired: The desired new value.
115+
/// - Parameter ordering: The memory ordering to apply on this operation.
116+
/// - Returns: A tuple `(exchanged, original)`, where `exchanged` is true if
117+
/// the exchange was successful, and `original` is the original value.
118+
@_semantics("atomics.requires_constant_orderings")
119+
@_transparent @_alwaysEmitIntoClient
120+
public func compareExchange(
121+
expected: Value,
122+
desired: __owned Value,
123+
ordering: AtomicUpdateOrdering
124+
) -> (exchanged: Bool, original: Value) {
125+
_Storage.atomicCompareExchange(
126+
expected: expected,
127+
desired: desired,
128+
at: _ptr,
129+
ordering: ordering)
130+
}
131+
132+
/// Perform an atomic compare and exchange operation on the current value,
133+
/// applying the specified success/failure memory orderings.
134+
///
135+
/// This operation performs the following algorithm as a single atomic
136+
/// transaction:
137+
///
138+
/// ```
139+
/// atomic(self) { currentValue in
140+
/// let original = currentValue
141+
/// guard original == expected else { return (false, original) }
142+
/// currentValue = desired
143+
/// return (true, original)
144+
/// }
145+
/// ```
146+
///
147+
/// The `successOrdering` argument specifies the memory ordering to use when
148+
/// the operation manages to update the current value, while `failureOrdering`
149+
/// will be used when the operation leaves the value intact.
150+
///
151+
/// This method implements a "strong" compare and exchange operation
152+
/// that does not permit spurious failures.
153+
///
154+
/// - Parameter expected: The expected current value.
155+
/// - Parameter desired: The desired new value.
156+
/// - Parameter successOrdering: The memory ordering to apply if this
157+
/// operation performs the exchange.
158+
/// - Parameter failureOrdering: The memory ordering to apply on this
159+
/// operation does not perform the exchange.
160+
/// - Returns: A tuple `(exchanged, original)`, where `exchanged` is true if
161+
/// the exchange was successful, and `original` is the original value.
162+
@_semantics("atomics.requires_constant_orderings")
163+
@_transparent @_alwaysEmitIntoClient
164+
public func compareExchange(
165+
expected: Value,
166+
desired: __owned Value,
167+
successOrdering: AtomicUpdateOrdering,
168+
failureOrdering: AtomicLoadOrdering
169+
) -> (exchanged: Bool, original: Value) {
170+
_Storage.atomicCompareExchange(
171+
expected: expected,
172+
desired: desired,
173+
at: _ptr,
174+
successOrdering: successOrdering,
175+
failureOrdering: failureOrdering)
176+
}
177+
178+
/// Perform an atomic weak compare and exchange operation on the current
179+
/// value, applying the memory ordering. This compare-exchange variant is
180+
/// allowed to spuriously fail; it is designed to be called in a loop until
181+
/// it indicates a successful exchange has happened.
182+
///
183+
/// This operation performs the following algorithm as a single atomic
184+
/// transaction:
185+
///
186+
/// ```
187+
/// atomic(self) { currentValue in
188+
/// let original = currentValue
189+
/// guard original == expected else { return (false, original) }
190+
/// currentValue = desired
191+
/// return (true, original)
192+
/// }
193+
/// ```
194+
///
195+
/// (In this weak form, transient conditions may cause the `original ==
196+
/// expected` check to sometimes return false when the two values are in fact
197+
/// the same.)
198+
///
199+
/// - Parameter expected: The expected current value.
200+
/// - Parameter desired: The desired new value.
201+
/// - Parameter ordering: The memory ordering to apply on this operation.
202+
/// - Returns: A tuple `(exchanged, original)`, where `exchanged` is true if
203+
/// the exchange was successful, and `original` is the original value.
204+
@_semantics("atomics.requires_constant_orderings")
205+
@_transparent @_alwaysEmitIntoClient
206+
public func weakCompareExchange(
207+
expected: Value,
208+
desired: __owned Value,
209+
ordering: AtomicUpdateOrdering
210+
) -> (exchanged: Bool, original: Value) {
211+
_Storage.atomicWeakCompareExchange(
212+
expected: expected,
213+
desired: desired,
214+
at: _ptr,
215+
ordering: ordering)
216+
}
217+
218+
/// Perform an atomic weak compare and exchange operation on the current
219+
/// value, applying the specified success/failure memory orderings. This
220+
/// compare-exchange variant is allowed to spuriously fail; it is designed to
221+
/// be called in a loop until it indicates a successful exchange has happened.
222+
///
223+
/// This operation performs the following algorithm as a single atomic
224+
/// transaction:
225+
///
226+
/// ```
227+
/// atomic(self) { currentValue in
228+
/// let original = currentValue
229+
/// guard original == expected else { return (false, original) }
230+
/// currentValue = desired
231+
/// return (true, original)
232+
/// }
233+
/// ```
234+
///
235+
/// (In this weak form, transient conditions may cause the `original ==
236+
/// expected` check to sometimes return false when the two values are in fact
237+
/// the same.)
238+
///
239+
/// The `ordering` argument specifies the memory ordering to use when the
240+
/// operation manages to update the current value, while `failureOrdering`
241+
/// will be used when the operation leaves the value intact.
242+
///
243+
/// - Parameter expected: The expected current value.
244+
/// - Parameter desired: The desired new value.
245+
/// - Parameter successOrdering: The memory ordering to apply if this
246+
/// operation performs the exchange.
247+
/// - Parameter failureOrdering: The memory ordering to apply on this
248+
/// operation does not perform the exchange.
249+
/// - Returns: A tuple `(exchanged, original)`, where `exchanged` is true if
250+
/// the exchange was successful, and `original` is the original value.
251+
@_semantics("atomics.requires_constant_orderings")
252+
@_transparent @_alwaysEmitIntoClient
253+
public func weakCompareExchange(
254+
expected: Value,
255+
desired: __owned Value,
256+
successOrdering: AtomicUpdateOrdering,
257+
failureOrdering: AtomicLoadOrdering
258+
) -> (exchanged: Bool, original: Value) {
259+
_Storage.atomicWeakCompareExchange(
260+
expected: expected,
261+
desired: desired,
262+
at: _ptr,
263+
successOrdering: successOrdering,
264+
failureOrdering: failureOrdering)
265+
}
266+
}

0 commit comments

Comments
 (0)