Advertisement
Guest User

Untitled

a guest
Dec 5th, 2016
67
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.96 KB | None | 0 0
  1. //
  2. // Asynchronous computation control library
  3. //
  4. import class Dispatch.DispatchQueue
  5. import struct Dispatch.DispatchQoS
  6.  
  7. // Outcome of a fallible process
  8. //
  9. public enum Result<R, T> {
  10. case success(T)
  11. case failure(R)
  12. }
  13.  
  14. // Single unit of asynchronous computation
  15. //
  16. public class Promise<T> {
  17. internal var result: Result<Error, T>?
  18. private weak var queue: PromiseQueue?
  19.  
  20. // Promises are created through a `PromiseQueue` instance
  21. //
  22. internal init(queue: PromiseQueue, result: Result<Error, T>? = nil) {
  23. self.queue = queue
  24. self.result = result
  25. }
  26.  
  27. // Schedule a promise to execute after another one
  28. //
  29. // The body only gets executed if the preceding promise
  30. // was fulfilled. In the other case, a new promise is returned
  31. // with the same reason as the broken preceding one.
  32. //
  33. @discardableResult
  34. public func `then`<Y>(_ body: @escaping (T) throws -> Y) -> Promise<Y> {
  35. return queue!.promise({
  36. switch self.result! {
  37. case .success(let result):
  38. return try body(result)
  39. case .failure(let reason):
  40. throw reason
  41. }
  42. })
  43. }
  44.  
  45. // Provide a fallback value by executing a promise
  46. //
  47. // Upon successful return, the new promise
  48. // becomes fulfilled with its value.
  49. // If the body throws, the new promise becomes broken
  50. // with the new reason.
  51. //
  52. @discardableResult
  53. public func `else`(_ body: @escaping (Error) throws -> T) -> Promise<T> {
  54. return queue!.promise({
  55. switch self.result! {
  56. case .success(let result):
  57. return result
  58. case .failure(let reason):
  59. return try body(reason)
  60. }
  61. })
  62. }
  63.  
  64. // Chain an action regardless of the preceding promise state
  65. //
  66. @discardableResult
  67. public func anyway<Y>(_ body: @escaping (Result<Error, T>) throws -> Y) -> Promise<Y> {
  68. return queue!.promise({
  69. return try body(self.result!)
  70. })
  71. }
  72.  
  73. // Wait until the promise finishes,
  74. // after that return the value or throw the reason
  75. //
  76. public func join() throws -> T {
  77. queue!.joinAll()
  78.  
  79. switch self.result! {
  80. case .success(let result):
  81. return result
  82. case .failure(let reason):
  83. throw reason
  84. }
  85. }
  86. }
  87.  
  88. // Factory of Promises
  89. //
  90. public class PromiseQueue {
  91. private let queue: DispatchQueue
  92.  
  93. public init() {
  94. self.queue = DispatchQueue(label: "", qos: DispatchQoS.background)
  95. }
  96.  
  97. // Make a promise from a throwing function
  98. //
  99. // The returned value of the supplied body
  100. // shall become the value of the fulfilled promise.
  101. // If the body throws, the promise becomes broken
  102. // with the reason of the error thrown.
  103. //
  104. @discardableResult
  105. public func promise<T>(_ body: @escaping () throws -> T) -> Promise<T> {
  106. let promise = Promise<T>(queue: self)
  107. queue.async(execute: {
  108. do {
  109. let result = try body()
  110. promise.result = .success(result)
  111. } catch (let error) {
  112. promise.result = .failure(error)
  113. }
  114. })
  115.  
  116. return promise
  117. }
  118.  
  119. // Wrap a pair of callbacks into a promise
  120. //
  121. // The first callback is used fulfill the promise with the given value;
  122. // the second one is used to break it with the given reason.
  123. //
  124. // After the promise has been either fulfilled or broken,
  125. // any subsequent calls to either of two callback have no effect.
  126. //
  127. // Note that other promises shall not start
  128. // until this promise has finished.
  129. //
  130. @discardableResult
  131. public func promise<T>(
  132. by body: @escaping (@escaping (T) -> Void, @escaping (Error) -> Void) -> ()
  133. ) -> Promise<T> {
  134. let promise = Promise<T>(queue: self)
  135. queue.async(execute: {
  136. self.queue.suspend()
  137. body({ x in
  138. guard promise.result == nil else { return }
  139. promise.result = .success(x)
  140. self.queue.resume()
  141. }, { x in
  142. guard promise.result == nil else { return }
  143. promise.result = .failure(x)
  144. self.queue.resume()
  145. })
  146. })
  147.  
  148. return promise
  149. }
  150.  
  151. // Wait until all previously submitted promises are finished
  152. //
  153. public func joinAll() {
  154. queue.sync(execute: {})
  155. }
  156. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement