diff --git a/engine/src/flutter/fml/BUILD.gn b/engine/src/flutter/fml/BUILD.gn index 285fdd6e32..c8fe26e3b1 100644 --- a/engine/src/flutter/fml/BUILD.gn +++ b/engine/src/flutter/fml/BUILD.gn @@ -13,6 +13,7 @@ source_set("fml") { "message_loop_impl.cc", "message_loop_impl.h", "paths.h", + "task_observer.h", "task_runner.cc", "task_runner.h", "thread.cc", diff --git a/engine/src/flutter/fml/message_loop.cc b/engine/src/flutter/fml/message_loop.cc index d2888d75e5..87fc88e8f2 100644 --- a/engine/src/flutter/fml/message_loop.cc +++ b/engine/src/flutter/fml/message_loop.cc @@ -63,8 +63,12 @@ ftl::RefPtr MessageLoop::GetLoopImpl() const { return loop_; } -void MessageLoop::SetTaskObserver(TaskObserver observer) { - loop_->SetTaskObserver(std::move(observer)); +void MessageLoop::AddTaskObserver(TaskObserver* observer) { + loop_->AddTaskObserver(observer); +} + +void MessageLoop::RemoveTaskObserver(TaskObserver* observer) { + loop_->RemoveTaskObserver(observer); } } // namespace fml diff --git a/engine/src/flutter/fml/message_loop.h b/engine/src/flutter/fml/message_loop.h index 04853deb0d..cf49b4186a 100644 --- a/engine/src/flutter/fml/message_loop.h +++ b/engine/src/flutter/fml/message_loop.h @@ -5,6 +5,7 @@ #ifndef FLUTTER_FML_MESSAGE_LOOP_H_ #define FLUTTER_FML_MESSAGE_LOOP_H_ +#include "flutter/fml/task_observer.h" #include "lib/ftl/macros.h" #include "lib/ftl/tasks/task_runner.h" @@ -23,9 +24,9 @@ class MessageLoop { void Terminate(); - using TaskObserver = std::function; + void AddTaskObserver(TaskObserver* observer); - void SetTaskObserver(TaskObserver observer); + void RemoveTaskObserver(TaskObserver* observer); ftl::RefPtr GetTaskRunner() const; diff --git a/engine/src/flutter/fml/message_loop_impl.cc b/engine/src/flutter/fml/message_loop_impl.cc index eaaa3b5a95..56282a1a22 100644 --- a/engine/src/flutter/fml/message_loop_impl.cc +++ b/engine/src/flutter/fml/message_loop_impl.cc @@ -4,6 +4,9 @@ #include "flutter/fml/message_loop_impl.h" +#include +#include + #include "lib/ftl/build_config.h" #if OS_MACOSX @@ -46,11 +49,20 @@ void MessageLoopImpl::RunExpiredTasksNow() { WakeUp(RunExpiredTasksAndGetNextWake()); } -void MessageLoopImpl::SetTaskObserver(MessageLoop::TaskObserver observer) { +void MessageLoopImpl::AddTaskObserver(TaskObserver* observer) { + FTL_DCHECK(observer != nullptr); FTL_DCHECK(MessageLoop::GetCurrent().GetLoopImpl().get() == this) - << "Message loop task observer must be set on the same thread as the " + << "Message loop task observer must be added on the same thread as the " "loop."; - task_observer_ = observer; + task_observers_.insert(observer); +} + +void MessageLoopImpl::RemoveTaskObserver(TaskObserver* observer) { + FTL_DCHECK(observer != nullptr); + FTL_DCHECK(MessageLoop::GetCurrent().GetLoopImpl().get() == this) + << "Message loop task observer must be removed from the same thread as " + "the loop."; + task_observers_.erase(observer); } void MessageLoopImpl::DoRun() { @@ -121,8 +133,8 @@ ftl::TimePoint MessageLoopImpl::RunExpiredTasksAndGetNextWake() { for (const auto& invocation : invocations) { invocation(); - if (task_observer_) { - task_observer_(); + for (const auto& observer : task_observers_) { + observer->DidProcessTask(); } } diff --git a/engine/src/flutter/fml/message_loop_impl.h b/engine/src/flutter/fml/message_loop_impl.h index b018b2fa1b..572778e0cc 100644 --- a/engine/src/flutter/fml/message_loop_impl.h +++ b/engine/src/flutter/fml/message_loop_impl.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include "flutter/fml/message_loop.h" @@ -34,7 +35,9 @@ class MessageLoopImpl : public ftl::RefCountedThreadSafe { void PostTask(ftl::Closure task, ftl::TimePoint target_time); - void SetTaskObserver(MessageLoop::TaskObserver observer); + void AddTaskObserver(TaskObserver* observer); + + void RemoveTaskObserver(TaskObserver* observer); void DoRun(); @@ -67,7 +70,7 @@ class MessageLoopImpl : public ftl::RefCountedThreadSafe { using DelayedTaskQueue = std:: priority_queue, DelayedTaskCompare>; - MessageLoop::TaskObserver task_observer_; + std::set task_observers_; ftl::Mutex delayed_tasks_mutex_; DelayedTaskQueue delayed_tasks_ FTL_GUARDED_BY(delayed_tasks_mutex_); size_t order_ FTL_GUARDED_BY(delayed_tasks_mutex_); diff --git a/engine/src/flutter/fml/message_loop_unittests.cc b/engine/src/flutter/fml/message_loop_unittests.cc index ea4d2781c0..1b36691315 100644 --- a/engine/src/flutter/fml/message_loop_unittests.cc +++ b/engine/src/flutter/fml/message_loop_unittests.cc @@ -238,6 +238,22 @@ TEST(MessageLoop, TIME_SENSITIVE(MultipleDelayedTasksWithDecreasingDeltas)) { ASSERT_EQ(checked, count); } +class CustomTaskObserver : public fml::TaskObserver { + public: + CustomTaskObserver(std::function lambda) : lambda_(lambda){}; + + ~CustomTaskObserver() override = default; + + void DidProcessTask() { + if (lambda_) { + lambda_(); + } + }; + + private: + std::function lambda_; +}; + TEST(MessageLoop, TaskObserverFire) { bool started = false; bool terminated = false; @@ -247,7 +263,7 @@ TEST(MessageLoop, TaskObserverFire) { auto& loop = fml::MessageLoop::GetCurrent(); size_t task_count = 0; size_t obs_count = 0; - loop.SetTaskObserver([&obs_count]() { obs_count++; }); + CustomTaskObserver obs([&obs_count]() { obs_count++; }); for (size_t i = 0; i < count; i++) { loop.GetTaskRunner()->PostTask([&terminated, count, i, &task_count]() { ASSERT_EQ(task_count, i); @@ -258,6 +274,7 @@ TEST(MessageLoop, TaskObserverFire) { } }); } + loop.AddTaskObserver(&obs); loop.Run(); ASSERT_EQ(task_count, count); ASSERT_EQ(obs_count, count); diff --git a/engine/src/flutter/fml/task_observer.h b/engine/src/flutter/fml/task_observer.h new file mode 100644 index 0000000000..b22a9bc43a --- /dev/null +++ b/engine/src/flutter/fml/task_observer.h @@ -0,0 +1,21 @@ +// Copyright 2017 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 FLUTTER_FML_TASK_OBSERVER_H_ +#define FLUTTER_FML_TASK_OBSERVER_H_ + +#include "lib/ftl/macros.h" + +namespace fml { + +class TaskObserver { + public: + virtual ~TaskObserver() = default; + + virtual void DidProcessTask() = 0; +}; + +} // namespace fml + +#endif // FLUTTER_FML_TASK_OBSERVER_H_