Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 // Time interval between two blocks. Default value is 200ms. | |
|
pkl (ping after 24h if needed)
2016/09/20 04:42:56
Isn't this and the next property already declared
gambard
2016/09/22 14:00:25
Yes but I consider that all that is exposed for te
pkl (ping after 24h if needed)
2016/09/22 14:17:09
I think in other places we locally declare them in
| |
| 92 @property(nonatomic) NSTimeInterval delayBetweenBlocks; | |
| 93 | |
| 94 // Time interval before running the first block. Default value is 3s. | |
| 95 @property(nonatomic) NSTimeInterval delayBeforeFirstBlock; | |
| 96 | |
| 97 @end | |
| 98 | |
| 99 @implementation DeferredInitializationRunner | |
| 100 | |
| 101 @synthesize delayBetweenBlocks = _delayBetweenBlocks; | |
| 102 @synthesize delayBeforeFirstBlock = _delayBeforeFirstBlock; | |
| 103 | |
| 79 + (DeferredInitializationRunner*)sharedInstance { | 104 + (DeferredInitializationRunner*)sharedInstance { |
| 80 static DeferredInitializationRunner* instance = | 105 static dispatch_once_t once = 0; |
| 81 [[DeferredInitializationRunner alloc] init]; | 106 static DeferredInitializationRunner* instance = nil; |
| 107 dispatch_once(&once, ^{ | |
| 108 instance = [[DeferredInitializationRunner alloc] init]; | |
| 109 }); | |
| 82 return instance; | 110 return instance; |
| 83 } | 111 } |
| 84 | 112 |
| 85 - (id)init { | 113 - (id)init { |
| 86 self = [super init]; | 114 self = [super init]; |
| 87 if (self) | 115 if (self) { |
| 116 _blocksNameQueue.reset([[NSMutableArray array] retain]); | |
| 88 _runBlocks.reset([[NSMutableDictionary dictionary] retain]); | 117 _runBlocks.reset([[NSMutableDictionary dictionary] retain]); |
| 118 _isBlockScheduled = NO; | |
| 119 _delayBetweenBlocks = 0.2; | |
| 120 _delayBeforeFirstBlock = 3.0; | |
| 121 } | |
| 89 return self; | 122 return self; |
| 90 } | 123 } |
| 91 | 124 |
| 125 - (void)enqueueBlockNamed:(NSString*)name block:(ProceduralBlock)block { | |
| 126 DCHECK(name); | |
| 127 [self cancelBlockNamed:name]; | |
| 128 [_blocksNameQueue addObject:name]; | |
| 129 | |
| 130 base::scoped_nsobject<DeferredInitializationBlock> deferredBlock( | |
| 131 [[DeferredInitializationBlock alloc] initWithName:name block:block]); | |
| 132 [_runBlocks setObject:deferredBlock forKey:name]; | |
| 133 | |
| 134 if (!_isBlockScheduled) { | |
| 135 [self scheduleNextBlockWithDelay:self.delayBeforeFirstBlock]; | |
| 136 } | |
| 137 } | |
| 138 | |
| 139 - (void)scheduleNextBlockWithDelay:(NSTimeInterval)delay { | |
| 140 _isBlockScheduled = NO; | |
| 141 NSString* nextBlockName = [_blocksNameQueue firstObject]; | |
| 142 if (!nextBlockName) | |
| 143 return; | |
| 144 | |
| 145 DeferredInitializationBlock* nextBlock = | |
| 146 [_runBlocks objectForKey:nextBlockName]; | |
| 147 DCHECK(nextBlock); | |
| 148 | |
| 149 base::WeakNSObject<DeferredInitializationRunner> weakSelf(self); | |
| 150 | |
| 151 dispatch_after( | |
| 152 dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), | |
| 153 dispatch_get_main_queue(), ^{ | |
| 154 [nextBlock run]; | |
| 155 [weakSelf scheduleNextBlockWithDelay:[weakSelf delayBetweenBlocks]]; | |
| 156 }); | |
| 157 | |
| 158 _isBlockScheduled = YES; | |
| 159 [_blocksNameQueue removeObjectAtIndex:0]; | |
| 160 } | |
| 161 | |
| 92 - (void)runBlockNamed:(NSString*)name | 162 - (void)runBlockNamed:(NSString*)name |
| 93 after:(NSTimeInterval)delaySeconds | 163 after:(NSTimeInterval)delaySeconds |
| 94 block:(ProceduralBlock)block { | 164 block:(ProceduralBlock)block { |
| 95 DCHECK(name); | 165 DCHECK(name); |
| 96 // Safety check in case this function is called with a nanosecond or | 166 // Safety check in case this function is called with a nanosecond or |
| 97 // microsecond parameter by mistake. | 167 // microsecond parameter by mistake. |
| 98 DCHECK(delaySeconds < 3600.0); | 168 DCHECK(delaySeconds < 3600.0); |
| 99 // Cancels the previously scheduled block, if there is one, so this | 169 // Cancels the previously scheduled block, if there is one, so this |
| 100 // |name| block will not be run more than once. | 170 // |name| block will not be run more than once. |
| 101 [[_runBlocks objectForKey:name] cancel]; | 171 [[_runBlocks objectForKey:name] cancel]; |
| 102 base::scoped_nsobject<DeferredInitializationBlock> deferredBlock( | 172 base::scoped_nsobject<DeferredInitializationBlock> deferredBlock( |
| 103 [[DeferredInitializationBlock alloc] initWithName:name block:block]); | 173 [[DeferredInitializationBlock alloc] initWithName:name block:block]); |
| 104 [_runBlocks setObject:deferredBlock forKey:name]; | 174 [_runBlocks setObject:deferredBlock forKey:name]; |
| 105 [deferredBlock dispatch:delaySeconds]; | 175 [deferredBlock dispatch:delaySeconds]; |
| 106 } | 176 } |
| 107 | 177 |
| 108 - (void)runBlockIfNecessary:(NSString*)name { | 178 - (void)runBlockIfNecessary:(NSString*)name { |
| 109 [[_runBlocks objectForKey:name] runSynchronously]; | 179 [[_runBlocks objectForKey:name] run]; |
| 110 } | 180 } |
| 111 | 181 |
| 112 - (void)cancelBlockNamed:(NSString*)name { | 182 - (void)cancelBlockNamed:(NSString*)name { |
| 113 DCHECK(name); | 183 DCHECK(name); |
| 184 [_blocksNameQueue removeObject:name]; | |
| 114 [[_runBlocks objectForKey:name] cancel]; | 185 [[_runBlocks objectForKey:name] cancel]; |
| 115 [_runBlocks removeObjectForKey:name]; | 186 [_runBlocks removeObjectForKey:name]; |
| 116 } | 187 } |
| 117 | 188 |
| 118 - (NSUInteger)numberOfBlocksRemaining { | 189 - (NSUInteger)numberOfBlocksRemaining { |
| 119 return [_runBlocks count]; | 190 return [_runBlocks count]; |
| 120 } | 191 } |
| 121 | 192 |
| 122 @end | 193 @end |
| OLD | NEW |