0001    //
0002    //  Async.swift
0003    //
0004    //  Created by Tobias DM on 15/07/14.
0005    //
0006    //	OS X 10.10+ and iOS 8.0+
0007    //	Only use with ARC
0008    //
0009    //	The MIT License (MIT)
0010    //	Copyright (c) 2014 Tobias Due Munk
0011    //
0012    //	Permission is hereby granted, free of charge, to any person obtaining a copy of
0013    //	this software and associated documentation files (the "Software"), to deal in
0014    //	the Software without restriction, including without limitation the rights to
0015    //	use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
0016    //	the Software, and to permit persons to whom the Software is furnished to do so,
0017    //	subject to the following conditions:
0018    //
0019    //	The above copyright notice and this permission notice shall be included in all
0020    //	copies or substantial portions of the Software.
0021    //
0022    //	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0023    //	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
0024    //	FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
0025    //	COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
0026    //	IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
0027    //	CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
0028    
0029    
0030    import Foundation
0031    
0032    
0033    // MARK: - DSL for GCD queues
0034    
0035    /**
0036    `GCD` is an empty struct with convenience static functions to get `dispatch_queue_t` of different quality of service classes, as provided by `dispatch_get_global_queue`.
0037    
0038    let utilityQueue = GCD.utilityQueue()
0039    
0040    - SeeAlso: Grand Central Dispatch
0041    */
0042    private struct GCD
Async.swift:196
        return Async.async(after, block: block, queue: GCD.mainQueue())
Async.swift:211
        return Async.async(after, block: block, queue: GCD.userInteractiveQueue())
Async.swift:226
        return Async.async(after, block: block, queue: GCD.userInitiatedQueue())
Async.swift:241
        return Async.async(after, block: block, queue: GCD.utilityQueue())
Async.swift:256
        return Async.async(after, block: block, queue: GCD.backgroundQueue())
Async.swift:361
        return chain(after, block: chainingBlock, queue: GCD.mainQueue())
Async.swift:376
        return chain(after, block: chainingBlock, queue: GCD.userInteractiveQueue())
Async.swift:391
        return chain(after, block: chainingBlock, queue: GCD.userInitiatedQueue())
Async.swift:406
        return chain(after, block: chainingBlock, queue: GCD.utilityQueue())
Async.swift:421
        return chain(after, block: chainingBlock, queue: GCD.backgroundQueue())
Async.swift:584
        dispatch_apply(iterations, GCD.userInteractiveQueue(), block)
Async.swift:595
        dispatch_apply(iterations, GCD.userInitiatedQueue(), block)
Async.swift:606
        dispatch_apply(iterations, GCD.utilityQueue(), block)
Async.swift:617
        dispatch_apply(iterations, GCD.backgroundQueue(), block)
Async.swift:735
        async(block: block, queue: GCD.mainQueue())
Async.swift:745
        async(block: block, queue: GCD.userInteractiveQueue())
Async.swift:755
        async(block: block, queue: GCD.userInitiatedQueue())
Async.swift:766
        async(block: block, queue: GCD.utilityQueue())
Async.swift:776
        async(block: block, queue: GCD.backgroundQueue())
{ 0043 0044 /** 0045 Convenience function for `dispatch_get_main_queue()`. 0046 Returns the default queue that is bound to the main thread. 0047 0048 - Returns: The main queue. This queue is created automatically on behalf of the main thread before main() is called. 0049 0050 - SeeAlso: dispatch_get_main_queue 0051 */ 0052 static func mainQueue
Async.swift:196
        return Async.async(after, block: block, queue: GCD.mainQueue())
Async.swift:361
        return chain(after, block: chainingBlock, queue: GCD.mainQueue())
Async.swift:735
        async(block: block, queue: GCD.mainQueue())
() -> dispatch_queue_t { 0053 return dispatch_get_main_queue() 0054 // Don't ever use dispatch_get_global_queue(qos_class_main(), 0) re https://gist.github.com/duemunk/34babc7ca8150ff81844 0055 } 0056 0057 /** 0058 Convenience function for dispatch_get_global_queue, with the parameter QOS_CLASS_USER_INTERACTIVE 0059 Returns a system-defined global concurrent queue with the specified quality of service class. 0060 0061 - Returns: The global concurrent queue with quality of service class QOS_CLASS_USER_INTERACTIVE. 0062 0063 - SeeAlso: dispatch_get_global_queue 0064 */ 0065 static func userInteractiveQueue
Async.swift:211
        return Async.async(after, block: block, queue: GCD.userInteractiveQueue())
Async.swift:376
        return chain(after, block: chainingBlock, queue: GCD.userInteractiveQueue())
Async.swift:584
        dispatch_apply(iterations, GCD.userInteractiveQueue(), block)
Async.swift:745
        async(block: block, queue: GCD.userInteractiveQueue())
() -> dispatch_queue_t { 0066 return dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0) 0067 } 0068 0069 /** 0070 Convenience function for dispatch_get_global_queue, with the parameter QOS_CLASS_USER_INITIATED 0071 Returns a system-defined global concurrent queue with the specified quality of service class. 0072 0073 - Returns: The global concurrent queue with quality of service class QOS_CLASS_USER_INITIATED. 0074 0075 - SeeAlso: dispatch_get_global_queue 0076 */ 0077 static func userInitiatedQueue
Async.swift:226
        return Async.async(after, block: block, queue: GCD.userInitiatedQueue())
Async.swift:391
        return chain(after, block: chainingBlock, queue: GCD.userInitiatedQueue())
Async.swift:595
        dispatch_apply(iterations, GCD.userInitiatedQueue(), block)
Async.swift:755
        async(block: block, queue: GCD.userInitiatedQueue())
() -> dispatch_queue_t { 0078 return dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0) 0079 } 0080 0081 /** 0082 Convenience function for dispatch_get_global_queue, with the parameter QOS_CLASS_UTILITY 0083 Returns a system-defined global concurrent queue with the specified quality of service class. 0084 0085 - Returns: The global concurrent queue with quality of service class QOS_CLASS_UTILITY. 0086 0087 - SeeAlso: dispatch_get_global_queue 0088 */ 0089 static func utilityQueue
Async.swift:241
        return Async.async(after, block: block, queue: GCD.utilityQueue())
Async.swift:406
        return chain(after, block: chainingBlock, queue: GCD.utilityQueue())
Async.swift:606
        dispatch_apply(iterations, GCD.utilityQueue(), block)
Async.swift:766
        async(block: block, queue: GCD.utilityQueue())
() -> dispatch_queue_t { 0090 return dispatch_get_global_queue(QOS_CLASS_UTILITY, 0) 0091 } 0092 0093 /** 0094 Convenience function for dispatch_get_global_queue, with the parameter QOS_CLASS_BACKGROUND 0095 Returns a system-defined global concurrent queue with the specified quality of service class. 0096 0097 - Returns: The global concurrent queue with quality of service class QOS_CLASS_BACKGROUND. 0098 0099 - SeeAlso: dispatch_get_global_queue 0100 */ 0101 static func backgroundQueue
Async.swift:256
        return Async.async(after, block: block, queue: GCD.backgroundQueue())
Async.swift:421
        return chain(after, block: chainingBlock, queue: GCD.backgroundQueue())
Async.swift:617
        dispatch_apply(iterations, GCD.backgroundQueue(), block)
Async.swift:776
        async(block: block, queue: GCD.backgroundQueue())
() -> dispatch_queue_t { 0102 return dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0) 0103 } 0104 } 0105 0106 0107 // MARK: - Async – Struct 0108 0109 /** 0110 The **Async** struct is the main part of the Async.framework. Handles a internally `dispatch_block_t`. 0111 0112 Chainable dispatch blocks with GCD: 0113 0114 Async.background { 0115 // Run on background queue 0116 }.main { 0117 // Run on main queue, after the previous block 0118 } 0119 0120 All moderns queue classes: 0121 0122 Async.main {} 0123 Async.userInteractive {} 0124 Async.userInitiated {} 0125 Async.utility {} 0126 Async.background {} 0127 0128 Custom queues: 0129 0130 let customQueue = dispatch_queue_create("Label", DISPATCH_QUEUE_CONCURRENT) 0131 Async.customQueue(customQueue) {} 0132 0133 Dispatch block after delay: 0134 0135 let seconds = 0.5 0136 Async.main(after: seconds) {} 0137 0138 Cancel blocks not yet dispatched 0139 0140 let block1 = Async.background { 0141 // Some work 0142 } 0143 let block2 = block1.background { 0144 // Some other work 0145 } 0146 Async.main { 0147 // Cancel async to allow block1 to begin 0148 block1.cancel() // First block is NOT cancelled 0149 block2.cancel() // Second block IS cancelled 0150 } 0151 0152 Wait for block to finish: 0153 0154 let block = Async.background { 0155 // Do stuff 0156 } 0157 // Do other stuff 0158 // Wait for "Do stuff" to finish 0159 block.wait() 0160 // Do rest of stuff 0161 0162 - SeeAlso: Grand Central Dispatch 0163 */ 0164 public struct Async
Async.swift:195
    public static func main(after after: Double? = nil, block: dispatch_block_t) -> Async {
Async.swift:196
        return Async.async(after, block: block, queue: GCD.mainQueue())
Async.swift:210
    public static func userInteractive(after after: Double? = nil, block: dispatch_block_t) -> Async {
Async.swift:211
        return Async.async(after, block: block, queue: GCD.userInteractiveQueue())
Async.swift:225
    public static func userInitiated(after after: Double? = nil, block: dispatch_block_t) -> Async {
Async.swift:226
        return Async.async(after, block: block, queue: GCD.userInitiatedQueue())
Async.swift:240
    public static func utility(after after: Double? = nil, block: dispatch_block_t) -> Async {
Async.swift:241
        return Async.async(after, block: block, queue: GCD.utilityQueue())
Async.swift:255
    public static func background(after after: Double? = nil, block: dispatch_block_t) -> Async {
Async.swift:256
        return Async.async(after, block: block, queue: GCD.backgroundQueue())
Async.swift:270
    public static func customQueue(queue: dispatch_queue_t, after: Double? = nil, block: dispatch_block_t) -> Async {
Async.swift:271
        return Async.async(after, block: block, queue: queue)
Async.swift:287
    private static func async(seconds: Double? = nil, block chainingBlock: dispatch_block_t, queue: dispatch_queue_t) -> Async {
Async.swift:303
    private static func asyncNow(block: dispatch_block_t, queue: dispatch_queue_t) -> Async {
Async.swift:310
        return Async(_block)
Async.swift:323
    private static func asyncAfter(seconds: Double, block: dispatch_block_t, queue: dispatch_queue_t) -> Async {
Async.swift:339
    private static func at(time: dispatch_time_t, block: dispatch_block_t, queue: dispatch_queue_t) -> Async {
Async.swift:343
        return Async(_block)
Async.swift:360
    public func main(after after: Double? = nil, chainingBlock: dispatch_block_t) -> Async {
Async.swift:375
    public func userInteractive(after after: Double? = nil, chainingBlock: dispatch_block_t) -> Async {
Async.swift:390
    public func userInitiated(after after: Double? = nil, chainingBlock: dispatch_block_t) -> Async {
Async.swift:405
    public func utility(after after: Double? = nil, chainingBlock: dispatch_block_t) -> Async {
Async.swift:420
    public func background(after after: Double? = nil, chainingBlock: dispatch_block_t) -> Async {
Async.swift:435
    public func customQueue(queue: dispatch_queue_t, after: Double? = nil, chainingBlock: dispatch_block_t) -> Async {
Async.swift:496
    private func chain(seconds: Double? = nil, block chainingBlock: dispatch_block_t, queue: dispatch_queue_t) -> Async {
Async.swift:514
    private func chainNow(block chainingBlock: dispatch_block_t, queue: dispatch_queue_t) -> Async {
Async.swift:518
        return Async(_chainingBlock)
Async.swift:532
    private func chainAfter(seconds: Double, block chainingBlock: dispatch_block_t, queue: dispatch_queue_t) -> Async {
Async.swift:550
        return Async(_chainingBlock)
{ 0165 0166 0167 // MARK: - Private properties and init 0168 0169 /** 0170 Private property to hold internally on to a `dispatch_block_t` 0171 */ 0172 private let block
Async.swift:178
        self.block = block
Async.swift:461
        dispatch_block_cancel(block)
Async.swift:478
            dispatch_block_wait(block, time)
Async.swift:480
            dispatch_block_wait(block, DISPATCH_TIME_FOREVER)
Async.swift:517
        dispatch_block_notify(block, queue, _chainingBlock)
Async.swift:548
        dispatch_block_notify(self.block, queue, _chainingWrapperBlock)
: dispatch_block_t 0173 0174 /** 0175 Private init that takes a `dispatch_block_t` 0176 */ 0177 private init
Async.swift:310
        return Async(_block)
Async.swift:343
        return Async(_block)
Async.swift:518
        return Async(_chainingBlock)
Async.swift:550
        return Async(_chainingBlock)
(_ block: dispatch_block_t) { 0178 self.block = block 0179 } 0180 0181 0182 // MARK: - Static methods 0183 0184 /** 0185 Sends the a block to be run asynchronously on the main thread. 0186 0187 - parameters: 0188 - after: After how many seconds the block should be run. 0189 - block: The block that is to be passed to be run on the main queue 0190 0191 - returns: An `Async` struct 0192 0193 - SeeAlso: Has parity with non-static method 0194 */ 0195 public static func main(after after: Double? = nil, block: dispatch_block_t) -> Async { 0196 return Async.async(after, block: block, queue: GCD.mainQueue()) 0197 } 0198 0199 /** 0200 Sends the a block to be run asynchronously on a queue with a quality of service of QOS_CLASS_USER_INTERACTIVE. 0201 0202 - parameters: 0203 - after: After how many seconds the block should be run. 0204 - block: The block that is to be passed to be run on the queue 0205 0206 - returns: An `Async` struct 0207 0208 - SeeAlso: Has parity with non-static method 0209 */ 0210 public static func userInteractive(after after: Double? = nil, block: dispatch_block_t) -> Async { 0211 return Async.async(after, block: block, queue: GCD.userInteractiveQueue()) 0212 } 0213 0214 /** 0215 Sends the a block to be run asynchronously on a queue with a quality of service of QOS_CLASS_USER_INITIATED. 0216 0217 - parameters: 0218 - after: After how many seconds the block should be run. 0219 - block: The block that is to be passed to be run on the queue 0220 0221 - returns: An `Async` struct 0222 0223 - SeeAlso: Has parity with non-static method 0224 */ 0225 public static func userInitiated(after after: Double? = nil, block: dispatch_block_t) -> Async { 0226 return Async.async(after, block: block, queue: GCD.userInitiatedQueue()) 0227 } 0228 0229 /** 0230 Sends the a block to be run asynchronously on a queue with a quality of service of QOS_CLASS_UTILITY. 0231 0232 - parameters: 0233 - after: After how many seconds the block should be run. 0234 - block: The block that is to be passed to be run on queue 0235 0236 - returns: An `Async` struct 0237 0238 - SeeAlso: Has parity with non-static method 0239 */ 0240 public static func utility(after after: Double? = nil, block: dispatch_block_t) -> Async { 0241 return Async.async(after, block: block, queue: GCD.utilityQueue()) 0242 } 0243 0244 /** 0245 Sends the a block to be run asynchronously on a queue with a quality of service of QOS_CLASS_BACKGROUND. 0246 0247 - parameters: 0248 - after: After how many seconds the block should be run. 0249 - block: The block that is to be passed to be run on the queue 0250 0251 - returns: An `Async` struct 0252 0253 - SeeAlso: Has parity with non-static method 0254 */ 0255 public static func background(after after: Double? = nil, block: dispatch_block_t) -> Async { 0256 return Async.async(after, block: block, queue: GCD.backgroundQueue()) 0257 } 0258 0259 /** 0260 Sends the a block to be run asynchronously on a custom queue. 0261 0262 - parameters: 0263 - after: After how many seconds the block should be run. 0264 - block: The block that is to be passed to be run on the queue 0265 0266 - returns: An `Async` struct 0267 0268 - SeeAlso: Has parity with non-static method 0269 */ 0270 public static func customQueue(queue: dispatch_queue_t, after: Double? = nil, block: dispatch_block_t) -> Async { 0271 return Async.async(after, block: block, queue: queue) 0272 } 0273 0274 0275 // MARK: - Private static methods 0276 0277 /** 0278 Convenience for `asyncNow()` or `asyncAfter()` depending on if the parameter `seconds` is passed or nil. 0279 0280 - parameters: 0281 - seconds: After how many seconds the block should be run. 0282 - block: The block that is to be passed to be run on the `queue` 0283 - queue: The queue on which the `block` is run. 0284 0285 - returns: An `Async` struct which encapsulates the `dispatch_block_t` 0286 */ 0287 private static func async
Async.swift:196
        return Async.async(after, block: block, queue: GCD.mainQueue())
Async.swift:211
        return Async.async(after, block: block, queue: GCD.userInteractiveQueue())
Async.swift:226
        return Async.async(after, block: block, queue: GCD.userInitiatedQueue())
Async.swift:241
        return Async.async(after, block: block, queue: GCD.utilityQueue())
Async.swift:256
        return Async.async(after, block: block, queue: GCD.backgroundQueue())
Async.swift:271
        return Async.async(after, block: block, queue: queue)
(seconds: Double? = nil, block chainingBlock: dispatch_block_t, queue: dispatch_queue_t) -> Async { 0288 if let seconds = seconds { 0289 return asyncAfter(seconds, block: chainingBlock, queue: queue) 0290 } 0291 return asyncNow(chainingBlock, queue: queue) 0292 } 0293 0294 /** 0295 Convenience for dispatch_async(). Encapsulates the block in a "true" GCD block using DISPATCH_BLOCK_INHERIT_QOS_CLASS. 0296 0297 - parameters: 0298 - block: The block that is to be passed to be run on the `queue` 0299 - queue: The queue on which the `block` is run. 0300 0301 - returns: An `Async` struct which encapsulates the `dispatch_block_t` 0302 */ 0303 private static func asyncNow
Async.swift:291
        return asyncNow(chainingBlock, queue: queue)
(block: dispatch_block_t, queue: dispatch_queue_t) -> Async { 0304 // Create a new block (Qos Class) from block to allow adding a notification to it later (see matching regular Async methods) 0305 // Create block with the "inherit" type 0306 let _block = dispatch_block_create(DISPATCH_BLOCK_INHERIT_QOS_CLASS, block) 0307 // Add block to queue 0308 dispatch_async(queue, _block) 0309 // Wrap block in a struct since dispatch_block_t can't be extended 0310 return Async(_block) 0311 } 0312 0313 /** 0314 Convenience for dispatch_after(). Encapsulates the block in a "true" GCD block using DISPATCH_BLOCK_INHERIT_QOS_CLASS. 0315 0316 - parameters: 0317 - seconds: After how many seconds the block should be run. 0318 - block: The block that is to be passed to be run on the `queue` 0319 - queue: The queue on which the `block` is run. 0320 0321 - returns: An `Async` struct which encapsulates the `dispatch_block_t` 0322 */ 0323 private static func asyncAfter
Async.swift:289
            return asyncAfter(seconds, block: chainingBlock, queue: queue)
(seconds: Double, block: dispatch_block_t, queue: dispatch_queue_t) -> Async { 0324 let nanoSeconds = Int64(seconds * Double(NSEC_PER_SEC)) 0325 let time = dispatch_time(DISPATCH_TIME_NOW, nanoSeconds) 0326 return at(time, block: block, queue: queue) 0327 } 0328 0329 /** 0330 Convenience for dispatch_after(). Encapsulates the block in a "true" GCD block using DISPATCH_BLOCK_INHERIT_QOS_CLASS. 0331 0332 - parameters: 0333 - time: The specific time (`dispatch_time_t`) the block should be run. 0334 - block: The block that is to be passed to be run on the `queue` 0335 - queue: The queue on which the `block` is run. 0336 0337 - returns: An `Async` struct which encapsulates the `dispatch_block_t` 0338 */ 0339 private static func at
Async.swift:326
        return at(time, block: block, queue: queue)
(time: dispatch_time_t, block: dispatch_block_t, queue: dispatch_queue_t) -> Async { 0340 // See Async.async() for comments 0341 let _block = dispatch_block_create(DISPATCH_BLOCK_INHERIT_QOS_CLASS, block) 0342 dispatch_after(time, queue, _block) 0343 return Async(_block) 0344 } 0345 0346 0347 // MARK: - Instance methods (matches static ones) 0348 0349 /** 0350 Sends the a block to be run asynchronously on the main thread, after the current block has finished. 0351 0352 - parameters: 0353 - after: After how many seconds the block should be run. 0354 - block: The block that is to be passed to be run on the main queue 0355 0356 - returns: An `Async` struct 0357 0358 - SeeAlso: Has parity with static method 0359 */ 0360 public func main(after after: Double? = nil, chainingBlock: dispatch_block_t) -> Async { 0361 return chain(after, block: chainingBlock, queue: GCD.mainQueue()) 0362 } 0363 0364 /** 0365 Sends the a block to be run asynchronously on a queue with a quality of service of QOS_CLASS_USER_INTERACTIVE, after the current block has finished. 0366 0367 - parameters: 0368 - after: After how many seconds the block should be run. 0369 - block: The block that is to be passed to be run on the queue 0370 0371 - returns: An `Async` struct 0372 0373 - SeeAlso: Has parity with static method 0374 */ 0375 public func userInteractive(after after: Double? = nil, chainingBlock: dispatch_block_t) -> Async { 0376 return chain(after, block: chainingBlock, queue: GCD.userInteractiveQueue()) 0377 } 0378 0379 /** 0380 Sends the a block to be run asynchronously on a queue with a quality of service of QOS_CLASS_USER_INITIATED, after the current block has finished. 0381 0382 - parameters: 0383 - after: After how many seconds the block should be run. 0384 - block: The block that is to be passed to be run on the queue 0385 0386 - returns: An `Async` struct 0387 0388 - SeeAlso: Has parity with static method 0389 */ 0390 public func userInitiated(after after: Double? = nil, chainingBlock: dispatch_block_t) -> Async { 0391 return chain(after, block: chainingBlock, queue: GCD.userInitiatedQueue()) 0392 } 0393 0394 /** 0395 Sends the a block to be run asynchronously on a queue with a quality of service of QOS_CLASS_UTILITY, after the current block has finished. 0396 0397 - parameters: 0398 - after: After how many seconds the block should be run. 0399 - block: The block that is to be passed to be run on the queue 0400 0401 - returns: An `Async` struct 0402 0403 - SeeAlso: Has parity with static method 0404 */ 0405 public func utility(after after: Double? = nil, chainingBlock: dispatch_block_t) -> Async { 0406 return chain(after, block: chainingBlock, queue: GCD.utilityQueue()) 0407 } 0408 0409 /** 0410 Sends the a block to be run asynchronously on a queue with a quality of service of QOS_CLASS_BACKGROUND, after the current block has finished. 0411 0412 - parameters: 0413 - after: After how many seconds the block should be run. 0414 - block: The block that is to be passed to be run on the queue 0415 0416 - returns: An `Async` struct 0417 0418 - SeeAlso: Has parity with static method 0419 */ 0420 public func background(after after: Double? = nil, chainingBlock: dispatch_block_t) -> Async { 0421 return chain(after, block: chainingBlock, queue: GCD.backgroundQueue()) 0422 } 0423 0424 /** 0425 Sends the a block to be run asynchronously on a custom queue, after the current block has finished. 0426 0427 - parameters: 0428 - after: After how many seconds the block should be run. 0429 - block: The block that is to be passed to be run on the queue 0430 0431 - returns: An `Async` struct 0432 0433 - SeeAlso: Has parity with static method 0434 */ 0435 public func customQueue(queue: dispatch_queue_t, after: Double? = nil, chainingBlock: dispatch_block_t) -> Async { 0436 return chain(after, block: chainingBlock, queue: queue) 0437 } 0438 0439 // MARK: - Instance methods 0440 0441 /** 0442 Convenience function to call `dispatch_block_cancel()` on the encapsulated block. 0443 Cancels the current block, if it hasn't already begun running to GCD. 0444 0445 Usage: 0446 0447 let block1 = Async.background { 0448 // Some work 0449 } 0450 let block2 = block1.background { 0451 // Some other work 0452 } 0453 Async.main { 0454 // Cancel async to allow block1 to begin 0455 block1.cancel() // First block is NOT cancelled 0456 block2.cancel() // Second block IS cancelled 0457 } 0458 0459 */ 0460 public func cancel() { 0461 dispatch_block_cancel(block) 0462 } 0463 0464 0465 /** 0466 Convenience function to call `dispatch_block_wait()` on the encapsulated block. 0467 Waits for the current block to finish, on any given thread. 0468 0469 - parameters: 0470 - seconds: Max seconds to wait for block to finish. If value is 0.0, it uses DISPATCH_TIME_FOREVER. Default value is 0. 0471 0472 - SeeAlso: dispatch_block_wait, DISPATCH_TIME_FOREVER 0473 */ 0474 public func wait(seconds seconds: Double! = nil) { 0475 if seconds != nil { 0476 let nanoSeconds = Int64(seconds * Double(NSEC_PER_SEC)) 0477 let time = dispatch_time(DISPATCH_TIME_NOW, nanoSeconds) 0478 dispatch_block_wait(block, time) 0479 } else { 0480 dispatch_block_wait(block, DISPATCH_TIME_FOREVER) 0481 } 0482 } 0483 0484 // MARK: Private instance methods 0485 0486 /** 0487 Convenience for `chainNow()` or `chainAfter()` depending on if the parameter `seconds` is passed or nil. 0488 0489 - parameters: 0490 - seconds: After how many seconds the block should be run. 0491 - block: The block that is to be passed to be run on the `queue` 0492 - queue: The queue on which the `block` is run. 0493 0494 - returns: An `Async` struct which encapsulates the `dispatch_block_t`, which is called when the current block has finished + any given amount of seconds. 0495 */ 0496 private func chain
Async.swift:361
        return chain(after, block: chainingBlock, queue: GCD.mainQueue())
Async.swift:376
        return chain(after, block: chainingBlock, queue: GCD.userInteractiveQueue())
Async.swift:391
        return chain(after, block: chainingBlock, queue: GCD.userInitiatedQueue())
Async.swift:406
        return chain(after, block: chainingBlock, queue: GCD.utilityQueue())
Async.swift:421
        return chain(after, block: chainingBlock, queue: GCD.backgroundQueue())
Async.swift:436
        return chain(after, block: chainingBlock, queue: queue)
(seconds: Double? = nil, block chainingBlock: dispatch_block_t, queue: dispatch_queue_t) -> Async { 0497 if let seconds = seconds { 0498 return chainAfter(seconds, block: chainingBlock, queue: queue) 0499 } 0500 return chainNow(block: chainingBlock, queue: queue) 0501 } 0502 0503 /** 0504 Convenience for `dispatch_block_notify()` to 0505 0506 - parameters: 0507 - block: The block that is to be passed to be run on the `queue` 0508 - queue: The queue on which the `block` is run. 0509 0510 - returns: An `Async` struct which encapsulates the `dispatch_block_t`, which is called when the current block has finished. 0511 0512 - SeeAlso: dispatch_block_notify, dispatch_block_create 0513 */ 0514 private func chainNow
Async.swift:500
        return chainNow(block: chainingBlock, queue: queue)
(block chainingBlock: dispatch_block_t, queue: dispatch_queue_t) -> Async { 0515 // See Async.async() for comments 0516 let _chainingBlock = dispatch_block_create(DISPATCH_BLOCK_INHERIT_QOS_CLASS, chainingBlock) 0517 dispatch_block_notify(block, queue, _chainingBlock) 0518 return Async(_chainingBlock) 0519 } 0520 0521 0522 /** 0523 Convenience for dispatch_after(). Encapsulates the block in a "true" GCD block using DISPATCH_BLOCK_INHERIT_QOS_CLASS. 0524 0525 - parameters: 0526 - seconds: After how many seconds the block should be run. 0527 - block: The block that is to be passed to be run on the `queue` 0528 - queue: The queue on which the `block` is run. 0529 0530 - returns: An `Async` struct which encapsulates the `dispatch_block_t`, which is called when the current block has finished + the given amount of seconds. 0531 */ 0532 private func chainAfter
Async.swift:498
            return chainAfter(seconds, block: chainingBlock, queue: queue)
(seconds: Double, block chainingBlock: dispatch_block_t, queue: dispatch_queue_t) -> Async { 0533 // Create a new block (Qos Class) from block to allow adding a notification to it later (see Async) 0534 // Create block with the "inherit" type 0535 let _chainingBlock = dispatch_block_create(DISPATCH_BLOCK_INHERIT_QOS_CLASS, chainingBlock) 0536 0537 // Wrap block to be called when previous block is finished 0538 let chainingWrapperBlock: dispatch_block_t = { 0539 // Calculate time from now 0540 let nanoSeconds = Int64(seconds * Double(NSEC_PER_SEC)) 0541 let time = dispatch_time(DISPATCH_TIME_NOW, nanoSeconds) 0542 dispatch_after(time, queue, _chainingBlock) 0543 } 0544 // Create a new block (Qos Class) from block to allow adding a notification to it later (see Async) 0545 // Create block with the "inherit" type 0546 let _chainingWrapperBlock = dispatch_block_create(DISPATCH_BLOCK_INHERIT_QOS_CLASS, chainingWrapperBlock) 0547 // Add block to queue *after* previous block is finished 0548 dispatch_block_notify(self.block, queue, _chainingWrapperBlock) 0549 // Wrap block in a struct since dispatch_block_t can't be extended 0550 return Async(_chainingBlock) 0551 } 0552 } 0553 0554 0555 // MARK: - Apply - DSL for `dispatch_apply` 0556 0557 /** 0558 `Apply` is an empty struct with convenience static functions to parallelize a for-loop, as provided by `dispatch_apply`. 0559 0560 Apply.background(100) { i in 0561 // Calls blocks in parallel 0562 } 0563 0564 `Apply` runs a block multiple times, before returning. If you want run the block asynchronously from the current thread, wrap it in an `Async` block: 0565 0566 Async.background { 0567 Apply.background(100) { i in 0568 // Calls blocks in parallel asynchronously 0569 } 0570 } 0571 0572 - SeeAlso: Grand Central Dispatch, dispatch_apply 0573 */ 0574 public struct Apply { 0575 0576 /** 0577 Block is run any given amount of times on a queue with a quality of service of QOS_CLASS_USER_INTERACTIVE. The block is being passed an index parameter. 0578 0579 - parameters: 0580 - iterations: How many times the block should be run. Index provided to block goes from `0..<iterations` 0581 - block: The block that is to be passed to be run on a . 0582 */ 0583 public static func userInteractive(iterations: Int, block: Int -> ()) { 0584 dispatch_apply(iterations, GCD.userInteractiveQueue(), block) 0585 } 0586 0587 /** 0588 Block is run any given amount of times on a queue with a quality of service of QOS_CLASS_USER_INITIATED. The block is being passed an index parameter. 0589 0590 - parameters: 0591 - iterations: How many times the block should be run. Index provided to block goes from `0..<iterations` 0592 - block: The block that is to be passed to be run on a . 0593 */ 0594 public static func userInitiated(iterations: Int, block: Int -> ()) { 0595 dispatch_apply(iterations, GCD.userInitiatedQueue(), block) 0596 } 0597 0598 /** 0599 Block is run any given amount of times on a queue with a quality of service of QOS_CLASS_UTILITY. The block is being passed an index parameter. 0600 0601 - parameters: 0602 - iterations: How many times the block should be run. Index provided to block goes from `0..<iterations` 0603 - block: The block that is to be passed to be run on a . 0604 */ 0605 public static func utility(iterations: Int, block: Int -> ()) { 0606 dispatch_apply(iterations, GCD.utilityQueue(), block) 0607 } 0608 0609 /** 0610 Block is run any given amount of times on a queue with a quality of service of QOS_CLASS_BACKGROUND. The block is being passed an index parameter. 0611 0612 - parameters: 0613 - iterations: How many times the block should be run. Index provided to block goes from `0..<iterations` 0614 - block: The block that is to be passed to be run on a . 0615 */ 0616 public static func background(iterations: Int, block: Int -> ()) { 0617 dispatch_apply(iterations, GCD.backgroundQueue(), block) 0618 } 0619 0620 /** 0621 Block is run any given amount of times on a custom queue. The block is being passed an index parameter. 0622 0623 - parameters: 0624 - iterations: How many times the block should be run. Index provided to block goes from `0..<iterations` 0625 - block: The block that is to be passed to be run on a . 0626 */ 0627 public static func customQueue(iterations: Int, queue: dispatch_queue_t, block: Int -> ()) { 0628 dispatch_apply(iterations, queue, block) 0629 } 0630 } 0631 0632 0633 // MARK: - AsyncGroup – Struct 0634 0635 /** 0636 The **AsyncGroup** struct facilitates working with groups of asynchronous blocks. Handles a internally `dispatch_group_t`. 0637 0638 Multiple dispatch blocks with GCD: 0639 0640 let group = AsyncGroup() 0641 group.background { 0642 // Run on background queue 0643 } 0644 group.utility { 0645 // Run on untility queue, after the previous block 0646 } 0647 group.wait() 0648 0649 All moderns queue classes: 0650 0651 group.main {} 0652 group.userInteractive {} 0653 group.userInitiated {} 0654 group.utility {} 0655 group.background {} 0656 0657 Custom queues: 0658 0659 let customQueue = dispatch_queue_create("Label", DISPATCH_QUEUE_CONCURRENT) 0660 group.customQueue(customQueue) {} 0661 0662 Wait for group to finish: 0663 0664 let group = AsyncGroup() 0665 group.background { 0666 // Do stuff 0667 } 0668 group.background { 0669 // Do other stuff in parallel 0670 } 0671 // Wait for both to finish 0672 group.wait() 0673 // Do rest of stuff 0674 0675 - SeeAlso: Grand Central Dispatch 0676 */ 0677 public struct AsyncGroup { 0678 0679 // MARK: - Private properties and init 0680 0681 /** 0682 Private property to hold internally on to a `dispatch_group_t` 0683 */ 0684 var group
Async.swift:690
        group = dispatch_group_create()
Async.swift:704
        dispatch_group_async(group, queue, block)
Async.swift:713
        dispatch_group_enter(group)
Async.swift:722
        dispatch_group_leave(group)
Async.swift:803
            dispatch_group_wait(group, time)
Async.swift:805
            dispatch_group_wait(group, DISPATCH_TIME_FOREVER)
: dispatch_group_t 0685 0686 /** 0687 Private init that takes a `dispatch_group_t` 0688 */ 0689 public init() { 0690 group = dispatch_group_create() 0691 } 0692 0693 0694 /** 0695 Convenience for `dispatch_group_async()` 0696 0697 - parameters: 0698 - block: The block that is to be passed to be run on the `queue` 0699 - queue: The queue on which the `block` is run. 0700 0701 - SeeAlso: dispatch_group_async, dispatch_group_create 0702 */ 0703 private func async
Async.swift:735
        async(block: block, queue: GCD.mainQueue())
Async.swift:745
        async(block: block, queue: GCD.userInteractiveQueue())
Async.swift:755
        async(block: block, queue: GCD.userInitiatedQueue())
Async.swift:766
        async(block: block, queue: GCD.utilityQueue())
Async.swift:776
        async(block: block, queue: GCD.backgroundQueue())
Async.swift:787
        async(block: block, queue: queue)
(block block: dispatch_block_t, queue: dispatch_queue_t) { 0704 dispatch_group_async(group, queue, block) 0705 } 0706 0707 /** 0708 Convenience for `dispatch_group_enter()`. Used to add custom blocks to the current group. 0709 0710 - SeeAlso: dispatch_group_enter, dispatch_group_leave 0711 */ 0712 public func enter() { 0713 dispatch_group_enter(group) 0714 } 0715 0716 /** 0717 Convenience for `dispatch_group_leave()`. Used to flag a custom added block is complete. 0718 0719 - SeeAlso: dispatch_group_enter, dispatch_group_leave 0720 */ 0721 public func leave() { 0722 dispatch_group_leave(group) 0723 } 0724 0725 0726 // MARK: - Instance methods 0727 0728 /** 0729 Sends the a block to be run asynchronously on the main thread, in the current group. 0730 0731 - parameters: 0732 - block: The block that is to be passed to be run on the main queue 0733 */ 0734 public func main(block: dispatch_block_t) { 0735 async(block: block, queue: GCD.mainQueue()) 0736 } 0737 0738 /** 0739 Sends the a block to be run asynchronously on a queue with a quality of service of QOS_CLASS_USER_INTERACTIVE, in the current group. 0740 0741 - parameters: 0742 - block: The block that is to be passed to be run on the queue 0743 */ 0744 public func userInteractive(block: dispatch_block_t) { 0745 async(block: block, queue: GCD.userInteractiveQueue()) 0746 } 0747 0748 /** 0749 Sends the a block to be run asynchronously on a queue with a quality of service of QOS_CLASS_USER_INITIATED, in the current group. 0750 0751 - parameters: 0752 - block: The block that is to be passed to be run on the queue 0753 */ 0754 public func userInitiated(block: dispatch_block_t) { 0755 async(block: block, queue: GCD.userInitiatedQueue()) 0756 } 0757 0758 /** 0759 Sends the a block to be run asynchronously on a queue with a quality of service of 0760 QOS_CLASS_UTILITY, in the current block. 0761 0762 - parameters: 0763 - block: The block that is to be passed to be run on the queue 0764 */ 0765 public func utility(block: dispatch_block_t) { 0766 async(block: block, queue: GCD.utilityQueue()) 0767 } 0768 0769 /** 0770 Sends the a block to be run asynchronously on a queue with a quality of service of QOS_CLASS_BACKGROUND, in the current block. 0771 0772 - parameters: 0773 - block: The block that is to be passed to be run on the queue 0774 */ 0775 public func background(block: dispatch_block_t) { 0776 async(block: block, queue: GCD.backgroundQueue()) 0777 } 0778 0779 /** 0780 Sends the a block to be run asynchronously on a custom queue, in the current group. 0781 0782 - parameters: 0783 - queue: Custom queue where the block will be run. 0784 - block: The block that is to be passed to be run on the queue 0785 */ 0786 public func customQueue(queue: dispatch_queue_t, block: dispatch_block_t) { 0787 async(block: block, queue: queue) 0788 } 0789 0790 /** 0791 Convenience function to call `dispatch_group_wait()` on the encapsulated block. 0792 Waits for the current group to finish, on any given thread. 0793 0794 - parameters: 0795 - seconds: Max seconds to wait for block to finish. If value is nil, it uses DISPATCH_TIME_FOREVER. Default value is nil. 0796 0797 - SeeAlso: dispatch_group_wait, DISPATCH_TIME_FOREVER 0798 */ 0799 public func wait(seconds seconds: Double! = nil) { 0800 if seconds != nil { 0801 let nanoSeconds = Int64(seconds * Double(NSEC_PER_SEC)) 0802 let time = dispatch_time(DISPATCH_TIME_NOW, nanoSeconds) 0803 dispatch_group_wait(group, time) 0804 } else { 0805 dispatch_group_wait(group, DISPATCH_TIME_FOREVER) 0806 } 0807 } 0808 0809 } 0810 0811 0812 // MARK: - Extension for `qos_class_t` 0813 0814 /** 0815 Extension to add description string for each quality of service class. 0816 */ 0817 public extension qos_class_t { 0818 0819 /** 0820 Description of the `qos_class_t`. E.g. "Main", "User Interactive", etc. for the given Quality of Service class. 0821 */ 0822 var description: String { 0823 get { 0824 switch self { 0825 case qos_class_main(): return "Main" 0826 case QOS_CLASS_USER_INTERACTIVE: return "User Interactive" 0827 case QOS_CLASS_USER_INITIATED: return "User Initiated" 0828 case QOS_CLASS_DEFAULT: return "Default" 0829 case QOS_CLASS_UTILITY: return "Utility" 0830 case QOS_CLASS_BACKGROUND: return "Background" 0831 case QOS_CLASS_UNSPECIFIED: return "Unspecified" 0832 default: return "Unknown" 0833 } 0834 } 0835 } 0836 } 0837