From a38736c02e1c47de9cca8a49754660b7e9524e68 Mon Sep 17 00:00:00 2001 From: David Grove Date: Tue, 28 Jun 2016 14:30:26 -0400 Subject: [PATCH] Initial Swift3 wrapping overlay for libdispatch A useful checkpoint along the way to a complete implementation of the Swift3 overlay for libdispatch on non-Objective C platforms. The overlay code builds successfully and simple example programs using queues and timers work as expected. The basic approach is to wrap the C libdispatch objects in Swift objects and make the C dispatch APIs available internally via the CDispatch module. A few pieces (marked with FIXME) are ifdefed out to avoid compilation problems (will get back to them in later commits) or still need to be implemented (release on deinit). Although the installed libdispatch can be used in Swift programs via 'import Dispatch', the swiftc command for the client program currently needs to pass additional command line flags (to be fixed later). For example: swiftc -Xcc -fblocks -Xcc -D__DISPATCH_BUILDING_SWIFT_MODULE__=1 Forever.swift --- configure.ac | 21 +- dispatch/Makefile.am | 2 +- dispatch/module.map | 7 - dispatch/module.modulemap | 16 +- src/Makefile.am | 70 +++-- src/data.c | 4 + src/swift/Block.swift | 49 ++-- src/swift/Data.swift | 83 ++---- src/swift/Dispatch.swift | 61 ++-- src/swift/{Dispatch.mm => DispatchStubs.cc} | 28 +- src/swift/IO.swift | 14 +- src/swift/Private.swift | 38 +-- src/swift/Queue.swift | 96 +++---- src/swift/Source.swift | 170 ++++++----- src/swift/Time.swift | 24 +- src/swift/Wrapper.swift | 297 ++++++++++++++++++++ tests/Makefile.am | 6 +- 17 files changed, 676 insertions(+), 310 deletions(-) delete mode 100644 dispatch/module.map rename src/swift/{Dispatch.mm => DispatchStubs.cc} (89%) create mode 100644 src/swift/Wrapper.swift diff --git a/configure.ac b/configure.ac index de2165ab2..297517ed8 100644 --- a/configure.ac +++ b/configure.ac @@ -94,6 +94,8 @@ AS_IF([test "x$enable_apple_tsd_optimizations" = "xyes"], [Define to use non-portable pthread TSD optimizations for Mac OS X)])] ) +AC_CANONICAL_TARGET + # # Enable building Swift overlay support into libdispatch # @@ -102,17 +104,34 @@ AC_ARG_WITH([swift-toolchain], [swift_toolchain_path=${withval} AC_DEFINE(HAVE_SWIFT, 1, [Define if building for Swift]) SWIFTC="$swift_toolchain_path/bin/swiftc" + case $target_os in + linux*) + os_string="linux" + ;; + *) + os_string=$target_os + ;; + esac + SWIFT_LIBDIR="$swift_toolchain_path/lib/swift/$os_string/$target_cpu" have_swift=true], [have_swift=false] ) AM_CONDITIONAL(HAVE_SWIFT, $have_swift) AC_SUBST([SWIFTC]) +AC_SUBST([SWIFT_LIBDIR]) + +# +# Enable use of gold linker when building the Swift overlay +# to avoid a symbol relocation issue. +# Ultimately the request to use gold should be passed in as an arg +# +AC_CHECK_PROG(use_gold_linker, ld.gold, true, false) +AM_CONDITIONAL(USE_GOLD_LINKER, $use_gold_linker) # # Enable __thread based TSD on platforms where it is efficient # Allow override based on command line argument to configure # -AC_CANONICAL_TARGET AC_ARG_ENABLE([thread-local-storage], [AS_HELP_STRING([--enable-thread-local-storage], [Enable usage of thread local storage via __thread])],, diff --git a/dispatch/Makefile.am b/dispatch/Makefile.am index 53ea5986c..89fd3daf0 100644 --- a/dispatch/Makefile.am +++ b/dispatch/Makefile.am @@ -24,5 +24,5 @@ dispatch_HEADERS= \ time.h if HAVE_SWIFT -dispatch_HEADERS+=module.map +dispatch_HEADERS+=module.modulemap endif diff --git a/dispatch/module.map b/dispatch/module.map deleted file mode 100644 index eefa75159..000000000 --- a/dispatch/module.map +++ /dev/null @@ -1,7 +0,0 @@ -module Dispatch [system] { - umbrella header "dispatch.h" - requires blocks - export * - link "dispatch" - link "BlocksRuntime" -} diff --git a/dispatch/module.modulemap b/dispatch/module.modulemap index addaae436..6f3c8aab8 100644 --- a/dispatch/module.modulemap +++ b/dispatch/module.modulemap @@ -1,10 +1,20 @@ -module Dispatch [system] [extern_c] { - umbrella header "dispatch.h" - module * { export * } +module Dispatch { + requires blocks export * + link "dispatch" + link "BlocksRuntime" } module DispatchIntrospection [system] [extern_c] { header "introspection.h" export * } + +module CDispatch [system] [extern_c] { + umbrella header "dispatch.h" + module * { export * } + export * + requires blocks + link "dispatch" + link "BlocksRuntime" +} diff --git a/src/Makefile.am b/src/Makefile.am index e51d15a33..58fa4ef12 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -40,6 +40,7 @@ libdispatch_la_SOURCES= \ source_internal.h \ trace.h \ voucher_internal.h \ + firehose/firehose_internal.h \ shims/atomic.h \ shims/atomic_sfb.h \ shims/getprogname.h \ @@ -83,6 +84,10 @@ libdispatch_la_LDFLAGS+=-Wl,-compatibility_version,1 \ -Wl,-alias_list,$(top_srcdir)/xcodeconfig/libdispatch.aliases endif +if USE_GOLD_LINKER +libdispatch_la_LDFLAGS+=-Xcompiler -fuse-ld=gold +endif + if USE_OBJC libdispatch_la_SOURCES+=block.cpp data.m object.m libdispatch_la_OBJCFLAGS=$(AM_OBJCFLAGS) -Wno-switch -fobjc-gc @@ -114,9 +119,7 @@ DTRACE_SOURCES=provider.h endif if HAVE_SWIFT -libdispatch_la_SOURCES+=swift/Dispatch.mm -EXTRA_libdispatch_la_SOURCES+= \ - swift/Dispatch.swift \ +SWIFT_SRC_FILES=\ swift/Block.swift \ swift/Data.swift \ swift/Dispatch.swift \ @@ -124,33 +127,52 @@ EXTRA_libdispatch_la_SOURCES+= \ 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 - -SWIFT_OBJECTS= \ - $(abs_builddir)/Dispatch.swiftmodule \ - $(abs_builddir)/Dispatch.swiftdoc \ - $(abs_builddir)/Dispatch.o + swift/Time.swift \ + swift/Wrapper.swift + +SWIFT_ABS_SRC_FILES = $(SWIFT_SRC_FILES:%=$(abs_srcdir)/%) +SWIFT_OBJ_FILES = $(SWIFT_SRC_FILES:%.swift=$(abs_builddir)/%.o) + +libdispatch_la_SOURCES+=swift/DispatchStubs.cc +EXTRA_libdispatch_la_SOURCES+=$(SWIFT_SRC_FILES) + +EXTRA_libdispatch_la_DEPENDENCIES+=$(SWIFT_OBJ_FILES) $(abs_builddir)/swift/Dispatch.swiftmodule +libdispatch_la_LIBADD+=$(SWIFT_OBJ_FILES) + +SWIFT_GEN_FILES= \ + $(abs_builddir)/swift/Dispatch.swiftmodule \ + $(abs_builddir)/swift/Dispatch.swiftdoc \ + $(SWIFT_OBJ_FILES) \ + $(SWIFT_OBJ_FILES:%=%.d) \ + $(SWIFT_OBJ_FILES:%=%.swiftdeps) \ + $(SWIFT_OBJ_FILES:%=%.~partial.swiftmodule) \ + $(SWIFT_OBJ_FILES:%=%.~partial.swiftdoc) \ + $(SWIFT_OBJ_FILES:%=%.~partial.swiftdeps) + +SWIFTC_FLAGS = -Xcc -D__DISPATCH_BUILDING_SWIFT_MODULE__=1 -Xcc -fmodule-map-file=$(abs_top_srcdir)/dispatch/module.modulemap -I$(abs_top_srcdir) -Xcc -fblocks + +$(abs_builddir)/swift/%.o: $(abs_srcdir)/swift/%.swift + $(SWIFTC) -frontend -c $(SWIFT_ABS_SRC_FILES) -primary-file $< \ + $(SWIFTC_FLAGS) -module-name Dispatch -module-link-name dispatch \ + -o $@ -emit-module-path $@.~partial.swiftmodule \ + -emit-module-doc-path $@.~partial.swiftdoc -emit-dependencies-path $@.d \ + -emit-reference-dependencies-path $@.swiftdeps \ + -module-cache-path $(top_builddir) + +$(abs_builddir)/swift/Dispatch.swiftmodule: $(SWIFT_ABS_SRC_FILES) + $(SWIFTC) -frontend -emit-module $(SWIFT_OBJ_FILES:%=%.~partial.swiftmodule) \ + $(SWIFTC_FLAGS) -module-cache-path $(top_builddir) -module-link-name dispatch \ + -o $@ -emit-module-doc-path $(@:%.swiftmodule=%.swiftdoc) -SWIFTC_FLAGS = -Xcc -D__DISPATCH_BUILDING_SWIFT_MODULE__=1 -Xcc -fmodule-map-file=$(abs_top_srcdir)/dispatch/module.map -I$(abs_top_srcdir) -parse-as-library -Xcc -fblocks - -$(abs_builddir)/Dispatch.o: $(abs_srcdir)/swift/Dispatch.swift - $(SWIFTC) $(SWIFTC_FLAGS) -c -o $@ $< - -$(abs_builddir)/Dispatch.swiftmodule: $(abs_srcdir)/swift/Dispatch.swift - $(SWIFTC) $(SWIFTC_FLAGS) -emit-module -emit-module-path $@ $< - -if HAVE_SWIFT swiftmoddir=${prefix}/lib/swift/linux/${build_cpu} -swiftmod_HEADERS=$(abs_builddir)/Dispatch.swiftmodule $(abs_builddir)/Dispatch.swiftdoc -endif +swiftmod_HEADERS=\ + $(abs_builddir)/swift/Dispatch.swiftmodule \ + $(abs_builddir)/swift/Dispatch.swiftdoc endif BUILT_SOURCES=$(MIG_SOURCES) $(DTRACE_SOURCES) nodist_libdispatch_la_SOURCES=$(BUILT_SOURCES) -CLEANFILES=$(BUILT_SOURCES) $(SWIFT_OBJECTS) +CLEANFILES=$(BUILT_SOURCES) $(SWIFT_GEN_FILES) DISTCLEANFILES=pthread_machdep.h pthread System mach objc diff --git a/src/data.c b/src/data.c index 33906d35d..5f1942fef 100644 --- a/src/data.c +++ b/src/data.c @@ -108,6 +108,10 @@ const dispatch_block_t _dispatch_data_destructor_none = ^{ DISPATCH_INTERNAL_CRASH(0, "none destructor called"); }; +const dispatch_block_t _dispatch_data_destructor_munmap = ^{ + DISPATCH_INTERNAL_CRASH(0, "munmap destructor called"); +}; + #ifndef __linux__ const dispatch_block_t _dispatch_data_destructor_vm_deallocate = ^{ DISPATCH_INTERNAL_CRASH(0, "vmdeallocate destructor called"); diff --git a/src/swift/Block.swift b/src/swift/Block.swift index e32478ea0..c1266cea1 100644 --- a/src/swift/Block.swift +++ b/src/swift/Block.swift @@ -10,6 +10,8 @@ // //===----------------------------------------------------------------------===// +import CDispatch + public struct DispatchWorkItemFlags : OptionSet, RawRepresentable { public let rawValue: UInt public init(rawValue: UInt) { self.rawValue = rawValue } @@ -38,14 +40,14 @@ public class DispatchWorkItem { 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) + _block = dispatch_block_create_with_qos_class(dispatch_block_flags_t(flags.rawValue), + qos.qosClass.rawValue.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) + _block = _swift_dispatch_block_create_noescape(dispatch_block_flags_t(flags.rawValue), noescapeBlock) } public func perform() { @@ -57,36 +59,36 @@ public class DispatchWorkItem { } public func wait() { - _ = _swift_dispatch_block_wait(_block, DispatchTime.distantFuture.rawValue) + _ = dispatch_block_wait(_block, DispatchTime.distantFuture.rawValue) } public func wait(timeout: DispatchTime) -> DispatchTimeoutResult { - return _swift_dispatch_block_wait(_block, timeout.rawValue) == 0 ? .Success : .TimedOut + return 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 + return 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) + dispatch_block_notify(_block, queue.__wrapped, item._block) } else { - _swift_dispatch_block_notify(_block, queue, execute) + dispatch_block_notify(_block, queue.__wrapped, execute) } } public func notify(queue: DispatchQueue, execute: DispatchWorkItem) { - _swift_dispatch_block_notify(_block, queue, execute._block) + dispatch_block_notify(_block, queue.__wrapped, execute._block) } public func cancel() { - _swift_dispatch_block_cancel(_block) + dispatch_block_cancel(_block) } public var isCancelled: Bool { - return _swift_dispatch_block_testcancel(_block) != 0 + return dispatch_block_testcancel(_block) != 0 } } @@ -96,7 +98,7 @@ public extension DispatchWorkItem { public func wait(timeout: DispatchWallTime) -> Int { switch wait(wallTimeout: timeout) { case .Success: return 0 - case .TimedOut: return Int(KERN_OPERATION_TIMED_OUT) + case .TimedOut: return DispatchTimeoutResult.KERN_OPERATION_TIMED_OUT } } } @@ -106,26 +108,7 @@ public extension DispatchWorkItem { /// 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 +internal typealias dispatch_block_t = @convention(block) () -> Void @_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 - +internal func _swift_dispatch_block_create_noescape(_ flags: dispatch_block_flags_t, _ block: @noescape () -> ()) -> _DispatchBlock diff --git a/src/swift/Data.swift b/src/swift/Data.swift index a78bf5bca..0d21e27c0 100644 --- a/src/swift/Data.swift +++ b/src/swift/Data.swift @@ -10,13 +10,16 @@ // //===----------------------------------------------------------------------===// -public struct DispatchData : RandomAccessCollection, _ObjectiveCBridgeable { +import CDispatch + +public struct DispatchData : RandomAccessCollection { public typealias Iterator = DispatchDataIterator public typealias Index = Int public typealias Indices = DefaultRandomAccessIndices public static let empty: DispatchData = DispatchData(data: _swift_dispatch_data_empty()) +#if false /* FIXME: dragging in _TMBO (Objective-C) */ public enum Deallocator { /// Use `free` case free @@ -35,18 +38,18 @@ public struct DispatchData : RandomAccessCollection, _ObjectiveCBridgeable { } } } - - private var __wrapped: __DispatchData +#endif + internal var __wrapped: dispatch_data_t /// 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( + __wrapped = dispatch_data_create( buffer.baseAddress!, buffer.count, nil, _dispatch_data_destructor_default()) } - +#if false /* FIXME: dragging in _TMBO (Objective-C) */ /// Initialize a `Data` without copying the bytes. /// /// - parameter bytes: A pointer to the bytes. @@ -55,16 +58,15 @@ public struct DispatchData : RandomAccessCollection, _ObjectiveCBridgeable { public init(bytesNoCopy bytes: UnsafeBufferPointer, deallocator: Deallocator = .free) { let (q, b) = deallocator._deallocator - __wrapped = __dispatch_data_create( - bytes.baseAddress!, bytes.count, q, b) + __wrapped = dispatch_data_create(bytes.baseAddress!, bytes.count, q?.__wrapped, b) } - - internal init(data: __DispatchData) { +#endif + internal init(data: dispatch_data_t) { __wrapped = data } public var count: Int { - return __dispatch_data_get_size(__wrapped) + return CDispatch.dispatch_data_get_size(__wrapped) } public func withUnsafeBytes( @@ -72,7 +74,7 @@ public struct DispatchData : RandomAccessCollection, _ObjectiveCBridgeable { { var ptr: UnsafePointer? = nil var size = 0; - let data = __dispatch_data_create_map(__wrapped, &ptr, &size) + let data = CDispatch.dispatch_data_create_map(__wrapped, &ptr, &size) defer { _fixLifetime(data) } return try body(UnsafePointer(ptr!)) } @@ -80,7 +82,7 @@ public struct DispatchData : RandomAccessCollection, _ObjectiveCBridgeable { 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 + _swift_dispatch_data_apply(__wrapped) { (data: dispatch_data_t, 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) @@ -93,7 +95,7 @@ public struct DispatchData : RandomAccessCollection, _ObjectiveCBridgeable { /// - 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()) + let data = dispatch_data_create(bytes, count, nil, _dispatch_data_destructor_default()) self.append(DispatchData(data: data)) } @@ -101,7 +103,7 @@ public struct DispatchData : RandomAccessCollection, _ObjectiveCBridgeable { /// /// - 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) + let data = CDispatch.dispatch_data_create_concat(__wrapped, other.__wrapped) __wrapped = data } @@ -109,12 +111,12 @@ public struct DispatchData : RandomAccessCollection, _ObjectiveCBridgeable { /// /// - 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)) + self.append(UnsafePointer(buffer.baseAddress!), count: buffer.count * sizeof(SourceType.self)) } 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 + _ = CDispatch.dispatch_data_apply(__wrapped) { (data: dispatch_data_t, offset: Int, ptr: UnsafePointer, size: Int) in let limit = Swift.min((range.endIndex - range.startIndex) - copiedCount, size) memcpy(pointer + copiedCount, ptr, limit) copiedCount += limit @@ -160,9 +162,9 @@ public struct DispatchData : RandomAccessCollection, _ObjectiveCBridgeable { 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)) + copyRange = r.startIndex..<(r.startIndex + Swift.min(buffer.count * sizeof(DestinationType.self), r.count)) } else { - copyRange = 0.. UInt8 { var offset = 0 - let subdata = __dispatch_data_copy_region(__wrapped, index, &offset) + let subdata = CDispatch.dispatch_data_copy_region(__wrapped, index, &offset) var ptr: UnsafePointer? = nil var size = 0 - let map = __dispatch_data_create_map(subdata, &ptr, &size) + let map = CDispatch.dispatch_data_create_map(subdata, &ptr, &size) defer { _fixLifetime(map) } let pptr = UnsafePointer(ptr!) @@ -194,14 +196,14 @@ public struct DispatchData : RandomAccessCollection, _ObjectiveCBridgeable { /// /// - parameter range: The range to copy. public func subdata(in range: CountableRange) -> DispatchData { - let subrange = __dispatch_data_create_subrange( + let subrange = CDispatch.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) + let data = CDispatch.dispatch_data_copy_region(__wrapped, location, &offset) return (DispatchData(data: data), offset) } @@ -235,8 +237,7 @@ public struct DispatchDataIterator : IteratorProtocol, Sequence { public init(_data: DispatchData) { var ptr: UnsafePointer? self._count = 0 - self._data = __dispatch_data_create_map( - _data as __DispatchData, &ptr, &self._count) + self._data = CDispatch.dispatch_data_create_map(_data.__wrapped, &ptr, &self._count) self._ptr = UnsafePointer(ptr!) self._position = _data.startIndex } @@ -252,45 +253,19 @@ public struct DispatchDataIterator : IteratorProtocol, Sequence { return element } - internal let _data: __DispatchData + internal let _data: dispatch_data_t 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 +typealias _swift_data_applier = @convention(block) @noescape (dispatch_data_t, Int, UnsafePointer, Int) -> Bool @_silgen_name("_swift_dispatch_data_apply") -internal func _swift_dispatch_data_apply(_ data: __DispatchData, _ block: _swift_data_applier) +internal func _swift_dispatch_data_apply(_ data: dispatch_data_t, _ block: _swift_data_applier) @_silgen_name("_swift_dispatch_data_empty") -internal func _swift_dispatch_data_empty() -> __DispatchData +internal func _swift_dispatch_data_empty() -> dispatch_data_t @_silgen_name("_swift_dispatch_data_destructor_free") internal func _dispatch_data_destructor_free() -> _DispatchBlock diff --git a/src/swift/Dispatch.swift b/src/swift/Dispatch.swift index 4ed2ad9cd..2b9cb2164 100644 --- a/src/swift/Dispatch.swift +++ b/src/swift/Dispatch.swift @@ -12,6 +12,8 @@ @_exported import Dispatch +import CDispatch + /// dispatch_assert @available(OSX 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *) @@ -25,11 +27,11 @@ public enum DispatchPredicate { public func _dispatchPreconditionTest(_ condition: DispatchPredicate) -> Bool { switch condition { case .onQueue(let q): - __dispatch_assert_queue(q) + dispatch_assert_queue(q.__wrapped) case .onQueueAsBarrier(let q): - __dispatch_assert_queue_barrier(q) + dispatch_assert_queue_barrier(q.__wrapped) case .notOnQueue(let q): - __dispatch_assert_queue_not(q) + dispatch_assert_queue_not(q.__wrapped) } return true } @@ -94,27 +96,27 @@ public struct DispatchQoS : Equatable { case unspecified @available(OSX 10.10, iOS 8.0, *) - internal init?(qosClass: qos_class_t) { + internal init?(qosClass: _OSQoSClass) { 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 + 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 { + internal var rawValue: _OSQoSClass { 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 + 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 } } } @@ -132,6 +134,7 @@ public func ==(a: DispatchQoS, b: DispatchQoS) -> Bool { /// public enum DispatchTimeoutResult { + static let KERN_OPERATION_TIMED_OUT:Int = 49 case Success case TimedOut } @@ -142,27 +145,27 @@ 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) + dispatch_group_notify(self.__wrapped, queue.__wrapped, item._block) } else { - __dispatch_group_notify(self, queue, work) + dispatch_group_notify(self.__wrapped, queue.__wrapped, work) } } @available(OSX 10.10, iOS 8.0, *) public func notify(queue: DispatchQueue, work: DispatchWorkItem) { - __dispatch_group_notify(self, queue, work._block) + dispatch_group_notify(self.__wrapped, queue.__wrapped, work._block) } public func wait() { - _ = __dispatch_group_wait(self, DispatchTime.distantFuture.rawValue) + _ = dispatch_group_wait(self.__wrapped, DispatchTime.distantFuture.rawValue) } public func wait(timeout: DispatchTime) -> DispatchTimeoutResult { - return __dispatch_group_wait(self, timeout.rawValue) == 0 ? .Success : .TimedOut + return dispatch_group_wait(self.__wrapped, timeout.rawValue) == 0 ? .Success : .TimedOut } public func wait(wallTimeout timeout: DispatchWallTime) -> DispatchTimeoutResult { - return __dispatch_group_wait(self, timeout.rawValue) == 0 ? .Success : .TimedOut + return dispatch_group_wait(self.__wrapped, timeout.rawValue) == 0 ? .Success : .TimedOut } } @@ -171,7 +174,7 @@ public extension DispatchGroup { public func wait(walltime timeout: DispatchWallTime) -> Int { switch wait(wallTimeout: timeout) { case .Success: return 0 - case .TimedOut: return Int(KERN_OPERATION_TIMED_OUT) + case .TimedOut: return DispatchTimeoutResult.KERN_OPERATION_TIMED_OUT } } } @@ -181,19 +184,19 @@ public extension DispatchGroup { public extension DispatchSemaphore { @discardableResult public func signal() -> Int { - return __dispatch_semaphore_signal(self) + return dispatch_semaphore_signal(self.__wrapped) } public func wait() { - _ = __dispatch_semaphore_wait(self, DispatchTime.distantFuture.rawValue) + _ = dispatch_semaphore_wait(self.__wrapped, DispatchTime.distantFuture.rawValue) } public func wait(timeout: DispatchTime) -> DispatchTimeoutResult { - return __dispatch_semaphore_wait(self, timeout.rawValue) == 0 ? .Success : .TimedOut + return dispatch_semaphore_wait(self.__wrapped, timeout.rawValue) == 0 ? .Success : .TimedOut } public func wait(wallTimeout: DispatchWallTime) -> DispatchTimeoutResult { - return __dispatch_semaphore_wait(self, wallTimeout.rawValue) == 0 ? .Success : .TimedOut + return dispatch_semaphore_wait(self.__wrapped, wallTimeout.rawValue) == 0 ? .Success : .TimedOut } } @@ -202,7 +205,7 @@ public extension DispatchSemaphore { public func wait(walltime timeout: DispatchWalltime) -> Int { switch wait(wallTimeout: timeout) { case .Success: return 0 - case .TimedOut: return Int(KERN_OPERATION_TIMED_OUT) + case .TimedOut: return DispatchTimeoutResult.KERN_OPERATION_TIMED_OUT } } } diff --git a/src/swift/Dispatch.mm b/src/swift/DispatchStubs.cc similarity index 89% rename from src/swift/Dispatch.mm rename to src/swift/DispatchStubs.cc index b66a34e8b..62a53ef6b 100644 --- a/src/swift/Dispatch.mm +++ b/src/swift/DispatchStubs.cc @@ -11,11 +11,11 @@ //===----------------------------------------------------------------------===// #include -#include #include #define DISPATCH_RUNTIME_STDLIB_INTERFACE __attribute__((__visibility__("default"))) +#if USE_OBJC @protocol OS_dispatch_source; @protocol OS_dispatch_source_mach_send; @protocol OS_dispatch_source_mach_recv; @@ -49,9 +49,15 @@ static void _dispatch_overlay_constructor() { } } +#endif /* USE_OBJC */ + +#if 0 /* FIXME -- adding directory to include path may need build-script plumbing to do properly... */ #include "swift/Runtime/Config.h" +#else +#define SWIFT_CC(x) /* FIXME!! */ +#endif -SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE +SWIFT_CC(swift) DISPATCH_RUNTIME_STDLIB_INTERFACE extern "C" dispatch_queue_attr_t _swift_dispatch_queue_concurrent(void) { return DISPATCH_QUEUE_CONCURRENT; @@ -95,7 +101,7 @@ static void _dispatch_overlay_constructor() { 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) { +_swift_dispatch_block_create_with_qos_class(dispatch_block_flags_t flags, dispatch_qos_class_t qos, int relative_priority, dispatch_block_t block) { return dispatch_block_create_with_qos_class(flags, qos, relative_priority, block); } @@ -168,12 +174,28 @@ static void _dispatch_overlay_constructor() { SOURCE(DATA_ADD) SOURCE(DATA_OR) +#if HAVE_MACH SOURCE(MACH_SEND) SOURCE(MACH_RECV) SOURCE(MEMORYPRESSURE) +#endif +#ifndef __linux__ SOURCE(PROC) +#endif SOURCE(READ) SOURCE(SIGNAL) SOURCE(TIMER) +#ifndef __linux__ SOURCE(VNODE) +#endif SOURCE(WRITE) + +// See comment in CFFuntime.c explaining why objc_retainAutoreleasedReturnValue is needed. +extern "C" void swift_release(void *); +extern "C" void * objc_retainAutoreleasedReturnValue(void *obj) { + if (obj) { + swift_release(obj); + return obj; + } + else return NULL; +} diff --git a/src/swift/IO.swift b/src/swift/IO.swift index 049f54f3c..6e6b6692e 100644 --- a/src/swift/IO.swift +++ b/src/swift/IO.swift @@ -10,6 +10,8 @@ // //===----------------------------------------------------------------------===// +import CDispatch + public extension DispatchIO { public enum StreamType : UInt { @@ -33,13 +35,13 @@ public extension DispatchIO { } 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 + dispatch_read(fromFileDescriptor, maxLength, queue.__wrapped) { (data: dispatch_data_t, 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 + dispatch_write(fromFileDescriptor, data.__wrapped, queue.__wrapped) { (data: dispatch_data_t?, error: Int32) in handler(data: data.flatMap { DispatchData(data: $0) }, error: error) } } @@ -74,23 +76,23 @@ public extension DispatchIO { } 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 + dispatch_io_read(self.__wrapped, offset, length, queue.__wrapped) { (done: Bool, data: dispatch_data_t?, 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 + dispatch_io_write(self.__wrapped, offset, data.__wrapped, queue.__wrapped) { (done: Bool, data: dispatch_data_t?, 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) + dispatch_io_set_interval(self.__wrapped, interval.rawValue, flags.rawValue) } public func close(flags: CloseFlags = []) { - __dispatch_io_close(self, flags.rawValue) + dispatch_io_close(self.__wrapped, flags.rawValue) } } diff --git a/src/swift/Private.swift b/src/swift/Private.swift index 3a0cdb630..e38f72861 100644 --- a/src/swift/Private.swift +++ b/src/swift/Private.swift @@ -12,14 +12,16 @@ // Redeclarations of all SwiftPrivate functions with appropriate markup. +import CDispatch + @available(*, unavailable, renamed:"DispatchQueue.init(label:attributes:target:)") -public func dispatch_queue_create(_ label: UnsafePointer?, _ attr: __OS_dispatch_queue_attr?) -> DispatchQueue +public func dispatch_queue_create(_ label: UnsafePointer?, _ attr: dispatch_queue_attr_t?) -> 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 +public func dispatch_queue_create_with_target(_ label: UnsafePointer?, _ attr: dispatch_queue_attr_t?, _ queue: DispatchQueue?) -> DispatchQueue { fatalError() } @@ -43,67 +45,67 @@ public func dispatch_io_create_with_io(_ type: UInt, _ io: DispatchIO, _ queue: } @available(*, unavailable, renamed:"DispatchIO.read(fileDescriptor:length:queue:handler:)") -public func dispatch_read(_ fd: Int32, _ length: Int, _ queue: DispatchQueue, _ handler: (__DispatchData, Int32) -> Void) +public func dispatch_read(_ fd: Int32, _ length: Int, _ queue: DispatchQueue, _ handler: (dispatch_data_t, 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) +func dispatch_io_read(_ channel: DispatchIO, _ offset: off_t, _ length: Int, _ queue: DispatchQueue, _ io_handler: (Bool, dispatch_data_t?, 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) +func dispatch_io_write(_ channel: DispatchIO, _ offset: off_t, _ data: dispatch_data_t, _ queue: DispatchQueue, _ io_handler: (Bool, dispatch_data_t?, 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) +func dispatch_write(_ fd: Int32, _ data: dispatch_data_t, _ queue: DispatchQueue, _ handler: (dispatch_data_t?, Int32) -> Void) { fatalError() } @available(*, unavailable, renamed:"DispatchData.init(bytes:)") -public func dispatch_data_create(_ buffer: UnsafePointer, _ size: Int, _ queue: DispatchQueue?, _ destructor: (() -> Void)?) -> __DispatchData +public func dispatch_data_create(_ buffer: UnsafePointer, _ size: Int, _ queue: DispatchQueue?, _ destructor: (() -> Void)?) -> dispatch_data_t { fatalError() } @available(*, unavailable, renamed:"getter:DispatchData.count(self:)") -public func dispatch_data_get_size(_ data: __DispatchData) -> Int +public func dispatch_data_get_size(_ data: dispatch_data_t) -> Int { fatalError() } @available(*, unavailable, renamed:"DispatchData.withUnsafeBytes(self:body:)") -public func dispatch_data_create_map(_ data: __DispatchData, _ buffer_ptr: UnsafeMutablePointer?>?, _ size_ptr: UnsafeMutablePointer?) -> __DispatchData +public func dispatch_data_create_map(_ data: dispatch_data_t, _ buffer_ptr: UnsafeMutablePointer?>?, _ size_ptr: UnsafeMutablePointer?) -> dispatch_data_t { fatalError() } @available(*, unavailable, renamed:"DispatchData.append(self:_:)") -public func dispatch_data_create_concat(_ data1: __DispatchData, _ data2: __DispatchData) -> __DispatchData +public func dispatch_data_create_concat(_ data1: dispatch_data_t, _ data2: dispatch_data_t) -> dispatch_data_t { fatalError() } @available(*, unavailable, renamed:"DispatchData.subdata(self:in:)") -public func dispatch_data_create_subrange(_ data: __DispatchData, _ offset: Int, _ length: Int) -> __DispatchData +public func dispatch_data_create_subrange(_ data: dispatch_data_t, _ offset: Int, _ length: Int) -> dispatch_data_t { fatalError() } @available(*, unavailable, renamed:"DispatchData.enumerateBytes(self:block:)") -public func dispatch_data_apply(_ data: __DispatchData, _ applier: (__DispatchData, Int, UnsafePointer, Int) -> Bool) -> Bool +public func dispatch_data_apply(_ data: dispatch_data_t, _ applier: (dispatch_data_t, 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 +public func dispatch_data_copy_region(_ data: dispatch_data_t, _ location: Int, _ offset_ptr: UnsafeMutablePointer) -> dispatch_data_t { fatalError() } @@ -163,19 +165,19 @@ public func dispatch_get_main_queue() -> DispatchQueue } @available(*, unavailable, renamed:"DispatchQueueAttributes.initiallyInactive") -public func dispatch_queue_attr_make_initially_inactive(_ attr: __OS_dispatch_queue_attr?) -> __OS_dispatch_queue_attr +public func dispatch_queue_attr_make_initially_inactive(_ attr: dispatch_queue_attr_t?) -> dispatch_queue_attr_t { 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 +public func dispatch_queue_attr_make_with_autorelease_frequency(_ attr: dispatch_queue_attr_t?, _ frequency: dispatch_autorelease_frequency_t) -> dispatch_queue_attr_t { 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 +public func dispatch_queue_attr_make_with_qos_class(_ attr: dispatch_queue_attr_t?, _ qos_class: dispatch_qos_class_t, _ relative_priority: Int32) -> dispatch_queue_attr_t { fatalError() } @@ -187,7 +189,7 @@ public func dispatch_queue_get_label(_ queue: DispatchQueue?) -> UnsafePointer?) -> qos_class_t +public func dispatch_queue_get_qos_class(_ queue: DispatchQueue, _ relative_priority_ptr: UnsafeMutablePointer?) -> dispatch_qos_class_t { fatalError() } @@ -259,7 +261,7 @@ public func dispatch_semaphore_signal(_ dsema: DispatchSemaphore) -> Int } @available(*, unavailable, message:"Use DispatchSource class methods") -public func dispatch_source_create(_ type: __dispatch_source_type_t, _ handle: UInt, _ mask: UInt, _ queue: DispatchQueue?) -> DispatchSource +public func dispatch_source_create(_ type: dispatch_source_type_t, _ handle: UInt, _ mask: UInt, _ queue: DispatchQueue?) -> DispatchSource { fatalError() } diff --git a/src/swift/Queue.swift b/src/swift/Queue.swift index 6f7b541e9..1710846f0 100644 --- a/src/swift/Queue.swift +++ b/src/swift/Queue.swift @@ -12,6 +12,8 @@ // dispatch/queue.h +import CDispatch + public struct DispatchQueueAttributes : OptionSet { public let rawValue: UInt64 public init(rawValue: UInt64) { self.rawValue = rawValue } @@ -49,38 +51,38 @@ public struct DispatchQueueAttributes : OptionSet { @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? + private var attr: dispatch_queue_attr_t? { + var attr: dispatch_queue_attr_t? 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) + attr = CDispatch.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)) + attr = CDispatch.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)) + attr = CDispatch.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)) + attr = CDispatch.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) + attr = CDispatch.dispatch_queue_attr_make_with_qos_class(attr, _OSQoSClass.QOS_CLASS_USER_INTERACTIVE.rawValue, 0) } else if self.contains(.qosUserInitiated) { - attr = __dispatch_queue_attr_make_with_qos_class(attr, QOS_CLASS_USER_INITIATED, 0) + attr = CDispatch.dispatch_queue_attr_make_with_qos_class(attr, _OSQoSClass.QOS_CLASS_USER_INITIATED.rawValue, 0) } else if self.contains(.qosDefault) { - attr = __dispatch_queue_attr_make_with_qos_class(attr, QOS_CLASS_DEFAULT, 0) + attr = CDispatch.dispatch_queue_attr_make_with_qos_class(attr, _OSQoSClass.QOS_CLASS_DEFAULT.rawValue, 0) } else if self.contains(.qosUtility) { - attr = __dispatch_queue_attr_make_with_qos_class(attr, QOS_CLASS_UTILITY, 0) + attr = CDispatch.dispatch_queue_attr_make_with_qos_class(attr, _OSQoSClass.QOS_CLASS_UTILITY.rawValue, 0) } else if self.contains(.qosBackground) { - attr = __dispatch_queue_attr_make_with_qos_class(attr, QOS_CLASS_BACKGROUND, 0) + attr = CDispatch.dispatch_queue_attr_make_with_qos_class(attr, _OSQoSClass.QOS_CLASS_BACKGROUND.rawValue, 0) } } return attr @@ -143,11 +145,11 @@ public extension DispatchQueue { 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(.qosUserInteractive) { return Int(_OSQoSClass.QOS_CLASS_USER_INTERACTIVE.rawValue) } + else if self.contains(.qosUserInitiated) { return Int(_OSQoSClass.QOS_CLASS_USER_INITIATED.rawValue) } + else if self.contains(.qosDefault) { return Int(_OSQoSClass.QOS_CLASS_DEFAULT.rawValue) } + else if self.contains(.qosUtility) { return Int(_OSQoSClass.QOS_CLASS_UTILITY.rawValue) } + else { return Int(_OSQoSClass.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 @@ -162,16 +164,17 @@ public extension DispatchQueue { } public class var main: DispatchQueue { - return _swift_dispatch_get_main_queue() + return DispatchQueue(queue: _swift_dispatch_get_main_queue()) } public class func global(attributes: GlobalAttributes = []) -> DispatchQueue { - return __dispatch_get_global_queue(attributes._translatedValue, 0) + // SubOptimal? Should we be caching these global DispatchQueue objects? + return DispatchQueue(queue: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) { + if let p = CDispatch.dispatch_get_specific(k) { let v = Unmanaged<_DispatchSpecificValue> .fromOpaque(p) .takeUnretainedValue() @@ -194,14 +197,12 @@ public extension DispatchQueue { } public var label: String { - return String(validatingUTF8: __dispatch_queue_get_label(self))! + return String(validatingUTF8: dispatch_queue_get_label(self.__wrapped))! } @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) + dispatch_sync(self.__wrapped, workItem._block) } @available(OSX 10.10, iOS 8.0, *) @@ -209,37 +210,37 @@ public extension DispatchQueue { // _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) + dispatch_group_async(g.__wrapped, self.__wrapped, workItem._block) } else { - _swift_dispatch_async(self, workItem._block) + dispatch_async(self.__wrapped, 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) + dispatch_async(self.__wrapped, 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) + dispatch_group_async(g.__wrapped, self.__wrapped, workItem._block) } else { - _swift_dispatch_async(self, workItem._block) + dispatch_async(self.__wrapped, workItem._block) } } else { if let g = group { - __dispatch_group_async(g, self, work) + dispatch_group_async(g.__wrapped, self.__wrapped, work) } else { - __dispatch_async(self, work) + dispatch_async(self.__wrapped, work) } } } private func _syncBarrier(block: @noescape () -> ()) { - __dispatch_barrier_sync(self, block) + dispatch_barrier_sync(self.__wrapped, block) } private func _syncHelper( @@ -304,41 +305,41 @@ public extension DispatchQueue { 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) + dispatch_after(when.rawValue, self.__wrapped, item._block) } else { - __dispatch_after(when.rawValue, self, work) + dispatch_after(when.rawValue, self.__wrapped, work) } } @available(OSX 10.10, iOS 8.0, *) public func after(when: DispatchTime, execute: DispatchWorkItem) { - __dispatch_after(when.rawValue, self, execute._block) + dispatch_after(when.rawValue, self.__wrapped, 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) + dispatch_after(when.rawValue, self.__wrapped, item._block) } else { - __dispatch_after(when.rawValue, self, work) + dispatch_after(when.rawValue, self.__wrapped, work) } } @available(OSX 10.10, iOS 8.0, *) public func after(walltime when: DispatchWallTime, execute: DispatchWorkItem) { - __dispatch_after(when.rawValue, self, execute._block) + dispatch_after(when.rawValue, self.__wrapped, 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))! + let cls = DispatchQoS.QoSClass(qosClass: _OSQoSClass(qosClass: dispatch_queue_get_qos_class(self.__wrapped, &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) { + if let p = dispatch_queue_get_specific(self.__wrapped, k) { let v = Unmanaged<_DispatchSpecificValue> .fromOpaque(p) .takeUnretainedValue() @@ -351,7 +352,7 @@ public extension DispatchQueue { 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) + dispatch_queue_set_specific(self.__wrapped, k, p, _destructDispatchSpecificValue) } } @@ -408,22 +409,13 @@ private func _destructDispatchSpecificValue(ptr: UnsafeMutablePointer?) { } @_silgen_name("_swift_dispatch_queue_concurrent") -internal func _swift_dispatch_queue_concurrent() -> __OS_dispatch_queue_attr +internal func _swift_dispatch_queue_concurrent() -> dispatch_queue_attr_t @_silgen_name("_swift_dispatch_get_main_queue") -internal func _swift_dispatch_get_main_queue() -> DispatchQueue +internal func _swift_dispatch_get_main_queue() -> dispatch_queue_t @_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) +internal func _swift_dispatch_apply_current_root_queue() -> dispatch_queue_t @_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 index 6ea3960f0..2830f010e 100644 --- a/src/swift/Source.swift +++ b/src/swift/Source.swift @@ -10,51 +10,50 @@ // //===----------------------------------------------------------------------===// -// import Foundation +import CDispatch 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) + CDispatch.dispatch_source_set_event_handler((self as! DispatchSource).__wrapped, item._block) } else { - __dispatch_source_set_event_handler(self as! DispatchSource, handler) + CDispatch.dispatch_source_set_event_handler((self as! DispatchSource).__wrapped, handler) } } @available(OSX 10.10, iOS 8.0, *) public func setEventHandler(handler: DispatchWorkItem) { - __dispatch_source_set_event_handler(self as! DispatchSource, handler._block) + CDispatch.dispatch_source_set_event_handler((self as! DispatchSource).__wrapped, 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) + CDispatch.dispatch_source_set_cancel_handler((self as! DispatchSource).__wrapped, item._block) } else { - __dispatch_source_set_cancel_handler(self as! DispatchSource, handler) + CDispatch.dispatch_source_set_cancel_handler((self as! DispatchSource).__wrapped, handler) } } @available(OSX 10.10, iOS 8.0, *) public func setCancelHandler(handler: DispatchWorkItem) { - __dispatch_source_set_cancel_handler(self as! DispatchSource, handler._block) + CDispatch.dispatch_source_set_cancel_handler((self as! DispatchSource).__wrapped, 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) + CDispatch.dispatch_source_set_registration_handler((self as! DispatchSource).__wrapped, item._block) } else { - __dispatch_source_set_registration_handler(self as! DispatchSource, handler) + CDispatch.dispatch_source_set_registration_handler((self as! DispatchSource).__wrapped, handler) } } @available(OSX 10.10, iOS 8.0, *) public func setRegistrationHandler(handler: DispatchWorkItem) { - __dispatch_source_set_registration_handler(self as! DispatchSource, handler._block) + CDispatch.dispatch_source_set_registration_handler((self as! DispatchSource).__wrapped, handler._block) } @available(OSX 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *) @@ -63,7 +62,7 @@ public extension DispatchSourceType { } public func cancel() { - __dispatch_source_cancel(self as! DispatchSource) + CDispatch.dispatch_source_cancel((self as! DispatchSource).__wrapped) } public func resume() { @@ -75,30 +74,33 @@ public extension DispatchSourceType { } public var handle: UInt { - return __dispatch_source_get_handle(self as! DispatchSource) + return CDispatch.dispatch_source_get_handle((self as! DispatchSource).__wrapped) } public var mask: UInt { - return __dispatch_source_get_mask(self as! DispatchSource) + return CDispatch.dispatch_source_get_mask((self as! DispatchSource).__wrapped) } public var data: UInt { - return __dispatch_source_get_data(self as! DispatchSource) + return CDispatch.dispatch_source_get_data((self as! DispatchSource).__wrapped) } public var isCancelled: Bool { - return __dispatch_source_testcancel(self as! DispatchSource) != 0 + return CDispatch.dispatch_source_testcancel((self as! DispatchSource).__wrapped) != 0 } } public extension DispatchSource { +#if HAVE_MACH public struct MachSendEvent : OptionSet, RawRepresentable { public let rawValue: UInt public init(rawValue: UInt) { self.rawValue = rawValue } public static let dead = MachSendEvent(rawValue: 0x1) } +#endif +#if HAVE_MACH public struct MemoryPressureEvent : OptionSet, RawRepresentable { public let rawValue: UInt public init(rawValue: UInt) { self.rawValue = rawValue } @@ -108,7 +110,9 @@ public extension DispatchSource { public static let critical = MemoryPressureEvent(rawValue: 0x4) public static let all: MemoryPressureEvent = [.normal, .warning, .critical] } +#endif +#if !os(Linux) public struct ProcessEvent : OptionSet, RawRepresentable { public let rawValue: UInt public init(rawValue: UInt) { self.rawValue = rawValue } @@ -119,6 +123,7 @@ public extension DispatchSource { public static let signal = ProcessEvent(rawValue: 0x08000000) public static let all: ProcessEvent = [.exit, .fork, .exec, .signal] } +#endif public struct TimerFlags : OptionSet, RawRepresentable { public let rawValue: UInt @@ -144,132 +149,153 @@ public extension DispatchSource { .delete, .write, .extend, .attrib, .link, .rename, .revoke] } +#if HAVE_MACH 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 + let source = dispatch_source_create(_swift_dispatch_source_type_mach_send(), UInt(port), eventMask.rawValue, queue?.__wrapped) + return DispatchSource(source: source) as DispatchSourceMachSend } +#endif +#if HAVE_MACH 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 + let source = dispatch_source_create(_swift_dispatch_source_type_mach_recv(), UInt(port), 0, queue?.__wrapped) + return DispatchSource(source) as DispatchSourceMachReceive } +#endif +#if HAVE_MACH 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 + let source = dispatch_source_create(_swift_dispatch_source_type_memorypressure(), 0, eventMask.rawValue, queue.__wrapped) + return DispatchSourceMemoryPressure(source) } +#endif +#if !os(Linux) 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 + let source = dispatch_source_create(_swift_dispatch_source_type_proc(), UInt(identifier), eventMask.rawValue, queue?.__wrapped) + return DispatchSource(source: source) as DispatchSourceProcess } +#endif 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 + let source = dispatch_source_create(_swift_dispatch_source_type_read(), UInt(fileDescriptor), 0, queue?.__wrapped) + return DispatchSource(source: source) 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 + let source = dispatch_source_create(_swift_dispatch_source_type_signal(), UInt(signal), 0, queue?.__wrapped) + return DispatchSource(source: source) 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 + let source = dispatch_source_create(_swift_dispatch_source_type_timer(), 0, flags.rawValue, queue?.__wrapped) + return DispatchSource(source: source) 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 + let source = dispatch_source_create(_swift_dispatch_source_type_data_add(), 0, 0, queue?.__wrapped) + return DispatchSource(source: source) 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 + let source = dispatch_source_create(_swift_dispatch_source_type_data_or(), 0, 0, queue?.__wrapped) + return DispatchSource(source: source) as DispatchSourceUserDataOr } +#if !os(Linux) 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 + let source = dispatch_source_create(_swift_dispatch_source_type_vnode(), UInt(fileDescriptor), eventMask.rawValue, queue?.__wrapped) + return DispatchSource(source: source) as DispatchSourceFileSystemObject } +#endif 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 + let source = dispatch_source_create(_swift_dispatch_source_type_write(), UInt(fileDescriptor), 0, queue?.__wrapped) + return DispatchSource(source: source) as DispatchSourceWrite } } +#if HAVE_MACH public extension DispatchSourceMachSend { public var handle: mach_port_t { - return mach_port_t(__dispatch_source_get_handle(self as! DispatchSource)) + 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) + 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) + let mask = dispatch_source_get_mask(self as! DispatchSource) return DispatchSource.MachSendEvent(rawValue: mask) } } +#endif +#if HAVE_MACH public extension DispatchSourceMachReceive { public var handle: mach_port_t { - return mach_port_t(__dispatch_source_get_handle(self as! DispatchSource)) + return mach_port_t(dispatch_source_get_handle(self as! DispatchSource)) } } +#endif +#if HAVE_MACH public extension DispatchSourceMemoryPressure { public var data: DispatchSource.MemoryPressureEvent { - let data = __dispatch_source_get_data(self as! DispatchSource) + 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) + let mask = dispatch_source_get_mask(self as! DispatchSource) return DispatchSource.MemoryPressureEvent(rawValue: mask) } } +#endif +#if !os(Linux) public extension DispatchSourceProcess { public var handle: pid_t { - return pid_t(__dispatch_source_get_handle(self as! DispatchSource)) + return pid_t(dispatch_source_get_handle(self as! DispatchSource)) } public var data: DispatchSource.ProcessEvent { - let data = __dispatch_source_get_data(self as! DispatchSource) + 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) + let mask = dispatch_source_get_mask(self as! DispatchSource) return DispatchSource.ProcessEvent(rawValue: mask) } } +#endif 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)) + dispatch_source_set_timer((self as! DispatchSource).__wrapped, 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)) + dispatch_source_set_timer((self as! DispatchSource).__wrapped, 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)) + dispatch_source_set_timer((self as! DispatchSource).__wrapped, 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)) + dispatch_source_set_timer((self as! DispatchSource).__wrapped, 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)) + dispatch_source_set_timer((self as! DispatchSource).__wrapped, 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)) + dispatch_source_set_timer((self as! DispatchSource).__wrapped, wallDeadline.rawValue, UInt64(interval * Double(NSEC_PER_SEC)), UInt64(leeway.rawValue)) } } @@ -300,26 +326,28 @@ public extension DispatchSourceTimer { } @available(*, deprecated, renamed: "DispatchSourceTimer.scheduleRepeating(self:wallDeadline:interval:leeway:)") - public func setTimer(walltime start: DispatchWalltime, interval: Double, leeway: DispatchTimeInterval = .nanoseconds(0)) { + public func setTimer(walltime start: DispatchWallTime, interval: Double, leeway: DispatchTimeInterval = .nanoseconds(0)) { scheduleRepeating(wallDeadline: start, interval: interval, leeway: leeway) } } +#if !os(Linux) public extension DispatchSourceFileSystemObject { public var handle: Int32 { - return Int32(__dispatch_source_get_handle(self as! DispatchSource)) + return Int32(dispatch_source_get_handle((self as! DispatchSource).__wrapped)) } public var data: DispatchSource.FileSystemEvent { - let data = __dispatch_source_get_data(self as! DispatchSource) + let data = dispatch_source_get_data((self as! DispatchSource).__wrapped) return DispatchSource.FileSystemEvent(rawValue: data) } public var mask: DispatchSource.FileSystemEvent { - let data = __dispatch_source_get_mask(self as! DispatchSource) + let data = dispatch_source_get_mask((self as! DispatchSource).__wrapped) return DispatchSource.FileSystemEvent(rawValue: data) } } +#endif public extension DispatchSourceUserDataAdd { /// @function mergeData @@ -334,11 +362,12 @@ public extension DispatchSourceUserDataAdd { /// 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) + dispatch_source_merge_data((self as! DispatchSource).__wrapped, value) } } public extension DispatchSourceUserDataOr { +#if false /*FIXME: clashes with UserDataAdd?? */ /// @function mergeData /// /// @abstract @@ -351,39 +380,46 @@ public extension DispatchSourceUserDataOr { /// 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) + dispatch_source_merge_data((self as! DispatchSource).__wrapped, value) } +#endif } @_silgen_name("_swift_dispatch_source_type_DATA_ADD") -internal func _swift_dispatch_source_type_data_add() -> __dispatch_source_type_t +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 +internal func _swift_dispatch_source_type_data_or() -> dispatch_source_type_t +#if HAVE_MACH @_silgen_name("_swift_dispatch_source_type_MACH_SEND") -internal func _swift_dispatch_source_type_mach_send() -> __dispatch_source_type_t +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 +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 +internal func _swift_dispatch_source_type_memorypressure() -> dispatch_source_type_t +#endif +#if !os(Linux) @_silgen_name("_swift_dispatch_source_type_PROC") -internal func _swift_dispatch_source_type_proc() -> __dispatch_source_type_t +internal func _swift_dispatch_source_type_proc() -> dispatch_source_type_t +#endif @_silgen_name("_swift_dispatch_source_type_READ") -internal func _swift_dispatch_source_type_read() -> __dispatch_source_type_t +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 +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 +internal func _swift_dispatch_source_type_timer() -> dispatch_source_type_t +#if !os(Linux) @_silgen_name("_swift_dispatch_source_type_VNODE") -internal func _swift_dispatch_source_type_vnode() -> __dispatch_source_type_t +internal func _swift_dispatch_source_type_vnode() -> dispatch_source_type_t +#endif @_silgen_name("_swift_dispatch_source_type_WRITE") -internal func _swift_dispatch_source_type_write() -> __dispatch_source_type_t +internal func _swift_dispatch_source_type_write() -> dispatch_source_type_t diff --git a/src/swift/Time.swift b/src/swift/Time.swift index e0b63b814..76a6979eb 100644 --- a/src/swift/Time.swift +++ b/src/swift/Time.swift @@ -14,11 +14,13 @@ // DISPATCH_TIME_NOW: ok // DISPATCH_TIME_FOREVER: ok +import CDispatch + public struct DispatchTime { public let rawValue: dispatch_time_t public static func now() -> DispatchTime { - let t = __dispatch_time(0, 0) + let t = CDispatch.dispatch_time(0, 0) return DispatchTime(rawValue: t) } @@ -33,7 +35,7 @@ public struct DispatchWallTime { public let rawValue: dispatch_time_t public static func now() -> DispatchWallTime { - return DispatchWallTime(rawValue: __dispatch_walltime(nil, 0)) + return DispatchWallTime(rawValue: CDispatch.dispatch_walltime(nil, 0)) } public static let distantFuture = DispatchWallTime(rawValue: ~0) @@ -44,7 +46,7 @@ public struct DispatchWallTime { public init(time: timespec) { var t = time - self.rawValue = __dispatch_walltime(&t, 0) + self.rawValue = CDispatch.dispatch_walltime(&t, 0) } } @@ -68,41 +70,41 @@ public enum DispatchTimeInterval { } public func +(time: DispatchTime, interval: DispatchTimeInterval) -> DispatchTime { - let t = __dispatch_time(time.rawValue, Int64(interval.rawValue)) + let t = CDispatch.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)) + let t = CDispatch.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))) + let t = CDispatch.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))) + let t = CDispatch.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)) + let t = CDispatch.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)) + let t = CDispatch.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))) + let t = CDispatch.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))) + let t = CDispatch.dispatch_time(time.rawValue, Int64(-seconds * Double(NSEC_PER_SEC))) return DispatchWallTime(rawValue: t) } diff --git a/src/swift/Wrapper.swift b/src/swift/Wrapper.swift new file mode 100644 index 000000000..a0d1e8e4f --- /dev/null +++ b/src/swift/Wrapper.swift @@ -0,0 +1,297 @@ +//===----------------------------------------------------------------------===// +// +// 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 CDispatch + +// This file contains declarations that are provided by the +// importer via Dispatch.apinote when the platform has Objective-C support + +public class DispatchObject { + // TODO: add deinit method to invoke dispatch_release on wrapped() + + internal func wrapped() -> dispatch_object_t { + assert(false, "should be override in subclass") + } + + public func setTarget(queue:DispatchQueue) { + dispatch_set_target_queue(wrapped(), queue.__wrapped) + } + + public func activate() { + dispatch_activate(wrapped()) + } + + public func suspend() { + dispatch_suspend(wrapped()) + } + + public func resume() { + dispatch_resume(wrapped()) + } +} + + +public class DispatchGroup : DispatchObject { + internal let __wrapped:dispatch_group_t; + + internal override func wrapped() -> dispatch_object_t { + return unsafeBitCast(__wrapped, to: dispatch_object_t.self) + } + + public override init() { + __wrapped = dispatch_group_create() + } + + public func enter() { + dispatch_group_enter(__wrapped) + } + + public func leave() { + dispatch_group_enter(__wrapped) + } +} + +public class DispatchSemaphore : DispatchObject { + internal let __wrapped: dispatch_semaphore_t; + + internal override func wrapped() -> dispatch_object_t { + return unsafeBitCast(__wrapped, to: dispatch_object_t.self) + } + + public init(value: Int) { + __wrapped = dispatch_semaphore_create(value) + } +} + +public class DispatchIO : DispatchObject { + internal let __wrapped:dispatch_io_t + + internal override func wrapped() -> dispatch_object_t { + return unsafeBitCast(__wrapped, to: dispatch_object_t.self) + } + + internal init(__type: UInt, fd: Int32, queue: DispatchQueue, + handler: (error: Int32) -> Void) { + __wrapped = dispatch_io_create(__type, fd, queue.__wrapped, handler) + } + + internal init(__type: UInt, path: UnsafePointer, oflag: Int32, + mode: mode_t, queue: DispatchQueue, handler: (error: Int32) -> Void) { + __wrapped = dispatch_io_create_with_path(__type, path, oflag, mode, queue.__wrapped, handler) + } + + internal init(__type: UInt, io: DispatchIO, + queue: DispatchQueue, handler: (error: Int32) -> Void) { + __wrapped = dispatch_io_create_with_io(__type, io.__wrapped, queue.__wrapped, handler) + } + + internal init(queue:dispatch_queue_t) { + __wrapped = queue + } + + public func barrier(execute: () -> ()) { + dispatch_io_barrier(self.__wrapped, execute) + } + + public var fileDescriptor: Int32 { + return dispatch_io_get_descriptor(__wrapped) + } + + public func setLimit(highWater: Int) { + dispatch_io_set_high_water(__wrapped, highWater) + } + + public func setLimit(lowWater: Int) { + dispatch_io_set_low_water(__wrapped, lowWater) + } +} + +public class DispatchQueue : DispatchObject { + internal let __wrapped:dispatch_queue_t; + + internal override func wrapped() -> dispatch_object_t { + return unsafeBitCast(__wrapped, to: dispatch_object_t.self) + } + + internal init(__label: String, attr: dispatch_queue_attr_t?) { + __wrapped = dispatch_queue_create(__label, attr) + } + + internal init(__label: String, attr: dispatch_queue_attr_t?, queue: DispatchQueue?) { + __wrapped = dispatch_queue_create_with_target(__label, attr, queue?.__wrapped) + } + + internal init(queue:dispatch_queue_t) { + __wrapped = queue + } + + public func sync(execute workItem: @noescape ()->()) { + dispatch_sync(self.__wrapped, workItem) + } +} + +public class DispatchSource : DispatchObject, + DispatchSourceType, DispatchSourceRead, + DispatchSourceSignal, DispatchSourceTimer, + DispatchSourceUserDataAdd, DispatchSourceUserDataOr, + DispatchSourceWrite { + internal let __wrapped:dispatch_source_t + + internal override func wrapped() -> dispatch_object_t { + return unsafeBitCast(__wrapped, to: dispatch_object_t.self) + } + + internal init(source:dispatch_source_t) { + __wrapped = source + } +} + +#if HAVE_MACH +extension DispatchSource : DispatchSourceMachSend, + DispatchSourceMachReceive, DispatchSourceMemoryPressure { +} +#endif + +#if !os(Linux) +extension DispatchSource : DispatchSourceProcess, + DispatchSourceFileSystemObject { +} +#endif + +public typealias DispatchSourceHandler = @convention(block) () -> Void + +public protocol DispatchSourceType { + func setEventHandler(qos: DispatchQoS, flags: DispatchWorkItemFlags, handler: DispatchSourceHandler?) + + func setEventHandler(handler: DispatchWorkItem) + + func setCancelHandler(qos: DispatchQoS, flags: DispatchWorkItemFlags, handler: DispatchSourceHandler?) + + func setCancelHandler(handler: DispatchWorkItem) + + func setRegistrationHandler(qos: DispatchQoS, flags: DispatchWorkItemFlags, handler: DispatchSourceHandler?) + + func setRegistrationHandler(handler: DispatchWorkItem) + + func cancel() + + func resume() + + func suspend() + + var handle: UInt { get } + + var mask: UInt { get } + + var data: UInt { get } + + var isCancelled: Bool { get } +} + +public protocol DispatchSourceUserDataAdd : DispatchSourceType { + func mergeData(value: UInt) +} + +public protocol DispatchSourceUserDataOr { +#if false /*FIXME: clashes with UserDataAdd?? */ + func mergeData(value: UInt) +#endif +} + +#if HAVE_MACH +public protocol DispatchSourceMachSend : DispatchSourceType { + public var handle: mach_port_t { get } + + public var data: DispatchSource.MachSendEvent { get } + + public var mask: DispatchSource.MachSendEvent { get } +} +#endif + +#if HAVE_MACH +public protocol DispatchSourceMachReceive : DispatchSourceType { + var handle: mach_port_t { get } +} +#endif + +#if HAVE_MACH +public protocol DispatchSourceMemoryPressure : DispatchSourceType { + public var data: DispatchSource.MemoryPressureEvent { get } + + public var mask: DispatchSource.MemoryPressureEvent { get } +} +#endif + +#if !os(Linux) +public protocol DispatchSourceProcess : DispatchSourceType { + var handle: pid_t { get } + + var data: DispatchSource.ProcessEvent { get } + + var mask: DispatchSource.ProcessEvent { get } +} +#endif + +public protocol DispatchSourceRead : DispatchSourceType { +} + +public protocol DispatchSourceSignal : DispatchSourceType { +} + +public protocol DispatchSourceTimer : DispatchSourceType { + func setTimer(start: DispatchTime, leeway: DispatchTimeInterval) + + func setTimer(walltime start: DispatchWallTime, leeway: DispatchTimeInterval) + + func setTimer(start: DispatchTime, interval: DispatchTimeInterval, leeway: DispatchTimeInterval) + + func setTimer(start: DispatchTime, interval: Double, leeway: DispatchTimeInterval) + + func setTimer(walltime start: DispatchWallTime, interval: DispatchTimeInterval, leeway: DispatchTimeInterval) + + func setTimer(walltime start: DispatchWallTime, interval: Double, leeway: DispatchTimeInterval) +} + +#if !os(Linux) +public protocol DispatchSourceFileSystemObject : DispatchSourceType { + var handle: Int32 { get } + + var data: DispatchSource.FileSystemEvent { get } + + var mask: DispatchSource.FileSystemEvent { get } +} +#endif + +public protocol DispatchSourceWrite : DispatchSourceType { +} + + +internal enum _OSQoSClass : UInt32 { + case QOS_CLASS_USER_INTERACTIVE = 0x21 + case QOS_CLASS_USER_INITIATED = 0x19 + case QOS_CLASS_DEFAULT = 0x15 + case QOS_CLASS_UTILITY = 0x11 + case QOS_CLASS_BACKGROUND = 0x09 + case QOS_CLASS_UNSPECIFIED = 0x00 + + internal init?(qosClass:dispatch_qos_class_t) { + switch qosClass { + case 0x21: self = .QOS_CLASS_USER_INTERACTIVE + case 0x19: self = .QOS_CLASS_USER_INITIATED + case 0x15: self = .QOS_CLASS_DEFAULT + case 0x11: self = QOS_CLASS_UTILITY + case 0x09: self = QOS_CLASS_BACKGROUND + case 0x00: self = QOS_CLASS_UNSPECIFIED + default: return nil + } + } +} diff --git a/tests/Makefile.am b/tests/Makefile.am index fa37f8a00..c7776e468 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -121,7 +121,11 @@ if HAVE_PTHREAD_WORKQUEUES endif endif -LDADD=libbsdtests.la $(top_builddir)/src/libdispatch.la $(KQUEUE_LIBS) $(PTHREAD_WORKQUEUE_LIBS) $(BSD_OVERLAY_LIBS) +if HAVE_SWIFT + SWIFT_LIBS=-L$(SWIFT_LIBDIR) -lswiftCore +endif + +LDADD=libbsdtests.la $(top_builddir)/src/libdispatch.la $(KQUEUE_LIBS) $(PTHREAD_WORKQUEUE_LIBS) $(BSD_OVERLAY_LIBS) $(SWIFT_LIBS) libbsdtests_la_LDFLAGS=-avoid-version bsdtestsummarize_LDADD=-lm $(BSD_OVERLAY_LIBS)