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

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

Issue 20803005: [Mac] Execute as many MessageLoop tasks as possible. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Hacks for Quit() Created 6 years, 5 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 | Annotate | Revision Log
« no previous file with comments | « base/message_loop/message_pump_mac.h ('k') | tools/metrics/histograms/histograms.xml » ('j') | 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 #include <dlfcn.h> 7 #include <dlfcn.h>
8 #import <Foundation/Foundation.h> 8 #import <Foundation/Foundation.h>
9 9
10 #include <limits> 10 #include <limits>
(...skipping 535 matching lines...) Expand 10 before | Expand all | Expand 10 after
546 if (instrumentation_) 546 if (instrumentation_)
547 instrumentation_->WorkSourceEntered(delegate_); 547 instrumentation_->WorkSourceEntered(delegate_);
548 548
549 // The NSApplication-based run loop only drains the autorelease pool at each 549 // The NSApplication-based run loop only drains the autorelease pool at each
550 // UI event (NSEvent). The autorelease pool is not drained for each 550 // UI event (NSEvent). The autorelease pool is not drained for each
551 // CFRunLoopSource target that's run. Use a local pool for any autoreleased 551 // CFRunLoopSource target that's run. Use a local pool for any autoreleased
552 // objects if the app is not currently handling a UI event to ensure they're 552 // objects if the app is not currently handling a UI event to ensure they're
553 // released promptly even in the absence of UI events. 553 // released promptly even in the absence of UI events.
554 MessagePumpScopedAutoreleasePool autorelease_pool(this); 554 MessagePumpScopedAutoreleasePool autorelease_pool(this);
555 555
556 // Call DoWork and DoDelayedWork once, and if something was done, arrange to 556 // Allocate a time slice in which as many tasks as possible will be run.
557 // come back here again as long as the loop is still running. 557 // Performing only one task per run loop tick is potentially inefficient in
558 bool did_work = delegate_->DoWork(); 558 // the face of a large backlog of pending tasks. https://crbug.com/264886
559 bool resignal_work_source = did_work; 559 base::TimeTicks now = base::TimeTicks::Now();
560 base::TimeTicks time_slice_end = now + base::TimeDelta::FromMilliseconds(50);
561 int ran_task_count = 0;
562 bool did_work = false, did_work_last_slice = true;
563 for ( ;
564 now < time_slice_end && did_work_last_slice;
565 now = base::TimeTicks::Now()) {
566 quit_was_called_ = false;
567 did_work_last_slice = delegate_->DoWork();
568 did_work |= did_work_last_slice;
569 if (quit_was_called_)
570 break;
571 if (did_work_last_slice)
572 ++ran_task_count;
573 }
574
575 // Record how many tasks were accomplished in the time slice, and by how
576 // much the work overran the time slice deadline.
577 UMA_HISTOGRAM_CUSTOM_TIMES("MessagePumpMac.TimeSliceOverRun",
578 time_slice_end - base::TimeTicks::Now(),
579 base::TimeDelta::FromMilliseconds(1),
580 base::TimeDelta::FromSeconds(5),
581 100);
582 UMA_HISTOGRAM_COUNTS("MessagePumpMac.TimeSliceTaskCount", ran_task_count);
583
584 if (quit_was_called_)
585 return false;
586
587 // If the time slice expired and work was done in the last fraction of the
588 // time slice, arrange to come back here to execute more tasks.
589 bool resignal_work_source = did_work_last_slice;
560 590
561 TimeTicks next_time; 591 TimeTicks next_time;
562 delegate_->DoDelayedWork(&next_time); 592 delegate_->DoDelayedWork(&next_time);
563 if (!did_work) { 593 if (!did_work) {
564 // Determine whether there's more delayed work, and if so, if it needs to 594 // Determine whether there's more delayed work, and if so, if it needs to
565 // be done at some point in the future or if it's already time to do it. 595 // be done at some point in the future or if it's already time to do it.
566 // Only do these checks if did_work is false. If did_work is true, this 596 // Only do these checks if did_work is false. If did_work is true, this
567 // function, and therefore any additional delayed work, will get another 597 // function, and therefore any additional delayed work, will get another
568 // chance to run before the loop goes to sleep. 598 // chance to run before the loop goes to sleep.
569 bool more_delayed_work = !next_time.is_null(); 599 bool more_delayed_work = !next_time.is_null();
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after
788 do { 818 do {
789 MessagePumpScopedAutoreleasePool autorelease_pool(this); 819 MessagePumpScopedAutoreleasePool autorelease_pool(this);
790 result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 820 result = CFRunLoopRunInMode(kCFRunLoopDefaultMode,
791 kCFTimeIntervalMax, 821 kCFTimeIntervalMax,
792 false); 822 false);
793 } while (result != kCFRunLoopRunStopped && result != kCFRunLoopRunFinished); 823 } while (result != kCFRunLoopRunStopped && result != kCFRunLoopRunFinished);
794 } 824 }
795 825
796 // Must be called on the run loop thread. 826 // Must be called on the run loop thread.
797 void MessagePumpCFRunLoop::Quit() { 827 void MessagePumpCFRunLoop::Quit() {
828 quit_was_called_ = true;
798 // Stop the innermost run loop managed by this MessagePumpCFRunLoop object. 829 // Stop the innermost run loop managed by this MessagePumpCFRunLoop object.
799 if (nesting_level() == run_nesting_level()) { 830 if (nesting_level() == run_nesting_level()) {
800 // This object is running the innermost loop, just stop it. 831 // This object is running the innermost loop, just stop it.
801 CFRunLoopStop(run_loop()); 832 CFRunLoopStop(run_loop());
802 } else { 833 } else {
803 // There's another loop running inside the loop managed by this object. 834 // There's another loop running inside the loop managed by this object.
804 // In other words, someone else called CFRunLoopRunInMode on the same 835 // In other words, someone else called CFRunLoopRunInMode on the same
805 // thread, deeper on the stack than the deepest Run call. Don't preempt 836 // thread, deeper on the stack than the deepest Run call. Don't preempt
806 // other run loops, just mark this object to quit the innermost Run as 837 // other run loops, just mark this object to quit the innermost Run as
807 // soon as the other inner loops not managed by Run are done. 838 // soon as the other inner loops not managed by Run are done.
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
842 while (keep_running_) { 873 while (keep_running_) {
843 // NSRunLoop manages autorelease pools itself. 874 // NSRunLoop manages autorelease pools itself.
844 [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode 875 [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
845 beforeDate:[NSDate distantFuture]]; 876 beforeDate:[NSDate distantFuture]];
846 } 877 }
847 878
848 keep_running_ = true; 879 keep_running_ = true;
849 } 880 }
850 881
851 void MessagePumpNSRunLoop::Quit() { 882 void MessagePumpNSRunLoop::Quit() {
883 quit_was_called_ = true;
852 keep_running_ = false; 884 keep_running_ = false;
853 CFRunLoopSourceSignal(quit_source_); 885 CFRunLoopSourceSignal(quit_source_);
854 CFRunLoopWakeUp(run_loop()); 886 CFRunLoopWakeUp(run_loop());
855 } 887 }
856 888
857 #if defined(OS_IOS) 889 #if defined(OS_IOS)
858 MessagePumpUIApplication::MessagePumpUIApplication() 890 MessagePumpUIApplication::MessagePumpUIApplication()
859 : run_loop_(NULL) { 891 : run_loop_(NULL) {
860 } 892 }
861 893
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
916 [NSApp sendEvent:event]; 948 [NSApp sendEvent:event];
917 } 949 }
918 } 950 }
919 keep_running_ = true; 951 keep_running_ = true;
920 } 952 }
921 953
922 running_own_loop_ = last_running_own_loop_; 954 running_own_loop_ = last_running_own_loop_;
923 } 955 }
924 956
925 void MessagePumpNSApplication::Quit() { 957 void MessagePumpNSApplication::Quit() {
958 quit_was_called_ = true;
926 if (!running_own_loop_) { 959 if (!running_own_loop_) {
927 [[NSApplication sharedApplication] stop:nil]; 960 [[NSApplication sharedApplication] stop:nil];
928 } else { 961 } else {
929 keep_running_ = false; 962 keep_running_ = false;
930 } 963 }
931 964
932 // Send a fake event to wake the loop up. 965 // Send a fake event to wake the loop up.
933 [NSApp postEvent:[NSEvent otherEventWithType:NSApplicationDefined 966 [NSApp postEvent:[NSEvent otherEventWithType:NSApplicationDefined
934 location:NSZeroPoint 967 location:NSZeroPoint
935 modifierFlags:0 968 modifierFlags:0
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
1024 [NSApplication sharedApplication]; 1057 [NSApplication sharedApplication];
1025 g_not_using_cr_app = true; 1058 g_not_using_cr_app = true;
1026 return new MessagePumpNSApplication; 1059 return new MessagePumpNSApplication;
1027 #endif 1060 #endif
1028 } 1061 }
1029 1062
1030 return new MessagePumpNSRunLoop; 1063 return new MessagePumpNSRunLoop;
1031 } 1064 }
1032 1065
1033 } // namespace base 1066 } // namespace base
OLDNEW
« no previous file with comments | « base/message_loop/message_pump_mac.h ('k') | tools/metrics/histograms/histograms.xml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698