schedule retry timer on main run loop

pull/1/head
Michael Kirk 6 years ago committed by Matthew Chen
parent a479e41628
commit 64cdaae02e

@ -1,5 +1,5 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
NS_ASSUME_NONNULL_BEGIN
@ -14,6 +14,12 @@ NS_ASSUME_NONNULL_BEGIN
userInfo:(nullable id)userInfo
repeats:(BOOL)repeats;
+ (NSTimer *)weakTimerWithTimeInterval:(NSTimeInterval)timeInterval
target:(id)target
selector:(SEL)selector
userInfo:(nullable id)userInfo
repeats:(BOOL)repeats;
@end
NS_ASSUME_NONNULL_END

@ -1,5 +1,5 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
#import "NSTimer+OWS.h"
@ -64,6 +64,24 @@ static void *kNSTimer_OWS_Proxy = &kNSTimer_OWS_Proxy;
return timer;
}
+ (NSTimer *)weakTimerWithTimeInterval:(NSTimeInterval)timeInterval
target:(id)target
selector:(SEL)selector
userInfo:(nullable id)userInfo
repeats:(BOOL)repeats
{
NSTimerProxy *proxy = [NSTimerProxy new];
proxy.target = target;
proxy.selector = selector;
NSTimer *timer = [NSTimer timerWithTimeInterval:timeInterval
target:proxy
selector:@selector(timerFired:)
userInfo:userInfo
repeats:repeats];
[timer ows_setProxy:proxy];
return timer;
}
@end
NS_ASSUME_NONNULL_END

@ -1,5 +1,5 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
#import "OWSOperation.h"
@ -131,18 +131,20 @@ NSString *const OWSOperationKeyIsFinished = @"isFinished";
- (void)runAnyQueuedRetry
{
__block NSTimer *_Nullable retryTimer;
dispatch_sync(self.retryTimerSerialQueue, ^{
retryTimer = self.retryTimer;
self.retryTimer = nil;
[retryTimer invalidate];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
__block NSTimer *_Nullable retryTimer;
dispatch_sync(self.retryTimerSerialQueue, ^{
retryTimer = self.retryTimer;
self.retryTimer = nil;
[retryTimer invalidate];
});
if (retryTimer != nil) {
[self run];
} else {
OWSLogVerbose(@"not re-running since operation is already running.");
}
});
if (retryTimer != nil) {
[self run];
} else {
OWSLogVerbose(@"not re-running since operation is already running.");
}
}
#pragma mark - Public Methods
@ -193,11 +195,22 @@ NSString *const OWSOperationKeyIsFinished = @"isFinished";
dispatch_sync(self.retryTimerSerialQueue, ^{
OWSAssertDebug(self.retryTimer == nil);
[self.retryTimer invalidate];
self.retryTimer = [NSTimer weakScheduledTimerWithTimeInterval:self.retryInterval
target:self
selector:@selector(runAnyQueuedRetry)
userInfo:nil
repeats:NO];
NSTimer *retryTimer = [NSTimer weakTimerWithTimeInterval:self.retryInterval
target:self
selector:@selector(runAnyQueuedRetry)
userInfo:nil
repeats:NO];
self.retryTimer = retryTimer;
// The `scheduledTimerWith*` methods add the timer to the current thread's RunLoop.
// Since Operations typically run on a background thread, that would mean the background
// thread's RunLoop. However, the OS can spin down background threads if there's no work
// being done, so we run the risk of the timer's RunLoop being deallocated before it's
// fired.
//
// To ensure the timer's thread sticks around, we schedule it on the main RunLoop.
[NSRunLoop.mainRunLoop addTimer:retryTimer forMode:NSDefaultRunLoopMode];
});
}

Loading…
Cancel
Save