summaryrefslogtreecommitdiffstats
path: root/chromium/base/message_loop
diff options
context:
space:
mode:
authorZeno Albisser <zeno.albisser@theqtcompany.com>2014-12-05 15:04:29 +0100
committerAndras Becsi <andras.becsi@theqtcompany.com>2014-12-09 10:49:28 +0100
commitaf6588f8d723931a298c995fa97259bb7f7deb55 (patch)
tree060ca707847ba1735f01af2372e0d5e494dc0366 /chromium/base/message_loop
parent2fff84d821cc7b1c785f6404e0f8091333283e74 (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')
-rw-r--r--chromium/base/message_loop/incoming_task_queue.cc83
-rw-r--r--chromium/base/message_loop/incoming_task_queue.h20
-rw-r--r--chromium/base/message_loop/message_loop.cc119
-rw-r--r--chromium/base/message_loop/message_loop.h79
-rw-r--r--chromium/base/message_loop/message_loop_proxy.h2
-rw-r--r--chromium/base/message_loop/message_loop_proxy_impl.h17
-rw-r--r--chromium/base/message_loop/message_loop_proxy_impl_unittest.cc4
-rw-r--r--chromium/base/message_loop/message_loop_proxy_unittest.cc4
-rw-r--r--chromium/base/message_loop/message_loop_unittest.cc64
-rw-r--r--chromium/base/message_loop/message_pump.h17
-rw-r--r--chromium/base/message_loop/message_pump_android.h8
-rw-r--r--chromium/base/message_loop/message_pump_default.h13
-rw-r--r--chromium/base/message_loop/message_pump_glib.h10
-rw-r--r--chromium/base/message_loop/message_pump_glib_unittest.cc4
-rw-r--r--chromium/base/message_loop/message_pump_io_ios_unittest.cc16
-rw-r--r--chromium/base/message_loop/message_pump_libevent.h10
-rw-r--r--chromium/base/message_loop/message_pump_libevent_unittest.cc36
-rw-r--r--chromium/base/message_loop/message_pump_mac.h58
-rw-r--r--chromium/base/message_loop/message_pump_mac.mm272
-rw-r--r--chromium/base/message_loop/message_pump_observer.h35
-rw-r--r--chromium/base/message_loop/message_pump_perftest.cc293
-rw-r--r--chromium/base/message_loop/message_pump_win.cc25
-rw-r--r--chromium/base/message_loop/message_pump_win.h15
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_;