session-ios/Signal/src/util/FutureUtil.m

99 lines
2.9 KiB
Objective-C

#import "Constraints.h"
#import "FutureUtil.h"
@implementation TOCCancelToken (FutureUtil)
-(void) whenCancelledTerminate:(id<Terminable>)terminable {
require(terminable != nil);
[self whenCancelledDo:^{ [terminable terminate]; }];
}
@end
@implementation TOCFuture (FutureUtil)
+(TOCUntilOperation) operationTry:(TOCUntilOperation)operation {
require(operation != nil);
return ^(TOCCancelToken* until) {
@try {
return operation(until);
} @catch (id ex) {
return [TOCFuture futureWithFailure:ex];
}
};
}
-(TOCFuture*) thenValue:(id)value {
return [self then:^(id _) { return value; }];
}
-(TOCFuture*) finallyTry:(TOCFutureFinallyContinuation)completionContinuation {
require(completionContinuation != nil);
return [self finally:^id(TOCFuture* completed){
@try {
return completionContinuation(completed);
} @catch (id ex) {
return [TOCFuture futureWithFailure:ex];
}
}];
}
-(TOCFuture*) thenTry:(TOCFutureThenContinuation)resultContinuation {
require(resultContinuation != nil);
return [self then:^id(id result){
@try {
return resultContinuation(result);
} @catch (id ex) {
return [TOCFuture futureWithFailure:ex];
}
}];
}
-(TOCFuture*) catchTry:(TOCFutureCatchContinuation)failureContinuation {
require(failureContinuation != nil);
return [self catch:^id(id failure){
@try {
return failureContinuation(failure);
} @catch (id ex) {
return [TOCFuture futureWithFailure:ex];
}
}];
}
+(TOCFuture*) retry:(TOCUntilOperation)operation
upToNTimes:(NSUInteger)maxTryCount
withBaseTimeout:(NSTimeInterval)baseTimeout
andRetryFactor:(NSTimeInterval)timeoutRetryFactor
untilCancelled:(TOCCancelToken*)untilCancelledToken {
require(operation != nil);
require(maxTryCount >= 0);
require(baseTimeout >= 0);
require(timeoutRetryFactor >= 0);
if (maxTryCount == 0) return TOCFuture.futureWithTimeoutFailure;
TOCFuture* futureResult = [TOCFuture futureFromUntilOperation:operation
withOperationTimeout:baseTimeout
until:untilCancelledToken];
return [futureResult catchTry:^(id error) {
bool operationCancelled = untilCancelledToken.isAlreadyCancelled;
bool operationDidNotTimeout = !futureResult.hasFailedWithTimeout;
if (operationCancelled || operationDidNotTimeout) {
return [TOCFuture futureWithFailure:error];
}
return [self retry:operation
upToNTimes:maxTryCount - 1
withBaseTimeout:baseTimeout * timeoutRetryFactor
andRetryFactor:timeoutRetryFactor
untilCancelled:untilCancelledToken];
}];
}
@end