LLVM 22.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"
21#include <optional>
22#include <tuple>
23#include <utility>
24
25#ifdef _WIN32
26typedef unsigned long DWORD;
27typedef void *PVOID;
28typedef PVOID HANDLE;
29#endif
30
31#if LLVM_ENABLE_THREADS
32
33#include <thread>
34
35namespace llvm {
36
37#if LLVM_ON_UNIX || _WIN32
38
39/// LLVM thread following std::thread interface with added constructor to
40/// specify stack size.
41class thread {
42 template <typename CalleeTuple> static void GenericThreadProxy(void *Ptr) {
43 std::unique_ptr<CalleeTuple> Callee(static_cast<CalleeTuple *>(Ptr));
44 std::apply(
45 [](auto &&F, auto &&...Args) {
46 std::forward<decltype(F)>(F)(std::forward<decltype(Args)>(Args)...);
47 },
48 *Callee);
49 }
50
51public:
52#if LLVM_ON_UNIX
53 using native_handle_type = pthread_t;
54 using id = pthread_t;
55 using start_routine_type = void *(*)(void *);
56
57 template <typename CalleeTuple> static void *ThreadProxy(void *Ptr) {
58 GenericThreadProxy<CalleeTuple>(Ptr);
59 return nullptr;
60 }
61#elif _WIN32
62 using native_handle_type = HANDLE;
63 using id = DWORD;
64 using start_routine_type = unsigned(__stdcall *)(void *);
65
66 template <typename CalleeTuple>
67 static unsigned __stdcall ThreadProxy(void *Ptr) {
68 GenericThreadProxy<CalleeTuple>(Ptr);
69 return 0;
70 }
71#endif
72
73 LLVM_ABI static const std::optional<unsigned> DefaultStackSize;
74
75 thread() : Thread(native_handle_type()) {}
76 thread(thread &&Other) noexcept
77 : Thread(std::exchange(Other.Thread, native_handle_type())) {}
78
79 template <class Function, class... Args>
80 explicit thread(Function &&f, Args &&...args)
81 : thread(DefaultStackSize, f, args...) {}
82
83 template <class Function, class... Args>
84 explicit thread(std::optional<unsigned> StackSizeInBytes, Function &&f,
85 Args &&...args);
86 thread(const thread &) = delete;
87
88 ~thread() {
89 if (joinable())
90 std::terminate();
91 }
92
93 thread &operator=(thread &&Other) noexcept {
94 if (joinable())
95 std::terminate();
96 Thread = std::exchange(Other.Thread, native_handle_type());
97 return *this;
98 }
99
100 bool joinable() const noexcept { return Thread != native_handle_type(); }
101
102 inline id get_id() const noexcept;
103
104 native_handle_type native_handle() const noexcept { return Thread; }
105
106 static unsigned hardware_concurrency() {
107 return std::thread::hardware_concurrency();
108 };
109
110 inline void join();
111 inline void detach();
112
113 void swap(llvm::thread &Other) noexcept { std::swap(Thread, Other.Thread); }
114
115private:
116 native_handle_type Thread;
117};
118
119LLVM_ABI thread::native_handle_type
120llvm_execute_on_thread_impl(thread::start_routine_type ThreadFunc, void *Arg,
121 std::optional<unsigned> StackSizeInBytes);
122LLVM_ABI void llvm_thread_join_impl(thread::native_handle_type Thread);
123LLVM_ABI void llvm_thread_detach_impl(thread::native_handle_type Thread);
124LLVM_ABI thread::id llvm_thread_get_id_impl(thread::native_handle_type Thread);
125LLVM_ABI thread::id llvm_thread_get_current_id_impl();
126
127template <class Function, class... Args>
128thread::thread(std::optional<unsigned> StackSizeInBytes, Function &&f,
129 Args &&...args) {
130 typedef std::tuple<std::decay_t<Function>, std::decay_t<Args>...> CalleeTuple;
131 std::unique_ptr<CalleeTuple> Callee(
132 new CalleeTuple(std::forward<Function>(f), std::forward<Args>(args)...));
133
134 Thread = llvm_execute_on_thread_impl(ThreadProxy<CalleeTuple>, Callee.get(),
135 StackSizeInBytes);
136 if (Thread != native_handle_type())
137 Callee.release();
138}
139
140thread::id thread::get_id() const noexcept {
141 return llvm_thread_get_id_impl(Thread);
142}
143
144void thread::join() {
145 llvm_thread_join_impl(Thread);
146 Thread = native_handle_type();
147}
148
149void thread::detach() {
150 llvm_thread_detach_impl(Thread);
151 Thread = native_handle_type();
152}
153
154namespace this_thread {
155inline thread::id get_id() { return llvm_thread_get_current_id_impl(); }
156} // namespace this_thread
157
158#else // !LLVM_ON_UNIX && !_WIN32
159
160/// std::thread backed implementation of llvm::thread interface that ignores the
161/// stack size request.
162class thread {
163public:
164 using native_handle_type = std::thread::native_handle_type;
165 using id = std::thread::id;
166
167 thread() : Thread(std::thread()) {}
168 thread(thread &&Other) noexcept
169 : Thread(std::exchange(Other.Thread, std::thread())) {}
170
171 template <class Function, class... Args>
172 explicit thread(std::optional<unsigned> StackSizeInBytes, Function &&f,
173 Args &&...args)
174 : Thread(std::forward<Function>(f), std::forward<Args>(args)...) {}
175
176 template <class Function, class... Args>
177 explicit thread(Function &&f, Args &&...args) : Thread(f, args...) {}
178
179 thread(const thread &) = delete;
180
181 ~thread() {}
182
183 thread &operator=(thread &&Other) noexcept {
184 Thread = std::exchange(Other.Thread, std::thread());
185 return *this;
186 }
187
188 bool joinable() const noexcept { return Thread.joinable(); }
189
190 id get_id() const noexcept { return Thread.get_id(); }
191
192 native_handle_type native_handle() noexcept { return Thread.native_handle(); }
193
194 static unsigned hardware_concurrency() {
195 return std::thread::hardware_concurrency();
196 };
197
198 inline void join() { Thread.join(); }
199 inline void detach() { Thread.detach(); }
200
201 void swap(llvm::thread &Other) noexcept { std::swap(Thread, Other.Thread); }
202
203private:
204 std::thread Thread;
205};
206
207namespace this_thread {
208inline thread::id get_id() { return std::this_thread::get_id(); }
209} // namespace this_thread
210
211#endif // LLVM_ON_UNIX || _WIN32
212
213} // namespace llvm
214
215#else // !LLVM_ENABLE_THREADS
216
218#include <utility>
219
220namespace llvm {
221
222struct thread {
224 thread(thread &&other) {}
225 template <class Function, class... Args>
226 explicit thread(std::optional<unsigned> StackSizeInBytes, Function &&f,
227 Args &&...args) {
228 f(std::forward<Args>(args)...);
229 }
230 template <class Function, class... Args>
231 explicit thread(Function &&f, Args &&...args) {
232 f(std::forward<Args>(args)...);
233 }
234 thread(const thread &) = delete;
235
236 void detach() {
237 report_fatal_error("Detaching from a thread does not make sense with no "
238 "threading support");
239 }
240 void join() {}
241 static unsigned hardware_concurrency() { return 1; };
242};
243
244} // namespace llvm
245
246#endif // LLVM_ENABLE_THREADS
247
248#endif // LLVM_SUPPORT_THREAD_H
aarch64 promote const
#define LLVM_ABI
Definition: Compiler.h:213
#define F(x, y, z)
Definition: MD5.cpp:55
nvptx lower args
uint64_t Thread
Definition: Profile.cpp:47
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition: Error.cpp:167
@ Other
Any other memory.
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:851
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition: BitVector.h:853
thread(std::optional< unsigned > StackSizeInBytes, Function &&f, Args &&...args)
Definition: thread.h:226
static unsigned hardware_concurrency()
Definition: thread.h:241
void join()
Definition: thread.h:240
thread(Function &&f, Args &&...args)
Definition: thread.h:231
thread(const thread &)=delete
thread(thread &&other)
Definition: thread.h:224
void detach()
Definition: thread.h:236