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

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