Skip to content

Commit

Permalink
Split out the thread data and the thread data set operator
Browse files Browse the repository at this point in the history
  • Loading branch information
JsouLiang committed Feb 10, 2022
1 parent c32e510 commit 151ab6d
Show file tree
Hide file tree
Showing 14 changed files with 295 additions and 272 deletions.
4 changes: 2 additions & 2 deletions fml/concurrent_message_loop.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ ConcurrentMessageLoop::ConcurrentMessageLoop(size_t worker_count)
: worker_count_(std::max<size_t>(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();
});
}
Expand Down
91 changes: 43 additions & 48 deletions fml/thread.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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<ThreadConfig> config) : joined_(false) {
fml::AutoResetWaitableEvent latch;
fml::RefPtr<fml::TaskRunner> runner;
thread_ = std::make_unique<std::thread>(
[&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<fml::TaskRunner> 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
Expand All @@ -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;
}
Expand All @@ -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<fml::TaskRunner> runner;

thread_ = std::make_unique<std::thread>(
[&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<fml::TaskRunner> Thread::GetTaskRunner() const {
return task_runner_;
}

void Thread::Join() {
if (joined_) {
return;
}
joined_ = true;
task_runner_->PostTask([]() { MessageLoop::GetCurrent().Terminate(); });
thread_->join();
}

} // namespace fml
47 changes: 18 additions & 29 deletions fml/thread.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#define FLUTTER_FML_THREAD_H_

#include <atomic>
#include <functional>
#include <memory>
#include <string>
#include <thread>
Expand All @@ -29,52 +30,40 @@ 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<ThreadConfig> MakeDefaultConfigure(
const std::string& name = "") {
return std::make_unique<ThreadConfig>(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<void(const ThreadConfig&)>;

explicit Thread(std::unique_ptr<ThreadConfig> config =
ThreadConfig::MakeDefaultConfigure());
explicit Thread(const std::string& name = "");

explicit Thread(const ThreadConfigSetter& setter,
const ThreadConfig& config = ThreadConfig());

~Thread();

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

void Join();

static void SetCurrentThreadName(const std::string& name);
static void SetCurrentThreadName(const ThreadConfig& config);

private:
std::unique_ptr<std::thread> thread_;

fml::RefPtr<fml::TaskRunner> task_runner_;

std::atomic_bool joined_;

FML_DISALLOW_COPY_AND_ASSIGN(Thread);
Expand Down
69 changes: 35 additions & 34 deletions fml/thread_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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 <pthread.h>
#else
#error "Doesn't has pthead.h"
#endif

#include <memory>
Expand All @@ -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, &param);
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, &param);
}

TEST(Thread, ThreadPriorityCreatedWithConfig) {
const std::string thread1_name = "Thread1";
const std::string thread2_name = "Thread2";
fml::Thread thread(std::make_unique<MockThreadConfig>(
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, &param);
ASSERT_EQ(thread_name, thread1_name);
ASSERT_EQ(policy, SCHED_OTHER);
ASSERT_EQ(param.sched_priority, 1);
});

fml::Thread thread2(std::make_unique<MockThreadConfig>(
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, &param);
ASSERT_EQ(thread_name, thread2_name);
ASSERT_EQ(policy, SCHED_OTHER);
Expand Down
12 changes: 6 additions & 6 deletions lib/ui/ui_benchmarks.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down Expand Up @@ -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(),
Expand Down
4 changes: 2 additions & 2 deletions shell/common/shell_benchmarks.cc
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@ static void StartupAndShutdownShell(benchmark::State& state,
};
}

thread_host = std::make_unique<ThreadHost>(
thread_host = std::make_unique<ThreadHost>(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(),
Expand Down
17 changes: 10 additions & 7 deletions shell/common/shell_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
Loading

0 comments on commit 151ab6d

Please sign in to comment.