Skip to content

Commit 9fa6b3c

Browse files
committed
Add chain dispatchers, DispatchState, dispatch(on:), revise wrappers
1 parent 84de7db commit 9fa6b3c

22 files changed

Lines changed: 802 additions & 261 deletions

Sources/Cancellation/CancellableCatchable.swift

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public extension CancellableCatchMixin {
2525
- SeeAlso: [Cancellation](https://github.com/mxcl/PromiseKit/blob/master/Documentation/CommonPatterns.md#cancellation)
2626
*/
2727
@discardableResult
28-
func `catch`(on: Dispatcher = conf.D.return, policy: CatchPolicy = conf.catchPolicy, _ body: @escaping(Error) -> Void) -> CancellableFinalizer {
28+
func `catch`(on: Dispatcher = conf.dd, policy: CatchPolicy = conf.catchPolicy, _ body: @escaping(Error) -> Void) -> CancellableFinalizer {
2929
return CancellableFinalizer(self.catchable.catch(on: on, policy: policy, body), cancel: self.cancelContext)
3030
}
3131

@@ -44,7 +44,7 @@ public extension CancellableCatchMixin {
4444
- Note: Since this method handles only specific errors, supplying a `CatchPolicy` is unsupported. You can instead specify e.g. your cancellable error.
4545
- SeeAlso: [Cancellation](https://github.com/mxcl/PromiseKit/blob/master/Documentation/CommonPatterns.md#cancellation)
4646
*/
47-
func `catch`<E: Swift.Error>(only: E, on: Dispatcher = conf.D.return, _ body: @escaping(E) -> Void) -> CancellableCascadingFinalizer where E: Equatable {
47+
func `catch`<E: Swift.Error>(only: E, on: Dispatcher = conf.dd, _ body: @escaping(E) -> Void) -> CancellableCascadingFinalizer where E: Equatable {
4848
return CancellableCascadingFinalizer(self.catchable.catch(only: only, on: on, body), cancel: self.cancelContext)
4949
}
5050

@@ -62,7 +62,7 @@ public extension CancellableCatchMixin {
6262
- Parameter execute: The handler to execute if this promise is rejected with the provided error type.
6363
- SeeAlso: [Cancellation](https://github.com/mxcl/PromiseKit/blob/master/Documentation/CommonPatterns.md#cancellation)
6464
*/
65-
func `catch`<E: Swift.Error>(only: E.Type, on: Dispatcher = conf.D.return, policy: CatchPolicy = conf.catchPolicy, _ body: @escaping(E) -> Void) -> CancellableCascadingFinalizer {
65+
func `catch`<E: Swift.Error>(only: E.Type, on: Dispatcher = conf.dd, policy: CatchPolicy = conf.catchPolicy, _ body: @escaping(E) -> Void) -> CancellableCascadingFinalizer {
6666
return CancellableCascadingFinalizer(self.catchable.catch(only: only, on: on, policy: policy, body), cancel: self.cancelContext)
6767
}
6868
}
@@ -119,7 +119,7 @@ public class CancellableFinalizer: CancelContextFinalizer {
119119

120120
/// `finally` is the same as `ensure`, but it is not chainable
121121
@discardableResult
122-
public func finally(on: Dispatcher = conf.D.return, _ body: @escaping () -> Void) -> CancelContext {
122+
public func finally(on: Dispatcher = conf.dd, _ body: @escaping () -> Void) -> CancelContext {
123123
pmkFinalizer.finally(on: on, body)
124124
return cancelContext
125125
}
@@ -148,7 +148,7 @@ public class CancellableCascadingFinalizer: CancelContextFinalizer {
148148
- SeeAlso: [Cancellation](https://github.com/mxcl/PromiseKit/blob/master/Documentation/CommonPatterns.md#cancellation)
149149
*/
150150
@discardableResult
151-
public func `catch`(on: Dispatcher = conf.D.return, policy: CatchPolicy = conf.catchPolicy, _ body: @escaping(Error) -> Void) -> CancellableFinalizer {
151+
public func `catch`(on: Dispatcher = conf.dd, policy: CatchPolicy = conf.catchPolicy, _ body: @escaping(Error) -> Void) -> CancellableFinalizer {
152152
return CancellableFinalizer(pmkCascadingFinalizer.catch(on: on, policy: policy, body), cancel: cancelContext)
153153
}
154154

@@ -166,7 +166,7 @@ public class CancellableCascadingFinalizer: CancelContextFinalizer {
166166
- Note: Since this method handles only specific errors, supplying a `CatchPolicy` is unsupported. You can instead specify e.g. your cancellable error.
167167
- SeeAlso: [Cancellation](https://github.com/mxcl/PromiseKit/blob/master/Documentation/CommonPatterns.md#cancellation)
168168
*/
169-
public func `catch`<E: Swift.Error>(only: E, on: Dispatcher = conf.D.return, _ body: @escaping(E) -> Void) -> CancellableCascadingFinalizer where E: Equatable {
169+
public func `catch`<E: Swift.Error>(only: E, on: Dispatcher = conf.dd, _ body: @escaping(E) -> Void) -> CancellableCascadingFinalizer where E: Equatable {
170170
return CancellableCascadingFinalizer(pmkCascadingFinalizer.catch(only: only, on: on, body), cancel: cancelContext)
171171
}
172172

@@ -183,10 +183,20 @@ public class CancellableCascadingFinalizer: CancelContextFinalizer {
183183
- Parameter execute: The handler to execute if this promise is rejected with the provided error type.
184184
- SeeAlso: [Cancellation](https://github.com/mxcl/PromiseKit/blob/master/Documentation/CommonPatterns.md#cancellation)
185185
*/
186-
public func `catch`<E: Swift.Error>(only: E.Type, on: Dispatcher = conf.D.return, policy: CatchPolicy = conf.catchPolicy, _ body: @escaping(E) -> Void) -> CancellableCascadingFinalizer {
186+
public func `catch`<E: Swift.Error>(only: E.Type, on: Dispatcher = conf.dd, policy: CatchPolicy = conf.catchPolicy, _ body: @escaping(E) -> Void) -> CancellableCascadingFinalizer {
187187
return CancellableCascadingFinalizer(pmkCascadingFinalizer.catch(only: only, on: on, policy: policy, body), cancel: cancelContext)
188188
}
189189

190+
/// Set a default Dispatcher for the chain. Within the chain, this Dispatcher will remain the
191+
/// default until you change it, even if you dispatch individual closures to other Dispatchers.
192+
///
193+
/// - Parameters:
194+
/// - on: The new default Dispatcher. Use `.default` to return to normal dispatching.
195+
196+
public func dispatch(on: Dispatcher) -> CancellableCascadingFinalizer {
197+
return CancellableCascadingFinalizer(pmkCascadingFinalizer.dispatch(on: on), cancel: cancelContext)
198+
}
199+
190200
/**
191201
Consumes the Swift unused-result warning.
192202
- Note: You should `catch`, but in situations where you know you don’t need a `catch`, `cauterize` makes your intentions clear.
@@ -221,7 +231,7 @@ public extension CancellableCatchMixin {
221231
- Parameter body: The handler to execute if this promise is rejected.
222232
- SeeAlso: [Cancellation](https://github.com/mxcl/PromiseKit/blob/master/Documentation/CommonPatterns.md#cancellation)
223233
*/
224-
func recover<V: CancellableThenable>(on: Dispatcher = conf.D.map, policy: CatchPolicy = conf.catchPolicy, _ body: @escaping(Error) throws -> V) -> CancellablePromise<C.T> where V.U.T == C.T {
234+
func recover<V: CancellableThenable>(on: Dispatcher = conf.dd, policy: CatchPolicy = conf.catchPolicy, _ body: @escaping(Error) throws -> V) -> CancellablePromise<C.T> where V.U.T == C.T {
225235
let cancelItemList = CancelItemList()
226236

227237
let cancelBody = { (error: Error) throws -> V.U in
@@ -263,7 +273,7 @@ public extension CancellableCatchMixin {
263273
- Parameter body: The handler to execute if this promise is rejected.
264274
- SeeAlso: [Cancellation](https://github.com/mxcl/PromiseKit/blob/master/Documentation/CommonPatterns.md#cancellation)
265275
*/
266-
func recover<V: Thenable>(on: Dispatcher = conf.D.map, policy: CatchPolicy = conf.catchPolicy, _ body: @escaping(Error) throws -> V) -> CancellablePromise<C.T> where V.T == C.T {
276+
func recover<V: Thenable>(on: Dispatcher = conf.dd, policy: CatchPolicy = conf.catchPolicy, _ body: @escaping(Error) throws -> V) -> CancellablePromise<C.T> where V.T == C.T {
267277
let cancelBody = { (error: Error) throws -> V in
268278
_ = self.cancelContext.removeItems(self.cancelItemList, clearList: true)
269279
let rval = try body(error)
@@ -302,7 +312,7 @@ public extension CancellableCatchMixin {
302312
- Note: Since this method recovers only specific errors, supplying a `CatchPolicy` is unsupported.
303313
- SeeAlso: [Cancellation](https://github.com/mxcl/PromiseKit/blob/master/Documentation/CommonPatterns.md#cancellation)
304314
*/
305-
func recover<V: CancellableThenable, E: Swift.Error>(only: E, on: Dispatcher = conf.D.map, _ body: @escaping(E) throws -> V) -> CancellablePromise<C.T> where V.U.T == C.T, E: Equatable {
315+
func recover<V: CancellableThenable, E: Swift.Error>(only: E, on: Dispatcher = conf.dd, _ body: @escaping(E) throws -> V) -> CancellablePromise<C.T> where V.U.T == C.T, E: Equatable {
306316
let cancelItemList = CancelItemList()
307317

308318
let cancelBody = { (error: E) throws -> V.U in
@@ -340,7 +350,7 @@ public extension CancellableCatchMixin {
340350
- Note: Since this method recovers only specific errors, supplying a `CatchPolicy` is unsupported. You can instead specify e.g. your cancellable error.
341351
- SeeAlso: [Cancellation](https://github.com/mxcl/PromiseKit/blob/master/Documentation/CommonPatterns.md#cancellation)
342352
*/
343-
func recover<V: Thenable, E: Swift.Error>(only: E, on: Dispatcher = conf.D.map, _ body: @escaping(E) throws -> V) -> CancellablePromise<C.T> where V.T == C.T, E: Equatable {
353+
func recover<V: Thenable, E: Swift.Error>(only: E, on: Dispatcher = conf.dd, _ body: @escaping(E) throws -> V) -> CancellablePromise<C.T> where V.T == C.T, E: Equatable {
344354
let cancelBody = { (error: E) throws -> V in
345355
_ = self.cancelContext.removeItems(self.cancelItemList, clearList: true)
346356
let rval = try body(error)
@@ -378,7 +388,7 @@ public extension CancellableCatchMixin {
378388
- Parameter body: The handler to execute if this promise is rejected with the provided error type.
379389
- SeeAlso: [Cancellation](https://github.com/mxcl/PromiseKit/blob/master/Documentation/CommonPatterns.md#cancellation)
380390
*/
381-
func recover<V: CancellableThenable, E: Swift.Error>(only: E.Type, on: Dispatcher = conf.D.map, policy: CatchPolicy = conf.catchPolicy, _ body: @escaping(E) throws -> V) -> CancellablePromise<C.T> where V.U.T == C.T {
391+
func recover<V: CancellableThenable, E: Swift.Error>(only: E.Type, on: Dispatcher = conf.dd, policy: CatchPolicy = conf.catchPolicy, _ body: @escaping(E) throws -> V) -> CancellablePromise<C.T> where V.U.T == C.T {
382392
let cancelItemList = CancelItemList()
383393

384394
let cancelBody = { (error: E) throws -> V.U in
@@ -417,7 +427,7 @@ public extension CancellableCatchMixin {
417427
- Parameter body: The handler to execute if this promise is rejected with the provided error type.
418428
- SeeAlso: [Cancellation](https://github.com/mxcl/PromiseKit/blob/master/Documentation/CommonPatterns.md#cancellation)
419429
*/
420-
func recover<V: Thenable, E: Swift.Error>(only: E.Type, on: Dispatcher = conf.D.map, policy: CatchPolicy = conf.catchPolicy, _ body: @escaping(E) throws -> V) -> CancellablePromise<C.T> where V.T == C.T {
430+
func recover<V: Thenable, E: Swift.Error>(only: E.Type, on: Dispatcher = conf.dd, policy: CatchPolicy = conf.catchPolicy, _ body: @escaping(E) throws -> V) -> CancellablePromise<C.T> where V.T == C.T {
421431
let cancelBody = { (error: E) throws -> V in
422432
_ = self.cancelContext.removeItems(self.cancelItemList, clearList: true)
423433
let rval = try body(error)
@@ -460,11 +470,12 @@ public extension CancellableCatchMixin {
460470
- Parameter body: The closure that executes when this promise resolves.
461471
- Returns: A new promise, resolved with this promise’s resolution.
462472
*/
463-
func ensure(on: Dispatcher = conf.D.return, _ body: @escaping () -> Void) -> CancellablePromise<C.T> {
473+
func ensure(on: Dispatcher = conf.dd, _ body: @escaping () -> Void) -> CancellablePromise<C.T> {
464474
let rp = CancellablePromise<C.T>.pending()
465475
rp.promise.cancelContext = self.cancelContext
476+
rp.promise.dispatchState = self.catchable.dispatchState.nextState(givenDispatcher: on)
466477
self.catchable.pipe { result in
467-
on.dispatch {
478+
rp.promise.dispatch {
468479
body()
469480
switch result {
470481
case .success(let value):
@@ -503,11 +514,12 @@ public extension CancellableCatchMixin {
503514
- Parameter body: The closure that executes when this promise resolves.
504515
- Returns: A new promise, resolved with this promise’s resolution.
505516
*/
506-
func ensureThen(on: Dispatcher = conf.D.return, _ body: @escaping () -> CancellablePromise<Void>) -> CancellablePromise<C.T> {
517+
func ensureThen(on: Dispatcher = conf.dd, _ body: @escaping () -> CancellablePromise<Void>) -> CancellablePromise<C.T> {
507518
let rp = CancellablePromise<C.T>.pending()
508519
rp.promise.cancelContext = cancelContext
520+
rp.promise.dispatchState = self.catchable.dispatchState.nextState(givenDispatcher: on)
509521
self.catchable.pipe { result in
510-
on.dispatch {
522+
rp.promise.dispatch {
511523
let rv = body()
512524
rp.promise.appendCancelContext(from: rv)
513525

@@ -552,7 +564,7 @@ public extension CancellableCatchMixin where C.T == Void {
552564
- Parameter body: The handler to execute if this promise is rejected.
553565
- SeeAlso: [Cancellation](https://github.com/mxcl/PromiseKit/blob/master/Documentation/CommonPatterns.md#cancellation)
554566
*/
555-
func recover(on: Dispatcher = conf.D.map, policy: CatchPolicy = conf.catchPolicy, _ body: @escaping(Error) throws -> Void) -> CancellablePromise<Void> {
567+
func recover(on: Dispatcher = conf.dd, policy: CatchPolicy = conf.catchPolicy, _ body: @escaping(Error) throws -> Void) -> CancellablePromise<Void> {
556568
let cancelBody = { (error: Error) throws -> Void in
557569
_ = self.cancelContext.removeItems(self.cancelItemList, clearList: true)
558570
try body(error)
@@ -581,7 +593,7 @@ public extension CancellableCatchMixin where C.T == Void {
581593
- Note: Since this method recovers only specific errors, supplying a `CatchPolicy` is unsupported. You can instead specify e.g. your cancellable error.
582594
- SeeAlso: [Cancellation](https://github.com/mxcl/PromiseKit/blob/master/Documentation/CommonPatterns.md#cancellation)
583595
*/
584-
func recover<E: Swift.Error>(only: E, on: Dispatcher = conf.D.map, _ body: @escaping(E) throws -> Void)
596+
func recover<E: Swift.Error>(only: E, on: Dispatcher = conf.dd, _ body: @escaping(E) throws -> Void)
585597
-> CancellablePromise<Void> where E: Equatable
586598
{
587599
let cancelBody = { (error: E) throws -> Void in
@@ -610,7 +622,7 @@ public extension CancellableCatchMixin where C.T == Void {
610622
- Parameter body: The handler to execute if this promise is rejected with the provided error type.
611623
- SeeAlso: [Cancellation](https://github.com/mxcl/PromiseKit/blob/master/Documentation/CommonPatterns.md#cancellation)
612624
*/
613-
func recover<E: Swift.Error>(only: E.Type, on: Dispatcher = conf.D.map, policy: CatchPolicy = conf.catchPolicy, _ body: @escaping(E) throws -> Void) -> CancellablePromise<Void> {
625+
func recover<E: Swift.Error>(only: E.Type, on: Dispatcher = conf.dd, policy: CatchPolicy = conf.catchPolicy, _ body: @escaping(E) throws -> Void) -> CancellablePromise<Void> {
614626
let cancelBody = { (error: E) throws -> Void in
615627
_ = self.cancelContext.removeItems(self.cancelItemList, clearList: true)
616628
try body(error)

Sources/Cancellation/CancellablePromise.swift

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,13 @@ import Dispatch
88

99
- See: `CancellableThenable`
1010
*/
11-
public class CancellablePromise<T>: CancellableThenable, CancellableCatchMixin {
11+
public class CancellablePromise<T>: CancellableThenable, CancellableCatchMixin, HasDispatchState {
1212
/// Delegate `promise` for this CancellablePromise
1313
public let promise: Promise<T>
14+
var dispatchState: DispatchState {
15+
get { return promise.dispatchState }
16+
set { promise.dispatchState = newValue }
17+
}
1418

1519
/// Type of the delegate `thenable`
1620
public typealias U = Promise<T>
@@ -70,13 +74,11 @@ public class CancellablePromise<T>: CancellableThenable, CancellableCatchMixin {
7074

7175
if promise == nil {
7276
// Wrapper promise
73-
promise = Promise { seal in
74-
reject = seal.reject
75-
bridge.done(on: CurrentThreadDispatcher()) {
76-
seal.fulfill($0)
77-
}.catch(on: CurrentThreadDispatcher(), policy: .allErrors) {
78-
seal.reject($0)
79-
}
77+
let pending = Promise<T>.pending()
78+
(promise, reject) = (pending.promise, pending.resolver.reject)
79+
promise.dispatchState = bridge.dispatchState
80+
bridge.pipe { result in
81+
pending.resolver.resolve(result)
8082
}
8183
}
8284

0 commit comments

Comments
 (0)