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

Commit 9378b40

Browse files
committed
Define thread priority enum and set thread priority for all threads in Engine
1 parent 4f1ea25 commit 9378b40

File tree

7 files changed

+333
-45
lines changed

7 files changed

+333
-45
lines changed

fml/thread.cc

Lines changed: 25 additions & 9 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,17 +24,32 @@
2324

2425
namespace fml {
2526

26-
Thread::Thread(const std::string& name) : joined_(false) {
27+
Thread::ThreadConfig::ThreadConfig(const std::string& name,
28+
ThreadPriority priority)
29+
: thread_name_(name), thread_priority_(priority) {}
30+
31+
void Thread::ThreadConfig::SetCurrentThreadName() const {
32+
Thread::SetCurrentThreadName(thread_name_);
33+
}
34+
35+
void Thread::ThreadConfig::SetCurrentThreadPriority() const {}
36+
37+
Thread::Thread(const std::string& name)
38+
: Thread(ThreadConfig::MakeDefaultConfigure(name)) {}
39+
40+
Thread::Thread(std::unique_ptr<ThreadConfig> config) : 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);
31-
fml::MessageLoop::EnsureInitializedForCurrentThread();
32-
auto& loop = MessageLoop::GetCurrent();
33-
runner = loop.GetTaskRunner();
34-
latch.Signal();
35-
loop.Run();
36-
});
43+
thread_ = std::make_unique<std::thread>(
44+
[&latch, &runner, threadConfig = std::move(config)]() -> void {
45+
threadConfig->SetCurrentThreadName();
46+
threadConfig->SetCurrentThreadPriority();
47+
fml::MessageLoop::EnsureInitializedForCurrentThread();
48+
auto& loop = MessageLoop::GetCurrent();
49+
runner = loop.GetTaskRunner();
50+
latch.Signal();
51+
loop.Run();
52+
});
3753
latch.Wait();
3854
task_runner_ = runner;
3955
}

fml/thread.h

Lines changed: 47 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(const std::string& name = "",
36+
ThreadPriority priority = ThreadPriority::NORMAL);
37+
38+
static std::unique_ptr<ThreadConfig> MakeDefaultConfigure(
39+
const std::string& name = "") {
40+
return std::make_unique<ThreadConfig>(name);
41+
}
42+
43+
ThreadPriority GetThreadPriority() const { return thread_priority_; }
44+
45+
const std::string& GetThreadName() const { return thread_name_; }
46+
47+
/// Set current thread name.
48+
virtual void SetCurrentThreadName() const;
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() const;
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> config =
65+
ThreadConfig::MakeDefaultConfigure());
2066

2167
~Thread();
2268

fml/thread_unittests.cc

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

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

7+
#define FLUTTER_PTHREAD_SUPPORTED \
8+
defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_ANDROID)
9+
10+
#ifdef FLUTTER_PTHREAD_SUPPORTED
11+
#include <pthread.h>
12+
#else
13+
#error "Doesn't has pthead.h"
14+
#endif
15+
16+
#include <memory>
717
#include "gtest/gtest.h"
818

919
TEST(Thread, CanStartAndEnd) {
@@ -24,3 +34,78 @@ TEST(Thread, HasARunningMessageLoop) {
2434
thread.Join();
2535
ASSERT_TRUE(done);
2636
}
37+
38+
#ifdef FLUTTER_PTHREAD_SUPPORTED
39+
TEST(Thread, ThreadNameCreatedWithConfig) {
40+
const std::string name = "Thread1";
41+
fml::Thread thread(fml::Thread::ThreadConfig::MakeDefaultConfigure(name));
42+
43+
bool done = false;
44+
constexpr int NAMELEN = 8;
45+
thread.GetTaskRunner()->PostTask([&done, &name]() {
46+
done = true;
47+
char thread_name[NAMELEN];
48+
pthread_t current_thread = pthread_self();
49+
pthread_getname_np(current_thread, thread_name, NAMELEN);
50+
ASSERT_EQ(thread_name, name);
51+
});
52+
thread.Join();
53+
ASSERT_TRUE(done);
54+
}
55+
56+
class MockThreadConfig : public fml::Thread::ThreadConfig {
57+
public:
58+
using fml::Thread::ThreadConfig::ThreadConfig;
59+
60+
void SetCurrentThreadPriority() const override {
61+
pthread_t tid = pthread_self();
62+
struct sched_param param;
63+
int policy = SCHED_OTHER;
64+
switch (GetThreadPriority()) {
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+
75+
TEST(Thread, ThreadPriorityCreatedWithConfig) {
76+
const std::string thread1_name = "Thread1";
77+
const std::string thread2_name = "Thread2";
78+
fml::Thread thread(std::make_unique<MockThreadConfig>(
79+
thread1_name, fml::Thread::ThreadPriority::NORMAL));
80+
81+
bool done = false;
82+
constexpr int NAMELEN = 8;
83+
struct sched_param param;
84+
int policy;
85+
thread.GetTaskRunner()->PostTask([&]() {
86+
done = true;
87+
char thread_name[NAMELEN];
88+
pthread_t current_thread = pthread_self();
89+
pthread_getname_np(current_thread, thread_name, NAMELEN);
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(std::make_unique<MockThreadConfig>(
97+
thread2_name, fml::Thread::ThreadPriority::DISPLAY));
98+
thread2.GetTaskRunner()->PostTask([&]() {
99+
done = true;
100+
char thread_name[NAMELEN];
101+
pthread_t current_thread = pthread_self();
102+
pthread_getname_np(current_thread, thread_name, NAMELEN);
103+
pthread_getschedparam(current_thread, &policy, &param);
104+
ASSERT_EQ(thread_name, thread2_name);
105+
ASSERT_EQ(policy, SCHED_OTHER);
106+
ASSERT_EQ(param.sched_priority, 10);
107+
});
108+
thread.Join();
109+
ASSERT_TRUE(done);
110+
}
111+
#endif

shell/common/thread_host.cc

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,32 +4,75 @@
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::ThreadHostConfig::MakeThreadName(
15+
Type type,
16+
const std::string& prefix) {
17+
switch (type) {
18+
case Type::Platform:
19+
return prefix + ".platform";
20+
case Type::UI:
21+
return prefix + ".ui";
22+
case Type::IO:
23+
return prefix + ".io";
24+
case Type::RASTER:
25+
return prefix + ".raster";
26+
case Type::Profiler:
27+
return prefix + ".profiler";
28+
}
29+
}
30+
31+
std::unique_ptr<fml::Thread> ThreadHost::CreateThread(
32+
Type type,
33+
ThreadHost::ThreadConfig configure) {
34+
std::string name = ThreadHostConfig::MakeThreadName(type, name_prefix);
35+
if (configure != nullptr) {
36+
return std::make_unique<fml::Thread>(std::move(configure));
37+
}
38+
return std::make_unique<fml::Thread>(
39+
fml::Thread::ThreadConfig::MakeDefaultConfigure(name));
40+
}
41+
942
ThreadHost::ThreadHost() = default;
1043

1144
ThreadHost::ThreadHost(ThreadHost&&) = default;
1245

13-
ThreadHost::ThreadHost(std::string name_prefix_arg, uint64_t mask)
46+
ThreadHost::ThreadHost(std::string name_prefix_arg,
47+
uint64_t mask,
48+
ThreadHostConfig configure_host)
1449
: name_prefix(name_prefix_arg) {
1550
if (mask & ThreadHost::Type::Platform) {
16-
platform_thread = std::make_unique<fml::Thread>(name_prefix + ".platform");
51+
platform_thread =
52+
CreateThread(ThreadHost::Type::Platform,
53+
std::move(configure_host.platform_configure));
1754
}
1855

1956
if (mask & ThreadHost::Type::UI) {
20-
ui_thread = std::make_unique<fml::Thread>(name_prefix + ".ui");
57+
ui_thread = CreateThread(ThreadHost::Type::UI,
58+
std::move(configure_host.ui_configure));
2159
}
2260

2361
if (mask & ThreadHost::Type::RASTER) {
24-
raster_thread = std::make_unique<fml::Thread>(name_prefix + ".raster");
62+
raster_thread = CreateThread(ThreadHost::Type::RASTER,
63+
std::move(configure_host.raster_configure));
2564
}
2665

2766
if (mask & ThreadHost::Type::IO) {
28-
io_thread = std::make_unique<fml::Thread>(name_prefix + ".io");
67+
io_thread = CreateThread(ThreadHost::Type::IO,
68+
std::move(configure_host.io_configure));
2969
}
3070

3171
if (mask & ThreadHost::Type::Profiler) {
32-
profiler_thread = std::make_unique<fml::Thread>(name_prefix + ".profiler");
72+
profiler_thread =
73+
CreateThread(ThreadHost::Type::Profiler,
74+
std::move(configure_host.profiler_configure));
75+
;
3376
}
3477
}
3578

shell/common/thread_host.h

Lines changed: 21 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,20 @@ struct ThreadHost {
2223
Profiler = 1 << 4,
2324
};
2425

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

3651
ThreadHost& operator=(ThreadHost&&) = default;
3752

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

4057
~ThreadHost();
58+
59+
private:
60+
std::unique_ptr<fml::Thread> CreateThread(Type type, ThreadConfig configure);
4161
};
4262

4363
} // namespace flutter

0 commit comments

Comments
 (0)