Sources/BoltsSwift/Executor.swift (83 lines of code) (raw):

/* * Copyright (c) 2016, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. */ import Foundation /// `Executor` is an `enum`, that defines different strategies for calling closures. public enum Executor { /** Calls closures immediately unless the call stack gets too deep, in which case it dispatches the closure in the default priority queue. */ case `default` /** Calls closures immediately. Tasks continuations will be run in the thread of the previous task. */ case immediate /** Calls closures on the main thread. Will execute synchronously if already on the main thread, otherwise - will execute asynchronously. */ case mainThread /** Dispatches closures on a GCD queue. */ case queue(DispatchQueue) /** Adds closures to an operation queue. */ case operationQueue(Foundation.OperationQueue) /** Passes closures to an executing closure. */ case closure((() -> Void) -> Void) /** Passes escaping closures to an executing closure. */ case escapingClosure((@escaping () -> Void) -> Void) /** Executes the given closure using the corresponding strategy. - parameter closure: The closure to execute. */ public func execute(_ closure: @escaping () -> Void) { switch self { case .default: struct Static { static let taskDepthKey = "com.bolts.TaskDepthKey" static let maxTaskDepth = 20 } let localThreadDictionary = Thread.current.threadDictionary var previousDepth: Int if let depth = localThreadDictionary[Static.taskDepthKey] as? Int { previousDepth = depth } else { previousDepth = 0 } if previousDepth > Static.maxTaskDepth { DispatchQueue.global(qos: .default).async(execute: closure) } else { localThreadDictionary[Static.taskDepthKey] = previousDepth + 1 closure() localThreadDictionary[Static.taskDepthKey] = previousDepth } case .immediate: closure() case .mainThread: if Thread.isMainThread { closure() } else { DispatchQueue.main.async(execute: closure) } case .queue(let queue): queue.async(execute: closure) case .operationQueue(let operationQueue): operationQueue.addOperation(closure) case .closure(let executingClosure): executingClosure(closure) case .escapingClosure(let executingEscapingClosure): executingEscapingClosure(closure) } } } extension Executor: CustomStringConvertible, CustomDebugStringConvertible { /// A textual representation of `self`. public var description: String { switch self { case .default: return "Default Executor" case .immediate: return "Immediate Executor" case .mainThread: return "MainThread Executor" case .queue: return "Executor with dispatch_queue" case .operationQueue: return "Executor with NSOperationQueue" case .closure: return "Executor with custom closure" case .escapingClosure: return "Executor with custom escaping closure" } } /// A textual representation of `self`, suitable for debugging. public var debugDescription: String { switch self { case .queue(let object): return "\(description): \(object)" case .operationQueue(let queue): return "\(description): \(queue)" case .closure(let closure): return "\(description): \(String(describing: closure))" case .escapingClosure(let closure): return "\(description): \(String(describing: closure))" default: return description } } }