Created
October 22, 2013 03:30
-
-
Save Strilanc/7094786 to your computer and use it in GitHub Desktop.
The TOCCancelTokenAndSource.m file from https://github.com/Strilanc/ObjC-CollapsingFutures, stripped of details related to the implementation of whenCancelledDo:unless:. Clone collapsing futures, paste this gist over TOCCancelTokenAndSource.m, and try to get the tests passing again. (Note that the tests aren't testing for thread safety. You may …
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import "TOCCancelTokenAndSource.h" | |
#import "TOCFutureAndSource.h" | |
#import "TOCInternal.h" | |
#include <libkern/OSAtomic.h> | |
static TOCCancelToken* SharedCancelledToken = nil; | |
static TOCCancelToken* SharedImmortalToken = nil; | |
@implementation TOCCancelToken { | |
@private NSMutableArray* _cancelHandlers; | |
@private enum TOCCancelTokenState _state; | |
} | |
+(void) initialize { | |
SharedCancelledToken = [TOCCancelToken new]; | |
SharedCancelledToken->_state = TOCCancelTokenState_Cancelled; | |
SharedImmortalToken = [TOCCancelToken new]; | |
assert(SharedImmortalToken->_state == TOCCancelTokenState_Immortal); // default state should be immortal | |
} | |
+(TOCCancelToken *)cancelledToken { | |
return SharedCancelledToken; | |
} | |
+(TOCCancelToken *)immortalToken { | |
return SharedImmortalToken; | |
} | |
+(TOCCancelToken*) _ForSource_cancellableToken { | |
TOCCancelToken* token = [TOCCancelToken new]; | |
token->_cancelHandlers = [NSMutableArray array]; | |
token->_state = TOCCancelTokenState_StillCancellable; | |
return token; | |
} | |
-(bool) _ForSource_tryImmortalize { | |
@synchronized(self) { | |
if (_state != TOCCancelTokenState_StillCancellable) return false; | |
_state = TOCCancelTokenState_Immortal; | |
_cancelHandlers = nil; | |
} | |
return true; | |
} | |
-(bool) _ForSource_tryCancel { | |
NSArray* cancelHandlersSnapshot; | |
@synchronized(self) { | |
if (_state != TOCCancelTokenState_StillCancellable) return false; | |
_state = TOCCancelTokenState_Cancelled; | |
cancelHandlersSnapshot = _cancelHandlers; | |
_cancelHandlers = nil; | |
} | |
for (TOCCancelHandler handler in cancelHandlersSnapshot) { | |
handler(); | |
} | |
return true; | |
} | |
-(enum TOCCancelTokenState)state { | |
@synchronized(self) { | |
return _state; | |
} | |
} | |
-(bool)isAlreadyCancelled { | |
return self.state == TOCCancelTokenState_Cancelled; | |
} | |
-(bool)canStillBeCancelled { | |
return self.state == TOCCancelTokenState_StillCancellable; | |
} | |
-(void)whenCancelledDo:(TOCCancelHandler)cancelHandler { | |
require(cancelHandler != nil); | |
@synchronized(self) { | |
if (_state == TOCCancelTokenState_Immortal) return; | |
if (_state == TOCCancelTokenState_StillCancellable) { | |
[_cancelHandlers addObject:cancelHandler]; | |
return; | |
} | |
} | |
cancelHandler(); | |
} | |
-(void) whenCancelledDo:(TOCCancelHandler)cancelHandler | |
unless:(TOCCancelToken*)unlessCancelledToken { | |
require(cancelHandler != nil); | |
// go for it! | |
} | |
-(NSString*) description { | |
switch (self.state) { | |
case TOCCancelTokenState_Cancelled: | |
return @"Cancelled Token"; | |
case TOCCancelTokenState_Immortal: | |
return @"Uncancelled Token (Immortal)"; | |
case TOCCancelTokenState_StillCancellable: | |
return @"Uncancelled Token"; | |
default: | |
return @"Cancel token in an unrecognized state"; | |
} | |
} | |
@end | |
@implementation TOCCancelTokenSource | |
@synthesize token; | |
-(TOCCancelTokenSource*) init { | |
self = [super init]; | |
if (self) { | |
self->token = [TOCCancelToken _ForSource_cancellableToken]; | |
} | |
return self; | |
} | |
+(TOCCancelTokenSource*) cancelTokenSourceUntil:(TOCCancelToken*)untilCancelledToken { | |
TOCCancelTokenSource* source = [TOCCancelTokenSource new]; | |
[untilCancelledToken whenCancelledDo:^{ [source cancel]; } | |
unless:source.token]; | |
return source; | |
} | |
-(void) dealloc { | |
[token _ForSource_tryImmortalize]; | |
} | |
-(void) cancel { | |
[self tryCancel]; | |
} | |
-(bool)tryCancel { | |
return [token _ForSource_tryCancel]; | |
} | |
-(NSString*) description { | |
return [NSString stringWithFormat:@"Cancel Token Source: %@", token]; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment