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

Split Task into multiple files. #24

Merged
merged 1 commit into from
Jun 1, 2016
Merged
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
40 changes: 40 additions & 0 deletions BoltsSwift.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,22 @@
81D3007F1C93AF9F00E1A1ED /* TaskTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81D300781C93AF9F00E1A1ED /* TaskTests.swift */; };
81D300801C93AF9F00E1A1ED /* TaskTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81D300781C93AF9F00E1A1ED /* TaskTests.swift */; };
87FEF3721A9085FA00C60678 /* BoltsSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 87FEF3661A9085FA00C60678 /* BoltsSwift.framework */; };
F569C0C11CFF6A07000749B6 /* Task+ContinueWith.swift in Sources */ = {isa = PBXBuildFile; fileRef = F569C0C01CFF6A07000749B6 /* Task+ContinueWith.swift */; };
F569C0C21CFF6A07000749B6 /* Task+ContinueWith.swift in Sources */ = {isa = PBXBuildFile; fileRef = F569C0C01CFF6A07000749B6 /* Task+ContinueWith.swift */; };
F569C0C31CFF6A07000749B6 /* Task+ContinueWith.swift in Sources */ = {isa = PBXBuildFile; fileRef = F569C0C01CFF6A07000749B6 /* Task+ContinueWith.swift */; };
F569C0C41CFF6A07000749B6 /* Task+ContinueWith.swift in Sources */ = {isa = PBXBuildFile; fileRef = F569C0C01CFF6A07000749B6 /* Task+ContinueWith.swift */; };
F569C0CC1CFF6AEE000749B6 /* Task+Delay.swift in Sources */ = {isa = PBXBuildFile; fileRef = F569C0CB1CFF6AEE000749B6 /* Task+Delay.swift */; };
F569C0CD1CFF6AEE000749B6 /* Task+Delay.swift in Sources */ = {isa = PBXBuildFile; fileRef = F569C0CB1CFF6AEE000749B6 /* Task+Delay.swift */; };
F569C0CE1CFF6AEE000749B6 /* Task+Delay.swift in Sources */ = {isa = PBXBuildFile; fileRef = F569C0CB1CFF6AEE000749B6 /* Task+Delay.swift */; };
F569C0CF1CFF6AEE000749B6 /* Task+Delay.swift in Sources */ = {isa = PBXBuildFile; fileRef = F569C0CB1CFF6AEE000749B6 /* Task+Delay.swift */; };
F569C0D71CFF6B18000749B6 /* Task+WhenAll.swift in Sources */ = {isa = PBXBuildFile; fileRef = F569C0D61CFF6B18000749B6 /* Task+WhenAll.swift */; };
F569C0D81CFF6B18000749B6 /* Task+WhenAll.swift in Sources */ = {isa = PBXBuildFile; fileRef = F569C0D61CFF6B18000749B6 /* Task+WhenAll.swift */; };
F569C0D91CFF6B18000749B6 /* Task+WhenAll.swift in Sources */ = {isa = PBXBuildFile; fileRef = F569C0D61CFF6B18000749B6 /* Task+WhenAll.swift */; };
F569C0DA1CFF6B18000749B6 /* Task+WhenAll.swift in Sources */ = {isa = PBXBuildFile; fileRef = F569C0D61CFF6B18000749B6 /* Task+WhenAll.swift */; };
F569C0E11CFF6B1F000749B6 /* Task+WhenAny.swift in Sources */ = {isa = PBXBuildFile; fileRef = F569C0E01CFF6B1F000749B6 /* Task+WhenAny.swift */; };
F569C0E21CFF6B1F000749B6 /* Task+WhenAny.swift in Sources */ = {isa = PBXBuildFile; fileRef = F569C0E01CFF6B1F000749B6 /* Task+WhenAny.swift */; };
F569C0E31CFF6B1F000749B6 /* Task+WhenAny.swift in Sources */ = {isa = PBXBuildFile; fileRef = F569C0E01CFF6B1F000749B6 /* Task+WhenAny.swift */; };
F569C0E41CFF6B1F000749B6 /* Task+WhenAny.swift in Sources */ = {isa = PBXBuildFile; fileRef = F569C0E01CFF6B1F000749B6 /* Task+WhenAny.swift */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -82,6 +98,10 @@
81D300781C93AF9F00E1A1ED /* TaskTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TaskTests.swift; sourceTree = "<group>"; };
87FEF3661A9085FA00C60678 /* BoltsSwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = BoltsSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; };
87FEF3711A9085FA00C60678 /* BoltsSwiftTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = BoltsSwiftTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
F569C0C01CFF6A07000749B6 /* Task+ContinueWith.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Task+ContinueWith.swift"; sourceTree = "<group>"; };
F569C0CB1CFF6AEE000749B6 /* Task+Delay.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Task+Delay.swift"; sourceTree = "<group>"; };
F569C0D61CFF6B18000749B6 /* Task+WhenAll.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Task+WhenAll.swift"; sourceTree = "<group>"; };
F569C0E01CFF6B1F000749B6 /* Task+WhenAny.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Task+WhenAny.swift"; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -154,6 +174,10 @@
children = (
81D300651C93AF7300E1A1ED /* Task.swift */,
81D300661C93AF7300E1A1ED /* TaskCompletionSource.swift */,
F569C0C01CFF6A07000749B6 /* Task+ContinueWith.swift */,
F569C0CB1CFF6AEE000749B6 /* Task+Delay.swift */,
F569C0D61CFF6B18000749B6 /* Task+WhenAll.swift */,
F569C0E01CFF6B1F000749B6 /* Task+WhenAny.swift */,
81D300641C93AF7300E1A1ED /* Executor.swift */,
81D300631C93AF7300E1A1ED /* Errors.swift */,
);
Expand Down Expand Up @@ -482,7 +506,11 @@
buildActionMask = 2147483647;
files = (
065894F21C9A9391000FDDA6 /* Errors.swift in Sources */,
F569C0DA1CFF6B18000749B6 /* Task+WhenAll.swift in Sources */,
065894EF1C9A9391000FDDA6 /* Task.swift in Sources */,
F569C0CF1CFF6AEE000749B6 /* Task+Delay.swift in Sources */,
F569C0C41CFF6A07000749B6 /* Task+ContinueWith.swift in Sources */,
F569C0E41CFF6B1F000749B6 /* Task+WhenAny.swift in Sources */,
065894F11C9A9391000FDDA6 /* Executor.swift in Sources */,
065894F01C9A9391000FDDA6 /* TaskCompletionSource.swift in Sources */,
);
Expand All @@ -493,7 +521,11 @@
buildActionMask = 2147483647;
files = (
065894F51C9A93B7000FDDA6 /* Executor.swift in Sources */,
F569C0D91CFF6B18000749B6 /* Task+WhenAll.swift in Sources */,
065894F61C9A93B7000FDDA6 /* Task.swift in Sources */,
F569C0CE1CFF6AEE000749B6 /* Task+Delay.swift in Sources */,
F569C0C31CFF6A07000749B6 /* Task+ContinueWith.swift in Sources */,
F569C0E31CFF6B1F000749B6 /* Task+WhenAny.swift in Sources */,
065894F71C9A93B7000FDDA6 /* Errors.swift in Sources */,
065894F81C9A93B7000FDDA6 /* TaskCompletionSource.swift in Sources */,
);
Expand All @@ -515,7 +547,11 @@
buildActionMask = 2147483647;
files = (
81D3006B1C93AF7300E1A1ED /* Executor.swift in Sources */,
F569C0D81CFF6B18000749B6 /* Task+WhenAll.swift in Sources */,
81D3006D1C93AF7300E1A1ED /* Task.swift in Sources */,
F569C0CD1CFF6AEE000749B6 /* Task+Delay.swift in Sources */,
F569C0C21CFF6A07000749B6 /* Task+ContinueWith.swift in Sources */,
F569C0E21CFF6B1F000749B6 /* Task+WhenAny.swift in Sources */,
81D300691C93AF7300E1A1ED /* Errors.swift in Sources */,
81D3006F1C93AF7300E1A1ED /* TaskCompletionSource.swift in Sources */,
);
Expand All @@ -537,7 +573,11 @@
buildActionMask = 2147483647;
files = (
81D3006A1C93AF7300E1A1ED /* Executor.swift in Sources */,
F569C0D71CFF6B18000749B6 /* Task+WhenAll.swift in Sources */,
81D3006C1C93AF7300E1A1ED /* Task.swift in Sources */,
F569C0CC1CFF6AEE000749B6 /* Task+Delay.swift in Sources */,
F569C0C11CFF6A07000749B6 /* Task+ContinueWith.swift in Sources */,
F569C0E11CFF6B1F000749B6 /* Task+WhenAny.swift in Sources */,
81D300681C93AF7300E1A1ED /* Errors.swift in Sources */,
81D3006E1C93AF7300E1A1ED /* TaskCompletionSource.swift in Sources */,
);
Expand Down
209 changes: 209 additions & 0 deletions Sources/BoltsSwift/Task+ContinueWith.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
/*
* 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

//--------------------------------------
// MARK: - ContinueWith
//--------------------------------------

extension Task {
/**
Internal continueWithTask. This is the method that all other continuations must go through.

- parameter executor: The executor to invoke the closure on.
- parameter options: The options to run the closure with
- parameter continuation: The closure to execute.

- returns: The task resulting from the continuation
*/
private func continueWithTask<S>(executor: Executor, options: TaskContinuationOptions, continuation: (Task throws -> Task<S>)) -> Task<S> {
let taskCompletionSource = TaskCompletionSource<S>()
let wrapperContinuation = {
switch self.state {
case .Success where options.contains(.RunOnSuccess): fallthrough
case .Error where options.contains(.RunOnError): fallthrough
case .Cancelled where options.contains(.RunOnCancelled):
executor.execute {
let wrappedState = TaskState<Task<S>>.fromClosure {
try continuation(self)
}
switch wrappedState {
case .Success(let nextTask):
switch nextTask.state {
case .Pending:
nextTask.continueWith { nextTask in
taskCompletionSource.setState(nextTask.state)
}
default:
taskCompletionSource.setState(nextTask.state)
}
case .Error(let error):
taskCompletionSource.setError(error)
case .Cancelled:
taskCompletionSource.cancel()
default: abort() // This should never happen.
}
}

case .Success(let result as S):
// This is for continueOnErrorWith - the type of the result doesn't change, so we can pass it through
taskCompletionSource.setResult(result)

case .Error(let error):
taskCompletionSource.setError(error)

case .Cancelled:
taskCompletionSource.cancel()

default:
fatalError("Task was in an invalid state \(self.state)")
}
}
appendOrRunContinuation(wrapperContinuation)
return taskCompletionSource.task
}

/**
Enqueues a given closure to be run once this task is complete.

- parameter executor: Determines how the the closure is called. The default is to call the closure immediately.
- parameter continuation: The closure that returns the result of the task.

- returns: A task that will be completed with a result from a given closure.
*/
public func continueWith<S>(executor: Executor = .Default, continuation: (Task throws -> S)) -> Task<S> {
return continueWithTask(executor) { task in
let state = TaskState.fromClosure({
try continuation(task)
})
return Task<S>(state: state)
}
}

/**
Enqueues a given closure to be run once this task is complete.

- parameter executor: Determines how the the closure is called. The default is to call the closure immediately.
- parameter continuation: The closure that returns a task to chain on.

- returns: A task that will be completed when a task returned from a closure is completed.
*/
public func continueWithTask<S>(executor: Executor = .Default, continuation: (Task throws -> Task<S>)) -> Task<S> {
return continueWithTask(executor, options: .RunAlways, continuation: continuation)
}
}

//--------------------------------------
// MARK: - ContinueOnSuccessWith
//--------------------------------------

extension Task {
/**
Enqueues a given closure to be run once this task completes with success (has intended result).

- parameter executor: Determines how the the closure is called. The default is to call the closure immediately.
- parameter continuation: The closure that returns a task to chain on.

- returns: A task that will be completed when a task returned from a closure is completed.
*/
public func continueOnSuccessWith<S>(executor: Executor = .Default, continuation: (TResult throws -> S)) -> Task<S> {
return continueOnSuccessWithTask(executor) { taskResult in
let state = TaskState.fromClosure({
try continuation(taskResult)
})
return Task<S>(state: state)
}
}

/**
Enqueues a given closure to be run once this task completes with success (has intended result).

- parameter executor: Determines how the the closure is called. The default is to call the closure immediately.
- parameter continuation: The closure that returns a task to chain on.

- returns: A task that will be completed when a task returned from a closure is completed.
*/
public func continueOnSuccessWithTask<S>(executor: Executor = .Default, continuation: (TResult throws -> Task<S>)) -> Task<S> {
return continueWithTask(executor, options: .RunOnSuccess) { task in
return try continuation(task.result!)
}
}
}

//--------------------------------------
// MARK: - ContinueOnErrorWith
//--------------------------------------

extension Task {
/**
Enqueues a given closure to be run once this task completes with error.

- parameter executor: Determines how the the closure is called. The default is to call the closure immediately.
- parameter continuation: The closure that returns a task to chain on.

- returns: A task that will be completed when a task returned from a closure is completed.
*/
public func continueOnErrorWith<E: ErrorType>(executor: Executor = .Default, continuation: (E throws -> TResult)) -> Task {
return continueOnErrorWithTask(executor) { (error: E) in
let state = TaskState.fromClosure({
try continuation(error)
})
return Task(state: state)
}
}

/**
Enqueues a given closure to be run once this task completes with error.

- parameter executor: Determines how the the closure is called. The default is to call the closure immediately.
- parameter continuation: The closure that returns a task to chain on.

- returns: A task that will be completed when a task returned from a closure is completed.
*/
public func continueOnErrorWith(executor: Executor = .Default, continuation: (ErrorType throws -> TResult)) -> Task {
return continueOnErrorWithTask(executor) { (error: ErrorType) in
let state = TaskState.fromClosure({
try continuation(error)
})
return Task(state: state)
}
}

/**
Enqueues a given closure to be run once this task completes with error.

- parameter executor: Determines how the the closure is called. The default is to call the closure immediately.
- parameter continuation: The closure that returns a task to chain on.

- returns: A task that will be completed when a task returned from a closure is completed.
*/
public func continueOnErrorWithTask<E: ErrorType>(executor: Executor = .Default, continuation: (E throws -> Task)) -> Task {
return continueOnErrorWithTask(executor) { (error: ErrorType) in
if let error = error as? E {
return try continuation(error)
}
return Task(state: .Error(error))
}
}

/**
Enqueues a given closure to be run once this task completes with error.

- parameter executor: Determines how the the closure is called. The default is to call the closure immediately.
- parameter continuation: The closure that returns a task to chain on.

- returns: A task that will be completed when a task returned from a closure is completed.
*/
public func continueOnErrorWithTask(executor: Executor = .Default, continuation: (ErrorType throws -> Task)) -> Task {
return continueWithTask(executor, options: .RunOnError) { task in
return try continuation(task.error!)
}
}
}
32 changes: 32 additions & 0 deletions Sources/BoltsSwift/Task+Delay.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* 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

//--------------------------------------
// MARK: - Task with Delay
//--------------------------------------

extension Task {
/**
Creates a task that will complete after the given delay.

- parameter delay: The delay for the task to completes.

- returns: A task that will complete after the given delay.
*/
public class func withDelay(delay: NSTimeInterval) -> Task<Void> {
let taskCompletionSource = TaskCompletionSource<Void>()
let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay * NSTimeInterval(NSEC_PER_SEC)))
dispatch_after(time, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
taskCompletionSource.trySetResult()
}
return taskCompletionSource.task
}
}
Loading