Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:44:34

0001 //===-- llvm/Support/thread.h - Wrapper for <thread> ------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // This header is a wrapper for <thread> that works around problems with the
0010 // MSVC headers when exceptions are disabled. It also provides llvm::thread,
0011 // which is either a typedef of std::thread or a replacement that calls the
0012 // function synchronously depending on the value of LLVM_ENABLE_THREADS.
0013 //
0014 //===----------------------------------------------------------------------===//
0015 
0016 #ifndef LLVM_SUPPORT_THREAD_H
0017 #define LLVM_SUPPORT_THREAD_H
0018 
0019 #include "llvm/Config/llvm-config.h"
0020 #include <optional>
0021 
0022 #ifdef _WIN32
0023 typedef unsigned long DWORD;
0024 typedef void *PVOID;
0025 typedef PVOID HANDLE;
0026 #endif
0027 
0028 #if LLVM_ENABLE_THREADS
0029 
0030 #include <thread>
0031 
0032 namespace llvm {
0033 
0034 #if LLVM_ON_UNIX || _WIN32
0035 
0036 /// LLVM thread following std::thread interface with added constructor to
0037 /// specify stack size.
0038 class thread {
0039   template <typename CalleeTuple> static void GenericThreadProxy(void *Ptr) {
0040     std::unique_ptr<CalleeTuple> Callee(static_cast<CalleeTuple *>(Ptr));
0041     std::apply(
0042         [](auto &&F, auto &&...Args) {
0043           std::forward<decltype(F)>(F)(std::forward<decltype(Args)>(Args)...);
0044         },
0045         *Callee);
0046   }
0047 
0048 public:
0049 #if LLVM_ON_UNIX
0050   using native_handle_type = pthread_t;
0051   using id = pthread_t;
0052   using start_routine_type = void *(*)(void *);
0053 
0054   template <typename CalleeTuple> static void *ThreadProxy(void *Ptr) {
0055     GenericThreadProxy<CalleeTuple>(Ptr);
0056     return nullptr;
0057   }
0058 #elif _WIN32
0059   using native_handle_type = HANDLE;
0060   using id = DWORD;
0061   using start_routine_type = unsigned(__stdcall *)(void *);
0062 
0063   template <typename CalleeTuple>
0064   static unsigned __stdcall ThreadProxy(void *Ptr) {
0065     GenericThreadProxy<CalleeTuple>(Ptr);
0066     return 0;
0067   }
0068 #endif
0069 
0070   static const std::optional<unsigned> DefaultStackSize;
0071 
0072   thread() : Thread(native_handle_type()) {}
0073   thread(thread &&Other) noexcept
0074       : Thread(std::exchange(Other.Thread, native_handle_type())) {}
0075 
0076   template <class Function, class... Args>
0077   explicit thread(Function &&f, Args &&...args)
0078       : thread(DefaultStackSize, f, args...) {}
0079 
0080   template <class Function, class... Args>
0081   explicit thread(std::optional<unsigned> StackSizeInBytes, Function &&f,
0082                   Args &&...args);
0083   thread(const thread &) = delete;
0084 
0085   ~thread() {
0086     if (joinable())
0087       std::terminate();
0088   }
0089 
0090   thread &operator=(thread &&Other) noexcept {
0091     if (joinable())
0092       std::terminate();
0093     Thread = std::exchange(Other.Thread, native_handle_type());
0094     return *this;
0095   }
0096 
0097   bool joinable() const noexcept { return Thread != native_handle_type(); }
0098 
0099   inline id get_id() const noexcept;
0100 
0101   native_handle_type native_handle() const noexcept { return Thread; }
0102 
0103   static unsigned hardware_concurrency() {
0104     return std::thread::hardware_concurrency();
0105   };
0106 
0107   inline void join();
0108   inline void detach();
0109 
0110   void swap(llvm::thread &Other) noexcept { std::swap(Thread, Other.Thread); }
0111 
0112 private:
0113   native_handle_type Thread;
0114 };
0115 
0116 thread::native_handle_type
0117 llvm_execute_on_thread_impl(thread::start_routine_type ThreadFunc, void *Arg,
0118                             std::optional<unsigned> StackSizeInBytes);
0119 void llvm_thread_join_impl(thread::native_handle_type Thread);
0120 void llvm_thread_detach_impl(thread::native_handle_type Thread);
0121 thread::id llvm_thread_get_id_impl(thread::native_handle_type Thread);
0122 thread::id llvm_thread_get_current_id_impl();
0123 
0124 template <class Function, class... Args>
0125 thread::thread(std::optional<unsigned> StackSizeInBytes, Function &&f,
0126                Args &&...args) {
0127   typedef std::tuple<std::decay_t<Function>, std::decay_t<Args>...> CalleeTuple;
0128   std::unique_ptr<CalleeTuple> Callee(
0129       new CalleeTuple(std::forward<Function>(f), std::forward<Args>(args)...));
0130 
0131   Thread = llvm_execute_on_thread_impl(ThreadProxy<CalleeTuple>, Callee.get(),
0132                                        StackSizeInBytes);
0133   if (Thread != native_handle_type())
0134     Callee.release();
0135 }
0136 
0137 thread::id thread::get_id() const noexcept {
0138   return llvm_thread_get_id_impl(Thread);
0139 }
0140 
0141 void thread::join() {
0142   llvm_thread_join_impl(Thread);
0143   Thread = native_handle_type();
0144 }
0145 
0146 void thread::detach() {
0147   llvm_thread_detach_impl(Thread);
0148   Thread = native_handle_type();
0149 }
0150 
0151 namespace this_thread {
0152 inline thread::id get_id() { return llvm_thread_get_current_id_impl(); }
0153 } // namespace this_thread
0154 
0155 #else // !LLVM_ON_UNIX && !_WIN32
0156 
0157 /// std::thread backed implementation of llvm::thread interface that ignores the
0158 /// stack size request.
0159 class thread {
0160 public:
0161   using native_handle_type = std::thread::native_handle_type;
0162   using id = std::thread::id;
0163 
0164   thread() : Thread(std::thread()) {}
0165   thread(thread &&Other) noexcept
0166       : Thread(std::exchange(Other.Thread, std::thread())) {}
0167 
0168   template <class Function, class... Args>
0169   explicit thread(std::optional<unsigned> StackSizeInBytes, Function &&f,
0170                   Args &&...args)
0171       : Thread(std::forward<Function>(f), std::forward<Args>(args)...) {}
0172 
0173   template <class Function, class... Args>
0174   explicit thread(Function &&f, Args &&...args) : Thread(f, args...) {}
0175 
0176   thread(const thread &) = delete;
0177 
0178   ~thread() {}
0179 
0180   thread &operator=(thread &&Other) noexcept {
0181     Thread = std::exchange(Other.Thread, std::thread());
0182     return *this;
0183   }
0184 
0185   bool joinable() const noexcept { return Thread.joinable(); }
0186 
0187   id get_id() const noexcept { return Thread.get_id(); }
0188 
0189   native_handle_type native_handle() noexcept { return Thread.native_handle(); }
0190 
0191   static unsigned hardware_concurrency() {
0192     return std::thread::hardware_concurrency();
0193   };
0194 
0195   inline void join() { Thread.join(); }
0196   inline void detach() { Thread.detach(); }
0197 
0198   void swap(llvm::thread &Other) noexcept { std::swap(Thread, Other.Thread); }
0199 
0200 private:
0201   std::thread Thread;
0202 };
0203 
0204 namespace this_thread {
0205   inline thread::id get_id() { return std::this_thread::get_id(); }
0206 }
0207 
0208 #endif // LLVM_ON_UNIX || _WIN32
0209 
0210 } // namespace llvm
0211 
0212 #else // !LLVM_ENABLE_THREADS
0213 
0214 #include <utility>
0215 
0216 namespace llvm {
0217 
0218 struct thread {
0219   thread() {}
0220   thread(thread &&other) {}
0221   template <class Function, class... Args>
0222   explicit thread(std::optional<unsigned> StackSizeInBytes, Function &&f,
0223                   Args &&...args) {
0224     f(std::forward<Args>(args)...);
0225   }
0226   template <class Function, class... Args>
0227   explicit thread(Function &&f, Args &&...args) {
0228     f(std::forward<Args>(args)...);
0229   }
0230   thread(const thread &) = delete;
0231 
0232   void detach() {
0233     report_fatal_error("Detaching from a thread does not make sense with no "
0234                        "threading support");
0235   }
0236   void join() {}
0237   static unsigned hardware_concurrency() { return 1; };
0238 };
0239 
0240 } // namespace llvm
0241 
0242 #endif // LLVM_ENABLE_THREADS
0243 
0244 #endif // LLVM_SUPPORT_THREAD_H