1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #import "ios/chrome/app/deferred_initialization_runner.h"
7 #include "base/logging.h"
8 #include "base/mac/scoped_nsobject.h"
10 // An object encapsulating the deferred execution of a block of initialization
12 @interface DeferredInitializationBlock : NSObject {
13 // A string to reference the initialization block.
14 base::scoped_nsobject<NSString> _name;
15 // A block of code to execute.
16 base::scoped_nsprotocol<ProceduralBlock> _runBlock;
19 // Designated initializer.
20 - (id)initWithName:(NSString*)name block:(ProceduralBlock)block;
22 // Dispatches the deferred execution the block after |delaySeconds|.
23 - (void)dispatch:(NSTimeInterval)delaySeconds;
25 // Executes the deferred block now.
26 - (void)runSynchronously;
28 // Cancels the block's execution.
32 @implementation DeferredInitializationBlock
34 // Overrides default designated initializer.
40 - (id)initWithName:(NSString*)name block:(ProceduralBlock)block {
44 _name.reset([name copy]);
45 _runBlock.reset([block copy]);
50 - (void)dispatch:(NSTimeInterval)delaySeconds {
51 int64_t nanoseconds = delaySeconds * NSEC_PER_SEC;
52 DCHECK([NSThread isMainThread]);
53 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, nanoseconds),
54 dispatch_get_main_queue(), ^() {
55 [self runSynchronously];
59 - (void)runSynchronously {
60 ProceduralBlock deferredBlock = _runBlock.get();
64 [[DeferredInitializationRunner sharedInstance] cancelBlockNamed:_name];
73 @implementation DeferredInitializationRunner {
74 base::scoped_nsobject<NSMutableDictionary> _runBlocks;
77 + (DeferredInitializationRunner*)sharedInstance {
78 static DeferredInitializationRunner* instance =
79 [[DeferredInitializationRunner alloc] init];
86 _runBlocks.reset([[NSMutableDictionary dictionary] retain]);
90 - (void)runBlockNamed:(NSString*)name
91 after:(NSTimeInterval)delaySeconds
92 block:(ProceduralBlock)block {
94 // Safety check in case this function is called with a nanosecond or
95 // microsecond parameter by mistake.
96 DCHECK(delaySeconds < 3600.0);
97 // Cancels the previously scheduled block, if there is one, so this
98 // |name| block will not be run more than once.
99 [[_runBlocks objectForKey:name] cancel];
100 base::scoped_nsobject<DeferredInitializationBlock> deferredBlock(
101 [[DeferredInitializationBlock alloc] initWithName:name block:block]);
102 [_runBlocks setObject:deferredBlock forKey:name];
103 [deferredBlock dispatch:delaySeconds];
106 - (void)runBlockIfNecessary:(NSString*)name {
107 [[_runBlocks objectForKey:name] runSynchronously];
110 - (void)cancelBlockNamed:(NSString*)name {
112 [[_runBlocks objectForKey:name] cancel];
113 [_runBlocks removeObjectForKey:name];
116 - (NSUInteger)numberOfBlocksRemaining {
117 return [_runBlocks count];