0001 // 0002 // FutureType.swift 0003 // Deferred 0004 // 0005 // Created by Zachary Waldowski on 8/29/15. 0006 // Copyright © 2014-2015 Big Nerd Ranch. Licensed under MIT. 0007 // 0008 0009 import Dispatch 0010 0011 // A generic catch-all dispatch queue for use with futures, when you just want 0012 // to throw some work into the concurrent pile. As an alternative to the 0013 // `QOS_CLASS_UTILITY` global queue, work dispatched onto this queue matches 0014 // the QoS of the caller, which is generally the right behavior. 0015 // 0016 // The technique is described and used in Core Foundation: 0017 // http://opensource.apple.com/source/CF/CF-1153.18/CFInternal.h 0018 var genericQueue: dispatch_queue_t! { 0019 return dispatch_get_global_queue(qos_class_self(), 0) 0020 } 0021 0022 /// A future models reading a value which may become available at some point. 0023 /// 0024 /// A `FutureType` may be preferable to an architecture using completion 0025 /// handlers; separating the mechanism for handling the completion from the call 0026 /// that began it leads to a more readable code flow. 0027 /// 0028 /// A future is primarily useful as a joining mechanism for asynchronous 0029 /// operations. Though the protocol requires a synchronous accessor, its use is 0030 /// not recommended outside of testing. `upon` is preferred for nearly all access: 0031 /// 0032 /// myFuture.upon(dispatch_get_main_queue()) { value in 0033 /// print("I now have the value: \(value)") 0034 /// } 0035 /// 0036 /// `FutureType` makes no requirement on conforming types regarding thread-safe 0037 /// access, though ideally all members of the future could be called from any 0038 /// thread. 0039 /// 0040 public protocol FutureType
FutureCollections.swift:48 dispatch_group_notify(group, genericQueue) {FutureType.swift:71 upon(genericQueue, body: body)FutureType.swift:127 func flatMap<NewFuture: FutureType>(upon queue: dispatch_queue_t = genericQueue, _ transform: Value -> NewFuture) -> Future<NewFuture.Value> {FutureType.swift:147 func map<NewValue>(upon queue: dispatch_queue_t = genericQueue, _ transform: Value -> NewValue) -> Future<NewValue> {{ 0041 /// A type that represents the result of some asynchronous operation. 0042 typealias Value
Deferred.swift:41 public struct Deferred<Value>: FutureType, PromiseType {ExistentialFuture.swift:20 private class FutureBase<Value>: FutureType {ExistentialFuture.swift:76 public struct Future<Value>: FutureType {ExistentialFuture.swift:80 public init<Future: FutureType where Future.Value == Value>(_ base: Future) {FutureType.swift:63 public extension FutureType {FutureType.swift:86 public extension FutureType {FutureType.swift:113 public extension FutureType {FutureType.swift:127 func flatMap<NewFuture: FutureType>(upon queue: dispatch_queue_t = genericQueue, _ transform: Value -> NewFuture) -> Future<NewFuture.Value> {FutureType.swift:156 public extension FutureType {FutureType.swift:163 func and<OtherFuture: FutureType>(other: OtherFuture) -> Future<(Value, OtherFuture.Value)> {FutureType.swift:174 func and<Other1: FutureType, Other2: FutureType>(one: Other1, _ two: Other2) -> Future<(Value, Other1.Value, Other2.Value)> {FutureType.swift:174 func and<Other1: FutureType, Other2: FutureType>(one: Other1, _ two: Other2) -> Future<(Value, Other1.Value, Other2.Value)> {FutureType.swift:190 func and<Other1: FutureType, Other2: FutureType, Other3: FutureType>(one: Other1, _ two: Other2, _ three: Other3) -> Future<(Value, Other1.Value, Other2.Value, Other3.Value)> {FutureType.swift:190 func and<Other1: FutureType, Other2: FutureType, Other3: FutureType>(one: Other1, _ two: Other2, _ three: Other3) -> Future<(Value, Other1.Value, Other2.Value, Other3.Value)> {FutureType.swift:190 func and<Other1: FutureType, Other2: FutureType, Other3: FutureType>(one: Other1, _ two: Other2, _ three: Other3) -> Future<(Value, Other1.Value, Other2.Value, Other3.Value)> {IgnoringFuture.swift:21 public struct IgnoringFuture<Base: FutureType>: FutureType {0043 0044 /// Call some function once the value is determined. 0045 /// 0046 /// If the value is determined, the function should be submitted to the 0047 /// queue immediately. An `upon` call should always execute asynchronously. 0048 /// 0049 /// - parameter queue: A dispatch queue for executing the given function on. 0050 /// - parameter body: A function that uses the determined value. 0051 func upon
ExistentialFuture.swift:31 private final class ForwardingFuture<Future: FutureType>: FutureBase<Future.Value> {ExistentialFuture.swift:37 override func upon(queue: dispatch_queue_t, body: Future.Value -> ()) {ExistentialFuture.swift:41 override func wait(time: Timeout) -> Future.Value? {ExistentialFuture.swift:80 public init<Future: FutureType where Future.Value == Value>(_ base: Future) {FutureCollections.swift:17 let combined = Deferred<Generator.Element.Value>()FutureCollections.swift:16 var earliestFilled: Future<Generator.Element.Value> {FutureCollections.swift:38 let combined = Deferred<[Generator.Element.Value]>()FutureCollections.swift:32 var joinedValues: Future<[Generator.Element.Value]> {FutureType.swift:51 func upon(queue: dispatch_queue_t, body: Value -> ())FutureType.swift:60 func wait(time: Timeout) -> Value?FutureType.swift:70 func upon(body: Value -> ()) {FutureType.swift:81 func uponMainQueue(body: Value -> ()) {FutureType.swift:90 func peek() -> Value? {FutureType.swift:103 internal var value: Value {FutureType.swift:127 func flatMap<NewFuture: FutureType>(upon queue: dispatch_queue_t = genericQueue, _ transform: Value -> NewFuture) -> Future<NewFuture.Value> {FutureType.swift:127 func flatMap<NewFuture: FutureType>(upon queue: dispatch_queue_t = genericQueue, _ transform: Value -> NewFuture) -> Future<NewFuture.Value> {FutureType.swift:128 let d = Deferred<NewFuture.Value>()FutureType.swift:147 func map<NewValue>(upon queue: dispatch_queue_t = genericQueue, _ transform: Value -> NewValue) -> Future<NewValue> {FutureType.swift:163 func and<OtherFuture: FutureType>(other: OtherFuture) -> Future<(Value, OtherFuture.Value)> {FutureType.swift:163 func and<OtherFuture: FutureType>(other: OtherFuture) -> Future<(Value, OtherFuture.Value)> {FutureType.swift:174 func and<Other1: FutureType, Other2: FutureType>(one: Other1, _ two: Other2) -> Future<(Value, Other1.Value, Other2.Value)> {FutureType.swift:174 func and<Other1: FutureType, Other2: FutureType>(one: Other1, _ two: Other2) -> Future<(Value, Other1.Value, Other2.Value)> {FutureType.swift:174 func and<Other1: FutureType, Other2: FutureType>(one: Other1, _ two: Other2) -> Future<(Value, Other1.Value, Other2.Value)> {FutureType.swift:190 func and<Other1: FutureType, Other2: FutureType, Other3: FutureType>(one: Other1, _ two: Other2, _ three: Other3) -> Future<(Value, Other1.Value, Other2.Value, Other3.Value)> {FutureType.swift:190 func and<Other1: FutureType, Other2: FutureType, Other3: FutureType>(one: Other1, _ two: Other2, _ three: Other3) -> Future<(Value, Other1.Value, Other2.Value, Other3.Value)> {FutureType.swift:190 func and<Other1: FutureType, Other2: FutureType, Other3: FutureType>(one: Other1, _ two: Other2, _ three: Other3) -> Future<(Value, Other1.Value, Other2.Value, Other3.Value)> {FutureType.swift:190 func and<Other1: FutureType, Other2: FutureType, Other3: FutureType>(one: Other1, _ two: Other2, _ three: Other3) -> Future<(Value, Other1.Value, Other2.Value, Other3.Value)> {(queue: dispatch_queue_t, body: Value -> ()) 0052 0053 /// Waits synchronously for the value to become determined. 0054 /// 0055 /// If the value is already determined, the call returns immediately with the 0056 /// value. 0057 /// 0058 /// - parameter time: A length of time to wait for the value to be determined. 0059 /// - returns: The determined value, if filled within the timeout, or `nil`. 0060 func wait
ExistentialFuture.swift:38 return base.upon(queue, body: body)FutureType.swift:71 upon(genericQueue, body: body)FutureType.swift:82 upon(dispatch_get_main_queue(), body: body)FutureType.swift:129 upon(queue) {FutureType.swift:130 transform($0).upon(queue) {FutureType.swift:149 upon(queue) {IgnoringFuture.swift:36 return base.upon(queue) { _ in body() }(time: Timeout) -> Value? 0061 } 0062 0063 public extension FutureType { 0064 /// Call some function in the background once the value is determined. 0065 /// 0066 /// If the value is determined, the function will be dispatched immediately. 0067 /// An `upon` call should always execute asynchronously. 0068 /// 0069 /// - parameter body: A function that uses the determined value. 0070 func upon
ExistentialFuture.swift:42 return base.wait(time)FutureType.swift:91 return wait(.Now)FutureType.swift:104 return unsafeUnwrap(wait(.Forever))FutureType.swift:109 return wait(.Now) != nilIgnoringFuture.swift:46 return base.wait(time).map { _ in }(body: Value -> ()) { 0071 upon(genericQueue, body: body) 0072 } 0073 0074 /// Call some function on the main queue once the value is determined. 0075 /// 0076 /// If the value is determined, the function will be submitted to the 0077 /// main queue immediately. The function should always be executed 0078 /// asynchronously, even if this function is called from the main queue. 0079 /// 0080 /// - parameter body: A function that uses the determined value. 0081 func uponMainQueue(body: Value -> ()) { 0082 upon(dispatch_get_main_queue(), body: body) 0083 } 0084 } 0085 0086 public extension FutureType { 0087 /// Checks for and returns a determined value. 0088 /// 0089 /// - returns: The determined value, if already filled, or `nil`. 0090 func peek() -> Value? { 0091 return wait(.Now) 0092 } 0093 0094 /// Waits for the value to become determined, then returns it. 0095 /// 0096 /// This is equivalent to unwrapping the value of calling `wait(.Forever)`, 0097 /// but may be more efficient. 0098 /// 0099 /// This getter will unnecessarily block execution. It might be useful for 0100 /// testing, but otherwise it should be strictly avoided. 0101 /// 0102 /// - returns: The determined value. 0103 internal var value
FutureCollections.swift:19 future.upon {FutureCollections.swift:43 deferred.upon { _ in: Value { 0104 return unsafeUnwrap(wait(.Forever)) 0105 } 0106 0107 /// Check whether or not the receiver is filled. 0108 internal var isFilled: Bool { 0109 return wait(.Now) != nil 0110 } 0111 } 0112 0113 public extension FutureType { 0114 /// Begins another asynchronous operation with the deferred value once it 0115 /// becomes determined. 0116 /// 0117 /// `flatMap` is similar to `map`, but `transform` returns a `Deferred` 0118 /// instead of an immediate value. Use `flatMap` when you want this future 0119 /// to feed into another asynchronous operation. You might hear this 0120 /// referred to as "chaining" or "binding". 0121 /// 0122 /// - parameter queue: Optional dispatch queue for starting the new 0123 /// operation from. Defaults to a global queue matching the current QoS. 0124 /// - parameter transform: Start a new operation using the deferred value. 0125 /// - returns: The new deferred value returned by the `transform`. 0126 /// - seealso: Deferred 0127 func flatMap
FutureCollections.swift:50 $0.value<NewFuture: FutureType>(upon queue: dispatch_queue_t = genericQueue, _ transform: Value -> NewFuture) -> Future<NewFuture.Value> { 0128 let d = Deferred<NewFuture.Value>() 0129 upon(queue) { 0130 transform($0).upon(queue) { 0131 d.fill($0) 0132 } 0133 } 0134 return Future(d) 0135 } 0136 0137 /// Transforms the future once it becomes determined. 0138 /// 0139 /// `map` executes a transform immediately when the future's value is 0140 /// determined. 0141 /// 0142 /// - parameter queue: Optional dispatch queue for executing the transform 0143 /// from. Defaults to a global queue matching the current QoS. 0144 /// - parameter transform: Create something using the deferred value. 0145 /// - returns: A new future that is filled once the reciever is determined. 0146 /// - seealso: Deferred 0147 func map
FutureType.swift:164 return Future(flatMap { t in other.map { u in (t, u) } })FutureType.swift:175 return Future(flatMap { t inFutureType.swift:176 one.flatMap { u inFutureType.swift:191 return Future(flatMap { t inFutureType.swift:192 one.flatMap { u inFutureType.swift:193 two.flatMap { v in<NewValue>(upon queue: dispatch_queue_t = genericQueue, _ transform: Value -> NewValue) -> Future<NewValue> { 0148 let d = Deferred<NewValue>() 0149 upon(queue) { 0150 d.fill(transform($0)) 0151 } 0152 return Future(d) 0153 } 0154 } 0155 0156 public extension FutureType { 0157 /// Composes this future with another. 0158 /// 0159 /// - parameter other: Any other future. 0160 /// - returns: A value that becomes determined after both the reciever and 0161 /// the given future become determined. 0162 /// - seealso: SequenceType.allFutures 0163 func and<OtherFuture: FutureType>(other: OtherFuture) -> Future<(Value, OtherFuture.Value)> { 0164 return Future(flatMap { t in other.map { u in (t, u) } }) 0165 } 0166 0167 /// Composes this future with others. 0168 /// 0169 /// - parameter one: Some other future to join with. 0170 /// - parameter two: Some other future to join with. 0171 /// - returns: A value that becomes determined after the reciever and both 0172 /// other futures become determined. 0173 /// - seealso: SequenceType.allFutures 0174 func and<Other1: FutureType, Other2: FutureType>(one: Other1, _ two: Other2) -> Future<(Value, Other1.Value, Other2.Value)> { 0175 return Future(flatMap { t in 0176 one.flatMap { u in 0177 two.map { v in (t, u, v) } 0178 } 0179 }) 0180 } 0181 0182 /// Composes this future with others. 0183 /// 0184 /// - parameter one: Some other future to join with. 0185 /// - parameter two: Some other future to join with. 0186 /// - parameter three: Some other future to join with. 0187 /// - returns: A value that becomes determined after the reciever and both 0188 /// other futures become determined. 0189 /// - seealso: SequenceType.allFutures 0190 func and<Other1: FutureType, Other2: FutureType, Other3: FutureType>(one: Other1, _ two: Other2, _ three: Other3) -> Future<(Value, Other1.Value, Other2.Value, Other3.Value)> { 0191 return Future(flatMap { t in 0192 one.flatMap { u in 0193 two.flatMap { v in 0194 three.map { w in (t, u, v, w) } 0195 } 0196 } 0197 }) 0198 } 0199 } 0200
FutureType.swift:164 return Future(flatMap { t in other.map { u in (t, u) } })FutureType.swift:177 two.map { v in (t, u, v) }FutureType.swift:194 three.map { w in (t, u, v, w) }