File indexing completed on 2026-05-10 08:44:34
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
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
0037
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 }
0154
0155 #else
0156
0157
0158
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
0209
0210 }
0211
0212 #else
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 }
0241
0242 #endif
0243
0244 #endif