@@ -26,48 +26,48 @@ DEALINGS IN THE SOFTWARE.
26
26
#include " threading/thread.h"
27
27
#include " threading/mutex_auto_lock.h"
28
28
#include " log.h"
29
+ #include " porting.h"
29
30
30
- #if __cplusplus >= 201103L
31
+ #define UNUSED (expr ) do { (void )(expr); } while (0 )
32
+
33
+ #if USE_CPP11_THREADS
31
34
#include < chrono>
32
- # else
33
- # define UNUSED ( expr ) do { ( void )(expr); } while ( 0 )
34
- # ifdef _WIN32
35
- # ifndef _WIN32_WCE
36
- #include < process.h >
37
- # endif
38
- # else
39
- #include < ctime >
40
- #include < cassert >
41
- #include < cstdlib >
35
+ # include < system_error >
36
+ # elif USE_WIN_THREADS
37
+ # ifndef _WIN32_WCE
38
+ # include < process.h >
39
+ #endif
40
+ #elif USE_POSIX_THREADS
41
+ # include < time.h >
42
+ #include < assert.h >
43
+ #include < stdlib.h >
44
+ #include < unistd.h >
42
45
#include < sys/time.h>
43
46
44
- // For getNumberOfProcessors
45
- #include < unistd.h>
46
- # if defined(__FreeBSD__) || defined(__APPLE__)
47
- #include < sys/types.h>
48
- #include < sys/sysctl.h>
49
- # elif defined(_GNU_SOURCE)
50
- #include < sys/sysinfo.h>
51
- # endif
52
- # endif
47
+ #if defined(__FreeBSD__) || defined(__APPLE__)
48
+ #include < sys/types.h>
49
+ #include < sys/sysctl.h>
50
+ #elif defined(_GNU_SOURCE)
51
+ #include < sys/sysinfo.h>
52
+ #endif
53
53
#endif
54
54
55
55
56
- // For setName
56
+ // for setName
57
57
#if defined(linux) || defined(__linux)
58
58
#include < sys/prctl.h>
59
59
#elif defined(__FreeBSD__) || defined(__OpenBSD__)
60
60
#include < pthread_np.h>
61
61
#elif defined(_MSC_VER)
62
62
struct THREADNAME_INFO {
63
- DWORD dwType; // Must be 0x1000
64
- LPCSTR szName; // Pointer to name (in user addr space)
63
+ DWORD dwType; // Must be 0x1000
64
+ LPCSTR szName; // Pointer to name (in user addr space)
65
65
DWORD dwThreadID; // Thread ID (-1=caller thread)
66
- DWORD dwFlags; // Reserved for future use, must be zero
66
+ DWORD dwFlags; // Reserved for future use, must be zero
67
67
};
68
68
#endif
69
69
70
- // For bindToProcessor
70
+ // for bindToProcessor
71
71
#if __FreeBSD_version >= 702106
72
72
typedef cpuset_t cpu_set_t ;
73
73
#elif defined(__linux) || defined(linux)
@@ -78,195 +78,254 @@ DEALINGS IN THE SOFTWARE.
78
78
#include < sys/procset.h>
79
79
#elif defined(_AIX)
80
80
#include < sys/processor.h>
81
+ #include < sys/thread.h>
81
82
#elif defined(__APPLE__)
82
83
#include < mach/mach_init.h>
83
84
#include < mach/thread_act.h>
84
85
#endif
85
86
86
87
87
88
Thread::Thread (const std::string &name) :
88
- name(name),
89
- retval(NULL ),
90
- request_stop(false ),
91
- running(false )
92
- #if __cplusplus >= 201103L
93
- , thread(NULL )
94
- #elif !defined(_WIN32)
95
- , started(false )
89
+ m_name(name),
90
+ m_retval(NULL ),
91
+ m_request_stop(false ),
92
+ m_running(false )
93
+ {
94
+ #ifdef _AIX
95
+ m_kernel_thread_id = -1 ;
96
96
#endif
97
- {}
98
97
98
+ #if USE_CPP11_THREADS
99
+ m_thread_obj = NULL ;
100
+ #endif
101
+ }
99
102
100
- void Thread::wait ()
103
+
104
+ Thread::~Thread ()
101
105
{
102
- #if __cplusplus >= 201103L
103
- if (!thread || !thread->joinable ())
104
- return ;
105
- thread->join ();
106
- #elif defined(_WIN32)
107
- if (!running)
108
- return ;
109
- WaitForSingleObject (thread, INFINITE);
110
- #else // pthread
111
- void *status;
112
- if (!started)
113
- return ;
114
- int ret = pthread_join (thread, &status);
115
- assert (!ret);
116
- UNUSED (ret);
117
- started = false ;
118
- #endif
106
+ kill ();
119
107
}
120
108
121
109
122
110
bool Thread::start ()
123
111
{
124
- if (running)
112
+ MutexAutoLock lock (m_continue_mutex);
113
+
114
+ if (m_running)
125
115
return false ;
126
- request_stop = false ;
127
116
128
- #if __cplusplus >= 201103L
129
- MutexAutoLock l (continue_mutex);
130
- thread = new std::thread (theThread, this );
131
- #elif defined(_WIN32)
132
- MutexAutoLock l (continue_mutex);
133
- # ifdef _WIN32_WCE
134
- thread = CreateThread (NULL , 0 , theThread, this , 0 , &thread_id);
135
- # else
136
- thread = (HANDLE)_beginthreadex (NULL , 0 , theThread, this , 0 , &thread_id);
137
- # endif
138
- if (!thread)
117
+ cleanup ();
118
+
119
+ #if USE_CPP11_THREADS
120
+
121
+ try {
122
+ m_thread_obj = new std::thread (threadProc, this );
123
+ m_thread_id = m_thread->get_id ();
124
+ m_thread_handle = m_thread->native_handle ();
125
+ } except (const std::system_error &e) {
139
126
return false ;
140
- #else
141
- int status;
127
+ }
142
128
143
- MutexAutoLock l (continue_mutex);
129
+ # elif USE_WIN_THREADS
144
130
145
- status = pthread_create (&thread, NULL , theThread, this );
131
+ m_thread_handle = CreateThread (NULL , 0 , threadProc, this , 0 , &m_thread_id);
132
+ if (!m_thread_handle)
133
+ return false ;
134
+
135
+ #elif USE_POSIX_THREADS
146
136
137
+ int status = pthread_create (&m_thread_handle, NULL , threadProc, this );
147
138
if (status)
148
139
return false ;
149
- #endif
150
140
151
- #if __cplusplus < 201103L
152
- // Wait until running
153
- while (!running) {
154
- # ifdef _WIN32
155
- Sleep (1 );
156
- }
157
- # else
158
- struct timespec req, rem;
159
- req.tv_sec = 0 ;
160
- req.tv_nsec = 1000000 ;
161
- nanosleep (&req, &rem);
162
- }
163
- started = true ;
164
- # endif
141
+ m_thread_id = m_thread_handle;
142
+
165
143
#endif
144
+
145
+ while (!m_running)
146
+ sleep_ms (1 );
147
+
148
+ return true ;
149
+ }
150
+
151
+
152
+ bool Thread::stop ()
153
+ {
154
+ m_request_stop = true ;
166
155
return true ;
167
156
}
168
157
169
158
159
+ void Thread::wait ()
160
+ {
161
+ if (!m_running)
162
+ return ;
163
+
164
+ #if USE_CPP11_THREADS
165
+
166
+ m_thread_obj->join ();
167
+
168
+ #elif USE_WIN_THREADS
169
+
170
+ int ret == WaitForSingleObject (m_thread_handle, INFINITE);
171
+ assert (ret == WAIT_OBJECT_0);
172
+ UNUSED (ret);
173
+
174
+ #elif USE_POSIX_THREADS
175
+
176
+ int ret = pthread_join (m_thread_handle, NULL );
177
+ assert (ret == 0 );
178
+ UNUSED (ret);
179
+
180
+ #endif
181
+
182
+ assert (m_running == false );
183
+
184
+ return ;
185
+ }
186
+
187
+
170
188
bool Thread::kill ()
171
189
{
172
- #ifdef _WIN32
173
- if (!running)
174
- return false ;
175
- TerminateThread (getThreadHandle (), 0 );
176
- CloseHandle (getThreadHandle ());
177
- #else
178
- if (!running) {
190
+ if (!m_running) {
179
191
wait ();
180
192
return false ;
181
193
}
194
+
195
+ #ifdef _WIN32
196
+ TerminateThread (m_thread_handle, 0 );
197
+ #else
198
+
199
+ // We need to pthread_kill instead on Android since NDKv5's pthread
200
+ // implementation is incomplete.
182
201
# ifdef __ANDROID__
183
- pthread_kill (getThreadHandle () , SIGKILL);
202
+ pthread_kill (m_thread_handle , SIGKILL);
184
203
# else
185
- pthread_cancel (getThreadHandle () );
204
+ pthread_cancel (m_thread_handle );
186
205
# endif
206
+
187
207
wait ();
188
208
#endif
189
- #if __cplusplus >= 201103L
190
- delete thread;
191
- #endif
192
- running = false ;
209
+
210
+ cleanup ();
211
+
193
212
return true ;
194
213
}
195
214
196
215
197
- bool Thread::isSameThread ()
216
+ void Thread::cleanup ()
198
217
{
199
- #if __cplusplus >= 201103L
200
- return thread->get_id () == std::this_thread::get_id ();
201
- #elif defined(_WIN32)
202
- return GetCurrentThreadId () == thread_id;
203
- #else
204
- return pthread_equal (pthread_self (), thread);
218
+ #if USE_CPP11_THREADS
219
+
220
+ delete m_thread_obj;
221
+ m_thread_obj = NULL ;
222
+
223
+ #elif USE_WIN_THREADS
224
+
225
+ CloseHandle (m_thread_handle);
226
+ m_thread_handle = NULL ;
227
+ m_thread_id = -1 ;
228
+
229
+ #elif USE_POSIX_THREADS
230
+
231
+ // Can't do any cleanup for pthreads
232
+
205
233
#endif
234
+
235
+ m_name = " " ;
236
+ m_retval = NULL ;
237
+ m_running = false ;
238
+ m_request_stop = false ;
206
239
}
207
240
208
241
209
- #if __cplusplus >= 201103L
210
- void Thread::theThread (Thread *th)
242
+ bool Thread::getReturnValue (void **ret)
243
+ {
244
+ if (m_running)
245
+ return false ;
246
+
247
+ *ret = m_retval;
248
+ return true ;
249
+ }
250
+
251
+
252
+ bool Thread::isCurrentThread ()
253
+ {
254
+ return thr_is_current_thread (m_thread_id);
255
+ }
256
+
257
+
258
+ #if USE_CPP11_THREADS || USE_POSIX_THREADS
259
+ void *(Thread::threadProc)(void *param)
211
260
#elif defined(_WIN32_WCE)
212
- DWORD WINAPI Thread::theThread ( void * param)
261
+ DWORD ( Thread::threadProc)(LPVOID param)
213
262
#elif defined(_WIN32)
214
- UINT __stdcall Thread::theThread (void *param)
215
- #else
216
- void *Thread::theThread (void *param)
263
+ DWORD WINAPI (Thread::threadProc)(LPVOID param)
217
264
#endif
218
265
{
219
- #if __cplusplus < 201103L
220
- Thread *th = static_cast <Thread *>(param);
266
+ Thread *thr = (Thread *)param;
267
+
268
+ #ifdef _AIX
269
+ m_kernel_thread_id = thread_self ();
221
270
#endif
222
- th->running = true ;
223
271
224
- th->setName ();
225
- g_logger.registerThread (th->name );
272
+ thr->setName (thr->m_name );
273
+
274
+ g_logger.registerThread (thr->m_name );
275
+ thr->m_running = true ;
226
276
227
- th-> retval = th ->run ();
277
+ thr-> m_retval = thr ->run ();
228
278
279
+ thr->m_running = false ;
229
280
g_logger.deregisterThread ();
230
281
231
- th->running = false ;
232
- #if __cplusplus < 201103L
233
- # ifdef _WIN32
234
- CloseHandle (th->thread );
235
- # endif
236
282
return NULL ;
237
- #endif
238
283
}
239
284
240
285
241
286
void Thread::setName (const std::string &name)
242
287
{
243
288
#if defined(linux) || defined(__linux)
244
- /* It would be cleaner to do this with pthread_setname_np,
245
- * which was added to glibc in version 2.12, but some major
246
- * distributions are still runing 2.11 and previous versions.
247
- */
289
+
290
+ // It would be cleaner to do this with pthread_setname_np,
291
+ // which was added to glibc in version 2.12, but some major
292
+ // distributions are still runing 2.11 and previous versions.
248
293
prctl (PR_SET_NAME, name.c_str ());
294
+
249
295
#elif defined(__FreeBSD__) || defined(__OpenBSD__)
296
+
250
297
pthread_set_name_np (pthread_self (), name.c_str ());
298
+
251
299
#elif defined(__NetBSD__)
300
+
252
301
pthread_setname_np (pthread_self (), name.c_str ());
302
+
253
303
#elif defined(__APPLE__)
304
+
254
305
pthread_setname_np (name.c_str ());
306
+
255
307
#elif defined(_MSC_VER)
308
+
256
309
// Windows itself doesn't support thread names,
257
310
// but the MSVC debugger does...
258
311
THREADNAME_INFO info;
312
+
259
313
info.dwType = 0x1000 ;
260
314
info.szName = name.c_str ();
261
315
info.dwThreadID = -1 ;
262
316
info.dwFlags = 0 ;
317
+
263
318
__try {
264
- RaiseException (0x406D1388 , 0 , sizeof (info) / sizeof (DWORD), (ULONG_PTR *)&info);
319
+ RaiseException (0x406D1388 , 0 ,
320
+ sizeof (info) / sizeof (DWORD), (ULONG_PTR *)&info);
265
321
} __except (EXCEPTION_CONTINUE_EXECUTION) {
266
322
}
323
+
267
324
#elif defined(_WIN32) || defined(__GNU__)
325
+
268
326
// These platforms are known to not support thread names.
269
327
// Silently ignore the request.
328
+
270
329
#else
271
330
#warning "Unrecognized platform, thread names will not be available."
272
331
#endif
@@ -276,79 +335,120 @@ void Thread::setName(const std::string &name)
276
335
unsigned int Thread::getNumberOfProcessors ()
277
336
{
278
337
#if __cplusplus >= 201103L
338
+
279
339
return std::thread::hardware_concurrency ();
340
+
280
341
#elif defined(_SC_NPROCESSORS_ONLN)
342
+
281
343
return sysconf (_SC_NPROCESSORS_ONLN);
282
- #elif defined(__FreeBSD__) || defined(__APPLE__)
283
- unsigned int len, count;
284
- len = sizeof (count);
285
- return sysctlbyname (" hw.ncpu" , &count, &len, NULL , 0 );
344
+
345
+ #elif defined(__FreeBSD__) || defined(__NetBSD__) || \
346
+ defined (__DragonFly__) || defined (__APPLE__)
347
+
348
+ unsigned int num_cpus = 1 ;
349
+ size_t len = sizeof (num_cpus);
350
+
351
+ int mib[2 ];
352
+ mib[0 ] = CTL_HW;
353
+ mib[1 ] = HW_NCPU;
354
+
355
+ sysctl (mib, 2 , &num_cpus, &len, NULL , 0 );
356
+ return num_cpus;
357
+
286
358
#elif defined(_GNU_SOURCE)
359
+
287
360
return get_nprocs ();
361
+
288
362
#elif defined(_WIN32)
363
+
289
364
SYSTEM_INFO sysinfo;
290
365
GetSystemInfo (&sysinfo);
291
366
return sysinfo.dwNumberOfProcessors ;
367
+
292
368
#elif defined(PTW32_VERSION) || defined(__hpux)
369
+
293
370
return pthread_num_processors_np ();
371
+
294
372
#else
373
+
295
374
return 1 ;
375
+
296
376
#endif
297
377
}
298
378
299
379
300
- bool Thread::bindToProcessor (unsigned int num )
380
+ bool Thread::bindToProcessor (unsigned int proc_number )
301
381
{
302
382
#if defined(__ANDROID__)
383
+
303
384
return false ;
385
+
304
386
#elif defined(_WIN32)
305
- return SetThreadAffinityMask (getThreadHandle (), 1 << num);
387
+
388
+ return SetThreadAffinityMask (m_thread_handle, 1 << proc_number);
389
+
306
390
#elif __FreeBSD_version >= 702106 || defined(__linux) || defined(linux)
391
+
307
392
cpu_set_t cpuset;
393
+
308
394
CPU_ZERO (&cpuset);
309
- CPU_SET (num, &cpuset);
310
- return pthread_setaffinity_np (getThreadHandle (), sizeof (cpuset),
311
- &cpuset) == 0 ;
395
+ CPU_SET (proc_number, &cpuset);
396
+
397
+ return pthread_setaffinity_np (m_thread_handle, sizeof (cpuset), &cpuset) == 0 ;
398
+
312
399
#elif defined(__sun) || defined(sun)
313
- return processor_bind (P_LWPID, MAKE_LWPID_PTHREAD (getThreadHandle ()),
314
- num, NULL ) == 0
400
+
401
+ return processor_bind (P_LWPID, P_MYID, proc_number, NULL ) == 0
402
+
315
403
#elif defined(_AIX)
316
- return bindprocessor (BINDTHREAD, (tid_t ) getThreadHandle (), pnumber) == 0 ;
404
+
405
+ return bindprocessor (BINDTHREAD, m_kernel_thread_id, proc_number) == 0 ;
406
+
317
407
#elif defined(__hpux) || defined(hpux)
408
+
318
409
pthread_spu_t answer;
319
410
320
411
return pthread_processor_bind_np (PTHREAD_BIND_ADVISORY_NP,
321
- &answer, num, getThreadHandle ()) == 0 ;
412
+ &answer, proc_number, m_thread_handle) == 0 ;
413
+
322
414
#elif defined(__APPLE__)
415
+
323
416
struct thread_affinity_policy tapol;
324
417
325
- thread_port_t threadport = pthread_mach_thread_np (getThreadHandle () );
326
- tapol.affinity_tag = num + 1 ;
418
+ thread_port_t threadport = pthread_mach_thread_np (m_thread_handle );
419
+ tapol.affinity_tag = proc_number + 1 ;
327
420
return thread_policy_set (threadport, THREAD_AFFINITY_POLICY,
328
421
(thread_policy_t )&tapol,
329
422
THREAD_AFFINITY_POLICY_COUNT) == KERN_SUCCESS;
423
+
330
424
#else
425
+
331
426
return false ;
427
+
332
428
#endif
333
429
}
334
430
335
431
336
432
bool Thread::setPriority (int prio)
337
433
{
338
434
#if defined(_WIN32)
339
- return SetThreadPriority (getThreadHandle (), prio);
435
+
436
+ return SetThreadPriority (m_thread_handle, prio);
437
+
340
438
#else
439
+
341
440
struct sched_param sparam;
342
441
int policy;
343
442
344
- if (pthread_getschedparam (getThreadHandle () , &policy, &sparam) != 0 )
443
+ if (pthread_getschedparam (m_thread_handle , &policy, &sparam) != 0 )
345
444
return false ;
346
445
347
446
int min = sched_get_priority_min (policy);
348
447
int max = sched_get_priority_max (policy);
349
448
350
449
sparam.sched_priority = min + prio * (max - min) / THREAD_PRIORITY_HIGHEST;
351
- return pthread_setschedparam (getThreadHandle (), policy, &sparam) == 0 ;
450
+ return pthread_setschedparam (m_thread_handle, policy, &sparam) == 0 ;
451
+
352
452
#endif
353
453
}
354
454
0 commit comments