Skip to content
GitLab
    • Explore Projects Groups Snippets
Projects Groups Snippets
  • /
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Sign in / Register
  • B Bolts-ObjC
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
  • Issues 34
    • Issues 34
    • List
    • Boards
    • Service Desk
    • Milestones
  • Merge requests 7
    • Merge requests 7
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
  • Deployments
    • Deployments
    • Environments
    • Releases
  • Packages and registries
    • Packages and registries
    • Package Registry
    • Infrastructure Registry
  • Monitor
    • Monitor
    • Incidents
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Repository
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • BoltsFramework
  • Bolts-ObjC
  • Merge requests
  • !89

Add Task Cancellation

  • Review changes

  • Download
  • Email patches
  • Plain diff
Merged Administrator requested to merge github/fork/josephearl/feature/task-cancellation into master 10 years ago
  • Overview 24
  • Commits 1
  • Pipelines 0
  • Changes 12

Created by: josephearl

Initial CancellationToken & CancellationTokenSource implementation to match the C# API (system.threading.cancellationtoken and system.threading.cancellationtokensource) and the cancellation API on Android (https://github.com/BoltsFramework/Bolts-Android/pull/53 and https://github.com/BoltsFramework/Bolts-Android/pull/56).

Compare
  • master (base)

and
  • latest version
    52fc0e22
    1 commit, 2 years ago

12 files
+ 706
- 5

    Preferences

    File browser
    Compare changes
Bolts.x‎codeproj‎
project‎.pbxproj‎ +42 -0
Bolts/‎Common‎
BFCancella‎tionToken.h‎ +38 -0
BFCancella‎tionToken.m‎ +135 -0
BFCancellationTo‎kenRegistration.h‎ +25 -0
BFCancellationTo‎kenRegistration.m‎ +74 -0
BFCancellatio‎nTokenSource.h‎ +56 -0
BFCancellatio‎nTokenSource.m‎ +70 -0
BFTa‎sk.h‎ +70 -0
BFTa‎sk.m‎ +55 -5
Bol‎ts.h‎ +3 -0
Bolts‎Tests‎
Cancellat‎ionTests.m‎ +56 -0
TaskT‎ests.m‎ +82 -0
Bolts/Common/BFCancellationToken.h 0 → 100644
+ 38
- 0
  • View file @ 52fc0e22

  • Edit in single-file editor

  • Open in Web IDE

/*
* Copyright (c) 2014, 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/Foundation.h>
#import <Bolts/BFCancellationTokenRegistration.h>
/*!
A block that will be called when a token is cancelled.
*/
typedef void(^BFCancellationBlock)();
/*!
The consumer view of a CancellationToken. Propagates notification that
operations should be canceled.
A BFCancellationToken has methods to inspect whether the token has been cancelled.
*/
@interface BFCancellationToken : NSObject
/*!
Whether cancellation has been requested for this token source.
*/
@property (nonatomic, assign, readonly, getter = isCancellationRequested) BOOL cancellationRequested;
/*!
Register a block to be notified when the token is cancelled.
If the token is already cancelled the delegate will be notified immediately.
*/
- (BFCancellationTokenRegistration *)registerCancellationObserverWithBlock:(BFCancellationBlock)block;
@end
Bolts/Common/BFCancellationToken.h 0 → 100644
+ 38
- 0
  • View file @ 52fc0e22

  • Edit in single-file editor

  • Open in Web IDE

/*
* Copyright (c) 2014, 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/Foundation.h>
#import <Bolts/BFCancellationTokenRegistration.h>
/*!
A block that will be called when a token is cancelled.
*/
typedef void(^BFCancellationBlock)();
/*!
The consumer view of a CancellationToken. Propagates notification that
operations should be canceled.
A BFCancellationToken has methods to inspect whether the token has been cancelled.
*/
@interface BFCancellationToken : NSObject
/*!
Whether cancellation has been requested for this token source.
*/
@property (nonatomic, assign, readonly, getter = isCancellationRequested) BOOL cancellationRequested;
/*!
Register a block to be notified when the token is cancelled.
If the token is already cancelled the delegate will be notified immediately.
*/
- (BFCancellationTokenRegistration *)registerCancellationObserverWithBlock:(BFCancellationBlock)block;
@end
Bolts/Common/BFCancellationToken.m 0 → 100644
+ 135
- 0
  • View file @ 52fc0e22

  • Edit in single-file editor

  • Open in Web IDE

/*
* Copyright (c) 2014, 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 "BFCancellationToken.h"
#import "BFCancellationTokenRegistration.h"
@interface BFCancellationToken ()
@property (atomic, assign, getter = isCancellationRequested) BOOL cancellationRequested;
@property (nonatomic, strong) NSMutableArray *registrations;
@property (nonatomic, strong) NSObject *lock;
@property (nonatomic) BOOL disposed;
@end
@interface BFCancellationTokenRegistration (BFCancellationToken)
+ (instancetype)registrationWithToken:(BFCancellationToken *)token delegate:(BFCancellationBlock)delegate;
- (void)notifyDelegate;
@end
@implementation BFCancellationToken
#pragma mark - Initializer
- (instancetype)init {
if (self = [super init]) {
_registrations = [NSMutableArray array];
_lock = [NSObject new];
}
return self;
}
#pragma mark - Custom Setters/Getters
- (BOOL)isCancellationRequested {
@synchronized(self.lock) {
[self throwIfDisposed];
return _cancellationRequested;
}
}
- (void)cancel {
NSArray *registrations;
@synchronized(self.lock) {
[self throwIfDisposed];
if (_cancellationRequested) {
return;
}
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(cancelPrivate) object:nil];
_cancellationRequested = YES;
registrations = [self.registrations copy];
}
[self notifyCancellation:registrations];
}
- (void)notifyCancellation:(NSArray *)registrations {
for (BFCancellationTokenRegistration *registration in registrations) {
[registration notifyDelegate];
}
}
- (BFCancellationTokenRegistration *)registerCancellationObserverWithBlock:(BFCancellationBlock)block {
@synchronized(self.lock) {
BFCancellationTokenRegistration *registration = [BFCancellationTokenRegistration registrationWithToken:self delegate:[block copy]];
[self.registrations addObject:registration];
return registration;
}
}
- (void)unregisterRegistration:(BFCancellationTokenRegistration *)registration {
@synchronized(self.lock) {
[self throwIfDisposed];
[self.registrations removeObject:registration];
}
}
// Delay on a non-public method to prevent interference with a user calling performSelector or
// cancelPreviousPerformRequestsWithTarget on the public method
- (void)cancelPrivate {
[self cancel];
}
- (void)cancelAfterDelay:(int)millis {
[self throwIfDisposed];
NSAssert(millis >= -1, @"Delay must be >= -1");
if (millis == 0) {
[self cancel];
return;
}
@synchronized(self.lock) {
[self throwIfDisposed];
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(cancelPrivate) object:nil];
if (self.cancellationRequested) {
return;
}
if (millis != -1) {
double delay = (double) millis / 1000;
[self performSelector:@selector(cancelPrivate) withObject:nil afterDelay:delay];
}
}
}
- (void)dispose {
@synchronized(self.lock) {
if (self.disposed) {
return;
}
self.disposed = YES;
for (BFCancellationTokenRegistration *registration in self.registrations) {
[registration dispose];
}
[self.registrations removeAllObjects];
}
}
- (void)throwIfDisposed {
NSAssert(!self.disposed, @"Object already disposed");
}
@end
Bolts/Common/BFCancellationTokenRegistration.h 0 → 100644
+ 25
- 0
  • View file @ 52fc0e22

  • Edit in single-file editor

  • Open in Web IDE

/*
* Copyright (c) 2014, 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/Foundation.h>
/*!
Represents the registration of a cancellation observer with a cancellation token.
Can be used to unregister the observer at a later time.
*/
@interface BFCancellationTokenRegistration : NSObject
/*!
Removes the cancellation observer registered with the token and releases all resources associated
with this registration.
*/
- (void)dispose;
@end
Bolts/Common/BFCancellationTokenRegistration.m 0 → 100644
+ 74
- 0
  • View file @ 52fc0e22

  • Edit in single-file editor

  • Open in Web IDE

/*
* Copyright (c) 2014, 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 "BFCancellationTokenRegistration.h"
#import "BFCancellationToken.h"
@interface BFCancellationTokenRegistration ()
@property (nonatomic, weak) BFCancellationToken *token;
@property (nonatomic, strong) BFCancellationBlock cancellationObserverBlock;
@property (nonatomic, strong) NSObject *lock;
@property (nonatomic) BOOL disposed;
@end
@interface BFCancellationToken (BFCancellationTokenRegistration)
- (void)unregisterRegistration:(BFCancellationTokenRegistration *)registration;
@end
@implementation BFCancellationTokenRegistration
+ (instancetype)registrationWithToken:(BFCancellationToken *)token delegate:(BFCancellationBlock)delegate {
BFCancellationTokenRegistration *registration = [BFCancellationTokenRegistration new];
registration.token = token;
registration.cancellationObserverBlock = delegate;
return registration;
}
- (instancetype)init {
if (self = [super init]) {
_lock = [NSObject new];
}
return self;
}
- (void)dispose {
@synchronized(self.lock) {
if (self.disposed) {
return;
}
self.disposed = YES;
}
BFCancellationToken *token = self.token;
if (token != nil) {
[token unregisterRegistration:self];
self.token = nil;
}
self.cancellationObserverBlock = nil;
}
- (void)notifyDelegate {
@synchronized(self.lock) {
[self throwIfDisposed];
self.cancellationObserverBlock();
}
}
- (void)throwIfDisposed {
NSAssert(!self.disposed, @"Object already disposed");
}
@end
Bolts/Common/BFCancellationTokenSource.h 0 → 100644
+ 56
- 0
  • View file @ 52fc0e22

  • Edit in single-file editor

  • Open in Web IDE

/*
* Copyright (c) 2014, 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/Foundation.h>
@class BFCancellationToken;
/*!
BFCancellationTokenSource represents the producer side of a CancellationToken.
Signals to a CancellationToken that it should be canceled.
It is a cancellation token that also has methods for changing the state of a token
by cancelling it.
*/
@interface BFCancellationTokenSource : NSObject
/*!
Creates a new cancellation token source.
*/
+ (instancetype)cancellationTokenSource;
/*!
The cancellation token associated with this CancellationTokenSource.
*/
@property (nonatomic, strong, readonly) BFCancellationToken *token;
/*!
Whether cancellation has been requested for this token source.
*/
@property (nonatomic, assign, readonly, getter = isCancellationRequested) BOOL cancellationRequested;
/*!
Cancels the token if it has not already been cancelled.
*/
- (void)cancel;
/*!
Schedules a cancel operation on this CancellationTokenSource after the specified number of milliseconds.
@param millis The number of milliseconds to wait before completing the returned task.
If delay is 0 the cancel is executed immediately. If delay is -1 any scheduled cancellation is stopped.
*/
- (void)cancelAfterDelay:(int)millis;
/*!
Releases all resources associated with this token source, including disposing of all
registrations.
*/
- (void)dispose;
@end
Bolts/Common/BFCancellationTokenSource.m 0 → 100644
+ 70
- 0
  • View file @ 52fc0e22

  • Edit in single-file editor

  • Open in Web IDE

/*
* Copyright (c) 2014, 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 "BFCancellationTokenSource.h"
#import "BFCancellationToken.h"
@interface BFCancellationTokenSource ()
@property (nonatomic, strong, readwrite) BFCancellationToken *token;
@property (atomic, assign, readwrite, getter=isCancellationRequested) BOOL cancellationRequested;
@property (atomic, assign) BOOL disposed;
@property (nonatomic, strong) NSObject *lock;
@end
@interface BFCancellationToken (BFCancellationTokenSource)
- (void)cancel;
- (void)cancelAfterDelay:(int)millis;
- (void)dispose;
- (void)throwIfDisposed;
@end
@implementation BFCancellationTokenSource
#pragma mark - Initializer
+ (instancetype)cancellationTokenSource {
return [BFCancellationTokenSource new];
}
- (instancetype)init {
if (self = [super init]) {
_token = [BFCancellationToken new];
_lock = [NSObject new];
}
return self;
}
#pragma mark - Custom Setters/Getters
- (BOOL)isCancellationRequested {
return _token.isCancellationRequested;
}
- (void)cancel {
[_token cancel];
}
- (void)cancelAfterDelay:(int)millis {
[_token cancelAfterDelay:millis];
}
- (void)dispose {
[_token dispose];
}
@end
Bolts/Common/BFTask.h
+ 70
- 0
  • View file @ 52fc0e22

  • Edit in single-file editor

  • Open in Web IDE


@@ -10,6 +10,8 @@
#import <Foundation/Foundation.h>
#import <Bolts/BFCancellationToken.h>
/*!
Error domain used if there was multiple errors on <BFTask taskForCompletionOfAllTasks:>.
*/
@@ -80,6 +82,15 @@ typedef id(^BFContinuationBlock)(BFTask *task);
*/
+ (instancetype)taskWithDelay:(int)millis;
/*!
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
task will be finished (with result == nil).
@param token The cancellation token (optional).
*/
+ (instancetype)taskWithDelay:(int)millis
cancellationToken:(BFCancellationToken *)token;
/*!
Returns a task that will be completed after the given block completes with
the specified executor.
@@ -139,6 +150,21 @@ typedef id(^BFContinuationBlock)(BFTask *task);
*/
- (instancetype)continueWithBlock:(BFContinuationBlock)block;
/*!
Enqueues the given block to be run once this task is complete.
This method uses a default execution strategy. The block will be
run on the thread where the previous task completes, unless the
the stack depth is too deep, in which case it will be run on a
dispatch queue with default priority.
@param block The block to be run once this task is complete.
@param cancellationToken The cancellation token (optional).
@returns A task that will be completed after block has run.
If block returns a BFTask, then the task returned from
this method will not be completed until that task is completed.
*/
- (instancetype)continueWithBlock:(BFContinuationBlock)block
cancellationToken:(BFCancellationToken *)cancellationToken;
/*!
Enqueues the given block to be run once this task is complete.
@param executor A BFExecutor responsible for determining how the
@@ -150,6 +176,19 @@ typedef id(^BFContinuationBlock)(BFTask *task);
*/
- (instancetype)continueWithExecutor:(BFExecutor *)executor
withBlock:(BFContinuationBlock)block;
/*!
Enqueues the given block to be run once this task is complete.
@param executor A BFExecutor responsible for determining how the
continuation block will be run.
@param block The block to be run once this task is complete.
@param cancellationToken The cancellation token (optional).
@returns A task that will be completed after block has run.
If block returns a BFTask, then the task returned from
his method will not be completed until that task is completed.
*/
- (instancetype)continueWithExecutor:(BFExecutor *)executor
block:(BFContinuationBlock)block
cancellationToken:(BFCancellationToken *)cancellationToken;
/*!
Identical to continueWithBlock:, except that the block is only run
@@ -163,6 +202,20 @@ typedef id(^BFContinuationBlock)(BFTask *task);
*/
- (instancetype)continueWithSuccessBlock:(BFContinuationBlock)block;
/*!
Identical to continueWithBlock:, except that the block is only run
if this task did not produce a cancellation, error, or exception.
If it did, then the failure will be propagated to the returned
task.
@param block The block to be run once this task is complete.
@param cancellationToken The cancellation token (optional).
@returns A task that will be completed after block has run.
If block returns a BFTask, then the task returned from
this method will not be completed until that task is completed.
*/
- (instancetype)continueWithSuccessBlock:(BFContinuationBlock)block
cancellationToken:(BFCancellationToken *)cancellationToken;
/*!
Identical to continueWithExecutor:withBlock:, except that the block
is only run if this task did not produce a cancellation, error, or
@@ -178,6 +231,23 @@ typedef id(^BFContinuationBlock)(BFTask *task);
- (instancetype)continueWithExecutor:(BFExecutor *)executor
withSuccessBlock:(BFContinuationBlock)block;
/*!
Identical to continueWithExecutor:withBlock:, except that the block
is only run if this task did not produce a cancellation, error, or
exception. If it did, then the failure will be propagated to the
returned task.
@param executor A BFExecutor responsible for determining how the
continuation block will be run.
@param block The block to be run once this task is complete.
@param cancellationToken The cancellation token (optional).
@returns A task that will be completed after block has run.
If block returns a BFTask, then the task returned from
this method will not be completed until that task is completed.
*/
- (instancetype)continueWithExecutor:(BFExecutor *)executor
successBlock:(BFContinuationBlock)block
cancellationToken:(BFCancellationToken *)cancellationToken;
/*!
Waits until this operation is completed.
This method is inefficient and consumes a thread resource while
Bolts/Common/BFTask.m
+ 55
- 5
  • View file @ 52fc0e22

  • Edit in single-file editor

  • Open in Web IDE


@@ -150,6 +150,24 @@ NSString *const BFTaskMultipleExceptionsException = @"BFMultipleExceptionsExcept
return tcs.task;
}
+ (instancetype)taskWithDelay:(int)millis
cancellationToken:(BFCancellationToken *)token {
if (token.cancellationRequested) {
return [BFTask cancelledTask];
}
BFTaskCompletionSource *tcs = [BFTaskCompletionSource taskCompletionSource];
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, millis * NSEC_PER_MSEC);
dispatch_after(popTime, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
if (token.cancellationRequested) {
[tcs cancel];
return;
}
tcs.result = nil;
});
return tcs.task;
}
+ (instancetype)taskFromExecutor:(BFExecutor *)executor
withBlock:(id (^)())block {
return [[self taskWithResult:nil] continueWithExecutor:executor withBlock:block];
@@ -295,11 +313,22 @@ NSString *const BFTaskMultipleExceptionsException = @"BFMultipleExceptionsExcept
- (instancetype)continueWithExecutor:(BFExecutor *)executor
withBlock:(BFContinuationBlock)block {
return [self continueWithExecutor:executor block:block cancellationToken:nil];
}
- (instancetype)continueWithExecutor:(BFExecutor *)executor
block:(BFContinuationBlock)block
cancellationToken:(BFCancellationToken *)cancellationToken {
BFTaskCompletionSource *tcs = [BFTaskCompletionSource taskCompletionSource];
// Capture all of the state that needs to used when the continuation is complete.
void (^wrappedBlock)() = ^() {
[executor execute:^{
if (cancellationToken.cancellationRequested) {
[tcs cancel];
return;
}
id result = nil;
@try {
result = block(self);
@@ -307,6 +336,7 @@ NSString *const BFTaskMultipleExceptionsException = @"BFMultipleExceptionsExcept
tcs.exception = exception;
return;
}
if ([result isKindOfClass:[BFTask class]]) {
id (^setupWithTask) (BFTask *) = ^id(BFTask *task) {
@@ -327,7 +357,7 @@ NSString *const BFTaskMultipleExceptionsException = @"BFMultipleExceptionsExcept
if (resultTask.completed) {
setupWithTask(resultTask);
} else {
[resultTask continueWithBlock:setupWithTask];
[resultTask continueWithBlock:setupWithTask cancellationToken:cancellationToken];
}
} else {
@@ -351,22 +381,42 @@ NSString *const BFTaskMultipleExceptionsException = @"BFMultipleExceptionsExcept
}
- (instancetype)continueWithBlock:(BFContinuationBlock)block {
return [self continueWithExecutor:[BFExecutor defaultExecutor] withBlock:block];
return [self continueWithExecutor:[BFExecutor defaultExecutor] block:block cancellationToken:nil];
}
- (instancetype)continueWithBlock:(BFContinuationBlock)block
cancellationToken:(BFCancellationToken *)cancellationToken {
return [self continueWithExecutor:[BFExecutor defaultExecutor] block:block cancellationToken:cancellationToken];
}
- (instancetype)continueWithExecutor:(BFExecutor *)executor
withSuccessBlock:(BFContinuationBlock)block {
return [self continueWithExecutor:executor withBlock:^id(BFTask *task) {
return [self continueWithExecutor:executor successBlock:block cancellationToken:nil];
}
- (instancetype)continueWithExecutor:(BFExecutor *)executor
successBlock:(BFContinuationBlock)block
cancellationToken:(BFCancellationToken *)cancellationToken {
if (cancellationToken.cancellationRequested) {
return [BFTask cancelledTask];
}
return [self continueWithExecutor:executor block:^id(BFTask *task) {
if (task.faulted || task.cancelled) {
return task;
} else {
return block(task);
}
}];
} cancellationToken:cancellationToken];
}
- (instancetype)continueWithSuccessBlock:(BFContinuationBlock)block {
return [self continueWithExecutor:[BFExecutor defaultExecutor] withSuccessBlock:block];
return [self continueWithExecutor:[BFExecutor defaultExecutor] successBlock:block cancellationToken:nil];
}
- (instancetype)continueWithSuccessBlock:(BFContinuationBlock)block
cancellationToken:(BFCancellationToken *)cancellationToken {
return [self continueWithExecutor:[BFExecutor defaultExecutor] successBlock:block cancellationToken:cancellationToken];
}
#pragma mark - Syncing Task (Avoid it)
Bolts/Common/Bolts.h
+ 3
- 0
  • View file @ 52fc0e22

  • Edit in single-file editor

  • Open in Web IDE


@@ -9,6 +9,9 @@
*/
#import <Bolts/BoltsVersion.h>
#import <Bolts/BFCancellationToken.h>
#import <Bolts/BFCancellationTokenRegistration.h>
#import <Bolts/BFCancellationTokenSource.h>
#import <Bolts/BFExecutor.h>
#import <Bolts/BFTask.h>
#import <Bolts/BFTaskCompletionSource.h>
Bolts.xcodeproj/project.pbxproj
+ 42
- 0
  • View file @ 52fc0e22

  • Edit in single-file editor

  • Open in Web IDE


@@ -15,6 +15,20 @@
1EC3017118CDAA8400D06D07 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EC3017018CDAA8400D06D07 /* AppDelegate.m */; };
1EC3017318CDAA8400D06D07 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1EC3017218CDAA8400D06D07 /* Images.xcassets */; };
1EC3019118CDABCE00D06D07 /* AppLinkTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EC3019018CDABCE00D06D07 /* AppLinkTests.m */; };
7C60AEBF1ACF08F300747DD7 /* BFCancellationToken.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C60AEBD1ACF08F300747DD7 /* BFCancellationToken.h */; settings = {ATTRIBUTES = (Public, ); }; };
7C60AEC01ACF08F300747DD7 /* BFCancellationToken.m in Sources */ = {isa = PBXBuildFile; fileRef = 7C60AEBE1ACF08F300747DD7 /* BFCancellationToken.m */; };
7C60AEC31ACF093D00747DD7 /* BFCancellationTokenSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C60AEC11ACF093D00747DD7 /* BFCancellationTokenSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
7C60AEC41ACF093D00747DD7 /* BFCancellationTokenSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 7C60AEC21ACF093D00747DD7 /* BFCancellationTokenSource.m */; };
7C60AEC61ACF19F900747DD7 /* CancellationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7C60AEC51ACF19F900747DD7 /* CancellationTests.m */; };
7C60AEC71ACF19FD00747DD7 /* CancellationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7C60AEC51ACF19F900747DD7 /* CancellationTests.m */; };
7C60AEC81ACF1A0100747DD7 /* BFCancellationToken.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C60AEBD1ACF08F300747DD7 /* BFCancellationToken.h */; settings = {ATTRIBUTES = (Public, ); }; };
7C60AEC91ACF1A0900747DD7 /* BFCancellationToken.m in Sources */ = {isa = PBXBuildFile; fileRef = 7C60AEBE1ACF08F300747DD7 /* BFCancellationToken.m */; };
7C60AECA1ACF1A0B00747DD7 /* BFCancellationTokenSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C60AEC11ACF093D00747DD7 /* BFCancellationTokenSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
7C60AECB1ACF1A0D00747DD7 /* BFCancellationTokenSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 7C60AEC21ACF093D00747DD7 /* BFCancellationTokenSource.m */; };
7CA39C921ADE715400DD78CC /* BFCancellationTokenRegistration.h in Headers */ = {isa = PBXBuildFile; fileRef = 7CA39C901ADE715400DD78CC /* BFCancellationTokenRegistration.h */; settings = {ATTRIBUTES = (Public, ); }; };
7CA39C931ADE715400DD78CC /* BFCancellationTokenRegistration.h in Headers */ = {isa = PBXBuildFile; fileRef = 7CA39C901ADE715400DD78CC /* BFCancellationTokenRegistration.h */; settings = {ATTRIBUTES = (Public, ); }; };
7CA39C941ADE715400DD78CC /* BFCancellationTokenRegistration.m in Sources */ = {isa = PBXBuildFile; fileRef = 7CA39C911ADE715400DD78CC /* BFCancellationTokenRegistration.m */; };
7CA39C951ADE715400DD78CC /* BFCancellationTokenRegistration.m in Sources */ = {isa = PBXBuildFile; fileRef = 7CA39C911ADE715400DD78CC /* BFCancellationTokenRegistration.m */; };
8103FA6819900A84000BAE3F /* BFExecutor.m in Sources */ = {isa = PBXBuildFile; fileRef = 8103FA4F19900A84000BAE3F /* BFExecutor.m */; };
8103FA6919900A84000BAE3F /* BFExecutor.m in Sources */ = {isa = PBXBuildFile; fileRef = 8103FA4F19900A84000BAE3F /* BFExecutor.m */; };
8103FA6A19900A84000BAE3F /* BFTask.m in Sources */ = {isa = PBXBuildFile; fileRef = 8103FA5119900A84000BAE3F /* BFTask.m */; };
@@ -101,6 +115,13 @@
1EC3017018CDAA8400D06D07 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
1EC3017218CDAA8400D06D07 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
1EC3019018CDABCE00D06D07 /* AppLinkTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppLinkTests.m; sourceTree = "<group>"; };
7C60AEBD1ACF08F300747DD7 /* BFCancellationToken.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BFCancellationToken.h; sourceTree = "<group>"; };
7C60AEBE1ACF08F300747DD7 /* BFCancellationToken.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BFCancellationToken.m; sourceTree = "<group>"; };
7C60AEC11ACF093D00747DD7 /* BFCancellationTokenSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BFCancellationTokenSource.h; sourceTree = "<group>"; };
7C60AEC21ACF093D00747DD7 /* BFCancellationTokenSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BFCancellationTokenSource.m; sourceTree = "<group>"; };
7C60AEC51ACF19F900747DD7 /* CancellationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CancellationTests.m; sourceTree = "<group>"; };
7CA39C901ADE715400DD78CC /* BFCancellationTokenRegistration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BFCancellationTokenRegistration.h; sourceTree = "<group>"; };
7CA39C911ADE715400DD78CC /* BFCancellationTokenRegistration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BFCancellationTokenRegistration.m; sourceTree = "<group>"; };
8103FA4E19900A84000BAE3F /* BFExecutor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BFExecutor.h; sourceTree = "<group>"; };
8103FA4F19900A84000BAE3F /* BFExecutor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BFExecutor.m; sourceTree = "<group>"; };
8103FA5019900A84000BAE3F /* BFTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BFTask.h; sourceTree = "<group>"; };
@@ -236,6 +257,12 @@
8103FA5319900A84000BAE3F /* BFTaskCompletionSource.m */,
8103FA4E19900A84000BAE3F /* BFExecutor.h */,
8103FA4F19900A84000BAE3F /* BFExecutor.m */,
7C60AEBD1ACF08F300747DD7 /* BFCancellationToken.h */,
7C60AEBE1ACF08F300747DD7 /* BFCancellationToken.m */,
7CA39C901ADE715400DD78CC /* BFCancellationTokenRegistration.h */,
7CA39C911ADE715400DD78CC /* BFCancellationTokenRegistration.m */,
7C60AEC11ACF093D00747DD7 /* BFCancellationTokenSource.h */,
7C60AEC21ACF093D00747DD7 /* BFCancellationTokenSource.m */,
);
path = Common;
sourceTree = "<group>";
@@ -274,6 +301,7 @@
1EC3019018CDABCE00D06D07 /* AppLinkTests.m */,
8EA6BF681805CF5600337041 /* BoltsTests.m */,
8E9C3D1C17DE9F6500427E62 /* TaskTests.m */,
7C60AEC51ACF19F900747DD7 /* CancellationTests.m */,
85D5138918E4E45800D19D87 /* AppLinkReturnToRefererViewTests.m */,
8E8C8ED817F23C3B00E3F1C7 /* Supporting Files */,
);
@@ -364,12 +392,15 @@
81D0EE9019AFAA5F0000AE75 /* BFAppLinkReturnToRefererView.h in Headers */,
81D0EE8719AFAA220000AE75 /* BFExecutor.h in Headers */,
81D0EE8919AFAA2B0000AE75 /* BFTaskCompletionSource.h in Headers */,
7C60AEC31ACF093D00747DD7 /* BFCancellationTokenSource.h in Headers */,
81D0EE9119AFAA6F0000AE75 /* BFAppLinkTarget.h in Headers */,
81D0EE8019AFA9E20000AE75 /* BoltsVersion.h in Headers */,
81D0EE8C19AFAA5F0000AE75 /* BFAppLink.h in Headers */,
81D0EE9219AFAA6F0000AE75 /* BFMeasurementEvent.h in Headers */,
81D0EE9319AFAA6F0000AE75 /* BFURL.h in Headers */,
7CA39C921ADE715400DD78CC /* BFCancellationTokenRegistration.h in Headers */,
81D0EE8419AFAA100000AE75 /* Bolts.h in Headers */,
7C60AEBF1ACF08F300747DD7 /* BFCancellationToken.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -377,11 +408,14 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
7CA39C931ADE715400DD78CC /* BFCancellationTokenRegistration.h in Headers */,
81D0EE8519AFAA190000AE75 /* BFTask.h in Headers */,
7C60AECA1ACF1A0B00747DD7 /* BFCancellationTokenSource.h in Headers */,
81D0EE8819AFAA240000AE75 /* BFExecutor.h in Headers */,
81D0EE8A19AFAA2C0000AE75 /* BFTaskCompletionSource.h in Headers */,
81D0EE8219AFAA060000AE75 /* BoltsVersion.h in Headers */,
81D0EE8319AFAA0E0000AE75 /* Bolts.h in Headers */,
7C60AEC81ACF1A0100747DD7 /* BFCancellationToken.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -556,6 +590,7 @@
buildActionMask = 2147483647;
files = (
1EC3019118CDABCE00D06D07 /* AppLinkTests.m in Sources */,
7C60AEC61ACF19F900747DD7 /* CancellationTests.m in Sources */,
85D5138A18E4E45800D19D87 /* AppLinkReturnToRefererViewTests.m in Sources */,
8EA6BF691805CF5600337041 /* BoltsTests.m in Sources */,
8E8C8EFB17F23E5F00E3F1C7 /* TaskTests.m in Sources */,
@@ -568,6 +603,7 @@
files = (
8E17EC271805D0A40049E862 /* BoltsTests.m in Sources */,
8E8C8F2917F241FF00E3F1C7 /* TaskTests.m in Sources */,
7C60AEC71ACF19FD00747DD7 /* CancellationTests.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -576,7 +612,9 @@
buildActionMask = 2147483647;
files = (
8103FA7819900A84000BAE3F /* BFAppLinkTarget.m in Sources */,
7CA39C941ADE715400DD78CC /* BFCancellationTokenRegistration.m in Sources */,
8103FA6C19900A84000BAE3F /* BFTaskCompletionSource.m in Sources */,
7C60AEC01ACF08F300747DD7 /* BFCancellationToken.m in Sources */,
8103FA7619900A84000BAE3F /* BFAppLinkReturnToRefererView.m in Sources */,
8103FA7419900A84000BAE3F /* BFAppLinkReturnToRefererController.m in Sources */,
8103FA7C19900A84000BAE3F /* BFWebViewAppLinkResolver.m in Sources */,
@@ -585,6 +623,7 @@
8103FA7019900A84000BAE3F /* BFAppLink.m in Sources */,
8103FA6819900A84000BAE3F /* BFExecutor.m in Sources */,
8103FA7A19900A84000BAE3F /* BFURL.m in Sources */,
7C60AEC41ACF093D00747DD7 /* BFCancellationTokenSource.m in Sources */,
8103FA7219900A84000BAE3F /* BFAppLinkNavigation.m in Sources */,
B242FABB19A567660097ECAE /* BFMeasurementEvent.m in Sources */,
);
@@ -597,7 +636,10 @@
8103FA6D19900A84000BAE3F /* BFTaskCompletionSource.m in Sources */,
8103FA6B19900A84000BAE3F /* BFTask.m in Sources */,
8103FA6F19900A84000BAE3F /* Bolts.m in Sources */,
7CA39C951ADE715400DD78CC /* BFCancellationTokenRegistration.m in Sources */,
7C60AECB1ACF1A0D00747DD7 /* BFCancellationTokenSource.m in Sources */,
8103FA6919900A84000BAE3F /* BFExecutor.m in Sources */,
7C60AEC91ACF1A0900747DD7 /* BFCancellationToken.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
BoltsTests/CancellationTests.m 0 → 100644
+ 56
- 0
  • View file @ 52fc0e22

  • Edit in single-file editor

  • Open in Web IDE

/*
* Copyright (c) 2014, 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 <XCTest/XCTest.h>
#import "Bolts.h"
@interface CancellationTests : XCTestCase
@end
@implementation CancellationTests
- (void)setUp {
[super setUp];
}
- (void)tearDown {
[super tearDown];
}
- (void)testCancellation {
BFCancellationTokenSource *cts = [BFCancellationTokenSource cancellationTokenSource];
XCTAssertFalse(cts.cancellationRequested, @"Source should not be cancelled");
XCTAssertFalse(cts.token.cancellationRequested, @"Token should not be cancelled");
[cts cancel];
XCTAssertTrue(cts.cancellationRequested, @"Source should be cancelled");
XCTAssertTrue(cts.token.cancellationRequested, @"Token should be cancelled");
}
- (void)testCancellationBlock {
__block BOOL cancelled = NO;
BFCancellationTokenSource *cts = [BFCancellationTokenSource cancellationTokenSource];
[cts.token registerCancellationObserverWithBlock:^{
cancelled = YES;
}];
XCTAssertFalse(cts.cancellationRequested, @"Source should not be cancelled");
XCTAssertFalse(cts.token.cancellationRequested, @"Token should not be cancelled");
[cts cancel];
XCTAssertTrue(cancelled, @"Source should be cancelled");
}
@end
BoltsTests/TaskTests.m
+ 82
- 0
  • View file @ 52fc0e22

  • Edit in single-file editor

  • Open in Web IDE


@@ -32,6 +32,37 @@
}] waitUntilFinished];
}
- (void)testBasicOnSuccessWithToken {
BFCancellationTokenSource *cts = [BFCancellationTokenSource cancellationTokenSource];
BFTask *task = [BFTask taskWithDelay:100];
task = [task continueWithExecutor:[BFExecutor immediateExecutor]
successBlock:^id(BFTask *task) {
XCTFail(@"Success block should not be triggered");
return nil;
} cancellationToken:cts.token];
[cts cancel];
[task waitUntilFinished];
XCTAssertTrue(task.isCancelled);
}
- (void)testBasicOnSuccessWithCancelledToken {
BFCancellationTokenSource *cts = [BFCancellationTokenSource cancellationTokenSource];
BFTask *task = [BFTask taskWithResult:nil];
[cts cancel];
task = [task continueWithExecutor:[BFExecutor immediateExecutor]
successBlock:^id(BFTask *task) {
XCTFail(@"Success block should not be triggered");
return nil;
} cancellationToken:cts.token];
XCTAssertTrue(task.isCancelled);
}
- (void)testBasicContinueWithError {
NSError *originalError = [NSError errorWithDomain:@"Bolts" code:22 userInfo:nil];
[[[BFTask taskWithError:originalError] continueWithBlock:^id(BFTask *task) {
@@ -53,6 +84,37 @@
}] waitUntilFinished];
}
- (void)testBasicContinueWithToken {
BFCancellationTokenSource *cts = [BFCancellationTokenSource cancellationTokenSource];
BFTask *task = [BFTask taskWithDelay:100];
task = [task continueWithExecutor:[BFExecutor immediateExecutor]
block:^id(BFTask *task) {
XCTFail(@"Continuation block should not be triggered");
return nil;
} cancellationToken:cts.token];
[cts cancel];
[task waitUntilFinished];
XCTAssertTrue(task.isCancelled);
}
- (void)testBasicContinueWithCancelledToken {
BFCancellationTokenSource *cts = [BFCancellationTokenSource cancellationTokenSource];
BFTask *task = [BFTask taskWithResult:nil];
[cts cancel];
task = [task continueWithExecutor:[BFExecutor immediateExecutor]
block:^id(BFTask *task) {
XCTFail(@"Continuation block should not be triggered");
return nil;
} cancellationToken:cts.token];
XCTAssertTrue(task.isCancelled);
}
- (void)testFinishLaterWithSuccess {
BFTaskCompletionSource *tcs = [BFTaskCompletionSource taskCompletionSource];
BFTask *task = [tcs.task continueWithBlock:^id(BFTask *task) {
@@ -550,6 +612,26 @@
XCTAssertEqualObjects(@"foo", task.result);
}
- (void)testDelayWithToken {
BFCancellationTokenSource *cts = [BFCancellationTokenSource cancellationTokenSource];
BFTask *task = [BFTask taskWithDelay:100 cancellationToken:cts.token];
[cts cancel];
[task waitUntilFinished];
XCTAssertTrue(task.cancelled, @"Task should be cancelled immediately");
}
- (void)testDelayWithCancelledToken {
BFCancellationTokenSource *cts = [BFCancellationTokenSource cancellationTokenSource];
[cts cancel];
BFTask *task = [BFTask taskWithDelay:100 cancellationToken:cts.token];
XCTAssertTrue(task.cancelled, @"Task should be cancelled immediately");
}
- (void)testTaskFromExecutor {
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0L);
BFExecutor *queueExecutor = [BFExecutor executorWithDispatchQueue:queue];
0 Assignees
None
Assign to
0 Reviewers
None
Request review from
Labels
1
CLA Signed
1
CLA Signed
    Assign labels
  • Manage project labels

Milestone
No milestone
None
None
Time tracking
No estimate or time spent
Lock merge request
Unlocked
2
2 participants
Administrator
Nikita Lutsenko
Reference: BoltsFramework/Bolts-ObjC!89
Source branch: github/fork/josephearl/feature/task-cancellation

Menu

Explore Projects Groups Snippets