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

151 lines
4.4 KiB
Objective-C

#import "TimeUtil.h"
#import "Util.h"
@implementation TimeUtil
+(NSTimeInterval) time {
return [[NSProcessInfo processInfo] systemUptime];
}
+(TOCFuture*) scheduleEvaluate:(Function)function
afterDelay:(NSTimeInterval)delay
onRunLoop:(NSRunLoop*)runLoop
unlessCancelled:(TOCCancelToken*)unlessCancelledToken {
require(function != NULL);
require(runLoop != nil);
require(delay >= 0);
TOCFutureSource* result = [TOCFutureSource futureSourceUntil:unlessCancelledToken];
Action evaler = ^{
[result trySetResult:function()];
};
[self scheduleHelper:evaler
withPeriod:delay
onRunLoop:runLoop
repeating:false
untilCancelled:unlessCancelledToken
andRunImmediately:NO];
return result.future;
}
+(TOCFuture*) scheduleEvaluate:(Function)function
at:(NSDate*)date
onRunLoop:(NSRunLoop*)runLoop
unlessCancelled:(TOCCancelToken*)unlessCancelledToken {
require(function != NULL);
require(runLoop != nil);
require(date != nil);
NSTimeInterval delay = [date timeIntervalSinceNow];
return [self scheduleEvaluate:function
afterDelay:MAX(0, delay)
onRunLoop:runLoop
unlessCancelled:unlessCancelledToken];
}
+(void) scheduleRun:(Action)action
afterDelay:(NSTimeInterval)delay
onRunLoop:(NSRunLoop*)runLoop
unlessCancelled:(TOCCancelToken*)unlessCancelledToken {
require(action != NULL);
require(runLoop != nil);
require(delay >= 0);
if (delay == INFINITY) return;
[self scheduleHelper:action
withPeriod:delay
onRunLoop:runLoop
repeating:false
untilCancelled:unlessCancelledToken
andRunImmediately:NO];
}
+(void) scheduleRun:(Action)action
at:(NSDate*)date
onRunLoop:(NSRunLoop*)runLoop
unlessCancelled:(TOCCancelToken*)unlessCancelledToken {
require(action != NULL);
require(runLoop != nil);
require(date != nil);
NSTimeInterval delay = [date timeIntervalSinceNow];
[self scheduleRun:action
afterDelay:MAX(0, delay)
onRunLoop:runLoop
unlessCancelled:unlessCancelledToken];
}
+(void) scheduleRun:(Action)action
periodically:(NSTimeInterval)interval
onRunLoop:(NSRunLoop*)runLoop
untilCancelled:(TOCCancelToken*)untilCancelledToken
andRunImmediately:(BOOL)shouldRunImmediately{
require(action != NULL);
require(runLoop != nil);
require(interval > 0);
[self scheduleHelper:action
withPeriod:interval
onRunLoop:runLoop
repeating:true
untilCancelled:untilCancelledToken
andRunImmediately:shouldRunImmediately];
}
+(void) scheduleHelper:(Action)callback
withPeriod:(NSTimeInterval)interval
onRunLoop:(NSRunLoop*)runLoop
repeating:(bool)repeats
untilCancelled:(TOCCancelToken*)untilCancelledToken
andRunImmediately:(BOOL)shouldRunImmediately{
require(callback != NULL);
require(runLoop != nil);
require(interval >= 0);
require(!repeats || interval > 0);
if (untilCancelledToken.isAlreadyCancelled) {
return;
}
if (!repeats && interval == 0) {
callback();
return;
}
if (shouldRunImmediately){
callback();
}
callback = [callback copy];
__block bool hasBeenCancelled = false;
__block NSObject* cancelLock = [NSObject new];
Operation* callbackUnlessCancelled = [Operation operation:^{
@synchronized(cancelLock) {
if (hasBeenCancelled) return;
callback();
}
}];
NSTimer* timer = [NSTimer timerWithTimeInterval:interval
target:callbackUnlessCancelled
selector:[callbackUnlessCancelled selectorToRun]
userInfo:nil
repeats:repeats];
[runLoop addTimer:timer forMode:NSDefaultRunLoopMode];
[untilCancelledToken whenCancelledDo:^{
@synchronized(cancelLock) {
hasBeenCancelled = true;
[timer invalidate];
}
}];
}
@end