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

Commit 49f45a9

Browse files
committed
Define thread priority enum and set thread priority for all threads in Engine
1 parent b6db081 commit 49f45a9

File tree

7 files changed

+319
-39
lines changed

7 files changed

+319
-39
lines changed

fml/thread.cc

Lines changed: 18 additions & 3 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,11 +24,25 @@
2324

2425
namespace fml {
2526

26-
Thread::Thread(const std::string& name) : joined_(false) {
27+
Thread::ThreadConfig::ThreadConfig(std::string name, ThreadPriority priority)
28+
: thread_name_(name), thread_priority_(priority) {}
29+
30+
void Thread::ThreadConfig::SetCurrentThreadName() {
31+
Thread::SetCurrentThreadName(thread_name_);
32+
}
33+
34+
void Thread::ThreadConfig::SetCurrentThreadPriority() {}
35+
36+
Thread::Thread(const std::string& name)
37+
: Thread(ThreadConfig::DefaultConfigure(name)) {}
38+
39+
Thread::Thread(std::unique_ptr<Thread::ThreadConfig> configurer)
40+
: thread_config_(std::move(configurer)), joined_(false) {
2741
fml::AutoResetWaitableEvent latch;
2842
fml::RefPtr<fml::TaskRunner> runner;
29-
thread_ = std::make_unique<std::thread>([&latch, &runner, name]() -> void {
30-
SetCurrentThreadName(name);
43+
thread_ = std::make_unique<std::thread>([&]() -> void {
44+
thread_config_->SetCurrentThreadName();
45+
thread_config_->SetCurrentThreadPriority();
3146
fml::MessageLoop::EnsureInitializedForCurrentThread();
3247
auto& loop = MessageLoop::GetCurrent();
3348
runner = loop.GetTaskRunner();

fml/thread.h

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#include <atomic>
99
#include <memory>
10+
#include <string>
1011
#include <thread>
1112

1213
#include "flutter/fml/macros.h"
@@ -16,7 +17,52 @@ namespace fml {
1617

1718
class Thread {
1819
public:
19-
explicit Thread(const std::string& name = "");
20+
// Valid values for priority of Thread
21+
enum class ThreadPriority : int {
22+
// Suitable for threads that shouldn't disrupt high priority work.
23+
BACKGROUND,
24+
// Default priority level.
25+
NORMAL,
26+
// Suitable for threads which generate data for the display.
27+
DISPLAY,
28+
// Suitable for thread which raster data
29+
RASTER,
30+
};
31+
32+
/// The ThreadConfig is used for setting thread perorities
33+
class ThreadConfig {
34+
public:
35+
explicit ThreadConfig(std::string name = "",
36+
ThreadPriority priority = ThreadPriority::NORMAL);
37+
38+
static std::unique_ptr<ThreadConfig> DefaultConfigure(
39+
const std::string& name = "") {
40+
return std::make_unique<ThreadConfig>(name);
41+
}
42+
43+
ThreadPriority thread_priority() const { return thread_priority_; }
44+
45+
const std::string& thread_name() const { return thread_name_; }
46+
47+
/// Set current thread name
48+
virtual void SetCurrentThreadName();
49+
50+
/// default do nothing, which mean user can use platform api to set priority
51+
/// example: iOS might use pthread_qos set thread priority, Android might
52+
/// use ::setPriority set thread priority
53+
virtual void SetCurrentThreadPriority();
54+
55+
virtual ~ThreadConfig() = default;
56+
57+
private:
58+
const std::string thread_name_;
59+
ThreadPriority thread_priority_;
60+
};
61+
62+
explicit Thread(const std::string& name);
63+
64+
explicit Thread(std::unique_ptr<ThreadConfig> configurer =
65+
ThreadConfig::DefaultConfigure());
2066

2167
~Thread();
2268

@@ -28,6 +74,8 @@ class Thread {
2874

2975
private:
3076
std::unique_ptr<std::thread> thread_;
77+
/// ThreadConfigure is used for setting thread configure some like `priority`
78+
std::unique_ptr<ThreadConfig> thread_config_;
3179
fml::RefPtr<fml::TaskRunner> task_runner_;
3280
std::atomic_bool joined_;
3381

fml/thread_unittests.cc

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

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

7+
#if defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_ANDROID)
8+
#include <pthread.h>
9+
#endif
10+
11+
#include <memory>
712
#include "gtest/gtest.h"
813

914
TEST(Thread, CanStartAndEnd) {
@@ -24,3 +29,78 @@ TEST(Thread, HasARunningMessageLoop) {
2429
thread.Join();
2530
ASSERT_TRUE(done);
2631
}
32+
33+
#if defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_ANDROID)
34+
TEST(Thread, ThreadNameCreatedWithConfig) {
35+
const std::string name = "Thread1";
36+
fml::Thread thread(fml::Thread::ThreadConfig::DefaultConfigure(name));
37+
38+
bool done = false;
39+
constexpr int NAMELEN = 8;
40+
thread.GetTaskRunner()->PostTask([&done, &name]() {
41+
done = true;
42+
char thread_name[NAMELEN];
43+
pthread_t current_thread = pthread_self();
44+
pthread_getname_np(current_thread, thread_name, NAMELEN);
45+
ASSERT_EQ(thread_name, name);
46+
});
47+
thread.Join();
48+
ASSERT_TRUE(done);
49+
}
50+
51+
class MockThreadConfig : public fml::Thread::ThreadConfig {
52+
public:
53+
using fml::Thread::ThreadConfig::ThreadConfig;
54+
55+
void SetCurrentThreadPriority() override {
56+
pthread_t tid = pthread_self();
57+
struct sched_param param;
58+
int policy = SCHED_OTHER;
59+
switch (thread_priority()) {
60+
case fml::Thread::ThreadPriority::DISPLAY:
61+
param.sched_priority = 10;
62+
break;
63+
default:
64+
param.sched_priority = 1;
65+
}
66+
pthread_setschedparam(tid, policy, &param);
67+
}
68+
};
69+
70+
TEST(Thread, ThreadPriorityCreatedWithConfig) {
71+
const std::string thread1_name = "Thread1";
72+
const std::string thread2_name = "Thread2";
73+
fml::Thread thread(std::make_unique<MockThreadConfig>(
74+
thread1_name, fml::Thread::ThreadPriority::NORMAL));
75+
76+
bool done = false;
77+
constexpr int NAMELEN = 8;
78+
struct sched_param param;
79+
int policy;
80+
thread.GetTaskRunner()->PostTask([&]() {
81+
done = true;
82+
char thread_name[NAMELEN];
83+
pthread_t current_thread = pthread_self();
84+
pthread_getname_np(current_thread, thread_name, NAMELEN);
85+
pthread_getschedparam(current_thread, &policy, &param);
86+
ASSERT_EQ(thread_name, thread1_name);
87+
ASSERT_EQ(policy, SCHED_OTHER);
88+
ASSERT_EQ(param.sched_priority, 1);
89+
});
90+
91+
fml::Thread thread2(std::make_unique<MockThreadConfig>(
92+
thread2_name, fml::Thread::ThreadPriority::DISPLAY));
93+
thread2.GetTaskRunner()->PostTask([&]() {
94+
done = true;
95+
char thread_name[NAMELEN];
96+
pthread_t current_thread = pthread_self();
97+
pthread_getname_np(current_thread, thread_name, NAMELEN);
98+
pthread_getschedparam(current_thread, &policy, &param);
99+
ASSERT_EQ(thread_name, thread2_name);
100+
ASSERT_EQ(policy, SCHED_OTHER);
101+
ASSERT_EQ(param.sched_priority, 10);
102+
});
103+
thread.Join();
104+
ASSERT_TRUE(done);
105+
}
106+
#endif

shell/common/thread_host.cc

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,32 +4,73 @@
44

55
#include "flutter/shell/common/thread_host.h"
66

7+
#include <algorithm>
8+
#include <memory>
9+
#include <string>
10+
#include <utility>
11+
712
namespace flutter {
813

14+
std::string ThreadHost::ThreadName(Type type, std::string prefix) {
15+
switch (type) {
16+
case Type::Platform:
17+
return prefix + ".platform";
18+
case Type::UI:
19+
return prefix + ".ui";
20+
case Type::IO:
21+
return prefix + ".io";
22+
case Type::RASTER:
23+
return prefix + ".raster";
24+
case Type::Profiler:
25+
return prefix + ".profiler";
26+
}
27+
}
28+
29+
std::unique_ptr<fml::Thread> ThreadHost::CreateThread(
30+
Type type,
31+
ThreadHost::ThreadConfig configure) {
32+
std::string name = ThreadName(type, name_prefix);
33+
if (configure != nullptr) {
34+
return std::make_unique<fml::Thread>(std::move(configure));
35+
}
36+
return std::make_unique<fml::Thread>(
37+
fml::Thread::ThreadConfig::DefaultConfigure(name));
38+
}
39+
940
ThreadHost::ThreadHost() = default;
1041

1142
ThreadHost::ThreadHost(ThreadHost&&) = default;
1243

13-
ThreadHost::ThreadHost(std::string name_prefix_arg, uint64_t mask)
44+
ThreadHost::ThreadHost(std::string name_prefix_arg,
45+
uint64_t mask,
46+
ThreadHostConfig configure_host)
1447
: name_prefix(name_prefix_arg) {
1548
if (mask & ThreadHost::Type::Platform) {
16-
platform_thread = std::make_unique<fml::Thread>(name_prefix + ".platform");
49+
platform_thread =
50+
CreateThread(ThreadHost::Type::Platform,
51+
std::move(configure_host.platform_configure));
1752
}
1853

1954
if (mask & ThreadHost::Type::UI) {
20-
ui_thread = std::make_unique<fml::Thread>(name_prefix + ".ui");
55+
ui_thread = CreateThread(ThreadHost::Type::UI,
56+
std::move(configure_host.ui_configure));
2157
}
2258

2359
if (mask & ThreadHost::Type::RASTER) {
24-
raster_thread = std::make_unique<fml::Thread>(name_prefix + ".raster");
60+
raster_thread = CreateThread(ThreadHost::Type::RASTER,
61+
std::move(configure_host.raster_configure));
2562
}
2663

2764
if (mask & ThreadHost::Type::IO) {
28-
io_thread = std::make_unique<fml::Thread>(name_prefix + ".io");
65+
io_thread = CreateThread(ThreadHost::Type::IO,
66+
std::move(configure_host.io_configure));
2967
}
3068

3169
if (mask & ThreadHost::Type::Profiler) {
32-
profiler_thread = std::make_unique<fml::Thread>(name_prefix + ".profiler");
70+
profiler_thread =
71+
CreateThread(ThreadHost::Type::Profiler,
72+
std::move(configure_host.profiler_configure));
73+
;
3374
}
3475
}
3576

shell/common/thread_host.h

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

88
#include <memory>
9+
#include <string>
910

1011
#include "flutter/fml/macros.h"
1112
#include "flutter/fml/thread.h"
@@ -22,6 +23,19 @@ struct ThreadHost {
2223
Profiler = 1 << 4,
2324
};
2425

26+
static std::string ThreadName(Type type, std::string prefix = "");
27+
28+
using ThreadConfig = std::unique_ptr<fml::Thread::ThreadConfig>;
29+
/// The collection of all the thread configures, and we create custom thread
30+
/// configure in engine to info the thread.
31+
struct ThreadHostConfig {
32+
ThreadConfig platform_configure;
33+
ThreadConfig ui_configure;
34+
ThreadConfig raster_configure;
35+
ThreadConfig io_configure;
36+
ThreadConfig profiler_configure;
37+
};
38+
2539
std::string name_prefix;
2640
std::unique_ptr<fml::Thread> platform_thread;
2741
std::unique_ptr<fml::Thread> ui_thread;
@@ -35,9 +49,14 @@ struct ThreadHost {
3549

3650
ThreadHost& operator=(ThreadHost&&) = default;
3751

38-
ThreadHost(std::string name_prefix, uint64_t type_mask);
52+
ThreadHost(std::string name_prefix,
53+
uint64_t type_mask,
54+
ThreadHostConfig configure_host = ThreadHostConfig());
3955

4056
~ThreadHost();
57+
58+
private:
59+
std::unique_ptr<fml::Thread> CreateThread(Type type, ThreadConfig configure);
4160
};
4261

4362
} // namespace flutter

0 commit comments

Comments
 (0)