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

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: comment 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 |delay| it will automatically
88 // schedule the next block after |delayBetweenBlocks|.
89 - (void)scheduleNextBlockWithDelay:(NSTimeInterval)delay;
90
91 @end
92
93 @implementation DeferredInitializationRunner
94
95 @synthesize delayBetweenBlocks = _delayBetweenBlocks;
96 @synthesize delayBeforeFirstBlocks = _delayBeforeFirstBlocks;
97
79 + (DeferredInitializationRunner*)sharedInstance { 98 + (DeferredInitializationRunner*)sharedInstance {
80 static DeferredInitializationRunner* instance = 99 static dispatch_once_t once = 0;
81 [[DeferredInitializationRunner alloc] init]; 100 static DeferredInitializationRunner* instance = nil;
101 dispatch_once(&once, ^{
102 instance = [[DeferredInitializationRunner alloc] init];
103 });
82 return instance; 104 return instance;
83 } 105 }
84 106
85 - (id)init { 107 - (id)init {
86 self = [super init]; 108 self = [super init];
87 if (self) 109 if (self) {
110 _blocksNameQueue.reset([[NSMutableArray array] retain]);
88 _runBlocks.reset([[NSMutableDictionary dictionary] retain]); 111 _runBlocks.reset([[NSMutableDictionary dictionary] retain]);
112 _isBlockScheduled = NO;
113 _delayBetweenBlocks = 0.2;
114 _delayBeforeFirstBlocks = 3.0;
115 }
89 return self; 116 return self;
90 } 117 }
91 118
119 - (void)enqueueBlockNamed:(NSString*)name block:(ProceduralBlock)block {
120 DCHECK(name);
121 [self cancelBlockNamed:name];
122 [_blocksNameQueue addObject:name];
123
124 base::scoped_nsobject<DeferredInitializationBlock> deferredBlock(
125 [[DeferredInitializationBlock alloc] initWithName:name block:block]);
126 [_runBlocks setObject:deferredBlock forKey:name];
127
128 if (!_isBlockScheduled) {
129 [self scheduleNextBlockWithDelay:self.delayBeforeFirstBlocks];
130 }
131 }
132
133 - (void)scheduleNextBlockWithDelay:(NSTimeInterval)delay {
134 _isBlockScheduled = NO;
135 NSString* nextBlockName = [_blocksNameQueue firstObject];
136 if (!nextBlockName)
137 return;
138
139 DeferredInitializationBlock* nextBlock =
140 [_runBlocks objectForKey:nextBlockName];
141 DCHECK(nextBlock);
142
143 base::WeakNSObject<DeferredInitializationRunner> weakSelf(self);
144
145 dispatch_after(
146 dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)),
147 dispatch_get_main_queue(), ^{
148 [nextBlock run];
149 [weakSelf scheduleNextBlockWithDelay:[weakSelf delayBetweenBlocks]];
150 });
151
152 _isBlockScheduled = YES;
153 [_blocksNameQueue removeObjectAtIndex:0];
154 }
155
92 - (void)runBlockNamed:(NSString*)name 156 - (void)runBlockNamed:(NSString*)name
93 after:(NSTimeInterval)delaySeconds 157 after:(NSTimeInterval)delaySeconds
94 block:(ProceduralBlock)block { 158 block:(ProceduralBlock)block {
95 DCHECK(name); 159 DCHECK(name);
96 // Safety check in case this function is called with a nanosecond or 160 // Safety check in case this function is called with a nanosecond or
97 // microsecond parameter by mistake. 161 // microsecond parameter by mistake.
98 DCHECK(delaySeconds < 3600.0); 162 DCHECK(delaySeconds < 3600.0);
99 // Cancels the previously scheduled block, if there is one, so this 163 // Cancels the previously scheduled block, if there is one, so this
100 // |name| block will not be run more than once. 164 // |name| block will not be run more than once.
101 [[_runBlocks objectForKey:name] cancel]; 165 [[_runBlocks objectForKey:name] cancel];
102 base::scoped_nsobject<DeferredInitializationBlock> deferredBlock( 166 base::scoped_nsobject<DeferredInitializationBlock> deferredBlock(
103 [[DeferredInitializationBlock alloc] initWithName:name block:block]); 167 [[DeferredInitializationBlock alloc] initWithName:name block:block]);
104 [_runBlocks setObject:deferredBlock forKey:name]; 168 [_runBlocks setObject:deferredBlock forKey:name];
105 [deferredBlock dispatch:delaySeconds]; 169 [deferredBlock dispatch:delaySeconds];
106 } 170 }
107 171
108 - (void)runBlockIfNecessary:(NSString*)name { 172 - (void)runBlockIfNecessary:(NSString*)name {
109 [[_runBlocks objectForKey:name] runSynchronously]; 173 [[_runBlocks objectForKey:name] run];
110 } 174 }
111 175
112 - (void)cancelBlockNamed:(NSString*)name { 176 - (void)cancelBlockNamed:(NSString*)name {
113 DCHECK(name); 177 DCHECK(name);
178 [_blocksNameQueue removeObject:name];
114 [[_runBlocks objectForKey:name] cancel]; 179 [[_runBlocks objectForKey:name] cancel];
115 [_runBlocks removeObjectForKey:name]; 180 [_runBlocks removeObjectForKey:name];
116 } 181 }
117 182
118 - (NSUInteger)numberOfBlocksRemaining { 183 - (NSUInteger)numberOfBlocksRemaining {
119 return [_runBlocks count]; 184 return [_runBlocks count];
120 } 185 }
121 186
122 @end 187 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698