12
12
13
13
import SwiftShims
14
14
15
+ /// A common base class for classes that need to be non-\ `@objc`,
16
+ /// recognizably in the type system.
17
+ ///
18
+ /// See `isUniquelyReferenced`
19
+ public class NonObjectiveCBase { }
20
+
15
21
/// A base class of `ManagedBuffer<Value,Element>`, used during
16
22
/// instance creation.
17
23
///
@@ -22,7 +28,7 @@ import SwiftShims
22
28
/// `ManagedProtoBuffer` does not offer
23
29
/// access to the as-yet uninitialized `value` property of
24
30
/// `ManagedBuffer`,
25
- public class ManagedProtoBuffer < Value, Element> {
31
+ public class ManagedProtoBuffer < Value, Element> : NonObjectiveCBase {
26
32
/// The actual number of elements that can be stored in this object.
27
33
///
28
34
/// This value may be nontrivial to compute; it is usually a good
@@ -172,3 +178,73 @@ public class ManagedBuffer<Value, Element>
172
178
}
173
179
}
174
180
}
181
+
182
+ // FIXME: when our calling convention changes to pass self at +0,
183
+ // inout should be dropped from the arguments to these functions.
184
+
185
+ /// Returns `true` iff `object` is a non-\ `@objc` class with a single
186
+ /// strong reference.
187
+ ///
188
+ /// * Does *not* modify `object`; the use of `inout` is an
189
+ /// implementation artifact.
190
+ /// * If `object` is an Objective-C class instance, returns `false`.
191
+ /// * Weak references do not affect the result of this function.
192
+ ///
193
+ /// Useful for implementing the copy-on-write optimization for the
194
+ /// deep storage of value types::
195
+ ///
196
+ /// mutating func modifyMe(arg: X) {
197
+ /// if isUniquelyReferencedNonObjC(&myStorage) {
198
+ /// myStorage.modifyInPlace(arg)
199
+ /// }
200
+ /// else {
201
+ /// myStorage = self.createModified(myStorage, arg)
202
+ /// }
203
+ /// }
204
+ ///
205
+ /// This function is safe to use for `mutating` functions in
206
+ /// multithreaded code because a false positive would imply that there
207
+ /// is already a user-level data race on the value being mutated.
208
+ public func isUniquelyReferencedNonObjC< T: AnyObject > ( inout object: T ) -> Bool {
209
+
210
+ // Note: the pointer must be extracted in a separate step or an
211
+ // extra reference will be held during the check below
212
+ let o = UnsafePointer < Void > ( Builtin . bridgeToRawPointer ( object) )
213
+ let result = _swift_isUniquelyReferencedNonObjC_nonNull ( o)
214
+ Builtin . fixLifetime ( object)
215
+ return result != 0
216
+ }
217
+
218
+ /// Returns `true` iff `object` is a non-\ `@objc` class with a single
219
+ /// strong reference.
220
+ ///
221
+ /// * Does *not* modify `object`; the use of `inout` is an
222
+ /// implementation artifact.
223
+ /// * Weak references do not affect the result of this function.
224
+ ///
225
+ /// Useful for implementing the copy-on-write optimization for the
226
+ /// deep storage of value types::
227
+ ///
228
+ /// mutating func modifyMe(arg: X) {
229
+ /// if isUniquelyReferenced(&myStorage) {
230
+ /// myStorage.modifyInPlace(arg)
231
+ /// }
232
+ /// else {
233
+ /// myStorage = myStorage.createModified(arg)
234
+ /// }
235
+ /// }
236
+ ///
237
+ /// This function is safe to use for `mutating` functions in
238
+ /// multithreaded code because a false positive would imply that there
239
+ /// is already a user-level data race on the value being mutated.
240
+ public func isUniquelyReferenced< T: NonObjectiveCBase > (
241
+ inout object: T
242
+ ) -> Bool {
243
+ // Note: the pointer must be extracted in a separate step or an
244
+ // extra reference will be held during the check below
245
+ let o = UnsafePointer < HeapObject > ( Builtin . bridgeToRawPointer ( object) )
246
+ let result = _swift_isUniquelyReferenced_nonNull_native ( o)
247
+ Builtin . fixLifetime ( object)
248
+ return result != 0
249
+ }
250
+
0 commit comments