diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-10-24 11:30:15 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-10-30 12:56:19 +0000 |
commit | 6036726eb981b6c4b42047513b9d3f4ac865daac (patch) | |
tree | 673593e70678e7789766d1f732eb51f613a2703b /chromium/base/message_loop/message_loop.cc | |
parent | 466052c4e7c052268fd931888cd58961da94c586 (diff) |
BASELINE: Update Chromium to 70.0.3538.78
Change-Id: Ie634710bf039e26c1957f4ae45e101bd4c434ae7
Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/base/message_loop/message_loop.cc')
-rw-r--r-- | chromium/base/message_loop/message_loop.cc | 156 |
1 files changed, 96 insertions, 60 deletions
diff --git a/chromium/base/message_loop/message_loop.cc b/chromium/base/message_loop/message_loop.cc index 3723960a5c0..ff55a15ce0f 100644 --- a/chromium/base/message_loop/message_loop.cc +++ b/chromium/base/message_loop/message_loop.cc @@ -8,15 +8,17 @@ #include <utility> #include "base/bind.h" +#include "base/callback_helpers.h" #include "base/compiler_specific.h" #include "base/debug/task_annotator.h" #include "base/logging.h" #include "base/memory/ptr_util.h" +#include "base/message_loop/message_loop_task_runner.h" #include "base/message_loop/message_pump_default.h" #include "base/message_loop/message_pump_for_io.h" #include "base/message_loop/message_pump_for_ui.h" +#include "base/message_loop/sequenced_task_source.h" #include "base/run_loop.h" -#include "base/third_party/dynamic_annotations/dynamic_annotations.h" #include "base/threading/thread_id_name_manager.h" #include "base/threading/thread_task_runner_handle.h" #include "base/trace_event/trace_event.h" @@ -37,7 +39,7 @@ std::unique_ptr<MessagePump> ReturnPump(std::unique_ptr<MessagePump> pump) { } // namespace -class MessageLoop::Controller : public internal::IncomingTaskQueue::Observer { +class MessageLoop::Controller : public SequencedTaskSource::Observer { public: // Constructs a MessageLoopController which controls |message_loop|, notifying // |task_annotator_| when tasks are queued scheduling work on |message_loop| @@ -47,7 +49,7 @@ class MessageLoop::Controller : public internal::IncomingTaskQueue::Observer { ~Controller() override; - // IncomingTaskQueue::Observer: + // SequencedTaskSource::Observer: void WillQueueTask(PendingTask* task) final; void DidQueueTask(bool was_empty) final; @@ -171,7 +173,7 @@ MessageLoop::~MessageLoop() { for (int i = 0; i < 100; ++i) { DeletePendingTasks(); // If we end up with empty queues, then break out of the loop. - tasks_remain = incoming_task_queue_->triage_tasks().HasTasks(); + tasks_remain = sequenced_task_source_->HasTasks(); if (!tasks_remain) break; } @@ -183,12 +185,22 @@ MessageLoop::~MessageLoop() { thread_task_runner_handle_.reset(); - // Tell the incoming queue that we are dying. + // Detach this instance's Controller from |this|. After this point, + // |underlying_task_runner_| may still receive tasks and notify the controller + // but the controller will no-op (and not use this MessageLoop after free). + // |underlying_task_runner_| being ref-counted and potentially kept alive by + // many SingleThreadTaskRunner refs, the best we can do is tell it to shutdown + // after which it will start returning false to PostTasks that happen-after + // this point (note that invoking Shutdown() first would not remove the need + // to DisconnectFromParent() since the controller is invoked *after* a task is + // enqueued and the incoming queue's lock is released (see + // MessageLoopTaskRunner::AddToIncomingQueue()). + // Details : while an "in-progress post tasks" refcount in Controller in lieu + // of |message_loop_lock_| would be an option to handle the "pending post + // tasks on shutdown" case, |message_loop_lock_| would still be required to + // serialize ScheduleWork() call and as such that optimization isn't worth it. message_loop_controller_->DisconnectFromParent(); - incoming_task_queue_->Shutdown(); - incoming_task_queue_ = nullptr; - unbound_task_runner_ = nullptr; - task_runner_ = nullptr; + underlying_task_runner_->Shutdown(); // OK, now make it so that no one can find us. if (MessageLoopCurrent::IsBoundToCurrentThreadInternal(this)) @@ -252,21 +264,29 @@ bool MessageLoop::IsType(Type type) const { // implementation detail. http://crbug.com/703346 void MessageLoop::AddTaskObserver(TaskObserver* task_observer) { DCHECK_CALLED_ON_VALID_THREAD(bound_thread_checker_); - task_observers_.AddObserver(task_observer); + task_observers_.push_back(task_observer); } void MessageLoop::RemoveTaskObserver(TaskObserver* task_observer) { DCHECK_CALLED_ON_VALID_THREAD(bound_thread_checker_); - task_observers_.RemoveObserver(task_observer); + auto it = + std::find(task_observers_.begin(), task_observers_.end(), task_observer); + DCHECK(it != task_observers_.end()); + task_observers_.erase(it); +} + +void MessageLoop::SetAddQueueTimeToTasks(bool enable) { + DCHECK_CALLED_ON_VALID_THREAD(bound_thread_checker_); + underlying_task_runner_->SetAddQueueTimeToTasks(enable); } bool MessageLoop::IsIdleForTesting() { // Have unprocessed tasks? (this reloads the work queue if necessary) - if (incoming_task_queue_->triage_tasks().HasTasks()) + if (sequenced_task_source_->HasTasks()) return false; // Have unprocessed deferred tasks which can be processed at this run-level? - if (incoming_task_queue_->deferred_tasks().HasTasks() && + if (pending_task_queue_.deferred_tasks().HasTasks() && !RunLoop::IsNestedOnCurrentThread()) { return false; } @@ -283,19 +303,16 @@ std::unique_ptr<MessageLoop> MessageLoop::CreateUnbound( return WrapUnique(new MessageLoop(type, std::move(pump_factory))); } -// TODO(gab): Avoid bare new + WrapUnique below when introducing -// SequencedTaskSource in follow-up @ -// https://chromium-review.googlesource.com/c/chromium/src/+/1088762. MessageLoop::MessageLoop(Type type, MessagePumpFactoryCallback pump_factory) : MessageLoopCurrent(this), type_(type), pump_factory_(std::move(pump_factory)), - message_loop_controller_(new Controller(this)), - incoming_task_queue_(MakeRefCounted<internal::IncomingTaskQueue>( + message_loop_controller_( + new Controller(this)), // Ownership transferred on the next line. + underlying_task_runner_(MakeRefCounted<internal::MessageLoopTaskRunner>( WrapUnique(message_loop_controller_))), - unbound_task_runner_(MakeRefCounted<internal::MessageLoopTaskRunner>( - incoming_task_queue_)), - task_runner_(unbound_task_runner_) { + sequenced_task_source_(underlying_task_runner_.get()), + task_runner_(underlying_task_runner_) { // If type is TYPE_CUSTOM non-null pump_factory must be given. DCHECK(type_ != TYPE_CUSTOM || !pump_factory_.is_null()); @@ -316,9 +333,8 @@ void MessageLoop::BindToCurrentThread() { << "should only have one message loop per thread"; MessageLoopCurrent::BindToCurrentThreadInternal(this); + underlying_task_runner_->BindToCurrentThread(); message_loop_controller_->StartScheduling(); - unbound_task_runner_->BindToCurrentThread(); - unbound_task_runner_ = nullptr; SetThreadTaskRunnerHandle(); thread_id_ = PlatformThread::CurrentId(); @@ -344,21 +360,18 @@ std::string MessageLoop::GetThreadName() const { void MessageLoop::SetTaskRunner( scoped_refptr<SingleThreadTaskRunner> task_runner) { - DCHECK_CALLED_ON_VALID_THREAD(bound_thread_checker_); - DCHECK(task_runner); - DCHECK(task_runner->BelongsToCurrentThread()); - DCHECK(!unbound_task_runner_); - task_runner_ = std::move(task_runner); - SetThreadTaskRunnerHandle(); -} - -void MessageLoop::ClearTaskRunnerForTesting() { - DCHECK_CALLED_ON_VALID_THREAD(bound_thread_checker_); - - DCHECK(!unbound_task_runner_); - task_runner_ = nullptr; - thread_task_runner_handle_.reset(); + if (thread_id_ == kInvalidThreadId) { + // ThreadTaskRunnerHandle will be set during BindToCurrentThread(). + task_runner_ = std::move(task_runner); + } else { + // Once MessageLoop is bound, |task_runner_| may only be altered on the + // bound thread. + DCHECK_CALLED_ON_VALID_THREAD(bound_thread_checker_); + DCHECK(task_runner->BelongsToCurrentThread()); + task_runner_ = std::move(task_runner); + SetThreadTaskRunnerHandle(); + } } void MessageLoop::Run(bool application_tasks_allowed) { @@ -381,7 +394,7 @@ void MessageLoop::Quit() { void MessageLoop::EnsureWorkScheduled() { DCHECK_CALLED_ON_VALID_THREAD(bound_thread_checker_); - if (incoming_task_queue_->triage_tasks().HasTasks()) + if (sequenced_task_source_->HasTasks()) pump_->ScheduleWork(); } @@ -397,8 +410,8 @@ bool MessageLoop::ProcessNextDelayedNonNestableTask() { if (RunLoop::IsNestedOnCurrentThread()) return false; - while (incoming_task_queue_->deferred_tasks().HasTasks()) { - PendingTask pending_task = incoming_task_queue_->deferred_tasks().Pop(); + while (pending_task_queue_.deferred_tasks().HasTasks()) { + PendingTask pending_task = pending_task_queue_.deferred_tasks().Pop(); if (!pending_task.task.IsCancelled()) { RunTask(&pending_task); return true; @@ -416,12 +429,12 @@ void MessageLoop::RunTask(PendingTask* pending_task) { TRACE_TASK_EXECUTION("MessageLoop::RunTask", *pending_task); - for (auto& observer : task_observers_) - observer.WillProcessTask(*pending_task); + for (TaskObserver* task_observer : task_observers_) + task_observer->WillProcessTask(*pending_task); message_loop_controller_->task_annotator().RunTask("MessageLoop::PostTask", pending_task); - for (auto& observer : task_observers_) - observer.DidProcessTask(*pending_task); + for (TaskObserver* task_observer : task_observers_) + task_observer->DidProcessTask(*pending_task); task_execution_allowed_ = true; } @@ -437,17 +450,41 @@ bool MessageLoop::DeferOrRunPendingTask(PendingTask pending_task) { // We couldn't run the task now because we're in a nested run loop // and the task isn't nestable. - incoming_task_queue_->deferred_tasks().Push(std::move(pending_task)); + pending_task_queue_.deferred_tasks().Push(std::move(pending_task)); return false; } void MessageLoop::DeletePendingTasks() { - incoming_task_queue_->triage_tasks().Clear(); - incoming_task_queue_->deferred_tasks().Clear(); + // Delete all currently pending tasks but not tasks potentially posted from + // their destructors. See ~MessageLoop() for the full logic mitigating against + // infite loops when clearing pending tasks. The ScopedClosureRunner below + // will be bound to a task posted at the end of the queue. After it is posted, + // tasks will be deleted one by one, when the bound ScopedClosureRunner is + // deleted and sets |deleted_all_originally_pending|, we know we've deleted + // all originally pending tasks. + bool deleted_all_originally_pending = false; + ScopedClosureRunner capture_deleted_all_originally_pending(BindOnce( + [](bool* deleted_all_originally_pending) { + *deleted_all_originally_pending = true; + }, + Unretained(&deleted_all_originally_pending))); + sequenced_task_source_->InjectTask( + BindOnce([](ScopedClosureRunner) {}, + std::move(capture_deleted_all_originally_pending))); + + while (!deleted_all_originally_pending) { + PendingTask pending_task = sequenced_task_source_->TakeTask(); + + // New delayed tasks should be deleted after older ones. + if (!pending_task.delayed_run_time.is_null()) + pending_task_queue_.delayed_tasks().Push(std::move(pending_task)); + } + + pending_task_queue_.deferred_tasks().Clear(); // TODO(robliao): Determine if we can move delayed task destruction before // deferred tasks to maintain the MessagePump DoWork, DoDelayedWork, and // DoIdleWork processing order. - incoming_task_queue_->delayed_tasks().Clear(); + pending_task_queue_.delayed_tasks().Clear(); } void MessageLoop::ScheduleWork() { @@ -463,17 +500,17 @@ bool MessageLoop::DoWork() { return false; // Execute oldest task. - while (incoming_task_queue_->triage_tasks().HasTasks()) { - PendingTask pending_task = incoming_task_queue_->triage_tasks().Pop(); + while (sequenced_task_source_->HasTasks()) { + PendingTask pending_task = sequenced_task_source_->TakeTask(); if (pending_task.task.IsCancelled()) continue; if (!pending_task.delayed_run_time.is_null()) { int sequence_num = pending_task.sequence_num; TimeTicks delayed_run_time = pending_task.delayed_run_time; - incoming_task_queue_->delayed_tasks().Push(std::move(pending_task)); + pending_task_queue_.delayed_tasks().Push(std::move(pending_task)); // If we changed the topmost task, then it is time to reschedule. - if (incoming_task_queue_->delayed_tasks().Peek().sequence_num == + if (pending_task_queue_.delayed_tasks().Peek().sequence_num == sequence_num) { pump_->ScheduleDelayedWork(delayed_run_time); } @@ -488,7 +525,7 @@ bool MessageLoop::DoWork() { bool MessageLoop::DoDelayedWork(TimeTicks* next_delayed_work_time) { if (!task_execution_allowed_ || - !incoming_task_queue_->delayed_tasks().HasTasks()) { + !pending_task_queue_.delayed_tasks().HasTasks()) { *next_delayed_work_time = TimeTicks(); return false; } @@ -501,7 +538,7 @@ bool MessageLoop::DoDelayedWork(TimeTicks* next_delayed_work_time) { // efficient we'll be at handling the tasks. TimeTicks next_run_time = - incoming_task_queue_->delayed_tasks().Peek().delayed_run_time; + pending_task_queue_.delayed_tasks().Peek().delayed_run_time; if (next_run_time > recent_time_) { recent_time_ = TimeTicks::Now(); // Get a better view of Now(); @@ -511,11 +548,11 @@ bool MessageLoop::DoDelayedWork(TimeTicks* next_delayed_work_time) { } } - PendingTask pending_task = incoming_task_queue_->delayed_tasks().Pop(); + PendingTask pending_task = pending_task_queue_.delayed_tasks().Pop(); - if (incoming_task_queue_->delayed_tasks().HasTasks()) { + if (pending_task_queue_.delayed_tasks().HasTasks()) { *next_delayed_work_time = CapAtOneDay( - incoming_task_queue_->delayed_tasks().Peek().delayed_run_time); + pending_task_queue_.delayed_tasks().Peek().delayed_run_time); } return DeferOrRunPendingTask(std::move(pending_task)); @@ -541,15 +578,14 @@ bool MessageLoop::DoIdleWork() { // only one UI thread per process and, for practical purposes, restricting // the MessageLoop diagnostic metrics to it yields similar information. if (type_ == TYPE_UI) - incoming_task_queue_->ReportMetricsOnIdle(); + pending_task_queue_.ReportMetricsOnIdle(); #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. - need_high_res_timers = - incoming_task_queue_->HasPendingHighResolutionTasks(); + need_high_res_timers = pending_task_queue_.HasPendingHighResolutionTasks(); #endif } |