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

Side by Side 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: Add test Created 4 years, 4 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 unified diff | Download patch
OLDNEW
1 // Copyright 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #import "ios/chrome/app/deferred_initialization_runner.h" 5 #import "ios/chrome/app/deferred_initialization_runner.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/mac/scoped_nsobject.h" 10 #include "base/mac/scoped_nsobject.h"
11 11
12 namespace {
13 // Interval between two blocks.
14 const NSTimeInterval kDelayBetweenBlock = 0.2;
gambard 2016/08/05 09:47:57 There are 18 current calls to this class ranging f
15 } // namespace
16
12 // An object encapsulating the deferred execution of a block of initialization 17 // An object encapsulating the deferred execution of a block of initialization
13 // code. 18 // code.
14 @interface DeferredInitializationBlock : NSObject { 19 @interface DeferredInitializationBlock : NSObject {
15 // A string to reference the initialization block. 20 // A string to reference the initialization block.
16 base::scoped_nsobject<NSString> _name; 21 base::scoped_nsobject<NSString> _name;
17 // A block of code to execute. 22 // A block of code to execute.
18 base::scoped_nsprotocol<ProceduralBlock> _runBlock; 23 base::scoped_nsprotocol<ProceduralBlock> _runBlock;
19 } 24 }
20 25
26 - (instancetype)init NS_UNAVAILABLE;
27
21 // Designated initializer. 28 // Designated initializer.
22 - (id)initWithName:(NSString*)name block:(ProceduralBlock)block; 29 - (instancetype)initWithName:(NSString*)name
30 block:(ProceduralBlock)block NS_DESIGNATED_INITIALIZER;
23 31
24 // Dispatches the deferred execution the block after |delaySeconds|. 32 // Dispatches the deferred execution the block after |delaySeconds|.
33 // Deprecated.
25 - (void)dispatch:(NSTimeInterval)delaySeconds; 34 - (void)dispatch:(NSTimeInterval)delaySeconds;
26 35
27 // Executes the deferred block now. 36 // Executes the deferred block now.
28 - (void)runSynchronously; 37 - (void)run;
29 38
30 // Cancels the block's execution. 39 // Cancels the block's execution.
31 - (void)cancel; 40 - (void)cancel;
41
32 @end 42 @end
33 43
34 @implementation DeferredInitializationBlock 44 @implementation DeferredInitializationBlock
35 45
36 // Overrides default designated initializer. 46 // Overrides default designated initializer.
37 - (id)init { 47 - (instancetype)init {
38 NOTREACHED(); 48 NOTREACHED();
39 return nil; 49 return nil;
40 } 50 }
41 51
42 - (id)initWithName:(NSString*)name block:(ProceduralBlock)block { 52 - (void)dispatch:(NSTimeInterval)delaySeconds {
53 int64_t nanoseconds = delaySeconds * NSEC_PER_SEC;
54 DCHECK([NSThread isMainThread]);
55 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, nanoseconds),
56 dispatch_get_main_queue(), ^() {
57 [self run];
58 });
59 }
60
61 - (instancetype)initWithName:(NSString*)name block:(ProceduralBlock)block {
43 DCHECK(block); 62 DCHECK(block);
44 self = [super init]; 63 self = [super init];
45 if (self) { 64 if (self) {
46 _name.reset([name copy]); 65 _name.reset([name copy]);
47 _runBlock.reset([block copy]); 66 _runBlock.reset([block copy]);
48 } 67 }
49 return self; 68 return self;
50 } 69 }
51 70
52 - (void)dispatch:(NSTimeInterval)delaySeconds { 71 - (void)run {
53 int64_t nanoseconds = delaySeconds * NSEC_PER_SEC;
54 DCHECK([NSThread isMainThread]);
55 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, nanoseconds),
56 dispatch_get_main_queue(), ^() {
57 [self runSynchronously];
58 });
59 }
60
61 - (void)runSynchronously {
62 ProceduralBlock deferredBlock = _runBlock.get(); 72 ProceduralBlock deferredBlock = _runBlock.get();
63 if (!deferredBlock) 73 if (!deferredBlock)
64 return; 74 return;
65 deferredBlock(); 75 deferredBlock();
66 [[DeferredInitializationRunner sharedInstance] cancelBlockNamed:_name]; 76 [[DeferredInitializationRunner sharedInstance] cancelBlockNamed:_name];
67 } 77 }
68 78
69 - (void)cancel { 79 - (void)cancel {
70 _runBlock.reset(); 80 _runBlock.reset();
71 } 81 }
72 82
73 @end 83 @end
74 84
75 @implementation DeferredInitializationRunner { 85 @interface DeferredInitializationRunner () {
86 base::scoped_nsobject<NSMutableArray> _blocksNameQueue;
76 base::scoped_nsobject<NSMutableDictionary> _runBlocks; 87 base::scoped_nsobject<NSMutableDictionary> _runBlocks;
88 BOOL isBlockScheduled;
77 } 89 }
78 90
91 // Schedule the next block to be run after |kDelayBetweenBlock|.
92 - (void)scheduleNextBlock;
93
94 @end
95
96 @implementation DeferredInitializationRunner
97
79 + (DeferredInitializationRunner*)sharedInstance { 98 + (DeferredInitializationRunner*)sharedInstance {
80 static DeferredInitializationRunner* instance = 99 static DeferredInitializationRunner* instance =
81 [[DeferredInitializationRunner alloc] init]; 100 [[DeferredInitializationRunner alloc] init];
82 return instance; 101 return instance;
83 } 102 }
84 103
85 - (id)init { 104 - (id)init {
86 self = [super init]; 105 self = [super init];
87 if (self) 106 if (self) {
107 _blocksNameQueue.reset([[NSMutableArray array] retain]);
88 _runBlocks.reset([[NSMutableDictionary dictionary] retain]); 108 _runBlocks.reset([[NSMutableDictionary dictionary] retain]);
109 isBlockScheduled = NO;
110 }
89 return self; 111 return self;
90 } 112 }
91 113
114 - (void)enqueueBlockNamed:(NSString*)name block:(ProceduralBlock)block {
115 DCHECK(name);
116 [self cancelBlockNamed:name];
117 [_blocksNameQueue addObject:name];
118
119 base::scoped_nsobject<DeferredInitializationBlock> deferredBlock(
120 [[DeferredInitializationBlock alloc] initWithName:name block:block]);
121 [_runBlocks setObject:deferredBlock forKey:name];
122
123 if (!isBlockScheduled) {
124 [self scheduleNextBlock];
125 }
126 }
127
128 - (void)scheduleNextBlock {
129 isBlockScheduled = NO;
130 if ([_blocksNameQueue count] > 0) {
131 NSString* nextBlockName = [_blocksNameQueue firstObject];
132
133 DeferredInitializationBlock* nextBlock =
134 [_runBlocks objectForKey:nextBlockName];
135 DCHECK(nextBlock);
136
137 dispatch_after(dispatch_time(DISPATCH_TIME_NOW,
138 (int64_t)(kDelayBetweenBlock * NSEC_PER_SEC)),
139 dispatch_get_main_queue(), ^{
140 [nextBlock run];
141 [self scheduleNextBlock];
142 });
143
144 isBlockScheduled = YES;
145 [_blocksNameQueue removeObjectAtIndex:0];
146 }
147 }
148
92 - (void)runBlockNamed:(NSString*)name 149 - (void)runBlockNamed:(NSString*)name
93 after:(NSTimeInterval)delaySeconds 150 after:(NSTimeInterval)delaySeconds
94 block:(ProceduralBlock)block { 151 block:(ProceduralBlock)block {
95 DCHECK(name); 152 DCHECK(name);
96 // Safety check in case this function is called with a nanosecond or 153 // Safety check in case this function is called with a nanosecond or
97 // microsecond parameter by mistake. 154 // microsecond parameter by mistake.
98 DCHECK(delaySeconds < 3600.0); 155 DCHECK(delaySeconds < 3600.0);
99 // Cancels the previously scheduled block, if there is one, so this 156 // Cancels the previously scheduled block, if there is one, so this
100 // |name| block will not be run more than once. 157 // |name| block will not be run more than once.
101 [[_runBlocks objectForKey:name] cancel]; 158 [[_runBlocks objectForKey:name] cancel];
102 base::scoped_nsobject<DeferredInitializationBlock> deferredBlock( 159 base::scoped_nsobject<DeferredInitializationBlock> deferredBlock(
103 [[DeferredInitializationBlock alloc] initWithName:name block:block]); 160 [[DeferredInitializationBlock alloc] initWithName:name block:block]);
104 [_runBlocks setObject:deferredBlock forKey:name]; 161 [_runBlocks setObject:deferredBlock forKey:name];
105 [deferredBlock dispatch:delaySeconds]; 162 [deferredBlock dispatch:delaySeconds];
106 } 163 }
107 164
108 - (void)runBlockIfNecessary:(NSString*)name { 165 - (void)runBlockIfNecessary:(NSString*)name {
109 [[_runBlocks objectForKey:name] runSynchronously]; 166 [[_runBlocks objectForKey:name] run];
110 } 167 }
111 168
112 - (void)cancelBlockNamed:(NSString*)name { 169 - (void)cancelBlockNamed:(NSString*)name {
113 DCHECK(name); 170 DCHECK(name);
171 [_blocksNameQueue removeObject:name];
114 [[_runBlocks objectForKey:name] cancel]; 172 [[_runBlocks objectForKey:name] cancel];
115 [_runBlocks removeObjectForKey:name]; 173 [_runBlocks removeObjectForKey:name];
116 } 174 }
117 175
118 - (NSUInteger)numberOfBlocksRemaining { 176 - (NSUInteger)numberOfBlocksRemaining {
119 return [_runBlocks count]; 177 return [_runBlocks count];
120 } 178 }
121 179
122 @end 180 @end
OLDNEW
« 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