//===----------------------------------------------------------------------===// // // 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 https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// import CDispatch import _SwiftDispatchOverlayShims public struct DispatchWorkItemFlags : OptionSet, RawRepresentable { public let rawValue: UInt public init(rawValue: UInt) { self.rawValue = rawValue } public static let barrier = DispatchWorkItemFlags(rawValue: 0x1) @available(macOS 10.10, iOS 8.0, *) public static let detached = DispatchWorkItemFlags(rawValue: 0x2) @available(macOS 10.10, iOS 8.0, *) public static let assignCurrentContext = DispatchWorkItemFlags(rawValue: 0x4) @available(macOS 10.10, iOS 8.0, *) public static let noQoS = DispatchWorkItemFlags(rawValue: 0x8) @available(macOS 10.10, iOS 8.0, *) public static let inheritQoS = DispatchWorkItemFlags(rawValue: 0x10) @available(macOS 10.10, iOS 8.0, *) public static let enforceQoS = DispatchWorkItemFlags(rawValue: 0x20) } @available(macOS 10.10, iOS 8.0, *) public class DispatchWorkItem { internal var _block: _DispatchBlock public init(qos: DispatchQoS = .unspecified, flags: DispatchWorkItemFlags = [], block: @escaping @convention(block) () -> ()) { _block = dispatch_block_create_with_qos_class(dispatch_block_flags_t(UInt32(flags.rawValue)), qos.qosClass.rawValue.rawValue, Int32(qos.relativePriority), block) } // Used by DispatchQueue.synchronously to provide a path through // dispatch_block_t, as we know the lifetime of the block in question. internal init(flags: DispatchWorkItemFlags = [], noescapeBlock: () -> ()) { _block = _swift_dispatch_block_create_noescape(dispatch_block_flags_t(UInt32(flags.rawValue)), noescapeBlock) } public func perform() { _block() } public func wait() { _ = dispatch_block_wait(_block, DispatchTime.distantFuture.rawValue) } public func wait(timeout: DispatchTime) -> DispatchTimeoutResult { return dispatch_block_wait(_block, timeout.rawValue) == 0 ? .success : .timedOut } public func wait(wallTimeout: DispatchWallTime) -> DispatchTimeoutResult { return dispatch_block_wait(_block, wallTimeout.rawValue) == 0 ? .success : .timedOut } public func notify( qos: DispatchQoS = .unspecified, flags: DispatchWorkItemFlags = [], queue: DispatchQueue, execute: @escaping @convention(block) () -> ()) { if qos != .unspecified || !flags.isEmpty { let item = DispatchWorkItem(qos: qos, flags: flags, block: execute) dispatch_block_notify(_block, queue.__wrapped, item._block) } else { dispatch_block_notify(_block, queue.__wrapped, execute) } } public func notify(queue: DispatchQueue, execute: DispatchWorkItem) { dispatch_block_notify(_block, queue.__wrapped, execute._block) } public func cancel() { dispatch_block_cancel(_block) } public var isCancelled: Bool { return dispatch_block_testcancel(_block) != 0 } } /// 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 internal typealias dispatch_block_t = @convention(block) () -> Void