CellModules
mingw.thread.h
Go to the documentation of this file.
1
20#ifndef WIN32STDTHREAD_H
21#define WIN32STDTHREAD_H
22
23#if !defined(__cplusplus) || (__cplusplus < 201103L)
24#error A C++11 compiler is required!
25#endif
26
27// Use the standard classes for std::, if available.
28#include <thread>
29
30#include <windows.h>
31#include <functional>
32#include <memory>
33#include <chrono>
34#include <system_error>
35#include <cerrno>
36#include <ostream>
37#include <process.h>
38#include <ostream>
39#include <type_traits>
40
41//instead of INVALID_HANDLE_VALUE _beginthreadex returns 0
42#define _STD_THREAD_INVALID_HANDLE 0
43namespace mingw_stdthread
44{
45namespace detail
46{
47// For compatibility, implement std::invoke for C++11 and C++14
48#if __cplusplus < 201703L
49 template<bool PMemFunc, bool PMemData>
50 struct Invoker
51 {
52 template<class F, class... Args>
53 inline static typename std::result_of<F(Args...)>::type invoke (F&& f, Args&&... args)
54 {
55 return std::forward<F>(f)(std::forward<Args>(args)...);
56 }
57 };
58 template<bool>
60
61 template<>
62 struct InvokerHelper<false>
63 {
64 template<class T1>
65 inline static auto get (T1&& t1) -> decltype(*std::forward<T1>(t1))
66 {
67 return *std::forward<T1>(t1);
68 }
69
70 template<class T1>
71 inline static auto get (const std::reference_wrapper<T1>& t1) -> decltype(t1.get())
72 {
73 return t1.get();
74 }
75 };
76
77 template<>
78 struct InvokerHelper<true>
79 {
80 template<class T1>
81 inline static auto get (T1&& t1) -> decltype(std::forward<T1>(t1))
82 {
83 return std::forward<T1>(t1);
84 }
85 };
86
87 template<>
88 struct Invoker<true, false>
89 {
90 template<class T, class F, class T1, class... Args>
91 inline static auto invoke (F T::* f, T1&& t1, Args&&... args) ->\
92 decltype((InvokerHelper<std::is_base_of<T,typename std::decay<T1>::type>::value>::get(std::forward<T1>(t1)).*f)(std::forward<Args>(args)...))
93 {
94 return (InvokerHelper<std::is_base_of<T,typename std::decay<T1>::type>::value>::get(std::forward<T1>(t1)).*f)(std::forward<Args>(args)...);
95 }
96 };
97
98 template<>
99 struct Invoker<false, true>
100 {
101 template<class T, class F, class T1, class... Args>
102 inline static auto invoke (F T::* f, T1&& t1, Args&&... args) ->\
103 decltype(InvokerHelper<std::is_base_of<T,typename std::decay<T1>::type>::value>::get(t1).*f)
104 {
106 }
107 };
108
109 template<class F, class... Args>
111 {
113 std::is_member_object_pointer<typename std::remove_reference<F>::type>::value &&
114 (sizeof...(Args) == 1)> invoker;
115 inline static auto invoke (F&& f, Args&&... args) -> decltype(invoker::invoke(std::forward<F>(f), std::forward<Args>(args)...))
116 {
117 return invoker::invoke(std::forward<F>(f), std::forward<Args>(args)...);
118 };
119 };
120
121 template<class F, class...Args>
122 auto invoke (F&& f, Args&&... args) -> decltype(InvokeResult<F, Args...>::invoke(std::forward<F>(f), std::forward<Args>(args)...))
123 {
124 return InvokeResult<F, Args...>::invoke(std::forward<F>(f), std::forward<Args>(args)...);
125 }
126#else
127 using std::invoke;
128#endif
129
130 template<int...>
131 struct IntSeq {};
132
133 template<int N, int... S>
134 struct GenIntSeq : GenIntSeq<N-1, N-1, S...> { };
135
136 template<int... S>
137 struct GenIntSeq<0, S...> { typedef IntSeq<S...> type; };
138
139 // We can't define the Call struct in the function - the standard forbids template methods in that case
140 template<class Func, typename... Args>
142 {
143 typedef std::tuple<Args...> Tuple;
144 Func mFunc;
146 ThreadFuncCall(Func&& aFunc, Args&&... aArgs)
147 :mFunc(std::forward<Func>(aFunc)), mArgs(std::forward<Args>(aArgs)...){}
148 template <int... S>
150 {
151 detail::invoke(std::forward<Func>(mFunc), std::get<S>(std::forward<Tuple>(mArgs)) ...);
152 }
153 };
154
155}
156
158{
159public:
160 class id
161 {
162 DWORD mId;
163 void clear() {mId = 0;}
164 friend class thread;
165 friend class std::hash<id>;
166 public:
167 explicit id(DWORD aId=0) noexcept : mId(aId){}
168 friend bool operator==(id x, id y) noexcept {return x.mId == y.mId; }
169 friend bool operator!=(id x, id y) noexcept {return x.mId != y.mId; }
170 friend bool operator< (id x, id y) noexcept {return x.mId < y.mId; }
171 friend bool operator<=(id x, id y) noexcept {return x.mId <= y.mId; }
172 friend bool operator> (id x, id y) noexcept {return x.mId > y.mId; }
173 friend bool operator>=(id x, id y) noexcept {return x.mId >= y.mId; }
174
175 template<class _CharT, class _Traits>
176 friend std::basic_ostream<_CharT, _Traits>&
177 operator<<(std::basic_ostream<_CharT, _Traits>& __out, id __id)
178 {
179 if (__id.mId == 0)
180 {
181 return __out << "(invalid std::thread::id)";
182 }
183 else
184 {
185 return __out << __id.mId;
186 }
187 }
188 };
189protected:
190 HANDLE mHandle;
192public:
193 typedef HANDLE native_handle_type;
194 id get_id() const noexcept {return mThreadId;}
197
198 thread(thread&& other)
199 :mHandle(other.mHandle), mThreadId(other.mThreadId)
200 {
201 other.mHandle = _STD_THREAD_INVALID_HANDLE;
202 other.mThreadId.clear();
203 }
204
205 thread(const thread &other)=delete;
206
207 template<class Func, typename... Args>
208 explicit thread(Func&& func, Args&&... args) : mHandle(), mThreadId()
209 {
210 typedef detail::ThreadFuncCall<Func, Args...> Call;
211 auto call = new Call(
212 std::forward<Func>(func), std::forward<Args>(args)...);
213 mHandle = (HANDLE)_beginthreadex(NULL, 0, threadfunc<Call, Args...>,
214 (LPVOID)call, 0, (unsigned*)&(mThreadId.mId));
216 {
217 int errnum = errno;
218 delete call;
219 throw std::system_error(errnum, std::generic_category());
220 }
221 }
222 template <class Call, typename... Args>
223 static unsigned __stdcall threadfunc(void* arg)
224 {
225 std::unique_ptr<Call> call(static_cast<Call*>(arg));
226 call->callFunc(typename detail::GenIntSeq<sizeof...(Args)>::type());
227 return 0;
228 }
230 void join()
231 {
232 if (get_id() == id(GetCurrentThreadId()))
233 throw std::system_error(EDEADLK, std::generic_category());
235 throw std::system_error(ESRCH, std::generic_category());
236 if (!joinable())
237 throw std::system_error(EINVAL, std::generic_category());
238 WaitForSingleObject(mHandle, INFINITE);
239 CloseHandle(mHandle);
242 }
243
245 {
246 if (joinable())
247 std::terminate();
248 }
249 thread& operator=(const thread&) = delete;
250 thread& operator=(thread&& other) noexcept
251 {
252 if (joinable())
253 std::terminate();
254 swap(std::forward<thread>(other));
255 return *this;
256 }
257 void swap(thread&& other) noexcept
258 {
259 std::swap(mHandle, other.mHandle);
260 std::swap(mThreadId.mId, other.mThreadId.mId);
261 }
262
263 static unsigned int _hardware_concurrency_helper() noexcept
264 {
265 SYSTEM_INFO sysinfo;
266 ::GetSystemInfo(&sysinfo);
267 return sysinfo.dwNumberOfProcessors;
268 }
269
270 static unsigned int hardware_concurrency() noexcept
271 {
272 static unsigned int cached = _hardware_concurrency_helper();
273 return cached;
274 }
275
276 void detach()
277 {
278 if (!joinable())
279 throw std::system_error(EINVAL, std::generic_category());
281 {
282 CloseHandle(mHandle);
284 }
286 }
287};
288
289namespace this_thread
290{
291 inline thread::id get_id() noexcept {return thread::id(GetCurrentThreadId());}
292 inline void yield() noexcept {Sleep(0);}
293 template< class Rep, class Period >
294 void sleep_for( const std::chrono::duration<Rep,Period>& sleep_duration)
295 {
296 Sleep(std::chrono::duration_cast<std::chrono::milliseconds>(sleep_duration).count());
297 }
298 template <class Clock, class Duration>
299 void sleep_until(const std::chrono::time_point<Clock,Duration>& sleep_time)
300 {
301 sleep_for(sleep_time-Clock::now());
302 }
303}
304} // Namespace mingw_stdthread
305
306namespace std
307{
308// Because of quirks of the compiler, the common "using namespace std;"
309// directive would flatten the namespaces and introduce ambiguity where there
310// was none. Direct specification (std::), however, would be unaffected.
311// Take the safe option, and include only in the presence of MinGW's win32
312// implementation.
313#if defined(__MINGW32__ ) && !defined(_GLIBCXX_HAS_GTHREADS)
315// Remove ambiguity immediately, to avoid problems arising from the above.
316//using std::thread;
317namespace this_thread
318{
319using namespace mingw_stdthread::this_thread;
320}
321#elif !defined(MINGW_STDTHREAD_REDUNDANCY_WARNING) // Skip repetition
322#define MINGW_STDTHREAD_REDUNDANCY_WARNING
323#pragma message "This version of MinGW seems to include a win32 port of\
324 pthreads, and probably already has C++11 std threading classes implemented,\
325 based on pthreads. These classes, found in namespace std, are not overridden\
326 by the mingw-std-thread library. If you would still like to use this\
327 implementation (as it is more lightweight), use the classes provided in\
328 namespace mingw_stdthread."
329#endif
330
331// Specialize hash for this implementation's thread::id, even if the
332// std::thread::id already has a hash.
333template<>
335{
337 typedef size_t result_type;
338 size_t operator() (const argument_type & i) const noexcept
339 {
340 return i.mId;
341 }
342};
343}
344#endif // WIN32STDTHREAD_H
friend bool operator==(id x, id y) noexcept
Definition: mingw.thread.h:168
friend bool operator<(id x, id y) noexcept
Definition: mingw.thread.h:170
friend bool operator>=(id x, id y) noexcept
Definition: mingw.thread.h:173
friend bool operator<=(id x, id y) noexcept
Definition: mingw.thread.h:171
id(DWORD aId=0) noexcept
Definition: mingw.thread.h:167
friend std::basic_ostream< _CharT, _Traits > & operator<<(std::basic_ostream< _CharT, _Traits > &__out, id __id)
Definition: mingw.thread.h:177
friend bool operator>(id x, id y) noexcept
Definition: mingw.thread.h:172
friend bool operator!=(id x, id y) noexcept
Definition: mingw.thread.h:169
static unsigned int _hardware_concurrency_helper() noexcept
Definition: mingw.thread.h:263
thread(Func &&func, Args &&... args)
Definition: mingw.thread.h:208
static unsigned int hardware_concurrency() noexcept
Definition: mingw.thread.h:270
id get_id() const noexcept
Definition: mingw.thread.h:194
thread(thread &&other)
Definition: mingw.thread.h:198
void swap(thread &&other) noexcept
Definition: mingw.thread.h:257
thread & operator=(thread &&other) noexcept
Definition: mingw.thread.h:250
static unsigned __stdcall threadfunc(void *arg)
Definition: mingw.thread.h:223
native_handle_type native_handle() const
Definition: mingw.thread.h:195
thread(const thread &other)=delete
thread & operator=(const thread &)=delete
#define _STD_THREAD_INVALID_HANDLE
Definition: mingw.thread.h:42
auto invoke(F &&f, Args &&... args) -> decltype(InvokeResult< F, Args... >::invoke(std::forward< F >(f), std::forward< Args >(args)...))
Definition: mingw.thread.h:122
thread::id get_id() noexcept
Definition: mingw.thread.h:291
void sleep_for(const std::chrono::duration< Rep, Period > &sleep_duration)
Definition: mingw.thread.h:294
void sleep_until(const std::chrono::time_point< Clock, Duration > &sleep_time)
Definition: mingw.thread.h:299
void swap(shared_lock< Mutex > &lhs, shared_lock< Mutex > &rhs) noexcept
auto get(const nlohmann::detail::iteration_proxy_value< IteratorType > &i) -> decltype(i.key())
Definition: json.hpp:1787
Provides common mathematical functions and vector operations.
Definition: std.hpp:4
static auto invoke(F &&f, Args &&... args) -> decltype(invoker::invoke(std::forward< F >(f), std::forward< Args >(args)...))
Definition: mingw.thread.h:115
Invoker< std::is_member_function_pointer< typename std::remove_reference< F >::type >::value, std::is_member_object_pointer< typename std::remove_reference< F >::type >::value &&(sizeof...(Args)==1)> invoker
Definition: mingw.thread.h:114
static auto invoke(F T::*f, T1 &&t1, Args &&... args) -> decltype(InvokerHelper< std::is_base_of< T, typename std::decay< T1 >::type >::value >::get(t1).*f)
Definition: mingw.thread.h:102
static auto invoke(F T::*f, T1 &&t1, Args &&... args) -> decltype((InvokerHelper< std::is_base_of< T, typename std::decay< T1 >::type >::value >::get(std::forward< T1 >(t1)).*f)(std::forward< Args >(args)...))
Definition: mingw.thread.h:91
static auto get(const std::reference_wrapper< T1 > &t1) -> decltype(t1.get())
Definition: mingw.thread.h:71
static auto get(T1 &&t1) -> decltype(*std::forward< T1 >(t1))
Definition: mingw.thread.h:65
static auto get(T1 &&t1) -> decltype(std::forward< T1 >(t1))
Definition: mingw.thread.h:81
static std::result_of< F(Args...)>::type invoke(F &&f, Args &&... args)
Definition: mingw.thread.h:53
void callFunc(detail::IntSeq< S... >)
Definition: mingw.thread.h:149
ThreadFuncCall(Func &&aFunc, Args &&... aArgs)
Definition: mingw.thread.h:146
mingw_stdthread::thread::id argument_type
Definition: mingw.thread.h:336