diff options
author | Zeno Albisser <zeno.albisser@theqtcompany.com> | 2014-12-05 15:04:29 +0100 |
---|---|---|
committer | Andras Becsi <andras.becsi@theqtcompany.com> | 2014-12-09 10:49:28 +0100 |
commit | af6588f8d723931a298c995fa97259bb7f7deb55 (patch) | |
tree | 060ca707847ba1735f01af2372e0d5e494dc0366 /chromium/base/message_loop | |
parent | 2fff84d821cc7b1c785f6404e0f8091333283e74 (diff) |
BASELINE: Update chromium to 40.0.2214.28 and ninja to 1.5.3.
Change-Id: I759465284fd64d59ad120219cbe257f7402c4181
Reviewed-by: Andras Becsi <andras.becsi@theqtcompany.com>
Diffstat (limited to 'chromium/base/message_loop')
23 files changed, 543 insertions, 661 deletions
diff --git a/chromium/base/message_loop/incoming_task_queue.cc b/chromium/base/message_loop/incoming_task_queue.cc index bcc712b4a5d..2ca32d6254b 100644 --- a/chromium/base/message_loop/incoming_task_queue.cc +++ b/chromium/base/message_loop/incoming_task_queue.cc @@ -4,16 +4,17 @@ #include "base/message_loop/incoming_task_queue.h" -#include "base/debug/trace_event.h" #include "base/location.h" #include "base/message_loop/message_loop.h" #include "base/synchronization/waitable_event.h" +#include "base/time/time.h" namespace base { namespace internal { IncomingTaskQueue::IncomingTaskQueue(MessageLoop* message_loop) - : message_loop_(message_loop), + : high_res_task_count_(0), + message_loop_(message_loop), next_sequence_num_(0) { } @@ -25,15 +26,23 @@ bool IncomingTaskQueue::AddToIncomingQueue( AutoLock locked(incoming_queue_lock_); PendingTask pending_task( from_here, task, CalculateDelayedRuntime(delay), nestable); +#if defined(OS_WIN) + // We consider the task needs a high resolution timer if the delay is + // more than 0 and less than 32ms. This caps the relative error to + // less than 50% : a 33ms wait can wake at 48ms since the default + // resolution on Windows is between 10 and 15ms. + if (delay > TimeDelta() && + delay.InMilliseconds() < (2 * Time::kMinLowResolutionThresholdMs)) { + ++high_res_task_count_; + pending_task.is_high_res = true; + } +#endif return PostPendingTask(&pending_task); } -bool IncomingTaskQueue::IsHighResolutionTimerEnabledForTesting() { -#if defined(OS_WIN) - return !high_resolution_timer_expiration_.is_null(); -#else - return true; -#endif +bool IncomingTaskQueue::HasHighResolutionTasks() { + AutoLock lock(incoming_queue_lock_); + return high_res_task_count_ > 0; } bool IncomingTaskQueue::IsIdleForTesting() { @@ -41,29 +50,22 @@ bool IncomingTaskQueue::IsIdleForTesting() { return incoming_queue_.empty(); } -void IncomingTaskQueue::ReloadWorkQueue(TaskQueue* work_queue) { +int IncomingTaskQueue::ReloadWorkQueue(TaskQueue* work_queue) { // Make sure no tasks are lost. DCHECK(work_queue->empty()); // Acquire all we can from the inter-thread queue with one lock acquisition. AutoLock lock(incoming_queue_lock_); if (!incoming_queue_.empty()) - incoming_queue_.Swap(work_queue); // Constant time + incoming_queue_.Swap(work_queue); - DCHECK(incoming_queue_.empty()); + // Reset the count of high resolution tasks since our queue is now empty. + int high_res_tasks = high_res_task_count_; + high_res_task_count_ = 0; + return high_res_tasks; } void IncomingTaskQueue::WillDestroyCurrentMessageLoop() { -#if defined(OS_WIN) - // If we left the high-resolution timer activated, deactivate it now. - // Doing this is not-critical, it is mainly to make sure we track - // the high resolution timer activations properly in our unit tests. - if (!high_resolution_timer_expiration_.is_null()) { - Time::ActivateHighResolutionTimer(false); - high_resolution_timer_expiration_ = TimeTicks(); - } -#endif - AutoLock lock(incoming_queue_lock_); message_loop_ = NULL; } @@ -75,40 +77,10 @@ IncomingTaskQueue::~IncomingTaskQueue() { TimeTicks IncomingTaskQueue::CalculateDelayedRuntime(TimeDelta delay) { TimeTicks delayed_run_time; - if (delay > TimeDelta()) { + if (delay > TimeDelta()) delayed_run_time = TimeTicks::Now() + delay; - -#if defined(OS_WIN) - if (high_resolution_timer_expiration_.is_null()) { - // Windows timers are granular to 15.6ms. If we only set high-res - // timers for those under 15.6ms, then a 18ms timer ticks at ~32ms, - // which as a percentage is pretty inaccurate. So enable high - // res timers for any timer which is within 2x of the granularity. - // This is a tradeoff between accuracy and power management. - bool needs_high_res_timers = delay.InMilliseconds() < - (2 * Time::kMinLowResolutionThresholdMs); - if (needs_high_res_timers) { - if (Time::ActivateHighResolutionTimer(true)) { - high_resolution_timer_expiration_ = TimeTicks::Now() + - TimeDelta::FromMilliseconds( - MessageLoop::kHighResolutionTimerModeLeaseTimeMs); - } - } - } -#endif - } else { + else DCHECK_EQ(delay.InMilliseconds(), 0) << "delay should not be negative"; - } - -#if defined(OS_WIN) - if (!high_resolution_timer_expiration_.is_null()) { - if (TimeTicks::Now() > high_resolution_timer_expiration_) { - Time::ActivateHighResolutionTimer(false); - high_resolution_timer_expiration_ = TimeTicks(); - } - } -#endif - return delayed_run_time; } @@ -130,9 +102,8 @@ bool IncomingTaskQueue::PostPendingTask(PendingTask* pending_task) { // delayed_run_time value) and for identifying the task in about:tracing. pending_task->sequence_num = next_sequence_num_++; - TRACE_EVENT_FLOW_BEGIN0(TRACE_DISABLED_BY_DEFAULT("toplevel.flow"), - "MessageLoop::PostTask", - TRACE_ID_MANGLE(message_loop_->GetTaskTraceID(*pending_task))); + message_loop_->task_annotator()->DidQueueTask("MessageLoop::PostTask", + *pending_task); bool was_empty = incoming_queue_.empty(); incoming_queue_.push(*pending_task); diff --git a/chromium/base/message_loop/incoming_task_queue.h b/chromium/base/message_loop/incoming_task_queue.h index 56c5638295b..30f26033a2d 100644 --- a/chromium/base/message_loop/incoming_task_queue.h +++ b/chromium/base/message_loop/incoming_task_queue.h @@ -38,16 +38,17 @@ class BASE_EXPORT IncomingTaskQueue TimeDelta delay, bool nestable); - // Returns true if the message loop has high resolution timers enabled. - // Provided for testing. - bool IsHighResolutionTimerEnabledForTesting(); + // Returns true if the queue contains tasks that require higher than default + // timer resolution. Currently only needed for Windows. + bool HasHighResolutionTasks(); // Returns true if the message loop is "idle". Provided for testing. bool IsIdleForTesting(); // Loads tasks from the |incoming_queue_| into |*work_queue|. Must be called - // from the thread that is running the loop. - void ReloadWorkQueue(TaskQueue* work_queue); + // from the thread that is running the loop. Returns the number of tasks that + // require high resolution timers. + int ReloadWorkQueue(TaskQueue* work_queue); // Disconnects |this| from the parent message loop. void WillDestroyCurrentMessageLoop(); @@ -65,12 +66,11 @@ class BASE_EXPORT IncomingTaskQueue // does not retain |pending_task->task| beyond this function call. bool PostPendingTask(PendingTask* pending_task); -#if defined(OS_WIN) - TimeTicks high_resolution_timer_expiration_; -#endif + // Number of tasks that require high resolution timing. This value is kept + // so that ReloadWorkQueue() completes in constant time. + int high_res_task_count_; - // The lock that protects access to |incoming_queue_|, |message_loop_| and - // |next_sequence_num_|. + // The lock that protects access to the members of this class. base::Lock incoming_queue_lock_; // An incoming queue of tasks that are acquired under a mutex for processing diff --git a/chromium/base/message_loop/message_loop.cc b/chromium/base/message_loop/message_loop.cc index dd1a393ab08..01402d070e3 100644 --- a/chromium/base/message_loop/message_loop.cc +++ b/chromium/base/message_loop/message_loop.cc @@ -8,8 +8,6 @@ #include "base/bind.h" #include "base/compiler_specific.h" -#include "base/debug/alias.h" -#include "base/debug/trace_event.h" #include "base/lazy_instance.h" #include "base/logging.h" #include "base/memory/scoped_ptr.h" @@ -92,6 +90,8 @@ MessageLoop::MessagePumpFactory* message_pump_for_ui_factory_ = NULL; // time for every task that is added to the MessageLoop incoming queue. bool AlwaysNotifyPump(MessageLoop::Type type) { #if defined(OS_ANDROID) + // The Android UI message loop needs to get notified each time a task is added + // to the incoming queue. return type == MessageLoop::TYPE_UI || type == MessageLoop::TYPE_JAVA; #else return false; @@ -100,7 +100,7 @@ bool AlwaysNotifyPump(MessageLoop::Type type) { #if defined(OS_IOS) typedef MessagePumpIOSForIO MessagePumpForIO; -#elif defined(OS_NACL) +#elif defined(OS_NACL_SFI) typedef MessagePumpDefault MessagePumpForIO; #elif defined(OS_POSIX) typedef MessagePumpLibevent MessagePumpForIO; @@ -127,6 +127,8 @@ MessageLoop::DestructionObserver::~DestructionObserver() { MessageLoop::MessageLoop(Type type) : type_(type), + pending_high_res_tasks_(0), + in_high_res_mode_(false), nestable_tasks_allowed_(true), #if defined(OS_WIN) os_modal_loop_(false), @@ -141,6 +143,8 @@ MessageLoop::MessageLoop(Type type) MessageLoop::MessageLoop(scoped_ptr<MessagePump> pump) : pump_(pump.Pass()), type_(TYPE_CUSTOM), + pending_high_res_tasks_(0), + in_high_res_mode_(false), nestable_tasks_allowed_(true), #if defined(OS_WIN) os_modal_loop_(false), @@ -155,7 +159,10 @@ MessageLoop::~MessageLoop() { DCHECK_EQ(this, current()); DCHECK(!run_loop_); - +#if defined(OS_WIN) + if (in_high_res_mode_) + Time::ActivateHighResolutionTimer(false); +#endif // Clean up any unprocessed tasks, but take care: deleting a task could // result in the addition of more tasks (e.g., via DeleteSoon). We set a // limit on the number of times we will allow a deleted task to generate more @@ -229,6 +236,14 @@ scoped_ptr<MessagePump> MessageLoop::CreateMessagePumpForType(Type type) { #define MESSAGE_PUMP_UI scoped_ptr<MessagePump>(new MessagePumpForUI()) #endif +#if defined(OS_MACOSX) + // Use an OS native runloop on Mac to support timer coalescing. + #define MESSAGE_PUMP_DEFAULT \ + scoped_ptr<MessagePump>(new MessagePumpCFRunLoop()) +#else + #define MESSAGE_PUMP_DEFAULT scoped_ptr<MessagePump>(new MessagePumpDefault()) +#endif + if (type == MessageLoop::TYPE_UI) { if (message_pump_for_ui_factory_) return message_pump_for_ui_factory_(); @@ -243,7 +258,7 @@ scoped_ptr<MessagePump> MessageLoop::CreateMessagePumpForType(Type type) { #endif DCHECK_EQ(MessageLoop::TYPE_DEFAULT, type); - return scoped_ptr<MessagePump>(new MessagePumpDefault()); + return MESSAGE_PUMP_DEFAULT; } void MessageLoop::AddDestructionObserver( @@ -361,8 +376,8 @@ bool MessageLoop::is_running() const { return run_loop_ != NULL; } -bool MessageLoop::IsHighResolutionTimerEnabledForTesting() { - return incoming_task_queue_->IsHighResolutionTimerEnabledForTesting(); +bool MessageLoop::HasHighResolutionTasks() { + return incoming_task_queue_->HasHighResolutionTasks(); } bool MessageLoop::IsIdleForTesting() { @@ -415,45 +430,24 @@ bool MessageLoop::ProcessNextDelayedNonNestableTask() { } void MessageLoop::RunTask(const PendingTask& pending_task) { - tracked_objects::TrackedTime start_time = - tracked_objects::ThreadData::NowForStartOfRun(pending_task.birth_tally); - - TRACE_EVENT_FLOW_END1(TRACE_DISABLED_BY_DEFAULT("toplevel.flow"), - "MessageLoop::PostTask", TRACE_ID_MANGLE(GetTaskTraceID(pending_task)), - "queue_duration", - (start_time - pending_task.EffectiveTimePosted()).InMilliseconds()); - // When tracing memory for posted tasks it's more valuable to attribute the - // memory allocations to the source function than generically to "RunTask". - TRACE_EVENT_WITH_MEMORY_TAG2( - "toplevel", "MessageLoop::RunTask", - pending_task.posted_from.function_name(), // Name for memory tracking. - "src_file", pending_task.posted_from.file_name(), - "src_func", pending_task.posted_from.function_name()); - DCHECK(nestable_tasks_allowed_); + + if (pending_task.is_high_res) { + pending_high_res_tasks_--; + CHECK(pending_high_res_tasks_ >= 0); + } // Execute the task and assume the worst: It is probably not reentrant. nestable_tasks_allowed_ = false; - // Before running the task, store the program counter where it was posted - // and deliberately alias it to ensure it is on the stack if the task - // crashes. Be careful not to assume that the variable itself will have the - // expected value when displayed by the optimizer in an optimized build. - // Look at a memory dump of the stack. - const void* program_counter = - pending_task.posted_from.program_counter(); - debug::Alias(&program_counter); - HistogramEvent(kTaskRunEvent); FOR_EACH_OBSERVER(TaskObserver, task_observers_, WillProcessTask(pending_task)); - pending_task.task.Run(); + task_annotator_.RunTask( + "MessageLoop::PostTask", "MessageLoop::RunTask", pending_task); FOR_EACH_OBSERVER(TaskObserver, task_observers_, DidProcessTask(pending_task)); - tracked_objects::ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, - start_time, tracked_objects::ThreadData::NowForEndOfRun()); - nestable_tasks_allowed_ = true; } @@ -505,23 +499,18 @@ bool MessageLoop::DeletePendingTasks() { return did_work; } -uint64 MessageLoop::GetTaskTraceID(const PendingTask& task) { - return (static_cast<uint64>(task.sequence_num) << 32) | - ((static_cast<uint64>(reinterpret_cast<intptr_t>(this)) << 32) >> 32); -} - void MessageLoop::ReloadWorkQueue() { // We can improve performance of our loading tasks from the incoming queue to // |*work_queue| by waiting until the last minute (|*work_queue| is empty) to // load. That reduces the number of locks-per-task significantly when our // queues get large. - if (work_queue_.empty()) - incoming_task_queue_->ReloadWorkQueue(&work_queue_); + if (work_queue_.empty()) { + pending_high_res_tasks_ += + incoming_task_queue_->ReloadWorkQueue(&work_queue_); + } } void MessageLoop::ScheduleWork(bool was_empty) { - // The Android UI message loop needs to get notified each time - // a task is added to the incoming queue. if (was_empty || AlwaysNotifyPump(type_)) pump_->ScheduleWork(); } @@ -621,21 +610,19 @@ bool MessageLoop::DoIdleWork() { if (run_loop_->quit_when_idle_received_) pump_->Quit(); - return false; -} - -void MessageLoop::GetQueueingInformation(size_t* queue_size, - TimeDelta* queueing_delay) { - *queue_size = work_queue_.size(); - if (*queue_size == 0) { - *queueing_delay = TimeDelta(); - return; + // When we return we will do a kernel wait for more tasks. +#if defined(OS_WIN) + // On Windows we activate the high resolution timer so that the wait + // _if_ triggered by the timer happens with good resolution. If we don't + // do this the default resolution is 15ms which might not be acceptable + // for some tasks. + bool high_res = pending_high_res_tasks_ > 0; + if (high_res != in_high_res_mode_) { + in_high_res_mode_ = high_res; + Time::ActivateHighResolutionTimer(in_high_res_mode_); } - - const PendingTask& next_to_run = work_queue_.front(); - tracked_objects::Duration duration = - tracked_objects::TrackedTime::Now() - next_to_run.EffectiveTimePosted(); - *queueing_delay = TimeDelta::FromMilliseconds(duration.InMilliseconds()); +#endif + return false; } void MessageLoop::DeleteSoonInternal(const tracked_objects::Location& from_here, @@ -668,17 +655,7 @@ void MessageLoopForUI::Attach() { } #endif -#if defined(OS_WIN) -void MessageLoopForUI::AddObserver(Observer* observer) { - static_cast<MessagePumpWin*>(pump_.get())->AddObserver(observer); -} - -void MessageLoopForUI::RemoveObserver(Observer* observer) { - static_cast<MessagePumpWin*>(pump_.get())->RemoveObserver(observer); -} -#endif // defined(OS_WIN) - -#if defined(USE_OZONE) || (defined(OS_CHROMEOS) && !defined(USE_GLIB)) +#if defined(USE_OZONE) || (defined(USE_X11) && !defined(USE_GLIB)) bool MessageLoopForUI::WatchFileDescriptor( int fd, bool persistent, @@ -699,7 +676,7 @@ bool MessageLoopForUI::WatchFileDescriptor( //------------------------------------------------------------------------------ // MessageLoopForIO -#if !defined(OS_NACL) +#if !defined(OS_NACL_SFI) void MessageLoopForIO::AddIOObserver( MessageLoopForIO::IOObserver* io_observer) { ToPumpIO(pump_.get())->AddIOObserver(io_observer); @@ -737,6 +714,6 @@ bool MessageLoopForIO::WatchFileDescriptor(int fd, } #endif -#endif // !defined(OS_NACL) +#endif // !defined(OS_NACL_SFI) } // namespace base diff --git a/chromium/base/message_loop/message_loop.h b/chromium/base/message_loop/message_loop.h index 22d4f7395e4..47df69a921b 100644 --- a/chromium/base/message_loop/message_loop.h +++ b/chromium/base/message_loop/message_loop.h @@ -11,6 +11,7 @@ #include "base/base_export.h" #include "base/basictypes.h" #include "base/callback_forward.h" +#include "base/debug/task_annotator.h" #include "base/location.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" @@ -38,7 +39,6 @@ namespace base { class HistogramBase; -class MessagePumpObserver; class RunLoop; class ThreadTaskRunnerHandle; class WaitableEvent; @@ -115,7 +115,7 @@ class BASE_EXPORT MessageLoop : public MessagePump::Delegate { // Creates a TYPE_CUSTOM MessageLoop with the supplied MessagePump, which must // be non-NULL. explicit MessageLoop(scoped_ptr<base::MessagePump> pump); - virtual ~MessageLoop(); + ~MessageLoop() override; // Returns the MessageLoop object for the current thread, or null if none. static MessageLoop* current(); @@ -194,9 +194,7 @@ class BASE_EXPORT MessageLoop : public MessagePump::Delegate { // good). // // NOTE: This method may be called on any thread. The object will be deleted - // on the thread that executes MessageLoop::Run(). If this is not the same - // as the thread that calls PostDelayedTask(FROM_HERE, ), then T MUST inherit - // from RefCountedThreadSafe<T>! + // on the thread that executes MessageLoop::Run(). template <class T> void DeleteSoon(const tracked_objects::Location& from_here, const T* object) { base::subtle::DeleteHelperInternal<T, void>::DeleteViaSequencedTaskRunner( @@ -223,7 +221,7 @@ class BASE_EXPORT MessageLoop : public MessagePump::Delegate { // NOTE: This method may be called on any thread. The object will be // released (and thus possibly deleted) on the thread that executes // MessageLoop::Run(). If this is not the same as the thread that calls - // PostDelayedTask(FROM_HERE, ), then T MUST inherit from + // ReleaseSoon(FROM_HERE, ), then T MUST inherit from // RefCountedThreadSafe<T>! template <class T> void ReleaseSoon(const tracked_objects::Location& from_here, @@ -295,10 +293,17 @@ class BASE_EXPORT MessageLoop : public MessagePump::Delegate { const std::string& thread_name() const { return thread_name_; } // Gets the message loop proxy associated with this message loop. + // + // NOTE: Deprecated; prefer task_runner() and the TaskRunner interfaces scoped_refptr<MessageLoopProxy> message_loop_proxy() { return message_loop_proxy_; } + // Gets the TaskRunner associated with this message loop. + scoped_refptr<SingleThreadTaskRunner> task_runner() { + return message_loop_proxy_; + } + // Enables or disables the recursive task processing. This happens in the case // of recursive message loops. Some unwanted message loop may occurs when // using common controls or printer functions. By default, recursive task @@ -364,10 +369,6 @@ class BASE_EXPORT MessageLoop : public MessagePump::Delegate { void AddTaskObserver(TaskObserver* task_observer); void RemoveTaskObserver(TaskObserver* task_observer); - // When we go into high resolution timer mode, we will stay in hi-res mode - // for at least 1s. - static const int kHighResolutionTimerModeLeaseTimeMs = 1000; - #if defined(OS_WIN) void set_os_modal_loop(bool os_modal_loop) { os_modal_loop_ = os_modal_loop; @@ -383,17 +384,27 @@ class BASE_EXPORT MessageLoop : public MessagePump::Delegate { // Returns true if the message loop has high resolution timers enabled. // Provided for testing. - bool IsHighResolutionTimerEnabledForTesting(); + bool HasHighResolutionTasks(); // Returns true if the message loop is "idle". Provided for testing. bool IsIdleForTesting(); + // Wakes up the message pump. Can be called on any thread. The caller is + // responsible for synchronizing ScheduleWork() calls. + void ScheduleWork(bool was_empty); + + // Returns the TaskAnnotator which is used to add debug information to posted + // tasks. + debug::TaskAnnotator* task_annotator() { return &task_annotator_; } + + // Runs the specified PendingTask. + void RunTask(const PendingTask& pending_task); + //---------------------------------------------------------------------------- protected: scoped_ptr<MessagePump> pump_; private: - friend class internal::IncomingTaskQueue; friend class RunLoop; // Configures various members for the two constructors. @@ -405,9 +416,6 @@ class BASE_EXPORT MessageLoop : public MessagePump::Delegate { // Called to process any delayed non-nestable tasks. bool ProcessNextDelayedNonNestableTask(); - // Runs the specified PendingTask. - void RunTask(const PendingTask& pending_task); - // Calls RunTask or queues the pending_task on the deferred task list if it // cannot be run right now. Returns true if the task was run. bool DeferOrRunPendingTask(const PendingTask& pending_task); @@ -420,19 +428,10 @@ class BASE_EXPORT MessageLoop : public MessagePump::Delegate { // true if some work was done. bool DeletePendingTasks(); - // Creates a process-wide unique ID to represent this task in trace events. - // This will be mangled with a Process ID hash to reduce the likelyhood of - // colliding with MessageLoop pointers on other processes. - uint64 GetTaskTraceID(const PendingTask& task); - // Loads tasks from the incoming queue to |work_queue_| if the latter is // empty. void ReloadWorkQueue(); - // Wakes up the message pump. Can be called on any thread. The caller is - // responsible for synchronizing ScheduleWork() calls. - void ScheduleWork(bool was_empty); - // Start recording histogram info about events and action IF it was enabled // and IF the statistics recorder can accept a registration of our histogram. void StartHistogrammer(); @@ -443,11 +442,9 @@ class BASE_EXPORT MessageLoop : public MessagePump::Delegate { void HistogramEvent(int event); // MessagePump::Delegate methods: - virtual bool DoWork() OVERRIDE; - virtual bool DoDelayedWork(TimeTicks* next_delayed_work_time) OVERRIDE; - virtual bool DoIdleWork() OVERRIDE; - virtual void GetQueueingInformation(size_t* queue_size, - TimeDelta* queueing_delay) OVERRIDE; + bool DoWork() override; + bool DoDelayedWork(TimeTicks* next_delayed_work_time) override; + bool DoIdleWork() override; const Type type_; @@ -455,6 +452,14 @@ class BASE_EXPORT MessageLoop : public MessagePump::Delegate { // this queue is only accessed (push/pop) by our current thread. TaskQueue work_queue_; + // How many high resolution tasks are in the pending task queue. This value + // increases by N every time we call ReloadWorkQueue() and decreases by 1 + // every time we call RunTask() if the task needs a high resolution timer. + int pending_high_res_tasks_; + // Tracks if we have requested high resolution timers. Its only use is to + // turn off the high resolution timer upon loop destruction. + bool in_high_res_mode_; + // Contains delayed tasks, sorted by their 'delayed_run_time' property. DelayedTaskQueue delayed_work_queue_; @@ -486,6 +491,8 @@ class BASE_EXPORT MessageLoop : public MessagePump::Delegate { ObserverList<TaskObserver> task_observers_; + debug::TaskAnnotator task_annotator_; + scoped_refptr<internal::IncomingTaskQueue> incoming_task_queue_; // The message loop proxy associated with this message loop. @@ -546,15 +553,7 @@ class BASE_EXPORT MessageLoopForUI : public MessageLoop { void Start(); #endif -#if defined(OS_WIN) - typedef MessagePumpObserver Observer; - - // Please see message_pump_win for definitions of these methods. - void AddObserver(Observer* observer); - void RemoveObserver(Observer* observer); -#endif - -#if defined(USE_OZONE) || (defined(OS_CHROMEOS) && !defined(USE_GLIB)) +#if defined(USE_OZONE) || (defined(USE_X11) && !defined(USE_GLIB)) // Please see MessagePumpLibevent for definition. bool WatchFileDescriptor( int fd, @@ -597,7 +596,7 @@ class BASE_EXPORT MessageLoopForIO : public MessageLoop { return loop && loop->type() == MessageLoop::TYPE_IO; } -#if !defined(OS_NACL) +#if !defined(OS_NACL_SFI) #if defined(OS_WIN) typedef MessagePumpForIO::IOHandler IOHandler; @@ -643,7 +642,7 @@ class BASE_EXPORT MessageLoopForIO : public MessageLoop { FileDescriptorWatcher *controller, Watcher *delegate); #endif // defined(OS_IOS) || defined(OS_POSIX) -#endif // !defined(OS_NACL) +#endif // !defined(OS_NACL_SFI) }; // Do not add any member variables to MessageLoopForIO! This is important b/c diff --git a/chromium/base/message_loop/message_loop_proxy.h b/chromium/base/message_loop/message_loop_proxy.h index 4ace8026db4..88eeac4ee6d 100644 --- a/chromium/base/message_loop/message_loop_proxy.h +++ b/chromium/base/message_loop/message_loop_proxy.h @@ -30,7 +30,7 @@ class BASE_EXPORT MessageLoopProxy : public SingleThreadTaskRunner { protected: MessageLoopProxy(); - virtual ~MessageLoopProxy(); + ~MessageLoopProxy() override; }; } // namespace base diff --git a/chromium/base/message_loop/message_loop_proxy_impl.h b/chromium/base/message_loop/message_loop_proxy_impl.h index b7f62b9770d..0fe629f9d14 100644 --- a/chromium/base/message_loop/message_loop_proxy_impl.h +++ b/chromium/base/message_loop/message_loop_proxy_impl.h @@ -25,18 +25,17 @@ class BASE_EXPORT MessageLoopProxyImpl : public MessageLoopProxy { scoped_refptr<IncomingTaskQueue> incoming_queue); // MessageLoopProxy implementation - virtual bool PostDelayedTask(const tracked_objects::Location& from_here, - const base::Closure& task, - base::TimeDelta delay) OVERRIDE; - virtual bool PostNonNestableDelayedTask( - const tracked_objects::Location& from_here, - const base::Closure& task, - base::TimeDelta delay) OVERRIDE; - virtual bool RunsTasksOnCurrentThread() const OVERRIDE; + bool PostDelayedTask(const tracked_objects::Location& from_here, + const base::Closure& task, + base::TimeDelta delay) override; + bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here, + const base::Closure& task, + base::TimeDelta delay) override; + bool RunsTasksOnCurrentThread() const override; private: friend class RefCountedThreadSafe<MessageLoopProxyImpl>; - virtual ~MessageLoopProxyImpl(); + ~MessageLoopProxyImpl() override; // THe incoming queue receiving all posted tasks. scoped_refptr<IncomingTaskQueue> incoming_queue_; diff --git a/chromium/base/message_loop/message_loop_proxy_impl_unittest.cc b/chromium/base/message_loop/message_loop_proxy_impl_unittest.cc index 81c9b0c51ba..5f31140303f 100644 --- a/chromium/base/message_loop/message_loop_proxy_impl_unittest.cc +++ b/chromium/base/message_loop/message_loop_proxy_impl_unittest.cc @@ -38,14 +38,14 @@ class MessageLoopProxyImplTest : public testing::Test { } protected: - virtual void SetUp() OVERRIDE { + virtual void SetUp() override { io_thread_.reset(new Thread("MessageLoopProxyImplTest_IO")); file_thread_.reset(new Thread("MessageLoopProxyImplTest_File")); io_thread_->Start(); file_thread_->Start(); } - virtual void TearDown() OVERRIDE { + virtual void TearDown() override { io_thread_->Stop(); file_thread_->Stop(); } diff --git a/chromium/base/message_loop/message_loop_proxy_unittest.cc b/chromium/base/message_loop/message_loop_proxy_unittest.cc index ada90808117..673ed884001 100644 --- a/chromium/base/message_loop/message_loop_proxy_unittest.cc +++ b/chromium/base/message_loop/message_loop_proxy_unittest.cc @@ -31,7 +31,7 @@ class MessageLoopProxyTest : public testing::Test { } protected: - virtual void SetUp() OVERRIDE { + virtual void SetUp() override { // Use SetUp() instead of the constructor to avoid posting a task to a // partialy constructed object. task_thread_.Start(); @@ -42,7 +42,7 @@ class MessageLoopProxyTest : public testing::Test { Bind(&MessageLoopProxyTest::BlockTaskThreadHelper, Unretained(this))); } - virtual void TearDown() OVERRIDE { + virtual void TearDown() override { // Make sure the |task_thread_| is not blocked, and stop the thread // fully before destuction because its tasks may still depend on the // |thread_sync_| event. diff --git a/chromium/base/message_loop/message_loop_unittest.cc b/chromium/base/message_loop/message_loop_unittest.cc index 1b09eb070fa..733f5e5b510 100644 --- a/chromium/base/message_loop/message_loop_unittest.cc +++ b/chromium/base/message_loop/message_loop_unittest.cc @@ -333,7 +333,7 @@ void RunTest_RecursiveDenial2(MessageLoop::Type message_loop_type) { &order, false)); // Let the other thread execute. - WaitForSingleObject(event, INFINITE); + WaitForSingleObject(event.Get(), INFINITE); MessageLoop::current()->Run(); ASSERT_EQ(order.Size(), 17); @@ -377,7 +377,7 @@ void RunTest_RecursiveSupport2(MessageLoop::Type message_loop_type) { &order, true)); // Let the other thread execute. - WaitForSingleObject(event, INFINITE); + WaitForSingleObject(event.Get(), INFINITE); MessageLoop::current()->Run(); ASSERT_EQ(order.Size(), 18); @@ -425,7 +425,7 @@ class DispatcherImpl : public MessagePumpDispatcher { public: DispatcherImpl() : dispatch_count_(0) {} - virtual uint32_t Dispatch(const NativeEvent& msg) OVERRIDE { + virtual uint32_t Dispatch(const NativeEvent& msg) override { ::TranslateMessage(&msg); ::DispatchMessage(&msg); // Do not count WM_TIMER since it is not what we post and it will cause @@ -517,10 +517,10 @@ TestIOHandler::TestIOHandler(const wchar_t* name, HANDLE signal, bool wait) } void TestIOHandler::Init() { - MessageLoopForIO::current()->RegisterIOHandler(file_, this); + MessageLoopForIO::current()->RegisterIOHandler(file_.Get(), this); DWORD read; - EXPECT_FALSE(ReadFile(file_, buffer_, size(), &read, context())); + EXPECT_FALSE(ReadFile(file_.Get(), buffer_, size(), &read, context())); EXPECT_EQ(ERROR_IO_PENDING, GetLastError()); if (wait_) WaitForIO(); @@ -554,7 +554,7 @@ void RunTest_IOHandler() { MessageLoop* thread_loop = thread.message_loop(); ASSERT_TRUE(NULL != thread_loop); - TestIOHandler handler(kPipeName, callback_called, false); + TestIOHandler handler(kPipeName, callback_called.Get(), false); thread_loop->PostTask(FROM_HERE, Bind(&TestIOHandler::Init, Unretained(&handler))); // Make sure the thread runs and sleeps for lack of work. @@ -562,9 +562,9 @@ void RunTest_IOHandler() { const char buffer[] = "Hello there!"; DWORD written; - EXPECT_TRUE(WriteFile(server, buffer, sizeof(buffer), &written, NULL)); + EXPECT_TRUE(WriteFile(server.Get(), buffer, sizeof(buffer), &written, NULL)); - DWORD result = WaitForSingleObject(callback_called, 1000); + DWORD result = WaitForSingleObject(callback_called.Get(), 1000); EXPECT_EQ(WAIT_OBJECT_0, result); thread.Stop(); @@ -595,8 +595,8 @@ void RunTest_WaitForIO() { MessageLoop* thread_loop = thread.message_loop(); ASSERT_TRUE(NULL != thread_loop); - TestIOHandler handler1(kPipeName1, callback1_called, false); - TestIOHandler handler2(kPipeName2, callback2_called, true); + TestIOHandler handler1(kPipeName1, callback1_called.Get(), false); + TestIOHandler handler2(kPipeName2, callback2_called.Get(), true); thread_loop->PostTask(FROM_HERE, Bind(&TestIOHandler::Init, Unretained(&handler1))); // TODO(ajwong): Do we really need such long Sleeps in ths function? @@ -612,12 +612,12 @@ void RunTest_WaitForIO() { const char buffer[] = "Hello there!"; DWORD written; - EXPECT_TRUE(WriteFile(server1, buffer, sizeof(buffer), &written, NULL)); + EXPECT_TRUE(WriteFile(server1.Get(), buffer, sizeof(buffer), &written, NULL)); PlatformThread::Sleep(2 * delay); - EXPECT_EQ(WAIT_TIMEOUT, WaitForSingleObject(callback1_called, 0)) << + EXPECT_EQ(WAIT_TIMEOUT, WaitForSingleObject(callback1_called.Get(), 0)) << "handler1 has not been called"; - EXPECT_TRUE(WriteFile(server2, buffer, sizeof(buffer), &written, NULL)); + EXPECT_TRUE(WriteFile(server2.Get(), buffer, sizeof(buffer), &written, NULL)); HANDLE objects[2] = { callback1_called.Get(), callback2_called.Get() }; DWORD result = WaitForMultipleObjects(2, objects, TRUE, 1000); @@ -664,16 +664,16 @@ class DummyTaskObserver : public MessageLoop::TaskObserver { num_tasks_processed_(0), num_tasks_(num_tasks) {} - virtual ~DummyTaskObserver() {} + ~DummyTaskObserver() override {} - virtual void WillProcessTask(const PendingTask& pending_task) OVERRIDE { + void WillProcessTask(const PendingTask& pending_task) override { num_tasks_started_++; EXPECT_TRUE(pending_task.time_posted != TimeTicks()); EXPECT_LE(num_tasks_started_, num_tasks_); EXPECT_EQ(num_tasks_started_, num_tasks_processed_ + 1); } - virtual void DidProcessTask(const PendingTask& pending_task) OVERRIDE { + void DidProcessTask(const PendingTask& pending_task) override { num_tasks_processed_++; EXPECT_TRUE(pending_task.time_posted != TimeTicks()); EXPECT_LE(num_tasks_started_, num_tasks_); @@ -726,34 +726,26 @@ TEST(MessageLoopTest, WaitForIO) { TEST(MessageLoopTest, HighResolutionTimer) { MessageLoop loop; + Time::EnableHighResolutionTimer(true); const TimeDelta kFastTimer = TimeDelta::FromMilliseconds(5); const TimeDelta kSlowTimer = TimeDelta::FromMilliseconds(100); - EXPECT_FALSE(loop.IsHighResolutionTimerEnabledForTesting()); - + EXPECT_FALSE(loop.HasHighResolutionTasks()); // Post a fast task to enable the high resolution timers. loop.PostDelayedTask(FROM_HERE, Bind(&PostNTasksThenQuit, 1), kFastTimer); + EXPECT_TRUE(loop.HasHighResolutionTasks()); loop.Run(); - EXPECT_TRUE(loop.IsHighResolutionTimerEnabledForTesting()); - - // Post a slow task and verify high resolution timers - // are still enabled. - loop.PostDelayedTask(FROM_HERE, Bind(&PostNTasksThenQuit, 1), - kSlowTimer); - loop.Run(); - EXPECT_TRUE(loop.IsHighResolutionTimerEnabledForTesting()); - - // Wait for a while so that high-resolution mode elapses. - PlatformThread::Sleep(TimeDelta::FromMilliseconds( - MessageLoop::kHighResolutionTimerModeLeaseTimeMs)); - - // Post a slow task to disable the high resolution timers. + EXPECT_FALSE(loop.HasHighResolutionTasks()); + EXPECT_FALSE(Time::IsHighResolutionTimerInUse()); + // Check that a slow task does not trigger the high resolution logic. loop.PostDelayedTask(FROM_HERE, Bind(&PostNTasksThenQuit, 1), kSlowTimer); + EXPECT_FALSE(loop.HasHighResolutionTasks()); loop.Run(); - EXPECT_FALSE(loop.IsHighResolutionTimerEnabledForTesting()); + EXPECT_FALSE(loop.HasHighResolutionTasks()); + Time::EnableHighResolutionTimer(false); } #endif // defined(OS_WIN) @@ -764,10 +756,10 @@ namespace { class QuitDelegate : public MessageLoopForIO::Watcher { public: - virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE { + void OnFileCanWriteWithoutBlocking(int fd) override { MessageLoop::current()->QuitWhenIdle(); } - virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE { + void OnFileCanReadWithoutBlocking(int fd) override { MessageLoop::current()->QuitWhenIdle(); } }; @@ -865,7 +857,7 @@ class MLDestructionObserver : public MessageLoop::DestructionObserver { destruction_observer_called_(destruction_observer_called), task_destroyed_before_message_loop_(false) { } - virtual void WillDestroyCurrentMessageLoop() OVERRIDE { + void WillDestroyCurrentMessageLoop() override { task_destroyed_before_message_loop_ = *task_destroyed_; *destruction_observer_called_ = true; } diff --git a/chromium/base/message_loop/message_pump.h b/chromium/base/message_loop/message_pump.h index a795f31b67c..a2edb458a96 100644 --- a/chromium/base/message_loop/message_pump.h +++ b/chromium/base/message_loop/message_pump.h @@ -12,7 +12,6 @@ namespace base { -class TimeDelta; class TimeTicks; class BASE_EXPORT MessagePump : public NonThreadSafe { @@ -40,21 +39,9 @@ class BASE_EXPORT MessagePump : public NonThreadSafe { virtual bool DoDelayedWork(TimeTicks* next_delayed_work_time) = 0; // Called from within Run just before the message pump goes to sleep. - // Returns true to indicate that idle work was done. + // Returns true to indicate that idle work was done. Returning false means + // the pump will now wait. virtual bool DoIdleWork() = 0; - - // Via the two required out pointers, returns the length of the Delegate's - // work queue and the length of time that the first item in the queue has - // been waiting to run. If the work queue is empty, the count and delay - // will both be zero. - // Note that this only counts the tasks in the ready-to-run queue and not - // the incoming queue that is used by other threads to post tasks. The - // latter queue requires holding a lock, which is deemed too expensive for - // instrumentation code. Under normal conditions, the incoming queue should - // be small or zero, but under heavy loads it may be much larger and - // |queue_count| may be up to 1/4 the size of the incoming queue. - virtual void GetQueueingInformation(size_t* queue_count, - TimeDelta* queueing_delay) {} }; MessagePump(); diff --git a/chromium/base/message_loop/message_pump_android.h b/chromium/base/message_loop/message_pump_android.h index 8a07a0f6e45..9b4540f6ff9 100644 --- a/chromium/base/message_loop/message_pump_android.h +++ b/chromium/base/message_loop/message_pump_android.h @@ -24,10 +24,10 @@ class BASE_EXPORT MessagePumpForUI : public MessagePump { MessagePumpForUI(); virtual ~MessagePumpForUI(); - virtual void Run(Delegate* delegate) OVERRIDE; - virtual void Quit() OVERRIDE; - virtual void ScheduleWork() OVERRIDE; - virtual void ScheduleDelayedWork(const TimeTicks& delayed_work_time) OVERRIDE; + virtual void Run(Delegate* delegate) override; + virtual void Quit() override; + virtual void ScheduleWork() override; + virtual void ScheduleDelayedWork(const TimeTicks& delayed_work_time) override; virtual void Start(Delegate* delegate); diff --git a/chromium/base/message_loop/message_pump_default.h b/chromium/base/message_loop/message_pump_default.h index a9b83e8de70..d63e8101a93 100644 --- a/chromium/base/message_loop/message_pump_default.h +++ b/chromium/base/message_loop/message_pump_default.h @@ -5,22 +5,23 @@ #ifndef BASE_MESSAGE_LOOP_MESSAGE_PUMP_DEFAULT_H_ #define BASE_MESSAGE_LOOP_MESSAGE_PUMP_DEFAULT_H_ +#include "base/base_export.h" #include "base/message_loop/message_pump.h" #include "base/synchronization/waitable_event.h" #include "base/time/time.h" namespace base { -class MessagePumpDefault : public MessagePump { +class BASE_EXPORT MessagePumpDefault : public MessagePump { public: MessagePumpDefault(); - virtual ~MessagePumpDefault(); + ~MessagePumpDefault() override; // MessagePump methods: - virtual void Run(Delegate* delegate) OVERRIDE; - virtual void Quit() OVERRIDE; - virtual void ScheduleWork() OVERRIDE; - virtual void ScheduleDelayedWork(const TimeTicks& delayed_work_time) OVERRIDE; + void Run(Delegate* delegate) override; + void Quit() override; + void ScheduleWork() override; + void ScheduleDelayedWork(const TimeTicks& delayed_work_time) override; private: // This flag is set to false when Run should return. diff --git a/chromium/base/message_loop/message_pump_glib.h b/chromium/base/message_loop/message_pump_glib.h index a13493a739c..9f4457141d7 100644 --- a/chromium/base/message_loop/message_pump_glib.h +++ b/chromium/base/message_loop/message_pump_glib.h @@ -22,7 +22,7 @@ namespace base { class BASE_EXPORT MessagePumpGlib : public MessagePump { public: MessagePumpGlib(); - virtual ~MessagePumpGlib(); + ~MessagePumpGlib() override; // Internal methods used for processing the pump callbacks. They are // public for simplicity but should not be used directly. HandlePrepare @@ -35,10 +35,10 @@ class BASE_EXPORT MessagePumpGlib : public MessagePump { void HandleDispatch(); // Overridden from MessagePump: - virtual void Run(Delegate* delegate) OVERRIDE; - virtual void Quit() OVERRIDE; - virtual void ScheduleWork() OVERRIDE; - virtual void ScheduleDelayedWork(const TimeTicks& delayed_work_time) OVERRIDE; + void Run(Delegate* delegate) override; + void Quit() override; + void ScheduleWork() override; + void ScheduleDelayedWork(const TimeTicks& delayed_work_time) override; private: bool ShouldQuit() const; diff --git a/chromium/base/message_loop/message_pump_glib_unittest.cc b/chromium/base/message_loop/message_pump_glib_unittest.cc index aaf6b4d5d06..ae4fefe2e75 100644 --- a/chromium/base/message_loop/message_pump_glib_unittest.cc +++ b/chromium/base/message_loop/message_pump_glib_unittest.cc @@ -161,11 +161,11 @@ class MessagePumpGLibTest : public testing::Test { MessagePumpGLibTest() : loop_(NULL), injector_(NULL) { } // Overridden from testing::Test: - virtual void SetUp() OVERRIDE { + virtual void SetUp() override { loop_ = new MessageLoop(MessageLoop::TYPE_UI); injector_ = new EventInjector(); } - virtual void TearDown() OVERRIDE { + virtual void TearDown() override { delete injector_; injector_ = NULL; delete loop_; diff --git a/chromium/base/message_loop/message_pump_io_ios_unittest.cc b/chromium/base/message_loop/message_pump_io_ios_unittest.cc index e6dcc33a4bf..0bf8c082f36 100644 --- a/chromium/base/message_loop/message_pump_io_ios_unittest.cc +++ b/chromium/base/message_loop/message_pump_io_ios_unittest.cc @@ -20,7 +20,7 @@ class MessagePumpIOSForIOTest : public testing::Test { io_thread_("MessagePumpIOSForIOTestIOThread") {} virtual ~MessagePumpIOSForIOTest() {} - virtual void SetUp() OVERRIDE { + virtual void SetUp() override { Thread::Options options(MessageLoop::TYPE_IO, 0); ASSERT_TRUE(io_thread_.StartWithOptions(options)); ASSERT_EQ(MessageLoop::TYPE_IO, io_thread_.message_loop()->type()); @@ -30,7 +30,7 @@ class MessagePumpIOSForIOTest : public testing::Test { ASSERT_EQ(0, ret); } - virtual void TearDown() OVERRIDE { + virtual void TearDown() override { if (IGNORE_EINTR(close(pipefds_[0])) < 0) PLOG(ERROR) << "close"; if (IGNORE_EINTR(close(pipefds_[1])) < 0) @@ -67,8 +67,8 @@ class StupidWatcher : public MessagePumpIOSForIO::Watcher { virtual ~StupidWatcher() {} // base:MessagePumpIOSForIO::Watcher interface - virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE {} - virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE {} + virtual void OnFileCanReadWithoutBlocking(int fd) override {} + virtual void OnFileCanWriteWithoutBlocking(int fd) override {} }; #if GTEST_HAS_DEATH_TEST && !defined(NDEBUG) @@ -96,11 +96,11 @@ class BaseWatcher : public MessagePumpIOSForIO::Watcher { virtual ~BaseWatcher() {} // MessagePumpIOSForIO::Watcher interface - virtual void OnFileCanReadWithoutBlocking(int /* fd */) OVERRIDE { + virtual void OnFileCanReadWithoutBlocking(int /* fd */) override { NOTREACHED(); } - virtual void OnFileCanWriteWithoutBlocking(int /* fd */) OVERRIDE { + virtual void OnFileCanWriteWithoutBlocking(int /* fd */) override { NOTREACHED(); } @@ -118,7 +118,7 @@ class DeleteWatcher : public BaseWatcher { DCHECK(!controller_); } - virtual void OnFileCanWriteWithoutBlocking(int /* fd */) OVERRIDE { + virtual void OnFileCanWriteWithoutBlocking(int /* fd */) override { DCHECK(controller_); delete controller_; controller_ = NULL; @@ -148,7 +148,7 @@ class StopWatcher : public BaseWatcher { virtual ~StopWatcher() {} - virtual void OnFileCanWriteWithoutBlocking(int /* fd */) OVERRIDE { + virtual void OnFileCanWriteWithoutBlocking(int /* fd */) override { controller_->StopWatchingFileDescriptor(); if (fd_to_start_watching_ >= 0) { pump_->WatchFileDescriptor(fd_to_start_watching_, diff --git a/chromium/base/message_loop/message_pump_libevent.h b/chromium/base/message_loop/message_pump_libevent.h index f3a48a9f62f..3f5ad51dae9 100644 --- a/chromium/base/message_loop/message_pump_libevent.h +++ b/chromium/base/message_loop/message_pump_libevent.h @@ -98,7 +98,7 @@ class BASE_EXPORT MessagePumpLibevent : public MessagePump { }; MessagePumpLibevent(); - virtual ~MessagePumpLibevent(); + ~MessagePumpLibevent() override; // Have the current thread's message loop watch for a a situation in which // reading/writing to the FD can be performed without blocking. @@ -122,10 +122,10 @@ class BASE_EXPORT MessagePumpLibevent : public MessagePump { void RemoveIOObserver(IOObserver* obs); // MessagePump methods: - virtual void Run(Delegate* delegate) OVERRIDE; - virtual void Quit() OVERRIDE; - virtual void ScheduleWork() OVERRIDE; - virtual void ScheduleDelayedWork(const TimeTicks& delayed_work_time) OVERRIDE; + void Run(Delegate* delegate) override; + void Quit() override; + void ScheduleWork() override; + void ScheduleDelayedWork(const TimeTicks& delayed_work_time) override; private: friend class MessagePumpLibeventTest; diff --git a/chromium/base/message_loop/message_pump_libevent_unittest.cc b/chromium/base/message_loop/message_pump_libevent_unittest.cc index 9298d687609..f9b89c4230b 100644 --- a/chromium/base/message_loop/message_pump_libevent_unittest.cc +++ b/chromium/base/message_loop/message_pump_libevent_unittest.cc @@ -23,7 +23,7 @@ class MessagePumpLibeventTest : public testing::Test { io_thread_("MessagePumpLibeventTestIOThread") {} virtual ~MessagePumpLibeventTest() {} - virtual void SetUp() OVERRIDE { + virtual void SetUp() override { Thread::Options options(MessageLoop::TYPE_IO, 0); ASSERT_TRUE(io_thread_.StartWithOptions(options)); ASSERT_EQ(MessageLoop::TYPE_IO, io_thread_.message_loop()->type()); @@ -31,7 +31,7 @@ class MessagePumpLibeventTest : public testing::Test { ASSERT_EQ(0, ret); } - virtual void TearDown() OVERRIDE { + virtual void TearDown() override { if (IGNORE_EINTR(close(pipefds_[0])) < 0) PLOG(ERROR) << "close"; if (IGNORE_EINTR(close(pipefds_[1])) < 0) @@ -62,11 +62,11 @@ namespace { // nothing useful. class StupidWatcher : public MessagePumpLibevent::Watcher { public: - virtual ~StupidWatcher() {} + ~StupidWatcher() override {} // base:MessagePumpLibevent::Watcher interface - virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE {} - virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE {} + void OnFileCanReadWithoutBlocking(int fd) override {} + void OnFileCanWriteWithoutBlocking(int fd) override {} }; #if GTEST_HAS_DEATH_TEST && !defined(NDEBUG) @@ -97,16 +97,12 @@ class BaseWatcher : public MessagePumpLibevent::Watcher { : controller_(controller) { DCHECK(controller_); } - virtual ~BaseWatcher() {} + ~BaseWatcher() override {} // base:MessagePumpLibevent::Watcher interface - virtual void OnFileCanReadWithoutBlocking(int /* fd */) OVERRIDE { - NOTREACHED(); - } + void OnFileCanReadWithoutBlocking(int /* fd */) override { NOTREACHED(); } - virtual void OnFileCanWriteWithoutBlocking(int /* fd */) OVERRIDE { - NOTREACHED(); - } + void OnFileCanWriteWithoutBlocking(int /* fd */) override { NOTREACHED(); } protected: MessagePumpLibevent::FileDescriptorWatcher* controller_; @@ -118,11 +114,9 @@ class DeleteWatcher : public BaseWatcher { MessagePumpLibevent::FileDescriptorWatcher* controller) : BaseWatcher(controller) {} - virtual ~DeleteWatcher() { - DCHECK(!controller_); - } + ~DeleteWatcher() override { DCHECK(!controller_); } - virtual void OnFileCanWriteWithoutBlocking(int /* fd */) OVERRIDE { + void OnFileCanWriteWithoutBlocking(int /* fd */) override { DCHECK(controller_); delete controller_; controller_ = NULL; @@ -147,9 +141,9 @@ class StopWatcher : public BaseWatcher { MessagePumpLibevent::FileDescriptorWatcher* controller) : BaseWatcher(controller) {} - virtual ~StopWatcher() {} + ~StopWatcher() override {} - virtual void OnFileCanWriteWithoutBlocking(int /* fd */) OVERRIDE { + void OnFileCanWriteWithoutBlocking(int /* fd */) override { controller_->StopWatchingFileDescriptor(); } }; @@ -177,16 +171,16 @@ void QuitMessageLoopAndStart(const Closure& quit_closure) { class NestedPumpWatcher : public MessagePumpLibevent::Watcher { public: NestedPumpWatcher() {} - virtual ~NestedPumpWatcher() {} + ~NestedPumpWatcher() override {} - virtual void OnFileCanReadWithoutBlocking(int /* fd */) OVERRIDE { + void OnFileCanReadWithoutBlocking(int /* fd */) override { RunLoop runloop; MessageLoop::current()->PostTask(FROM_HERE, Bind(&QuitMessageLoopAndStart, runloop.QuitClosure())); runloop.Run(); } - virtual void OnFileCanWriteWithoutBlocking(int /* fd */) OVERRIDE {} + void OnFileCanWriteWithoutBlocking(int /* fd */) override {} }; TEST_F(MessagePumpLibeventTest, NestedPumpWatcher) { diff --git a/chromium/base/message_loop/message_pump_mac.h b/chromium/base/message_loop/message_pump_mac.h index 6e63d2b5516..55ab2c674d4 100644 --- a/chromium/base/message_loop/message_pump_mac.h +++ b/chromium/base/message_loop/message_pump_mac.h @@ -58,7 +58,6 @@ namespace base { -class MessagePumpInstrumentation; class RunLoop; class TimeTicks; @@ -83,18 +82,18 @@ class MessagePumpCFRunLoopBase : public MessagePump { friend class MessagePumpScopedAutoreleasePool; public: MessagePumpCFRunLoopBase(); - virtual ~MessagePumpCFRunLoopBase(); + ~MessagePumpCFRunLoopBase() override; // Subclasses should implement the work they need to do in MessagePump::Run // in the DoRun method. MessagePumpCFRunLoopBase::Run calls DoRun directly. // This arrangement is used because MessagePumpCFRunLoopBase needs to set // up and tear down things before and after the "meat" of DoRun. - virtual void Run(Delegate* delegate) OVERRIDE; + void Run(Delegate* delegate) override; virtual void DoRun(Delegate* delegate) = 0; - virtual void ScheduleWork() OVERRIDE; - virtual void ScheduleDelayedWork(const TimeTicks& delayed_work_time) OVERRIDE; - virtual void SetTimerSlack(TimerSlack timer_slack) OVERRIDE; + void ScheduleWork() override; + void ScheduleDelayedWork(const TimeTicks& delayed_work_time) override; + void SetTimerSlack(TimerSlack timer_slack) override; protected: // Accessors for private data members to be used by subclasses. @@ -112,11 +111,6 @@ class MessagePumpCFRunLoopBase : public MessagePump { // objects autoreleased by work to fall into the current autorelease pool. virtual AutoreleasePoolType* CreateAutoreleasePool(); - // Enables instrumentation of the MessagePump. See MessagePumpInstrumentation - // in the implementation for details. - void EnableInstrumentation(); - WeakPtr<MessagePumpInstrumentation> instrumentation_; - private: // Timer callback scheduled by ScheduleDelayedWork. This does not do any // work, but it signals work_source_ so that delayed work can be performed @@ -130,11 +124,11 @@ class MessagePumpCFRunLoopBase : public MessagePump { static void RunWorkSource(void* info); bool RunWork(); - // Perform idle-priority work. This is normally called by - // StartOrEndWaitObserver, but is also associated with idle_work_source_. When - // this function actually does perform idle work, it will resignal that - // source. The static method calls the instance method; the instance method - // returns true if idle work was done. + // Perform idle-priority work. This is normally called by PreWaitObserver, + // but is also associated with idle_work_source_. When this function + // actually does perform idle work, it will resignal that source. The + // static method calls the instance method; the instance method returns + // true if idle work was done. static void RunIdleWorkSource(void* info); bool RunIdleWork(); @@ -156,8 +150,8 @@ class MessagePumpCFRunLoopBase : public MessagePump { // Observer callback responsible for performing idle-priority work, before // the run loop goes to sleep. Associated with idle_work_observer_. - static void StartOrEndWaitObserver(CFRunLoopObserverRef observer, - CFRunLoopActivity activity, void* info); + static void PreWaitObserver(CFRunLoopObserverRef observer, + CFRunLoopActivity activity, void* info); // Observer callback called before the run loop processes any sources. // Associated with pre_source_observer_. @@ -226,13 +220,13 @@ class MessagePumpCFRunLoopBase : public MessagePump { class BASE_EXPORT MessagePumpCFRunLoop : public MessagePumpCFRunLoopBase { public: MessagePumpCFRunLoop(); - virtual ~MessagePumpCFRunLoop(); + ~MessagePumpCFRunLoop() override; - virtual void DoRun(Delegate* delegate) OVERRIDE; - virtual void Quit() OVERRIDE; + void DoRun(Delegate* delegate) override; + void Quit() override; private: - virtual void EnterExitRunLoop(CFRunLoopActivity activity) OVERRIDE; + void EnterExitRunLoop(CFRunLoopActivity activity) override; // True if Quit is called to stop the innermost MessagePump // (innermost_quittable_) but some other CFRunLoopRun loop (nesting_level_) @@ -245,10 +239,10 @@ class BASE_EXPORT MessagePumpCFRunLoop : public MessagePumpCFRunLoopBase { class BASE_EXPORT MessagePumpNSRunLoop : public MessagePumpCFRunLoopBase { public: MessagePumpNSRunLoop(); - virtual ~MessagePumpNSRunLoop(); + ~MessagePumpNSRunLoop() override; - virtual void DoRun(Delegate* delegate) OVERRIDE; - virtual void Quit() OVERRIDE; + void DoRun(Delegate* delegate) override; + void Quit() override; private: // A source that doesn't do anything but provide something signalable @@ -270,8 +264,8 @@ class MessagePumpUIApplication : public MessagePumpCFRunLoopBase { public: MessagePumpUIApplication(); virtual ~MessagePumpUIApplication(); - virtual void DoRun(Delegate* delegate) OVERRIDE; - virtual void Quit() OVERRIDE; + virtual void DoRun(Delegate* delegate) override; + virtual void Quit() override; // This message pump can not spin the main message loop directly. Instead, // call |Attach()| to set up a delegate. It is an error to call |Run()|. @@ -288,10 +282,10 @@ class MessagePumpUIApplication : public MessagePumpCFRunLoopBase { class MessagePumpNSApplication : public MessagePumpCFRunLoopBase { public: MessagePumpNSApplication(); - virtual ~MessagePumpNSApplication(); + ~MessagePumpNSApplication() override; - virtual void DoRun(Delegate* delegate) OVERRIDE; - virtual void Quit() OVERRIDE; + void DoRun(Delegate* delegate) override; + void Quit() override; private: // False after Quit is called. @@ -309,12 +303,12 @@ class MessagePumpNSApplication : public MessagePumpCFRunLoopBase { class MessagePumpCrApplication : public MessagePumpNSApplication { public: MessagePumpCrApplication(); - virtual ~MessagePumpCrApplication(); + ~MessagePumpCrApplication() override; protected: // Returns nil if NSApp is currently in the middle of calling // -sendEvent. Requires NSApp implementing CrAppProtocol. - virtual AutoreleasePoolType* CreateAutoreleasePool() OVERRIDE; + AutoreleasePoolType* CreateAutoreleasePool() override; private: DISALLOW_COPY_AND_ASSIGN(MessagePumpCrApplication); diff --git a/chromium/base/message_loop/message_pump_mac.mm b/chromium/base/message_loop/message_pump_mac.mm index 0ab9ab7c467..914977b13d5 100644 --- a/chromium/base/message_loop/message_pump_mac.mm +++ b/chromium/base/message_loop/message_pump_mac.mm @@ -8,15 +8,11 @@ #import <Foundation/Foundation.h> #include <limits> -#include <stack> -#include "base/format_macros.h" #include "base/logging.h" #include "base/mac/scoped_cftyperef.h" #include "base/message_loop/timer_slack.h" -#include "base/metrics/histogram.h" #include "base/run_loop.h" -#include "base/strings/stringprintf.h" #include "base/time/time.h" #if !defined(OS_IOS) @@ -123,226 +119,6 @@ class MessagePumpScopedAutoreleasePool { DISALLOW_COPY_AND_ASSIGN(MessagePumpScopedAutoreleasePool); }; -// This class is used to instrument the MessagePump to gather various timing -// data about when the underlying run loop is entered, when it is waiting, and -// when it is servicing its delegate. -// -// The metrics are gathered as UMA-tracked histograms. To gather the data over -// time, sampling is used, such that a new histogram is created for each metric -// every |sampling_interval| for |sampling_duration|. After sampling is -// complete, this class deletes itself. -class MessagePumpInstrumentation { - public: - // Creates an instrument for the MessagePump on the current thread. Every - // |sampling_interval|, a new histogram will be created to track the metrics - // over time. After |sampling_duration|, this will delete itself, causing the - // WeakPtr to go NULL. - static WeakPtr<MessagePumpInstrumentation> Create( - const TimeDelta& sampling_interval, - const TimeDelta& sampling_duration) { - MessagePumpInstrumentation* instrument = - new MessagePumpInstrumentation(sampling_interval, sampling_duration); - return instrument->weak_ptr_factory_.GetWeakPtr(); - } - - // Starts the timer that runs the sampling instrumentation. Can be called - // multiple times as a noop. - void StartIfNeeded() { - if (timer_) - return; - - sampling_start_time_ = generation_start_time_ = TimeTicks::Now(); - - CFRunLoopTimerContext timer_context = { .info = this }; - timer_.reset(CFRunLoopTimerCreate( - NULL, // allocator - (Time::Now() + sampling_interval_).ToCFAbsoluteTime(), - sampling_interval_.InSecondsF(), - 0, // flags - 0, // order - &MessagePumpInstrumentation::TimerFired, - &timer_context)); - CFRunLoopAddTimerToAllModes(CFRunLoopGetCurrent(), timer_); - } - - // Used to track kCFRunLoopEntry. - void LoopEntered() { - loop_run_times_.push(TimeTicks::Now()); - } - - // Used to track kCFRunLoopExit. - void LoopExited() { - TimeDelta duration = TimeTicks::Now() - loop_run_times_.top(); - loop_run_times_.pop(); - GetHistogram(LOOP_CYCLE)->AddTime(duration); - } - - // Used to track kCFRunLoopBeforeWaiting. - void WaitingStarted() { - loop_wait_times_.push(TimeTicks::Now()); - } - - // Used to track kCFRunLoopAfterWaiting. - void WaitingFinished() { - TimeDelta duration = TimeTicks::Now() - loop_wait_times_.top(); - loop_wait_times_.pop(); - GetHistogram(LOOP_WAIT)->AddTime(duration); - } - - // Used to track when the MessagePump will invoke its |delegate|. - void WorkSourceEntered(MessagePump::Delegate* delegate) { - work_source_times_.push(TimeTicks::Now()); - if (delegate) { - size_t queue_size; - TimeDelta queuing_delay; - delegate->GetQueueingInformation(&queue_size, &queuing_delay); - GetHistogram(QUEUE_SIZE)->Add(queue_size); - GetHistogram(QUEUE_DELAY)->AddTime(queuing_delay); - } - } - - // Used to track the completion of servicing the MessagePump::Delegate. - void WorkSourceExited() { - TimeDelta duration = TimeTicks::Now() - work_source_times_.top(); - work_source_times_.pop(); - GetHistogram(WORK_SOURCE)->AddTime(duration); - } - - private: - enum HistogramEvent { - // Time-based histograms: - LOOP_CYCLE, // LoopEntered/LoopExited - LOOP_WAIT, // WaitingStarted/WaitingEnded - WORK_SOURCE, // WorkSourceExited - QUEUE_DELAY, // WorkSourceEntered - - // Value-based histograms: - // NOTE: Do not add value-based histograms before this event, only after. - QUEUE_SIZE, // WorkSourceEntered - - HISTOGRAM_EVENT_MAX, - }; - - MessagePumpInstrumentation(const TimeDelta& sampling_interval, - const TimeDelta& sampling_duration) - : weak_ptr_factory_(this), - sampling_interval_(sampling_interval), - sampling_duration_(sampling_duration), - sample_generation_(0) { - // Create all the histogram objects that will be used for sampling. - const char kHistogramName[] = "MessagePumpMac.%s.SampleMs.%" PRId64; - for (TimeDelta i; i < sampling_duration_; i += sampling_interval_) { - int64 sample = i.InMilliseconds(); - - // Generate the time-based histograms. - for (int j = LOOP_CYCLE; j < QUEUE_SIZE; ++j) { - std::string name = StringPrintf(kHistogramName, - NameForEnum(static_cast<HistogramEvent>(j)), sample); - histograms_[j].push_back( - Histogram::FactoryTimeGet(name, TimeDelta::FromMilliseconds(1), - sampling_interval_, 50, - HistogramBase::kUmaTargetedHistogramFlag)); - } - - // Generate the value-based histograms. - for (int j = QUEUE_SIZE; j < HISTOGRAM_EVENT_MAX; ++j) { - std::string name = StringPrintf(kHistogramName, - NameForEnum(static_cast<HistogramEvent>(j)), sample); - histograms_[j].push_back( - Histogram::FactoryGet(name, 1, 10000, 50, - HistogramBase::kUmaTargetedHistogramFlag)); - } - } - } - - ~MessagePumpInstrumentation() { - if (timer_) - CFRunLoopTimerInvalidate(timer_); - } - - const char* NameForEnum(HistogramEvent event) { - switch (event) { - case LOOP_CYCLE: return "LoopCycle"; - case LOOP_WAIT: return "Waiting"; - case WORK_SOURCE: return "WorkSource"; - case QUEUE_DELAY: return "QueueingDelay"; - case QUEUE_SIZE: return "QueueSize"; - default: - NOTREACHED(); - return NULL; - } - } - - static void TimerFired(CFRunLoopTimerRef timer, void* context) { - static_cast<MessagePumpInstrumentation*>(context)->TimerFired(); - } - - // Called by the run loop when the sampling_interval_ has elapsed. Advances - // the sample_generation_, which controls into which histogram data is - // recorded, while recording and accounting for timer skew. Will delete this - // object after |sampling_duration_| has elapsed. - void TimerFired() { - TimeTicks now = TimeTicks::Now(); - TimeDelta delta = now - generation_start_time_; - - // The timer fired, so advance the generation by at least one. - ++sample_generation_; - - // To account for large timer skew/drift, advance the generation by any - // more completed intervals. - for (TimeDelta skew_advance = delta - sampling_interval_; - skew_advance >= sampling_interval_; - skew_advance -= sampling_interval_) { - ++sample_generation_; - } - - generation_start_time_ = now; - if (now >= sampling_start_time_ + sampling_duration_) - delete this; - } - - HistogramBase* GetHistogram(HistogramEvent event) { - DCHECK_LT(sample_generation_, histograms_[event].size()); - return histograms_[event][sample_generation_]; - } - - // Vends the pointer to the Create()or. - WeakPtrFactory<MessagePumpInstrumentation> weak_ptr_factory_; - - // The interval and duration of the sampling. - TimeDelta sampling_interval_; - TimeDelta sampling_duration_; - - // The time at which sampling started. - TimeTicks sampling_start_time_; - - // The timer that advances the sample_generation_ and sets the - // generation_start_time_ for the current sample interval. - base::ScopedCFTypeRef<CFRunLoopTimerRef> timer_; - - // The two-dimensional array of histograms. The first dimension is the - // HistogramEvent type. The second is for the sampling intervals. - std::vector<HistogramBase*> histograms_[HISTOGRAM_EVENT_MAX]; - - // The index in the second dimension of histograms_, which controls in which - // sampled histogram events are recorded. - size_t sample_generation_; - - // The last time at which the timer fired. This is used to track timer skew - // (i.e. it did not fire on time) and properly account for it when advancing - // samle_generation_. - TimeTicks generation_start_time_; - - // MessagePump activations can be nested. Use a stack for each of the - // possibly reentrant HistogramEvent types to properly balance and calculate - // the timing information. - std::stack<TimeTicks> loop_run_times_; - std::stack<TimeTicks> loop_wait_times_; - std::stack<TimeTicks> work_source_times_; - - DISALLOW_COPY_AND_ASSIGN(MessagePumpInstrumentation); -}; - // Must be called on the run loop thread. MessagePumpCFRunLoopBase::MessagePumpCFRunLoopBase() : delegate_(NULL), @@ -393,11 +169,10 @@ MessagePumpCFRunLoopBase::MessagePumpCFRunLoopBase() CFRunLoopObserverContext observer_context = CFRunLoopObserverContext(); observer_context.info = this; pre_wait_observer_ = CFRunLoopObserverCreate(NULL, // allocator - kCFRunLoopBeforeWaiting | - kCFRunLoopAfterWaiting, + kCFRunLoopBeforeWaiting, true, // repeat 0, // priority - StartOrEndWaitObserver, + PreWaitObserver, &observer_context); CFRunLoopAddObserverToAllModes(run_loop_, pre_wait_observer_); @@ -482,11 +257,6 @@ void MessagePumpCFRunLoopBase::SetDelegate(Delegate* delegate) { } } -void MessagePumpCFRunLoopBase::EnableInstrumentation() { - instrumentation_ = MessagePumpInstrumentation::Create( - TimeDelta::FromSeconds(1), TimeDelta::FromSeconds(15)); -} - // May be called on any thread. void MessagePumpCFRunLoopBase::ScheduleWork() { CFRunLoopSourceSignal(work_source_); @@ -543,9 +313,6 @@ bool MessagePumpCFRunLoopBase::RunWork() { return false; } - if (instrumentation_) - instrumentation_->WorkSourceEntered(delegate_); - // The NSApplication-based run loop only drains the autorelease pool at each // UI event (NSEvent). The autorelease pool is not drained for each // CFRunLoopSource target that's run. Use a local pool for any autoreleased @@ -585,9 +352,6 @@ bool MessagePumpCFRunLoopBase::RunWork() { CFRunLoopSourceSignal(work_source_); } - if (instrumentation_) - instrumentation_->WorkSourceExited(); - return resignal_work_source; } @@ -672,18 +436,11 @@ void MessagePumpCFRunLoopBase::MaybeScheduleNestingDeferredWork() { // Called from the run loop. // static -void MessagePumpCFRunLoopBase::StartOrEndWaitObserver( - CFRunLoopObserverRef observer, - CFRunLoopActivity activity, - void* info) { +void MessagePumpCFRunLoopBase::PreWaitObserver(CFRunLoopObserverRef observer, + CFRunLoopActivity activity, + void* info) { MessagePumpCFRunLoopBase* self = static_cast<MessagePumpCFRunLoopBase*>(info); - if (activity == kCFRunLoopAfterWaiting) { - if (self->instrumentation_) - self->instrumentation_->WaitingFinished(); - return; - } - // Attempt to do some idle work before going to sleep. self->RunIdleWork(); @@ -692,9 +449,6 @@ void MessagePumpCFRunLoopBase::StartOrEndWaitObserver( // nesting-deferred work may have accumulated. Schedule it for processing // if appropriate. self->MaybeScheduleNestingDeferredWork(); - - if (self->instrumentation_) - self->instrumentation_->WaitingStarted(); } // Called from the run loop. @@ -721,9 +475,6 @@ void MessagePumpCFRunLoopBase::EnterExitObserver(CFRunLoopObserverRef observer, switch (activity) { case kCFRunLoopEntry: - if (self->instrumentation_) - self->instrumentation_->LoopEntered(); - ++self->nesting_level_; if (self->nesting_level_ > self->deepest_nesting_level_) { self->deepest_nesting_level_ = self->nesting_level_; @@ -737,9 +488,9 @@ void MessagePumpCFRunLoopBase::EnterExitObserver(CFRunLoopObserverRef observer, // handling sources to exiting without any sleep. This most commonly // occurs when CFRunLoopRunInMode is passed a timeout of 0, causing it // to make a single pass through the loop and exit without sleep. Some - // native loops use CFRunLoop in this way. Because StartOrEndWaitObserver - // will not be called in these case, MaybeScheduleNestingDeferredWork - // needs to be called here, as the run loop exits. + // native loops use CFRunLoop in this way. Because PreWaitObserver will + // not be called in these case, MaybeScheduleNestingDeferredWork needs + // to be called here, as the run loop exits. // // MaybeScheduleNestingDeferredWork consults self->nesting_level_ // to determine whether to schedule nesting-deferred work. It expects @@ -749,9 +500,6 @@ void MessagePumpCFRunLoopBase::EnterExitObserver(CFRunLoopObserverRef observer, // loop. self->MaybeScheduleNestingDeferredWork(); --self->nesting_level_; - - if (self->instrumentation_) - self->instrumentation_->LoopExited(); break; default: @@ -881,15 +629,11 @@ void MessagePumpUIApplication::Attach(Delegate* delegate) { MessagePumpNSApplication::MessagePumpNSApplication() : keep_running_(true), running_own_loop_(false) { - EnableInstrumentation(); } MessagePumpNSApplication::~MessagePumpNSApplication() {} void MessagePumpNSApplication::DoRun(Delegate* delegate) { - if (instrumentation_) - instrumentation_->StartIfNeeded(); - bool last_running_own_loop_ = running_own_loop_; // NSApp must be initialized by calling: diff --git a/chromium/base/message_loop/message_pump_observer.h b/chromium/base/message_loop/message_pump_observer.h deleted file mode 100644 index d6e7abf786a..00000000000 --- a/chromium/base/message_loop/message_pump_observer.h +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_MESSAGE_LOOP_MESSAGE_PUMP_OBSERVER_H -#define BASE_MESSAGE_LOOP_MESSAGE_PUMP_OBSERVER_H - -#include "base/base_export.h" -#include "base/event_types.h" - -#if !defined(OS_WIN) -#error Should not be here. -#endif - -namespace base { - -// A MessagePumpObserver is an object that receives global -// notifications from the UI MessageLoop with MessagePumpWin. -// -// NOTE: An Observer implementation should be extremely fast! -class BASE_EXPORT MessagePumpObserver { - public: - // This method is called before processing a NativeEvent. - virtual void WillProcessEvent(const NativeEvent& event) = 0; - - // This method is called after processing a message. - virtual void DidProcessEvent(const NativeEvent& event) = 0; - - protected: - virtual ~MessagePumpObserver() {} -}; - -} // namespace base - -#endif // BASE_MESSAGE_LOOP_MESSAGE_PUMP_OBSERVER_H diff --git a/chromium/base/message_loop/message_pump_perftest.cc b/chromium/base/message_loop/message_pump_perftest.cc new file mode 100644 index 00000000000..9fca4653dbe --- /dev/null +++ b/chromium/base/message_loop/message_pump_perftest.cc @@ -0,0 +1,293 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/bind.h" +#include "base/format_macros.h" +#include "base/memory/scoped_vector.h" +#include "base/strings/stringprintf.h" +#include "base/synchronization/condition_variable.h" +#include "base/synchronization/lock.h" +#include "base/synchronization/waitable_event.h" +#include "base/threading/thread.h" +#include "base/time/time.h" +#include "build/build_config.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/perf/perf_test.h" + +#if defined(OS_ANDROID) +#include "base/android/java_handler_thread.h" +#endif + +namespace base { +namespace { + +class ScheduleWorkTest : public testing::Test { + public: + ScheduleWorkTest() : counter_(0) {} + + void Increment(uint64_t amount) { counter_ += amount; } + + void Schedule(int index) { + base::TimeTicks start = base::TimeTicks::HighResNow(); + base::TimeTicks thread_start; + if (TimeTicks::IsThreadNowSupported()) + thread_start = base::TimeTicks::ThreadNow(); + base::TimeDelta minimum = base::TimeDelta::Max(); + base::TimeDelta maximum = base::TimeDelta(); + base::TimeTicks now, lastnow = start; + uint64_t schedule_calls = 0u; + do { + for (size_t i = 0; i < kBatchSize; ++i) { + target_message_loop()->ScheduleWork(true); + schedule_calls++; + } + now = base::TimeTicks::HighResNow(); + base::TimeDelta laptime = now - lastnow; + lastnow = now; + minimum = std::min(minimum, laptime); + maximum = std::max(maximum, laptime); + } while (now - start < base::TimeDelta::FromSeconds(kTargetTimeSec)); + + scheduling_times_[index] = now - start; + if (TimeTicks::IsThreadNowSupported()) + scheduling_thread_times_[index] = + base::TimeTicks::ThreadNow() - thread_start; + min_batch_times_[index] = minimum; + max_batch_times_[index] = maximum; + target_message_loop()->PostTask(FROM_HERE, + base::Bind(&ScheduleWorkTest::Increment, + base::Unretained(this), + schedule_calls)); + } + + void ScheduleWork(MessageLoop::Type target_type, int num_scheduling_threads) { +#if defined(OS_ANDROID) + if (target_type == MessageLoop::TYPE_JAVA) { + java_thread_.reset(new android::JavaHandlerThread("target")); + java_thread_->Start(); + } else +#endif + { + target_.reset(new Thread("target")); + target_->StartWithOptions(Thread::Options(target_type, 0u)); + } + + ScopedVector<Thread> scheduling_threads; + scheduling_times_.reset(new base::TimeDelta[num_scheduling_threads]); + scheduling_thread_times_.reset(new base::TimeDelta[num_scheduling_threads]); + min_batch_times_.reset(new base::TimeDelta[num_scheduling_threads]); + max_batch_times_.reset(new base::TimeDelta[num_scheduling_threads]); + + for (int i = 0; i < num_scheduling_threads; ++i) { + scheduling_threads.push_back(new Thread("posting thread")); + scheduling_threads[i]->Start(); + } + + for (int i = 0; i < num_scheduling_threads; ++i) { + scheduling_threads[i]->message_loop()->PostTask( + FROM_HERE, + base::Bind(&ScheduleWorkTest::Schedule, base::Unretained(this), i)); + } + + for (int i = 0; i < num_scheduling_threads; ++i) { + scheduling_threads[i]->Stop(); + } +#if defined(OS_ANDROID) + if (target_type == MessageLoop::TYPE_JAVA) { + java_thread_->Stop(); + java_thread_.reset(); + } else +#endif + { + target_->Stop(); + target_.reset(); + } + base::TimeDelta total_time; + base::TimeDelta total_thread_time; + base::TimeDelta min_batch_time = base::TimeDelta::Max(); + base::TimeDelta max_batch_time = base::TimeDelta(); + for (int i = 0; i < num_scheduling_threads; ++i) { + total_time += scheduling_times_[i]; + total_thread_time += scheduling_thread_times_[i]; + min_batch_time = std::min(min_batch_time, min_batch_times_[i]); + max_batch_time = std::max(max_batch_time, max_batch_times_[i]); + } + std::string trace = StringPrintf( + "%d_threads_scheduling_to_%s_pump", + num_scheduling_threads, + target_type == MessageLoop::TYPE_IO + ? "io" + : (target_type == MessageLoop::TYPE_UI ? "ui" : "default")); + perf_test::PrintResult( + "task", + "", + trace, + total_time.InMicroseconds() / static_cast<double>(counter_), + "us/task", + true); + perf_test::PrintResult( + "task", + "_min_batch_time", + trace, + min_batch_time.InMicroseconds() / static_cast<double>(kBatchSize), + "us/task", + false); + perf_test::PrintResult( + "task", + "_max_batch_time", + trace, + max_batch_time.InMicroseconds() / static_cast<double>(kBatchSize), + "us/task", + false); + if (TimeTicks::IsThreadNowSupported()) { + perf_test::PrintResult( + "task", + "_thread_time", + trace, + total_thread_time.InMicroseconds() / static_cast<double>(counter_), + "us/task", + true); + } + } + + MessageLoop* target_message_loop() { +#if defined(OS_ANDROID) + if (java_thread_) + return java_thread_->message_loop(); +#endif + return target_->message_loop(); + } + + private: + scoped_ptr<Thread> target_; +#if defined(OS_ANDROID) + scoped_ptr<android::JavaHandlerThread> java_thread_; +#endif + scoped_ptr<base::TimeDelta[]> scheduling_times_; + scoped_ptr<base::TimeDelta[]> scheduling_thread_times_; + scoped_ptr<base::TimeDelta[]> min_batch_times_; + scoped_ptr<base::TimeDelta[]> max_batch_times_; + uint64_t counter_; + + static const size_t kTargetTimeSec = 5; + static const size_t kBatchSize = 1000; +}; + +TEST_F(ScheduleWorkTest, ThreadTimeToIOFromOneThread) { + ScheduleWork(MessageLoop::TYPE_IO, 1); +} + +TEST_F(ScheduleWorkTest, ThreadTimeToIOFromTwoThreads) { + ScheduleWork(MessageLoop::TYPE_IO, 2); +} + +TEST_F(ScheduleWorkTest, ThreadTimeToIOFromFourThreads) { + ScheduleWork(MessageLoop::TYPE_IO, 4); +} + +TEST_F(ScheduleWorkTest, ThreadTimeToUIFromOneThread) { + ScheduleWork(MessageLoop::TYPE_UI, 1); +} + +TEST_F(ScheduleWorkTest, ThreadTimeToUIFromTwoThreads) { + ScheduleWork(MessageLoop::TYPE_UI, 2); +} + +TEST_F(ScheduleWorkTest, ThreadTimeToUIFromFourThreads) { + ScheduleWork(MessageLoop::TYPE_UI, 4); +} + +TEST_F(ScheduleWorkTest, ThreadTimeToDefaultFromOneThread) { + ScheduleWork(MessageLoop::TYPE_DEFAULT, 1); +} + +TEST_F(ScheduleWorkTest, ThreadTimeToDefaultFromTwoThreads) { + ScheduleWork(MessageLoop::TYPE_DEFAULT, 2); +} + +TEST_F(ScheduleWorkTest, ThreadTimeToDefaultFromFourThreads) { + ScheduleWork(MessageLoop::TYPE_DEFAULT, 4); +} + +#if defined(OS_ANDROID) +TEST_F(ScheduleWorkTest, ThreadTimeToJavaFromOneThread) { + ScheduleWork(MessageLoop::TYPE_JAVA, 1); +} + +TEST_F(ScheduleWorkTest, ThreadTimeToJavaFromTwoThreads) { + ScheduleWork(MessageLoop::TYPE_JAVA, 2); +} + +TEST_F(ScheduleWorkTest, ThreadTimeToJavaFromFourThreads) { + ScheduleWork(MessageLoop::TYPE_JAVA, 4); +} +#endif + +static void DoNothing() { +} + +class FakeMessagePump : public MessagePump { + public: + FakeMessagePump() {} + ~FakeMessagePump() override {} + + void Run(Delegate* delegate) override {} + + void Quit() override {} + void ScheduleWork() override {} + void ScheduleDelayedWork(const TimeTicks& delayed_work_time) override {} +}; + +class PostTaskTest : public testing::Test { + public: + void Run(int batch_size, int tasks_per_reload) { + base::TimeTicks start = base::TimeTicks::HighResNow(); + base::TimeTicks now; + MessageLoop loop(scoped_ptr<MessagePump>(new FakeMessagePump)); + scoped_refptr<internal::IncomingTaskQueue> queue( + new internal::IncomingTaskQueue(&loop)); + uint32_t num_posted = 0; + do { + for (int i = 0; i < batch_size; ++i) { + for (int j = 0; j < tasks_per_reload; ++j) { + queue->AddToIncomingQueue( + FROM_HERE, base::Bind(&DoNothing), base::TimeDelta(), false); + num_posted++; + } + TaskQueue loop_local_queue; + queue->ReloadWorkQueue(&loop_local_queue); + while (!loop_local_queue.empty()) { + PendingTask t = loop_local_queue.front(); + loop_local_queue.pop(); + loop.RunTask(t); + } + } + + now = base::TimeTicks::HighResNow(); + } while (now - start < base::TimeDelta::FromSeconds(5)); + std::string trace = StringPrintf("%d_tasks_per_reload", tasks_per_reload); + perf_test::PrintResult( + "task", + "", + trace, + (now - start).InMicroseconds() / static_cast<double>(num_posted), + "us/task", + true); + } +}; + +TEST_F(PostTaskTest, OneTaskPerReload) { + Run(10000, 1); +} + +TEST_F(PostTaskTest, TenTasksPerReload) { + Run(10000, 10); +} + +TEST_F(PostTaskTest, OneHundredTasksPerReload) { + Run(1000, 100); +} + +} // namespace +} // namespace base diff --git a/chromium/base/message_loop/message_pump_win.cc b/chromium/base/message_loop/message_pump_win.cc index ae022bf0957..ad89b7f6384 100644 --- a/chromium/base/message_loop/message_pump_win.cc +++ b/chromium/base/message_loop/message_pump_win.cc @@ -35,22 +35,6 @@ static const int kMsgHaveWork = WM_USER + 1; //----------------------------------------------------------------------------- // MessagePumpWin public: -void MessagePumpWin::AddObserver(MessagePumpObserver* observer) { - observers_.AddObserver(observer); -} - -void MessagePumpWin::RemoveObserver(MessagePumpObserver* observer) { - observers_.RemoveObserver(observer); -} - -void MessagePumpWin::WillProcessMessage(const MSG& msg) { - FOR_EACH_OBSERVER(MessagePumpObserver, observers_, WillProcessEvent(msg)); -} - -void MessagePumpWin::DidProcessMessage(const MSG& msg) { - FOR_EACH_OBSERVER(MessagePumpObserver, observers_, DidProcessEvent(msg)); -} - void MessagePumpWin::RunWithDispatcher( Delegate* delegate, MessagePumpDispatcher* dispatcher) { RunState s; @@ -369,8 +353,6 @@ bool MessagePumpForUI::ProcessMessageHelper(const MSG& msg) { if (CallMsgFilter(const_cast<MSG*>(&msg), kMessageFilterCode)) return true; - WillProcessMessage(msg); - uint32_t action = MessagePumpDispatcher::POST_DISPATCH_PERFORM_DEFAULT; if (state_->dispatcher) action = state_->dispatcher->Dispatch(msg); @@ -381,7 +363,6 @@ bool MessagePumpForUI::ProcessMessageHelper(const MSG& msg) { DispatchMessage(&msg); } - DidProcessMessage(msg); return true; } @@ -440,7 +421,7 @@ void MessagePumpForIO::ScheduleWork() { return; // Someone else continued the pumping. // Make sure the MessagePump does some work for us. - BOOL ret = PostQueuedCompletionStatus(port_, 0, + BOOL ret = PostQueuedCompletionStatus(port_.Get(), 0, reinterpret_cast<ULONG_PTR>(this), reinterpret_cast<OVERLAPPED*>(this)); if (ret) @@ -462,7 +443,7 @@ void MessagePumpForIO::ScheduleDelayedWork(const TimeTicks& delayed_work_time) { void MessagePumpForIO::RegisterIOHandler(HANDLE file_handle, IOHandler* handler) { ULONG_PTR key = HandlerToKey(handler, true); - HANDLE port = CreateIoCompletionPort(file_handle, port_, key, 1); + HANDLE port = CreateIoCompletionPort(file_handle, port_.Get(), key, 1); DPCHECK(port); } @@ -474,7 +455,7 @@ bool MessagePumpForIO::RegisterJobObject(HANDLE job_handle, ULONG_PTR key = HandlerToKey(handler, false); JOBOBJECT_ASSOCIATE_COMPLETION_PORT info; info.CompletionKey = reinterpret_cast<void*>(key); - info.CompletionPort = port_; + info.CompletionPort = port_.Get(); return SetInformationJobObject(job_handle, JobObjectAssociateCompletionPortInformation, &info, diff --git a/chromium/base/message_loop/message_pump_win.h b/chromium/base/message_loop/message_pump_win.h index 535a21320e0..b2573174228 100644 --- a/chromium/base/message_loop/message_pump_win.h +++ b/chromium/base/message_loop/message_pump_win.h @@ -13,7 +13,6 @@ #include "base/basictypes.h" #include "base/message_loop/message_pump.h" #include "base/message_loop/message_pump_dispatcher.h" -#include "base/message_loop/message_pump_observer.h" #include "base/observer_list.h" #include "base/time/time.h" #include "base/win/scoped_handle.h" @@ -28,18 +27,6 @@ class BASE_EXPORT MessagePumpWin : public MessagePump { MessagePumpWin() : have_work_(0), state_(NULL) {} virtual ~MessagePumpWin() {} - // Add an Observer, which will start receiving notifications immediately. - void AddObserver(MessagePumpObserver* observer); - - // Remove an Observer. It is safe to call this method while an Observer is - // receiving a notification callback. - void RemoveObserver(MessagePumpObserver* observer); - - // Give a chance to code processing additional messages to notify the - // message loop observers that another message has been processed. - void WillProcessMessage(const MSG& msg); - void DidProcessMessage(const MSG& msg); - // Like MessagePump::Run, but MSG objects are routed through dispatcher. void RunWithDispatcher(Delegate* delegate, MessagePumpDispatcher* dispatcher); @@ -62,8 +49,6 @@ class BASE_EXPORT MessagePumpWin : public MessagePump { virtual void DoRunLoop() = 0; int GetCurrentDelay() const; - ObserverList<MessagePumpObserver> observers_; - // The time at which delayed work should run. TimeTicks delayed_work_time_; |