Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
14 pmbaty 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
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 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
 
48
public:
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
 
112
private:
113
  native_handle_type Thread;
114
};
115
 
116
thread::native_handle_type
117
llvm_execute_on_thread_impl(thread::start_routine_type ThreadFunc, void *Arg,
118
                            std::optional<unsigned> StackSizeInBytes);
119
void llvm_thread_join_impl(thread::native_handle_type Thread);
120
void llvm_thread_detach_impl(thread::native_handle_type Thread);
121
thread::id llvm_thread_get_id_impl(thread::native_handle_type Thread);
122
thread::id llvm_thread_get_current_id_impl();
123
 
124
template <class Function, class... Args>
125
thread::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
 
137
thread::id thread::get_id() const noexcept {
138
  return llvm_thread_get_id_impl(Thread);
139
}
140
 
141
void thread::join() {
142
  llvm_thread_join_impl(Thread);
143
  Thread = native_handle_type();
144
}
145
 
146
void thread::detach() {
147
  llvm_thread_detach_impl(Thread);
148
  Thread = native_handle_type();
149
}
150
 
151
namespace this_thread {
152
inline 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.
159
class thread {
160
public:
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
 
200
private:
201
  std::thread Thread;
202
};
203
 
204
namespace 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
 
216
namespace llvm {
217
 
218
struct thread {
219
  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