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

Side by Side Diff: base/message_loop/message_pump_mac.mm

Issue 2889293002: Filter run loop modes in message_pump_mac.mm (Closed)
Patch Set: respond to comments, sort methods Created 3 years, 7 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
« no previous file with comments | « base/message_loop/message_pump_mac.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 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 "base/message_loop/message_pump_mac.h" 5 #import "base/message_loop/message_pump_mac.h"
6 6
7 #import <Foundation/Foundation.h> 7 #import <Foundation/Foundation.h>
8 8
9 #include <limits> 9 #include <limits>
10 10
(...skipping 26 matching lines...) Expand all
37 // Mode that only sees Chrome work sources. 37 // Mode that only sees Chrome work sources.
38 kMessageLoopExclusiveRunLoopMode, 38 kMessageLoopExclusiveRunLoopMode,
39 39
40 // Process work when NSMenus are fading out. 40 // Process work when NSMenus are fading out.
41 CFSTR("com.apple.hitoolbox.windows.windowfadingmode"), 41 CFSTR("com.apple.hitoolbox.windows.windowfadingmode"),
42 42
43 // Process work when AppKit is highlighting an item on the main menubar. 43 // Process work when AppKit is highlighting an item on the main menubar.
44 CFSTR("NSUnhighlightMenuRunLoopMode"), 44 CFSTR("NSUnhighlightMenuRunLoopMode"),
45 }; 45 };
46 46
47 void CFRunLoopAddSourceToAllModes(CFRunLoopRef rl, CFRunLoopSourceRef source) { 47 // Mask that determines which modes in |kAllModes| to use.
48 for (const CFStringRef& mode : kAllModes) 48 enum { kCommonModeMask = 0x1, kAllModesMask = ~0 };
49 CFRunLoopAddSource(rl, source, mode);
50 }
51
52 void CFRunLoopRemoveSourceFromAllModes(CFRunLoopRef rl,
53 CFRunLoopSourceRef source) {
54 for (const CFStringRef& mode : kAllModes)
55 CFRunLoopRemoveSource(rl, source, mode);
56 }
57
58 void CFRunLoopAddTimerToAllModes(CFRunLoopRef rl, CFRunLoopTimerRef timer) {
59 for (const CFStringRef& mode : kAllModes)
60 CFRunLoopAddTimer(rl, timer, mode);
61 }
62
63 void CFRunLoopRemoveTimerFromAllModes(CFRunLoopRef rl,
64 CFRunLoopTimerRef timer) {
65 for (const CFStringRef& mode : kAllModes)
66 CFRunLoopRemoveTimer(rl, timer, mode);
67 }
68
69 void CFRunLoopAddObserverToAllModes(CFRunLoopRef rl,
70 CFRunLoopObserverRef observer) {
71 for (const CFStringRef& mode : kAllModes)
72 CFRunLoopAddObserver(rl, observer, mode);
73 }
74
75 void CFRunLoopRemoveObserverFromAllModes(CFRunLoopRef rl,
76 CFRunLoopObserverRef observer) {
77 for (const CFStringRef& mode : kAllModes)
78 CFRunLoopRemoveObserver(rl, observer, mode);
79 }
80 49
81 void NoOp(void* info) { 50 void NoOp(void* info) {
82 } 51 }
83 52
84 const CFTimeInterval kCFTimeIntervalMax = 53 const CFTimeInterval kCFTimeIntervalMax =
85 std::numeric_limits<CFTimeInterval>::max(); 54 std::numeric_limits<CFTimeInterval>::max();
86 55
87 #if !defined(OS_IOS) 56 #if !defined(OS_IOS)
88 // Set to true if MessagePumpMac::Create() is called before NSApp is 57 // Set to true if MessagePumpMac::Create() is called before NSApp is
89 // initialized. Only accessed from the main thread. 58 // initialized. Only accessed from the main thread.
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
147 } 116 }
148 ~MessagePumpScopedAutoreleasePool() { 117 ~MessagePumpScopedAutoreleasePool() {
149 [pool_ drain]; 118 [pool_ drain];
150 } 119 }
151 120
152 private: 121 private:
153 NSAutoreleasePool* pool_; 122 NSAutoreleasePool* pool_;
154 DISALLOW_COPY_AND_ASSIGN(MessagePumpScopedAutoreleasePool); 123 DISALLOW_COPY_AND_ASSIGN(MessagePumpScopedAutoreleasePool);
155 }; 124 };
156 125
157 #if !defined(OS_IOS) 126 // Must be called on the run loop thread.
158 // This function uses private API to modify a test timer's valid state and 127 void MessagePumpCFRunLoopBase::Run(Delegate* delegate) {
159 // uses public API to confirm that the private API changed the correct bit. 128 // nesting_level_ will be incremented in EnterExitRunLoop, so set
160 // static 129 // run_nesting_level_ accordingly.
161 bool MessagePumpCFRunLoopBase::CanInvalidateCFRunLoopTimers() { 130 int last_run_nesting_level = run_nesting_level_;
162 CFRunLoopTimerContext timer_context = CFRunLoopTimerContext(); 131 run_nesting_level_ = nesting_level_ + 1;
163 timer_context.info = nullptr; 132
164 ScopedCFTypeRef<CFRunLoopTimerRef> test_timer( 133 Delegate* last_delegate = delegate_;
165 CFRunLoopTimerCreate(NULL, // allocator 134 SetDelegate(delegate);
166 kCFTimeIntervalMax, // fire time 135
167 kCFTimeIntervalMax, // interval 136 DoRun(delegate);
168 0, // flags 137
169 0, // priority 138 // Restore the previous state of the object.
170 nullptr, &timer_context)); 139 SetDelegate(last_delegate);
171 // Should be valid from the start. 140 run_nesting_level_ = last_run_nesting_level;
172 if (!CFRunLoopTimerIsValid(test_timer)) {
173 return false;
174 }
175 // Confirm that the private API can mark the timer invalid.
176 __ChromeCFRunLoopTimerSetValid(test_timer, false);
177 if (CFRunLoopTimerIsValid(test_timer)) {
178 return false;
179 }
180 // Confirm that the private API can mark the timer valid.
181 __ChromeCFRunLoopTimerSetValid(test_timer, true);
182 return CFRunLoopTimerIsValid(test_timer);
183 } 141 }
184 #endif // !defined(OS_IOS)
185 142
186 // static 143 // May be called on any thread.
187 void MessagePumpCFRunLoopBase::ChromeCFRunLoopTimerSetValid( 144 void MessagePumpCFRunLoopBase::ScheduleWork() {
188 CFRunLoopTimerRef timer, 145 CFRunLoopSourceSignal(work_source_);
189 bool valid) { 146 CFRunLoopWakeUp(run_loop_);
190 #if !defined(OS_IOS)
191 static bool can_invalidate_timers = CanInvalidateCFRunLoopTimers();
192 if (can_invalidate_timers) {
193 __ChromeCFRunLoopTimerSetValid(timer, valid);
194 }
195 #endif // !defined(OS_IOS)
196 } 147 }
197 148
198 // Must be called on the run loop thread. 149 // Must be called on the run loop thread.
199 MessagePumpCFRunLoopBase::MessagePumpCFRunLoopBase() 150 void MessagePumpCFRunLoopBase::ScheduleDelayedWork(
200 : delegate_(NULL), 151 const TimeTicks& delayed_work_time) {
152 TimeDelta delta = delayed_work_time - TimeTicks::Now();
153 delayed_work_fire_time_ = CFAbsoluteTimeGetCurrent() + delta.InSecondsF();
154
155 // Flip the timer's validation bit just before setting the new fire time. Do
156 // this now because CFRunLoopTimerSetNextFireDate() likely checks the validity
157 // of a timer before proceeding to set its fire date. Making the timer valid
158 // now won't have any side effects (such as a premature firing of the timer)
159 // because we're only flipping a bit.
160 //
161 // Please see the comment in RunDelayedWorkTimer() for more info on the whys
162 // of invalidation.
163 ChromeCFRunLoopTimerSetValid(delayed_work_timer_, true);
164
165 CFRunLoopTimerSetNextFireDate(delayed_work_timer_, delayed_work_fire_time_);
166 if (timer_slack_ == TIMER_SLACK_MAXIMUM) {
167 CFRunLoopTimerSetTolerance(delayed_work_timer_, delta.InSecondsF() * 0.5);
168 } else {
169 CFRunLoopTimerSetTolerance(delayed_work_timer_, 0);
170 }
171 }
172
173 void MessagePumpCFRunLoopBase::SetTimerSlack(TimerSlack timer_slack) {
174 timer_slack_ = timer_slack;
175 }
176
177 // Must be called on the run loop thread.
178 MessagePumpCFRunLoopBase::MessagePumpCFRunLoopBase(int mode_mask)
179 : mode_mask_(mode_mask),
180 delegate_(NULL),
201 delayed_work_fire_time_(kCFTimeIntervalMax), 181 delayed_work_fire_time_(kCFTimeIntervalMax),
202 timer_slack_(base::TIMER_SLACK_NONE), 182 timer_slack_(base::TIMER_SLACK_NONE),
203 nesting_level_(0), 183 nesting_level_(0),
204 run_nesting_level_(0), 184 run_nesting_level_(0),
205 deepest_nesting_level_(0), 185 deepest_nesting_level_(0),
206 delegateless_work_(false), 186 delegateless_work_(false),
207 delegateless_idle_work_(false) { 187 delegateless_idle_work_(false) {
208 run_loop_ = CFRunLoopGetCurrent(); 188 run_loop_ = CFRunLoopGetCurrent();
209 CFRetain(run_loop_); 189 CFRetain(run_loop_);
210 190
211 // Set a repeating timer with a preposterous firing time and interval. The 191 // Set a repeating timer with a preposterous firing time and interval. The
212 // timer will effectively never fire as-is. The firing time will be adjusted 192 // timer will effectively never fire as-is. The firing time will be adjusted
213 // as needed when ScheduleDelayedWork is called. 193 // as needed when ScheduleDelayedWork is called.
214 CFRunLoopTimerContext timer_context = CFRunLoopTimerContext(); 194 CFRunLoopTimerContext timer_context = CFRunLoopTimerContext();
215 timer_context.info = this; 195 timer_context.info = this;
216 delayed_work_timer_ = CFRunLoopTimerCreate(NULL, // allocator 196 delayed_work_timer_ = CFRunLoopTimerCreate(NULL, // allocator
217 kCFTimeIntervalMax, // fire time 197 kCFTimeIntervalMax, // fire time
218 kCFTimeIntervalMax, // interval 198 kCFTimeIntervalMax, // interval
219 0, // flags 199 0, // flags
220 0, // priority 200 0, // priority
221 RunDelayedWorkTimer, 201 RunDelayedWorkTimer,
222 &timer_context); 202 &timer_context);
223 CFRunLoopAddTimerToAllModes(run_loop_, delayed_work_timer_); 203 InvokeForEnabledModes(&CFRunLoopAddTimer, delayed_work_timer_);
224 204
225 CFRunLoopSourceContext source_context = CFRunLoopSourceContext(); 205 CFRunLoopSourceContext source_context = CFRunLoopSourceContext();
226 source_context.info = this; 206 source_context.info = this;
227 source_context.perform = RunWorkSource; 207 source_context.perform = RunWorkSource;
228 work_source_ = CFRunLoopSourceCreate(NULL, // allocator 208 work_source_ = CFRunLoopSourceCreate(NULL, // allocator
229 1, // priority 209 1, // priority
230 &source_context); 210 &source_context);
231 CFRunLoopAddSourceToAllModes(run_loop_, work_source_); 211 InvokeForEnabledModes(&CFRunLoopAddSource, work_source_);
232 212
233 source_context.perform = RunIdleWorkSource; 213 source_context.perform = RunIdleWorkSource;
234 idle_work_source_ = CFRunLoopSourceCreate(NULL, // allocator 214 idle_work_source_ = CFRunLoopSourceCreate(NULL, // allocator
235 2, // priority 215 2, // priority
236 &source_context); 216 &source_context);
237 CFRunLoopAddSourceToAllModes(run_loop_, idle_work_source_); 217 InvokeForEnabledModes(&CFRunLoopAddSource, idle_work_source_);
238 218
239 source_context.perform = RunNestingDeferredWorkSource; 219 source_context.perform = RunNestingDeferredWorkSource;
240 nesting_deferred_work_source_ = CFRunLoopSourceCreate(NULL, // allocator 220 nesting_deferred_work_source_ = CFRunLoopSourceCreate(NULL, // allocator
241 0, // priority 221 0, // priority
242 &source_context); 222 &source_context);
243 CFRunLoopAddSourceToAllModes(run_loop_, nesting_deferred_work_source_); 223 InvokeForEnabledModes(&CFRunLoopAddSource, nesting_deferred_work_source_);
244 224
245 CFRunLoopObserverContext observer_context = CFRunLoopObserverContext(); 225 CFRunLoopObserverContext observer_context = CFRunLoopObserverContext();
246 observer_context.info = this; 226 observer_context.info = this;
247 pre_wait_observer_ = CFRunLoopObserverCreate(NULL, // allocator 227 pre_wait_observer_ = CFRunLoopObserverCreate(NULL, // allocator
248 kCFRunLoopBeforeWaiting, 228 kCFRunLoopBeforeWaiting,
249 true, // repeat 229 true, // repeat
250 0, // priority 230 0, // priority
251 PreWaitObserver, 231 PreWaitObserver,
252 &observer_context); 232 &observer_context);
253 CFRunLoopAddObserverToAllModes(run_loop_, pre_wait_observer_); 233 InvokeForEnabledModes(&CFRunLoopAddObserver, pre_wait_observer_);
254 234
255 pre_source_observer_ = CFRunLoopObserverCreate(NULL, // allocator 235 pre_source_observer_ = CFRunLoopObserverCreate(NULL, // allocator
256 kCFRunLoopBeforeSources, 236 kCFRunLoopBeforeSources,
257 true, // repeat 237 true, // repeat
258 0, // priority 238 0, // priority
259 PreSourceObserver, 239 PreSourceObserver,
260 &observer_context); 240 &observer_context);
261 CFRunLoopAddObserverToAllModes(run_loop_, pre_source_observer_); 241 InvokeForEnabledModes(&CFRunLoopAddObserver, pre_source_observer_);
262 242
263 enter_exit_observer_ = CFRunLoopObserverCreate(NULL, // allocator 243 enter_exit_observer_ = CFRunLoopObserverCreate(NULL, // allocator
264 kCFRunLoopEntry | 244 kCFRunLoopEntry |
265 kCFRunLoopExit, 245 kCFRunLoopExit,
266 true, // repeat 246 true, // repeat
267 0, // priority 247 0, // priority
268 EnterExitObserver, 248 EnterExitObserver,
269 &observer_context); 249 &observer_context);
270 CFRunLoopAddObserverToAllModes(run_loop_, enter_exit_observer_); 250 InvokeForEnabledModes(&CFRunLoopAddObserver, enter_exit_observer_);
271 } 251 }
272 252
273 // Ideally called on the run loop thread. If other run loops were running 253 // Ideally called on the run loop thread. If other run loops were running
274 // lower on the run loop thread's stack when this object was created, the 254 // lower on the run loop thread's stack when this object was created, the
275 // same number of run loops must be running when this object is destroyed. 255 // same number of run loops must be running when this object is destroyed.
276 MessagePumpCFRunLoopBase::~MessagePumpCFRunLoopBase() { 256 MessagePumpCFRunLoopBase::~MessagePumpCFRunLoopBase() {
277 CFRunLoopRemoveObserverFromAllModes(run_loop_, enter_exit_observer_); 257 for (const CFRunLoopObserverRef& observer :
278 CFRelease(enter_exit_observer_); 258 {enter_exit_observer_, pre_source_observer_, pre_wait_observer_}) {
279 259 InvokeForEnabledModes(&CFRunLoopRemoveObserver, observer);
280 CFRunLoopRemoveObserverFromAllModes(run_loop_, pre_source_observer_); 260 CFRelease(observer);
281 CFRelease(pre_source_observer_); 261 }
282 262 for (const CFRunLoopSourceRef& source :
283 CFRunLoopRemoveObserverFromAllModes(run_loop_, pre_wait_observer_); 263 {nesting_deferred_work_source_, idle_work_source_, work_source_}) {
284 CFRelease(pre_wait_observer_); 264 InvokeForEnabledModes(&CFRunLoopRemoveSource, source);
285 265 CFRelease(source);
286 CFRunLoopRemoveSourceFromAllModes(run_loop_, nesting_deferred_work_source_); 266 }
287 CFRelease(nesting_deferred_work_source_); 267 InvokeForEnabledModes(&CFRunLoopRemoveTimer, delayed_work_timer_);
288
289 CFRunLoopRemoveSourceFromAllModes(run_loop_, idle_work_source_);
290 CFRelease(idle_work_source_);
291
292 CFRunLoopRemoveSourceFromAllModes(run_loop_, work_source_);
293 CFRelease(work_source_);
294
295 CFRunLoopRemoveTimerFromAllModes(run_loop_, delayed_work_timer_);
296 CFRelease(delayed_work_timer_); 268 CFRelease(delayed_work_timer_);
297
298 CFRelease(run_loop_); 269 CFRelease(run_loop_);
299 } 270 }
300 271
301 // Must be called on the run loop thread.
302 void MessagePumpCFRunLoopBase::Run(Delegate* delegate) {
303 // nesting_level_ will be incremented in EnterExitRunLoop, so set
304 // run_nesting_level_ accordingly.
305 int last_run_nesting_level = run_nesting_level_;
306 run_nesting_level_ = nesting_level_ + 1;
307
308 Delegate* last_delegate = delegate_;
309 SetDelegate(delegate);
310
311 DoRun(delegate);
312
313 // Restore the previous state of the object.
314 SetDelegate(last_delegate);
315 run_nesting_level_ = last_run_nesting_level;
316 }
317
318 void MessagePumpCFRunLoopBase::SetDelegate(Delegate* delegate) { 272 void MessagePumpCFRunLoopBase::SetDelegate(Delegate* delegate) {
319 delegate_ = delegate; 273 delegate_ = delegate;
320 274
321 if (delegate) { 275 if (delegate) {
322 // If any work showed up but could not be dispatched for want of a 276 // If any work showed up but could not be dispatched for want of a
323 // delegate, set it up for dispatch again now that a delegate is 277 // delegate, set it up for dispatch again now that a delegate is
324 // available. 278 // available.
325 if (delegateless_work_) { 279 if (delegateless_work_) {
326 CFRunLoopSourceSignal(work_source_); 280 CFRunLoopSourceSignal(work_source_);
327 delegateless_work_ = false; 281 delegateless_work_ = false;
328 } 282 }
329 if (delegateless_idle_work_) { 283 if (delegateless_idle_work_) {
330 CFRunLoopSourceSignal(idle_work_source_); 284 CFRunLoopSourceSignal(idle_work_source_);
331 delegateless_idle_work_ = false; 285 delegateless_idle_work_ = false;
332 } 286 }
333 } 287 }
334 } 288 }
335 289
336 // May be called on any thread. 290 // Base version returns a standard NSAutoreleasePool.
337 void MessagePumpCFRunLoopBase::ScheduleWork() { 291 AutoreleasePoolType* MessagePumpCFRunLoopBase::CreateAutoreleasePool() {
338 CFRunLoopSourceSignal(work_source_); 292 return [[NSAutoreleasePool alloc] init];
339 CFRunLoopWakeUp(run_loop_);
340 } 293 }
341 294
342 // Must be called on the run loop thread. 295 template <typename Argument>
343 void MessagePumpCFRunLoopBase::ScheduleDelayedWork( 296 void MessagePumpCFRunLoopBase::InvokeForEnabledModes(void method(CFRunLoopRef,
344 const TimeTicks& delayed_work_time) { 297 Argument,
345 TimeDelta delta = delayed_work_time - TimeTicks::Now(); 298 CFStringRef),
346 delayed_work_fire_time_ = CFAbsoluteTimeGetCurrent() + delta.InSecondsF(); 299 Argument argument) {
347 300 for (size_t i = 0; i < arraysize(kAllModes); ++i) {
348 // Flip the timer's validation bit just before setting the new fire time. Do 301 if (mode_mask_ & (0x1 << i))
349 // this now because CFRunLoopTimerSetNextFireDate() likely checks the validity 302 method(run_loop_, argument, kAllModes[i]);
350 // of a timer before proceeding to set its fire date. Making the timer valid
351 // now won't have any side effects (such as a premature firing of the timer)
352 // because we're only flipping a bit.
353 //
354 // Please see the comment in RunDelayedWorkTimer() for more info on the whys
355 // of invalidation.
356 ChromeCFRunLoopTimerSetValid(delayed_work_timer_, true);
357
358 CFRunLoopTimerSetNextFireDate(delayed_work_timer_, delayed_work_fire_time_);
359 if (timer_slack_ == TIMER_SLACK_MAXIMUM) {
360 CFRunLoopTimerSetTolerance(delayed_work_timer_, delta.InSecondsF() * 0.5);
361 } else {
362 CFRunLoopTimerSetTolerance(delayed_work_timer_, 0);
363 } 303 }
364 } 304 }
365 305
366 void MessagePumpCFRunLoopBase::SetTimerSlack(TimerSlack timer_slack) { 306 #if !defined(OS_IOS)
367 timer_slack_ = timer_slack; 307 // This function uses private API to modify a test timer's valid state and
308 // uses public API to confirm that the private API changed the correct bit.
309 // static
310 bool MessagePumpCFRunLoopBase::CanInvalidateCFRunLoopTimers() {
311 CFRunLoopTimerContext timer_context = CFRunLoopTimerContext();
312 timer_context.info = nullptr;
313 ScopedCFTypeRef<CFRunLoopTimerRef> test_timer(
314 CFRunLoopTimerCreate(NULL, // allocator
315 kCFTimeIntervalMax, // fire time
316 kCFTimeIntervalMax, // interval
317 0, // flags
318 0, // priority
319 nullptr, &timer_context));
320 // Should be valid from the start.
321 if (!CFRunLoopTimerIsValid(test_timer)) {
322 return false;
323 }
324 // Confirm that the private API can mark the timer invalid.
325 __ChromeCFRunLoopTimerSetValid(test_timer, false);
326 if (CFRunLoopTimerIsValid(test_timer)) {
327 return false;
328 }
329 // Confirm that the private API can mark the timer valid.
330 __ChromeCFRunLoopTimerSetValid(test_timer, true);
331 return CFRunLoopTimerIsValid(test_timer);
332 }
333 #endif // !defined(OS_IOS)
334
335 // static
336 void MessagePumpCFRunLoopBase::ChromeCFRunLoopTimerSetValid(
337 CFRunLoopTimerRef timer,
338 bool valid) {
339 #if !defined(OS_IOS)
340 static bool can_invalidate_timers = CanInvalidateCFRunLoopTimers();
341 if (can_invalidate_timers) {
342 __ChromeCFRunLoopTimerSetValid(timer, valid);
343 }
344 #endif // !defined(OS_IOS)
368 } 345 }
369 346
370 // Called from the run loop. 347 // Called from the run loop.
371 // static 348 // static
372 void MessagePumpCFRunLoopBase::RunDelayedWorkTimer(CFRunLoopTimerRef timer, 349 void MessagePumpCFRunLoopBase::RunDelayedWorkTimer(CFRunLoopTimerRef timer,
373 void* info) { 350 void* info) {
374 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info); 351 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info);
375 352
376 // The timer won't fire again until it's reset. 353 // The timer won't fire again until it's reset.
377 self->delayed_work_fire_time_ = kCFTimeIntervalMax; 354 self->delayed_work_fire_time_ = kCFTimeIntervalMax;
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after
632 base::mac::CallWithEHFrame(^{ 609 base::mac::CallWithEHFrame(^{
633 self->EnterExitRunLoop(activity); 610 self->EnterExitRunLoop(activity);
634 }); 611 });
635 } 612 }
636 613
637 // Called by MessagePumpCFRunLoopBase::EnterExitRunLoop. The default 614 // Called by MessagePumpCFRunLoopBase::EnterExitRunLoop. The default
638 // implementation is a no-op. 615 // implementation is a no-op.
639 void MessagePumpCFRunLoopBase::EnterExitRunLoop(CFRunLoopActivity activity) { 616 void MessagePumpCFRunLoopBase::EnterExitRunLoop(CFRunLoopActivity activity) {
640 } 617 }
641 618
642 // Base version returns a standard NSAutoreleasePool.
643 AutoreleasePoolType* MessagePumpCFRunLoopBase::CreateAutoreleasePool() {
644 return [[NSAutoreleasePool alloc] init];
645 }
646
647 MessagePumpCFRunLoop::MessagePumpCFRunLoop() 619 MessagePumpCFRunLoop::MessagePumpCFRunLoop()
648 : quit_pending_(false) { 620 : MessagePumpCFRunLoopBase(kCommonModeMask), quit_pending_(false) {}
649 }
650 621
651 MessagePumpCFRunLoop::~MessagePumpCFRunLoop() {} 622 MessagePumpCFRunLoop::~MessagePumpCFRunLoop() {}
652 623
653 // Called by MessagePumpCFRunLoopBase::DoRun. If other CFRunLoopRun loops were 624 // Called by MessagePumpCFRunLoopBase::DoRun. If other CFRunLoopRun loops were
654 // running lower on the run loop thread's stack when this object was created, 625 // running lower on the run loop thread's stack when this object was created,
655 // the same number of CFRunLoopRun loops must be running for the outermost call 626 // the same number of CFRunLoopRun loops must be running for the outermost call
656 // to Run. Run/DoRun are reentrant after that point. 627 // to Run. Run/DoRun are reentrant after that point.
657 void MessagePumpCFRunLoop::DoRun(Delegate* delegate) { 628 void MessagePumpCFRunLoop::DoRun(Delegate* delegate) {
658 // This is completely identical to calling CFRunLoopRun(), except autorelease 629 // This is completely identical to calling CFRunLoopRun(), except autorelease
659 // pool management is introduced. 630 // pool management is introduced.
(...skipping 30 matching lines...) Expand all
690 // Quit was called while loops other than those managed by this object 661 // Quit was called while loops other than those managed by this object
691 // were running further inside a run loop managed by this object. Now 662 // were running further inside a run loop managed by this object. Now
692 // that all unmanaged inner run loops are gone, stop the loop running 663 // that all unmanaged inner run loops are gone, stop the loop running
693 // just inside Run. 664 // just inside Run.
694 CFRunLoopStop(run_loop()); 665 CFRunLoopStop(run_loop());
695 quit_pending_ = false; 666 quit_pending_ = false;
696 } 667 }
697 } 668 }
698 669
699 MessagePumpNSRunLoop::MessagePumpNSRunLoop() 670 MessagePumpNSRunLoop::MessagePumpNSRunLoop()
700 : keep_running_(true) { 671 : MessagePumpCFRunLoopBase(kCommonModeMask), keep_running_(true) {
701 CFRunLoopSourceContext source_context = CFRunLoopSourceContext(); 672 CFRunLoopSourceContext source_context = CFRunLoopSourceContext();
702 source_context.perform = NoOp; 673 source_context.perform = NoOp;
703 quit_source_ = CFRunLoopSourceCreate(NULL, // allocator 674 quit_source_ = CFRunLoopSourceCreate(NULL, // allocator
704 0, // priority 675 0, // priority
705 &source_context); 676 &source_context);
706 CFRunLoopAddSourceToAllModes(run_loop(), quit_source_); 677 InvokeForEnabledModes(&CFRunLoopAddSource, quit_source_);
707 } 678 }
708 679
709 MessagePumpNSRunLoop::~MessagePumpNSRunLoop() { 680 MessagePumpNSRunLoop::~MessagePumpNSRunLoop() {
710 CFRunLoopRemoveSourceFromAllModes(run_loop(), quit_source_); 681 InvokeForEnabledModes(&CFRunLoopRemoveSource, quit_source_);
711 CFRelease(quit_source_); 682 CFRelease(quit_source_);
712 } 683 }
713 684
714 void MessagePumpNSRunLoop::DoRun(Delegate* delegate) { 685 void MessagePumpNSRunLoop::DoRun(Delegate* delegate) {
715 while (keep_running_) { 686 while (keep_running_) {
716 // NSRunLoop manages autorelease pools itself. 687 // NSRunLoop manages autorelease pools itself.
717 [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode 688 [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
718 beforeDate:[NSDate distantFuture]]; 689 beforeDate:[NSDate distantFuture]];
719 } 690 }
720 691
721 keep_running_ = true; 692 keep_running_ = true;
722 } 693 }
723 694
724 void MessagePumpNSRunLoop::Quit() { 695 void MessagePumpNSRunLoop::Quit() {
725 keep_running_ = false; 696 keep_running_ = false;
726 CFRunLoopSourceSignal(quit_source_); 697 CFRunLoopSourceSignal(quit_source_);
727 CFRunLoopWakeUp(run_loop()); 698 CFRunLoopWakeUp(run_loop());
728 } 699 }
729 700
730 #if defined(OS_IOS) 701 #if defined(OS_IOS)
731 MessagePumpUIApplication::MessagePumpUIApplication() 702 MessagePumpUIApplication::MessagePumpUIApplication()
732 : run_loop_(NULL) { 703 : MessagePumpCFRunLoopBase(kCommonModeMask), run_loop_(NULL) {}
733 }
734 704
735 MessagePumpUIApplication::~MessagePumpUIApplication() {} 705 MessagePumpUIApplication::~MessagePumpUIApplication() {}
736 706
737 void MessagePumpUIApplication::DoRun(Delegate* delegate) { 707 void MessagePumpUIApplication::DoRun(Delegate* delegate) {
738 NOTREACHED(); 708 NOTREACHED();
739 } 709 }
740 710
741 void MessagePumpUIApplication::Quit() { 711 void MessagePumpUIApplication::Quit() {
742 NOTREACHED(); 712 NOTREACHED();
743 } 713 }
744 714
745 void MessagePumpUIApplication::Attach(Delegate* delegate) { 715 void MessagePumpUIApplication::Attach(Delegate* delegate) {
746 DCHECK(!run_loop_); 716 DCHECK(!run_loop_);
747 run_loop_ = new RunLoop(); 717 run_loop_ = new RunLoop();
748 CHECK(run_loop_->BeforeRun()); 718 CHECK(run_loop_->BeforeRun());
749 SetDelegate(delegate); 719 SetDelegate(delegate);
750 } 720 }
751 721
752 #else 722 #else
753 723
754 MessagePumpNSApplication::MessagePumpNSApplication() 724 MessagePumpNSApplication::MessagePumpNSApplication()
755 : keep_running_(true), 725 : MessagePumpCFRunLoopBase(kAllModesMask),
756 running_own_loop_(false) { 726 keep_running_(true),
757 } 727 running_own_loop_(false) {}
758 728
759 MessagePumpNSApplication::~MessagePumpNSApplication() {} 729 MessagePumpNSApplication::~MessagePumpNSApplication() {}
760 730
761 void MessagePumpNSApplication::DoRun(Delegate* delegate) { 731 void MessagePumpNSApplication::DoRun(Delegate* delegate) {
762 bool last_running_own_loop_ = running_own_loop_; 732 bool last_running_own_loop_ = running_own_loop_;
763 733
764 // NSApp must be initialized by calling: 734 // NSApp must be initialized by calling:
765 // [{some class which implements CrAppProtocol} sharedApplication] 735 // [{some class which implements CrAppProtocol} sharedApplication]
766 // Most likely candidates are CrApplication or BrowserCrApplication. 736 // Most likely candidates are CrApplication or BrowserCrApplication.
767 // These can be initialized from C++ code by calling 737 // These can be initialized from C++ code by calling
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
893 [NSApplication sharedApplication]; 863 [NSApplication sharedApplication];
894 g_not_using_cr_app = true; 864 g_not_using_cr_app = true;
895 return new MessagePumpNSApplication; 865 return new MessagePumpNSApplication;
896 #endif 866 #endif
897 } 867 }
898 868
899 return new MessagePumpNSRunLoop; 869 return new MessagePumpNSRunLoop;
900 } 870 }
901 871
902 } // namespace base 872 } // namespace base
OLDNEW
« no previous file with comments | « base/message_loop/message_pump_mac.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698