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)26Thread::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()41Thread::~Thread() { 42 Join(); 43 } 44 GetTaskRunner() const45fml::RefPtr<fml::TaskRunner> Thread::GetTaskRunner() const { 46 return task_runner_; 47 } 48 Join()49void 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)70void 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