| Index: base/message_loop/message_pump_mac.mm
|
| diff --git a/base/message_loop/message_pump_mac.mm b/base/message_loop/message_pump_mac.mm
|
| index 0ab9ab7c467de5128be33444db018ce73d369f7d..205bd3e2f229c6c424fe55bc584fb21a3bfbfc06 100644
|
| --- a/base/message_loop/message_pump_mac.mm
|
| +++ b/base/message_loop/message_pump_mac.mm
|
| @@ -553,10 +553,40 @@ bool MessagePumpCFRunLoopBase::RunWork() {
|
| // released promptly even in the absence of UI events.
|
| MessagePumpScopedAutoreleasePool autorelease_pool(this);
|
|
|
| - // Call DoWork and DoDelayedWork once, and if something was done, arrange to
|
| - // come back here again as long as the loop is still running.
|
| - bool did_work = delegate_->DoWork();
|
| - bool resignal_work_source = did_work;
|
| + // Allocate a time slice in which as many tasks as possible will be run.
|
| + // Performing only one task per run loop tick is potentially inefficient in
|
| + // the face of a large backlog of pending tasks. https://crbug.com/264886
|
| + base::TimeTicks now = base::TimeTicks::Now();
|
| + base::TimeTicks time_slice_end = now + base::TimeDelta::FromMilliseconds(50);
|
| + int ran_task_count = 0;
|
| + bool did_work = false, did_work_last_slice = true;
|
| + for ( ;
|
| + now < time_slice_end && did_work_last_slice;
|
| + now = base::TimeTicks::Now()) {
|
| + quit_was_called_ = false;
|
| + did_work_last_slice = delegate_->DoWork();
|
| + did_work |= did_work_last_slice;
|
| + if (quit_was_called_)
|
| + break;
|
| + if (did_work_last_slice)
|
| + ++ran_task_count;
|
| + }
|
| +
|
| + // Record how many tasks were accomplished in the time slice, and by how
|
| + // much the work overran the time slice deadline.
|
| + UMA_HISTOGRAM_CUSTOM_TIMES("MessagePumpMac.TimeSliceOverRun",
|
| + time_slice_end - base::TimeTicks::Now(),
|
| + base::TimeDelta::FromMilliseconds(1),
|
| + base::TimeDelta::FromSeconds(5),
|
| + 100);
|
| + UMA_HISTOGRAM_COUNTS("MessagePumpMac.TimeSliceTaskCount", ran_task_count);
|
| +
|
| + if (quit_was_called_)
|
| + return false;
|
| +
|
| + // If the time slice expired and work was done in the last fraction of the
|
| + // time slice, arrange to come back here to execute more tasks.
|
| + bool resignal_work_source = did_work_last_slice;
|
|
|
| TimeTicks next_time;
|
| delegate_->DoDelayedWork(&next_time);
|
| @@ -795,6 +825,7 @@ void MessagePumpCFRunLoop::DoRun(Delegate* delegate) {
|
|
|
| // Must be called on the run loop thread.
|
| void MessagePumpCFRunLoop::Quit() {
|
| + quit_was_called_ = true;
|
| // Stop the innermost run loop managed by this MessagePumpCFRunLoop object.
|
| if (nesting_level() == run_nesting_level()) {
|
| // This object is running the innermost loop, just stop it.
|
| @@ -849,6 +880,7 @@ void MessagePumpNSRunLoop::DoRun(Delegate* delegate) {
|
| }
|
|
|
| void MessagePumpNSRunLoop::Quit() {
|
| + quit_was_called_ = true;
|
| keep_running_ = false;
|
| CFRunLoopSourceSignal(quit_source_);
|
| CFRunLoopWakeUp(run_loop());
|
| @@ -923,6 +955,7 @@ void MessagePumpNSApplication::DoRun(Delegate* delegate) {
|
| }
|
|
|
| void MessagePumpNSApplication::Quit() {
|
| + quit_was_called_ = true;
|
| if (!running_own_loop_) {
|
| [[NSApplication sharedApplication] stop:nil];
|
| } else {
|
|
|