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

Unified Diff: ios/chrome/app/deferred_initialization_runner.mm

Issue 2217083002: Add sequential dispatching for InitializationRunner (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Comments Created 4 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: 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..3fa081241dc8aab5abd3f292153b0df9f795df29 100644
--- a/ios/chrome/app/deferred_initialization_runner.mm
+++ b/ios/chrome/app/deferred_initialization_runner.mm
@@ -6,7 +6,9 @@
#include <stdint.h>
+#import "base/ios/weak_nsobject.h"
#include "base/logging.h"
+#include "base/mac/scoped_block.h"
#include "base/mac/scoped_nsobject.h"
// An object encapsulating the deferred execution of a block of initialization
@@ -15,50 +17,56 @@
// A string to reference the initialization block.
base::scoped_nsobject<NSString> _name;
// A block of code to execute.
- base::scoped_nsprotocol<ProceduralBlock> _runBlock;
+ base::mac::ScopedBlock<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) {
_name.reset([name copy]);
- _runBlock.reset([block copy]);
+ _runBlock.reset(block, base::scoped_policy::RETAIN);
}
return self;
}
-- (void)dispatch:(NSTimeInterval)delaySeconds {
- int64_t nanoseconds = delaySeconds * NSEC_PER_SEC;
+- (void)run {
DCHECK([NSThread isMainThread]);
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, nanoseconds),
- dispatch_get_main_queue(), ^() {
- [self runSynchronously];
- });
-}
-
-- (void)runSynchronously {
ProceduralBlock deferredBlock = _runBlock.get();
if (!deferredBlock)
return;
@@ -72,23 +80,89 @@
@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 |delay| it will automatically
+// schedule the next block after |delayBetweenBlocks|.
+- (void)scheduleNextBlockWithDelay:(NSTimeInterval)delay;
+
+// Time interval between two blocks. Default value is 200ms.
+@property(nonatomic) NSTimeInterval delayBetweenBlocks;
+
+// Time interval before running the first block. Default value is 3s.
+@property(nonatomic) NSTimeInterval delayBeforeFirstBlock;
+
+@end
+
+@implementation DeferredInitializationRunner
+
+@synthesize delayBetweenBlocks = _delayBetweenBlocks;
+@synthesize delayBeforeFirstBlock = _delayBeforeFirstBlock;
+
+ (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;
+ _delayBeforeFirstBlock = 3.0;
+ }
return self;
}
+- (void)enqueueBlockNamed:(NSString*)name block:(ProceduralBlock)block {
+ DCHECK(name);
+ DCHECK([NSThread isMainThread]);
+ [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 scheduleNextBlockWithDelay:self.delayBeforeFirstBlock];
+ }
+}
+
+- (void)scheduleNextBlockWithDelay:(NSTimeInterval)delay {
+ DCHECK([NSThread isMainThread]);
+ _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)(delay * NSEC_PER_SEC)),
+ dispatch_get_main_queue(), ^{
+ [nextBlock run];
+ [weakSelf scheduleNextBlockWithDelay:[weakSelf delayBetweenBlocks]];
+ });
+
+ _isBlockScheduled = YES;
+ [_blocksNameQueue removeObjectAtIndex:0];
+}
+
- (void)runBlockNamed:(NSString*)name
after:(NSTimeInterval)delaySeconds
block:(ProceduralBlock)block {
@@ -106,11 +180,14 @@
}
- (void)runBlockIfNecessary:(NSString*)name {
- [[_runBlocks objectForKey:name] runSynchronously];
+ DCHECK([NSThread isMainThread]);
+ [[_runBlocks objectForKey:name] run];
}
- (void)cancelBlockNamed:(NSString*)name {
+ DCHECK([NSThread isMainThread]);
DCHECK(name);
+ [_blocksNameQueue removeObject:name];
[[_runBlocks objectForKey:name] cancel];
[_runBlocks removeObjectForKey:name];
}
« no previous file with comments | « ios/chrome/app/deferred_initialization_runner.h ('k') | ios/chrome/app/deferred_initialization_runner_unittest.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698