| 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 |