Skip to content

Commit

Permalink
Merge pull request #76 from JosephEarl/feature/whenall-result
Browse files Browse the repository at this point in the history
Add taskForCompletionOfAllTasksWithResults and faulted property
  • Loading branch information
nlutsenko committed Jan 26, 2015
2 parents bf4785b + 417e52c commit 8721616
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 0 deletions.
13 changes: 13 additions & 0 deletions Bolts/Common/BFTask.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,14 @@ typedef id(^BFContinuationBlock)(BFTask *task);
*/
+ (instancetype)taskForCompletionOfAllTasks:(NSArray *)tasks;

/*!
Returns a task that will be completed once all of the input tasks have completed.
If all tasks complete successfully without being faulted or cancelled the result will be
an `NSArray` of all task results in the order they were provided.
@param tasks An `NSArray` of the tasks to use as an input.
*/
+ (instancetype)taskForCompletionOfAllTasksWithResults:(NSArray *)tasks;

/*!
Returns a task that will be completed a certain amount of time in the future.
@param millis The approximate number of milliseconds to wait before the
Expand Down Expand Up @@ -98,6 +106,11 @@ typedef id(^BFContinuationBlock)(BFTask *task);
*/
@property (nonatomic, assign, readonly, getter = isCancelled) BOOL cancelled;

/*!
Whether this task has completed due to an error or exception.
*/
@property (nonatomic, assign, readonly, getter = isFaulted) BOOL faulted;

/*!
Whether this task has completed.
*/
Expand Down
15 changes: 15 additions & 0 deletions Bolts/Common/BFTask.m
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ @interface BFTask () {
}

@property (atomic, assign, readwrite, getter = isCancelled) BOOL cancelled;
@property (atomic, assign, readwrite, getter = isFaulted) BOOL faulted;
@property (atomic, assign, readwrite, getter = isCompleted) BOOL completed;

@property (nonatomic, retain, readwrite) NSObject *lock;
Expand Down Expand Up @@ -131,6 +132,12 @@ + (instancetype)taskForCompletionOfAllTasks:(NSArray *)tasks {
return tcs.task;
}

+ (instancetype)taskForCompletionOfAllTasksWithResults:(NSArray *)tasks {
return [[self taskForCompletionOfAllTasks:tasks] continueWithSuccessBlock:^id(BFTask *task) {
return [tasks valueForKey:@"result"];
}];
}

+ (instancetype)taskWithDelay:(int)millis {
BFTaskCompletionSource *tcs = [BFTaskCompletionSource taskCompletionSource];
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, millis * NSEC_PER_MSEC);
Expand Down Expand Up @@ -191,6 +198,7 @@ - (BOOL)trySetError:(NSError *)error {
return NO;
}
self.completed = YES;
self.faulted = YES;
_error = error;
[self runContinuations];
return YES;
Expand All @@ -216,6 +224,7 @@ - (BOOL)trySetException:(NSException *)exception {
return NO;
}
self.completed = YES;
self.faulted = YES;
_exception = exception;
[self runContinuations];
return YES;
Expand All @@ -228,6 +237,12 @@ - (BOOL)isCancelled {
}
}

- (BOOL)isFaulted {
@synchronized (self.lock) {
return _faulted;
}
}

- (void)cancel {
@synchronized (self.lock) {
if (![self trySetCancelled]) {
Expand Down
44 changes: 44 additions & 0 deletions BoltsTests/TaskTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,50 @@ - (void)testTaskForCompletionOfAllTasksCancelled {
}] waitUntilFinished];
}

- (void)testTaskForCompletionOfAllTasksNoTasksImmediateCompletion {
NSMutableArray *tasks = [NSMutableArray array];

BFTask *task = [BFTask taskForCompletionOfAllTasks:tasks];
XCTAssertTrue(task.completed);
XCTAssertFalse(task.cancelled);
XCTAssertFalse(task.faulted);
}

- (void)testTaskForCompletionOfAllTasksWithResultsSuccess {
NSMutableArray *tasks = [NSMutableArray array];

const int kTaskCount = 20;
for (int i = 0; i < kTaskCount; ++i) {
double sleepTimeInMs = i * 10;
int result = i + 1;
[tasks addObject:[[BFTask taskWithDelay:sleepTimeInMs] continueWithBlock:^id(BFTask *task) {
return @(result);
}]];
}

[[[BFTask taskForCompletionOfAllTasksWithResults:tasks] continueWithBlock:^id(BFTask *task) {
XCTAssertFalse(task.cancelled);
XCTAssertFalse(task.faulted);

NSArray *results = task.result;
for (int i = 0; i < kTaskCount; ++i) {
NSNumber *individualResult = [results objectAtIndex:i];
XCTAssertEqual([individualResult intValue], [((BFTask *)[tasks objectAtIndex:i]).result intValue]);
}
return nil;
}] waitUntilFinished];
}

- (void)testTaskForCompletionOfAllTasksWithResultsNoTasksImmediateCompletion {
NSMutableArray *tasks = [NSMutableArray array];

BFTask *task = [BFTask taskForCompletionOfAllTasksWithResults:tasks];
XCTAssertTrue(task.completed);
XCTAssertFalse(task.cancelled);
XCTAssertFalse(task.faulted);
XCTAssertTrue(task.result != nil);
}

- (void)testWaitUntilFinished {
BFTask *task = [[BFTask taskWithDelay:50] continueWithBlock:^id(BFTask *task) {
return @"foo";
Expand Down

0 comments on commit 8721616

Please sign in to comment.