• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "flutter/fml/build_config.h"
10 
11 // WINDOWS_PLATFORM is defined by ACE PC preview.
12 #if defined(OS_WIN) && !defined(WINDOWS_PLATFORM)
13 #include <windows.h>
14 #else
15 #include <pthread.h>
16 #endif
17 
18 #include <memory>
19 #include <string>
20 
21 #include "flutter/fml/message_loop.h"
22 #include "flutter/fml/synchronization/waitable_event.h"
23 
24 namespace fml {
25 
Thread(const std::string & name)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 
~Thread()41 Thread::~Thread() {
42   Join();
43 }
44 
GetTaskRunner() const45 fml::RefPtr<fml::TaskRunner> Thread::GetTaskRunner() const {
46   return task_runner_;
47 }
48 
Join()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 
58 #if defined(OS_WIN) && !defined(WINDOWS_PLATFORM)
59 // The information on how to set the thread name comes from
60 // a MSDN article: http://msdn2.microsoft.com/en-us/library/xcb2z8hs.aspx
61 const DWORD kVCThreadNameException = 0x406D1388;
62 typedef struct tagTHREADNAME_INFO {
63   DWORD dwType;      // Must be 0x1000.
64   LPCSTR szName;     // Pointer to name (in user addr space).
65   DWORD dwThreadID;  // Thread ID (-1=caller thread).
66   DWORD dwFlags;     // Reserved for future use, must be zero.
67 } THREADNAME_INFO;
68 #endif
69 
SetCurrentThreadName(const std::string & name)70 void Thread::SetCurrentThreadName(const std::string& name) {
71   if (name == "") {
72     return;
73   }
74 #if OS_MACOSX
75   pthread_setname_np(name.c_str());
76 #elif OS_LINUX || OS_ANDROID || WINDOWS_PLATFORM
77   pthread_setname_np(pthread_self(), name.c_str());
78 #elif OS_WIN
79   THREADNAME_INFO info;
80   info.dwType = 0x1000;
81   info.szName = name.c_str();
82   info.dwThreadID = GetCurrentThreadId();
83   info.dwFlags = 0;
84   __try {
85     RaiseException(kVCThreadNameException, 0, sizeof(info) / sizeof(DWORD),
86                    reinterpret_cast<DWORD_PTR*>(&info));
87   } __except (EXCEPTION_CONTINUE_EXECUTION) {
88   }
89 #else
90   FML_DLOG(INFO) << "Could not set the thread name to '" << name
91                  << "' on this platform.";
92 #endif
93 }
94 
95 }  // namespace fml
96