Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Possible option for chain dispatchers #1051

Open
wants to merge 7 commits into
base: v7
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 32 additions & 20 deletions Sources/Cancellation/CancellableCatchable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public extension CancellableCatchMixin {
- SeeAlso: [Cancellation](https://github.com/mxcl/PromiseKit/blob/master/Documentation/CommonPatterns.md#cancellation)
*/
@discardableResult
func `catch`(on: Dispatcher = conf.D.return, policy: CatchPolicy = conf.catchPolicy, _ body: @escaping(Error) -> Void) -> CancellableFinalizer {
func `catch`(on: Dispatcher = conf.dd, policy: CatchPolicy = conf.catchPolicy, _ body: @escaping(Error) -> Void) -> CancellableFinalizer {
return CancellableFinalizer(self.catchable.catch(on: on, policy: policy, body), cancel: self.cancelContext)
}

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

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

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

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

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

/// Set a default Dispatcher for the chain. Within the chain, this Dispatcher will remain the
/// default until you change it, even if you dispatch individual closures to other Dispatchers.
///
/// - Parameters:
/// - on: The new default Dispatcher. Use `.default` to return to normal dispatching.

public func dispatch(on: Dispatcher) -> CancellableCascadingFinalizer {
return CancellableCascadingFinalizer(pmkCascadingFinalizer.dispatch(on: on), cancel: cancelContext)
}

/**
Consumes the Swift unused-result warning.
- Note: You should `catch`, but in situations where you know you don’t need a `catch`, `cauterize` makes your intentions clear.
Expand Down Expand Up @@ -221,7 +231,7 @@ public extension CancellableCatchMixin {
- Parameter body: The handler to execute if this promise is rejected.
- SeeAlso: [Cancellation](https://github.com/mxcl/PromiseKit/blob/master/Documentation/CommonPatterns.md#cancellation)
*/
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 {
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 {
let cancelItemList = CancelItemList()

let cancelBody = { (error: Error) throws -> V.U in
Expand Down Expand Up @@ -263,7 +273,7 @@ public extension CancellableCatchMixin {
- Parameter body: The handler to execute if this promise is rejected.
- SeeAlso: [Cancellation](https://github.com/mxcl/PromiseKit/blob/master/Documentation/CommonPatterns.md#cancellation)
*/
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 {
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 {
let cancelBody = { (error: Error) throws -> V in
_ = self.cancelContext.removeItems(self.cancelItemList, clearList: true)
let rval = try body(error)
Expand Down Expand Up @@ -302,7 +312,7 @@ public extension CancellableCatchMixin {
- Note: Since this method recovers only specific errors, supplying a `CatchPolicy` is unsupported.
- SeeAlso: [Cancellation](https://github.com/mxcl/PromiseKit/blob/master/Documentation/CommonPatterns.md#cancellation)
*/
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 {
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 {
let cancelItemList = CancelItemList()

let cancelBody = { (error: E) throws -> V.U in
Expand Down Expand Up @@ -340,7 +350,7 @@ public extension CancellableCatchMixin {
- Note: Since this method recovers only specific errors, supplying a `CatchPolicy` is unsupported. You can instead specify e.g. your cancellable error.
- SeeAlso: [Cancellation](https://github.com/mxcl/PromiseKit/blob/master/Documentation/CommonPatterns.md#cancellation)
*/
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 {
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 {
let cancelBody = { (error: E) throws -> V in
_ = self.cancelContext.removeItems(self.cancelItemList, clearList: true)
let rval = try body(error)
Expand Down Expand Up @@ -378,7 +388,7 @@ public extension CancellableCatchMixin {
- Parameter body: The handler to execute if this promise is rejected with the provided error type.
- SeeAlso: [Cancellation](https://github.com/mxcl/PromiseKit/blob/master/Documentation/CommonPatterns.md#cancellation)
*/
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 {
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 {
let cancelItemList = CancelItemList()

let cancelBody = { (error: E) throws -> V.U in
Expand Down Expand Up @@ -417,7 +427,7 @@ public extension CancellableCatchMixin {
- Parameter body: The handler to execute if this promise is rejected with the provided error type.
- SeeAlso: [Cancellation](https://github.com/mxcl/PromiseKit/blob/master/Documentation/CommonPatterns.md#cancellation)
*/
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 {
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 {
let cancelBody = { (error: E) throws -> V in
_ = self.cancelContext.removeItems(self.cancelItemList, clearList: true)
let rval = try body(error)
Expand Down Expand Up @@ -460,11 +470,12 @@ public extension CancellableCatchMixin {
- Parameter body: The closure that executes when this promise resolves.
- Returns: A new promise, resolved with this promise’s resolution.
*/
func ensure(on: Dispatcher = conf.D.return, _ body: @escaping () -> Void) -> CancellablePromise<C.T> {
func ensure(on: Dispatcher = conf.dd, _ body: @escaping () -> Void) -> CancellablePromise<C.T> {
let rp = CancellablePromise<C.T>.pending()
rp.promise.cancelContext = self.cancelContext
rp.promise.dispatchState = self.catchable.dispatchState.nextState(givenDispatcher: on)
self.catchable.pipe { result in
on.dispatch {
rp.promise.dispatch {
body()
switch result {
case .success(let value):
Expand Down Expand Up @@ -503,11 +514,12 @@ public extension CancellableCatchMixin {
- Parameter body: The closure that executes when this promise resolves.
- Returns: A new promise, resolved with this promise’s resolution.
*/
func ensureThen(on: Dispatcher = conf.D.return, _ body: @escaping () -> CancellablePromise<Void>) -> CancellablePromise<C.T> {
func ensureThen(on: Dispatcher = conf.dd, _ body: @escaping () -> CancellablePromise<Void>) -> CancellablePromise<C.T> {
let rp = CancellablePromise<C.T>.pending()
rp.promise.cancelContext = cancelContext
rp.promise.dispatchState = self.catchable.dispatchState.nextState(givenDispatcher: on)
self.catchable.pipe { result in
on.dispatch {
rp.promise.dispatch {
let rv = body()
rp.promise.appendCancelContext(from: rv)

Expand Down Expand Up @@ -552,7 +564,7 @@ public extension CancellableCatchMixin where C.T == Void {
- Parameter body: The handler to execute if this promise is rejected.
- SeeAlso: [Cancellation](https://github.com/mxcl/PromiseKit/blob/master/Documentation/CommonPatterns.md#cancellation)
*/
func recover(on: Dispatcher = conf.D.map, policy: CatchPolicy = conf.catchPolicy, _ body: @escaping(Error) throws -> Void) -> CancellablePromise<Void> {
func recover(on: Dispatcher = conf.dd, policy: CatchPolicy = conf.catchPolicy, _ body: @escaping(Error) throws -> Void) -> CancellablePromise<Void> {
let cancelBody = { (error: Error) throws -> Void in
_ = self.cancelContext.removeItems(self.cancelItemList, clearList: true)
try body(error)
Expand Down Expand Up @@ -581,7 +593,7 @@ public extension CancellableCatchMixin where C.T == Void {
- Note: Since this method recovers only specific errors, supplying a `CatchPolicy` is unsupported. You can instead specify e.g. your cancellable error.
- SeeAlso: [Cancellation](https://github.com/mxcl/PromiseKit/blob/master/Documentation/CommonPatterns.md#cancellation)
*/
func recover<E: Swift.Error>(only: E, on: Dispatcher = conf.D.map, _ body: @escaping(E) throws -> Void)
func recover<E: Swift.Error>(only: E, on: Dispatcher = conf.dd, _ body: @escaping(E) throws -> Void)
-> CancellablePromise<Void> where E: Equatable
{
let cancelBody = { (error: E) throws -> Void in
Expand Down Expand Up @@ -610,7 +622,7 @@ public extension CancellableCatchMixin where C.T == Void {
- Parameter body: The handler to execute if this promise is rejected with the provided error type.
- SeeAlso: [Cancellation](https://github.com/mxcl/PromiseKit/blob/master/Documentation/CommonPatterns.md#cancellation)
*/
func recover<E: Swift.Error>(only: E.Type, on: Dispatcher = conf.D.map, policy: CatchPolicy = conf.catchPolicy, _ body: @escaping(E) throws -> Void) -> CancellablePromise<Void> {
func recover<E: Swift.Error>(only: E.Type, on: Dispatcher = conf.dd, policy: CatchPolicy = conf.catchPolicy, _ body: @escaping(E) throws -> Void) -> CancellablePromise<Void> {
let cancelBody = { (error: E) throws -> Void in
_ = self.cancelContext.removeItems(self.cancelItemList, clearList: true)
try body(error)
Expand Down
18 changes: 10 additions & 8 deletions Sources/Cancellation/CancellablePromise.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,13 @@ import Dispatch

- See: `CancellableThenable`
*/
public class CancellablePromise<T>: CancellableThenable, CancellableCatchMixin {
public class CancellablePromise<T>: CancellableThenable, CancellableCatchMixin, HasDispatchState {
/// Delegate `promise` for this CancellablePromise
public let promise: Promise<T>
var dispatchState: DispatchState {
get { return promise.dispatchState }
set { promise.dispatchState = newValue }
}

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

if promise == nil {
// Wrapper promise
promise = Promise { seal in
reject = seal.reject
bridge.done(on: CurrentThreadDispatcher()) {
seal.fulfill($0)
}.catch(on: CurrentThreadDispatcher(), policy: .allErrors) {
seal.reject($0)
}
let pending = Promise<T>.pending()
(promise, reject) = (pending.promise, pending.resolver.reject)
promise.dispatchState = bridge.dispatchState
bridge.pipe { result in
pending.resolver.resolve(result)
}
}

Expand Down
Loading