There is no need to use the main queue just for perform selector.
We were using the main queue to queue up a perform selector and then the code
[self sendStoredCrashReports] was immediately doing a dispatch_async.
This unnecessary thread switching is not needed.
We simplify the above logic and use dispatch_after to queue the block on
the
internal queue after a delay
Note that main queue is typically more loaded and it is better for
non-UI code
to not use the main queue. This may also help improve crash log upload.
This change also switches from @synchronized to dispatch_once as that is
faster
Reference:
http://googlemac.blogspot.com/2006/10/synchronized-swimming.html
BUG=
Change-Id: I81035149cbbf13a3058ca3a11e6efd23980f19ad
Reviewed-on: https://chromium-review.googlesource.com/441364
Reviewed-by: Joshua Peraza <jperaza@chromium.org>
diff --git a/src/client/ios/BreakpadController.mm b/src/client/ios/BreakpadController.mm
index dd71cff..22f397a 100644
--- a/src/client/ios/BreakpadController.mm
+++ b/src/client/ios/BreakpadController.mm
@@ -93,11 +93,12 @@
@implementation BreakpadController
+ (BreakpadController*)sharedInstance {
- @synchronized(self) {
- static BreakpadController* sharedInstance_ =
- [[BreakpadController alloc] initSingleton];
- return sharedInstance_;
- }
+ static dispatch_once_t onceToken;
+ static BreakpadController* sharedInstance ;
+ dispatch_once(&onceToken, ^{
+ sharedInstance = [[BreakpadController alloc] initSingleton];
+ });
+ return sharedInstance;
}
- (id)init {
@@ -179,10 +180,9 @@
enableUploads_ = YES;
[self sendStoredCrashReports];
} else {
+ // disable the enableUpload_ flag.
+ // sendDelay checks this flag and disables the upload of logs by sendStoredCrashReports
enableUploads_ = NO;
- [NSObject cancelPreviousPerformRequestsWithTarget:self
- selector:@selector(sendStoredCrashReports)
- object:nil];
}
});
}
@@ -317,38 +317,35 @@
[userDefaults synchronize];
}
+// This method must be called from the breakpad queue.
- (void)sendStoredCrashReports {
- dispatch_async(queue_, ^{
- if (BreakpadGetCrashReportCount(breakpadRef_) == 0)
- return;
+ if (BreakpadGetCrashReportCount(breakpadRef_) == 0)
+ return;
- int timeToWait = [self sendDelay];
+ int timeToWait = [self sendDelay];
- // Unable to ever send report.
- if (timeToWait == -1)
- return;
+ // Unable to ever send report.
+ if (timeToWait == -1)
+ return;
- // A report can be sent now.
- if (timeToWait == 0) {
- [self reportWillBeSent];
- BreakpadUploadNextReportWithParameters(breakpadRef_,
- uploadTimeParameters_);
+ // A report can be sent now.
+ if (timeToWait == 0) {
+ [self reportWillBeSent];
+ BreakpadUploadNextReportWithParameters(breakpadRef_,
+ uploadTimeParameters_);
- // If more reports must be sent, make sure this method is called again.
- if (BreakpadGetCrashReportCount(breakpadRef_) > 0)
- timeToWait = uploadIntervalInSeconds_;
- }
+ // If more reports must be sent, make sure this method is called again.
+ if (BreakpadGetCrashReportCount(breakpadRef_) > 0)
+ timeToWait = uploadIntervalInSeconds_;
+ }
- // A report must be sent later.
- if (timeToWait > 0) {
- // performSelector: doesn't work on queue_
- dispatch_async(dispatch_get_main_queue(), ^{
- [self performSelector:@selector(sendStoredCrashReports)
- withObject:nil
- afterDelay:timeToWait];
- });
- }
- });
+ // A report must be sent later.
+ if (timeToWait > 0) {
+ dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(timeToWait * NSEC_PER_SEC));
+ dispatch_after(delay, queue_, ^{
+ [self sendStoredCrashReports];
+ });
+ }
}
@end