| 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" | |
| 10 #include "base/logging.h" | 9 #include "base/logging.h" |
| 11 #include "base/mac/scoped_block.h" | 10 #include "base/mac/scoped_block.h" |
| 12 #include "base/mac/scoped_nsobject.h" | 11 |
| 12 #if !defined(__has_feature) || !__has_feature(objc_arc) |
| 13 #error "This file requires ARC support." |
| 14 #endif |
| 13 | 15 |
| 14 // An object encapsulating the deferred execution of a block of initialization | 16 // An object encapsulating the deferred execution of a block of initialization |
| 15 // code. | 17 // code. |
| 16 @interface DeferredInitializationBlock : NSObject { | 18 @interface DeferredInitializationBlock : NSObject |
| 17 // A string to reference the initialization block. | |
| 18 base::scoped_nsobject<NSString> _name; | |
| 19 // A block of code to execute. | |
| 20 base::mac::ScopedBlock<ProceduralBlock> _runBlock; | |
| 21 } | |
| 22 | 19 |
| 23 - (instancetype)init NS_UNAVAILABLE; | 20 - (instancetype)init NS_UNAVAILABLE; |
| 24 | 21 |
| 25 // Designated initializer. | 22 // Designated initializer. |
| 26 - (instancetype)initWithName:(NSString*)name | 23 - (instancetype)initWithName:(NSString*)name |
| 27 block:(ProceduralBlock)block NS_DESIGNATED_INITIALIZER; | 24 block:(ProceduralBlock)block NS_DESIGNATED_INITIALIZER; |
| 28 | 25 |
| 29 // Executes the deferred block now. | 26 // Executes the deferred block now. |
| 30 - (void)run; | 27 - (void)run; |
| 31 | 28 |
| 32 // Cancels the block's execution. | 29 // Cancels the block's execution. |
| 33 - (void)cancel; | 30 - (void)cancel; |
| 34 | 31 |
| 35 @end | 32 @end |
| 36 | 33 |
| 37 @implementation DeferredInitializationBlock | 34 @implementation DeferredInitializationBlock { |
| 35 // A string to reference the initialization block. |
| 36 NSString* _name; |
| 37 // A block of code to execute. |
| 38 ProceduralBlock _runBlock; |
| 39 } |
| 38 | 40 |
| 39 // Overrides default designated initializer. | 41 // Overrides default designated initializer. |
| 40 - (instancetype)init { | 42 - (instancetype)init { |
| 41 NOTREACHED(); | 43 NOTREACHED(); |
| 42 return nil; | 44 return nil; |
| 43 } | 45 } |
| 44 | 46 |
| 45 - (instancetype)initWithName:(NSString*)name block:(ProceduralBlock)block { | 47 - (instancetype)initWithName:(NSString*)name block:(ProceduralBlock)block { |
| 46 DCHECK(block); | 48 DCHECK(block); |
| 47 self = [super init]; | 49 self = [super init]; |
| 48 if (self) { | 50 if (self) { |
| 49 _name.reset([name copy]); | 51 _name = [name copy]; |
| 50 _runBlock.reset(block, base::scoped_policy::RETAIN); | 52 _runBlock = block; |
| 51 } | 53 } |
| 52 return self; | 54 return self; |
| 53 } | 55 } |
| 54 | 56 |
| 55 - (void)run { | 57 - (void)run { |
| 56 DCHECK([NSThread isMainThread]); | 58 DCHECK([NSThread isMainThread]); |
| 57 ProceduralBlock deferredBlock = _runBlock.get(); | 59 ProceduralBlock deferredBlock = _runBlock; |
| 58 if (!deferredBlock) | 60 if (!deferredBlock) |
| 59 return; | 61 return; |
| 60 deferredBlock(); | 62 deferredBlock(); |
| 61 [[DeferredInitializationRunner sharedInstance] cancelBlockNamed:_name]; | 63 [[DeferredInitializationRunner sharedInstance] cancelBlockNamed:_name]; |
| 62 } | 64 } |
| 63 | 65 |
| 64 - (void)cancel { | 66 - (void)cancel { |
| 65 _runBlock.reset(); | 67 _runBlock = nil; |
| 66 } | 68 } |
| 67 | 69 |
| 68 @end | 70 @end |
| 69 | 71 |
| 70 @interface DeferredInitializationRunner () { | 72 @interface DeferredInitializationRunner () { |
| 71 base::scoped_nsobject<NSMutableArray> _blocksNameQueue; | 73 NSMutableArray* _blocksNameQueue; |
| 72 base::scoped_nsobject<NSMutableDictionary> _runBlocks; | 74 NSMutableDictionary* _runBlocks; |
| 73 BOOL _isBlockScheduled; | 75 BOOL _isBlockScheduled; |
| 74 } | 76 } |
| 75 | 77 |
| 76 // Schedule the next block to be run after |delay| it will automatically | 78 // Schedule the next block to be run after |delay| it will automatically |
| 77 // schedule the next block after |delayBetweenBlocks|. | 79 // schedule the next block after |delayBetweenBlocks|. |
| 78 - (void)scheduleNextBlockWithDelay:(NSTimeInterval)delay; | 80 - (void)scheduleNextBlockWithDelay:(NSTimeInterval)delay; |
| 79 | 81 |
| 80 // Time interval between two blocks. Default value is 200ms. | 82 // Time interval between two blocks. Default value is 200ms. |
| 81 @property(nonatomic) NSTimeInterval delayBetweenBlocks; | 83 @property(nonatomic) NSTimeInterval delayBetweenBlocks; |
| 82 | 84 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 95 static DeferredInitializationRunner* instance = nil; | 97 static DeferredInitializationRunner* instance = nil; |
| 96 dispatch_once(&once, ^{ | 98 dispatch_once(&once, ^{ |
| 97 instance = [[DeferredInitializationRunner alloc] init]; | 99 instance = [[DeferredInitializationRunner alloc] init]; |
| 98 }); | 100 }); |
| 99 return instance; | 101 return instance; |
| 100 } | 102 } |
| 101 | 103 |
| 102 - (instancetype)init { | 104 - (instancetype)init { |
| 103 self = [super init]; | 105 self = [super init]; |
| 104 if (self) { | 106 if (self) { |
| 105 _blocksNameQueue.reset([[NSMutableArray array] retain]); | 107 _blocksNameQueue = [NSMutableArray array]; |
| 106 _runBlocks.reset([[NSMutableDictionary dictionary] retain]); | 108 _runBlocks = [NSMutableDictionary dictionary]; |
| 107 _isBlockScheduled = NO; | 109 _isBlockScheduled = NO; |
| 108 _delayBetweenBlocks = 0.2; | 110 _delayBetweenBlocks = 0.2; |
| 109 _delayBeforeFirstBlock = 3.0; | 111 _delayBeforeFirstBlock = 3.0; |
| 110 } | 112 } |
| 111 return self; | 113 return self; |
| 112 } | 114 } |
| 113 | 115 |
| 114 - (void)enqueueBlockNamed:(NSString*)name block:(ProceduralBlock)block { | 116 - (void)enqueueBlockNamed:(NSString*)name block:(ProceduralBlock)block { |
| 115 DCHECK(name); | 117 DCHECK(name); |
| 116 DCHECK([NSThread isMainThread]); | 118 DCHECK([NSThread isMainThread]); |
| 117 [self cancelBlockNamed:name]; | 119 [self cancelBlockNamed:name]; |
| 118 [_blocksNameQueue addObject:name]; | 120 [_blocksNameQueue addObject:name]; |
| 119 | 121 |
| 120 base::scoped_nsobject<DeferredInitializationBlock> deferredBlock( | 122 DeferredInitializationBlock* deferredBlock = |
| 121 [[DeferredInitializationBlock alloc] initWithName:name block:block]); | 123 [[DeferredInitializationBlock alloc] initWithName:name block:block]; |
| 122 [_runBlocks setObject:deferredBlock forKey:name]; | 124 [_runBlocks setObject:deferredBlock forKey:name]; |
| 123 | 125 |
| 124 if (!_isBlockScheduled) { | 126 if (!_isBlockScheduled) { |
| 125 [self scheduleNextBlockWithDelay:self.delayBeforeFirstBlock]; | 127 [self scheduleNextBlockWithDelay:self.delayBeforeFirstBlock]; |
| 126 } | 128 } |
| 127 } | 129 } |
| 128 | 130 |
| 129 - (void)scheduleNextBlockWithDelay:(NSTimeInterval)delay { | 131 - (void)scheduleNextBlockWithDelay:(NSTimeInterval)delay { |
| 130 DCHECK([NSThread isMainThread]); | 132 DCHECK([NSThread isMainThread]); |
| 131 _isBlockScheduled = NO; | 133 _isBlockScheduled = NO; |
| 132 NSString* nextBlockName = [_blocksNameQueue firstObject]; | 134 NSString* nextBlockName = [_blocksNameQueue firstObject]; |
| 133 if (!nextBlockName) | 135 if (!nextBlockName) |
| 134 return; | 136 return; |
| 135 | 137 |
| 136 DeferredInitializationBlock* nextBlock = | 138 DeferredInitializationBlock* nextBlock = |
| 137 [_runBlocks objectForKey:nextBlockName]; | 139 [_runBlocks objectForKey:nextBlockName]; |
| 138 DCHECK(nextBlock); | 140 DCHECK(nextBlock); |
| 139 | 141 |
| 140 base::WeakNSObject<DeferredInitializationRunner> weakSelf(self); | 142 __weak DeferredInitializationRunner* weakSelf = self; |
| 141 | 143 |
| 142 dispatch_after( | 144 dispatch_after( |
| 143 dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), | 145 dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), |
| 144 dispatch_get_main_queue(), ^{ | 146 dispatch_get_main_queue(), ^{ |
| 145 [nextBlock run]; | 147 [nextBlock run]; |
| 146 [weakSelf scheduleNextBlockWithDelay:[weakSelf delayBetweenBlocks]]; | 148 [weakSelf scheduleNextBlockWithDelay:[weakSelf delayBetweenBlocks]]; |
| 147 }); | 149 }); |
| 148 | 150 |
| 149 _isBlockScheduled = YES; | 151 _isBlockScheduled = YES; |
| 150 [_blocksNameQueue removeObjectAtIndex:0]; | 152 [_blocksNameQueue removeObjectAtIndex:0]; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 161 [_blocksNameQueue removeObject:name]; | 163 [_blocksNameQueue removeObject:name]; |
| 162 [[_runBlocks objectForKey:name] cancel]; | 164 [[_runBlocks objectForKey:name] cancel]; |
| 163 [_runBlocks removeObjectForKey:name]; | 165 [_runBlocks removeObjectForKey:name]; |
| 164 } | 166 } |
| 165 | 167 |
| 166 - (NSUInteger)numberOfBlocksRemaining { | 168 - (NSUInteger)numberOfBlocksRemaining { |
| 167 return [_runBlocks count]; | 169 return [_runBlocks count]; |
| 168 } | 170 } |
| 169 | 171 |
| 170 @end | 172 @end |
| OLD | NEW |