| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |