- //===-- llvm/Support/thread.h - Wrapper for <thread> ------------*- C++ -*-===// 
- // 
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 
- // See https://llvm.org/LICENSE.txt for license information. 
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 
- // 
- //===----------------------------------------------------------------------===// 
- // 
- // This header is a wrapper for <thread> that works around problems with the 
- // MSVC headers when exceptions are disabled. It also provides llvm::thread, 
- // which is either a typedef of std::thread or a replacement that calls the 
- // function synchronously depending on the value of LLVM_ENABLE_THREADS. 
- // 
- //===----------------------------------------------------------------------===// 
-   
- #ifndef LLVM_SUPPORT_THREAD_H 
- #define LLVM_SUPPORT_THREAD_H 
-   
- #include "llvm/Config/llvm-config.h" 
- #include <optional> 
-   
- #ifdef _WIN32 
- typedef unsigned long DWORD; 
- typedef void *PVOID; 
- typedef PVOID HANDLE; 
- #endif 
-   
- #if LLVM_ENABLE_THREADS 
-   
- #include <thread> 
-   
- namespace llvm { 
-   
- #if LLVM_ON_UNIX || _WIN32 
-   
- /// LLVM thread following std::thread interface with added constructor to 
- /// specify stack size. 
- class thread { 
-   template <typename CalleeTuple> static void GenericThreadProxy(void *Ptr) { 
-     std::unique_ptr<CalleeTuple> Callee(static_cast<CalleeTuple *>(Ptr)); 
-     std::apply( 
-         [](auto &&F, auto &&...Args) { 
-           std::forward<decltype(F)>(F)(std::forward<decltype(Args)>(Args)...); 
-         }, 
-         *Callee); 
-   } 
-   
- public: 
- #if LLVM_ON_UNIX 
-   using native_handle_type = pthread_t; 
-   using id = pthread_t; 
-   using start_routine_type = void *(*)(void *); 
-   
-   template <typename CalleeTuple> static void *ThreadProxy(void *Ptr) { 
-     GenericThreadProxy<CalleeTuple>(Ptr); 
-     return nullptr; 
-   } 
- #elif _WIN32 
-   using native_handle_type = HANDLE; 
-   using id = DWORD; 
-   using start_routine_type = unsigned(__stdcall *)(void *); 
-   
-   template <typename CalleeTuple> 
-   static unsigned __stdcall ThreadProxy(void *Ptr) { 
-     GenericThreadProxy<CalleeTuple>(Ptr); 
-     return 0; 
-   } 
- #endif 
-   
-   static const std::optional<unsigned> DefaultStackSize; 
-   
-   thread() : Thread(native_handle_type()) {} 
-   thread(thread &&Other) noexcept 
-       : Thread(std::exchange(Other.Thread, native_handle_type())) {} 
-   
-   template <class Function, class... Args> 
-   explicit thread(Function &&f, Args &&...args) 
-       : thread(DefaultStackSize, f, args...) {} 
-   
-   template <class Function, class... Args> 
-   explicit thread(std::optional<unsigned> StackSizeInBytes, Function &&f, 
-                   Args &&...args); 
-   thread(const thread &) = delete; 
-   
-   ~thread() { 
-     if (joinable()) 
-       std::terminate(); 
-   } 
-   
-   thread &operator=(thread &&Other) noexcept { 
-     if (joinable()) 
-       std::terminate(); 
-     Thread = std::exchange(Other.Thread, native_handle_type()); 
-     return *this; 
-   } 
-   
-   bool joinable() const noexcept { return Thread != native_handle_type(); } 
-   
-   inline id get_id() const noexcept; 
-   
-   native_handle_type native_handle() const noexcept { return Thread; } 
-   
-   static unsigned hardware_concurrency() { 
-     return std::thread::hardware_concurrency(); 
-   }; 
-   
-   inline void join(); 
-   inline void detach(); 
-   
-   void swap(llvm::thread &Other) noexcept { std::swap(Thread, Other.Thread); } 
-   
- private: 
-   native_handle_type Thread; 
- }; 
-   
- thread::native_handle_type 
- llvm_execute_on_thread_impl(thread::start_routine_type ThreadFunc, void *Arg, 
-                             std::optional<unsigned> StackSizeInBytes); 
- void llvm_thread_join_impl(thread::native_handle_type Thread); 
- void llvm_thread_detach_impl(thread::native_handle_type Thread); 
- thread::id llvm_thread_get_id_impl(thread::native_handle_type Thread); 
- thread::id llvm_thread_get_current_id_impl(); 
-   
- template <class Function, class... Args> 
- thread::thread(std::optional<unsigned> StackSizeInBytes, Function &&f, 
-                Args &&...args) { 
-   typedef std::tuple<std::decay_t<Function>, std::decay_t<Args>...> CalleeTuple; 
-   std::unique_ptr<CalleeTuple> Callee( 
-       new CalleeTuple(std::forward<Function>(f), std::forward<Args>(args)...)); 
-   
-   Thread = llvm_execute_on_thread_impl(ThreadProxy<CalleeTuple>, Callee.get(), 
-                                        StackSizeInBytes); 
-   if (Thread != native_handle_type()) 
-     Callee.release(); 
- } 
-   
- thread::id thread::get_id() const noexcept { 
-   return llvm_thread_get_id_impl(Thread); 
- } 
-   
- void thread::join() { 
-   llvm_thread_join_impl(Thread); 
-   Thread = native_handle_type(); 
- } 
-   
- void thread::detach() { 
-   llvm_thread_detach_impl(Thread); 
-   Thread = native_handle_type(); 
- } 
-   
- namespace this_thread { 
- inline thread::id get_id() { return llvm_thread_get_current_id_impl(); } 
- } // namespace this_thread 
-   
- #else // !LLVM_ON_UNIX && !_WIN32 
-   
- /// std::thread backed implementation of llvm::thread interface that ignores the 
- /// stack size request. 
- class thread { 
- public: 
-   using native_handle_type = std::thread::native_handle_type; 
-   using id = std::thread::id; 
-   
-   thread() : Thread(std::thread()) {} 
-   thread(thread &&Other) noexcept 
-       : Thread(std::exchange(Other.Thread, std::thread())) {} 
-   
-   template <class Function, class... Args> 
-   explicit thread(std::optional<unsigned> StackSizeInBytes, Function &&f, 
-                   Args &&...args) 
-       : Thread(std::forward<Function>(f), std::forward<Args>(args)...) {} 
-   
-   template <class Function, class... Args> 
-   explicit thread(Function &&f, Args &&...args) : Thread(f, args...) {} 
-   
-   thread(const thread &) = delete; 
-   
-   ~thread() {} 
-   
-   thread &operator=(thread &&Other) noexcept { 
-     Thread = std::exchange(Other.Thread, std::thread()); 
-     return *this; 
-   } 
-   
-   bool joinable() const noexcept { return Thread.joinable(); } 
-   
-   id get_id() const noexcept { return Thread.get_id(); } 
-   
-   native_handle_type native_handle() noexcept { return Thread.native_handle(); } 
-   
-   static unsigned hardware_concurrency() { 
-     return std::thread::hardware_concurrency(); 
-   }; 
-   
-   inline void join() { Thread.join(); } 
-   inline void detach() { Thread.detach(); } 
-   
-   void swap(llvm::thread &Other) noexcept { std::swap(Thread, Other.Thread); } 
-   
- private: 
-   std::thread Thread; 
- }; 
-   
- namespace this_thread { 
-   inline thread::id get_id() { return std::this_thread::get_id(); } 
- } 
-   
- #endif // LLVM_ON_UNIX || _WIN32 
-   
- } // namespace llvm 
-   
- #else // !LLVM_ENABLE_THREADS 
-   
- #include <utility> 
-   
- namespace llvm { 
-   
- struct thread { 
-   thread() {} 
-   thread(thread &&other) {} 
-   template <class Function, class... Args> 
-   explicit thread(std::optional<unsigned> StackSizeInBytes, Function &&f, 
-                   Args &&...args) { 
-     f(std::forward<Args>(args)...); 
-   } 
-   template <class Function, class... Args> 
-   explicit thread(Function &&f, Args &&...args) { 
-     f(std::forward<Args>(args)...); 
-   } 
-   thread(const thread &) = delete; 
-   
-   void detach() { 
-     report_fatal_error("Detaching from a thread does not make sense with no " 
-                        "threading support"); 
-   } 
-   void join() {} 
-   static unsigned hardware_concurrency() { return 1; }; 
- }; 
-   
- } // namespace llvm 
-   
- #endif // LLVM_ENABLE_THREADS 
-   
- #endif // LLVM_SUPPORT_THREAD_H 
-