LLVM  16.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/ADT/Optional.h"
20 #include "llvm/Config/llvm-config.h"
21 
22 #ifdef _WIN32
23 typedef unsigned long DWORD;
24 typedef void *PVOID;
25 typedef PVOID HANDLE;
26 #endif
27 
28 #if LLVM_ENABLE_THREADS
29 
30 #include <thread>
31 
32 namespace llvm {
33 
34 #if LLVM_ON_UNIX || _WIN32
35 
36 /// LLVM thread following std::thread interface with added constructor to
37 /// specify stack size.
38 class thread {
39  template <typename FPtr, typename... Args, size_t... Indices>
40  static void Apply(std::tuple<FPtr, Args...> &Callee,
41  std::index_sequence<Indices...>) {
42  std::move(std::get<0>(Callee))(std::move(std::get<Indices + 1>(Callee))...);
43  }
44 
45  template <typename CalleeTuple> static void GenericThreadProxy(void *Ptr) {
46  std::unique_ptr<CalleeTuple> Callee(static_cast<CalleeTuple *>(Ptr));
47 
48  // FIXME: use std::apply when C++17 is allowed.
49  std::make_index_sequence<std::tuple_size<CalleeTuple>() - 1> Indices{};
50  Apply(*Callee.get(), Indices);
51  }
52 
53 public:
54 #if LLVM_ON_UNIX
55  using native_handle_type = pthread_t;
56  using id = pthread_t;
57  using start_routine_type = void *(*)(void *);
58 
59  template <typename CalleeTuple> static void *ThreadProxy(void *Ptr) {
60  GenericThreadProxy<CalleeTuple>(Ptr);
61  return nullptr;
62  }
63 #elif _WIN32
64  using native_handle_type = HANDLE;
65  using id = DWORD;
66  using start_routine_type = unsigned(__stdcall *)(void *);
67 
68  template <typename CalleeTuple>
69  static unsigned __stdcall ThreadProxy(void *Ptr) {
70  GenericThreadProxy<CalleeTuple>(Ptr);
71  return 0;
72  }
73 #endif
74 
76 
77  thread() : Thread(native_handle_type()) {}
78  thread(thread &&Other) noexcept
79  : Thread(std::exchange(Other.Thread, native_handle_type())) {}
80 
81  template <class Function, class... Args>
82  explicit thread(Function &&f, Args &&...args)
83  : thread(DefaultStackSize, f, args...) {}
84 
85  template <class Function, class... Args>
86  explicit thread(llvm::Optional<unsigned> StackSizeInBytes, Function &&f,
87  Args &&...args);
88  thread(const thread &) = delete;
89 
90  ~thread() {
91  if (joinable())
92  std::terminate();
93  }
94 
95  thread &operator=(thread &&Other) noexcept {
96  if (joinable())
97  std::terminate();
98  Thread = std::exchange(Other.Thread, native_handle_type());
99  return *this;
100  }
101 
102  bool joinable() const noexcept { return Thread != native_handle_type(); }
103 
104  inline id get_id() const noexcept;
105 
106  native_handle_type native_handle() const noexcept { return Thread; }
107 
108  static unsigned hardware_concurrency() {
110  };
111 
112  inline void join();
113  inline void detach();
114 
115  void swap(llvm::thread &Other) noexcept { std::swap(Thread, Other.Thread); }
116 
117 private:
118  native_handle_type Thread;
119 };
120 
123  llvm::Optional<unsigned> StackSizeInBytes);
128 
129 template <class Function, class... Args>
131  Args &&...args) {
132  typedef std::tuple<std::decay_t<Function>, std::decay_t<Args>...> CalleeTuple;
133  std::unique_ptr<CalleeTuple> Callee(
134  new CalleeTuple(std::forward<Function>(f), std::forward<Args>(args)...));
135 
136  Thread = llvm_execute_on_thread_impl(ThreadProxy<CalleeTuple>, Callee.get(),
137  StackSizeInBytes);
138  if (Thread != native_handle_type())
139  Callee.release();
140 }
141 
143  return llvm_thread_get_id_impl(Thread);
144 }
145 
146 void thread::join() {
147  llvm_thread_join_impl(Thread);
148  Thread = native_handle_type();
149 }
150 
152  llvm_thread_detach_impl(Thread);
153  Thread = native_handle_type();
154 }
155 
156 namespace this_thread {
158 } // namespace this_thread
159 
160 #else // !LLVM_ON_UNIX && !_WIN32
161 
162 /// std::thread backed implementation of llvm::thread interface that ignores the
163 /// stack size request.
164 class thread {
165 public:
166  using native_handle_type = std::thread::native_handle_type;
167  using id = std::thread::id;
168 
169  thread() : Thread(std::thread()) {}
170  thread(thread &&Other) noexcept
171  : Thread(std::exchange(Other.Thread, std::thread())) {}
172 
173  template <class Function, class... Args>
174  explicit thread(llvm::Optional<unsigned> StackSizeInBytes, Function &&f,
175  Args &&...args)
176  : Thread(std::forward<Function>(f), std::forward<Args>(args)...) {}
177 
178  template <class Function, class... Args>
179  explicit thread(Function &&f, Args &&...args) : Thread(f, args...) {}
180 
181  thread(const thread &) = delete;
182 
183  ~thread() {}
184 
185  thread &operator=(thread &&Other) noexcept {
186  Thread = std::exchange(Other.Thread, std::thread());
187  return *this;
188  }
189 
190  bool joinable() const noexcept { return Thread.joinable(); }
191 
192  id get_id() const noexcept { return Thread.get_id(); }
193 
194  native_handle_type native_handle() noexcept { return Thread.native_handle(); }
195 
196  static unsigned hardware_concurrency() {
198  };
199 
200  inline void join() { Thread.join(); }
201  inline void detach() { Thread.detach(); }
202 
203  void swap(llvm::thread &Other) noexcept { std::swap(Thread, Other.Thread); }
204 
205 private:
206  std::thread Thread;
207 };
208 
209 namespace this_thread {
210  inline thread::id get_id() { return std::this_thread::get_id(); }
211 }
212 
213 #endif // LLVM_ON_UNIX || _WIN32
214 
215 } // namespace llvm
216 
217 #else // !LLVM_ENABLE_THREADS
218 
219 #include <utility>
220 
221 namespace llvm {
222 
223 struct thread {
224  thread() {}
225  thread(thread &&other) {}
226  template <class Function, class... Args>
227  explicit thread(llvm::Optional<unsigned> StackSizeInBytes, Function &&f,
228  Args &&...args) {
229  f(std::forward<Args>(args)...);
230  }
231  template <class Function, class... Args>
232  explicit thread(Function &&f, Args &&...args) {
233  f(std::forward<Args>(args)...);
234  }
235  thread(const thread &) = delete;
236 
237  void detach() {
238  report_fatal_error("Detaching from a thread does not make sense with no "
239  "threading support");
240  }
241  void join() {}
242  static unsigned hardware_concurrency() { return 1; };
243 };
244 
245 } // namespace llvm
246 
247 #endif // LLVM_ENABLE_THREADS
248 
249 #endif // LLVM_SUPPORT_THREAD_H
llvm::this_thread::get_id
thread::id get_id()
Definition: thread.h:157
llvm::llvm_thread_get_id_impl
thread::id llvm_thread_get_id_impl(thread::native_handle_type Thread)
llvm::thread::operator=
thread & operator=(thread &&Other) noexcept
Definition: thread.h:95
llvm::hardware_concurrency
ThreadPoolStrategy hardware_concurrency(unsigned ThreadCount=0)
Returns a default thread strategy where all available hardware resources are to be used,...
Definition: Threading.h:185
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
Optional.h
llvm::thread::hardware_concurrency
static unsigned hardware_concurrency()
Definition: thread.h:108
llvm::Function
Definition: Function.h:60
llvm::thread::ThreadProxy
static void * ThreadProxy(void *Ptr)
Definition: thread.h:59
Thread
uint64_t Thread
Definition: Profile.cpp:48
llvm::llvm_thread_get_current_id_impl
thread::id llvm_thread_get_current_id_impl()
llvm::thread::thread
thread(Function &&f, Args &&...args)
Definition: thread.h:82
llvm::llvm_thread_join_impl
void llvm_thread_join_impl(thread::native_handle_type Thread)
llvm::llvm_thread_detach_impl
void llvm_thread_detach_impl(thread::native_handle_type Thread)
llvm::llvm_execute_on_thread_impl
thread::native_handle_type llvm_execute_on_thread_impl(thread::start_routine_type ThreadFunc, void *Arg, llvm::Optional< unsigned > StackSizeInBytes)
llvm::Optional< unsigned >
Arg
amdgpu Simplify well known AMD library false FunctionCallee Value * Arg
Definition: AMDGPULibCalls.cpp:187
f
Itanium Name Demangler i e convert the string _Z1fv into f()". You can also use the CRTP base ManglingParser to perform some simple analysis on the mangled name
llvm::thread::id
pthread_t id
Definition: thread.h:56
llvm::report_fatal_error
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:145
llvm::thread::get_id
id get_id() const noexcept
Definition: thread.h:142
llvm::thread::detach
void detach()
Definition: thread.h:151
const
aarch64 promote const
Definition: AArch64PromoteConstant.cpp:232
llvm::thread
LLVM thread following std::thread interface with added constructor to specify stack size.
Definition: thread.h:38
move
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Definition: README.txt:546
llvm::AMDGPU::SDWA::DWORD
@ DWORD
Definition: SIDefines.h:769
std::swap
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition: BitVector.h:853
Ptr
@ Ptr
Definition: TargetLibraryInfo.cpp:60
llvm::thread::thread
thread()
Definition: thread.h:77
llvm::thread::join
void join()
Definition: thread.h:146
llvm::thread::~thread
~thread()
Definition: thread.h:90
llvm::thread::native_handle
native_handle_type native_handle() const noexcept
Definition: thread.h:106
Callee
amdgpu Simplify well known AMD library false FunctionCallee Callee
Definition: AMDGPULibCalls.cpp:187
llvm::thread::DefaultStackSize
static const llvm::Optional< unsigned > DefaultStackSize
Definition: thread.h:75
std
Definition: BitVector.h:851
llvm::thread::joinable
bool joinable() const noexcept
Definition: thread.h:102
llvm::thread::native_handle_type
pthread_t native_handle_type
Definition: thread.h:55
llvm::thread::thread
thread(thread &&Other) noexcept
Definition: thread.h:78
Other
std::optional< std::vector< StOtherPiece > > Other
Definition: ELFYAML.cpp:1252
llvm::AMDGPU::HSAMD::Kernel::Key::Args
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
Definition: AMDGPUMetadata.h:394
llvm::thread::swap
void swap(llvm::thread &Other) noexcept
Definition: thread.h:115
llvm::codeview::PublicSymFlags::Function
@ Function
llvm::thread::start_routine_type
void *(*)(void *) start_routine_type
Definition: thread.h:57