| Index: base/message_pump_mac.mm
|
| ===================================================================
|
| --- base/message_pump_mac.mm (revision 28751)
|
| +++ base/message_pump_mac.mm (working copy)
|
| @@ -23,6 +23,7 @@
|
| // Must be called on the run loop thread.
|
| MessagePumpCFRunLoopBase::MessagePumpCFRunLoopBase()
|
| : nesting_level_(0),
|
| + run_nesting_level_(0),
|
| delegate_(NULL),
|
| delegateless_work_(false),
|
| delegateless_delayed_work_(false),
|
| @@ -125,6 +126,11 @@
|
|
|
| // Must be called on the run loop thread.
|
| void MessagePumpCFRunLoopBase::Run(Delegate* delegate) {
|
| + // nesting_level_ will be incremented in EnterExitRunLoop, so set
|
| + // run_nesting_level_ accordingly.
|
| + int last_run_nesting_level = run_nesting_level_;
|
| + run_nesting_level_ = nesting_level_ + 1;
|
| +
|
| Delegate* last_delegate = delegate_;
|
| delegate_ = delegate;
|
|
|
| @@ -145,7 +151,14 @@
|
|
|
| DoRun(delegate);
|
|
|
| + // If this was an inner Run invocation, arrange to run nesting-deferred work
|
| + // when the stack has unwound to an outer invocation.
|
| + if (nesting_level_)
|
| + CFRunLoopSourceSignal(nesting_deferred_work_source_);
|
| +
|
| + // Restore the previous state of the object.
|
| delegate_ = last_delegate;
|
| + run_nesting_level_ = last_run_nesting_level;
|
| }
|
|
|
| // May be called on any thread.
|
| @@ -357,12 +370,20 @@
|
| ++self->nesting_level_;
|
| break;
|
| case kCFRunLoopExit:
|
| + // After decrementing self->nesting_level_, it will be one less than
|
| + // self->run_nesting_level_ if the loop that is now exiting was directly
|
| + // started by a DoRun call.
|
| --self->nesting_level_;
|
| - if (self->nesting_level_) {
|
| +
|
| + if (self->nesting_level_ >= self->run_nesting_level_ &&
|
| + self->nesting_level_) {
|
| // It's possible that some work was not performed because it was
|
| // inappropriate to do within a nested loop. When leaving any inner
|
| - // loop, signal the nesting-deferred work source to ensure that such
|
| + // loop not directly supervised by a DoRun call, such as nested native
|
| + // loops, signal the nesting-deferred work source to ensure that such
|
| // work be afforded an opportunity to be processed if appropriate.
|
| + // This is not done for loops being run directly by Run/DoRun because
|
| + // it can be done directly as Run exits.
|
| CFRunLoopSourceSignal(self->nesting_deferred_work_source_);
|
| }
|
| break;
|
| @@ -379,8 +400,7 @@
|
| }
|
|
|
| MessagePumpCFRunLoop::MessagePumpCFRunLoop()
|
| - : innermost_quittable_(0),
|
| - quit_pending_(false) {
|
| + : quit_pending_(false) {
|
| }
|
|
|
| // Called by MessagePumpCFRunLoopBase::DoRun. If other CFRunLoopRun loops were
|
| @@ -388,11 +408,6 @@
|
| // the same number of CFRunLoopRun loops must be running for the outermost call
|
| // to Run. Run/DoRun are reentrant after that point.
|
| void MessagePumpCFRunLoop::DoRun(Delegate* delegate) {
|
| - // nesting_level_ will be incremented in EnterExitRunLoop, so set
|
| - // innermost_quittable_ accordingly.
|
| - int last_innermost_quittable = innermost_quittable_;
|
| - innermost_quittable_ = nesting_level_ + 1;
|
| -
|
| // This is completely identical to calling CFRunLoopRun(), except autorelease
|
| // pool management is introduced.
|
| int result;
|
| @@ -400,15 +415,12 @@
|
| ScopedNSAutoreleasePool autorelease_pool;
|
| result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, DBL_MAX, false);
|
| } while (result != kCFRunLoopRunStopped && result != kCFRunLoopRunFinished);
|
| -
|
| - // Restore the previous state of the object.
|
| - innermost_quittable_ = last_innermost_quittable;
|
| }
|
|
|
| // Must be called on the run loop thread.
|
| void MessagePumpCFRunLoop::Quit() {
|
| // Stop the innermost run loop managed by this MessagePumpCFRunLoop object.
|
| - if (nesting_level_ == innermost_quittable_) {
|
| + if (nesting_level_ == run_nesting_level_) {
|
| // This object is running the innermost loop, just stop it.
|
| CFRunLoopStop(run_loop_);
|
| } else {
|
| @@ -424,7 +436,7 @@
|
| // Called by MessagePumpCFRunLoopBase::EnterExitObserver.
|
| void MessagePumpCFRunLoop::EnterExitRunLoop(CFRunLoopActivity activity) {
|
| if (activity == kCFRunLoopExit &&
|
| - nesting_level_ == innermost_quittable_ &&
|
| + nesting_level_ == run_nesting_level_ &&
|
| quit_pending_) {
|
| // Quit was called while loops other than those managed by this object
|
| // were running further inside a run loop managed by this object. Now
|
|
|