OLD | NEW |
1 // Copyright (c) 2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2008 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 #include "base/message_pump_mac.h" | 5 #include "base/message_pump_mac.h" |
6 | 6 |
7 #import <AppKit/AppKit.h> | 7 #import <AppKit/AppKit.h> |
8 #import <Foundation/Foundation.h> | 8 #import <Foundation/Foundation.h> |
9 #include <float.h> | 9 #include <float.h> |
10 | 10 |
11 #include "base/scoped_nsautorelease_pool.h" | 11 #include "base/scoped_nsautorelease_pool.h" |
12 #include "base/time.h" | 12 #include "base/time.h" |
13 | 13 |
14 namespace { | 14 namespace { |
15 | 15 |
16 void NoOp(void* info) { | 16 void NoOp(void* info) { |
17 } | 17 } |
18 | 18 |
19 } // namespace | 19 } // namespace |
20 | 20 |
21 namespace base { | 21 namespace base { |
22 | 22 |
23 // Must be called on the run loop thread. | 23 // Must be called on the run loop thread. |
24 MessagePumpCFRunLoopBase::MessagePumpCFRunLoopBase() | 24 MessagePumpCFRunLoopBase::MessagePumpCFRunLoopBase() |
25 : nesting_level_(0), | 25 : delegate_(NULL), |
| 26 nesting_level_(0), |
26 run_nesting_level_(0), | 27 run_nesting_level_(0), |
27 delegate_(NULL), | 28 deepest_nesting_level_(0), |
28 delegateless_work_(false), | 29 delegateless_work_(false), |
29 delegateless_delayed_work_(false), | 30 delegateless_delayed_work_(false), |
30 delegateless_idle_work_(false) | 31 delegateless_idle_work_(false) { |
31 { | |
32 run_loop_ = CFRunLoopGetCurrent(); | 32 run_loop_ = CFRunLoopGetCurrent(); |
33 CFRetain(run_loop_); | 33 CFRetain(run_loop_); |
34 | 34 |
35 // Set a repeating timer with a preposterous firing time and interval. The | 35 // Set a repeating timer with a preposterous firing time and interval. The |
36 // timer will effectively never fire as-is. The firing time will be adjusted | 36 // timer will effectively never fire as-is. The firing time will be adjusted |
37 // as needed when ScheduleDelayedWork is called. | 37 // as needed when ScheduleDelayedWork is called. |
38 CFRunLoopTimerContext timer_context = CFRunLoopTimerContext(); | 38 CFRunLoopTimerContext timer_context = CFRunLoopTimerContext(); |
39 timer_context.info = this; | 39 timer_context.info = this; |
40 delayed_work_timer_ = CFRunLoopTimerCreate(NULL, // allocator | 40 delayed_work_timer_ = CFRunLoopTimerCreate(NULL, // allocator |
41 DBL_MAX, // fire time | 41 DBL_MAX, // fire time |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
127 // Must be called on the run loop thread. | 127 // Must be called on the run loop thread. |
128 void MessagePumpCFRunLoopBase::Run(Delegate* delegate) { | 128 void MessagePumpCFRunLoopBase::Run(Delegate* delegate) { |
129 // nesting_level_ will be incremented in EnterExitRunLoop, so set | 129 // nesting_level_ will be incremented in EnterExitRunLoop, so set |
130 // run_nesting_level_ accordingly. | 130 // run_nesting_level_ accordingly. |
131 int last_run_nesting_level = run_nesting_level_; | 131 int last_run_nesting_level = run_nesting_level_; |
132 run_nesting_level_ = nesting_level_ + 1; | 132 run_nesting_level_ = nesting_level_ + 1; |
133 | 133 |
134 Delegate* last_delegate = delegate_; | 134 Delegate* last_delegate = delegate_; |
135 delegate_ = delegate; | 135 delegate_ = delegate; |
136 | 136 |
137 // If any work showed up but could not be dispatched for want of a delegate, | 137 if (delegate) { |
138 // set it up for dispatch again now that a delegate is available. | 138 // If any work showed up but could not be dispatched for want of a |
139 if (delegateless_work_) { | 139 // delegate, set it up for dispatch again now that a delegate is |
140 CFRunLoopSourceSignal(work_source_); | 140 // available. |
141 delegateless_work_ = false; | 141 if (delegateless_work_) { |
142 } | 142 CFRunLoopSourceSignal(work_source_); |
143 if (delegateless_delayed_work_) { | 143 delegateless_work_ = false; |
144 CFRunLoopSourceSignal(delayed_work_source_); | 144 } |
145 delegateless_delayed_work_ = false; | 145 if (delegateless_delayed_work_) { |
146 } | 146 CFRunLoopSourceSignal(delayed_work_source_); |
147 if (delegateless_idle_work_) { | 147 delegateless_delayed_work_ = false; |
148 CFRunLoopSourceSignal(idle_work_source_); | 148 } |
149 delegateless_idle_work_ = false; | 149 if (delegateless_idle_work_) { |
| 150 CFRunLoopSourceSignal(idle_work_source_); |
| 151 delegateless_idle_work_ = false; |
| 152 } |
150 } | 153 } |
151 | 154 |
152 DoRun(delegate); | 155 DoRun(delegate); |
153 | 156 |
154 // If this was an inner Run invocation, arrange to run nesting-deferred work | |
155 // when the stack has unwound to an outer invocation. | |
156 if (nesting_level_) | |
157 CFRunLoopSourceSignal(nesting_deferred_work_source_); | |
158 | |
159 // Restore the previous state of the object. | 157 // Restore the previous state of the object. |
160 delegate_ = last_delegate; | 158 delegate_ = last_delegate; |
161 run_nesting_level_ = last_run_nesting_level; | 159 run_nesting_level_ = last_run_nesting_level; |
162 } | 160 } |
163 | 161 |
164 // May be called on any thread. | 162 // May be called on any thread. |
165 void MessagePumpCFRunLoopBase::ScheduleWork() { | 163 void MessagePumpCFRunLoopBase::ScheduleWork() { |
166 CFRunLoopSourceSignal(work_source_); | 164 CFRunLoopSourceSignal(work_source_); |
167 CFRunLoopWakeUp(run_loop_); | 165 CFRunLoopWakeUp(run_loop_); |
168 } | 166 } |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
213 // Called by MessagePumpCFRunLoopBase::RunWorkSource. | 211 // Called by MessagePumpCFRunLoopBase::RunWorkSource. |
214 bool MessagePumpCFRunLoopBase::RunWork() { | 212 bool MessagePumpCFRunLoopBase::RunWork() { |
215 if (!delegate_) { | 213 if (!delegate_) { |
216 // This point can be reached with a NULL delegate_ if Run is not on the | 214 // This point can be reached with a NULL delegate_ if Run is not on the |
217 // stack but foreign code is spinning the CFRunLoop. Arrange to come back | 215 // stack but foreign code is spinning the CFRunLoop. Arrange to come back |
218 // here when a delegate is available. | 216 // here when a delegate is available. |
219 delegateless_work_ = true; | 217 delegateless_work_ = true; |
220 return false; | 218 return false; |
221 } | 219 } |
222 | 220 |
223 // If we're on the main event loop, the NSApp runloop won't clean up the | 221 // The NSApplication-based run loop only drains the autorelease pool at each |
224 // autorelease pool until there is a UI event, so use a local one for any | 222 // UI event (NSEvent). The autorelease pool is not drained for each |
225 // autoreleased objects to ensure they go away sooner. | 223 // CFRunLoopSource target that's run. Use a local pool for any autoreleased |
| 224 // objects to ensure they're released promptly even in the absence of UI |
| 225 // events. |
226 ScopedNSAutoreleasePool autorelease_pool; | 226 ScopedNSAutoreleasePool autorelease_pool; |
227 | 227 |
228 // Call DoWork once, and if something was done, arrange to come back here | 228 // Call DoWork once, and if something was done, arrange to come back here |
229 // again as long as the loop is still running. | 229 // again as long as the loop is still running. |
230 bool did_work = delegate_->DoWork(); | 230 bool did_work = delegate_->DoWork(); |
231 if (did_work) { | 231 if (did_work) { |
232 CFRunLoopSourceSignal(work_source_); | 232 CFRunLoopSourceSignal(work_source_); |
233 } | 233 } |
234 | 234 |
235 return did_work; | 235 return did_work; |
236 } | 236 } |
237 | 237 |
238 // Called from the run loop. | 238 // Called from the run loop. |
239 // static | 239 // static |
240 void MessagePumpCFRunLoopBase::RunDelayedWorkSource(void* info) { | 240 void MessagePumpCFRunLoopBase::RunDelayedWorkSource(void* info) { |
241 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info); | 241 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info); |
242 self->RunDelayedWork(); | 242 self->RunDelayedWork(); |
243 } | 243 } |
244 | 244 |
245 // Called by MessagePumpCFRunLoopBase::RunDelayedWorkSource. | 245 // Called by MessagePumpCFRunLoopBase::RunDelayedWorkSource. |
246 bool MessagePumpCFRunLoopBase::RunDelayedWork() { | 246 bool MessagePumpCFRunLoopBase::RunDelayedWork() { |
247 if (!delegate_) { | 247 if (!delegate_) { |
248 // This point can be reached with a NULL delegate_ if Run is not on the | 248 // This point can be reached with a NULL delegate_ if Run is not on the |
249 // stack but foreign code is spinning the CFRunLoop. Arrange to come back | 249 // stack but foreign code is spinning the CFRunLoop. Arrange to come back |
250 // here when a delegate is available. | 250 // here when a delegate is available. |
251 delegateless_delayed_work_ = true; | 251 delegateless_delayed_work_ = true; |
252 return false; | 252 return false; |
253 } | 253 } |
254 | 254 |
255 // If we're on the main event loop, the NSApp runloop won't clean up the | 255 // The NSApplication-based run loop only drains the autorelease pool at each |
256 // autorelease pool until there is a UI event, so use a local one for any | 256 // UI event (NSEvent). The autorelease pool is not drained for each |
257 // autoreleased objects to ensure they go away sooner. | 257 // CFRunLoopSource target that's run. Use a local pool for any autoreleased |
| 258 // objects to ensure they're released promptly even in the absence of UI |
| 259 // events. |
258 ScopedNSAutoreleasePool autorelease_pool; | 260 ScopedNSAutoreleasePool autorelease_pool; |
259 | 261 |
260 Time next_time; | 262 Time next_time; |
261 delegate_->DoDelayedWork(&next_time); | 263 delegate_->DoDelayedWork(&next_time); |
262 | 264 |
263 bool more_work = !next_time.is_null(); | 265 bool more_work = !next_time.is_null(); |
264 if (more_work) { | 266 if (more_work) { |
265 TimeDelta delay = next_time - Time::Now(); | 267 TimeDelta delay = next_time - Time::Now(); |
266 if (delay > TimeDelta()) { | 268 if (delay > TimeDelta()) { |
267 // There's more delayed work to be done in the future. | 269 // There's more delayed work to be done in the future. |
(...skipping 19 matching lines...) Expand all Loading... |
287 // Called by MessagePumpCFRunLoopBase::RunIdleWorkSource. | 289 // Called by MessagePumpCFRunLoopBase::RunIdleWorkSource. |
288 bool MessagePumpCFRunLoopBase::RunIdleWork() { | 290 bool MessagePumpCFRunLoopBase::RunIdleWork() { |
289 if (!delegate_) { | 291 if (!delegate_) { |
290 // This point can be reached with a NULL delegate_ if Run is not on the | 292 // This point can be reached with a NULL delegate_ if Run is not on the |
291 // stack but foreign code is spinning the CFRunLoop. Arrange to come back | 293 // stack but foreign code is spinning the CFRunLoop. Arrange to come back |
292 // here when a delegate is available. | 294 // here when a delegate is available. |
293 delegateless_idle_work_ = true; | 295 delegateless_idle_work_ = true; |
294 return false; | 296 return false; |
295 } | 297 } |
296 | 298 |
297 // If we're on the main event loop, the NSApp runloop won't clean up the | 299 // The NSApplication-based run loop only drains the autorelease pool at each |
298 // autorelease pool until there is a UI event, so use a local one for any | 300 // UI event (NSEvent). The autorelease pool is not drained for each |
299 // autoreleased objects to ensure they go away sooner. | 301 // CFRunLoopSource target that's run. Use a local pool for any autoreleased |
| 302 // objects to ensure they're released promptly even in the absence of UI |
| 303 // events. |
300 ScopedNSAutoreleasePool autorelease_pool; | 304 ScopedNSAutoreleasePool autorelease_pool; |
301 | 305 |
302 // Call DoIdleWork once, and if something was done, arrange to come back here | 306 // Call DoIdleWork once, and if something was done, arrange to come back here |
303 // again as long as the loop is still running. | 307 // again as long as the loop is still running. |
304 bool did_work = delegate_->DoIdleWork(); | 308 bool did_work = delegate_->DoIdleWork(); |
305 if (did_work) { | 309 if (did_work) { |
306 CFRunLoopSourceSignal(idle_work_source_); | 310 CFRunLoopSourceSignal(idle_work_source_); |
307 } | 311 } |
308 | 312 |
309 return did_work; | 313 return did_work; |
(...skipping 30 matching lines...) Expand all Loading... |
340 } else { | 344 } else { |
341 // Work was done. Arrange for the loop to try non-nestable delayed and | 345 // Work was done. Arrange for the loop to try non-nestable delayed and |
342 // idle work on a subsequent pass. | 346 // idle work on a subsequent pass. |
343 CFRunLoopSourceSignal(delayed_work_source_); | 347 CFRunLoopSourceSignal(delayed_work_source_); |
344 CFRunLoopSourceSignal(idle_work_source_); | 348 CFRunLoopSourceSignal(idle_work_source_); |
345 } | 349 } |
346 | 350 |
347 return true; | 351 return true; |
348 } | 352 } |
349 | 353 |
| 354 // Called before the run loop goes to sleep or exits. |
| 355 void MessagePumpCFRunLoopBase::MaybeScheduleNestingDeferredWork() { |
| 356 // deepest_nesting_level_ is set as run loops are entered. If the deepest |
| 357 // level encountered is deeper than the current level (about to sleep or |
| 358 // exit), a nested loop (relative to the current level) ran since the last |
| 359 // time nesting-deferred work was scheduled. When that situation is |
| 360 // encountered, schedule nesting-deferred work in case any work was deferred |
| 361 // because nested work was disallowed. |
| 362 if (deepest_nesting_level_ > nesting_level_) { |
| 363 deepest_nesting_level_ = nesting_level_; |
| 364 CFRunLoopSourceSignal(nesting_deferred_work_source_); |
| 365 } |
| 366 } |
| 367 |
350 // Called from the run loop. | 368 // Called from the run loop. |
351 // static | 369 // static |
352 void MessagePumpCFRunLoopBase::PreWaitObserver(CFRunLoopObserverRef observer, | 370 void MessagePumpCFRunLoopBase::PreWaitObserver(CFRunLoopObserverRef observer, |
353 CFRunLoopActivity activity, | 371 CFRunLoopActivity activity, |
354 void* info) { | 372 void* info) { |
355 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info); | 373 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info); |
356 | 374 |
357 // Attempt to do some idle work before going to sleep. | 375 // Attempt to do some idle work before going to sleep. |
358 self->RunIdleWork(); | 376 self->RunIdleWork(); |
| 377 |
| 378 // The run loop is about to go to sleep. If any of the work done since it |
| 379 // started or woke up resulted in a nested run loop running, |
| 380 // nesting-deferred work may have accumulated. Schedule it for processing |
| 381 // if appropriate. |
| 382 self->MaybeScheduleNestingDeferredWork(); |
359 } | 383 } |
360 | 384 |
361 // Called from the run loop. | 385 // Called from the run loop. |
362 // static | 386 // static |
363 void MessagePumpCFRunLoopBase::EnterExitObserver(CFRunLoopObserverRef observer, | 387 void MessagePumpCFRunLoopBase::EnterExitObserver(CFRunLoopObserverRef observer, |
364 CFRunLoopActivity activity, | 388 CFRunLoopActivity activity, |
365 void* info) { | 389 void* info) { |
366 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info); | 390 MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info); |
367 | 391 |
368 switch (activity) { | 392 switch (activity) { |
369 case kCFRunLoopEntry: | 393 case kCFRunLoopEntry: |
370 ++self->nesting_level_; | 394 ++self->nesting_level_; |
| 395 if (self->nesting_level_ > self->deepest_nesting_level_) { |
| 396 self->deepest_nesting_level_ = self->nesting_level_; |
| 397 } |
371 break; | 398 break; |
372 case kCFRunLoopExit: | 399 case kCFRunLoopExit: |
373 // After decrementing self->nesting_level_, it will be one less than | 400 // Not all run loops go to sleep. If a run loop is stopped before it |
374 // self->run_nesting_level_ if the loop that is now exiting was directly | 401 // goes to sleep due to a CFRunLoopStop call, or if the timeout passed |
375 // started by a DoRun call. | 402 // to CFRunLoopRunInMode expires, the run loop may proceed directly from |
| 403 // handling sources to exiting without any sleep. This most commonly |
| 404 // occurs when CFRunLoopRunInMode is passed a timeout of 0, causing it |
| 405 // to make a single pass through the loop and exit without sleep. Some |
| 406 // native loops use CFRunLoop in this way. Because PreWaitObserver will |
| 407 // not be called in these case, MaybeScheduleNestingDeferredWork needs |
| 408 // to be called here, as the run loop exits. |
| 409 // |
| 410 // MaybeScheduleNestingDeferredWork consults self->nesting_level_ |
| 411 // to determine whether to schedule nesting-deferred work. It expects |
| 412 // the nesting level to be set to the depth of the loop that is going |
| 413 // to sleep or exiting. It must be called before decrementing the |
| 414 // value so that the value still corresponds to the level of the exiting |
| 415 // loop. |
| 416 self->MaybeScheduleNestingDeferredWork(); |
376 --self->nesting_level_; | 417 --self->nesting_level_; |
377 | |
378 if (self->nesting_level_ >= self->run_nesting_level_ && | |
379 self->nesting_level_) { | |
380 // It's possible that some work was not performed because it was | |
381 // inappropriate to do within a nested loop. When leaving any inner | |
382 // loop not directly supervised by a DoRun call, such as nested native | |
383 // loops, signal the nesting-deferred work source to ensure that such | |
384 // work be afforded an opportunity to be processed if appropriate. | |
385 // This is not done for loops being run directly by Run/DoRun because | |
386 // it can be done directly as Run exits. | |
387 CFRunLoopSourceSignal(self->nesting_deferred_work_source_); | |
388 } | |
389 break; | 418 break; |
390 default: | 419 default: |
391 break; | 420 break; |
392 } | 421 } |
393 | 422 |
394 self->EnterExitRunLoop(activity); | 423 self->EnterExitRunLoop(activity); |
395 } | 424 } |
396 | 425 |
397 // Called by MessagePumpCFRunLoopBase::EnterExitRunLoop. The default | 426 // Called by MessagePumpCFRunLoopBase::EnterExitRunLoop. The default |
398 // implementation is a no-op. | 427 // implementation is a no-op. |
(...skipping 14 matching lines...) Expand all Loading... |
413 int result; | 442 int result; |
414 do { | 443 do { |
415 ScopedNSAutoreleasePool autorelease_pool; | 444 ScopedNSAutoreleasePool autorelease_pool; |
416 result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, DBL_MAX, false); | 445 result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, DBL_MAX, false); |
417 } while (result != kCFRunLoopRunStopped && result != kCFRunLoopRunFinished); | 446 } while (result != kCFRunLoopRunStopped && result != kCFRunLoopRunFinished); |
418 } | 447 } |
419 | 448 |
420 // Must be called on the run loop thread. | 449 // Must be called on the run loop thread. |
421 void MessagePumpCFRunLoop::Quit() { | 450 void MessagePumpCFRunLoop::Quit() { |
422 // Stop the innermost run loop managed by this MessagePumpCFRunLoop object. | 451 // Stop the innermost run loop managed by this MessagePumpCFRunLoop object. |
423 if (nesting_level_ == run_nesting_level_) { | 452 if (nesting_level() == run_nesting_level()) { |
424 // This object is running the innermost loop, just stop it. | 453 // This object is running the innermost loop, just stop it. |
425 CFRunLoopStop(run_loop_); | 454 CFRunLoopStop(run_loop()); |
426 } else { | 455 } else { |
427 // There's another loop running inside the loop managed by this object. | 456 // There's another loop running inside the loop managed by this object. |
428 // In other words, someone else called CFRunLoopRun on the same thread, | 457 // In other words, someone else called CFRunLoopRunInMode on the same |
429 // higher on the stack than our highest Run call. Don't preempt other | 458 // thread, deeper on the stack than the deepest Run call. Don't preempt |
430 // run loops, just mark the object to quit our innermost run loop as soon | 459 // other run loops, just mark this object to quit the innermost Run as |
431 // as the other inner loops we don't manage are done. | 460 // soon as the other inner loops not managed by Run are done. |
432 quit_pending_ = true; | 461 quit_pending_ = true; |
433 } | 462 } |
434 } | 463 } |
435 | 464 |
436 // Called by MessagePumpCFRunLoopBase::EnterExitObserver. | 465 // Called by MessagePumpCFRunLoopBase::EnterExitObserver. |
437 void MessagePumpCFRunLoop::EnterExitRunLoop(CFRunLoopActivity activity) { | 466 void MessagePumpCFRunLoop::EnterExitRunLoop(CFRunLoopActivity activity) { |
438 if (activity == kCFRunLoopExit && | 467 if (activity == kCFRunLoopExit && |
439 nesting_level_ == run_nesting_level_ && | 468 nesting_level() == run_nesting_level() && |
440 quit_pending_) { | 469 quit_pending_) { |
441 // Quit was called while loops other than those managed by this object | 470 // Quit was called while loops other than those managed by this object |
442 // were running further inside a run loop managed by this object. Now | 471 // were running further inside a run loop managed by this object. Now |
443 // that all unmanaged inner run loops are gone, stop the loop running | 472 // that all unmanaged inner run loops are gone, stop the loop running |
444 // just inside Run. | 473 // just inside Run. |
445 CFRunLoopStop(run_loop_); | 474 CFRunLoopStop(run_loop()); |
446 quit_pending_ = false; | 475 quit_pending_ = false; |
447 } | 476 } |
448 } | 477 } |
449 | 478 |
450 MessagePumpNSRunLoop::MessagePumpNSRunLoop() | 479 MessagePumpNSRunLoop::MessagePumpNSRunLoop() |
451 : keep_running_(true) { | 480 : keep_running_(true) { |
452 CFRunLoopSourceContext source_context = CFRunLoopSourceContext(); | 481 CFRunLoopSourceContext source_context = CFRunLoopSourceContext(); |
453 source_context.perform = NoOp; | 482 source_context.perform = NoOp; |
454 quit_source_ = CFRunLoopSourceCreate(NULL, // allocator | 483 quit_source_ = CFRunLoopSourceCreate(NULL, // allocator |
455 0, // priority | 484 0, // priority |
456 &source_context); | 485 &source_context); |
457 CFRunLoopAddSource(run_loop_, quit_source_, kCFRunLoopCommonModes); | 486 CFRunLoopAddSource(run_loop(), quit_source_, kCFRunLoopCommonModes); |
458 } | 487 } |
459 | 488 |
460 MessagePumpNSRunLoop::~MessagePumpNSRunLoop() { | 489 MessagePumpNSRunLoop::~MessagePumpNSRunLoop() { |
461 CFRunLoopRemoveSource(run_loop_, quit_source_, kCFRunLoopCommonModes); | 490 CFRunLoopRemoveSource(run_loop(), quit_source_, kCFRunLoopCommonModes); |
462 CFRelease(quit_source_); | 491 CFRelease(quit_source_); |
463 } | 492 } |
464 | 493 |
465 void MessagePumpNSRunLoop::DoRun(Delegate* delegate) { | 494 void MessagePumpNSRunLoop::DoRun(Delegate* delegate) { |
466 while (keep_running_) { | 495 while (keep_running_) { |
467 // NSRunLoop manages autorelease pools itself. | 496 // NSRunLoop manages autorelease pools itself. |
468 [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode | 497 [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode |
469 beforeDate:[NSDate distantFuture]]; | 498 beforeDate:[NSDate distantFuture]]; |
470 } | 499 } |
471 | 500 |
472 keep_running_ = true; | 501 keep_running_ = true; |
473 } | 502 } |
474 | 503 |
475 void MessagePumpNSRunLoop::Quit() { | 504 void MessagePumpNSRunLoop::Quit() { |
476 keep_running_ = false; | 505 keep_running_ = false; |
477 CFRunLoopSourceSignal(quit_source_); | 506 CFRunLoopSourceSignal(quit_source_); |
478 CFRunLoopWakeUp(run_loop_); | 507 CFRunLoopWakeUp(run_loop()); |
479 } | 508 } |
480 | 509 |
481 MessagePumpNSApplication::MessagePumpNSApplication() | 510 MessagePumpNSApplication::MessagePumpNSApplication() |
482 : keep_running_(true), | 511 : keep_running_(true), |
483 running_own_loop_(false) { | 512 running_own_loop_(false) { |
484 } | 513 } |
485 | 514 |
486 void MessagePumpNSApplication::DoRun(Delegate* delegate) { | 515 void MessagePumpNSApplication::DoRun(Delegate* delegate) { |
487 bool last_running_own_loop_ = running_own_loop_; | 516 bool last_running_own_loop_ = running_own_loop_; |
488 | 517 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
533 // static | 562 // static |
534 MessagePump* MessagePumpMac::Create() { | 563 MessagePump* MessagePumpMac::Create() { |
535 if ([NSThread isMainThread]) { | 564 if ([NSThread isMainThread]) { |
536 return new MessagePumpNSApplication; | 565 return new MessagePumpNSApplication; |
537 } | 566 } |
538 | 567 |
539 return new MessagePumpNSRunLoop; | 568 return new MessagePumpNSRunLoop; |
540 } | 569 } |
541 | 570 |
542 } // namespace base | 571 } // namespace base |
OLD | NEW |