Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. //===-- llvm/Support/thread.h - Wrapper for <thread> ------------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This header is a wrapper for <thread> that works around problems with the
  10. // MSVC headers when exceptions are disabled. It also provides llvm::thread,
  11. // which is either a typedef of std::thread or a replacement that calls the
  12. // function synchronously depending on the value of LLVM_ENABLE_THREADS.
  13. //
  14. //===----------------------------------------------------------------------===//
  15.  
  16. #ifndef LLVM_SUPPORT_THREAD_H
  17. #define LLVM_SUPPORT_THREAD_H
  18.  
  19. #include "llvm/Config/llvm-config.h"
  20. #include <optional>
  21.  
  22. #ifdef _WIN32
  23. typedef unsigned long DWORD;
  24. typedef void *PVOID;
  25. typedef PVOID HANDLE;
  26. #endif
  27.  
  28. #if LLVM_ENABLE_THREADS
  29.  
  30. #include <thread>
  31.  
  32. namespace llvm {
  33.  
  34. #if LLVM_ON_UNIX || _WIN32
  35.  
  36. /// LLVM thread following std::thread interface with added constructor to
  37. /// specify stack size.
  38. class thread {
  39.   template <typename CalleeTuple> static void GenericThreadProxy(void *Ptr) {
  40.     std::unique_ptr<CalleeTuple> Callee(static_cast<CalleeTuple *>(Ptr));
  41.     std::apply(
  42.         [](auto &&F, auto &&...Args) {
  43.           std::forward<decltype(F)>(F)(std::forward<decltype(Args)>(Args)...);
  44.         },
  45.         *Callee);
  46.   }
  47.  
  48. public:
  49. #if LLVM_ON_UNIX
  50.   using native_handle_type = pthread_t;
  51.   using id = pthread_t;
  52.   using start_routine_type = void *(*)(void *);
  53.  
  54.   template <typename CalleeTuple> static void *ThreadProxy(void *Ptr) {
  55.     GenericThreadProxy<CalleeTuple>(Ptr);
  56.     return nullptr;
  57.   }
  58. #elif _WIN32
  59.   using native_handle_type = HANDLE;
  60.   using id = DWORD;
  61.   using start_routine_type = unsigned(__stdcall *)(void *);
  62.  
  63.   template <typename CalleeTuple>
  64.   static unsigned __stdcall ThreadProxy(void *Ptr) {
  65.     GenericThreadProxy<CalleeTuple>(Ptr);
  66.     return 0;
  67.   }
  68. #endif
  69.  
  70.   static const std::optional<unsigned> DefaultStackSize;
  71.  
  72.   thread() : Thread(native_handle_type()) {}
  73.   thread(thread &&Other) noexcept
  74.       : Thread(std::exchange(Other.Thread, native_handle_type())) {}
  75.  
  76.   template <class Function, class... Args>
  77.   explicit thread(Function &&f, Args &&...args)
  78.       : thread(DefaultStackSize, f, args...) {}
  79.  
  80.   template <class Function, class... Args>
  81.   explicit thread(std::optional<unsigned> StackSizeInBytes, Function &&f,
  82.                   Args &&...args);
  83.   thread(const thread &) = delete;
  84.  
  85.   ~thread() {
  86.     if (joinable())
  87.       std::terminate();
  88.   }
  89.  
  90.   thread &operator=(thread &&Other) noexcept {
  91.     if (joinable())
  92.       std::terminate();
  93.     Thread = std::exchange(Other.Thread, native_handle_type());
  94.     return *this;
  95.   }
  96.  
  97.   bool joinable() const noexcept { return Thread != native_handle_type(); }
  98.  
  99.   inline id get_id() const noexcept;
  100.  
  101.   native_handle_type native_handle() const noexcept { return Thread; }
  102.  
  103.   static unsigned hardware_concurrency() {
  104.     return std::thread::hardware_concurrency();
  105.   };
  106.  
  107.   inline void join();
  108.   inline void detach();
  109.  
  110.   void swap(llvm::thread &Other) noexcept { std::swap(Thread, Other.Thread); }
  111.  
  112. private:
  113.   native_handle_type Thread;
  114. };
  115.  
  116. thread::native_handle_type
  117. llvm_execute_on_thread_impl(thread::start_routine_type ThreadFunc, void *Arg,
  118.                             std::optional<unsigned> StackSizeInBytes);
  119. void llvm_thread_join_impl(thread::native_handle_type Thread);
  120. void llvm_thread_detach_impl(thread::native_handle_type Thread);
  121. thread::id llvm_thread_get_id_impl(thread::native_handle_type Thread);
  122. thread::id llvm_thread_get_current_id_impl();
  123.  
  124. template <class Function, class... Args>
  125. thread::thread(std::optional<unsigned> StackSizeInBytes, Function &&f,
  126.                Args &&...args) {
  127.   typedef std::tuple<std::decay_t<Function>, std::decay_t<Args>...> CalleeTuple;
  128.   std::unique_ptr<CalleeTuple> Callee(
  129.       new CalleeTuple(std::forward<Function>(f), std::forward<Args>(args)...));
  130.  
  131.   Thread = llvm_execute_on_thread_impl(ThreadProxy<CalleeTuple>, Callee.get(),
  132.                                        StackSizeInBytes);
  133.   if (Thread != native_handle_type())
  134.     Callee.release();
  135. }
  136.  
  137. thread::id thread::get_id() const noexcept {
  138.   return llvm_thread_get_id_impl(Thread);
  139. }
  140.  
  141. void thread::join() {
  142.   llvm_thread_join_impl(Thread);
  143.   Thread = native_handle_type();
  144. }
  145.  
  146. void thread::detach() {
  147.   llvm_thread_detach_impl(Thread);
  148.   Thread = native_handle_type();
  149. }
  150.  
  151. namespace this_thread {
  152. inline thread::id get_id() { return llvm_thread_get_current_id_impl(); }
  153. } // namespace this_thread
  154.  
  155. #else // !LLVM_ON_UNIX && !_WIN32
  156.  
  157. /// std::thread backed implementation of llvm::thread interface that ignores the
  158. /// stack size request.
  159. class thread {
  160. public:
  161.   using native_handle_type = std::thread::native_handle_type;
  162.   using id = std::thread::id;
  163.  
  164.   thread() : Thread(std::thread()) {}
  165.   thread(thread &&Other) noexcept
  166.       : Thread(std::exchange(Other.Thread, std::thread())) {}
  167.  
  168.   template <class Function, class... Args>
  169.   explicit thread(std::optional<unsigned> StackSizeInBytes, Function &&f,
  170.                   Args &&...args)
  171.       : Thread(std::forward<Function>(f), std::forward<Args>(args)...) {}
  172.  
  173.   template <class Function, class... Args>
  174.   explicit thread(Function &&f, Args &&...args) : Thread(f, args...) {}
  175.  
  176.   thread(const thread &) = delete;
  177.  
  178.   ~thread() {}
  179.  
  180.   thread &operator=(thread &&Other) noexcept {
  181.     Thread = std::exchange(Other.Thread, std::thread());
  182.     return *this;
  183.   }
  184.  
  185.   bool joinable() const noexcept { return Thread.joinable(); }
  186.  
  187.   id get_id() const noexcept { return Thread.get_id(); }
  188.  
  189.   native_handle_type native_handle() noexcept { return Thread.native_handle(); }
  190.  
  191.   static unsigned hardware_concurrency() {
  192.     return std::thread::hardware_concurrency();
  193.   };
  194.  
  195.   inline void join() { Thread.join(); }
  196.   inline void detach() { Thread.detach(); }
  197.  
  198.   void swap(llvm::thread &Other) noexcept { std::swap(Thread, Other.Thread); }
  199.  
  200. private:
  201.   std::thread Thread;
  202. };
  203.  
  204. namespace this_thread {
  205.   inline thread::id get_id() { return std::this_thread::get_id(); }
  206. }
  207.  
  208. #endif // LLVM_ON_UNIX || _WIN32
  209.  
  210. } // namespace llvm
  211.  
  212. #else // !LLVM_ENABLE_THREADS
  213.  
  214. #include <utility>
  215.  
  216. namespace llvm {
  217.  
  218. struct thread {
  219.   thread() {}
  220.   thread(thread &&other) {}
  221.   template <class Function, class... Args>
  222.   explicit thread(std::optional<unsigned> StackSizeInBytes, Function &&f,
  223.                   Args &&...args) {
  224.     f(std::forward<Args>(args)...);
  225.   }
  226.   template <class Function, class... Args>
  227.   explicit thread(Function &&f, Args &&...args) {
  228.     f(std::forward<Args>(args)...);
  229.   }
  230.   thread(const thread &) = delete;
  231.  
  232.   void detach() {
  233.     report_fatal_error("Detaching from a thread does not make sense with no "
  234.                        "threading support");
  235.   }
  236.   void join() {}
  237.   static unsigned hardware_concurrency() { return 1; };
  238. };
  239.  
  240. } // namespace llvm
  241.  
  242. #endif // LLVM_ENABLE_THREADS
  243.  
  244. #endif // LLVM_SUPPORT_THREAD_H
  245.