From 151ab6d4c59ea848665128e26258517bbf167192 Mon Sep 17 00:00:00 2001 From: weiguoliang Date: Thu, 10 Feb 2022 14:31:51 +0800 Subject: [PATCH] Split out the thread data and the thread data set operator --- fml/concurrent_message_loop.cc | 4 +- fml/thread.cc | 91 ++++++++--------- fml/thread.h | 47 ++++----- fml/thread_unittests.cc | 69 ++++++------- lib/ui/ui_benchmarks.cc | 12 +-- shell/common/shell_benchmarks.cc | 4 +- shell/common/shell_unittests.cc | 17 ++-- shell/common/thread_host.cc | 50 +++++----- shell/common/thread_host.h | 54 +++++++--- .../android/android_context_gl_unittests.cc | 22 +++-- .../platform/android/android_shell_holder.cc | 99 +++++++++---------- .../ios/framework/Source/FlutterEngine.mm | 86 ++++++++-------- .../platform/embedder/embedder_thread_host.cc | 9 +- shell/platform/fuchsia/flutter/engine.cc | 3 +- 14 files changed, 295 insertions(+), 272 deletions(-) diff --git a/fml/concurrent_message_loop.cc b/fml/concurrent_message_loop.cc index b58431b7df3d2..f352467c44f50 100644 --- a/fml/concurrent_message_loop.cc +++ b/fml/concurrent_message_loop.cc @@ -21,8 +21,8 @@ ConcurrentMessageLoop::ConcurrentMessageLoop(size_t worker_count) : worker_count_(std::max(worker_count, 1ul)) { for (size_t i = 0; i < worker_count_; ++i) { workers_.emplace_back([i, this]() { - fml::Thread::SetCurrentThreadName( - std::string{"io.worker." + std::to_string(i + 1)}); + fml::Thread::SetCurrentThreadName(fml::Thread::ThreadConfig( + std::string{"io.worker." + std::to_string(i + 1)})); WorkerMain(); }); } diff --git a/fml/thread.cc b/fml/thread.cc index efe6f2cca2213..a905fd071eaa9 100644 --- a/fml/thread.cc +++ b/fml/thread.cc @@ -24,53 +24,6 @@ namespace fml { -Thread::ThreadConfig::ThreadConfig(const std::string& name, - ThreadPriority priority) - : thread_name_(name), thread_priority_(priority) {} - -void Thread::ThreadConfig::SetCurrentThreadName() const { - Thread::SetCurrentThreadName(thread_name_); -} - -void Thread::ThreadConfig::SetCurrentThreadPriority() const {} - -Thread::Thread(const std::string& name) - : Thread(ThreadConfig::MakeDefaultConfigure(name)) {} - -Thread::Thread(std::unique_ptr config) : joined_(false) { - fml::AutoResetWaitableEvent latch; - fml::RefPtr runner; - thread_ = std::make_unique( - [&latch, &runner, threadConfig = std::move(config)]() -> void { - threadConfig->SetCurrentThreadName(); - threadConfig->SetCurrentThreadPriority(); - fml::MessageLoop::EnsureInitializedForCurrentThread(); - auto& loop = MessageLoop::GetCurrent(); - runner = loop.GetTaskRunner(); - latch.Signal(); - loop.Run(); - }); - latch.Wait(); - task_runner_ = runner; -} - -Thread::~Thread() { - Join(); -} - -fml::RefPtr Thread::GetTaskRunner() const { - return task_runner_; -} - -void Thread::Join() { - if (joined_) { - return; - } - joined_ = true; - task_runner_->PostTask([]() { MessageLoop::GetCurrent().Terminate(); }); - thread_->join(); -} - #if defined(FML_OS_WIN) // The information on how to set the thread name comes from // a MSDN article: http://msdn2.microsoft.com/en-us/library/xcb2z8hs.aspx @@ -83,7 +36,7 @@ typedef struct tagTHREADNAME_INFO { } THREADNAME_INFO; #endif -void Thread::SetCurrentThreadName(const std::string& name) { +void SetThreadName(const std::string& name) { if (name == "") { return; } @@ -110,4 +63,46 @@ void Thread::SetCurrentThreadName(const std::string& name) { #endif } +void Thread::SetCurrentThreadName(const Thread::ThreadConfig& config) { + SetThreadName(config.name); +} + +Thread::Thread(const std::string& name) + : Thread(Thread::SetCurrentThreadName, ThreadConfig(name)) {} + +Thread::Thread(const ThreadConfigSetter& setter, const ThreadConfig& config) + : joined_(false) { + fml::AutoResetWaitableEvent latch; + fml::RefPtr runner; + + thread_ = std::make_unique( + [&latch, &runner, setter, config]() -> void { + setter(config); + fml::MessageLoop::EnsureInitializedForCurrentThread(); + auto& loop = MessageLoop::GetCurrent(); + runner = loop.GetTaskRunner(); + latch.Signal(); + loop.Run(); + }); + latch.Wait(); + task_runner_ = runner; +} + +Thread::~Thread() { + Join(); +} + +fml::RefPtr Thread::GetTaskRunner() const { + return task_runner_; +} + +void Thread::Join() { + if (joined_) { + return; + } + joined_ = true; + task_runner_->PostTask([]() { MessageLoop::GetCurrent().Terminate(); }); + thread_->join(); +} + } // namespace fml diff --git a/fml/thread.h b/fml/thread.h index 653a7541e9a4d..0b176c2ff5d6f 100644 --- a/fml/thread.h +++ b/fml/thread.h @@ -6,6 +6,7 @@ #define FLUTTER_FML_THREAD_H_ #include +#include #include #include #include @@ -29,40 +30,26 @@ class Thread { RASTER, }; - /// The ThreadConfig is used for setting thread perorities. - class ThreadConfig { - public: - explicit ThreadConfig(const std::string& name = "", - ThreadPriority priority = ThreadPriority::NORMAL); + /// The ThreadConfig is the thread info include thread name, thread priority. + struct ThreadConfig { + ThreadConfig(const std::string& name, ThreadPriority priority) + : name(name), priority(priority) {} - static std::unique_ptr MakeDefaultConfigure( - const std::string& name = "") { - return std::make_unique(name); - } + explicit ThreadConfig(const std::string& name) + : ThreadConfig(name, ThreadPriority::NORMAL) {} - ThreadPriority GetThreadPriority() const { return thread_priority_; } + ThreadConfig() : ThreadConfig("", ThreadPriority::NORMAL) {} - const std::string& GetThreadName() const { return thread_name_; } - - /// Set current thread name. - virtual void SetCurrentThreadName() const; - - /// default do nothing, which mean user can use platform api to set priority - /// example: iOS might use pthread_qos set thread priority, Android might - /// use ::setPriority set thread priority - virtual void SetCurrentThreadPriority() const; - - virtual ~ThreadConfig() = default; - - private: - const std::string thread_name_; - ThreadPriority thread_priority_; + std::string name; + ThreadPriority priority; }; - explicit Thread(const std::string& name); + using ThreadConfigSetter = std::function; - explicit Thread(std::unique_ptr config = - ThreadConfig::MakeDefaultConfigure()); + explicit Thread(const std::string& name = ""); + + explicit Thread(const ThreadConfigSetter& setter, + const ThreadConfig& config = ThreadConfig()); ~Thread(); @@ -70,11 +57,13 @@ class Thread { void Join(); - static void SetCurrentThreadName(const std::string& name); + static void SetCurrentThreadName(const ThreadConfig& config); private: std::unique_ptr thread_; + fml::RefPtr task_runner_; + std::atomic_bool joined_; FML_DISALLOW_COPY_AND_ASSIGN(Thread); diff --git a/fml/thread_unittests.cc b/fml/thread_unittests.cc index cc4449c96413f..6e8001ac8b0bd 100644 --- a/fml/thread_unittests.cc +++ b/fml/thread_unittests.cc @@ -4,13 +4,15 @@ #include "flutter/fml/thread.h" -#define FLUTTER_PTHREAD_SUPPORTED \ - defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_ANDROID) +#if defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_ANDROID) +#define FLUTTER_PTHREAD_SUPPORTED 1 +#else +#define FLUTTER_PTHREAD_SUPPORTED 0 +#endif -#ifdef FLUTTER_PTHREAD_SUPPORTED +#if FLUTTER_PTHREAD_SUPPORTED #include #else -#error "Doesn't has pthead.h" #endif #include @@ -35,71 +37,70 @@ TEST(Thread, HasARunningMessageLoop) { ASSERT_TRUE(done); } -#ifdef FLUTTER_PTHREAD_SUPPORTED +#if FLUTTER_PTHREAD_SUPPORTED TEST(Thread, ThreadNameCreatedWithConfig) { const std::string name = "Thread1"; - fml::Thread thread(fml::Thread::ThreadConfig::MakeDefaultConfigure(name)); + fml::Thread thread(name); bool done = false; - constexpr int NAMELEN = 8; thread.GetTaskRunner()->PostTask([&done, &name]() { done = true; - char thread_name[NAMELEN]; + char thread_name[8]; pthread_t current_thread = pthread_self(); - pthread_getname_np(current_thread, thread_name, NAMELEN); + pthread_getname_np(current_thread, thread_name, 8); ASSERT_EQ(thread_name, name); }); thread.Join(); ASSERT_TRUE(done); } -class MockThreadConfig : public fml::Thread::ThreadConfig { - public: - using fml::Thread::ThreadConfig::ThreadConfig; +static void MockThreadConfigSetter(const fml::Thread::ThreadConfig& config) { + // set thread name + fml::Thread::SetCurrentThreadName(config); - void SetCurrentThreadPriority() const override { - pthread_t tid = pthread_self(); - struct sched_param param; - int policy = SCHED_OTHER; - switch (GetThreadPriority()) { - case fml::Thread::ThreadPriority::DISPLAY: - param.sched_priority = 10; - break; - default: - param.sched_priority = 1; - } - pthread_setschedparam(tid, policy, ¶m); + pthread_t tid = pthread_self(); + struct sched_param param; + int policy = SCHED_OTHER; + switch (config.priority) { + case fml::Thread::ThreadPriority::DISPLAY: + param.sched_priority = 10; + break; + default: + param.sched_priority = 1; } -}; + pthread_setschedparam(tid, policy, ¶m); +} TEST(Thread, ThreadPriorityCreatedWithConfig) { const std::string thread1_name = "Thread1"; const std::string thread2_name = "Thread2"; - fml::Thread thread(std::make_unique( - thread1_name, fml::Thread::ThreadPriority::NORMAL)); + fml::Thread thread(MockThreadConfigSetter, + fml::Thread::ThreadConfig( + thread1_name, fml::Thread::ThreadPriority::NORMAL)); bool done = false; - constexpr int NAMELEN = 8; + struct sched_param param; int policy; thread.GetTaskRunner()->PostTask([&]() { done = true; - char thread_name[NAMELEN]; + char thread_name[8]; pthread_t current_thread = pthread_self(); - pthread_getname_np(current_thread, thread_name, NAMELEN); + pthread_getname_np(current_thread, thread_name, 8); pthread_getschedparam(current_thread, &policy, ¶m); ASSERT_EQ(thread_name, thread1_name); ASSERT_EQ(policy, SCHED_OTHER); ASSERT_EQ(param.sched_priority, 1); }); - fml::Thread thread2(std::make_unique( - thread2_name, fml::Thread::ThreadPriority::DISPLAY)); + fml::Thread thread2(MockThreadConfigSetter, + fml::Thread::ThreadConfig( + thread2_name, fml::Thread::ThreadPriority::DISPLAY)); thread2.GetTaskRunner()->PostTask([&]() { done = true; - char thread_name[NAMELEN]; + char thread_name[8]; pthread_t current_thread = pthread_self(); - pthread_getname_np(current_thread, thread_name, NAMELEN); + pthread_getname_np(current_thread, thread_name, 8); pthread_getschedparam(current_thread, &policy, ¶m); ASSERT_EQ(thread_name, thread2_name); ASSERT_EQ(policy, SCHED_OTHER); diff --git a/lib/ui/ui_benchmarks.cc b/lib/ui/ui_benchmarks.cc index a88877dac798d..4c8239b0f5dfe 100644 --- a/lib/ui/ui_benchmarks.cc +++ b/lib/ui/ui_benchmarks.cc @@ -20,9 +20,9 @@ class Fixture : public testing::FixtureTest { }; static void BM_PlatformMessageResponseDartComplete(benchmark::State& state) { - ThreadHost thread_host("test", - ThreadHost::Type::Platform | ThreadHost::Type::RASTER | - ThreadHost::Type::IO | ThreadHost::Type::UI); + ThreadHost thread_host(ThreadHost::ThreadHostConfig( + "test", ThreadHost::Type::Platform | ThreadHost::Type::RASTER | + ThreadHost::Type::IO | ThreadHost::Type::UI)); TaskRunners task_runners("test", thread_host.platform_thread->GetTaskRunner(), thread_host.raster_thread->GetTaskRunner(), thread_host.ui_thread->GetTaskRunner(), @@ -68,9 +68,9 @@ static void BM_PlatformMessageResponseDartComplete(benchmark::State& state) { } static void BM_PathVolatilityTracker(benchmark::State& state) { - ThreadHost thread_host("test", - ThreadHost::Type::Platform | ThreadHost::Type::RASTER | - ThreadHost::Type::IO | ThreadHost::Type::UI); + ThreadHost thread_host(ThreadHost::ThreadHostConfig( + "test", ThreadHost::Type::Platform | ThreadHost::Type::RASTER | + ThreadHost::Type::IO | ThreadHost::Type::UI)); TaskRunners task_runners("test", thread_host.platform_thread->GetTaskRunner(), thread_host.raster_thread->GetTaskRunner(), thread_host.ui_thread->GetTaskRunner(), diff --git a/shell/common/shell_benchmarks.cc b/shell/common/shell_benchmarks.cc index cf73ab352fcf7..09a696c8af026 100644 --- a/shell/common/shell_benchmarks.cc +++ b/shell/common/shell_benchmarks.cc @@ -43,10 +43,10 @@ static void StartupAndShutdownShell(benchmark::State& state, }; } - thread_host = std::make_unique( + thread_host = std::make_unique(ThreadHost::ThreadHostConfig( "io.flutter.bench.", ThreadHost::Type::Platform | ThreadHost::Type::RASTER | - ThreadHost::Type::IO | ThreadHost::Type::UI); + ThreadHost::Type::IO | ThreadHost::Type::UI)); TaskRunners task_runners("test", thread_host->platform_thread->GetTaskRunner(), diff --git a/shell/common/shell_unittests.cc b/shell/common/shell_unittests.cc index 8df8ec96aaf76..06ef8c795ce1a 100644 --- a/shell/common/shell_unittests.cc +++ b/shell/common/shell_unittests.cc @@ -264,9 +264,10 @@ TEST_F(ShellTest, InitializeWithInvalidThreads) { TEST_F(ShellTest, InitializeWithDifferentThreads) { ASSERT_FALSE(DartVMRef::IsInstanceRunning()); Settings settings = CreateSettingsForFixture(); - ThreadHost thread_host("io.flutter.test." + GetCurrentTestName() + ".", - ThreadHost::Type::Platform | ThreadHost::Type::RASTER | - ThreadHost::Type::IO | ThreadHost::Type::UI); + ThreadHost thread_host(ThreadHost::ThreadHostConfig( + "io.flutter.test." + GetCurrentTestName() + ".", + ThreadHost::Type::Platform | ThreadHost::Type::RASTER | + ThreadHost::Type::IO | ThreadHost::Type::UI)); TaskRunners task_runners("test", thread_host.platform_thread->GetTaskRunner(), thread_host.raster_thread->GetTaskRunner(), thread_host.ui_thread->GetTaskRunner(), @@ -3112,8 +3113,9 @@ TEST_F(ShellTest, UpdateAssetResolverByTypeAppends) { TEST_F(ShellTest, UpdateAssetResolverByTypeNull) { ASSERT_FALSE(DartVMRef::IsInstanceRunning()); Settings settings = CreateSettingsForFixture(); - ThreadHost thread_host("io.flutter.test." + GetCurrentTestName() + ".", - ThreadHost::Type::Platform); + ThreadHost thread_host(ThreadHost::ThreadHostConfig( + "io.flutter.test." + GetCurrentTestName() + ".", + ThreadHost::Type::Platform)); auto task_runner = thread_host.platform_thread->GetTaskRunner(); TaskRunners task_runners("test", task_runner, task_runner, task_runner, task_runner); @@ -3149,8 +3151,9 @@ TEST_F(ShellTest, UpdateAssetResolverByTypeNull) { TEST_F(ShellTest, UpdateAssetResolverByTypeDoesNotReplaceMismatchType) { ASSERT_FALSE(DartVMRef::IsInstanceRunning()); Settings settings = CreateSettingsForFixture(); - ThreadHost thread_host("io.flutter.test." + GetCurrentTestName() + ".", - ThreadHost::Type::Platform); + ThreadHost thread_host(ThreadHost::ThreadHostConfig( + "io.flutter.test." + GetCurrentTestName() + ".", + ThreadHost::Type::Platform)); auto task_runner = thread_host.platform_thread->GetTaskRunner(); TaskRunners task_runners("test", task_runner, task_runner, task_runner, task_runner); diff --git a/shell/common/thread_host.cc b/shell/common/thread_host.cc index 87513a5e9a4d0..b79ed6c99a0da 100644 --- a/shell/common/thread_host.cc +++ b/shell/common/thread_host.cc @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -30,49 +31,46 @@ std::string ThreadHost::ThreadHostConfig::MakeThreadName( std::unique_ptr ThreadHost::CreateThread( Type type, - ThreadHost::ThreadConfig configure) { - std::string name = ThreadHostConfig::MakeThreadName(type, name_prefix); - if (configure != nullptr) { - return std::make_unique(std::move(configure)); + std::optional thread_config, + const ThreadHostConfig& host_config) const { + /// if not specified ThreadConfig, create a ThreadConfig. + if (!thread_config.has_value()) { + thread_config = ThreadConfig( + ThreadHostConfig::MakeThreadName(type, host_config.name_prefix)); } - return std::make_unique( - fml::Thread::ThreadConfig::MakeDefaultConfigure(name)); + return std::make_unique(host_config.config_setter, + thread_config.value()); } ThreadHost::ThreadHost() = default; ThreadHost::ThreadHost(ThreadHost&&) = default; -ThreadHost::ThreadHost(std::string name_prefix_arg, - uint64_t mask, - ThreadHostConfig configure_host) - : name_prefix(name_prefix_arg) { - if (mask & ThreadHost::Type::Platform) { +ThreadHost::ThreadHost(const std::string name_prefix, uint64_t mask) + : ThreadHost(ThreadHostConfig(name_prefix, mask)) {} + +ThreadHost::ThreadHost(const ThreadHostConfig& host_config) { + if (host_config.isThreadNeeded(ThreadHost::Type::Platform)) { platform_thread = - CreateThread(ThreadHost::Type::Platform, - std::move(configure_host.platform_configure)); + CreateThread(Type::Platform, host_config.platform_config, host_config); } - if (mask & ThreadHost::Type::UI) { - ui_thread = CreateThread(ThreadHost::Type::UI, - std::move(configure_host.ui_configure)); + if (host_config.isThreadNeeded(ThreadHost::Type::UI)) { + ui_thread = CreateThread(Type::UI, host_config.ui_config, host_config); } - if (mask & ThreadHost::Type::RASTER) { - raster_thread = CreateThread(ThreadHost::Type::RASTER, - std::move(configure_host.raster_configure)); + if (host_config.isThreadNeeded(ThreadHost::Type::RASTER)) { + raster_thread = + CreateThread(Type::RASTER, host_config.raster_config, host_config); } - if (mask & ThreadHost::Type::IO) { - io_thread = CreateThread(ThreadHost::Type::IO, - std::move(configure_host.io_configure)); + if (host_config.isThreadNeeded(ThreadHost::Type::IO)) { + io_thread = CreateThread(Type::IO, host_config.io_config, host_config); } - if (mask & ThreadHost::Type::Profiler) { + if (host_config.isThreadNeeded(ThreadHost::Type::Profiler)) { profiler_thread = - CreateThread(ThreadHost::Type::Profiler, - std::move(configure_host.profiler_configure)); - ; + CreateThread(Type::Profiler, host_config.profiler_config, host_config); } } diff --git a/shell/common/thread_host.h b/shell/common/thread_host.h index 8635cbfcabfd8..8586740a6c940 100644 --- a/shell/common/thread_host.h +++ b/shell/common/thread_host.h @@ -6,6 +6,7 @@ #define FLUTTER_SHELL_COMMON_THREAD_HOST_H_ #include +#include #include #include "flutter/fml/macros.h" @@ -13,6 +14,9 @@ namespace flutter { +using ThreadConfig = fml::Thread::ThreadConfig; +using ThreadConfigSetter = fml::Thread::ThreadConfigSetter; + /// The collection of all the threads used by the engine. struct ThreadHost { enum Type { @@ -23,18 +27,39 @@ struct ThreadHost { Profiler = 1 << 4, }; - using ThreadConfig = std::unique_ptr; /// The collection of all the thread configures, and we create custom thread /// configure in engine to info the thread. struct ThreadHostConfig { - ThreadConfig platform_configure; - ThreadConfig ui_configure; - ThreadConfig raster_configure; - ThreadConfig io_configure; - ThreadConfig profiler_configure; - - static std::string MakeThreadName(Type type, - const std::string& prefix = ""); + ThreadHostConfig() : type_mask(0) {} + + explicit ThreadHostConfig( + const std::string& name_prefix, + uint64_t mask, + const ThreadConfigSetter& setter = fml::Thread::SetCurrentThreadName) + : type_mask(mask), name_prefix(name_prefix), config_setter(setter) {} + + explicit ThreadHostConfig( + uint64_t mask, + const ThreadConfigSetter& setter = fml::Thread::SetCurrentThreadName) + : ThreadHostConfig("", mask, setter) {} + + /// Check if need to create thread. + bool isThreadNeeded(Type type) const { return type_mask & type; } + + /// Use the prefix and thread type to generator a thread name. + static std::string MakeThreadName(Type type, const std::string& prefix); + + uint64_t type_mask; + + std::string name_prefix = ""; + + const ThreadConfigSetter config_setter; + + std::optional platform_config; + std::optional ui_config; + std::optional raster_config; + std::optional io_config; + std::optional profiler_config; }; std::string name_prefix; @@ -50,14 +75,17 @@ struct ThreadHost { ThreadHost& operator=(ThreadHost&&) = default; - ThreadHost(std::string name_prefix, - uint64_t type_mask, - ThreadHostConfig configure_host = ThreadHostConfig()); + ThreadHost(const std::string name_prefix, uint64_t mask); + + explicit ThreadHost(const ThreadHostConfig& host_config); ~ThreadHost(); private: - std::unique_ptr CreateThread(Type type, ThreadConfig configure); + std::unique_ptr CreateThread( + Type type, + std::optional thread_config, + const ThreadHostConfig& host_config) const; }; } // namespace flutter diff --git a/shell/platform/android/android_context_gl_unittests.cc b/shell/platform/android/android_context_gl_unittests.cc index 4205864189a0b..9b376bc848233 100644 --- a/shell/platform/android/android_context_gl_unittests.cc +++ b/shell/platform/android/android_context_gl_unittests.cc @@ -80,9 +80,10 @@ TEST(AndroidContextGl, Create) { auto environment = fml::MakeRefCounted(); std::string thread_label = ::testing::UnitTest::GetInstance()->current_test_info()->name(); - ThreadHost thread_host(thread_label, ThreadHost::Type::UI | - ThreadHost::Type::RASTER | - ThreadHost::Type::IO); + + ThreadHost thread_host(ThreadHost::ThreadHostConfig( + thread_label, + ThreadHost::Type::UI | ThreadHost::Type::RASTER | ThreadHost::Type::IO)); TaskRunners task_runners = MakeTaskRunners(thread_label, thread_host); auto context = std::make_unique( AndroidRenderingAPI::kOpenGLES, environment, task_runners); @@ -120,9 +121,9 @@ TEST(AndroidSurfaceGL, CreateSnapshopSurfaceWhenOnscreenSurfaceIsNotNull) { auto environment = fml::MakeRefCounted(); std::string thread_label = ::testing::UnitTest::GetInstance()->current_test_info()->name(); - ThreadHost thread_host(thread_label, ThreadHost::Type::UI | - ThreadHost::Type::RASTER | - ThreadHost::Type::IO); + ThreadHost thread_host(ThreadHost::ThreadHostConfig( + thread_label, + ThreadHost::Type::UI | ThreadHost::Type::RASTER | ThreadHost::Type::IO)); TaskRunners task_runners = MakeTaskRunners(thread_label, thread_host); auto android_context = std::make_shared( AndroidRenderingAPI::kOpenGLES, environment, task_runners); @@ -145,9 +146,12 @@ TEST(AndroidSurfaceGL, CreateSnapshopSurfaceWhenOnscreenSurfaceIsNull) { auto environment = fml::MakeRefCounted(); std::string thread_label = ::testing::UnitTest::GetInstance()->current_test_info()->name(); - ThreadHost thread_host(thread_label, ThreadHost::Type::UI | - ThreadHost::Type::RASTER | - ThreadHost::Type::IO); + + auto mask = + ThreadHost::Type::UI | ThreadHost::Type::RASTER | ThreadHost::Type::IO; + flutter::ThreadHost::ThreadHostConfig host_config(mask); + + ThreadHost thread_host(host_config); TaskRunners task_runners = MakeTaskRunners(thread_label, thread_host); auto android_context = std::make_shared( AndroidRenderingAPI::kOpenGLES, environment, task_runners); diff --git a/shell/platform/android/android_shell_holder.cc b/shell/platform/android/android_shell_holder.cc index 16bb0d903ce3e..14e8555c40c16 100644 --- a/shell/platform/android/android_shell_holder.cc +++ b/shell/platform/android/android_shell_holder.cc @@ -34,45 +34,43 @@ namespace flutter { /// Inheriting ThreadConfigurer and use Android platform thread API to configure /// the thread priorities -class PlatformAndroidThreadConfig : public fml::Thread::ThreadConfig { - public: - using fml::Thread::ThreadConfig::ThreadConfig; - - void SetCurrentThreadPriority() const override { - switch (GetThreadPriority()) { - case fml::Thread::ThreadPriority::BACKGROUND: { - if (::setpriority(PRIO_PROCESS, 0, 10) != 0) { - FML_LOG(ERROR) << "Failed to set IO task runner priority"; - } - break; +static void AndroidPlatformThreadConfigSetter( + const fml::Thread::ThreadConfig& config) { + // set thread name + fml::Thread::SetCurrentThreadName(config); + // set thread priority + switch (config.priority) { + case fml::Thread::ThreadPriority::BACKGROUND: { + if (::setpriority(PRIO_PROCESS, 0, 10) != 0) { + FML_LOG(ERROR) << "Failed to set IO task runner priority"; } - case fml::Thread::ThreadPriority::DISPLAY: { - if (::setpriority(PRIO_PROCESS, 0, -1) != 0) { - FML_LOG(ERROR) << "Failed to set UI task runner priority"; - } - break; + break; + } + case fml::Thread::ThreadPriority::DISPLAY: { + if (::setpriority(PRIO_PROCESS, 0, -1) != 0) { + FML_LOG(ERROR) << "Failed to set UI task runner priority"; } - case fml::Thread::ThreadPriority::RASTER: { - // Android describes -8 as "most important display threads, for - // compositing the screen and retrieving input events". Conservatively - // set the raster thread to slightly lower priority than it. - if (::setpriority(PRIO_PROCESS, 0, -5) != 0) { - // Defensive fallback. Depending on the OEM, it may not be possible - // to set priority to -5. - if (::setpriority(PRIO_PROCESS, 0, -2) != 0) { - FML_LOG(ERROR) << "Failed to set raster task runner priority"; - } + break; + } + case fml::Thread::ThreadPriority::RASTER: { + // Android describes -8 as "most important display threads, for + // compositing the screen and retrieving input events". Conservatively + // set the raster thread to slightly lower priority than it. + if (::setpriority(PRIO_PROCESS, 0, -5) != 0) { + // Defensive fallback. Depending on the OEM, it may not be possible + // to set priority to -5. + if (::setpriority(PRIO_PROCESS, 0, -2) != 0) { + FML_LOG(ERROR) << "Failed to set raster task runner priority"; } - break; } - default: - if (::setpriority(PRIO_PROCESS, 0, 0) != 0) { - FML_LOG(ERROR) << "Failed to set priority"; - } + break; } + default: + if (::setpriority(PRIO_PROCESS, 0, 0) != 0) { + FML_LOG(ERROR) << "Failed to set priority"; + } } -}; - +} static PlatformData GetDefaultPlatformData() { PlatformData platform_data; platform_data.lifecycle_state = "AppLifecycleState.detached"; @@ -86,24 +84,25 @@ AndroidShellHolder::AndroidShellHolder( static size_t thread_host_count = 1; auto thread_label = std::to_string(thread_host_count++); - auto ui_thread_name = flutter::ThreadHost::ThreadHostConfig::MakeThreadName( - flutter::ThreadHost::Type::UI, thread_label); - auto raster_thread_name = + auto mask = + ThreadHost::Type::UI | ThreadHost::Type::RASTER | ThreadHost::Type::IO; + + flutter::ThreadHost::ThreadHostConfig host_config( + mask, AndroidPlatformThreadConfigSetter); + host_config.ui_config = fml::Thread::ThreadConfig( flutter::ThreadHost::ThreadHostConfig::MakeThreadName( - flutter::ThreadHost::Type::RASTER, thread_label); - auto io_thread_name = flutter::ThreadHost::ThreadHostConfig::MakeThreadName( - flutter::ThreadHost::Type::IO, thread_label); - - thread_host_ = std::make_shared( - thread_label, - ThreadHost::Type::UI | ThreadHost::Type::RASTER | ThreadHost::Type::IO, - (flutter::ThreadHost::ThreadHostConfig){ - .ui_configure = std::make_unique( - ui_thread_name, fml::Thread::ThreadPriority::DISPLAY), - .raster_configure = std::make_unique( - raster_thread_name, fml::Thread::ThreadPriority::RASTER), - .io_configure = std::make_unique( - io_thread_name, fml::Thread::ThreadPriority::BACKGROUND)}); + flutter::ThreadHost::Type::UI, thread_label), + fml::Thread::ThreadPriority::DISPLAY); + host_config.raster_config = fml::Thread::ThreadConfig( + flutter::ThreadHost::ThreadHostConfig::MakeThreadName( + flutter::ThreadHost::Type::RASTER, thread_label), + fml::Thread::ThreadPriority::RASTER); + host_config.io_config = fml::Thread::ThreadConfig( + flutter::ThreadHost::ThreadHostConfig::MakeThreadName( + flutter::ThreadHost::Type::IO, thread_label), + fml::Thread::ThreadPriority::BACKGROUND); + + thread_host_ = std::make_shared(host_config); fml::WeakPtr weak_platform_view; Shell::CreateCallback on_create_platform_view = diff --git a/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm b/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm index e5fe74a0c91d6..812f2d32e720c 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm @@ -35,36 +35,35 @@ #include "flutter/shell/profiling/sampling_profiler.h" /// Inheriting ThreadConfigurer and use iOS platform thread API to configure the thread priorities -class PlatformIOSThreadConfig : public fml::Thread::ThreadConfig { - public: - using fml::Thread::ThreadConfig::ThreadConfig; - - /// Using iOS platform thread API to configure thread priority - void SetCurrentThreadPriority() const override { - switch (GetThreadPriority()) { - case fml::Thread::ThreadPriority::BACKGROUND: { - [[NSThread currentThread] setThreadPriority:0]; - break; - } - case fml::Thread::ThreadPriority::NORMAL: { - [[NSThread currentThread] setThreadPriority:0.5]; - break; - } - case fml::Thread::ThreadPriority::RASTER: - case fml::Thread::ThreadPriority::DISPLAY: { - [[NSThread currentThread] setThreadPriority:1.0]; - sched_param param; - int policy; - pthread_t thread = pthread_self(); - if (!pthread_getschedparam(thread, &policy, ¶m)) { - param.sched_priority = 50; - pthread_setschedparam(thread, policy, ¶m); - } - break; +/// Using iOS platform thread API to configure thread priority +static void IOSPlatformThreadConfigSetter(const fml::Thread::ThreadConfig& config) { + // set thread name + fml::Thread::SetCurrentThreadName(config); + + // set thread priority + switch (config.priority) { + case fml::Thread::ThreadPriority::BACKGROUND: { + [[NSThread currentThread] setThreadPriority:0]; + break; + } + case fml::Thread::ThreadPriority::NORMAL: { + [[NSThread currentThread] setThreadPriority:0.5]; + break; + } + case fml::Thread::ThreadPriority::RASTER: + case fml::Thread::ThreadPriority::DISPLAY: { + [[NSThread currentThread] setThreadPriority:1.0]; + sched_param param; + int policy; + pthread_t thread = pthread_self(); + if (!pthread_getschedparam(thread, &policy, ¶m)) { + param.sched_priority = 50; + pthread_setschedparam(thread, policy, ¶m); } + break; } } -}; +} NSString* const FlutterDefaultDartEntrypoint = nil; NSString* const FlutterDefaultInitialRoute = nil; @@ -649,20 +648,25 @@ + (NSString*)generateThreadLabel:(NSString*)labelPrefix { if ([FlutterEngine isProfilerEnabled]) { threadHostType = threadHostType | flutter::ThreadHost::Type::Profiler; } - auto ui_thread_name = flutter::ThreadHost::ThreadHostConfig::MakeThreadName( - flutter::ThreadHost::Type::UI, threadLabel.UTF8String); - auto raster_thread_name = flutter::ThreadHost::ThreadHostConfig::MakeThreadName( - flutter::ThreadHost::Type::RASTER, threadLabel.UTF8String); - auto io_thread_name = flutter::ThreadHost::ThreadHostConfig::MakeThreadName( - flutter::ThreadHost::Type::IO, threadLabel.UTF8String); - return (flutter::ThreadHost){threadLabel.UTF8String, threadHostType, - (flutter::ThreadHost::ThreadHostConfig){ - .ui_configure = std::make_unique( - ui_thread_name, fml::Thread::ThreadPriority::DISPLAY), - .raster_configure = std::make_unique( - raster_thread_name, fml::Thread::ThreadPriority::RASTER), - .io_configure = std::make_unique( - io_thread_name, fml::Thread::ThreadPriority::BACKGROUND)}}; + + flutter::ThreadHost::ThreadHostConfig host_config(threadHostType, IOSPlatformThreadConfigSetter); + + host_config.ui_config = + fml::Thread::ThreadConfig(flutter::ThreadHost::ThreadHostConfig::MakeThreadName( + flutter::ThreadHost::Type::UI, threadLabel.UTF8String), + fml::Thread::ThreadPriority::DISPLAY); + + host_config.raster_config = + fml::Thread::ThreadConfig(flutter::ThreadHost::ThreadHostConfig::MakeThreadName( + flutter::ThreadHost::Type::RASTER, threadLabel.UTF8String), + fml::Thread::ThreadPriority::RASTER); + + host_config.io_config = + fml::Thread::ThreadConfig(flutter::ThreadHost::ThreadHostConfig::MakeThreadName( + flutter::ThreadHost::Type::IO, threadLabel.UTF8String), + fml::Thread::ThreadPriority::BACKGROUND); + + return (flutter::ThreadHost){host_config}; } static void SetEntryPoint(flutter::Settings* settings, NSString* entrypoint, NSString* libraryURI) { diff --git a/shell/platform/embedder/embedder_thread_host.cc b/shell/platform/embedder/embedder_thread_host.cc index 1f02eead41118..30955caa6622c 100644 --- a/shell/platform/embedder/embedder_thread_host.cc +++ b/shell/platform/embedder/embedder_thread_host.cc @@ -154,7 +154,8 @@ EmbedderThreadHost::CreateEmbedderManagedThreadHost( // Create a thread host with just the threads that need to be managed by the // engine. The embedder has provided the rest. - ThreadHost thread_host(kFlutterThreadName, engine_thread_host_mask); + ThreadHost thread_host(ThreadHost::ThreadHostConfig(kFlutterThreadName, + engine_thread_host_mask)); // If the embedder has supplied a platform task runner, use that. If not, use // the current thread task runner. @@ -208,9 +209,9 @@ std::unique_ptr EmbedderThreadHost::CreateEngineManagedThreadHost() { // Create a thread host with the current thread as the platform thread and all // other threads managed. - ThreadHost thread_host(kFlutterThreadName, ThreadHost::Type::RASTER | - ThreadHost::Type::IO | - ThreadHost::Type::UI); + ThreadHost thread_host(ThreadHost::ThreadHostConfig( + kFlutterThreadName, + ThreadHost::Type::RASTER | ThreadHost::Type::IO | ThreadHost::Type::UI)); // For embedder platforms that don't have native message loop interop, this // will reference a task runner that points to a null message loop diff --git a/shell/platform/fuchsia/flutter/engine.cc b/shell/platform/fuchsia/flutter/engine.cc index ccad16a902d50..f74973aef64db 100644 --- a/shell/platform/fuchsia/flutter/engine.cc +++ b/shell/platform/fuchsia/flutter/engine.cc @@ -57,7 +57,8 @@ std::unique_ptr MakeLocalizationPlatformMessage( } // namespace flutter::ThreadHost Engine::CreateThreadHost(const std::string& name_prefix) { - fml::Thread::SetCurrentThreadName(name_prefix + ".platform"); + fml::Thread::SetCurrentThreadName( + fml::Thread::ThreadConfig(name_prefix + ".platform")); return flutter::ThreadHost(name_prefix, flutter::ThreadHost::Type::RASTER | flutter::ThreadHost::Type::UI | flutter::ThreadHost::Type::IO);