| 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..cb333cc81b69feb5604471a67f13342e8e06f731 100644
|
| --- a/ios/chrome/app/deferred_initialization_runner.mm
|
| +++ b/ios/chrome/app/deferred_initialization_runner.mm
|
| @@ -6,6 +6,7 @@
|
|
|
| #include <stdint.h>
|
|
|
| +#import "base/ios/weak_nsobject.h"
|
| #include "base/logging.h"
|
| #include "base/mac/scoped_nsobject.h"
|
|
|
| @@ -18,28 +19,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 +64,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 +78,79 @@
|
|
|
| @end
|
|
|
| -@implementation DeferredInitializationRunner {
|
| +@interface DeferredInitializationRunner () {
|
| + base::scoped_nsobject<NSMutableArray> _blocksNameQueue;
|
| base::scoped_nsobject<NSMutableDictionary> _runBlocks;
|
| + BOOL _isBlockScheduled;
|
| }
|
|
|
| +// 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;
|
| + NSString* nextBlockName = [_blocksNameQueue firstObject];
|
| + if (!nextBlockName)
|
| + return;
|
| +
|
| + DeferredInitializationBlock* nextBlock =
|
| + [_runBlocks objectForKey:nextBlockName];
|
| + DCHECK(nextBlock);
|
| +
|
| + base::WeakNSObject<DeferredInitializationRunner> weakSelf(self);
|
| +
|
| + dispatch_after(
|
| + dispatch_time(DISPATCH_TIME_NOW,
|
| + (int64_t)(self.delayBetweenBlocks * NSEC_PER_SEC)),
|
| + dispatch_get_main_queue(), ^{
|
| + [nextBlock run];
|
| + [weakSelf scheduleNextBlock];
|
| + });
|
| +
|
| + _isBlockScheduled = YES;
|
| + [_blocksNameQueue removeObjectAtIndex:0];
|
| +}
|
| +
|
| - (void)runBlockNamed:(NSString*)name
|
| after:(NSTimeInterval)delaySeconds
|
| block:(ProceduralBlock)block {
|
| @@ -106,11 +168,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];
|
| }
|
|
|