[swift-evolution] Draft: Add @noescape and rethrows to ManagedBuffer API

Károly Lőrentey karoly at lorentey.hu
Sat Feb 6 14:03:51 CST 2016


I’d like to request feedback on the draft proposal below, about a (hopefully) trivial change to the standard library. 

I considered adding it to SE-0012 <https://github.com/apple/swift-evolution/blob/master/proposals/0012-add-noescape-to-public-library-api.md>, which is also about @noescape, but that proposal is about modifying C/Obj-C API, so it’s not a good fit <https://github.com/apple/swift-evolution/pull/122>.

Introduction

stdlib’s ManagedBuffer family of APIs has some public initializers and methods taking closures that are missing the @noescape attribute. The same family has a set of withUnsafeMutablePointer* functions that do not have a rethrows declaration, while all similar methods elsewhere in the standard library allow closures to throw.

I propose to add the missing @noescape attributes and rethrows.

Motivation

- ManagedBuffer seems designed for raw performance. Not having @noescape on the only API that allows access to the buffer’s contents defeats some compiler optimizations, such as omitting unneccessary retain/release calls. This can negate the performance advantage of ManagedBuffer over simpler solutions, like using an Array.
- Accepting throwing closures makes these APIs more versatile, and also improves their consistency with other parts of stdlib.

Detailed Design

The following set of APIs would be affected by this proposal:

public class ManagedProtoBuffer<Value, Element> : NonObjectiveCBase {
  public final func withUnsafeMutablePointerToValue<R>(body: (UnsafeMutablePointer<Value>) -> R) -> R
  public final func withUnsafeMutablePointerToElements<R>(body: (UnsafeMutablePointer<Element>) -> R) -> R
  public final func withUnsafeMutablePointers<R>(body: (_: UnsafeMutablePointer<Value>, _: UnsafeMutablePointer<Element>) -> R) -> R
}

public class ManagedBuffer<Value, Element> : ManagedProtoBuffer<Value, Element> {
  public final class func create(minimumCapacity: Int, initialValue: (ManagedProtoBuffer<Value,Element>) -> Value) -> ManagedBuffer<Value,Element> 
}

public struct ManagedBufferPointer<Value, Element> : Equatable {
  public init(bufferClass: AnyClass, minimumCapacity: Int, initialValue: (buffer: AnyObject, allocatedCount: (AnyObject) -> Int) -> Value)
  public func withUnsafeMutablePointerToValue<R>(body: (UnsafeMutablePointer<Value>) -> R) -> R
  public func withUnsafeMutablePointerToElements<R>(body: (UnsafeMutablePointer<Element>) -> R) -> R
  public func withUnsafeMutablePointers<R>(body: (_: UnsafeMutablePointer<Value>, _: UnsafeMutablePointer<Element>) -> R) -> R
}

Here is how they would look after the proposed changes:

public class ManagedProtoBuffer<Value, Element> : NonObjectiveCBase {
  public final func withUnsafeMutablePointerToValue<R>(@noescape body: (UnsafeMutablePointer<Value>) throws -> R) rethrows -> R
  public final func withUnsafeMutablePointerToElements<R>(@noescape body: (UnsafeMutablePointer<Element>) throws -> R) rethrows -> R
  public final func withUnsafeMutablePointers<R>(@noescape body: (_: UnsafeMutablePointer<Value>, _: UnsafeMutablePointer<Element>) throws -> R) rethrows -> R

public class ManagedBuffer<Value, Element> : ManagedProtoBuffer<Value, Element> {
  public final class func create(minimumCapacity: Int, @noescape initialValue: (ManagedProtoBuffer<Value,Element>) -> Value) -> ManagedBuffer<Value,Element> 
}

public struct ManagedBufferPointer<Value, Element> : Equatable {
  public init(bufferClass: AnyClass, minimumCapacity: Int, @noescape initialValue: (buffer: AnyObject, allocatedCount: (AnyObject) -> Int) -> Value)
  public func withUnsafeMutablePointerToValue<R>(@noescape body: (UnsafeMutablePointer<Value>) throws -> R) rethrows -> R
  public func withUnsafeMutablePointerToElements<R>(@noescape body: (UnsafeMutablePointer<Element>) throws -> R) rethrows -> R
  public func withUnsafeMutablePointers<R>(@noescape body: (_: UnsafeMutablePointer<Value>,_: UnsafeMutablePointer<Element>) throws -> R) rethrows -> R
}

A draft implementation is available at https://github.com/apple/swift/compare/master...lorentey:noescape <https://github.com/apple/swift/compare/master...lorentey:noescape>

Impact on Existing Code

Luckily, all modified API is either marked final, or defined in a struct, so I expect no existing code is going to break due to these changes.

-- 
Károly

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160206/a0e7b3d5/attachment.html>


More information about the swift-evolution mailing list