Skip to content

Instantly share code, notes, and snippets.

@dbachrach
Created July 23, 2014 16:15
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dbachrach/296586173a303c17c0ad to your computer and use it in GitHub Desktop.
Save dbachrach/296586173a303c17c0ad to your computer and use it in GitHub Desktop.
Simple CancelToken for PromiseKit
#import <Foundation/Foundation.h>
typedef void (^MHCancelHandler)(void);
@interface MHCancelToken : NSObject
- (void)onCancel:(MHCancelHandler)cancelHandler;
- (void)cancel;
@end
#import "MHCancelToken.h"
typedef NS_ENUM(NSInteger, MHCancelTokenState)
{
MHCancelTokenStateReady,
MHCancelTokenStateCancelled
};
@interface MHCancelToken ()
@property (strong, nonatomic) NSMutableArray* cancelHandlers;
@property (nonatomic) MHCancelTokenState state;
@end
@implementation MHCancelToken
- (instancetype)init
{
if (self = [super init]) {
_cancelHandlers = [NSMutableArray array];
_state = MHCancelTokenStateReady;
}
return self;
}
- (void)onCancel:(MHCancelHandler)cancelHandler
{
@synchronized(self) {
if (self.state == MHCancelTokenStateReady) {
[self.cancelHandlers addObject:cancelHandler];
return;
}
}
cancelHandler();
}
- (void)cancel
{
NSArray* cancelHandlersSnapshot;
@synchronized(self) {
if (self.state != MHCancelTokenStateReady) {
return;
}
self.state = MHCancelTokenStateCancelled;
cancelHandlersSnapshot = self.cancelHandlers;
self.cancelHandlers = nil;
}
for (MHCancelHandler handler in cancelHandlersSnapshot) {
handler();
}
}
@end
@paulfreeman
Copy link

I'm trying to get my head around this as I think I need it to make use of PromiseKit in my application. Why does onCancel call cancelHandler() in the last line? You can call cancel on the cancellation token from where the client/call site needs it which seems right, but what if I only want to cancel it from the call site and not when setting up the handler?

Would I be right to think that this is just to ensure that if this is to ensure cancellation occurs in an edge case connected to when the enclosing block is initially constructed?

eg: Your code example on the thread on cancelling in PromiseKit. I think its useful to have this example client along with your valuable gist on this matter.

- (PMKPromise*)GET:(NSString*)URLString
    parameters:(NSDictionary*)parameters
    cancelToken:(MHCancelToken*)cancelToken
{
    return [PMKPromise new:^(PMKPromiseFulfiller fulfiller, PMKPromiseRejecter rejecter) {
          NSURLSessionDataTask* task = [self.sessionManager GET:URLString
                                                     parameters:parameters
                                                        success:^(NSURLSessionDataTask* resultTask, id responseObject) {
                                                            fulfiller(responseObject);
                                                        }
                                                        failure:^(NSURLSessionDataTask* resultTask, NSError* error) {
                                                            rejecter(error);
                                                        }];

          [cancelToken onCancel:^{
              if (task.state != NSURLSessionTaskStateCompleted) {
                  [task cancel];
              }
          }];
    }];
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment