- Proposal: SE-0088
- Author: Matt Wright
- Review Manager: Chris Lattner
- Status: Implemented (Swift 3)
- Decision Notes: Rationale
- Previous Revision: 1
The existing libdispatch module imports the C API almost verbatim. To move towards a more natural Swift interface and away from the C API, this proposal outlines changes to the libdispatch module and the motivation behind them.
This discussion focuses on the transformation of the existing libdispatch API.
libdispatch on Darwin already presents Objective-C compatible types to allow its objects to participate in automatic reference counting. We propose extending this support to present a design that feels “object-oriented” and inline with Swift 3's API guidelines, all without adding runtime overhead.
In Swift 2.2, libdispatch is exposed as a collection of functions imported from C. While trailing closure syntax does much to improve the basic usage of libdispatch, the experience in Swift still feels very C-like. As the introduction implies, we intend to transform the entire libdispatch API surface.
Previously, typical dispatch usage in Swift would look like:
let queue = dispatch_queue_create("com.test.myqueue", nil)
dispatch_async(queue) {
print("Hello World")
}
This proposal will transform that code into:
let queue = DispatchQueue(label: "com.test.myqueue")
queue.asynchronously {
print("Hello World")
}
All of the types used by libdispatch will be renamed to meet the Swift 3 naming guidelines.
C type | Swift type |
---|---|
dispatch_object_t | DispatchObject |
dispatch_queue_t | DispatchQueue |
dispatch_group_t | DispatchGroup |
dispatch_data_t | DispatchData |
dispatch_io_t | DispatchIO |
dispatch_semaphore_t | DispatchSemaphore |
dispatch_source_t | DispatchSource¹ |
dispatch_time_t | DispatchTime, DispatchWalltime |
Several other libdispatch C types will be removed and replaced with their underlying type. These C typedefs serve to make the C API more clear as headerdoc, however in Swift these types are clearer when presented as their original type. Several other types will be replaced with OptionSet
types, where appropriate.
C type | Swift type |
---|---|
dispatch_fd_t | Int32 |
dispatch_block_t | () -> () |
dispatch_queue_attr_t | DispatchQueueAttributes |
[1] Additional DispatchSource sub-types have also been introduced, a more thorough explanation is included below.
Accessors to the main queue and global queues will be moved onto DispatchQueue
as class properties.
class DispatchQueue : DispatchObject {
class var main: DispatchQueue
class func global(attributes: GlobalAttributes) -> DispatchQueue
}
Queue and group functions that are responsible for submitting work to dispatch queues will be transformed or replaced by Swift methods on DispatchQueue
. These existing functions act on, or with, queues and form a more cohesive API surface when presented on DispatchQueue
itself. Previously these functions took the following form:
func dispatch_sync(queue: dispatch_queue_t, block: dispatch_block_t)
func dispatch_async(queue: dispatch_queue_t, block: dispatch_block_t)
func dispatch_group_async(group: dispatch_group_t, queue: dispatch_queue_t, block: dispatch_block_t)
This proposal collects these APIs into two methods on DispatchQueue
and also introduces default parameters that cover QoS and work item flags. In turn this allows for control over block and QoS inheritance behaviour:
class DispatchQueue : DispatchObject {
func synchronously(execute block: @noescape () -> Void)
func asynchronously(
group: DispatchGroup? = nil,
qos: DispatchQoS = .unspecified,
flags: DispatchWorkItemFlags = [],
work: @convention(block) () -> Void)
}
queue.asynchronously(group: group) {
print("Hello World")
}
queue.synchronously {
print("Hello World")
}
The existing dispatch_specific_*
functions have a cumbersome interface when presented in Swift. These functions will also be refined in Swift, presenting a more typesafe API. The aim here is to provide the same underlying functionality but with additional type information, reducing the need for casting and opportunity for misuse.
Before:
func dispatch_get_specific(key: UnsafePointer<Void>) -> UnsafeMutablePointer<Void>
func dispatch_queue_get_specific(queue: dispatch_queue_t, _ key: UnsafePointer<Void>) -> UnsafeMutablePointer<Void>
func dispatch_queue_set_specific(queue: dispatch_queue_t, _ key: UnsafePointer<Void>, _ context: UnsafeMutablePointer<Void>, _ destructor: dispatch_function_t?)
After:
class DispatchSpecificKey<T> {
init() {}
}
class DispatchQueue : DispatchObject {
/// Return the Value? for a given DispatchSpecificKey object from
/// the current dispatch queue hierarchy.
class func getSpecific<Value>(key: DispatchSpecificKey<Value>) -> Value?
/// Get and set the DispatchSpecificKey for this queue,
/// providing type information via the DispatchSpecificKey
/// specialisation.
func getSpecific<Value>(key: DispatchSpecificKey<Value>) -> Value?
func setSpecific<Value>(key: DispatchSpecificKey<Value>, value: Value?)
}
// Example usage, using a global key object
let akey = DispatchSpecificKey<Int>()
queue.setSpecific(key: akey, value: 42)
The existing dispatch_block_*
API group exposes functionality that produces dispatch_block_t
blocks that are wrapped with additional metadata. That behaviour in C has multiple cases where this API group can be accidentally misused because the C types are ambiguously overloaded. This proposal will introduce a new explict class to cover this functionality, DispatchWorkItem
that provides more explicit, safer typing.
class DispatchWorkItem {
init(group: DispatchGroup? = nil,
qos: DispatchQoS = .unspecified,
flags: DispatchWorkItemFlags = [],
execute: () -> ())
func perform()
func wait(timeout: DispatchTime = .forever) -> Int
func wait(timeout: DispatchWalltime) -> Int
func notify(queue: DispatchQueue, execute: @convention(block) () -> Void)
func cancel()
var isCancelled: Bool
}
All dispatch methods that accept blocks also accept DispatchWorkItem
:
let item = DispatchWorkItem(qos: .qosUserInitiated) {
print("Hello World")
}
queue.asynchronously(execute: item)
libdispatch exposes a lightweight representation of time², focussing on deadlines and intervals for timers. However, the C interfaces for dispatch_time_t
are very unfortunately imported in Swift 2.2, with type impedance problems that require unnecessary casting in order to use in Swift. This proposal will replace dispatch_time_t
with two new time types and one interval type. DispatchTime
, DispatchWalltime
and DispatchTimeInterval
.
struct DispatchTime {
static func now() -> DispatchTime
static let forever: DispatchTime
}
struct DispatchWalltime {
static func now() -> DispatchWalltime
static let forever: DispatchWalltime
init(time: timespec)
}
enum DispatchTimeInterval {
case seconds(Int)
case milliseconds(Int)
case microseconds(Int)
case nanoseconds(Int)
}
func +(time: DispatchTime, interval: DispatchTimeInterval) -> DispatchTime
func -(time: DispatchTime, interval: DispatchTimeInterval) -> DispatchTime
func +(time: DispatchTime, seconds: Double) -> DispatchTime
func -(time: DispatchTime, seconds: Double) -> DispatchTime
func +(time: DispatchWalltime, interval: DispatchTimeInterval) -> DispatchWalltime
func -(time: DispatchWalltime, interval: DispatchTimeInterval) -> DispatchWalltime
func +(time: DispatchWalltime, seconds: Double) -> DispatchWalltime
func -(time: DispatchWalltime, seconds: Double) -> DispatchWalltime
The aim here is to continue to provide a lightweight representation of time, while distinguishing between time and interval quantities. Time, to be used to set deadlines, and intervals used to represent the period of repeating events. This model also allows for the expression of time and intervals either as natural second-addition, or with explicit sub-second quantities.
let a = DispatchTime.now() + 3.5 // 3.5 seconds in the future
let b = DispatchTime.now() + .microseconds(350)
// Modify a DispatchSourceTimer with new start time and interval
timer.setTimer(start: .now(), interval: .milliseconds(500))
[2] Note that libdispatch is unable to use Date
from Foundation due to layering restrictions
dispatch_data_t
will be transformed into a value type, DispatchData
. Data objects in libdispatch have always been immutable objects, so these objects are natural candidates for value semantics in Swift.
struct DispatchData : RandomAccessCollection, _ObjectiveCBridgeable {
enum Deallocator {
/// Use `free`
case free
/// Use `munmap`
case unmap
/// A custom deallocator
case custom(DispatchQueue?, @convention(block) () -> Void)
}
/// Initialize a `Data` with copied memory content.
init(bytes buffer: UnsafeBufferPointer<UInt8>)
/// Initialize a `Data` without copying the bytes.
init(bytesNoCopy bytes: UnsafeBufferPointer<UInt8>, deallocator: Deallocator = .free)
mutating func append(_ bytes: UnsafePointer<UInt8>, count: Int)
mutating func append(_ other: DispatchData)
mutating func append<SourceType>(_ buffer: UnsafeBufferPointer<SourceType>)
func subdata(in range: CountableRange<Index>) -> DispatchData
func region(location: Int) -> (DispatchData, Int)
}
This proposal will introduce new accessor methods to access the bytes in a Data object. Along with becoming iteratable, several methods will be introduced that replace the dispatch_data_create_map
approach used in C:
struct DispatchData : RandomAccessCollection, _ObjectiveCBridgeable {
func withUnsafeBytes<Result, ContentType>(
body: @noescape (UnsafePointer<ContentType>) throws -> Result) rethrows -> Result
func enumerateBytes(
block: @noescape (buffer: UnsafeBufferPointer<UInt8>, byteIndex: Int, stop: inout Bool) -> Void)
func copyBytes(to pointer: UnsafeMutablePointer<UInt8>, count: Int)
func copyBytes(
to pointer: UnsafeMutablePointer<UInt8>,
from range: Range<Index>)
func copyBytes<DestinationType>(
to buffer: UnsafeMutableBufferPointer<DestinationType>,
from range: Range<Index>? = nil) -> Int
subscript(index: Index) -> UInt8
}
Finally, this proposal will introduce additional type safety to dispatch sources. While adding additional DispatchSource subclasses is out of scope for this proposal, it will introduce a new constructor for each dispatch source type.
Kind of Source | Protocol |
---|---|
DISPATCH_SOURCE_TYPE_DATA_ADD | DispatchSourceUserDataAdd |
DISPATCH_SOURCE_TYPE_DATA_OR | DispatchSourceUserDataOr |
DISPATCH_SOURCE_TYPE_MACH_SEND | DispatchSourceMachSend |
DISPATCH_SOURCE_TYPE_MACH_RECV | DispatchSourceMachReceive |
DISPATCH_SOURCE_TYPE_MEMORYPRESSURE | DispatchSourceMemoryPressure |
DISPATCH_SOURCE_TYPE_PROC | DispatchSourceProcess |
DISPATCH_SOURCE_TYPE_READ | DispatchSourceRead |
DISPATCH_SOURCE_TYPE_SIGNAL | DispatchSourceSignal |
DISPATCH_SOURCE_TYPE_TIMER | DispatchSourceTimer |
DISPATCH_SOURCE_TYPE_VNODE | DispatchSourceFileSystemObject |
DISPATCH_SOURCE_TYPE_WRITE | DispatchSourceWrite |
Introducing protocols for each source allows DispatchSource to return protocols that are more strongly typed then their C equivalent. Furthermore, this proposal also adds stronger typing to return types of dispatch source accessors, where appropriate:
class DispatchSource {
class func machSend(port: mach_port_t, eventMask: DispatchSource.MachSendEvent, queue: DispatchQueue? = default) -> DispatchSourceMachSend
class func machReceive(port: mach_port_t, queue: DispatchQueue? = default) -> DispatchSourceMachReceive
class func memoryPressure(eventMask: DispatchSource.MemoryPressureEvent, queue: DispatchQueue? = default) -> DispatchSourceMemoryPressure
class func process(identifier: pid_t, eventMask: DispatchSource.ProcessEvent, queue: DispatchQueue? = default) -> DispatchSourceProcess
class func read(fileDescriptor: Int32, queue: DispatchQueue? = default) -> DispatchSourceRead
class func signal(signal: Int32, queue: DispatchQueue? = default) -> DispatchSourceSignal
class func timer(flags: DispatchSource.TimerFlags = default, queue: DispatchQueue? = default) -> DispatchSourceTimer
class func userDataAdd(queue: DispatchQueue? = default) -> DispatchSourceUserDataAdd
class func userDataOr(queue: DispatchQueue? = default) -> DispatchSourceUserDataOr
class func fileSystemObject(fileDescriptor: Int32, eventMask: DispatchSource.FileSystemEvent, queue: DispatchQueue? = default) -> DispatchSourceFileSystemObject
class func write(fileDescriptor: Int32, queue: DispatchQueue? = default) -> DispatchSourceWrite
}
class DispatchSource {
struct ProcessEvent : OptionSet, RawRepresentable {
let rawValue: UInt
init(rawValue: UInt)
static let exit: ProcessEvent
static let fork: ProcessEvent
static let exec: ProcessEvent
static let signal: ProcessEvent
static let all: ProcessEvent = [.exit, .fork, .exec, .signal]
}
}
extension DispatchSourceProcess {
var handle: pid_t
var data: DispatchSource.ProcessEvent
var mask: DispatchSource.ProcessEvent
}
extension DispatchSourceUserDataAdd {
func mergeData(value: UInt)
}
The first revision of this proposal included only a brief overview of the most critical changes in the Dispatch module. For the interested, included below is a full output of the Dispatch module after the transformations proposed by this document.
class DispatchGroup : DispatchObject {
init()
func wait(timeout: DispatchTime = default) -> Int
func wait(walltime timeout: DispatchWalltime) -> Int
func notify(queue: DispatchQueue, exeute block: () -> Void)
func enter()
func leave()
}
class DispatchIO : DispatchObject {
enum StreamType : UInt {
case stream
case random
typealias RawValue = UInt
var hashValue: Int { get }
init?(rawValue: UInt)
var rawValue: UInt { get }
}
struct CloseFlags : OptionSet, RawRepresentable {
let rawValue: UInt
init(rawValue: UInt)
static let stop: DispatchIO.CloseFlags
typealias Element = DispatchIO.CloseFlags
typealias RawValue = UInt
}
struct IntervalFlags : OptionSet, RawRepresentable {
let rawValue: UInt
init(rawValue: UInt)
static let strictInterval: DispatchIO.IntervalFlags
typealias Element = DispatchIO.IntervalFlags
typealias RawValue = UInt
}
class func read(fileDescriptor: Int32, length: Int, queue: DispatchQueue, handler: (DispatchData, Int32) -> Void)
class func write(fileDescriptor: Int32, data: DispatchData, queue: DispatchQueue, handler: (DispatchData?, Int32) -> Void)
convenience init(type: DispatchIO.StreamType, fileDescriptor: Int32, queue: DispatchQueue, cleanupHandler: (error: Int32) -> Void)
convenience init(type: DispatchIO.StreamType, path: UnsafePointer<Int8>, oflag: Int32, mode: mode_t, queue: DispatchQueue, cleanupHandler: (error: Int32) -> Void)
convenience init(type: DispatchIO.StreamType, io: DispatchIO, queue: DispatchQueue, cleanupHandler: (error: Int32) -> Void)
func close(flags: DispatchIO.CloseFlags)
var fileDescriptor: Int32 { get }
func read(offset: off_t, length: Int, queue: DispatchQueue, ioHandler io_handler: (Bool, DispatchData?, Int32) -> Void)
func setHighWater(highWater high_water: Int)
func setInterval(interval: UInt64, flags: DispatchIO.IntervalFlags)
func setLowWater(lowWater low_water: Int)
func withBarrier(barrier: () -> Void)
func write(offset: off_t, data: DispatchData, queue: DispatchQueue, ioHandler io_handler: (Bool, DispatchData?, Int32) -> Void)
}
class DispatchObject : OS_object {
func suspend()
func resume()
func setTargetQueue(queue: DispatchQueue?)
}
class DispatchQueue : DispatchObject {
struct GlobalAttributes : OptionSet {
let rawValue: UInt64
init(rawValue: UInt64)
static let qosUserInteractive: DispatchQueue.GlobalAttributes
static let qosUserInitiated: DispatchQueue.GlobalAttributes
static let qosDefault: DispatchQueue.GlobalAttributes
static let qosUtility: DispatchQueue.GlobalAttributes
static let qosBackground: DispatchQueue.GlobalAttributes
typealias Element = DispatchQueue.GlobalAttributes
typealias RawValue = UInt64
}
class var main: DispatchQueue { get }
class func global(attributes: DispatchQueue.GlobalAttributes) -> DispatchQueue
class func getSpecific<T>(key: DispatchSpecificKey<T>) -> T?
convenience init(label: String, attributes: DispatchQueueAttributes = default, target: DispatchQueue? = default)
func after(when: DispatchTime, execute work: @convention(block) () -> Void)
func after(walltime when: DispatchWalltime, execute work: @convention(block) () -> Void)
func apply(applier iterations: Int, execute block: @noescape (Int) -> Void)
func asynchronously(execute workItem: DispatchWorkItem)
func asynchronously(group: DispatchGroup? = default, qos: DispatchQoS = default, flags: DispatchWorkItemFlags = default, execute work: @convention(block) () -> Void)
var label: String { get }
func synchronously(execute block: @noescape () -> Void)
func synchronously(execute workItem: DispatchWorkItem)
func synchronously<T>(execute work: @noescape () throws -> T) rethrows -> T
func synchronously<T>(flags: DispatchWorkItemFlags, execute work: @noescape () throws -> T) rethrows -> T
var qos: DispatchQoS { get }
func getSpecific<T>(key: DispatchSpecificKey<T>) -> T?
func setSpecific<T>(key: DispatchSpecificKey<T>, value: T)
}
@noreturn
func dispatchMain()
class DispatchSemaphore : DispatchObject {
init(value: Int)
func wait(timeout: DispatchTime = default) -> Int
func wait(walltime timeout: DispatchWalltime) -> Int
func signal() -> Int
}
class DispatchSource : DispatchObject {
struct MachSendEvent : OptionSet, RawRepresentable {
let rawValue: UInt
init(rawValue: UInt)
static let dead: DispatchSource.MachSendEvent
typealias Element = DispatchSource.MachSendEvent
typealias RawValue = UInt
}
struct MemoryPressureEvent : OptionSet, RawRepresentable {
let rawValue: UInt
init(rawValue: UInt)
static let normal: DispatchSource.MemoryPressureEvent
static let warning: DispatchSource.MemoryPressureEvent
static let critical: DispatchSource.MemoryPressureEvent
static let all: DispatchSource.MemoryPressureEvent
typealias Element = DispatchSource.MemoryPressureEvent
typealias RawValue = UInt
}
struct ProcessEvent : OptionSet, RawRepresentable {
let rawValue: UInt
init(rawValue: UInt)
static let exit: DispatchSource.ProcessEvent
static let fork: DispatchSource.ProcessEvent
static let exec: DispatchSource.ProcessEvent
static let signal: DispatchSource.ProcessEvent
static let all: DispatchSource.ProcessEvent
typealias Element = DispatchSource.ProcessEvent
typealias RawValue = UInt
}
struct TimerFlags : OptionSet, RawRepresentable {
let rawValue: UInt
init(rawValue: UInt)
static let strict: DispatchSource.TimerFlags
typealias Element = DispatchSource.TimerFlags
typealias RawValue = UInt
}
struct FileSystemEvent : OptionSet, RawRepresentable {
let rawValue: UInt
init(rawValue: UInt)
static let delete: DispatchSource.FileSystemEvent
static let write: DispatchSource.FileSystemEvent
static let extend: DispatchSource.FileSystemEvent
static let attrib: DispatchSource.FileSystemEvent
static let link: DispatchSource.FileSystemEvent
static let rename: DispatchSource.FileSystemEvent
static let revoke: DispatchSource.FileSystemEvent
static let all: DispatchSource.FileSystemEvent
typealias Element = DispatchSource.FileSystemEvent
typealias RawValue = UInt
}
class func machSend(port: mach_port_t, eventMask: DispatchSource.MachSendEvent, queue: DispatchQueue? = default) -> DispatchSourceMachSend
class func machReceive(port: mach_port_t, queue: DispatchQueue? = default) -> DispatchSourceMachReceive
class func memoryPressure(eventMask: DispatchSource.MemoryPressureEvent, queue: DispatchQueue? = default) -> DispatchSourceMemoryPressure
class func process(identifier: pid_t, eventMask: DispatchSource.ProcessEvent, queue: DispatchQueue? = default) -> DispatchSourceProcess
class func read(fileDescriptor: Int32, queue: DispatchQueue? = default) -> DispatchSourceRead
class func signal(signal: Int32, queue: DispatchQueue? = default) -> DispatchSourceSignal
class func timer(flags: DispatchSource.TimerFlags = default, queue: DispatchQueue? = default) -> DispatchSourceTimer
class func userDataAdd(queue: DispatchQueue? = default) -> DispatchSourceUserDataAdd
class func userDataOr(queue: DispatchQueue? = default) -> DispatchSourceUserDataOr
class func fileSystemObject(fileDescriptor: Int32, eventMask: DispatchSource.FileSystemEvent, queue: DispatchQueue? = default) -> DispatchSourceFileSystemObject
class func write(fileDescriptor: Int32, queue: DispatchQueue? = default) -> DispatchSourceWrite
}
protocol DispatchSourceType : NSObjectProtocol {
typealias DispatchSourceHandler = @convention(block) () -> Void
func setEventHandler(handler: DispatchSourceHandler?)
func setCancelHandler(handler: DispatchSourceHandler?)
func setRegistrationHandler(handler: DispatchSourceHandler?)
func cancel()
func resume()
func suspend()
var handle: UInt { get }
var mask: UInt { get }
var data: UInt { get }
var isCancelled: Bool { get }
}
extension DispatchSource : DispatchSourceType {
}
protocol DispatchSourceUserDataAdd : DispatchSourceType {
func mergeData(value: UInt)
}
extension DispatchSource : DispatchSourceUserDataAdd {
}
protocol DispatchSourceUserDataOr : DispatchSourceType {
func mergeData(value: UInt)
}
extension DispatchSource : DispatchSourceUserDataOr {
}
protocol DispatchSourceMachSend : DispatchSourceType {
var handle: mach_port_t { get }
var data: DispatchSource.MachSendEvent { get }
var mask: DispatchSource.MachSendEvent { get }
}
extension DispatchSource : DispatchSourceMachSend {
}
protocol DispatchSourceMachReceive : DispatchSourceType {
var handle: mach_port_t { get }
}
extension DispatchSource : DispatchSourceMachReceive {
}
protocol DispatchSourceMemoryPressure : DispatchSourceType {
var data: DispatchSource.MemoryPressureEvent { get }
var mask: DispatchSource.MemoryPressureEvent { get }
}
extension DispatchSource : DispatchSourceMemoryPressure {
}
protocol DispatchSourceProcess : DispatchSourceType {
var handle: pid_t { get }
var data: DispatchSource.ProcessEvent { get }
var mask: DispatchSource.ProcessEvent { get }
}
extension DispatchSource : DispatchSourceProcess {
}
protocol DispatchSourceRead : DispatchSourceType {
}
extension DispatchSource : DispatchSourceRead {
}
protocol DispatchSourceSignal : DispatchSourceType {
}
extension DispatchSource : DispatchSourceSignal {
}
protocol DispatchSourceTimer : DispatchSourceType {
func setTimer(start: DispatchTime, leeway: DispatchTimeInterval = default)
func setTimer(walltime start: DispatchWalltime, leeway: DispatchTimeInterval = default)
func setTimer(start: DispatchTime, interval: DispatchTimeInterval, leeway: DispatchTimeInterval = default)
func setTimer(start: DispatchTime, interval: Double, leeway: DispatchTimeInterval = default)
func setTimer(walltime start: DispatchWalltime, interval: DispatchTimeInterval, leeway: DispatchTimeInterval = default)
func setTimer(walltime start: DispatchWalltime, interval: Double, leeway: DispatchTimeInterval = default)
}
extension DispatchSource : DispatchSourceTimer {
}
protocol DispatchSourceFileSystemObject : DispatchSourceType {
var handle: Int32 { get }
var data: DispatchSource.FileSystemEvent { get }
var mask: DispatchSource.FileSystemEvent { get }
}
extension DispatchSource : DispatchSourceFileSystemObject {
}
protocol DispatchSourceWrite : DispatchSourceType {
}
extension DispatchSource : DispatchSourceWrite {
}
extension DispatchSourceMemoryPressure {
var data: DispatchSource.MemoryPressureEvent { get }
var mask: DispatchSource.MemoryPressureEvent { get }
}
extension DispatchSourceMachReceive {
var handle: mach_port_t { get }
}
extension DispatchSourceFileSystemObject {
var handle: Int32 { get }
var data: DispatchSource.FileSystemEvent { get }
var mask: DispatchSource.FileSystemEvent { get }
}
extension DispatchSourceUserDataOr {
func mergeData(value: UInt)
}
struct DispatchData : RandomAccessCollection, _ObjectiveCBridgeable {
typealias Iterator = DispatchDataIterator
typealias Index = Int
typealias Indices = DefaultRandomAccessIndices<DispatchData>
static let empty: DispatchData
enum Deallocator {
case free
case unmap
case custom(DispatchQueue?, @convention(block) () -> Void)
}
init(bytes buffer: UnsafeBufferPointer<UInt8>)
init(bytesNoCopy bytes: UnsafeBufferPointer<UInt8>, deallocator: DispatchData.Deallocator = default)
var count: Int { get }
func withUnsafeBytes<Result, ContentType>(body: @noescape (UnsafePointer<ContentType>) throws -> Result) rethrows -> Result
func enumerateBytes(block: @noescape (buffer: UnsafeBufferPointer<UInt8>, byteIndex: Int, stop: inout Bool) -> Void)
mutating func append(_ bytes: UnsafePointer<UInt8>, count: Int)
mutating func append(_ other: DispatchData)
mutating func append<SourceType>(_ buffer: UnsafeBufferPointer<SourceType>)
func copyBytes(to pointer: UnsafeMutablePointer<UInt8>, count: Int)
func copyBytes(to pointer: UnsafeMutablePointer<UInt8>, from range: CountableRange<Index>)
func copyBytes<DestinationType>(to buffer: UnsafeMutableBufferPointer<DestinationType>, from range: CountableRange<Index>? = default) -> Int
subscript(index: Index) -> UInt8 { get }
subscript(bounds: Range<Int>) -> RandomAccessSlice<DispatchData> { get }
func subdata(in range: CountableRange<Index>) -> DispatchData
func region(location: Int) -> (data: DispatchData, offset: Int)
var startIndex: Index { get }
var endIndex: Index { get }
func index(before i: Index) -> Index
func index(after i: Index) -> Index
func makeIterator() -> Iterator
typealias IndexDistance = Int
typealias _Element = UInt8
typealias SubSequence = RandomAccessSlice<DispatchData>
typealias _ObjectiveCType = __DispatchData
}
struct DispatchDataIterator : IteratorProtocol, Sequence {
mutating func next() -> _Element?
typealias Element = _Element
typealias Iterator = DispatchDataIterator
typealias SubSequence = AnySequence<_Element>
}
struct DispatchQoS : Equatable {
let qosClass: DispatchQoS.QoSClass
let relativePriority: Int
static let background: DispatchQoS
static let utility: DispatchQoS
static let defaultQoS: DispatchQoS
static let userInitiated: DispatchQoS
static let userInteractive: DispatchQoS
static let unspecified: DispatchQoS
enum QoSClass {
case background
case utility
case defaultQoS
case userInitiated
case userInteractive
case unspecified
var hashValue: Int { get }
}
init(qosClass: DispatchQoS.QoSClass, relativePriority: Int)
}
infix func ==(a: DispatchQoS.QoSClass, b: DispatchQoS.QoSClass) -> Bool
func ==(a: DispatchQoS, b: DispatchQoS) -> Bool
infix func ==(a: DispatchQoS.QoSClass, b: DispatchQoS.QoSClass) -> Bool
struct DispatchQueueAttributes : OptionSet {
let rawValue: UInt64
init(rawValue: UInt64)
static let serial: DispatchQueueAttributes
static let concurrent: DispatchQueueAttributes
static let qosUserInteractive: DispatchQueueAttributes
static let qosUserInitiated: DispatchQueueAttributes
static let qosDefault: DispatchQueueAttributes
static let qosUtility: DispatchQueueAttributes
static let qosBackground: DispatchQueueAttributes
static let noQoS: DispatchQueueAttributes
typealias Element = DispatchQueueAttributes
typealias RawValue = UInt64
}
final class DispatchSpecificKey<T> {
init()
}
struct DispatchTime {
let rawValue: dispatch_time_t
static func now() -> DispatchTime
static let distantFuture: DispatchTime
}
enum DispatchTimeInterval {
case seconds(Int)
case milliseconds(Int)
case microseconds(Int)
case nanoseconds(Int)
}
struct DispatchWalltime {
let rawValue: dispatch_time_t
static func now() -> DispatchWalltime
static let distantFuture: DispatchWalltime
init(time: timespec)
}
func +(time: DispatchTime, interval: DispatchTimeInterval) -> DispatchTime
func +(time: DispatchTime, seconds: Double) -> DispatchTime
func +(time: DispatchWalltime, interval: DispatchTimeInterval) -> DispatchWalltime
func +(time: DispatchWalltime, seconds: Double) -> DispatchWalltime
func -(time: DispatchTime, interval: DispatchTimeInterval) -> DispatchTime
func -(time: DispatchTime, seconds: Double) -> DispatchTime
func -(time: DispatchWalltime, interval: DispatchTimeInterval) -> DispatchWalltime
func -(time: DispatchWalltime, seconds: Double) -> DispatchWalltime
class DispatchWorkItem {
init(group: DispatchGroup? = default, qos: DispatchQoS = default, flags: DispatchWorkItemFlags = default, block: () -> ())
func perform()
func wait(timeout: DispatchTime = default) -> Int
func wait(timeout: DispatchWalltime) -> Int
func notify(queue: DispatchQueue, execute: @convention(block) () -> Void)
func cancel()
var isCancelled: Bool { get }
}
struct DispatchWorkItemFlags : OptionSet, RawRepresentable {
let rawValue: UInt
init(rawValue: UInt)
static let barrier: DispatchWorkItemFlags
static let detached: DispatchWorkItemFlags
static let assignCurrentContext: DispatchWorkItemFlags
static let noQoS: DispatchWorkItemFlags
static let inheritQoS: DispatchWorkItemFlags
static let enforceQoS: DispatchWorkItemFlags
typealias Element = DispatchWorkItemFlags
typealias RawValue = UInt
}
All Swift code that uses libdispatch via the current C API will be affected by this change.
The alternative here was to leave the libdispatch API as it is currently imported in C. This proposal aims to improve the experience of using libdispatch in Swift and we did not feel that leaving the API as-is was a viable alternative.