LLVM 20.0.0git
thread.h
Go to the documentation of this file.
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
23typedef unsigned long DWORD;
24typedef void *PVOID;
25typedef PVOID HANDLE;
26#endif
27
28#if LLVM_ENABLE_THREADS
29
30#include <thread>
31
32namespace llvm {
33
34#if LLVM_ON_UNIX || _WIN32
35
36/// LLVM thread following std::thread interface with added constructor to
37/// specify stack size.
38class 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
48public:
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
112private:
113 native_handle_type Thread;
114};
115
116thread::native_handle_type
117llvm_execute_on_thread_impl(thread::start_routine_type ThreadFunc, void *Arg,
118 std::optional<unsigned> StackSizeInBytes);
119void llvm_thread_join_impl(thread::native_handle_type Thread);
120void llvm_thread_detach_impl(thread::native_handle_type Thread);
121thread::id llvm_thread_get_id_impl(thread::native_handle_type Thread);
122thread::id llvm_thread_get_current_id_impl();
123
124template <class Function, class... Args>
125thread::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
137thread::id thread::get_id() const noexcept {
138 return llvm_thread_get_id_impl(Thread);
139}
140
141void thread::join() {
142 llvm_thread_join_impl(Thread);
143 Thread = native_handle_type();
144}
145
146void thread::detach() {
147 llvm_thread_detach_impl(Thread);
148 Thread = native_handle_type();
149}
150
151namespace this_thread {
152inline 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.
159class thread {
160public:
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
200private:
201 std::thread Thread;
202};
203
204namespace 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
216namespace llvm {
217
218struct 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
aarch64 promote const
#define F(x, y, z)
Definition: MD5.cpp:55
nvptx lower args
uint64_t Thread
Definition: Profile.cpp:48
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:167
@ Other
Any other memory.
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:858
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition: BitVector.h:860
thread(std::optional< unsigned > StackSizeInBytes, Function &&f, Args &&...args)
Definition: thread.h:222
static unsigned hardware_concurrency()
Definition: thread.h:237
void join()
Definition: thread.h:236
thread(Function &&f, Args &&...args)
Definition: thread.h:227
thread(const thread &)=delete
thread(thread &&other)
Definition: thread.h:220
void detach()
Definition: thread.h:232