summaryrefslogtreecommitdiff
path: root/src/common/std_thread.h
diff options
context:
space:
mode:
authorGravatar bunnei2014-04-08 19:25:03 -0400
committerGravatar bunnei2014-04-08 19:25:03 -0400
commit63e46abdb8764bc97e91bae862c8d461e61b1965 (patch)
treee73f4aa25d7b4015a265e7bbfb6004dab7561027 /src/common/std_thread.h
parentfixed some license headers that I missed (diff)
downloadyuzu-63e46abdb8764bc97e91bae862c8d461e61b1965.tar.gz
yuzu-63e46abdb8764bc97e91bae862c8d461e61b1965.tar.xz
yuzu-63e46abdb8764bc97e91bae862c8d461e61b1965.zip
got rid of 'src' folders in each sub-project
Diffstat (limited to 'src/common/std_thread.h')
-rw-r--r--src/common/std_thread.h317
1 files changed, 317 insertions, 0 deletions
diff --git a/src/common/std_thread.h b/src/common/std_thread.h
new file mode 100644
index 000000000..9ed0072c3
--- /dev/null
+++ b/src/common/std_thread.h
@@ -0,0 +1,317 @@
1
2#ifndef STD_THREAD_H_
3#define STD_THREAD_H_
4
5#define GCC_VER(x,y,z) ((x) * 10000 + (y) * 100 + (z))
6#define GCC_VERSION GCC_VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
7
8#ifndef __has_include
9#define __has_include(s) 0
10#endif
11
12#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__
13// GCC 4.4 provides <thread>
14#ifndef _GLIBCXX_USE_SCHED_YIELD
15#define _GLIBCXX_USE_SCHED_YIELD
16#endif
17#include <thread>
18#elif __has_include(<thread>) && !ANDROID
19// Clang + libc++
20#include <thread>
21#else
22
23// partial std::thread implementation for win32/pthread
24
25#include <algorithm>
26
27#if (_MSC_VER >= 1600) || (GCC_VERSION >= GCC_VER(4,3,0) && __GXX_EXPERIMENTAL_CXX0X__)
28#define USE_RVALUE_REFERENCES
29#endif
30
31#ifdef __APPLE__
32#import <Foundation/NSAutoreleasePool.h>
33#endif
34
35#if defined(_WIN32)
36// WIN32
37
38#define WIN32_LEAN_AND_MEAN
39#include <Windows.h>
40
41#if defined(_MSC_VER) && defined(_MT)
42// When linking with LIBCMT (the multithreaded C library), Microsoft recommends
43// using _beginthreadex instead of CreateThread.
44#define USE_BEGINTHREADEX
45#include <process.h>
46#endif
47
48#ifdef USE_BEGINTHREADEX
49#define THREAD_ID unsigned
50#define THREAD_RETURN unsigned __stdcall
51#else
52#define THREAD_ID DWORD
53#define THREAD_RETURN DWORD WINAPI
54#endif
55#define THREAD_HANDLE HANDLE
56
57#else
58// PTHREAD
59
60#include <unistd.h>
61
62#ifndef _POSIX_THREADS
63#error unsupported platform (no pthreads?)
64#endif
65
66#include <pthread.h>
67
68#define THREAD_ID pthread_t
69#define THREAD_HANDLE pthread_t
70#define THREAD_RETURN void*
71
72#endif
73
74namespace std
75{
76
77class thread
78{
79public:
80 typedef THREAD_HANDLE native_handle_type;
81
82 class id
83 {
84 friend class thread;
85 public:
86 id() : m_thread(0) {}
87 id(THREAD_ID _id) : m_thread(_id) {}
88
89 bool operator==(const id& rhs) const
90 {
91 return m_thread == rhs.m_thread;
92 }
93
94 bool operator!=(const id& rhs) const
95 {
96 return !(*this == rhs);
97 }
98
99 bool operator<(const id& rhs) const
100 {
101 return m_thread < rhs.m_thread;
102 }
103
104 private:
105 THREAD_ID m_thread;
106 };
107
108 // no variadic template support in msvc
109 //template <typename C, typename... A>
110 //thread(C&& func, A&&... args);
111
112 template <typename C>
113 thread(C func)
114 {
115 StartThread(new Func<C>(func));
116 }
117
118 template <typename C, typename A>
119 thread(C func, A arg)
120 {
121 StartThread(new FuncArg<C, A>(func, arg));
122 }
123
124 thread() /*= default;*/ {}
125
126#ifdef USE_RVALUE_REFERENCES
127 thread(const thread&) /*= delete*/;
128
129 thread(thread&& other)
130 {
131#else
132 thread(const thread& t)
133 {
134 // ugly const_cast to get around lack of rvalue references
135 thread& other = const_cast<thread&>(t);
136#endif
137 swap(other);
138 }
139
140#ifdef USE_RVALUE_REFERENCES
141 thread& operator=(const thread&) /*= delete*/;
142
143 thread& operator=(thread&& other)
144 {
145#else
146 thread& operator=(const thread& t)
147 {
148 // ugly const_cast to get around lack of rvalue references
149 thread& other = const_cast<thread&>(t);
150#endif
151 if (joinable())
152 detach();
153 swap(other);
154 return *this;
155 }
156
157 ~thread()
158 {
159 if (joinable())
160 detach();
161 }
162
163 bool joinable() const
164 {
165 return m_id != id();
166 }
167
168 id get_id() const
169 {
170 return m_id;
171 }
172
173 native_handle_type native_handle()
174 {
175#ifdef _WIN32
176 return m_handle;
177#else
178 return m_id.m_thread;
179#endif
180 }
181
182 void join()
183 {
184#ifdef _WIN32
185 WaitForSingleObject(m_handle, INFINITE);
186 detach();
187#else
188 pthread_join(m_id.m_thread, NULL);
189 m_id = id();
190#endif
191 }
192
193 void detach()
194 {
195#ifdef _WIN32
196 CloseHandle(m_handle);
197#else
198 pthread_detach(m_id.m_thread);
199#endif
200 m_id = id();
201 }
202
203 void swap(thread& other)
204 {
205 std::swap(m_id, other.m_id);
206#ifdef _WIN32
207 std::swap(m_handle, other.m_handle);
208#endif
209 }
210
211 static unsigned hardware_concurrency()
212 {
213#ifdef _WIN32
214 SYSTEM_INFO sysinfo;
215 GetSystemInfo(&sysinfo);
216 return static_cast<unsigned>(sysinfo.dwNumberOfProcessors);
217#else
218 return 0;
219#endif
220 }
221
222private:
223 id m_id;
224
225#ifdef _WIN32
226 native_handle_type m_handle;
227#endif
228
229 template <typename F>
230 void StartThread(F* param)
231 {
232#ifdef USE_BEGINTHREADEX
233 m_handle = (HANDLE)_beginthreadex(NULL, 0, &RunAndDelete<F>, param, 0, &m_id.m_thread);
234#elif defined(_WIN32)
235 m_handle = CreateThread(NULL, 0, &RunAndDelete<F>, param, 0, &m_id.m_thread);
236#else
237 pthread_attr_t attr;
238 pthread_attr_init(&attr);
239 pthread_attr_setstacksize(&attr, 1024 * 1024);
240 if (pthread_create(&m_id.m_thread, &attr, &RunAndDelete<F>, param))
241 m_id = id();
242#endif
243 }
244
245 template <typename C>
246 class Func
247 {
248 public:
249 Func(C _func) : func(_func) {}
250
251 void Run() { func(); }
252
253 private:
254 C const func;
255 };
256
257 template <typename C, typename A>
258 class FuncArg
259 {
260 public:
261 FuncArg(C _func, A _arg) : func(_func), arg(_arg) {}
262
263 void Run() { func(arg); }
264
265 private:
266 C const func;
267 A arg;
268 };
269
270 template <typename F>
271 static THREAD_RETURN RunAndDelete(void* param)
272 {
273#ifdef __APPLE__
274 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
275#endif
276 static_cast<F*>(param)->Run();
277 delete static_cast<F*>(param);
278#ifdef __APPLE__
279 [pool release];
280#endif
281 return 0;
282 }
283};
284
285namespace this_thread
286{
287
288inline void yield()
289{
290#ifdef _WIN32
291 SwitchToThread();
292#else
293 sleep(0);
294#endif
295}
296
297inline thread::id get_id()
298{
299#ifdef _WIN32
300 return GetCurrentThreadId();
301#else
302 return pthread_self();
303#endif
304}
305
306} // namespace this_thread
307
308} // namespace std
309
310#undef USE_RVALUE_REFERENCES
311#undef USE_BEGINTHREADEX
312#undef THREAD_ID
313#undef THREAD_RETURN
314#undef THREAD_HANDLE
315
316#endif
317#endif