Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1160)

Unified Diff: webrtc/sdk/objc/Framework/Classes/Common/RTCUIApplicationStatusObserver.m

Issue 3009383002: Enhance RTCUIApplicationStatusObserver thread safety. (Closed)
Patch Set: Rebase Created 3 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: webrtc/sdk/objc/Framework/Classes/Common/RTCUIApplicationStatusObserver.m
diff --git a/webrtc/sdk/objc/Framework/Classes/Common/RTCUIApplicationStatusObserver.m b/webrtc/sdk/objc/Framework/Classes/Common/RTCUIApplicationStatusObserver.m
index 1d2aab48e852945fe25bd9d08a66ebb2fde9a0ac..7134773610b857304ca767662672937df4249127 100644
--- a/webrtc/sdk/objc/Framework/Classes/Common/RTCUIApplicationStatusObserver.m
+++ b/webrtc/sdk/objc/Framework/Classes/Common/RTCUIApplicationStatusObserver.m
@@ -26,6 +26,7 @@
@implementation RTCUIApplicationStatusObserver {
BOOL _initialized;
dispatch_block_t _initializeBlock;
+ dispatch_semaphore_t _waitForInitializeSemaphore;
UIApplicationState _state;
id<NSObject> _activeObserver;
@@ -45,6 +46,12 @@
return sharedInstance;
}
+// Method to make sure observers are added and the initialization block is
+// scheduled to run on the main queue.
++ (void)prepareForUse {
tkchin_webrtc 2017/09/13 18:32:02 This class feels more complex than it needs to be.
andersc 2017/09/14 08:08:45 I agree, and I mentioned a solution similar to tha
+ __unused RTCUIApplicationStatusObserver *observer = [self sharedInstance];
+}
+
- (id)init {
if (self = [super init]) {
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
@@ -65,6 +72,7 @@
[UIApplication sharedApplication].applicationState;
}];
+ _waitForInitializeSemaphore = dispatch_semaphore_create(1);
_initialized = NO;
_initializeBlock = dispatch_block_create(DISPATCH_BLOCK_INHERIT_QOS_CLASS, ^{
weakSelf.state = [UIApplication sharedApplication].applicationState;
@@ -84,10 +92,19 @@
}
- (BOOL)isApplicationActive {
+ // NOTE: The function `dispatch_block_wait` can only legally be called once.
+ // Because of this, if several threads call the `isApplicationActive` method before
+ // the `_initializeBlock` has been executed, instead of multiple threads calling
+ // `dispatch_block_wait`, the other threads need to wait for the first waiting thread
+ // instead.
if (!_initialized) {
- long ret = dispatch_block_wait(_initializeBlock,
- dispatch_time(DISPATCH_TIME_NOW, 10.0 * NSEC_PER_SEC));
- RTC_DCHECK_EQ(ret, 0);
+ dispatch_semaphore_wait(_waitForInitializeSemaphore, DISPATCH_TIME_FOREVER);
+ if (!_initialized) {
+ long ret = dispatch_block_wait(_initializeBlock,
+ dispatch_time(DISPATCH_TIME_NOW, 10.0 * NSEC_PER_SEC));
tkchin_webrtc 2017/09/13 18:32:02 What's the benefit of setting a short timeout here
andersc 2017/09/14 08:08:46 10 seconds was picked to be a long timeout. A test
+ RTC_DCHECK_EQ(ret, 0);
+ }
+ dispatch_semaphore_signal(_waitForInitializeSemaphore);
}
return _state == UIApplicationStateActive;
}

Powered by Google App Engine
This is Rietveld 408576698