 Chromium Code Reviews
 Chromium Code Reviews Issue 3009383002:
  Enhance RTCUIApplicationStatusObserver thread safety.  (Closed)
    
  
    Issue 3009383002:
  Enhance RTCUIApplicationStatusObserver thread safety.  (Closed) 
  | 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; | 
| } |