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