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

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

Powered by Google App Engine
This is Rietveld 408576698