Skip to content

Commit

Permalink
Split Task into multiple files. (#24)
Browse files Browse the repository at this point in the history
This helps for readability, and keeping every file concerned with a
single aspect of 'Task'.
  • Loading branch information
richardjrossiii committed Jun 1, 2016
1 parent 4e08f7e commit 3f10966
Show file tree
Hide file tree
Showing 6 changed files with 469 additions and 364 deletions.
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

0 comments on commit 3f10966

Please sign in to comment.