mirror of
https://github.com/oxen-io/session-ios.git
synced 2023-12-13 21:30:14 +01:00
Improve background task logic.
This commit is contained in:
parent
f9ce34f553
commit
c3b6de4f83
|
@ -10,6 +10,17 @@ typedef NS_ENUM(NSUInteger, BackgroundTaskState) {
|
|||
|
||||
typedef void (^BackgroundTaskCompletionBlock)(BackgroundTaskState backgroundTaskState);
|
||||
|
||||
// This class makes it easier and safer to use background tasks.
|
||||
//
|
||||
// * Uses RAII (Resource Acquisition Is Initialization) pattern.
|
||||
// * Ensures completion block is called exactly once and on main thread,
|
||||
// to facilitate handling "background task timed out" case, for example.
|
||||
// * Ensures we properly handle the "background task could not be created"
|
||||
// case.
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// * Use factory method to start a background task.
|
||||
@interface OWSBackgroundTask : NSObject
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#import "OWSBackgroundTask.h"
|
||||
#import "AppContext.h"
|
||||
#import "Threading.h"
|
||||
|
||||
@interface OWSBackgroundTask ()
|
||||
|
||||
|
@ -12,6 +13,7 @@
|
|||
// This property should only be accessed while synchronized on this instance.
|
||||
@property (nonatomic) UIBackgroundTaskIdentifier backgroundTaskId;
|
||||
|
||||
// This property should only be accessed while synchronized on this instance.
|
||||
@property (nonatomic, nullable) BackgroundTaskCompletionBlock completionBlock;
|
||||
|
||||
@end
|
||||
|
@ -74,12 +76,14 @@
|
|||
|
||||
- (void)startBackgroundTask
|
||||
{
|
||||
__weak typeof(self) weakSelf = self;
|
||||
// beginBackgroundTaskWithExpirationHandler must be called on the main thread.
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
DispatchMainThreadSafe(^{
|
||||
__weak typeof(self) weakSelf = self;
|
||||
self.backgroundTaskId = [CurrentAppContext() beginBackgroundTaskWithExpirationHandler:^{
|
||||
OWSAssert([NSThread isMainThread]);
|
||||
__strong typeof(self) strongSelf = weakSelf;
|
||||
// Note the usage of OWSCAssert() to avoid capturing a reference to self.
|
||||
OWSCAssert([NSThread isMainThread]);
|
||||
|
||||
OWSBackgroundTask *strongSelf = weakSelf;
|
||||
if (!strongSelf) {
|
||||
return;
|
||||
}
|
||||
|
@ -88,7 +92,7 @@
|
|||
if (strongSelf.backgroundTaskId == UIBackgroundTaskInvalid) {
|
||||
return;
|
||||
}
|
||||
DDLogInfo(@"%@ %@ background task expired", strongSelf.logTag, strongSelf.label);
|
||||
DDLogInfo(@"%@ %@ background task expired.", strongSelf.logTag, strongSelf.label);
|
||||
strongSelf.backgroundTaskId = UIBackgroundTaskInvalid;
|
||||
|
||||
if (strongSelf.completionBlock) {
|
||||
|
@ -100,6 +104,11 @@
|
|||
|
||||
// If a background task could not be begun, call the completion block.
|
||||
if (self.backgroundTaskId == UIBackgroundTaskInvalid) {
|
||||
|
||||
DDLogInfo(@"%@ %@ background task could not be started.", self.logTag, self.label);
|
||||
|
||||
// Make a local copy of completionBlock to ensure that it is called
|
||||
// exactly once.
|
||||
BackgroundTaskCompletionBlock _Nullable completionBlock;
|
||||
@synchronized(self)
|
||||
{
|
||||
|
@ -107,7 +116,7 @@
|
|||
self.completionBlock = nil;
|
||||
}
|
||||
if (completionBlock) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
DispatchMainThreadSafe(^{
|
||||
completionBlock(BackgroundTaskState_CouldNotStart);
|
||||
});
|
||||
}
|
||||
|
@ -119,22 +128,24 @@
|
|||
{
|
||||
// Make a local copy of this state, since this method is called by `dealloc`.
|
||||
UIBackgroundTaskIdentifier backgroundTaskId;
|
||||
BackgroundTaskCompletionBlock _Nullable completionBlock;
|
||||
NSString *logTag = self.logTag;
|
||||
NSString *label = self.label;
|
||||
BackgroundTaskCompletionBlock _Nullable completionBlock = self.completionBlock;
|
||||
|
||||
@synchronized(self)
|
||||
{
|
||||
backgroundTaskId = self.backgroundTaskId;
|
||||
completionBlock = self.completionBlock;
|
||||
}
|
||||
|
||||
if (backgroundTaskId == UIBackgroundTaskInvalid) {
|
||||
OWSAssert(!completionBlock);
|
||||
return;
|
||||
}
|
||||
|
||||
// endBackgroundTask must be called on the main thread.
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
DDLogInfo(@"%@ %@ background task completed", logTag, label);
|
||||
DispatchMainThreadSafe(^{
|
||||
DDLogVerbose(@"%@ %@ background task completed.", logTag, label);
|
||||
[CurrentAppContext() endBackgroundTask:backgroundTaskId];
|
||||
|
||||
if (completionBlock) {
|
||||
|
|
Loading…
Reference in a new issue