Skip to content

Commit

Permalink
Merge pull request #3638 from aschwaighofer/remove_nonobjectivecbase_2
Browse files Browse the repository at this point in the history
Remove `isUniquelyReferenced` and the `NonObjectiveCBase` class
  • Loading branch information
aschwaighofer committed Jul 26, 2016
2 parents 67aac58 + 39389b9 commit 4ea93f6
Show file tree
Hide file tree
Showing 12 changed files with 75 additions and 105 deletions.
4 changes: 2 additions & 2 deletions stdlib/public/SDK/Foundation/Boxing.swift
Expand Up @@ -54,7 +54,7 @@ extension _MutableBoxing {
@inline(__always)
mutating func _applyMutation<ReturnType>(_ whatToDo : @noescape(ReferenceType) -> ReturnType) -> ReturnType {
// Only create a new box if we are not uniquely referenced
if !isUniquelyReferencedNonObjC(&_handle) {
if !isKnownUniquelyReferenced(&_handle) {
let ref = _handle._pointer
_handle = _MutableHandle(reference: ref)
}
Expand Down Expand Up @@ -187,7 +187,7 @@ extension _MutablePairBoxing {
case .Immutable(_):
break
case .Mutable(_):
unique = isUniquelyReferencedNonObjC(&_wrapped)
unique = isKnownUniquelyReferenced(&_wrapped)
}

switch (wrapper) {
Expand Down
2 changes: 1 addition & 1 deletion stdlib/public/SDK/Foundation/IndexSet.swift
Expand Up @@ -734,7 +734,7 @@ public struct IndexSet : ReferenceConvertible, Equatable, BidirectionalCollectio
case .Default(_):
break
case .Mutable(_):
unique = isUniquelyReferencedNonObjC(&_handle)
unique = isKnownUniquelyReferenced(&_handle)
}

switch _handle._pointer {
Expand Down
2 changes: 1 addition & 1 deletion stdlib/public/SDK/Foundation/URLRequest.swift
Expand Up @@ -26,7 +26,7 @@ public struct URLRequest : ReferenceConvertible, Equatable, Hashable {
internal var _handle: _MutableHandle<NSMutableURLRequest>

internal mutating func _applyMutation<ReturnType>(_ whatToDo : @noescape (NSMutableURLRequest) -> ReturnType) -> ReturnType {
if !isUniquelyReferencedNonObjC(&_handle) {
if !isKnownUniquelyReferenced(&_handle) {
let ref = _handle._uncopiedReference()
_handle = _MutableHandle(reference: ref)
}
Expand Down
4 changes: 2 additions & 2 deletions stdlib/public/core/ContiguousArrayBuffer.swift
Expand Up @@ -411,14 +411,14 @@ struct _ContiguousArrayBuffer<Element> : _ArrayBufferProtocol {
/// may need to be considered, such as whether the buffer could be
/// some immutable Cocoa container.
public mutating func isUniquelyReferenced() -> Bool {
return __bufferPointer.holdsUniqueReference()
return __bufferPointer.isUniqueReference()
}

/// Returns `true` iff this buffer's storage is either
/// uniquely-referenced or pinned. NOTE: this does not mean
/// the buffer is mutable; see the comment on isUniquelyReferenced.
public mutating func isUniquelyReferencedOrPinned() -> Bool {
return __bufferPointer.holdsUniqueOrPinnedReference()
return __bufferPointer._isUniqueOrPinnedReference()
}

#if _runtime(_ObjC)
Expand Down
4 changes: 2 additions & 2 deletions stdlib/public/core/HeapBuffer.swift
Expand Up @@ -40,8 +40,8 @@ internal func _swift_bufferAllocate(
/// either in a derived class, or it can be in some manager object
/// that owns the _HeapBuffer.
public // @testable (test/Prototypes/MutableIndexableDict.swift)
class _HeapBufferStorage<Value, Element> : NonObjectiveCBase {
public override init() {}
class _HeapBufferStorage<Value, Element> {
public init() {}

/// The type used to actually manage instances of
/// `_HeapBufferStorage<Value, Element>`.
Expand Down
105 changes: 49 additions & 56 deletions stdlib/public/core/ManagedBuffer.swift
Expand Up @@ -12,14 +12,6 @@

import SwiftShims

/// A common base class for classes that need to be non-`@objc`,
/// recognizably in the type system.
///
/// - SeeAlso: `isUniquelyReferenced`
public class NonObjectiveCBase {
public init() {}
}

/// A base class of `ManagedBuffer<Header, Element>`, used during
/// instance creation.
///
Expand All @@ -28,7 +20,7 @@ public class NonObjectiveCBase {
/// `header` property is as-yet uninitialized, and therefore
/// `ManagedProtoBuffer` does not offer access to the as-yet
/// uninitialized `header` property of `ManagedBuffer`.
public class ManagedProtoBuffer<Header, Element> : NonObjectiveCBase {
public class ManagedProtoBuffer<Header, Element> {
/// The actual number of elements that can be stored in this object.
///
/// This header may be nontrivial to compute; it is usually a good
Expand Down Expand Up @@ -299,18 +291,10 @@ public struct ManagedBufferPointer<Header, Element> : Equatable {
/// Returns `true` iff `self` holds the only strong reference to its buffer.
///
/// See `isUniquelyReferenced` for details.
public mutating func holdsUniqueReference() -> Bool {
public mutating func isUniqueReference() -> Bool {
return _isUnique(&_nativeBuffer)
}

/// Returns `true` iff either `self` holds the only strong reference
/// to its buffer or the pinned has been 'pinned'.
///
/// See `isUniquelyReferenced` for details.
public mutating func holdsUniqueOrPinnedReference() -> Bool {
return _isUniqueOrPinned(&_nativeBuffer)
}

//===--- internal/private API -------------------------------------------===//

/// Create with new storage containing space for an initial `Header`
Expand Down Expand Up @@ -453,6 +437,10 @@ public struct ManagedBufferPointer<Header, Element> : Equatable {
toAlignment: alignof(Element.self))
}

internal mutating func _isUniqueOrPinnedReference() -> Bool {
return _isUniqueOrPinned(&_nativeBuffer)
}

internal var _nativeBuffer: Builtin.NativeObject
}

Expand All @@ -466,19 +454,18 @@ public func == <Header, Element>(
// FIXME: when our calling convention changes to pass self at +0,
// inout should be dropped from the arguments to these functions.

/// Returns `true` iff `object` is a non-`@objc` class instance with
/// a single strong reference.
/// Returns `true` iff `object` is known to be a class instance with a single
/// strong reference.
///
/// * Does *not* modify `object`; the use of `inout` is an
/// implementation artifact.
/// * If `object` is an Objective-C class instance, returns `false`.
/// * Weak references do not affect the result of this function.
///
/// Useful for implementing the copy-on-write optimization for the
/// deep storage of value types:
///
/// mutating func modifyMe(_ arg: X) {
/// if isUniquelyReferencedNonObjC(&myStorage) {
/// if isKnownUniquelyReferenced(&myStorage) {
/// myStorage.modifyInPlace(arg)
/// }
/// else {
Expand All @@ -489,16 +476,16 @@ public func == <Header, Element>(
/// This function is safe to use for `mutating` functions in
/// multithreaded code because a false positive would imply that there
/// is already a user-level data race on the value being mutated.
public func isUniquelyReferencedNonObjC<T : AnyObject>(_ object: inout T) -> Bool
public func isKnownUniquelyReferenced<T : AnyObject>(_ object: inout T) -> Bool
{
return _isUnique(&object)
}

internal func isUniquelyReferencedOrPinnedNonObjC<T : AnyObject>(_ object: inout T) -> Bool {
internal func _isKnownUniquelyReferencedOrPinned<T : AnyObject>(_ object: inout T) -> Bool {
return _isUniqueOrPinned(&object)
}

/// Returns `true` iff `object` is a non-`@objc` class instance with a single
/// Returns `true` iff `object` is known to be a class instance with a single
/// strong reference.
///
/// * Does *not* modify `object`; the use of `inout` is an
Expand All @@ -509,36 +496,7 @@ internal func isUniquelyReferencedOrPinnedNonObjC<T : AnyObject>(_ object: inout
/// deep storage of value types:
///
/// mutating func modifyMe(_ arg: X) {
/// if isUniquelyReferenced(&myStorage) {
/// myStorage.modifyInPlace(arg)
/// }
/// else {
/// myStorage = myStorage.createModified(arg)
/// }
/// }
///
/// This function is safe to use for `mutating` functions in
/// multithreaded code because a false positive would imply that there
/// is already a user-level data race on the value being mutated.
public func isUniquelyReferenced<T : NonObjectiveCBase>(
_ object: inout T
) -> Bool {
return _isUnique(&object)
}

/// Returns `true` iff `object` is a non-`@objc` class instance with
/// a single strong reference.
///
/// * Does *not* modify `object`; the use of `inout` is an
/// implementation artifact.
/// * If `object` is an Objective-C class instance, returns `false`.
/// * Weak references do not affect the result of this function.
///
/// Useful for implementing the copy-on-write optimization for the
/// deep storage of value types:
///
/// mutating func modifyMe(_ arg: X) {
/// if isUniquelyReferencedNonObjC(&myStorage) {
/// if isKnownUniquelyReferenced(&myStorage) {
/// myStorage.modifyInPlace(arg)
/// }
/// else {
Expand All @@ -549,7 +507,7 @@ public func isUniquelyReferenced<T : NonObjectiveCBase>(
/// This function is safe to use for `mutating` functions in
/// multithreaded code because a false positive would imply that there
/// is already a user-level data race on the value being mutated.
public func isUniquelyReferencedNonObjC<T : AnyObject>(
public func isKnownUniquelyReferenced<T : AnyObject>(
_ object: inout T?
) -> Bool {
return _isUnique(&object)
Expand All @@ -560,4 +518,39 @@ extension ManagedBufferPointer {
public var allocatedElementCount: Int {
Builtin.unreachable()
}

@available(*, unavailable, renamed: "isUniqueReference")
public mutating func holdsUniqueReference() -> Bool {
Builtin.unreachable()
}

@available(*, unavailable, message: "this API is no longer available")
public mutating func holdsUniqueOrPinnedReference() -> Bool {
Builtin.unreachable()
}
}

@available(*, unavailable, renamed: "isKnownUniquelyReferenced")
public func isUniquelyReferenced<T>(
_ object: inout T
) -> Bool {
Builtin.unreachable()
}

@available(*, unavailable, message: "use isKnownUniquelyReferenced instead")
public class NonObjectiveCBase {}


@available(*, unavailable, renamed: "isKnownUniquelyReferenced")
public func isUniquelyReferencedNonObjC<T : AnyObject>(
_ object: inout T
) -> Bool {
Builtin.unreachable()
}

@available(*, unavailable, renamed: "isKnownUniquelyReferenced")
public func isUniquelyReferencedNonObjC<T : AnyObject>(
_ object: inout T?
) -> Bool {
Builtin.unreachable()
}
4 changes: 2 additions & 2 deletions stdlib/public/core/SliceBuffer.swift
Expand Up @@ -235,11 +235,11 @@ struct _SliceBuffer<Element> : _ArrayBufferProtocol, RandomAccessCollection {
}

mutating func isUniquelyReferenced() -> Bool {
return isUniquelyReferencedNonObjC(&owner)
return isKnownUniquelyReferenced(&owner)
}

mutating func isUniquelyReferencedOrPinned() -> Bool {
return isUniquelyReferencedOrPinnedNonObjC(&owner)
return _isKnownUniquelyReferencedOrPinned(&owner)
}

@_versioned
Expand Down
4 changes: 2 additions & 2 deletions stdlib/public/core/StringCore.swift
Expand Up @@ -614,7 +614,7 @@ extension _StringCore : RangeReplaceableCollection {
let appending = bounds.lowerBound == endIndex

let existingStorage = !hasCocoaBuffer && (
appending || isUniquelyReferencedNonObjC(&_owner)
appending || isKnownUniquelyReferenced(&_owner)
) ? _claimCapacity(newCount, minElementWidth: width).1 : nil

if _fastPath(existingStorage != nil) {
Expand Down Expand Up @@ -666,7 +666,7 @@ extension _StringCore : RangeReplaceableCollection {

public mutating func reserveCapacity(_ n: Int) {
if _fastPath(!hasCocoaBuffer) {
if _fastPath(isUniquelyReferencedNonObjC(&_owner)) {
if _fastPath(isKnownUniquelyReferenced(&_owner)) {

let bounds: Range<UnsafePointer<_RawByte>>
= UnsafePointer(_pointer(toElementAt:0))..<UnsafePointer(_pointer(toElementAt:count))
Expand Down
37 changes: 9 additions & 28 deletions test/1_stdlib/ManagedBuffer.swift
Expand Up @@ -19,15 +19,6 @@ import StdlibUnittest
import Foundation
#endif

// Check that `NonObjectiveCBase` can be subclassed and the subclass can be
// created.
public class SubclassOfNonObjectiveCBase : NonObjectiveCBase {
public override init() {}
}
func createSubclassOfNonObjectiveCBase() {
_ = SubclassOfNonObjectiveCBase()
}

// Check that the generic parameters are called 'Header' and 'Element'.
protocol TestProtocol1 {}

Expand Down Expand Up @@ -199,11 +190,11 @@ tests.test("ManagedBufferPointer") {
CountAndCapacity(
count: LifetimeTracked(0), capacity: getRealCapacity(buffer))
}
expectTrue(mgr.holdsUniqueReference())
expectTrue(mgr.isUniqueReference())

let buf = mgr.buffer as? TestManagedBuffer<LifetimeTracked>
expectTrue(buf != nil)
expectFalse(mgr.holdsUniqueReference())
expectFalse(mgr.isUniqueReference())

let s = buf!
expectEqual(0, s.count)
Expand Down Expand Up @@ -232,38 +223,28 @@ tests.test("ManagedBufferPointer") {
minimumCapacity: 0
) { _, _ in CountAndCapacity(count: LifetimeTracked(0), capacity: 99) }

expectTrue(mgr.holdsUniqueReference())
expectTrue(mgr.isUniqueReference())
expectEqual(mgr.header.count.value, 0)
expectEqual(mgr.header.capacity, 99)

let s2 = mgr.buffer as! MyBuffer<LifetimeTracked>
expectFalse(mgr.holdsUniqueReference())
expectFalse(mgr.isUniqueReference())

let val = mgr.withUnsafeMutablePointerToHeader { $0 }.pointee
expectEqual(val.count.value, 0)
expectEqual(val.capacity, 99)
}
}

tests.test("isUniquelyReferenced") {
var s = TestManagedBuffer<LifetimeTracked>.create(0)
expectTrue(isUniquelyReferenced(&s))
var s2 = s
expectFalse(isUniquelyReferenced(&s))
expectFalse(isUniquelyReferenced(&s2))
_fixLifetime(s)
_fixLifetime(s2)
}

tests.test("isUniquelyReferencedNonObjC") {
tests.test("isKnownUniquelyReferenced") {
var s = TestManagedBuffer<LifetimeTracked>.create(0)
expectTrue(isUniquelyReferencedNonObjC(&s))
expectTrue(isKnownUniquelyReferenced(&s))
var s2 = s
expectFalse(isUniquelyReferencedNonObjC(&s))
expectFalse(isUniquelyReferencedNonObjC(&s2))
expectFalse(isKnownUniquelyReferenced(&s))
expectFalse(isKnownUniquelyReferenced(&s2))
#if _runtime(_ObjC)
var s3 = NSArray()
expectFalse(isUniquelyReferencedNonObjC(&s3))
expectFalse(isKnownUniquelyReferenced(&s3))
#endif
_fixLifetime(s)
_fixLifetime(s2)
Expand Down
3 changes: 0 additions & 3 deletions test/1_stdlib/Runtime.swift.gyb
Expand Up @@ -349,9 +349,6 @@ Runtime.test("typeByName") {
expectTrue(_typeByName("a.SomeSubclass") == SomeSubclass.self)
// name lookup will be via protocol conformance table
expectTrue(_typeByName("a.SomeConformingClass") == SomeConformingClass.self)
// FIXME: NonObjectiveCBase is slated to die, but I can't think of another
// nongeneric public class in the stdlib...
expectTrue(_typeByName("Swift.NonObjectiveCBase") == NonObjectiveCBase.self)
}

Runtime.test("demangleName") {
Expand Down

0 comments on commit 4ea93f6

Please sign in to comment.