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