Flutter Engine
The Flutter Engine
thread.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#define FML_USED_ON_EMBEDDER
6
7#include "flutter/fml/thread.h"
8
9#include <memory>
10#include <string>
11#include <utility>
12
13#include "flutter/fml/build_config.h"
14#include "flutter/fml/message_loop.h"
15#include "flutter/fml/synchronization/waitable_event.h"
16
17#if defined(FML_OS_WIN)
18#include <windows.h>
19#elif defined(OS_FUCHSIA)
20#include <lib/zx/thread.h>
21#else
22#include <pthread.h>
23#endif
24
25namespace fml {
26
28
30 public:
33
34 void Join();
35
36 private:
37#if defined(FML_OS_WIN)
38 HANDLE thread_;
39#else
40 pthread_t thread_;
41#endif
42};
43
44#if defined(FML_OS_WIN)
46 thread_ = (HANDLE*)_beginthreadex(
48 [](void* arg) -> unsigned {
49 std::unique_ptr<ThreadFunction> function(
50 reinterpret_cast<ThreadFunction*>(arg));
51 (*function)();
52 return 0;
53 },
54 new ThreadFunction(std::move(function)), 0, nullptr);
55 FML_CHECK(thread_ != nullptr);
56}
57
58void ThreadHandle::Join() {
59 WaitForSingleObjectEx(thread_, INFINITE, FALSE);
60}
61
63 CloseHandle(thread_);
64}
65#else
67 pthread_attr_t attr;
68 pthread_attr_init(&attr);
69 int result = pthread_attr_setstacksize(&attr, Thread::GetDefaultStackSize());
70 FML_CHECK(result == 0);
71 result = pthread_create(
72 &thread_, &attr,
73 [](void* arg) -> void* {
74 std::unique_ptr<ThreadFunction> function(
75 reinterpret_cast<ThreadFunction*>(arg));
76 (*function)();
77 return nullptr;
78 },
79 new ThreadFunction(std::move(function)));
80 FML_CHECK(result == 0);
81 result = pthread_attr_destroy(&attr);
82 FML_CHECK(result == 0);
83}
84
86 pthread_join(thread_, nullptr);
87}
88
90#endif
91
92#if defined(FML_OS_WIN)
93// The information on how to set the thread name comes from
94// a MSDN article: http://msdn2.microsoft.com/en-us/library/xcb2z8hs.aspx
95const DWORD kVCThreadNameException = 0x406D1388;
96typedef struct tagTHREADNAME_INFO {
97 DWORD dwType; // Must be 0x1000.
98 LPCSTR szName; // Pointer to name (in user addr space).
99 DWORD dwThreadID; // Thread ID (-1=caller thread).
100 DWORD dwFlags; // Reserved for future use, must be zero.
101} THREADNAME_INFO;
102#endif
103
104void SetThreadName(const std::string& name) {
105 if (name == "") {
106 return;
107 }
108#if defined(FML_OS_MACOSX)
109 pthread_setname_np(name.c_str());
110#elif defined(FML_OS_LINUX) || defined(FML_OS_ANDROID)
111 // Linux thread names are limited to 16 characters including the terminating
112 // null.
113 constexpr std::string::size_type kLinuxMaxThreadNameLen = 15;
114 pthread_setname_np(pthread_self(),
115 name.substr(0, kLinuxMaxThreadNameLen).c_str());
116#elif defined(FML_OS_WIN)
117 THREADNAME_INFO info;
118 info.dwType = 0x1000;
119 info.szName = name.c_str();
120 info.dwThreadID = GetCurrentThreadId();
121 info.dwFlags = 0;
122 __try {
123 RaiseException(kVCThreadNameException, 0, sizeof(info) / sizeof(DWORD),
124 reinterpret_cast<DWORD_PTR*>(&info));
125 } __except (EXCEPTION_CONTINUE_EXECUTION) {
126 }
127#elif defined(OS_FUCHSIA)
128 zx::thread::self()->set_property(ZX_PROP_NAME, name.c_str(), name.size());
129#else
130 FML_DLOG(INFO) << "Could not set the thread name to '" << name
131 << "' on this platform.";
132#endif
133}
134
136 SetThreadName(config.name);
137}
138
139Thread::Thread(const std::string& name)
140 : Thread(Thread::SetCurrentThreadName, ThreadConfig(name)) {}
141
142Thread::Thread(const ThreadConfigSetter& setter, const ThreadConfig& config)
143 : joined_(false) {
146
147 thread_ = std::make_unique<ThreadHandle>(
148 [&latch, &runner, setter, config]() -> void {
149 setter(config);
151 auto& loop = MessageLoop::GetCurrent();
152 runner = loop.GetTaskRunner();
153 latch.Signal();
154 loop.Run();
155 });
156 latch.Wait();
157 task_runner_ = runner;
158}
159
161 Join();
162}
163
165 return task_runner_;
166}
167
169 if (joined_) {
170 return;
171 }
172 joined_ = true;
173 task_runner_->PostTask([]() { MessageLoop::GetCurrent().Terminate(); });
174 thread_->Join();
175}
176
178 return 1024 * 1024 * 2;
179}
180
181} // namespace fml
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
static void EnsureInitializedForCurrentThread()
Definition: message_loop.cc:27
static FML_EMBEDDER_ONLY MessageLoop & GetCurrent()
Definition: message_loop.cc:19
virtual void PostTask(const fml::closure &task) override
Definition: task_runner.cc:24
ThreadHandle(ThreadFunction &&function)
Definition: thread.cc:66
void Join()
Definition: thread.cc:168
fml::RefPtr< fml::TaskRunner > GetTaskRunner() const
Definition: thread.cc:164
static size_t GetDefaultStackSize()
Definition: thread.cc:177
std::function< void(const ThreadConfig &)> ThreadConfigSetter
Definition: thread.h:48
Thread(const std::string &name="")
Definition: thread.cc:139
static void SetCurrentThreadName(const ThreadConfig &config)
Definition: thread.cc:135
GAsyncResult * result
#define FML_DLOG(severity)
Definition: logging.h:102
#define FML_CHECK(condition)
Definition: logging.h:85
Dart_NativeFunction function
Definition: fuchsia.cc:51
return FALSE
DEF_SWITCHES_START aot vmservice shared library name
Definition: switches.h:32
Definition: ascii_trie.cc:9
std::function< void()> ThreadFunction
Definition: thread.cc:27
void SetThreadName(const std::string &name)
Definition: thread.cc:104
The ThreadConfig is the thread info include thread name, thread priority.
Definition: thread.h:35
std::string name
Definition: thread.h:44
void * HANDLE
Definition: windows_types.h:36
unsigned long DWORD
Definition: windows_types.h:22