Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 5140a44

Browse files
authored
Define thread priority enum and set thread priority for all threads in Engine (#30605)
* Define thread priority enum and set thread priority for all threads in Engine * Split out the thread data and the thread data set operator
1 parent e031e07 commit 5140a44

File tree

14 files changed

+417
-106
lines changed

14 files changed

+417
-106
lines changed

fml/concurrent_message_loop.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ ConcurrentMessageLoop::ConcurrentMessageLoop(size_t worker_count)
2121
: worker_count_(std::max<size_t>(worker_count, 1ul)) {
2222
for (size_t i = 0; i < worker_count_; ++i) {
2323
workers_.emplace_back([i, this]() {
24-
fml::Thread::SetCurrentThreadName(
25-
std::string{"io.worker." + std::to_string(i + 1)});
24+
fml::Thread::SetCurrentThreadName(fml::Thread::ThreadConfig(
25+
std::string{"io.worker." + std::to_string(i + 1)}));
2626
WorkerMain();
2727
});
2828
}

fml/thread.cc

Lines changed: 44 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include <memory>
1010
#include <string>
11+
#include <utility>
1112

1213
#include "flutter/fml/build_config.h"
1314
#include "flutter/fml/message_loop.h"
@@ -23,38 +24,6 @@
2324

2425
namespace fml {
2526

26-
Thread::Thread(const std::string& name) : joined_(false) {
27-
fml::AutoResetWaitableEvent latch;
28-
fml::RefPtr<fml::TaskRunner> runner;
29-
thread_ = std::make_unique<std::thread>([&latch, &runner, name]() -> void {
30-
SetCurrentThreadName(name);
31-
fml::MessageLoop::EnsureInitializedForCurrentThread();
32-
auto& loop = MessageLoop::GetCurrent();
33-
runner = loop.GetTaskRunner();
34-
latch.Signal();
35-
loop.Run();
36-
});
37-
latch.Wait();
38-
task_runner_ = runner;
39-
}
40-
41-
Thread::~Thread() {
42-
Join();
43-
}
44-
45-
fml::RefPtr<fml::TaskRunner> Thread::GetTaskRunner() const {
46-
return task_runner_;
47-
}
48-
49-
void Thread::Join() {
50-
if (joined_) {
51-
return;
52-
}
53-
joined_ = true;
54-
task_runner_->PostTask([]() { MessageLoop::GetCurrent().Terminate(); });
55-
thread_->join();
56-
}
57-
5827
#if defined(FML_OS_WIN)
5928
// The information on how to set the thread name comes from
6029
// a MSDN article: http://msdn2.microsoft.com/en-us/library/xcb2z8hs.aspx
@@ -67,7 +36,7 @@ typedef struct tagTHREADNAME_INFO {
6736
} THREADNAME_INFO;
6837
#endif
6938

70-
void Thread::SetCurrentThreadName(const std::string& name) {
39+
void SetThreadName(const std::string& name) {
7140
if (name == "") {
7241
return;
7342
}
@@ -94,4 +63,46 @@ void Thread::SetCurrentThreadName(const std::string& name) {
9463
#endif
9564
}
9665

66+
void Thread::SetCurrentThreadName(const Thread::ThreadConfig& config) {
67+
SetThreadName(config.name);
68+
}
69+
70+
Thread::Thread(const std::string& name)
71+
: Thread(Thread::SetCurrentThreadName, ThreadConfig(name)) {}
72+
73+
Thread::Thread(const ThreadConfigSetter& setter, const ThreadConfig& config)
74+
: joined_(false) {
75+
fml::AutoResetWaitableEvent latch;
76+
fml::RefPtr<fml::TaskRunner> runner;
77+
78+
thread_ = std::make_unique<std::thread>(
79+
[&latch, &runner, setter, config]() -> void {
80+
setter(config);
81+
fml::MessageLoop::EnsureInitializedForCurrentThread();
82+
auto& loop = MessageLoop::GetCurrent();
83+
runner = loop.GetTaskRunner();
84+
latch.Signal();
85+
loop.Run();
86+
});
87+
latch.Wait();
88+
task_runner_ = runner;
89+
}
90+
91+
Thread::~Thread() {
92+
Join();
93+
}
94+
95+
fml::RefPtr<fml::TaskRunner> Thread::GetTaskRunner() const {
96+
return task_runner_;
97+
}
98+
99+
void Thread::Join() {
100+
if (joined_) {
101+
return;
102+
}
103+
joined_ = true;
104+
task_runner_->PostTask([]() { MessageLoop::GetCurrent().Terminate(); });
105+
thread_->join();
106+
}
107+
97108
} // namespace fml

fml/thread.h

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
#define FLUTTER_FML_THREAD_H_
77

88
#include <atomic>
9+
#include <functional>
910
#include <memory>
11+
#include <string>
1012
#include <thread>
1113

1214
#include "flutter/fml/macros.h"
@@ -16,19 +18,52 @@ namespace fml {
1618

1719
class Thread {
1820
public:
21+
/// Valid values for priority of Thread.
22+
enum class ThreadPriority : int {
23+
/// Suitable for threads that shouldn't disrupt high priority work.
24+
BACKGROUND,
25+
/// Default priority level.
26+
NORMAL,
27+
/// Suitable for threads which generate data for the display.
28+
DISPLAY,
29+
/// Suitable for thread which raster data.
30+
RASTER,
31+
};
32+
33+
/// The ThreadConfig is the thread info include thread name, thread priority.
34+
struct ThreadConfig {
35+
ThreadConfig(const std::string& name, ThreadPriority priority)
36+
: name(name), priority(priority) {}
37+
38+
explicit ThreadConfig(const std::string& name)
39+
: ThreadConfig(name, ThreadPriority::NORMAL) {}
40+
41+
ThreadConfig() : ThreadConfig("", ThreadPriority::NORMAL) {}
42+
43+
std::string name;
44+
ThreadPriority priority;
45+
};
46+
47+
using ThreadConfigSetter = std::function<void(const ThreadConfig&)>;
48+
1949
explicit Thread(const std::string& name = "");
2050

51+
explicit Thread(const ThreadConfigSetter& setter,
52+
const ThreadConfig& config = ThreadConfig());
53+
2154
~Thread();
2255

2356
fml::RefPtr<fml::TaskRunner> GetTaskRunner() const;
2457

2558
void Join();
2659

27-
static void SetCurrentThreadName(const std::string& name);
60+
static void SetCurrentThreadName(const ThreadConfig& config);
2861

2962
private:
3063
std::unique_ptr<std::thread> thread_;
64+
3165
fml::RefPtr<fml::TaskRunner> task_runner_;
66+
3267
std::atomic_bool joined_;
3368

3469
FML_DISALLOW_COPY_AND_ASSIGN(Thread);

fml/thread_unittests.cc

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,18 @@
44

55
#include "flutter/fml/thread.h"
66

7+
#if defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_ANDROID)
8+
#define FLUTTER_PTHREAD_SUPPORTED 1
9+
#else
10+
#define FLUTTER_PTHREAD_SUPPORTED 0
11+
#endif
12+
13+
#if FLUTTER_PTHREAD_SUPPORTED
14+
#include <pthread.h>
15+
#else
16+
#endif
17+
18+
#include <memory>
719
#include "gtest/gtest.h"
820

921
TEST(Thread, CanStartAndEnd) {
@@ -24,3 +36,77 @@ TEST(Thread, HasARunningMessageLoop) {
2436
thread.Join();
2537
ASSERT_TRUE(done);
2638
}
39+
40+
#if FLUTTER_PTHREAD_SUPPORTED
41+
TEST(Thread, ThreadNameCreatedWithConfig) {
42+
const std::string name = "Thread1";
43+
fml::Thread thread(name);
44+
45+
bool done = false;
46+
thread.GetTaskRunner()->PostTask([&done, &name]() {
47+
done = true;
48+
char thread_name[8];
49+
pthread_t current_thread = pthread_self();
50+
pthread_getname_np(current_thread, thread_name, 8);
51+
ASSERT_EQ(thread_name, name);
52+
});
53+
thread.Join();
54+
ASSERT_TRUE(done);
55+
}
56+
57+
static void MockThreadConfigSetter(const fml::Thread::ThreadConfig& config) {
58+
// set thread name
59+
fml::Thread::SetCurrentThreadName(config);
60+
61+
pthread_t tid = pthread_self();
62+
struct sched_param param;
63+
int policy = SCHED_OTHER;
64+
switch (config.priority) {
65+
case fml::Thread::ThreadPriority::DISPLAY:
66+
param.sched_priority = 10;
67+
break;
68+
default:
69+
param.sched_priority = 1;
70+
}
71+
pthread_setschedparam(tid, policy, &param);
72+
}
73+
74+
TEST(Thread, ThreadPriorityCreatedWithConfig) {
75+
const std::string thread1_name = "Thread1";
76+
const std::string thread2_name = "Thread2";
77+
78+
fml::Thread thread(MockThreadConfigSetter,
79+
fml::Thread::ThreadConfig(
80+
thread1_name, fml::Thread::ThreadPriority::NORMAL));
81+
bool done = false;
82+
83+
struct sched_param param;
84+
int policy;
85+
thread.GetTaskRunner()->PostTask([&]() {
86+
done = true;
87+
char thread_name[8];
88+
pthread_t current_thread = pthread_self();
89+
pthread_getname_np(current_thread, thread_name, 8);
90+
pthread_getschedparam(current_thread, &policy, &param);
91+
ASSERT_EQ(thread_name, thread1_name);
92+
ASSERT_EQ(policy, SCHED_OTHER);
93+
ASSERT_EQ(param.sched_priority, 1);
94+
});
95+
96+
fml::Thread thread2(MockThreadConfigSetter,
97+
fml::Thread::ThreadConfig(
98+
thread2_name, fml::Thread::ThreadPriority::DISPLAY));
99+
thread2.GetTaskRunner()->PostTask([&]() {
100+
done = true;
101+
char thread_name[8];
102+
pthread_t current_thread = pthread_self();
103+
pthread_getname_np(current_thread, thread_name, 8);
104+
pthread_getschedparam(current_thread, &policy, &param);
105+
ASSERT_EQ(thread_name, thread2_name);
106+
ASSERT_EQ(policy, SCHED_OTHER);
107+
ASSERT_EQ(param.sched_priority, 10);
108+
});
109+
thread.Join();
110+
ASSERT_TRUE(done);
111+
}
112+
#endif

lib/ui/ui_benchmarks.cc

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ class Fixture : public testing::FixtureTest {
2020
};
2121

2222
static void BM_PlatformMessageResponseDartComplete(benchmark::State& state) {
23-
ThreadHost thread_host("test",
24-
ThreadHost::Type::Platform | ThreadHost::Type::RASTER |
25-
ThreadHost::Type::IO | ThreadHost::Type::UI);
23+
ThreadHost thread_host(ThreadHost::ThreadHostConfig(
24+
"test", ThreadHost::Type::Platform | ThreadHost::Type::RASTER |
25+
ThreadHost::Type::IO | ThreadHost::Type::UI));
2626
TaskRunners task_runners("test", thread_host.platform_thread->GetTaskRunner(),
2727
thread_host.raster_thread->GetTaskRunner(),
2828
thread_host.ui_thread->GetTaskRunner(),
@@ -68,9 +68,9 @@ static void BM_PlatformMessageResponseDartComplete(benchmark::State& state) {
6868
}
6969

7070
static void BM_PathVolatilityTracker(benchmark::State& state) {
71-
ThreadHost thread_host("test",
72-
ThreadHost::Type::Platform | ThreadHost::Type::RASTER |
73-
ThreadHost::Type::IO | ThreadHost::Type::UI);
71+
ThreadHost thread_host(ThreadHost::ThreadHostConfig(
72+
"test", ThreadHost::Type::Platform | ThreadHost::Type::RASTER |
73+
ThreadHost::Type::IO | ThreadHost::Type::UI));
7474
TaskRunners task_runners("test", thread_host.platform_thread->GetTaskRunner(),
7575
thread_host.raster_thread->GetTaskRunner(),
7676
thread_host.ui_thread->GetTaskRunner(),

shell/common/shell_benchmarks.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,10 @@ static void StartupAndShutdownShell(benchmark::State& state,
4343
};
4444
}
4545

46-
thread_host = std::make_unique<ThreadHost>(
46+
thread_host = std::make_unique<ThreadHost>(ThreadHost::ThreadHostConfig(
4747
"io.flutter.bench.", ThreadHost::Type::Platform |
4848
ThreadHost::Type::RASTER |
49-
ThreadHost::Type::IO | ThreadHost::Type::UI);
49+
ThreadHost::Type::IO | ThreadHost::Type::UI));
5050

5151
TaskRunners task_runners("test",
5252
thread_host->platform_thread->GetTaskRunner(),

shell/common/shell_unittests.cc

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -267,9 +267,10 @@ TEST_F(ShellTest, InitializeWithInvalidThreads) {
267267
TEST_F(ShellTest, InitializeWithDifferentThreads) {
268268
ASSERT_FALSE(DartVMRef::IsInstanceRunning());
269269
Settings settings = CreateSettingsForFixture();
270-
ThreadHost thread_host("io.flutter.test." + GetCurrentTestName() + ".",
271-
ThreadHost::Type::Platform | ThreadHost::Type::RASTER |
272-
ThreadHost::Type::IO | ThreadHost::Type::UI);
270+
ThreadHost thread_host(ThreadHost::ThreadHostConfig(
271+
"io.flutter.test." + GetCurrentTestName() + ".",
272+
ThreadHost::Type::Platform | ThreadHost::Type::RASTER |
273+
ThreadHost::Type::IO | ThreadHost::Type::UI));
273274
TaskRunners task_runners("test", thread_host.platform_thread->GetTaskRunner(),
274275
thread_host.raster_thread->GetTaskRunner(),
275276
thread_host.ui_thread->GetTaskRunner(),
@@ -3116,8 +3117,9 @@ TEST_F(ShellTest, UpdateAssetResolverByTypeAppends) {
31163117
TEST_F(ShellTest, UpdateAssetResolverByTypeNull) {
31173118
ASSERT_FALSE(DartVMRef::IsInstanceRunning());
31183119
Settings settings = CreateSettingsForFixture();
3119-
ThreadHost thread_host("io.flutter.test." + GetCurrentTestName() + ".",
3120-
ThreadHost::Type::Platform);
3120+
ThreadHost thread_host(ThreadHost::ThreadHostConfig(
3121+
"io.flutter.test." + GetCurrentTestName() + ".",
3122+
ThreadHost::Type::Platform));
31213123
auto task_runner = thread_host.platform_thread->GetTaskRunner();
31223124
TaskRunners task_runners("test", task_runner, task_runner, task_runner,
31233125
task_runner);
@@ -3153,8 +3155,9 @@ TEST_F(ShellTest, UpdateAssetResolverByTypeNull) {
31533155
TEST_F(ShellTest, UpdateAssetResolverByTypeDoesNotReplaceMismatchType) {
31543156
ASSERT_FALSE(DartVMRef::IsInstanceRunning());
31553157
Settings settings = CreateSettingsForFixture();
3156-
ThreadHost thread_host("io.flutter.test." + GetCurrentTestName() + ".",
3157-
ThreadHost::Type::Platform);
3158+
ThreadHost thread_host(ThreadHost::ThreadHostConfig(
3159+
"io.flutter.test." + GetCurrentTestName() + ".",
3160+
ThreadHost::Type::Platform));
31583161
auto task_runner = thread_host.platform_thread->GetTaskRunner();
31593162
TaskRunners task_runners("test", task_runner, task_runner, task_runner,
31603163
task_runner);

0 commit comments

Comments
 (0)