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

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