Index: ios/chrome/app/deferred_initialization_runner.mm |
diff --git a/ios/chrome/app/deferred_initialization_runner.mm b/ios/chrome/app/deferred_initialization_runner.mm |
index 4f537ff20964701b433a873ef8775853e21d1676..37e9d8c9c2ce1f6b19405a3d46948927b628006a 100644 |
--- a/ios/chrome/app/deferred_initialization_runner.mm |
+++ b/ios/chrome/app/deferred_initialization_runner.mm |
@@ -18,28 +18,42 @@ |
base::scoped_nsprotocol<ProceduralBlock> _runBlock; |
} |
+- (instancetype)init NS_UNAVAILABLE; |
+ |
// Designated initializer. |
-- (id)initWithName:(NSString*)name block:(ProceduralBlock)block; |
+- (instancetype)initWithName:(NSString*)name |
+ block:(ProceduralBlock)block NS_DESIGNATED_INITIALIZER; |
// Dispatches the deferred execution the block after |delaySeconds|. |
+// Deprecated. |
- (void)dispatch:(NSTimeInterval)delaySeconds; |
// Executes the deferred block now. |
-- (void)runSynchronously; |
+- (void)run; |
// Cancels the block's execution. |
- (void)cancel; |
+ |
@end |
@implementation DeferredInitializationBlock |
// Overrides default designated initializer. |
-- (id)init { |
+- (instancetype)init { |
NOTREACHED(); |
return nil; |
} |
-- (id)initWithName:(NSString*)name block:(ProceduralBlock)block { |
+- (void)dispatch:(NSTimeInterval)delaySeconds { |
+ int64_t nanoseconds = delaySeconds * NSEC_PER_SEC; |
+ DCHECK([NSThread isMainThread]); |
+ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, nanoseconds), |
+ dispatch_get_main_queue(), ^() { |
+ [self run]; |
+ }); |
+} |
+ |
+- (instancetype)initWithName:(NSString*)name block:(ProceduralBlock)block { |
DCHECK(block); |
self = [super init]; |
if (self) { |
@@ -49,16 +63,7 @@ |
return self; |
} |
-- (void)dispatch:(NSTimeInterval)delaySeconds { |
- int64_t nanoseconds = delaySeconds * NSEC_PER_SEC; |
- DCHECK([NSThread isMainThread]); |
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, nanoseconds), |
- dispatch_get_main_queue(), ^() { |
- [self runSynchronously]; |
- }); |
-} |
- |
-- (void)runSynchronously { |
+- (void)run { |
ProceduralBlock deferredBlock = _runBlock.get(); |
if (!deferredBlock) |
return; |
@@ -72,23 +77,77 @@ |
@end |
-@implementation DeferredInitializationRunner { |
+@interface DeferredInitializationRunner () { |
+ base::scoped_nsobject<NSMutableArray> _blocksNameQueue; |
base::scoped_nsobject<NSMutableDictionary> _runBlocks; |
+ BOOL isBlockScheduled; |
rohitrao (ping after 24h)
2016/08/08 14:07:23
Should this be _isBlockScheduled?
gambard
2016/08/08 15:02:10
Done.
|
} |
+// Schedule the next block to be run after |kDelayBetweenBlock|. |
+- (void)scheduleNextBlock; |
+ |
+@end |
+ |
+@implementation DeferredInitializationRunner |
+ |
+@synthesize delayBetweenBlocks = _delayBetweenBlocks; |
+ |
+ (DeferredInitializationRunner*)sharedInstance { |
- static DeferredInitializationRunner* instance = |
- [[DeferredInitializationRunner alloc] init]; |
+ static dispatch_once_t once = 0; |
+ static DeferredInitializationRunner* instance = nil; |
+ dispatch_once(&once, ^{ |
+ instance = [[DeferredInitializationRunner alloc] init]; |
+ }); |
return instance; |
} |
- (id)init { |
self = [super init]; |
- if (self) |
+ if (self) { |
+ _blocksNameQueue.reset([[NSMutableArray array] retain]); |
_runBlocks.reset([[NSMutableDictionary dictionary] retain]); |
+ isBlockScheduled = NO; |
+ _delayBetweenBlocks = 0.2; |
+ } |
return self; |
} |
+- (void)enqueueBlockNamed:(NSString*)name block:(ProceduralBlock)block { |
+ DCHECK(name); |
+ [self cancelBlockNamed:name]; |
+ [_blocksNameQueue addObject:name]; |
+ |
+ base::scoped_nsobject<DeferredInitializationBlock> deferredBlock( |
+ [[DeferredInitializationBlock alloc] initWithName:name block:block]); |
+ [_runBlocks setObject:deferredBlock forKey:name]; |
+ |
+ if (!isBlockScheduled) { |
+ [self scheduleNextBlock]; |
+ } |
+} |
+ |
+- (void)scheduleNextBlock { |
+ isBlockScheduled = NO; |
+ if ([_blocksNameQueue count] > 0) { |
+ NSString* nextBlockName = [_blocksNameQueue firstObject]; |
+ |
+ DeferredInitializationBlock* nextBlock = |
+ [_runBlocks objectForKey:nextBlockName]; |
+ DCHECK(nextBlock); |
+ |
+ dispatch_after( |
+ dispatch_time(DISPATCH_TIME_NOW, |
+ (int64_t)(self.delayBetweenBlocks * NSEC_PER_SEC)), |
+ dispatch_get_main_queue(), ^{ |
+ [nextBlock run]; |
+ [self scheduleNextBlock]; |
rohitrao (ping after 24h)
2016/08/08 14:07:23
Is there any chance that retaining |self| could ca
gambard
2016/08/08 15:02:10
As it was a singleton I thought it would be ok to
|
+ }); |
+ |
+ isBlockScheduled = YES; |
+ [_blocksNameQueue removeObjectAtIndex:0]; |
+ } |
+} |
+ |
- (void)runBlockNamed:(NSString*)name |
after:(NSTimeInterval)delaySeconds |
block:(ProceduralBlock)block { |
@@ -106,11 +165,12 @@ |
} |
- (void)runBlockIfNecessary:(NSString*)name { |
- [[_runBlocks objectForKey:name] runSynchronously]; |
+ [[_runBlocks objectForKey:name] run]; |
} |
- (void)cancelBlockNamed:(NSString*)name { |
DCHECK(name); |
+ [_blocksNameQueue removeObject:name]; |
[[_runBlocks objectForKey:name] cancel]; |
[_runBlocks removeObjectForKey:name]; |
} |