diff --git a/src/Makefile.am b/src/Makefile.am index ea4a32e2b..e51d15a33 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -114,8 +114,18 @@ DTRACE_SOURCES=provider.h endif if HAVE_SWIFT -libdispatch_la_SOURCES+=swift/swift_wrappers.c -EXTRA_libdispatch_la_SOURCES+=swift/Dispatch.swift +libdispatch_la_SOURCES+=swift/Dispatch.mm +EXTRA_libdispatch_la_SOURCES+= \ + swift/Dispatch.swift \ + swift/Block.swift \ + swift/Data.swift \ + swift/Dispatch.swift \ + swift/IO.swift \ + swift/Private.swift \ + swift/Queue.swift \ + swift/Source.swift \ + swift/Time.swift + EXTRA_libdispatch_la_DEPENDENCIES+=$(abs_builddir)/Dispatch.o $(abs_builddir)/Dispatch.swiftmodule libdispatch_la_LIBADD+=$(abs_builddir)/Dispatch.o diff --git a/src/swift/Block.swift b/src/swift/Block.swift new file mode 100644 index 000000000..e32478ea0 --- /dev/null +++ b/src/swift/Block.swift @@ -0,0 +1,131 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See http://swift.org/LICENSE.txt for license information +// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +public struct DispatchWorkItemFlags : OptionSet, RawRepresentable { + public let rawValue: UInt + public init(rawValue: UInt) { self.rawValue = rawValue } + + public static let barrier = DispatchWorkItemFlags(rawValue: 0x1) + + @available(OSX 10.10, iOS 8.0, *) + public static let detached = DispatchWorkItemFlags(rawValue: 0x2) + + @available(OSX 10.10, iOS 8.0, *) + public static let assignCurrentContext = DispatchWorkItemFlags(rawValue: 0x4) + + @available(OSX 10.10, iOS 8.0, *) + public static let noQoS = DispatchWorkItemFlags(rawValue: 0x8) + + @available(OSX 10.10, iOS 8.0, *) + public static let inheritQoS = DispatchWorkItemFlags(rawValue: 0x10) + + @available(OSX 10.10, iOS 8.0, *) + public static let enforceQoS = DispatchWorkItemFlags(rawValue: 0x20) +} + +@available(OSX 10.10, iOS 8.0, *) +public class DispatchWorkItem { + internal var _block: _DispatchBlock + internal var _group: DispatchGroup? + + public init(group: DispatchGroup? = nil, qos: DispatchQoS = .unspecified, flags: DispatchWorkItemFlags = [], block: @convention(block) () -> ()) { + _block = _swift_dispatch_block_create_with_qos_class(__dispatch_block_flags_t(flags.rawValue), + qos.qosClass.rawValue, Int32(qos.relativePriority), block) + } + + // Used by DispatchQueue.synchronously to provide a @noescape path through + // dispatch_block_t, as we know the lifetime of the block in question. + internal init(flags: DispatchWorkItemFlags = [], noescapeBlock: @noescape () -> ()) { + _block = _swift_dispatch_block_create_noescape(__dispatch_block_flags_t(flags.rawValue), noescapeBlock) + } + + public func perform() { + if let g = _group { + g.enter() + defer { g.leave() } + } + _block() + } + + public func wait() { + _ = _swift_dispatch_block_wait(_block, DispatchTime.distantFuture.rawValue) + } + + public func wait(timeout: DispatchTime) -> DispatchTimeoutResult { + return _swift_dispatch_block_wait(_block, timeout.rawValue) == 0 ? .Success : .TimedOut + } + + public func wait(wallTimeout: DispatchWallTime) -> DispatchTimeoutResult { + return _swift_dispatch_block_wait(_block, wallTimeout.rawValue) == 0 ? .Success : .TimedOut + } + + public func notify(qos: DispatchQoS = .unspecified, flags: DispatchWorkItemFlags = [], queue: DispatchQueue, execute: @convention(block) () -> Void) { + if qos != .unspecified || !flags.isEmpty { + let item = DispatchWorkItem(qos: qos, flags: flags, block: execute) + _swift_dispatch_block_notify(_block, queue, item._block) + } else { + _swift_dispatch_block_notify(_block, queue, execute) + } + } + + public func notify(queue: DispatchQueue, execute: DispatchWorkItem) { + _swift_dispatch_block_notify(_block, queue, execute._block) + } + + public func cancel() { + _swift_dispatch_block_cancel(_block) + } + + public var isCancelled: Bool { + return _swift_dispatch_block_testcancel(_block) != 0 + } +} + +@available(OSX 10.10, iOS 8.0, *) +public extension DispatchWorkItem { + @available(*, deprecated, renamed: "DispatchWorkItem.wait(self:wallTimeout:)") + public func wait(timeout: DispatchWallTime) -> Int { + switch wait(wallTimeout: timeout) { + case .Success: return 0 + case .TimedOut: return Int(KERN_OPERATION_TIMED_OUT) + } + } +} + +/// The dispatch_block_t typealias is different from usual closures in that it +/// uses @convention(block). This is to avoid unnecessary bridging between +/// C blocks and Swift closures, which interferes with dispatch APIs that depend +/// on the referential identity of a block. Particularly, dispatch_block_create. +internal typealias _DispatchBlock = @convention(block) () -> Void + +/// APINotes also removes the old dispatch_block_t typedef from the Dispatch module +/// completely. In doing so it causes the dispatch_block_* API to lose their +/// @convention(block) attributes. As such, all of the entry points are shimmed +//// through Dispatch.mm with _DispatchBlock types. +@_silgen_name("_swift_dispatch_block_create_with_qos_class") +internal func _swift_dispatch_block_create_with_qos_class(_ flags: __dispatch_block_flags_t, _ qos: qos_class_t, _ relativePriority: Int32, _ block: _DispatchBlock) -> _DispatchBlock + +@_silgen_name("_swift_dispatch_block_create_noescape") +internal func _swift_dispatch_block_create_noescape(_ flags: __dispatch_block_flags_t, _ block: @noescape () -> ()) -> _DispatchBlock + +@_silgen_name("_swift_dispatch_block_wait") +internal func _swift_dispatch_block_wait(_ block: _DispatchBlock, _ timeout: UInt64) -> Int + +@_silgen_name("_swift_dispatch_block_notify") +internal func _swift_dispatch_block_notify(_ block: _DispatchBlock, _ queue: DispatchQueue, _ notifier: _DispatchBlock) + +@_silgen_name("_swift_dispatch_block_cancel") +internal func _swift_dispatch_block_cancel(_ block: _DispatchBlock) + +@_silgen_name("_swift_dispatch_block_testcancel") +internal func _swift_dispatch_block_testcancel(_ block: _DispatchBlock) -> Int + diff --git a/src/swift/Data.swift b/src/swift/Data.swift new file mode 100644 index 000000000..a78bf5bca --- /dev/null +++ b/src/swift/Data.swift @@ -0,0 +1,302 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See http://swift.org/LICENSE.txt for license information +// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +public struct DispatchData : RandomAccessCollection, _ObjectiveCBridgeable { + public typealias Iterator = DispatchDataIterator + public typealias Index = Int + public typealias Indices = DefaultRandomAccessIndices + + public static let empty: DispatchData = DispatchData(data: _swift_dispatch_data_empty()) + + public enum Deallocator { + /// Use `free` + case free + + /// Use `munmap` + case unmap + + /// A custom deallocator + case custom(DispatchQueue?, @convention(block) () -> Void) + + private var _deallocator: (DispatchQueue?, @convention(block) () -> Void) { + switch self { + case .free: return (nil, _dispatch_data_destructor_free()) + case .unmap: return (nil, _dispatch_data_destructor_munmap()) + case .custom(let q, let b): return (q, b) + } + } + } + + private var __wrapped: __DispatchData + + /// Initialize a `Data` with copied memory content. + /// + /// - parameter bytes: A pointer to the memory. It will be copied. + /// - parameter count: The number of bytes to copy. + public init(bytes buffer: UnsafeBufferPointer) { + __wrapped = __dispatch_data_create( + buffer.baseAddress!, buffer.count, nil, _dispatch_data_destructor_default()) + } + + /// Initialize a `Data` without copying the bytes. + /// + /// - parameter bytes: A pointer to the bytes. + /// - parameter count: The size of the bytes. + /// - parameter deallocator: Specifies the mechanism to free the indicated buffer. + public init(bytesNoCopy bytes: UnsafeBufferPointer, deallocator: Deallocator = .free) { + let (q, b) = deallocator._deallocator + + __wrapped = __dispatch_data_create( + bytes.baseAddress!, bytes.count, q, b) + } + + internal init(data: __DispatchData) { + __wrapped = data + } + + public var count: Int { + return __dispatch_data_get_size(__wrapped) + } + + public func withUnsafeBytes( + body: @noescape (UnsafePointer) throws -> Result) rethrows -> Result + { + var ptr: UnsafePointer? = nil + var size = 0; + let data = __dispatch_data_create_map(__wrapped, &ptr, &size) + defer { _fixLifetime(data) } + return try body(UnsafePointer(ptr!)) + } + + public func enumerateBytes( + block: @noescape (buffer: UnsafeBufferPointer, byteIndex: Int, stop: inout Bool) -> Void) + { + _swift_dispatch_data_apply(__wrapped) { (data: __DispatchData, offset: Int, ptr: UnsafePointer, size: Int) in + let bp = UnsafeBufferPointer(start: UnsafePointer(ptr), count: size) + var stop = false + block(buffer: bp, byteIndex: offset, stop: &stop) + return !stop + } + } + + /// Append bytes to the data. + /// + /// - parameter bytes: A pointer to the bytes to copy in to the data. + /// - parameter count: The number of bytes to copy. + public mutating func append(_ bytes: UnsafePointer, count: Int) { + let data = __dispatch_data_create(bytes, count, nil, _dispatch_data_destructor_default()) + self.append(DispatchData(data: data)) + } + + /// Append data to the data. + /// + /// - parameter data: The data to append to this data. + public mutating func append(_ other: DispatchData) { + let data = __dispatch_data_create_concat(__wrapped, other as __DispatchData) + __wrapped = data + } + + /// Append a buffer of bytes to the data. + /// + /// - parameter buffer: The buffer of bytes to append. The size is calculated from `SourceType` and `buffer.count`. + public mutating func append(_ buffer : UnsafeBufferPointer) { + self.append(UnsafePointer(buffer.baseAddress!), count: buffer.count * sizeof(SourceType)) + } + + private func _copyBytesHelper(to pointer: UnsafeMutablePointer, from range: CountableRange) { + var copiedCount = 0 + __dispatch_data_apply(__wrapped) { (data: __DispatchData, offset: Int, ptr: UnsafePointer, size: Int) in + let limit = Swift.min((range.endIndex - range.startIndex) - copiedCount, size) + memcpy(pointer + copiedCount, ptr, limit) + copiedCount += limit + return copiedCount < (range.endIndex - range.startIndex) + } + } + + /// Copy the contents of the data to a pointer. + /// + /// - parameter pointer: A pointer to the buffer you wish to copy the bytes into. + /// - parameter count: The number of bytes to copy. + /// - warning: This method does not verify that the contents at pointer have enough space to hold `count` bytes. + public func copyBytes(to pointer: UnsafeMutablePointer, count: Int) { + _copyBytesHelper(to: pointer, from: 0.., from range: CountableRange) { + _copyBytesHelper(to: pointer, from: range) + } + + /// Copy the contents of the data into a buffer. + /// + /// This function copies the bytes in `range` from the data into the buffer. If the count of the `range` is greater than `sizeof(DestinationType) * buffer.count` then the first N bytes will be copied into the buffer. + /// - precondition: The range must be within the bounds of the data. Otherwise `fatalError` is called. + /// - parameter buffer: A buffer to copy the data into. + /// - parameter range: A range in the data to copy into the buffer. If the range is empty, this function will return 0 without copying anything. If the range is nil, as much data as will fit into `buffer` is copied. + /// - returns: Number of bytes copied into the destination buffer. + public func copyBytes(to buffer: UnsafeMutableBufferPointer, from range: CountableRange? = nil) -> Int { + let cnt = count + guard cnt > 0 else { return 0 } + + let copyRange : CountableRange + if let r = range { + guard !r.isEmpty else { return 0 } + precondition(r.startIndex >= 0) + precondition(r.startIndex < cnt, "The range is outside the bounds of the data") + + precondition(r.endIndex >= 0) + precondition(r.endIndex <= cnt, "The range is outside the bounds of the data") + + copyRange = r.startIndex..<(r.startIndex + Swift.min(buffer.count * sizeof(DestinationType), r.count)) + } else { + copyRange = 0.. = UnsafeMutablePointer(buffer.baseAddress!) + _copyBytesHelper(to: pointer, from: copyRange) + return copyRange.count + } + + /// Sets or returns the byte at the specified index. + public subscript(index: Index) -> UInt8 { + var offset = 0 + let subdata = __dispatch_data_copy_region(__wrapped, index, &offset) + + var ptr: UnsafePointer? = nil + var size = 0 + let map = __dispatch_data_create_map(subdata, &ptr, &size) + defer { _fixLifetime(map) } + + let pptr = UnsafePointer(ptr!) + return pptr[index - offset] + } + + public subscript(bounds: Range) -> RandomAccessSlice { + return RandomAccessSlice(base: self, bounds: bounds) + } + + /// Return a new copy of the data in a specified range. + /// + /// - parameter range: The range to copy. + public func subdata(in range: CountableRange) -> DispatchData { + let subrange = __dispatch_data_create_subrange( + __wrapped, range.startIndex, range.endIndex - range.startIndex) + return DispatchData(data: subrange) + } + + public func region(location: Int) -> (data: DispatchData, offset: Int) { + var offset: Int = 0 + let data = __dispatch_data_copy_region(__wrapped, location, &offset) + return (DispatchData(data: data), offset) + } + + public var startIndex: Index { + return 0 + } + + public var endIndex: Index { + return count + } + + public func index(before i: Index) -> Index { + return i - 1 + } + + public func index(after i: Index) -> Index { + return i + 1 + } + + /// An iterator over the contents of the data. + /// + /// The iterator will increment byte-by-byte. + public func makeIterator() -> DispatchData.Iterator { + return DispatchDataIterator(_data: self) + } +} + +public struct DispatchDataIterator : IteratorProtocol, Sequence { + + /// Create an iterator over the given DisaptchData + public init(_data: DispatchData) { + var ptr: UnsafePointer? + self._count = 0 + self._data = __dispatch_data_create_map( + _data as __DispatchData, &ptr, &self._count) + self._ptr = UnsafePointer(ptr!) + self._position = _data.startIndex + } + + /// Advance to the next element and return it, or `nil` if no next + /// element exists. + /// + /// - Precondition: No preceding call to `self.next()` has returned `nil`. + public mutating func next() -> DispatchData._Element? { + if _position == _count { return nil } + let element = _ptr[_position]; + _position = _position + 1 + return element + } + + internal let _data: __DispatchData + internal var _ptr: UnsafePointer + internal var _count: Int + internal var _position: DispatchData.Index +} + +extension DispatchData { + public static func _isBridgedToObjectiveC() -> Bool { + return true + } + + @_semantics("convertToObjectiveC") + public func _bridgeToObjectiveC() -> __DispatchData { + return unsafeBitCast(__wrapped, to: __DispatchData.self) + } + + public static func _forceBridgeFromObjectiveC(_ input: __DispatchData, result: inout DispatchData?) { + result = DispatchData(data: input) + } + + public static func _conditionallyBridgeFromObjectiveC(_ input: __DispatchData, result: inout DispatchData?) -> Bool { + result = DispatchData(data: input) + return true + } + + public static func _unconditionallyBridgeFromObjectiveC(_ source: __DispatchData?) -> DispatchData { + var result: DispatchData? = nil + _forceBridgeFromObjectiveC(source!, result: &result) + return result! + } +} + +typealias _swift_data_applier = @convention(block) @noescape (__DispatchData, Int, UnsafePointer, Int) -> Bool + +@_silgen_name("_swift_dispatch_data_apply") +internal func _swift_dispatch_data_apply(_ data: __DispatchData, _ block: _swift_data_applier) + +@_silgen_name("_swift_dispatch_data_empty") +internal func _swift_dispatch_data_empty() -> __DispatchData + +@_silgen_name("_swift_dispatch_data_destructor_free") +internal func _dispatch_data_destructor_free() -> _DispatchBlock + +@_silgen_name("_swift_dispatch_data_destructor_munmap") +internal func _dispatch_data_destructor_munmap() -> _DispatchBlock + +@_silgen_name("_swift_dispatch_data_destructor_default") +internal func _dispatch_data_destructor_default() -> _DispatchBlock diff --git a/src/swift/Dispatch.apinotes b/src/swift/Dispatch.apinotes new file mode 100644 index 000000000..6e804515a --- /dev/null +++ b/src/swift/Dispatch.apinotes @@ -0,0 +1,328 @@ +--- +Name: Dispatch +Typedefs: +- Name: dispatch_object_t + Availability: nonswift +- Name: dispatch_block_t + Availability: nonswift +- Name: dispatch_queue_t + Availability: nonswift +- Name: dispatch_semaphore_t + Availability: nonswift +- Name: dispatch_io_t + Availability: nonswift +- Name: dispatch_data_t + Availability: nonswift +- Name: dispatch_group_t + Availability: nonswift +- Name: dispatch_qos_class_t + Availability: nonswift +- Name: dispatch_data_applier_t + Availability: nonswift +- Name: dispatch_fd_t + Availability: nonswift +- Name: dispatch_io_handler_t + Availability: nonswift +- Name: dispatch_source_t + Availability: nonswift +- Name: dispatch_function_t + Availability: nonswift +- Name: dispatch_io_close_flags_t + Availability: nonswift +- Name: dispatch_io_interval_flags_t + Availability: nonswift +- Name: dispatch_io_type_t + Availability: nonswift +- Name: dispatch_source_timer_flags_t + Availability: nonswift +- Name: dispatch_autorelease_frequency_t + SwiftPrivate: true +- Name: dispatch_queue_attr_t + Availability: nonswift +- Name: dispatch_queue_priority_t + Availability: nonswift +- Name: dispatch_block_flags_t + SwiftPrivate: true +- Name: dispatch_source_type_t + SwiftPrivate: true +- Name: dispatch_source_mach_send_flags_t + Availability: nonswift +- Name: dispatch_source_memorypressure_flags_t + Availability: nonswift +- Name: dispatch_source_proc_flags_t + Availability: nonswift +- Name: dispatch_source_vnode_flags_t + Availability: nonswift +Classes: +- Name: OS_dispatch_object + SwiftName: DispatchObject +- Name: OS_dispatch_queue + SwiftName: DispatchQueue +- Name: OS_dispatch_io + SwiftName: DispatchIO +- Name: OS_dispatch_semaphore + SwiftName: DispatchSemaphore +- Name: OS_dispatch_group + SwiftName: DispatchGroup +- Name: OS_dispatch_source + SwiftName: DispatchSource +- Name: OS_dispatch_queue_attr + SwiftPrivate: true +- Name: OS_dispatch_data + SwiftName: __DispatchData +Protocols: +- Name: OS_dispatch_source + SwiftName: DispatchSourceType +- Name: OS_dispatch_source_mach_send + SwiftName: DispatchSourceMachSend +- Name: OS_dispatch_source_mach_recv + SwiftName: DispatchSourceMachReceive +- Name: OS_dispatch_source_memorypressure + SwiftName: DispatchSourceMemoryPressure +- Name: OS_dispatch_source_proc + SwiftName: DispatchSourceProcess +- Name: OS_dispatch_source_read + SwiftName: DispatchSourceRead +- Name: OS_dispatch_source_signal + SwiftName: DispatchSourceSignal +- Name: OS_dispatch_source_timer + SwiftName: DispatchSourceTimer +- Name: OS_dispatch_source_data_or + SwiftName: DispatchSourceUserDataOr +- Name: OS_dispatch_source_data_add + SwiftName: DispatchSourceUserDataAdd +- Name: OS_dispatch_source_vnode + SwiftName: DispatchSourceFileSystemObject +- Name: OS_dispatch_source_write + SwiftName: DispatchSourceWrite +Functions: +- Name: dispatch_release + Availability: nonswift +- Name: dispatch_retain + Availability: nonswift +# dispatch_queue_t +- Name: dispatch_queue_create + SwiftName: 'DispatchQueue.init(__label:attr:)' + SwiftPrivate: true +- Name: dispatch_get_global_queue + SwiftPrivate: true +- Name: dispatch_queue_create_with_target + SwiftName: 'DispatchQueue.init(__label:attr:queue:)' + SwiftPrivate: true +- Name: dispatch_assert_queue + SwiftPrivate: true +- Name: dispatch_assert_queue_barrier + SwiftPrivate: true +- Name: dispatch_assert_queue_not + SwiftPrivate: true +- Name: dispatch_async + SwiftPrivate: true +- Name: dispatch_async_f + Availability: nonswift +- Name: dispatch_barrier_async + SwiftPrivate: true +- Name: dispatch_barrier_async_f + Availability: nonswift +- Name: dispatch_apply + SwiftPrivate: true +- Name: dispatch_apply_f + Availability: nonswift +- Name: dispatch_sync + SwiftName: 'DispatchQueue.sync(self:execute:)' +- Name: dispatch_sync_f + Availability: nonswift +- Name: dispatch_barrier_sync + SwiftPrivate: true +- Name: dispatch_barrier_sync_f + Availability: nonswift +- Name: dispatch_queue_get_label + SwiftPrivate: true +- Name: dispatch_queue_get_qos_class + SwiftPrivate: true +- Name: dispatch_after + SwiftPrivate: true +- Name: dispatch_after_f + Availability: nonswift +- Name: dispatch_queue_get_specific + SwiftPrivate: true +- Name: dispatch_queue_set_specific + SwiftPrivate: true +- Name: dispatch_get_specific + SwiftPrivate: true +- Name: dispatch_get_main_queue + Availability: nonswift +- Name: dispatch_queue_attr_make_initially_inactive + SwiftPrivate: true +- Name: dispatch_queue_attr_make_with_autorelease_frequency + SwiftPrivate: true +- Name: dispatch_queue_attr_make_with_qos_class + SwiftPrivate: true +# dispatch_object_t +- Name: dispatch_set_target_queue + SwiftName: 'DispatchObject.setTarget(self:queue:)' +- Name: dispatch_activate + SwiftName: 'DispatchObject.activate(self:)' +- Name: dispatch_suspend + SwiftName: 'DispatchObject.suspend(self:)' +- Name: dispatch_resume + SwiftName: 'DispatchObject.resume(self:)' +- Name: dispatch_set_finalizer_f + Availability: nonswift +- Name: dispatch_get_context + Availability: nonswift +- Name: dispatch_set_context + Availability: nonswift +- Name: _dispatch_object_validate + Availability: nonswift +# dispatch_block +- Name: dispatch_block_create + Availability: nonswift + AvailabilityMsg: 'Use DispatchWorkItem()' +- Name: dispatch_block_create_with_qos_class + Availability: nonswift + AvailabilityMsg: 'Use DispatchWorkItem()' +- Name: dispatch_block_perform + Availability: nonswift + AvailabilityMsg: 'Use DispatchWorkItem.perform()' +- Name: dispatch_block_wait + Availability: nonswift + AvailabilityMsg: 'Use DispatchWorkItem.wait(timeout:)' +- Name: dispatch_block_notify + Availability: nonswift + AvailabilityMsg: 'Use DispatchWorkItem.notify(queue:execute:)' +- Name: dispatch_block_cancel + Availability: nonswift + AvailabilityMsg: 'Use DispatchWorkItem.cancel()' +- Name: dispatch_block_testcancel + Availability: nonswift + AvailabilityMsg: 'Use DispatchWorkItem.isCancelled' +# dispatch_data +- Name: dispatch_data_create + SwiftPrivate: true +- Name: dispatch_data_get_size + SwiftPrivate: true +- Name: dispatch_data_apply + SwiftPrivate: true +- Name: dispatch_data_create_concat + SwiftPrivate: true +- Name: dispatch_data_create_subrange + SwiftPrivate: true +- Name: dispatch_data_copy_region + SwiftPrivate: true +- Name: dispatch_data_create_map + SwiftPrivate: true +# dispatch_group_t +- Name: dispatch_group_create + SwiftName: 'DispatchGroup.init()' + Availability: available +- Name: dispatch_group_async + SwiftPrivate: true +- Name: dispatch_group_async_f + Availability: nonswift +- Name: dispatch_group_wait + SwiftPrivate: true +- Name: dispatch_group_notify + SwiftPrivate: true +- Name: dispatch_group_notify_f + Availability: nonswift +- Name: dispatch_group_enter + SwiftName: 'DispatchGroup.enter(self:)' +- Name: dispatch_group_leave + SwiftName: 'DispatchGroup.leave(self:)' +# dispatch_io +- Name: dispatch_io_create + SwiftPrivate: true + SwiftName: 'DispatchIO.init(__type:fd:queue:handler:)' +- Name: dispatch_io_create_with_path + SwiftPrivate: true + SwiftName: 'DispatchIO.init(__type:path:oflag:mode:queue:handler:)' +- Name: dispatch_io_create_with_io + SwiftPrivate: true + SwiftName: 'DispatchIO.init(__type:io:queue:handler:)' +- Name: dispatch_io_read + SwiftPrivate: true +- Name: dispatch_io_write + SwiftPrivate: true +- Name: dispatch_io_close + SwiftPrivate: true +- Name: dispatch_io_barrier + SwiftName: 'DispatchIO.barrier(self:execute:)' +- Name: dispatch_io_get_descriptor + SwiftName: 'getter:DispatchIO.fileDescriptor(self:)' +- Name: dispatch_io_set_high_water + SwiftName: 'DispatchIO.setLimit(self:highWater:)' +- Name: dispatch_io_set_low_water + SwiftName: 'DispatchIO.setLimit(self:lowWater:)' +- Name: dispatch_io_set_interval + SwiftPrivate: true +- Name: dispatch_read + SwiftPrivate: true +- Name: dispatch_write + SwiftPrivate: true +# dispatch_semaphore +- Name: dispatch_semaphore_create + SwiftName: 'DispatchSemaphore.init(value:)' +- Name: dispatch_semaphore_wait + SwiftPrivate: true +- Name: dispatch_semaphore_signal + SwiftPrivate: true +# dispatch_source +- Name: dispatch_source_create + SwiftPrivate: true +- Name: dispatch_source_get_handle + SwiftPrivate: true +- Name: dispatch_source_get_mask + SwiftPrivate: true +- Name: dispatch_source_get_data + SwiftPrivate: true +- Name: dispatch_source_merge_data + SwiftPrivate: true +- Name: dispatch_source_set_event_handler + SwiftPrivate: true +- Name: dispatch_source_set_event_handler_f + Availability: nonswift +- Name: dispatch_source_set_cancel_handler + SwiftPrivate: true +- Name: dispatch_source_set_cancel_handler_f + Availability: nonswift +- Name: dispatch_source_set_registration_handler + SwiftPrivate: true +- Name: dispatch_source_set_registration_handler_f + Availability: nonswift +- Name: dispatch_source_cancel + SwiftPrivate: true +- Name: dispatch_source_testcancel + SwiftPrivate: true +- Name: dispatch_source_set_timer + SwiftPrivate: true +# dispatch_time +- Name: dispatch_time + SwiftPrivate: true +- Name: dispatch_walltime + SwiftPrivate: true +- Name: dispatch_main + SwiftName: 'dispatchMain()' +Globals: +- Name: _dispatch_data_destructor_free + Availability: nonswift +- Name: _dispatch_data_destructor_munmap + Availability: nonswift +Enumerators: +- Name: DISPATCH_BLOCK_BARRIER + Availability: nonswift +- Name: DISPATCH_BLOCK_DETACHED + Availability: nonswift +- Name: DISPATCH_BLOCK_ASSIGN_CURRENT + Availability: nonswift +- Name: DISPATCH_BLOCK_NO_QOS_CLASS + Availability: nonswift +- Name: DISPATCH_BLOCK_INHERIT_QOS_CLASS + Availability: nonswift +- Name: DISPATCH_BLOCK_ENFORCE_QOS_CLASS + Availability: nonswift +- Name: DISPATCH_AUTORELEASE_FREQUENCY_INHERIT + Availability: nonswift +- Name: DISPATCH_AUTORELEASE_FREQUENCY_WORK_ITEM + Availability: nonswift +- Name: DISPATCH_AUTORELEASE_FREQUENCY_NEVER + Availability: nonswift diff --git a/src/swift/Dispatch.mm b/src/swift/Dispatch.mm new file mode 100644 index 000000000..b66a34e8b --- /dev/null +++ b/src/swift/Dispatch.mm @@ -0,0 +1,179 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See http://swift.org/LICENSE.txt for license information +// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +#include +#include +#include + +#define DISPATCH_RUNTIME_STDLIB_INTERFACE __attribute__((__visibility__("default"))) + +@protocol OS_dispatch_source; +@protocol OS_dispatch_source_mach_send; +@protocol OS_dispatch_source_mach_recv; +@protocol OS_dispatch_source_memorypressure; +@protocol OS_dispatch_source_proc; +@protocol OS_dispatch_source_read; +@protocol OS_dispatch_source_signal; +@protocol OS_dispatch_source_timer; +@protocol OS_dispatch_source_data_add; +@protocol OS_dispatch_source_data_or; +@protocol OS_dispatch_source_vnode; +@protocol OS_dispatch_source_write; + +// #include +__attribute__((constructor)) +static void _dispatch_overlay_constructor() { + Class source = objc_lookUpClass("OS_dispatch_source"); + if (source) { + class_addProtocol(source, @protocol(OS_dispatch_source)); + class_addProtocol(source, @protocol(OS_dispatch_source_mach_send)); + class_addProtocol(source, @protocol(OS_dispatch_source_mach_recv)); + class_addProtocol(source, @protocol(OS_dispatch_source_memorypressure)); + class_addProtocol(source, @protocol(OS_dispatch_source_proc)); + class_addProtocol(source, @protocol(OS_dispatch_source_read)); + class_addProtocol(source, @protocol(OS_dispatch_source_signal)); + class_addProtocol(source, @protocol(OS_dispatch_source_timer)); + class_addProtocol(source, @protocol(OS_dispatch_source_data_add)); + class_addProtocol(source, @protocol(OS_dispatch_source_data_or)); + class_addProtocol(source, @protocol(OS_dispatch_source_vnode)); + class_addProtocol(source, @protocol(OS_dispatch_source_write)); + } +} + +#include "swift/Runtime/Config.h" + +SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE +extern "C" dispatch_queue_attr_t +_swift_dispatch_queue_concurrent(void) { + return DISPATCH_QUEUE_CONCURRENT; +} + +SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE +extern "C" void +_swift_dispatch_apply_current(size_t iterations, __attribute__((__noescape__)) void (^block)(size_t)) { + dispatch_apply(iterations, (dispatch_queue_t _Nonnull)0, block); +} + +SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE +extern "C" dispatch_queue_t +_swift_dispatch_get_main_queue(void) { + return dispatch_get_main_queue(); +} + +SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE +extern "C" dispatch_data_t +_swift_dispatch_data_empty(void) { + return dispatch_data_empty; +} + +SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE +extern "C" dispatch_block_t +_swift_dispatch_data_destructor_default(void) { + return DISPATCH_DATA_DESTRUCTOR_DEFAULT; +} + +SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE +extern "C" dispatch_block_t +_swift_dispatch_data_destructor_free(void) { + return _dispatch_data_destructor_free; +} + +SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE +extern "C" dispatch_block_t +_swift_dispatch_data_destructor_munmap(void) { + return _dispatch_data_destructor_munmap; +} + +SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE +extern "C" dispatch_block_t +_swift_dispatch_block_create_with_qos_class(dispatch_block_flags_t flags, qos_class_t qos, int relative_priority, dispatch_block_t block) { + return dispatch_block_create_with_qos_class(flags, qos, relative_priority, block); +} + +SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE +extern "C" dispatch_block_t +_swift_dispatch_block_create_noescape(dispatch_block_flags_t flags, dispatch_block_t block) { + return dispatch_block_create(flags, block); +} + +SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE +extern "C" void +_swift_dispatch_block_cancel(dispatch_block_t block) { + dispatch_block_cancel(block); +} + +SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE +extern "C" long +_swift_dispatch_block_wait(dispatch_block_t block, dispatch_time_t timeout) { + return dispatch_block_wait(block, timeout); +} + +SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE +extern "C" void +_swift_dispatch_block_notify(dispatch_block_t block, dispatch_queue_t queue, dispatch_block_t notification_block) { + dispatch_block_notify(block, queue, notification_block); +} + +SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE +extern "C" long +_swift_dispatch_block_testcancel(dispatch_block_t block) { + return dispatch_block_testcancel(block); +} + +SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE +extern "C" bool +_swift_dispatch_data_apply(dispatch_data_t data, bool (^applier)(dispatch_data_t, size_t, const void *, size_t)) { + return dispatch_data_apply(data, applier); +} + +SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE +extern "C" void +_swift_dispatch_async(dispatch_queue_t queue, dispatch_block_t block) { + dispatch_async(queue, block); +} + +SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE +extern "C" void +_swift_dispatch_group_async(dispatch_group_t group, dispatch_queue_t queue, dispatch_block_t block) { + dispatch_group_async(group, queue, block); +} + +SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE +extern "C" void +_swift_dispatch_sync(dispatch_queue_t queue, dispatch_block_t block) { + dispatch_sync(queue, block); +} + +// DISPATCH_RUNTIME_STDLIB_INTERFACE +// extern "C" dispatch_queue_t +// _swift_apply_current_root_queue() { +// return DISPATCH_APPLY_CURRENT_ROOT_QUEUE; +// } + +#define SOURCE(t) \ + SWIFT_CC(swift) \ + DISPATCH_RUNTIME_STDLIB_INTERFACE extern "C" dispatch_source_type_t \ + _swift_dispatch_source_type_##t(void) { \ + return DISPATCH_SOURCE_TYPE_##t; \ + } + +SOURCE(DATA_ADD) +SOURCE(DATA_OR) +SOURCE(MACH_SEND) +SOURCE(MACH_RECV) +SOURCE(MEMORYPRESSURE) +SOURCE(PROC) +SOURCE(READ) +SOURCE(SIGNAL) +SOURCE(TIMER) +SOURCE(VNODE) +SOURCE(WRITE) diff --git a/src/swift/Dispatch.swift b/src/swift/Dispatch.swift index a5f88c1ff..4ed2ad9cd 100644 --- a/src/swift/Dispatch.swift +++ b/src/swift/Dispatch.swift @@ -12,157 +12,197 @@ @_exported import Dispatch -/// The type of blocks submitted to dispatch queues, which take no arguments -/// and have no return value. -/// -/// The dispatch_block_t typealias is different from usual closures in that it -/// uses @convention(block). This is to avoid unnecessary bridging between -/// C blocks and Swift closures, which interferes with Grand Central Dispatch -/// APIs that depend on the referential identity of a block. -public typealias dispatch_block_t = @convention(block) () -> Void - -//===----------------------------------------------------------------------===// -// Macros -// FIXME: rdar://16851050 update API so these import better -//===----------------------------------------------------------------------===// - -// dispatch/io.h -public var DISPATCH_IO_STREAM: dispatch_io_type_t { - return 0 -} -public var DISPATCH_IO_RANDOM: dispatch_io_type_t { - return 1 +/// dispatch_assert + +@available(OSX 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *) +public enum DispatchPredicate { + case onQueue(DispatchQueue) + case onQueueAsBarrier(DispatchQueue) + case notOnQueue(DispatchQueue) +} + +@available(OSX 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *) +public func _dispatchPreconditionTest(_ condition: DispatchPredicate) -> Bool { + switch condition { + case .onQueue(let q): + __dispatch_assert_queue(q) + case .onQueueAsBarrier(let q): + __dispatch_assert_queue_barrier(q) + case .notOnQueue(let q): + __dispatch_assert_queue_not(q) + } + return true } -public var DISPATCH_IO_STOP: dispatch_io_close_flags_t { - return 1 -} -public var DISPATCH_IO_STRICT_INTERVAL: dispatch_io_interval_flags_t { - return 1 +@_transparent +@available(OSX 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *) +public func dispatchPrecondition(condition: @autoclosure () -> DispatchPredicate) { + // precondition is able to determine release-vs-debug asserts where the overlay + // cannot, so formulating this into a call that we can call with precondition() + precondition(_dispatchPreconditionTest(condition()), "dispatchPrecondition failure") } -public var DISPATCH_QUEUE_SERIAL: dispatch_queue_attr_t! { - return nil -} -public var DISPATCH_CURRENT_QUEUE_LABEL: dispatch_queue_t! { - return nil -} -public var DISPATCH_TARGET_QUEUE_DEFAULT: dispatch_queue_t! { - return nil -} -public var DISPATCH_QUEUE_PRIORITY_HIGH: dispatch_queue_priority_t { - return 2 -} -public var DISPATCH_QUEUE_PRIORITY_DEFAULT: dispatch_queue_priority_t { - return 0 -} -public var DISPATCH_QUEUE_PRIORITY_LOW: dispatch_queue_priority_t { - return -2 -} -public var DISPATCH_QUEUE_PRIORITY_BACKGROUND: dispatch_queue_priority_t { - return -32768 -} +/// qos_class_t -/* -FIXME: LINUX_PORT: qos_class_t not being imported -@warn_unused_result -public func dispatch_get_global_queue(identifier: qos_class_t, - _ flags: UInt) -> dispatch_queue_t { - return dispatch_get_global_queue(Int(identifier.rawValue), flags) -} -*/ +public struct DispatchQoS : Equatable { + public let qosClass: QoSClass + public let relativePriority: Int -public var DISPATCH_QUEUE_CONCURRENT: dispatch_queue_attr_t { - return _swift_dispatch_queue_concurrent() -} + @available(OSX 10.10, iOS 8.0, *) + public static let background = DispatchQoS(qosClass: .background, relativePriority: 0) -@warn_unused_result -@_silgen_name("_swift_dispatch_queue_concurrent") -internal func _swift_dispatch_queue_concurrent() -> dispatch_queue_attr_t + @available(OSX 10.10, iOS 8.0, *) + public static let utility = DispatchQoS(qosClass: .utility, relativePriority: 0) -// dispatch/data.h -public var dispatch_data_empty: dispatch_data_t { - return _swift_dispatch_data_empty() -} + @available(OSX 10.10, iOS 8.0, *) + public static let `default` = DispatchQoS(qosClass: .default, relativePriority: 0) -@warn_unused_result -@_silgen_name("_swift_dispatch_data_empty") -internal func _swift_dispatch_data_empty() -> dispatch_data_t + @available(OSX, introduced: 10.10, deprecated: 10.10, renamed: "DispatchQoS.default") + @available(iOS, introduced: 8.0, deprecated: 8.0, renamed: "DispatchQoS.default") + @available(*, deprecated, renamed: "DispatchQoS.default") + public static let defaultQoS = DispatchQoS.default -// dispatch/source.h -// FIXME: DISPATCH_SOURCE_TYPE_* -public var DISPATCH_PROC_EXIT: dispatch_source_proc_flags_t { - return 0x80000000 -} -public var DISPATCH_PROC_FORK: dispatch_source_proc_flags_t { return 0x40000000 } -public var DISPATCH_PROC_EXEC: dispatch_source_proc_flags_t { return 0x20000000 } -public var DISPATCH_PROC_SIGNAL: dispatch_source_proc_flags_t { return 0x08000000 } -public var DISPATCH_VNODE_DELETE: dispatch_source_vnode_flags_t { return 0x1 } -public var DISPATCH_VNODE_WRITE: dispatch_source_vnode_flags_t { return 0x2 } -public var DISPATCH_VNODE_EXTEND: dispatch_source_vnode_flags_t { return 0x4 } -public var DISPATCH_VNODE_ATTRIB: dispatch_source_vnode_flags_t { return 0x8 } -public var DISPATCH_VNODE_LINK: dispatch_source_vnode_flags_t { return 0x10 } -public var DISPATCH_VNODE_RENAME: dispatch_source_vnode_flags_t { return 0x20 } -public var DISPATCH_VNODE_REVOKE: dispatch_source_vnode_flags_t { return 0x40 } -public var DISPATCH_TIMER_STRICT: dispatch_source_timer_flags_t { return 1 } - -public var DISPATCH_SOURCE_TYPE_DATA_ADD: dispatch_source_type_t { - return _swift_dispatch_source_type_data_add() -} -public var DISPATCH_SOURCE_TYPE_DATA_OR: dispatch_source_type_t { - return _swift_dispatch_source_type_data_or() -} -public var DISPATCH_SOURCE_TYPE_READ: dispatch_source_type_t { - return _swift_dispatch_source_type_read() -} -public var DISPATCH_SOURCE_TYPE_PROC: dispatch_source_type_t { - return _swift_dispatch_source_type_proc() -} -public var DISPATCH_SOURCE_TYPE_SIGNAL: dispatch_source_type_t { - return _swift_dispatch_source_type_signal() -} -public var DISPATCH_SOURCE_TYPE_TIMER: dispatch_source_type_t { - return _swift_dispatch_source_type_timer() -} -public var DISPATCH_SOURCE_TYPE_VNODE: dispatch_source_type_t { - return _swift_dispatch_source_type_vnode() -} -public var DISPATCH_SOURCE_TYPE_WRITE: dispatch_source_type_t { - return _swift_dispatch_source_type_write() + @available(OSX 10.10, iOS 8.0, *) + public static let userInitiated = DispatchQoS(qosClass: .userInitiated, relativePriority: 0) + + @available(OSX 10.10, iOS 8.0, *) + public static let userInteractive = DispatchQoS(qosClass: .userInteractive, relativePriority: 0) + + public static let unspecified = DispatchQoS(qosClass: .unspecified, relativePriority: 0) + + public enum QoSClass { + @available(OSX 10.10, iOS 8.0, *) + case background + + @available(OSX 10.10, iOS 8.0, *) + case utility + + @available(OSX 10.10, iOS 8.0, *) + case `default` + + @available(OSX, introduced: 10.10, deprecated: 10.10, renamed: "QoSClass.default") + @available(iOS, introduced: 8.0, deprecated: 8.0, renamed: "QoSClass.default") + @available(*, deprecated, renamed: "QoSClass.default") + static let defaultQoS = QoSClass.default + + @available(OSX 10.10, iOS 8.0, *) + case userInitiated + + @available(OSX 10.10, iOS 8.0, *) + case userInteractive + + case unspecified + + @available(OSX 10.10, iOS 8.0, *) + internal init?(qosClass: qos_class_t) { + switch qosClass { + case QOS_CLASS_BACKGROUND: self = .background + case QOS_CLASS_UTILITY: self = .utility + case QOS_CLASS_DEFAULT: self = .default + case QOS_CLASS_USER_INITIATED: self = .userInitiated + case QOS_CLASS_USER_INTERACTIVE: self = .userInteractive + case QOS_CLASS_UNSPECIFIED: self = .unspecified + default: return nil + } + } + + @available(OSX 10.10, iOS 8.0, *) + internal var rawValue: qos_class_t { + switch self { + case .background: return QOS_CLASS_BACKGROUND + case .utility: return QOS_CLASS_UTILITY + case .default: return QOS_CLASS_DEFAULT + case .userInitiated: return QOS_CLASS_USER_INITIATED + case .userInteractive: return QOS_CLASS_USER_INTERACTIVE + case .unspecified: return QOS_CLASS_UNSPECIFIED + } + } + } + + public init(qosClass: QoSClass, relativePriority: Int) { + self.qosClass = qosClass + self.relativePriority = relativePriority + } } -@warn_unused_result -@_silgen_name("_swift_dispatch_source_type_DATA_ADD") -internal func _swift_dispatch_source_type_data_add() -> dispatch_source_type_t +public func ==(a: DispatchQoS, b: DispatchQoS) -> Bool { + return a.qosClass == b.qosClass && a.relativePriority == b.relativePriority +} -@warn_unused_result -@_silgen_name("_swift_dispatch_source_type_DATA_OR") -internal func _swift_dispatch_source_type_data_or() -> dispatch_source_type_t +/// -@warn_unused_result -@_silgen_name("_swift_dispatch_source_type_PROC") -internal func _swift_dispatch_source_type_proc() -> dispatch_source_type_t +public enum DispatchTimeoutResult { + case Success + case TimedOut +} -@warn_unused_result -@_silgen_name("_swift_dispatch_source_type_READ") -internal func _swift_dispatch_source_type_read() -> dispatch_source_type_t +/// dispatch_group -@warn_unused_result -@_silgen_name("_swift_dispatch_source_type_SIGNAL") -internal func _swift_dispatch_source_type_signal() -> dispatch_source_type_t +public extension DispatchGroup { + public func notify(qos: DispatchQoS = .unspecified, flags: DispatchWorkItemFlags = [], queue: DispatchQueue, execute work: @convention(block) () -> ()) { + if #available(OSX 10.10, iOS 8.0, *), qos != .unspecified || !flags.isEmpty { + let item = DispatchWorkItem(qos: qos, flags: flags, block: work) + __dispatch_group_notify(self, queue, item._block) + } else { + __dispatch_group_notify(self, queue, work) + } + } -@warn_unused_result -@_silgen_name("_swift_dispatch_source_type_TIMER") -internal func _swift_dispatch_source_type_timer() -> dispatch_source_type_t + @available(OSX 10.10, iOS 8.0, *) + public func notify(queue: DispatchQueue, work: DispatchWorkItem) { + __dispatch_group_notify(self, queue, work._block) + } -@warn_unused_result -@_silgen_name("_swift_dispatch_source_type_VNODE") -internal func _swift_dispatch_source_type_vnode() -> dispatch_source_type_t + public func wait() { + _ = __dispatch_group_wait(self, DispatchTime.distantFuture.rawValue) + } -@warn_unused_result -@_silgen_name("_swift_dispatch_source_type_WRITE") -internal func _swift_dispatch_source_type_write() -> dispatch_source_type_t + public func wait(timeout: DispatchTime) -> DispatchTimeoutResult { + return __dispatch_group_wait(self, timeout.rawValue) == 0 ? .Success : .TimedOut + } -// dispatch/time.h -// DISPATCH_TIME_NOW: ok -// DISPATCH_TIME_FOREVER: ok + public func wait(wallTimeout timeout: DispatchWallTime) -> DispatchTimeoutResult { + return __dispatch_group_wait(self, timeout.rawValue) == 0 ? .Success : .TimedOut + } +} + +public extension DispatchGroup { + @available(*, deprecated, renamed: "DispatchGroup.wait(self:wallTimeout:)") + public func wait(walltime timeout: DispatchWallTime) -> Int { + switch wait(wallTimeout: timeout) { + case .Success: return 0 + case .TimedOut: return Int(KERN_OPERATION_TIMED_OUT) + } + } +} + +/// dispatch_semaphore + +public extension DispatchSemaphore { + @discardableResult + public func signal() -> Int { + return __dispatch_semaphore_signal(self) + } + + public func wait() { + _ = __dispatch_semaphore_wait(self, DispatchTime.distantFuture.rawValue) + } + + public func wait(timeout: DispatchTime) -> DispatchTimeoutResult { + return __dispatch_semaphore_wait(self, timeout.rawValue) == 0 ? .Success : .TimedOut + } + + public func wait(wallTimeout: DispatchWallTime) -> DispatchTimeoutResult { + return __dispatch_semaphore_wait(self, wallTimeout.rawValue) == 0 ? .Success : .TimedOut + } +} + +public extension DispatchSemaphore { + @available(*, deprecated, renamed: "DispatchSemaphore.wait(self:wallTimeout:)") + public func wait(walltime timeout: DispatchWalltime) -> Int { + switch wait(wallTimeout: timeout) { + case .Success: return 0 + case .TimedOut: return Int(KERN_OPERATION_TIMED_OUT) + } + } +} diff --git a/src/swift/IO.swift b/src/swift/IO.swift new file mode 100644 index 000000000..049f54f3c --- /dev/null +++ b/src/swift/IO.swift @@ -0,0 +1,127 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See http://swift.org/LICENSE.txt for license information +// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +public extension DispatchIO { + + public enum StreamType : UInt { + case stream = 0 + case random = 1 + } + + public struct CloseFlags : OptionSet, RawRepresentable { + public let rawValue: UInt + public init(rawValue: UInt) { self.rawValue = rawValue } + + public static let stop = CloseFlags(rawValue: 1) + } + + public struct IntervalFlags : OptionSet, RawRepresentable { + public let rawValue: UInt + public init(rawValue: UInt) { self.rawValue = rawValue } + public init(nilLiteral: ()) { self.rawValue = 0 } + + public static let strictInterval = IntervalFlags(rawValue: 1) + } + + public class func read(fromFileDescriptor: Int32, maxLength: Int, runningHandlerOn queue: DispatchQueue, handler: (data: DispatchData, error: Int32) -> Void) { + __dispatch_read(fromFileDescriptor, maxLength, queue) { (data: __DispatchData, error: Int32) in + handler(data: DispatchData(data: data), error: error) + } + } + + public class func write(fromFileDescriptor: Int32, data: DispatchData, runningHandlerOn queue: DispatchQueue, handler: (data: DispatchData?, error: Int32) -> Void) { + __dispatch_write(fromFileDescriptor, data as __DispatchData, queue) { (data: __DispatchData?, error: Int32) in + handler(data: data.flatMap { DispatchData(data: $0) }, error: error) + } + } + + public convenience init( + type: StreamType, + fileDescriptor: Int32, + queue: DispatchQueue, + cleanupHandler: (error: Int32) -> Void) + { + self.init(__type: type.rawValue, fd: fileDescriptor, queue: queue, handler: cleanupHandler) + } + + public convenience init( + type: StreamType, + path: UnsafePointer, + oflag: Int32, + mode: mode_t, + queue: DispatchQueue, + cleanupHandler: (error: Int32) -> Void) + { + self.init(__type: type.rawValue, path: path, oflag: oflag, mode: mode, queue: queue, handler: cleanupHandler) + } + + public convenience init( + type: StreamType, + io: DispatchIO, + queue: DispatchQueue, + cleanupHandler: (error: Int32) -> Void) + { + self.init(__type: type.rawValue, io: io, queue: queue, handler: cleanupHandler) + } + + public func read(offset: off_t, length: Int, queue: DispatchQueue, ioHandler: (done: Bool, data: DispatchData?, error: Int32) -> Void) { + __dispatch_io_read(self, offset, length, queue) { (done: Bool, data: __DispatchData?, error: Int32) in + ioHandler(done: done, data: data.flatMap { DispatchData(data: $0) }, error: error) + } + } + + public func write(offset: off_t, data: DispatchData, queue: DispatchQueue, ioHandler: (done: Bool, data: DispatchData?, error: Int32) -> Void) { + __dispatch_io_write(self, offset, data as __DispatchData, queue) { (done: Bool, data: __DispatchData?, error: Int32) in + ioHandler(done: done, data: data.flatMap { DispatchData(data: $0) }, error: error) + } + } + + public func setInterval(interval: DispatchTimeInterval, flags: IntervalFlags = []) { + __dispatch_io_set_interval(self, interval.rawValue, flags.rawValue) + } + + public func close(flags: CloseFlags = []) { + __dispatch_io_close(self, flags.rawValue) + } +} + +extension DispatchIO { + @available(*, deprecated, renamed: "DispatchIO.read(fromFileDescriptor:maxLength:runningHandlerOn:handler:)") + public class func read(fd: Int32, length: Int, queue: DispatchQueue, handler: (DispatchData, Int32) -> Void) { + DispatchIO.read(fromFileDescriptor: fd, maxLength: length, runningHandlerOn: queue, handler: handler) + } + + @available(*, deprecated, renamed: "DispatchIO.write(fromFileDescriptor:data:runningHandlerOn:handler:)") + public class func write(fd: Int32, data: DispatchData, queue: DispatchQueue, handler: (DispatchData?, Int32) -> Void) { + DispatchIO.write(fromFileDescriptor: fd, data: data, runningHandlerOn: queue, handler: handler) + } + + @available(*, deprecated, renamed: "DispatchIO.barrier(self:execute:)") + public func withBarrier(barrier work: () -> ()) { + barrier(execute: work) + } + + @available(*, deprecated, renamed: "DispatchIO.setLimit(self:highWater:)") + public func setHighWater(highWater: Int) { + setLimit(highWater: highWater) + } + + @available(*, deprecated, renamed: "DispatchIO.setLimit(self:lowWater:)") + public func setLowWater(lowWater: Int) { + setLimit(lowWater: lowWater) + } + + @available(*, deprecated, renamed: "DispatchIO.setInterval(self:interval:flags:)") + public func setInterval(interval: UInt64, flags: IntervalFlags) { + setInterval(interval: .nanoseconds(Int(interval)), flags: flags) + } +} diff --git a/src/swift/Private.swift b/src/swift/Private.swift new file mode 100644 index 000000000..3a0cdb630 --- /dev/null +++ b/src/swift/Private.swift @@ -0,0 +1,472 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See http://swift.org/LICENSE.txt for license information +// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +// Redeclarations of all SwiftPrivate functions with appropriate markup. + +@available(*, unavailable, renamed:"DispatchQueue.init(label:attributes:target:)") +public func dispatch_queue_create(_ label: UnsafePointer?, _ attr: __OS_dispatch_queue_attr?) -> DispatchQueue +{ + fatalError() +} + +@available(*, unavailable, renamed:"DispatchQueue.init(label:attributes:target:)") +public func dispatch_queue_create_with_target(_ label: UnsafePointer?, _ attr: __OS_dispatch_queue_attr?, _ queue: DispatchQueue?) -> DispatchQueue +{ + fatalError() +} + +@available(*, unavailable, renamed:"DispatchIO.init(type:fileDescriptor:queue:cleanupHandler:)") +public func dispatch_io_create(_ type: UInt, _ fd: Int32, _ queue: DispatchQueue, _ cleanup_handler: (Int32) -> Void) -> DispatchIO +{ + fatalError() +} + +@available(*, unavailable, renamed:"DispatchIO.init(type:path:oflag:mode:queue:cleanupHandler:)") +public func dispatch_io_create_with_path(_ type: UInt, _ path: UnsafePointer, _ oflag: Int32, _ mode: mode_t, _ queue: DispatchQueue, _ cleanup_handler: (Int32) -> Void) -> DispatchIO +{ + fatalError() +} + +@available(*, unavailable, renamed:"DispatchIO.init(type:io:queue:cleanupHandler:)") +public func dispatch_io_create_with_io(_ type: UInt, _ io: DispatchIO, _ queue: DispatchQueue, _ cleanup_handler: (Int32) -> Void) -> DispatchIO +{ + fatalError() +} + +@available(*, unavailable, renamed:"DispatchIO.read(fileDescriptor:length:queue:handler:)") +public func dispatch_read(_ fd: Int32, _ length: Int, _ queue: DispatchQueue, _ handler: (__DispatchData, Int32) -> Void) +{ + fatalError() +} + +@available(*, unavailable, renamed:"DispatchIO.read(self:offset:length:queue:ioHandler:)") +func dispatch_io_read(_ channel: DispatchIO, _ offset: off_t, _ length: Int, _ queue: DispatchQueue, _ io_handler: (Bool, __DispatchData?, Int32) -> Void) +{ + fatalError() +} + +@available(*, unavailable, renamed:"DispatchIO.write(self:offset:data:queue:ioHandler:)") +func dispatch_io_write(_ channel: DispatchIO, _ offset: off_t, _ data: __DispatchData, _ queue: DispatchQueue, _ io_handler: (Bool, __DispatchData?, Int32) -> Void) +{ + fatalError() +} + +@available(*, unavailable, renamed:"DispatchIO.write(fileDescriptor:data:queue:handler:)") +func dispatch_write(_ fd: Int32, _ data: __DispatchData, _ queue: DispatchQueue, _ handler: (__DispatchData?, Int32) -> Void) +{ + fatalError() +} + +@available(*, unavailable, renamed:"DispatchData.init(bytes:)") +public func dispatch_data_create(_ buffer: UnsafePointer, _ size: Int, _ queue: DispatchQueue?, _ destructor: (() -> Void)?) -> __DispatchData +{ + fatalError() +} + +@available(*, unavailable, renamed:"getter:DispatchData.count(self:)") +public func dispatch_data_get_size(_ data: __DispatchData) -> Int +{ + fatalError() +} + +@available(*, unavailable, renamed:"DispatchData.withUnsafeBytes(self:body:)") +public func dispatch_data_create_map(_ data: __DispatchData, _ buffer_ptr: UnsafeMutablePointer?>?, _ size_ptr: UnsafeMutablePointer?) -> __DispatchData +{ + fatalError() +} + +@available(*, unavailable, renamed:"DispatchData.append(self:_:)") +public func dispatch_data_create_concat(_ data1: __DispatchData, _ data2: __DispatchData) -> __DispatchData +{ + fatalError() +} + +@available(*, unavailable, renamed:"DispatchData.subdata(self:in:)") +public func dispatch_data_create_subrange(_ data: __DispatchData, _ offset: Int, _ length: Int) -> __DispatchData +{ + fatalError() +} + +@available(*, unavailable, renamed:"DispatchData.enumerateBytes(self:block:)") +public func dispatch_data_apply(_ data: __DispatchData, _ applier: (__DispatchData, Int, UnsafePointer, Int) -> Bool) -> Bool +{ + fatalError() +} + +@available(*, unavailable, renamed:"DispatchData.region(self:location:)") +public func dispatch_data_copy_region(_ data: __DispatchData, _ location: Int, _ offset_ptr: UnsafeMutablePointer) -> __DispatchData +{ + fatalError() +} + +@available(*, unavailable, renamed:"DispatchQueue.asynchronously(self:group:qos:flags:execute:)") +public func dispatch_group_async(_ group: DispatchGroup, _ queue: DispatchQueue, _ block: () -> Void) +{ + fatalError() +} + +@available(*, unavailable, renamed: "DispatchGroup.notify(self:qos:flags:queue:execute:)") +public func dispatch_group_notify(_ group: DispatchGroup, _ queue: DispatchQueue, _ block: () -> Void) +{ + fatalError() +} + +@available(*, unavailable, renamed:"DispatchGroup.wait(self:timeout:)") +public func dispatch_group_wait(_ group: DispatchGroup, _ timeout: dispatch_time_t) -> Int +{ + fatalError() +} + +@available(*, unavailable, renamed:"DispatchIO.close(self:flags:)") +public func dispatch_io_close(_ channel: DispatchIO, _ flags: UInt) +{ + fatalError() +} + +@available(*, unavailable, renamed:"DispatchIO.setInterval(self:interval:flags:)") +public func dispatch_io_set_interval(_ channel: DispatchIO, _ interval: UInt64, _ flags: UInt) +{ + fatalError() +} + +@available(*, unavailable, renamed:"DispatchQueue.apply(attributes:iterations:execute:)") +public func dispatch_apply(_ iterations: Int, _ queue: DispatchQueue, _ block: @noescape (Int) -> Void) +{ + fatalError() +} + +@available(*, unavailable, renamed:"DispatchQueue.asynchronously(self:execute:)") +public func dispatch_async(_ queue: DispatchQueue, _ block: () -> Void) +{ + fatalError() +} + +@available(*, unavailable, renamed:"DispatchQueue.global(attributes:)") +public func dispatch_get_global_queue(_ identifier: Int, _ flags: UInt) -> DispatchQueue +{ + fatalError() +} + +@available(*, unavailable, renamed: "DispatchQueue.main") +public func dispatch_get_main_queue() -> DispatchQueue +{ + fatalError() +} + +@available(*, unavailable, renamed:"DispatchQueueAttributes.initiallyInactive") +public func dispatch_queue_attr_make_initially_inactive(_ attr: __OS_dispatch_queue_attr?) -> __OS_dispatch_queue_attr +{ + fatalError() +} + +@available(*, unavailable, renamed:"DispatchQueueAttributes.autoreleaseWorkItem") +public func dispatch_queue_attr_make_with_autorelease_frequency(_ attr: __OS_dispatch_queue_attr?, _ frequency: __dispatch_autorelease_frequency_t) -> __OS_dispatch_queue_attr +{ + fatalError() +} + +@available(*, unavailable, renamed:"DispatchQueueAttributes.qosUserInitiated") +public func dispatch_queue_attr_make_with_qos_class(_ attr: __OS_dispatch_queue_attr?, _ qos_class: qos_class_t, _ relative_priority: Int32) -> __OS_dispatch_queue_attr +{ + fatalError() +} + +@available(*, unavailable, renamed:"getter:DispatchQueue.label(self:)") +public func dispatch_queue_get_label(_ queue: DispatchQueue?) -> UnsafePointer +{ + fatalError() +} + +@available(*, unavailable, renamed:"getter:DispatchQueue.qos(self:)") +public func dispatch_queue_get_qos_class(_ queue: DispatchQueue, _ relative_priority_ptr: UnsafeMutablePointer?) -> qos_class_t +{ + fatalError() +} + +@available(*, unavailable, renamed:"DispatchQueue.after(self:when:execute:)") +public func dispatch_after(_ when: dispatch_time_t, _ queue: DispatchQueue, _ block: () -> Void) +{ + fatalError() +} + +@available(*, unavailable, renamed:"DispatchQueue.asynchronously(self:group:qos:flags:execute:)") +public func dispatch_barrier_async(_ queue: DispatchQueue, _ block: () -> Void) +{ + fatalError() +} + +@available(*, unavailable, renamed:"DispatchQueue.synchronously(self:flags:execute:)") +public func dispatch_barrier_sync(_ queue: DispatchQueue, _ block: @noescape () -> Void) +{ + fatalError() +} + +@available(*, unavailable, renamed:"DispatchQueue.setSpecific(self:key:value:)") +public func dispatch_queue_set_specific(_ queue: DispatchQueue, _ key: UnsafePointer, _ context: UnsafeMutablePointer?, _ destructor: (@convention(c) (UnsafeMutablePointer?) -> Void)?) +{ + fatalError() +} + +@available(*, unavailable, renamed:"DispatchQueue.getSpecific(self:key:)") +public func dispatch_queue_get_specific(_ queue: DispatchQueue, _ key: UnsafePointer) -> UnsafeMutablePointer? +{ + fatalError() +} + +@available(*, unavailable, renamed:"DispatchQueue.getSpecific(key:)") +public func dispatch_get_specific(_ key: UnsafePointer) -> UnsafeMutablePointer? +{ + fatalError() +} + +@available(*, unavailable, renamed:"dispatchPrecondition(_:)") +public func dispatch_assert_queue(_ queue: DispatchQueue) +{ + fatalError() +} + +@available(*, unavailable, renamed:"dispatchPrecondition(_:)") +public func dispatch_assert_queue_barrier(_ queue: DispatchQueue) +{ + fatalError() +} + +@available(*, unavailable, renamed:"dispatchPrecondition(_:)") +public func dispatch_assert_queue_not(_ queue: DispatchQueue) +{ + fatalError() +} + +@available(*, unavailable, renamed:"DispatchSemaphore.wait(self:timeout:)") +public func dispatch_semaphore_wait(_ dsema: DispatchSemaphore, _ timeout: dispatch_time_t) -> Int +{ + fatalError() +} + +@available(*, unavailable, renamed: "DispatchSemaphore.signal(self:)") +public func dispatch_semaphore_signal(_ dsema: DispatchSemaphore) -> Int +{ + fatalError() +} + +@available(*, unavailable, message:"Use DispatchSource class methods") +public func dispatch_source_create(_ type: __dispatch_source_type_t, _ handle: UInt, _ mask: UInt, _ queue: DispatchQueue?) -> DispatchSource +{ + fatalError() +} + +@available(*, unavailable, renamed:"DispatchSource.setEventHandler(self:handler:)") +public func dispatch_source_set_event_handler(_ source: DispatchSource, _ handler: (() -> Void)?) +{ + fatalError() +} + +@available(*, unavailable, renamed:"DispatchSource.setCancelHandler(self:handler:)") +public func dispatch_source_set_cancel_handler(_ source: DispatchSource, _ handler: (() -> Void)?) +{ + fatalError() +} + +@available(*, unavailable, renamed:"DispatchSource.cancel(self:)") +public func dispatch_source_cancel(_ source: DispatchSource) +{ + fatalError() +} + +@available(*, unavailable, renamed:"getter:DispatchSource.isCancelled(self:)") +public func dispatch_source_testcancel(_ source: DispatchSource) -> Int +{ + fatalError() +} + +@available(*, unavailable, renamed:"getter:DispatchSource.handle(self:)") +public func dispatch_source_get_handle(_ source: DispatchSource) -> UInt +{ + fatalError() +} + +@available(*, unavailable, renamed:"getter:DispatchSource.mask(self:)") +public func dispatch_source_get_mask(_ source: DispatchSource) -> UInt +{ + fatalError() +} + +@available(*, unavailable, renamed:"getter:DispatchSource.data(self:)") +public func dispatch_source_get_data(_ source: DispatchSource) -> UInt +{ + fatalError() +} + +@available(*, unavailable, renamed:"DispatchUserDataAdd.mergeData(self:value:)") +public func dispatch_source_merge_data(_ source: DispatchSource, _ value: UInt) +{ + fatalError() +} + +@available(*, unavailable, renamed:"DispatchTimerSource.setTimer(self:start:interval:leeway:)") +public func dispatch_source_set_timer(_ source: DispatchSource, _ start: dispatch_time_t, _ interval: UInt64, _ leeway: UInt64) +{ + fatalError() +} + +@available(*, unavailable, renamed:"DispatchSource.setRegistrationHandler(self:handler:)") +public func dispatch_source_set_registration_handler(_ source: DispatchSource, _ handler: (() -> Void)?) +{ + fatalError() +} + +@available(*, unavailable, renamed:"DispatchTime.now()") +public func dispatch_time(_ when: dispatch_time_t, _ delta: Int64) -> dispatch_time_t +{ + fatalError() +} + +@available(*, unavailable, renamed:"DispatchWalltime.init(time:)") +public func dispatch_walltime(_ when: UnsafePointer?, _ delta: Int64) -> dispatch_time_t +{ + fatalError() +} + +@available(*, unavailable, renamed: "DispatchQueue.GlobalAttributes.qosUserInitiated") +public var DISPATCH_QUEUE_PRIORITY_HIGH: Int { + fatalError() +} + +@available(*, unavailable, renamed: "DispatchQueue.GlobalAttributes.qosDefault") +public var DISPATCH_QUEUE_PRIORITY_DEFAULT: Int { + fatalError() +} + +@available(*, unavailable, renamed: "DispatchQueue.GlobalAttributes.qosUtility") +public var DISPATCH_QUEUE_PRIORITY_LOW: Int { + fatalError() +} + +@available(*, unavailable, renamed: "DispatchQueue.GlobalAttributes.qosBackground") +public var DISPATCH_QUEUE_PRIORITY_BACKGROUND: Int { + fatalError() +} + +@available(*, unavailable, renamed: "DispatchIO.StreamType.stream") +public var DISPATCH_IO_STREAM: Int { + fatalError() +} + +@available(*, unavailable, renamed: "DispatchIO.StreamType.random") +public var DISPATCH_IO_RANDOM: Int { + fatalError() +} + +@available(*, unavailable, renamed: "DispatchIO.CloseFlags.stop") +public var DISPATCH_IO_STOP: Int { + fatalError() +} + +@available(*, unavailable, renamed: "DispatchIO.IntervalFlags.strictInterval") +public var DISPATCH_IO_STRICT_INTERVAL: Int { + fatalError() +} + +@available(*, unavailable, renamed: "DispatchSource.MachSendEvent.dead") +public var DISPATCH_MACH_SEND_DEAD: Int { + fatalError() +} + +@available(*, unavailable, renamed: "DispatchSource.MemoryPressureEvent.normal") +public var DISPATCH_MEMORYPRESSURE_NORMAL: Int { + fatalError() +} + +@available(*, unavailable, renamed: "DispatchSource.MemoryPressureEvent.warning") +public var DISPATCH_MEMORYPRESSURE_WARN: Int { + fatalError() +} + +@available(*, unavailable, renamed: "DispatchSource.MemoryPressureEvent.critical") +public var DISPATCH_MEMORYPRESSURE_CRITICAL: Int { + fatalError() +} + +@available(*, unavailable, renamed: "DispatchSource.ProcessEvent.exit") +public var DISPATCH_PROC_EXIT: Int { + fatalError() +} + +@available(*, unavailable, renamed: "DispatchSource.ProcessEvent.fork") +public var DISPATCH_PROC_FORK: Int { + fatalError() +} + +@available(*, unavailable, renamed: "DispatchSource.ProcessEvent.exec") +public var DISPATCH_PROC_EXEC: Int { + fatalError() +} + +@available(*, unavailable, renamed: "DispatchSource.ProcessEvent.signal") +public var DISPATCH_PROC_SIGNAL: Int { + fatalError() +} + +@available(*, unavailable, renamed: "DispatchSource.TimerFlags.strict") +public var DISPATCH_TIMER_STRICT: Int { + fatalError() +} + +@available(*, unavailable, renamed: "DispatchSource.FileSystemEvent.delete") +public var DISPATCH_VNODE_DELETE: Int { + fatalError() +} + +@available(*, unavailable, renamed: "DispatchSource.FileSystemEvent.write") +public var DISPATCH_VNODE_WRITE: Int { + fatalError() +} + +@available(*, unavailable, renamed: "DispatchSource.FileSystemEvent.extend") +public var DISPATCH_VNODE_EXTEND: Int { + fatalError() +} + +@available(*, unavailable, renamed: "DispatchSource.FileSystemEvent.attrib") +public var DISPATCH_VNODE_ATTRIB: Int { + fatalError() +} + +@available(*, unavailable, renamed: "DispatchSource.FileSystemEvent.link") +public var DISPATCH_VNODE_LINK: Int { + fatalError() +} + +@available(*, unavailable, renamed: "DispatchSource.FileSystemEvent.rename") +public var DISPATCH_VNODE_RENAME: Int { + fatalError() +} + +@available(*, unavailable, renamed: "DispatchSource.FileSystemEvent.revoke") +public var DISPATCH_VNODE_REVOKE: Int { + fatalError() +} + +@available(*, unavailable, renamed: "DispatchSource.FileSystemEvent.funlock") +public var DISPATCH_VNODE_FUNLOCK: Int { + fatalError() +} + +@available(*, unavailable, renamed: "DispatchTime.now()") +public var DISPATCH_TIME_NOW: Int { + fatalError() +} + +@available(*, unavailable, renamed: "DispatchTime.distantFuture") +public var DISPATCH_TIME_FOREVER: Int { + fatalError() +} diff --git a/src/swift/Queue.swift b/src/swift/Queue.swift new file mode 100644 index 000000000..6f7b541e9 --- /dev/null +++ b/src/swift/Queue.swift @@ -0,0 +1,429 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See http://swift.org/LICENSE.txt for license information +// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +// dispatch/queue.h + +public struct DispatchQueueAttributes : OptionSet { + public let rawValue: UInt64 + public init(rawValue: UInt64) { self.rawValue = rawValue } + + public static let serial = DispatchQueueAttributes(rawValue: 0<<0) + public static let concurrent = DispatchQueueAttributes(rawValue: 1<<1) + + @available(OSX 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *) + public static let initiallyInactive = DispatchQueueAttributes(rawValue: 1<<2) + + @available(OSX 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *) + public static let autoreleaseInherit = DispatchQueueAttributes(rawValue: 1<<3) + + @available(OSX 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *) + public static let autoreleaseWorkItem = DispatchQueueAttributes(rawValue: 1<<4) + + @available(OSX 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *) + public static let autoreleaseNever = DispatchQueueAttributes(rawValue: 1<<5) + + @available(OSX 10.10, iOS 8.0, *) + public static let qosUserInteractive = DispatchQueueAttributes(rawValue: 1<<6) + + @available(OSX 10.10, iOS 8.0, *) + public static let qosUserInitiated = DispatchQueueAttributes(rawValue: 1<<7) + + @available(OSX 10.10, iOS 8.0, *) + public static let qosDefault = DispatchQueueAttributes(rawValue: 1<<8) + + @available(OSX 10.10, iOS 8.0, *) + public static let qosUtility = DispatchQueueAttributes(rawValue: 1<<9) + + @available(OSX 10.10, iOS 8.0, *) + public static let qosBackground = DispatchQueueAttributes(rawValue: 1<<10) + + @available(*, deprecated, message: ".noQoS has no effect, it should not be used") + public static let noQoS = DispatchQueueAttributes(rawValue: 1<<11) + + private var attr: __OS_dispatch_queue_attr? { + var attr: __OS_dispatch_queue_attr? + + if self.contains(.concurrent) { + attr = _swift_dispatch_queue_concurrent() + } + if #available(OSX 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *) { + if self.contains(.initiallyInactive) { + attr = __dispatch_queue_attr_make_initially_inactive(attr) + } + if self.contains(.autoreleaseWorkItem) { + // DISPATCH_AUTORELEASE_FREQUENCY_WORK_ITEM + attr = __dispatch_queue_attr_make_with_autorelease_frequency(attr, __dispatch_autorelease_frequency_t(1)) + } else if self.contains(.autoreleaseInherit) { + // DISPATCH_AUTORELEASE_FREQUENCY_INHERIT + attr = __dispatch_queue_attr_make_with_autorelease_frequency(attr, __dispatch_autorelease_frequency_t(0)) + } else if self.contains(.autoreleaseNever) { + // DISPATCH_AUTORELEASE_FREQUENCY_NEVER + attr = __dispatch_queue_attr_make_with_autorelease_frequency(attr, __dispatch_autorelease_frequency_t(2)) + } + } + if #available(OSX 10.10, iOS 8.0, *) { + if self.contains(.qosUserInteractive) { + attr = __dispatch_queue_attr_make_with_qos_class(attr, QOS_CLASS_USER_INTERACTIVE, 0) + } else if self.contains(.qosUserInitiated) { + attr = __dispatch_queue_attr_make_with_qos_class(attr, QOS_CLASS_USER_INITIATED, 0) + } else if self.contains(.qosDefault) { + attr = __dispatch_queue_attr_make_with_qos_class(attr, QOS_CLASS_DEFAULT, 0) + } else if self.contains(.qosUtility) { + attr = __dispatch_queue_attr_make_with_qos_class(attr, QOS_CLASS_UTILITY, 0) + } else if self.contains(.qosBackground) { + attr = __dispatch_queue_attr_make_with_qos_class(attr, QOS_CLASS_BACKGROUND, 0) + } + } + return attr + } +} + + +public final class DispatchSpecificKey { + public init() {} +} + +internal class _DispatchSpecificValue { + internal let value: T + internal init(value: T) { self.value = value } +} + +public extension DispatchQueue { + + public struct GlobalAttributes : OptionSet { + public let rawValue: UInt64 + public init(rawValue: UInt64) { self.rawValue = rawValue } + + @available(OSX 10.10, iOS 8.0, *) + public static let qosUserInteractive = GlobalAttributes(rawValue: 1<<0) + + @available(OSX 10.10, iOS 8.0, *) + public static let qosUserInitiated = GlobalAttributes(rawValue: 1<<1) + + @available(OSX 10.10, iOS 8.0, *) + public static let qosDefault = GlobalAttributes(rawValue: 1<<2) + + @available(OSX 10.10, iOS 8.0, *) + public static let qosUtility = GlobalAttributes(rawValue: 1<<3) + + @available(OSX 10.10, iOS 8.0, *) + public static let qosBackground = GlobalAttributes(rawValue: 1<<4) + + // Avoid using our own deprecated constants here by declaring + // non-deprecated constants and then basing the public ones on those. + internal static let _priorityHigh = GlobalAttributes(rawValue: 1<<5) + internal static let _priorityDefault = GlobalAttributes(rawValue: 1<<6) + internal static let _priorityLow = GlobalAttributes(rawValue: 1<<7) + internal static let _priorityBackground = GlobalAttributes(rawValue: 1<<8) + + @available(OSX, deprecated: 10.10, message: "Use qos attributes instead") + @available(*, deprecated: 8.0, message: "Use qos attributes instead") + public static let priorityHigh = _priorityHigh + + @available(OSX, deprecated: 10.10, message: "Use qos attributes instead") + @available(*, deprecated: 8.0, message: "Use qos attributes instead") + public static let priorityDefault = _priorityDefault + + @available(OSX, deprecated: 10.10, message: "Use qos attributes instead") + @available(*, deprecated: 8.0, message: "Use qos attributes instead") + public static let priorityLow = _priorityLow + + @available(OSX, deprecated: 10.10, message: "Use qos attributes instead") + @available(*, deprecated: 8.0, message: "Use qos attributes instead") + public static let priorityBackground = _priorityBackground + + internal var _translatedValue: Int { + if #available(OSX 10.10, iOS 8.0, *) { + if self.contains(.qosUserInteractive) { return Int(QOS_CLASS_USER_INTERACTIVE.rawValue) } + else if self.contains(.qosUserInitiated) { return Int(QOS_CLASS_USER_INITIATED.rawValue) } + else if self.contains(.qosDefault) { return Int(QOS_CLASS_DEFAULT.rawValue) } + else if self.contains(.qosUtility) { return Int(QOS_CLASS_UTILITY.rawValue) } + else { return Int(QOS_CLASS_BACKGROUND.rawValue) } + } + if self.contains(._priorityHigh) { return 2 } // DISPATCH_QUEUE_PRIORITY_HIGH + else if self.contains(._priorityDefault) { return 0 } // DISPATCH_QUEUE_PRIORITY_DEFAULT + else if self.contains(._priorityLow) { return -2 } // // DISPATCH_QUEUE_PRIORITY_LOW + else if self.contains(._priorityBackground) { return Int(Int16.min) } // // DISPATCH_QUEUE_PRIORITY_BACKGROUND + return 0 + } + } + + public class func concurrentPerform(iterations: Int, execute work: @noescape (Int) -> Void) { + _swift_dispatch_apply_current(iterations, work) + } + + public class var main: DispatchQueue { + return _swift_dispatch_get_main_queue() + } + + public class func global(attributes: GlobalAttributes = []) -> DispatchQueue { + return __dispatch_get_global_queue(attributes._translatedValue, 0) + } + + public class func getSpecific(key: DispatchSpecificKey) -> T? { + let k = Unmanaged.passUnretained(key).toOpaque() + if let p = __dispatch_get_specific(k) { + let v = Unmanaged<_DispatchSpecificValue> + .fromOpaque(p) + .takeUnretainedValue() + return v.value + } + return nil + } + + public convenience init( + label: String, + attributes: DispatchQueueAttributes = .serial, + target: DispatchQueue? = nil) + { + if #available(OSX 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *) { + self.init(__label: label, attr: attributes.attr, queue: target) + } else { + self.init(__label: label, attr: attributes.attr) + if let tq = target { self.setTarget(queue: tq) } + } + } + + public var label: String { + return String(validatingUTF8: __dispatch_queue_get_label(self))! + } + + @available(OSX 10.10, iOS 8.0, *) + public func sync(execute workItem: DispatchWorkItem) { + // _swift_dispatch_sync preserves the @convention(block) for + // work item blocks. + _swift_dispatch_sync(self, workItem._block) + } + + @available(OSX 10.10, iOS 8.0, *) + public func async(execute workItem: DispatchWorkItem) { + // _swift_dispatch_{group,}_async preserves the @convention(block) + // for work item blocks. + if let g = workItem._group { + _swift_dispatch_group_async(g, self, workItem._block) + } else { + _swift_dispatch_async(self, workItem._block) + } + } + + public func async(group: DispatchGroup? = nil, qos: DispatchQoS = .unspecified, flags: DispatchWorkItemFlags = [], execute work: @convention(block) () -> Void) { + if group == nil && qos == .unspecified && flags.isEmpty { + // Fast-path route for the most common API usage + __dispatch_async(self, work) + return + } + + if #available(OSX 10.10, iOS 8.0, *), (qos != .unspecified || !flags.isEmpty) { + let workItem = DispatchWorkItem(qos: qos, flags: flags, block: work) + if let g = group { + _swift_dispatch_group_async(g, self, workItem._block) + } else { + _swift_dispatch_async(self, workItem._block) + } + } else { + if let g = group { + __dispatch_group_async(g, self, work) + } else { + __dispatch_async(self, work) + } + } + } + + private func _syncBarrier(block: @noescape () -> ()) { + __dispatch_barrier_sync(self, block) + } + + private func _syncHelper( + fn: (@noescape () -> ()) -> (), + execute work: @noescape () throws -> T, + rescue: ((ErrorProtocol) throws -> (T))) rethrows -> T + { + var result: T? + var error: ErrorProtocol? + fn { + do { + result = try work() + } catch let e { + error = e + } + } + if let e = error { + return try rescue(e) + } else { + return result! + } + } + + @available(OSX 10.10, iOS 8.0, *) + private func _syncHelper( + fn: (DispatchWorkItem) -> (), + flags: DispatchWorkItemFlags, + execute work: @noescape () throws -> T, + rescue: ((ErrorProtocol) throws -> (T))) rethrows -> T + { + var result: T? + var error: ErrorProtocol? + let workItem = DispatchWorkItem(flags: flags, noescapeBlock: { + do { + result = try work() + } catch let e { + error = e + } + }) + fn(workItem) + if let e = error { + return try rescue(e) + } else { + return result! + } + } + + public func sync(execute work: @noescape () throws -> T) rethrows -> T { + return try self._syncHelper(fn: sync, execute: work, rescue: { throw $0 }) + } + + public func sync(flags: DispatchWorkItemFlags, execute work: @noescape () throws -> T) rethrows -> T { + if flags == .barrier { + return try self._syncHelper(fn: _syncBarrier, execute: work, rescue: { throw $0 }) + } else if #available(OSX 10.10, iOS 8.0, *), !flags.isEmpty { + return try self._syncHelper(fn: sync, flags: flags, execute: work, rescue: { throw $0 }) + } else { + return try self._syncHelper(fn: sync, execute: work, rescue: { throw $0 }) + } + } + + public func after(when: DispatchTime, qos: DispatchQoS = .unspecified, flags: DispatchWorkItemFlags = [], execute work: @convention(block) () -> Void) { + if #available(OSX 10.10, iOS 8.0, *), qos != .unspecified || !flags.isEmpty { + let item = DispatchWorkItem(qos: qos, flags: flags, block: work) + __dispatch_after(when.rawValue, self, item._block) + } else { + __dispatch_after(when.rawValue, self, work) + } + } + + @available(OSX 10.10, iOS 8.0, *) + public func after(when: DispatchTime, execute: DispatchWorkItem) { + __dispatch_after(when.rawValue, self, execute._block) + } + + public func after(walltime when: DispatchWallTime, qos: DispatchQoS = .unspecified, flags: DispatchWorkItemFlags = [], execute work: @convention(block) () -> Void) { + if #available(OSX 10.10, iOS 8.0, *), qos != .unspecified || !flags.isEmpty { + let item = DispatchWorkItem(qos: qos, flags: flags, block: work) + __dispatch_after(when.rawValue, self, item._block) + } else { + __dispatch_after(when.rawValue, self, work) + } + } + + @available(OSX 10.10, iOS 8.0, *) + public func after(walltime when: DispatchWallTime, execute: DispatchWorkItem) { + __dispatch_after(when.rawValue, self, execute._block) + } + + @available(OSX 10.10, iOS 8.0, *) + public var qos: DispatchQoS { + var relPri: Int32 = 0 + let cls = DispatchQoS.QoSClass(qosClass: __dispatch_queue_get_qos_class(self, &relPri))! + return DispatchQoS(qosClass: cls, relativePriority: Int(relPri)) + } + + public func getSpecific(key: DispatchSpecificKey) -> T? { + let k = Unmanaged.passUnretained(key).toOpaque() + if let p = __dispatch_queue_get_specific(self, k) { + let v = Unmanaged<_DispatchSpecificValue> + .fromOpaque(p) + .takeUnretainedValue() + return v.value + } + return nil + } + + public func setSpecific(key: DispatchSpecificKey, value: T) { + let v = _DispatchSpecificValue(value: value) + let k = Unmanaged.passUnretained(key).toOpaque() + let p = Unmanaged.passRetained(v).toOpaque() + __dispatch_queue_set_specific(self, k, p, _destructDispatchSpecificValue) + } +} + +extension DispatchQueue { + @available(*, deprecated, renamed: "DispatchQueue.sync(self:execute:)") + public func synchronously(execute work: @noescape () -> ()) { + sync(execute: work) + } + + @available(OSX, introduced: 10.10, deprecated: 10.12, renamed: "DispatchQueue.sync(self:execute:)") + @available(iOS, introduced: 8.0, deprecated: 10.0, renamed: "DispatchQueue.sync(self:execute:)") + @available(*, deprecated, renamed: "DispatchQueue.sync(self:execute:)") + public func synchronously(execute workItem: DispatchWorkItem) { + sync(execute: workItem) + } + + @available(OSX, introduced: 10.10, deprecated: 10.12, renamed: "DispatchQueue.async(self:execute:)") + @available(iOS, introduced: 8.0, deprecated: 10.0, renamed: "DispatchQueue.async(self:execute:)") + @available(*, deprecated, renamed: "DispatchQueue.async(self:execute:)") + public func asynchronously(execute workItem: DispatchWorkItem) { + async(execute: workItem) + } + + @available(*, deprecated, renamed: "DispatchQueue.async(self:group:qos:flags:execute:)") + public func asynchronously(group: DispatchGroup? = nil, qos: DispatchQoS = .unspecified, flags: DispatchWorkItemFlags = [], execute work: @convention(block) () -> Void) { + async(group: group, qos: qos, flags: flags, execute: work) + } + + @available(*, deprecated, renamed: "DispatchQueue.sync(self:execute:)") + public func synchronously(execute work: @noescape () throws -> T) rethrows -> T { + return try sync(execute: work) + } + + @available(*, deprecated, renamed: "DispatchQueue.sync(self:flags:execute:)") + public func synchronously(flags: DispatchWorkItemFlags, execute work: @noescape () throws -> T) rethrows -> T { + return try sync(flags: flags, execute: work) + } + + @available(*, deprecated, renamed: "DispatchQueue.concurrentPerform(iterations:execute:)") + public func apply(applier iterations: Int, execute block: @noescape (Int) -> Void) { + DispatchQueue.concurrentPerform(iterations: iterations, execute: block) + } + + @available(*, deprecated, renamed: "DispatchQueue.setTarget(self:queue:)") + public func setTargetQueue(queue: DispatchQueue) { + self.setTarget(queue: queue) + } +} + +private func _destructDispatchSpecificValue(ptr: UnsafeMutablePointer?) { + if let p = ptr { + Unmanaged.fromOpaque(p).release() + } +} + +@_silgen_name("_swift_dispatch_queue_concurrent") +internal func _swift_dispatch_queue_concurrent() -> __OS_dispatch_queue_attr + +@_silgen_name("_swift_dispatch_get_main_queue") +internal func _swift_dispatch_get_main_queue() -> DispatchQueue + +@_silgen_name("_swift_dispatch_apply_current_root_queue") +internal func _swift_dispatch_apply_current_root_queue() -> DispatchQueue + +@_silgen_name("_swift_dispatch_async") +internal func _swift_dispatch_async(_ queue: DispatchQueue, _ block: _DispatchBlock) + +@_silgen_name("_swift_dispatch_group_async") +internal func _swift_dispatch_group_async(_ group: DispatchGroup, _ queue: DispatchQueue, _ block: _DispatchBlock) + +@_silgen_name("_swift_dispatch_sync") +internal func _swift_dispatch_sync(_ queue: DispatchQueue, _ block: _DispatchBlock) + +@_silgen_name("_swift_dispatch_apply_current") +internal func _swift_dispatch_apply_current(_ iterations: Int, _ block: @convention(block) @noescape (Int) -> Void) diff --git a/src/swift/Source.swift b/src/swift/Source.swift new file mode 100644 index 000000000..6ea3960f0 --- /dev/null +++ b/src/swift/Source.swift @@ -0,0 +1,389 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See http://swift.org/LICENSE.txt for license information +// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +// import Foundation + +public extension DispatchSourceType { + typealias DispatchSourceHandler = @convention(block) () -> Void + + public func setEventHandler(qos: DispatchQoS = .unspecified, flags: DispatchWorkItemFlags = [], handler: DispatchSourceHandler?) { + if #available(OSX 10.10, iOS 8.0, *), let h = handler where qos != .unspecified || !flags.isEmpty { + let item = DispatchWorkItem(qos: qos, flags: flags, block: h) + __dispatch_source_set_event_handler(self as! DispatchSource, item._block) + } else { + __dispatch_source_set_event_handler(self as! DispatchSource, handler) + } + } + + @available(OSX 10.10, iOS 8.0, *) + public func setEventHandler(handler: DispatchWorkItem) { + __dispatch_source_set_event_handler(self as! DispatchSource, handler._block) + } + + public func setCancelHandler(qos: DispatchQoS = .unspecified, flags: DispatchWorkItemFlags = [], handler: DispatchSourceHandler?) { + if #available(OSX 10.10, iOS 8.0, *), let h = handler where qos != .unspecified || !flags.isEmpty { + let item = DispatchWorkItem(qos: qos, flags: flags, block: h) + __dispatch_source_set_cancel_handler(self as! DispatchSource, item._block) + } else { + __dispatch_source_set_cancel_handler(self as! DispatchSource, handler) + } + } + + @available(OSX 10.10, iOS 8.0, *) + public func setCancelHandler(handler: DispatchWorkItem) { + __dispatch_source_set_cancel_handler(self as! DispatchSource, handler._block) + } + + public func setRegistrationHandler(qos: DispatchQoS = .unspecified, flags: DispatchWorkItemFlags = [], handler: DispatchSourceHandler?) { + if #available(OSX 10.10, iOS 8.0, *), let h = handler where qos != .unspecified || !flags.isEmpty { + let item = DispatchWorkItem(qos: qos, flags: flags, block: h) + __dispatch_source_set_registration_handler(self as! DispatchSource, item._block) + } else { + __dispatch_source_set_registration_handler(self as! DispatchSource, handler) + } + } + + @available(OSX 10.10, iOS 8.0, *) + public func setRegistrationHandler(handler: DispatchWorkItem) { + __dispatch_source_set_registration_handler(self as! DispatchSource, handler._block) + } + + @available(OSX 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *) + public func activate() { + (self as! DispatchSource).activate() + } + + public func cancel() { + __dispatch_source_cancel(self as! DispatchSource) + } + + public func resume() { + (self as! DispatchSource).resume() + } + + public func suspend() { + (self as! DispatchSource).suspend() + } + + public var handle: UInt { + return __dispatch_source_get_handle(self as! DispatchSource) + } + + public var mask: UInt { + return __dispatch_source_get_mask(self as! DispatchSource) + } + + public var data: UInt { + return __dispatch_source_get_data(self as! DispatchSource) + } + + public var isCancelled: Bool { + return __dispatch_source_testcancel(self as! DispatchSource) != 0 + } +} + +public extension DispatchSource { + public struct MachSendEvent : OptionSet, RawRepresentable { + public let rawValue: UInt + public init(rawValue: UInt) { self.rawValue = rawValue } + + public static let dead = MachSendEvent(rawValue: 0x1) + } + + public struct MemoryPressureEvent : OptionSet, RawRepresentable { + public let rawValue: UInt + public init(rawValue: UInt) { self.rawValue = rawValue } + + public static let normal = MemoryPressureEvent(rawValue: 0x1) + public static let warning = MemoryPressureEvent(rawValue: 0x2) + public static let critical = MemoryPressureEvent(rawValue: 0x4) + public static let all: MemoryPressureEvent = [.normal, .warning, .critical] + } + + public struct ProcessEvent : OptionSet, RawRepresentable { + public let rawValue: UInt + public init(rawValue: UInt) { self.rawValue = rawValue } + + public static let exit = ProcessEvent(rawValue: 0x80000000) + public static let fork = ProcessEvent(rawValue: 0x40000000) + public static let exec = ProcessEvent(rawValue: 0x20000000) + public static let signal = ProcessEvent(rawValue: 0x08000000) + public static let all: ProcessEvent = [.exit, .fork, .exec, .signal] + } + + public struct TimerFlags : OptionSet, RawRepresentable { + public let rawValue: UInt + public init(rawValue: UInt) { self.rawValue = rawValue } + + public static let strict = TimerFlags(rawValue: 1) + } + + public struct FileSystemEvent : OptionSet, RawRepresentable { + public let rawValue: UInt + public init(rawValue: UInt) { self.rawValue = rawValue } + + public static let delete = FileSystemEvent(rawValue: 0x1) + public static let write = FileSystemEvent(rawValue: 0x2) + public static let extend = FileSystemEvent(rawValue: 0x4) + public static let attrib = FileSystemEvent(rawValue: 0x8) + public static let link = FileSystemEvent(rawValue: 0x10) + public static let rename = FileSystemEvent(rawValue: 0x20) + public static let revoke = FileSystemEvent(rawValue: 0x40) + public static let funlock = FileSystemEvent(rawValue: 0x100) + + public static let all: FileSystemEvent = [ + .delete, .write, .extend, .attrib, .link, .rename, .revoke] + } + + public class func machSend(port: mach_port_t, eventMask: MachSendEvent, queue: DispatchQueue? = nil) -> DispatchSourceMachSend { + return __dispatch_source_create( + _swift_dispatch_source_type_mach_send(), UInt(port), eventMask.rawValue, queue) as DispatchSourceMachSend + } + + public class func machReceive(port: mach_port_t, queue: DispatchQueue? = nil) -> DispatchSourceMachReceive { + return __dispatch_source_create( + _swift_dispatch_source_type_mach_recv(), UInt(port), 0, queue) as DispatchSourceMachReceive + } + + public class func memoryPressure(eventMask: MemoryPressureEvent, queue: DispatchQueue? = nil) -> DispatchSourceMemoryPressure { + return __dispatch_source_create( + _swift_dispatch_source_type_memorypressure(), 0, eventMask.rawValue, queue) as DispatchSourceMemoryPressure + } + + public class func process(identifier: pid_t, eventMask: ProcessEvent, queue: DispatchQueue? = nil) -> DispatchSourceProcess { + return __dispatch_source_create( + _swift_dispatch_source_type_proc(), UInt(identifier), eventMask.rawValue, queue) as DispatchSourceProcess + } + + public class func read(fileDescriptor: Int32, queue: DispatchQueue? = nil) -> DispatchSourceRead { + return __dispatch_source_create( + _swift_dispatch_source_type_read(), UInt(fileDescriptor), 0, queue) as DispatchSourceRead + } + + public class func signal(signal: Int32, queue: DispatchQueue? = nil) -> DispatchSourceSignal { + return __dispatch_source_create( + _swift_dispatch_source_type_read(), UInt(signal), 0, queue) as DispatchSourceSignal + } + + public class func timer(flags: TimerFlags = [], queue: DispatchQueue? = nil) -> DispatchSourceTimer { + return __dispatch_source_create(_swift_dispatch_source_type_timer(), 0, flags.rawValue, queue) as DispatchSourceTimer + } + + public class func userDataAdd(queue: DispatchQueue? = nil) -> DispatchSourceUserDataAdd { + return __dispatch_source_create(_swift_dispatch_source_type_data_add(), 0, 0, queue) as DispatchSourceUserDataAdd + } + + public class func userDataOr(queue: DispatchQueue? = nil) -> DispatchSourceUserDataOr { + return __dispatch_source_create(_swift_dispatch_source_type_data_or(), 0, 0, queue) as DispatchSourceUserDataOr + } + + public class func fileSystemObject(fileDescriptor: Int32, eventMask: FileSystemEvent, queue: DispatchQueue? = nil) -> DispatchSourceFileSystemObject { + return __dispatch_source_create( + _swift_dispatch_source_type_vnode(), UInt(fileDescriptor), eventMask.rawValue, queue) as DispatchSourceFileSystemObject + } + + public class func write(fileDescriptor: Int32, queue: DispatchQueue? = nil) -> DispatchSourceWrite { + return __dispatch_source_create( + _swift_dispatch_source_type_write(), UInt(fileDescriptor), 0, queue) as DispatchSourceWrite + } +} + +public extension DispatchSourceMachSend { + public var handle: mach_port_t { + return mach_port_t(__dispatch_source_get_handle(self as! DispatchSource)) + } + + public var data: DispatchSource.MachSendEvent { + let data = __dispatch_source_get_data(self as! DispatchSource) + return DispatchSource.MachSendEvent(rawValue: data) + } + + public var mask: DispatchSource.MachSendEvent { + let mask = __dispatch_source_get_mask(self as! DispatchSource) + return DispatchSource.MachSendEvent(rawValue: mask) + } +} + +public extension DispatchSourceMachReceive { + public var handle: mach_port_t { + return mach_port_t(__dispatch_source_get_handle(self as! DispatchSource)) + } +} + +public extension DispatchSourceMemoryPressure { + public var data: DispatchSource.MemoryPressureEvent { + let data = __dispatch_source_get_data(self as! DispatchSource) + return DispatchSource.MemoryPressureEvent(rawValue: data) + } + + public var mask: DispatchSource.MemoryPressureEvent { + let mask = __dispatch_source_get_mask(self as! DispatchSource) + return DispatchSource.MemoryPressureEvent(rawValue: mask) + } +} + +public extension DispatchSourceProcess { + public var handle: pid_t { + return pid_t(__dispatch_source_get_handle(self as! DispatchSource)) + } + + public var data: DispatchSource.ProcessEvent { + let data = __dispatch_source_get_data(self as! DispatchSource) + return DispatchSource.ProcessEvent(rawValue: data) + } + + public var mask: DispatchSource.ProcessEvent { + let mask = __dispatch_source_get_mask(self as! DispatchSource) + return DispatchSource.ProcessEvent(rawValue: mask) + } +} + +public extension DispatchSourceTimer { + public func scheduleOneshot(deadline: DispatchTime, leeway: DispatchTimeInterval = .nanoseconds(0)) { + __dispatch_source_set_timer(self as! DispatchSource, deadline.rawValue, ~0, UInt64(leeway.rawValue)) + } + + public func scheduleOneshot(wallDeadline: DispatchWallTime, leeway: DispatchTimeInterval = .nanoseconds(0)) { + __dispatch_source_set_timer(self as! DispatchSource, wallDeadline.rawValue, ~0, UInt64(leeway.rawValue)) + } + + public func scheduleRepeating(deadline: DispatchTime, interval: DispatchTimeInterval, leeway: DispatchTimeInterval = .nanoseconds(0)) { + __dispatch_source_set_timer(self as! DispatchSource, deadline.rawValue, interval.rawValue, UInt64(leeway.rawValue)) + } + + public func scheduleRepeating(deadline: DispatchTime, interval: Double, leeway: DispatchTimeInterval = .nanoseconds(0)) { + __dispatch_source_set_timer(self as! DispatchSource, deadline.rawValue, UInt64(interval * Double(NSEC_PER_SEC)), UInt64(leeway.rawValue)) + } + + public func scheduleRepeating(wallDeadline: DispatchWallTime, interval: DispatchTimeInterval, leeway: DispatchTimeInterval = .nanoseconds(0)) { + __dispatch_source_set_timer(self as! DispatchSource, wallDeadline.rawValue, interval.rawValue, UInt64(leeway.rawValue)) + } + + public func scheduleRepeating(wallDeadline: DispatchWallTime, interval: Double, leeway: DispatchTimeInterval = .nanoseconds(0)) { + __dispatch_source_set_timer(self as! DispatchSource, wallDeadline.rawValue, UInt64(interval * Double(NSEC_PER_SEC)), UInt64(leeway.rawValue)) + } +} + +public extension DispatchSourceTimer { + @available(*, deprecated, renamed: "DispatchSourceTimer.scheduleOneshot(self:deadline:leeway:)") + public func setTimer(start: DispatchTime, leeway: DispatchTimeInterval = .nanoseconds(0)) { + scheduleOneshot(deadline: start, leeway: leeway) + } + + @available(*, deprecated, renamed: "DispatchSourceTimer.scheduleOneshot(self:wallDeadline:leeway:)") + public func setTimer(walltime start: DispatchWallTime, leeway: DispatchTimeInterval = .nanoseconds(0)) { + scheduleOneshot(wallDeadline: start, leeway: leeway) + } + + @available(*, deprecated, renamed: "DispatchSourceTimer.scheduleRepeating(self:deadline:interval:leeway:)") + public func setTimer(start: DispatchTime, interval: DispatchTimeInterval, leeway: DispatchTimeInterval = .nanoseconds(0)) { + scheduleRepeating(deadline: start, interval: interval, leeway: leeway) + } + + @available(*, deprecated, renamed: "DispatchSourceTimer.scheduleRepeating(self:deadline:interval:leeway:)") + public func setTimer(start: DispatchTime, interval: Double, leeway: DispatchTimeInterval = .nanoseconds(0)) { + scheduleRepeating(deadline: start, interval: interval, leeway: leeway) + } + + @available(*, deprecated, renamed: "DispatchSourceTimer.scheduleRepeating(self:wallDeadline:interval:leeway:)") + public func setTimer(walltime start: DispatchWallTime, interval: DispatchTimeInterval, leeway: DispatchTimeInterval = .nanoseconds(0)) { + scheduleRepeating(wallDeadline: start, interval: interval, leeway: leeway) + } + + @available(*, deprecated, renamed: "DispatchSourceTimer.scheduleRepeating(self:wallDeadline:interval:leeway:)") + public func setTimer(walltime start: DispatchWalltime, interval: Double, leeway: DispatchTimeInterval = .nanoseconds(0)) { + scheduleRepeating(wallDeadline: start, interval: interval, leeway: leeway) + } +} + +public extension DispatchSourceFileSystemObject { + public var handle: Int32 { + return Int32(__dispatch_source_get_handle(self as! DispatchSource)) + } + + public var data: DispatchSource.FileSystemEvent { + let data = __dispatch_source_get_data(self as! DispatchSource) + return DispatchSource.FileSystemEvent(rawValue: data) + } + + public var mask: DispatchSource.FileSystemEvent { + let data = __dispatch_source_get_mask(self as! DispatchSource) + return DispatchSource.FileSystemEvent(rawValue: data) + } +} + +public extension DispatchSourceUserDataAdd { + /// @function mergeData + /// + /// @abstract + /// Merges data into a dispatch source of type DISPATCH_SOURCE_TYPE_DATA_ADD or + /// DISPATCH_SOURCE_TYPE_DATA_OR and submits its event handler block to its + /// target queue. + /// + /// @param value + /// The value to coalesce with the pending data using a logical OR or an ADD + /// as specified by the dispatch source type. A value of zero has no effect + /// and will not result in the submission of the event handler block. + public func mergeData(value: UInt) { + __dispatch_source_merge_data(self as! DispatchSource, value) + } +} + +public extension DispatchSourceUserDataOr { + /// @function mergeData + /// + /// @abstract + /// Merges data into a dispatch source of type DISPATCH_SOURCE_TYPE_DATA_ADD or + /// DISPATCH_SOURCE_TYPE_DATA_OR and submits its event handler block to its + /// target queue. + /// + /// @param value + /// The value to coalesce with the pending data using a logical OR or an ADD + /// as specified by the dispatch source type. A value of zero has no effect + /// and will not result in the submission of the event handler block. + public func mergeData(value: UInt) { + __dispatch_source_merge_data(self as! DispatchSource, value) + } +} + +@_silgen_name("_swift_dispatch_source_type_DATA_ADD") +internal func _swift_dispatch_source_type_data_add() -> __dispatch_source_type_t + +@_silgen_name("_swift_dispatch_source_type_DATA_OR") +internal func _swift_dispatch_source_type_data_or() -> __dispatch_source_type_t + +@_silgen_name("_swift_dispatch_source_type_MACH_SEND") +internal func _swift_dispatch_source_type_mach_send() -> __dispatch_source_type_t + +@_silgen_name("_swift_dispatch_source_type_MACH_RECV") +internal func _swift_dispatch_source_type_mach_recv() -> __dispatch_source_type_t + +@_silgen_name("_swift_dispatch_source_type_MEMORYPRESSURE") +internal func _swift_dispatch_source_type_memorypressure() -> __dispatch_source_type_t + +@_silgen_name("_swift_dispatch_source_type_PROC") +internal func _swift_dispatch_source_type_proc() -> __dispatch_source_type_t + +@_silgen_name("_swift_dispatch_source_type_READ") +internal func _swift_dispatch_source_type_read() -> __dispatch_source_type_t + +@_silgen_name("_swift_dispatch_source_type_SIGNAL") +internal func _swift_dispatch_source_type_signal() -> __dispatch_source_type_t + +@_silgen_name("_swift_dispatch_source_type_TIMER") +internal func _swift_dispatch_source_type_timer() -> __dispatch_source_type_t + +@_silgen_name("_swift_dispatch_source_type_VNODE") +internal func _swift_dispatch_source_type_vnode() -> __dispatch_source_type_t + +@_silgen_name("_swift_dispatch_source_type_WRITE") +internal func _swift_dispatch_source_type_write() -> __dispatch_source_type_t diff --git a/src/swift/Time.swift b/src/swift/Time.swift new file mode 100644 index 000000000..e0b63b814 --- /dev/null +++ b/src/swift/Time.swift @@ -0,0 +1,108 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See http://swift.org/LICENSE.txt for license information +// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +// dispatch/time.h +// DISPATCH_TIME_NOW: ok +// DISPATCH_TIME_FOREVER: ok + +public struct DispatchTime { + public let rawValue: dispatch_time_t + + public static func now() -> DispatchTime { + let t = __dispatch_time(0, 0) + return DispatchTime(rawValue: t) + } + + public static let distantFuture = DispatchTime(rawValue: ~0) + + private init(rawValue: dispatch_time_t) { + self.rawValue = rawValue + } +} + +public struct DispatchWallTime { + public let rawValue: dispatch_time_t + + public static func now() -> DispatchWallTime { + return DispatchWallTime(rawValue: __dispatch_walltime(nil, 0)) + } + + public static let distantFuture = DispatchWallTime(rawValue: ~0) + + private init(rawValue: dispatch_time_t) { + self.rawValue = rawValue + } + + public init(time: timespec) { + var t = time + self.rawValue = __dispatch_walltime(&t, 0) + } +} + +@available(*, deprecated, renamed: "DispatchWallTime") +public typealias DispatchWalltime = DispatchWallTime + +public enum DispatchTimeInterval { + case seconds(Int) + case milliseconds(Int) + case microseconds(Int) + case nanoseconds(Int) + + internal var rawValue: UInt64 { + switch self { + case .seconds(let s): return UInt64(s) * NSEC_PER_SEC + case .milliseconds(let ms): return UInt64(ms) * NSEC_PER_MSEC + case .microseconds(let us): return UInt64(us) * NSEC_PER_USEC + case .nanoseconds(let ns): return UInt64(ns) + } + } +} + +public func +(time: DispatchTime, interval: DispatchTimeInterval) -> DispatchTime { + let t = __dispatch_time(time.rawValue, Int64(interval.rawValue)) + return DispatchTime(rawValue: t) +} + +public func -(time: DispatchTime, interval: DispatchTimeInterval) -> DispatchTime { + let t = __dispatch_time(time.rawValue, -Int64(interval.rawValue)) + return DispatchTime(rawValue: t) +} + +public func +(time: DispatchTime, seconds: Double) -> DispatchTime { + let t = __dispatch_time(time.rawValue, Int64(seconds * Double(NSEC_PER_SEC))) + return DispatchTime(rawValue: t) +} + +public func -(time: DispatchTime, seconds: Double) -> DispatchTime { + let t = __dispatch_time(time.rawValue, Int64(-seconds * Double(NSEC_PER_SEC))) + return DispatchTime(rawValue: t) +} + +public func +(time: DispatchWallTime, interval: DispatchTimeInterval) -> DispatchWallTime { + let t = __dispatch_time(time.rawValue, Int64(interval.rawValue)) + return DispatchWallTime(rawValue: t) +} + +public func -(time: DispatchWallTime, interval: DispatchTimeInterval) -> DispatchWallTime { + let t = __dispatch_time(time.rawValue, -Int64(interval.rawValue)) + return DispatchWallTime(rawValue: t) +} + +public func +(time: DispatchWallTime, seconds: Double) -> DispatchWallTime { + let t = __dispatch_time(time.rawValue, Int64(seconds * Double(NSEC_PER_SEC))) + return DispatchWallTime(rawValue: t) +} + +public func -(time: DispatchWallTime, seconds: Double) -> DispatchWallTime { + let t = __dispatch_time(time.rawValue, Int64(-seconds * Double(NSEC_PER_SEC))) + return DispatchWallTime(rawValue: t) +} diff --git a/src/swift/swift_wrappers.c b/src/swift/swift_wrappers.c deleted file mode 100644 index 0b982b91c..000000000 --- a/src/swift/swift_wrappers.c +++ /dev/null @@ -1,47 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See http://swift.org/LICENSE.txt for license information -// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -#include - -DISPATCH_EXPORT -dispatch_queue_attr_t -_swift_dispatch_queue_serial(void) { - return DISPATCH_QUEUE_SERIAL; -} - -DISPATCH_EXPORT -dispatch_queue_attr_t -_swift_dispatch_queue_concurrent(void) { - return DISPATCH_QUEUE_CONCURRENT; -} - -DISPATCH_EXPORT -dispatch_data_t -_swift_dispatch_data_empty(void) { - return dispatch_data_empty; -} - -#define SOURCE(t) \ - DISPATCH_EXPORT \ - dispatch_source_type_t \ - _swift_dispatch_source_type_##t(void) { \ - return DISPATCH_SOURCE_TYPE_##t; \ - } - -SOURCE(DATA_ADD) -SOURCE(DATA_OR) -SOURCE(PROC) -SOURCE(READ) -SOURCE(SIGNAL) -SOURCE(TIMER) -SOURCE(VNODE) -SOURCE(WRITE)