Skip to content

Commit 765a834

Browse files
committedOct 17, 2015
Refactor Thread class to improve readability and portability
- Fix some incompatibilities with obscure platforms (AIX and WinCE) - Clean up Thread class interface - Add m_ prefix to private member variables - Simplify platform-dependent logic, reducing preprocessor conditional clauses and improving readibility - Add Thread class documentation
1 parent 6be74d1 commit 765a834

File tree

3 files changed

+350
-205
lines changed

3 files changed

+350
-205
lines changed
 

Diff for: ‎src/emerge.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ void EmergeManager::initMapgens()
219219
Mapgen *EmergeManager::getCurrentMapgen()
220220
{
221221
for (u32 i = 0; i != m_threads.size(); i++) {
222-
if (m_threads[i]->isSameThread())
222+
if (m_threads[i]->isCurrentThread())
223223
return m_threads[i]->m_mapgen;
224224
}
225225

@@ -476,7 +476,7 @@ EmergeThread::EmergeThread(Server *server, int ethreadid) :
476476
m_emerge(NULL),
477477
m_mapgen(NULL)
478478
{
479-
name = "Emerge-" + itos(ethreadid);
479+
m_name = "Emerge-" + itos(ethreadid);
480480
}
481481

482482

Diff for: ‎src/threading/thread.cpp

+245-145
Original file line numberDiff line numberDiff line change
@@ -26,48 +26,48 @@ DEALINGS IN THE SOFTWARE.
2626
#include "threading/thread.h"
2727
#include "threading/mutex_auto_lock.h"
2828
#include "log.h"
29+
#include "porting.h"
2930

30-
#if __cplusplus >= 201103L
31+
#define UNUSED(expr) do { (void)(expr); } while (0)
32+
33+
#if USE_CPP11_THREADS
3134
#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>
4245
#include <sys/time.h>
4346

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
5353
#endif
5454

5555

56-
// For setName
56+
// for setName
5757
#if defined(linux) || defined(__linux)
5858
#include <sys/prctl.h>
5959
#elif defined(__FreeBSD__) || defined(__OpenBSD__)
6060
#include <pthread_np.h>
6161
#elif defined(_MSC_VER)
6262
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)
6565
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
6767
};
6868
#endif
6969

70-
// For bindToProcessor
70+
// for bindToProcessor
7171
#if __FreeBSD_version >= 702106
7272
typedef cpuset_t cpu_set_t;
7373
#elif defined(__linux) || defined(linux)
@@ -78,195 +78,254 @@ DEALINGS IN THE SOFTWARE.
7878
#include <sys/procset.h>
7979
#elif defined(_AIX)
8080
#include <sys/processor.h>
81+
#include <sys/thread.h>
8182
#elif defined(__APPLE__)
8283
#include <mach/mach_init.h>
8384
#include <mach/thread_act.h>
8485
#endif
8586

8687

8788
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;
9696
#endif
97-
{}
9897

98+
#if USE_CPP11_THREADS
99+
m_thread_obj = NULL;
100+
#endif
101+
}
99102

100-
void Thread::wait()
103+
104+
Thread::~Thread()
101105
{
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();
119107
}
120108

121109

122110
bool Thread::start()
123111
{
124-
if (running)
112+
MutexAutoLock lock(m_continue_mutex);
113+
114+
if (m_running)
125115
return false;
126-
request_stop = false;
127116

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) {
139126
return false;
140-
#else
141-
int status;
127+
}
142128

143-
MutexAutoLock l(continue_mutex);
129+
#elif USE_WIN_THREADS
144130

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
146136

137+
int status = pthread_create(&m_thread_handle, NULL, threadProc, this);
147138
if (status)
148139
return false;
149-
#endif
150140

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+
165143
#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;
166155
return true;
167156
}
168157

169158

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+
170188
bool Thread::kill()
171189
{
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) {
179191
wait();
180192
return false;
181193
}
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.
182201
# ifdef __ANDROID__
183-
pthread_kill(getThreadHandle(), SIGKILL);
202+
pthread_kill(m_thread_handle, SIGKILL);
184203
# else
185-
pthread_cancel(getThreadHandle());
204+
pthread_cancel(m_thread_handle);
186205
# endif
206+
187207
wait();
188208
#endif
189-
#if __cplusplus >= 201103L
190-
delete thread;
191-
#endif
192-
running = false;
209+
210+
cleanup();
211+
193212
return true;
194213
}
195214

196215

197-
bool Thread::isSameThread()
216+
void Thread::cleanup()
198217
{
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+
205233
#endif
234+
235+
m_name = "";
236+
m_retval = NULL;
237+
m_running = false;
238+
m_request_stop = false;
206239
}
207240

208241

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)
211260
#elif defined(_WIN32_WCE)
212-
DWORD WINAPI Thread::theThread(void *param)
261+
DWORD (Thread::threadProc)(LPVOID param)
213262
#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)
217264
#endif
218265
{
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();
221270
#endif
222-
th->running = true;
223271

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;
226276

227-
th->retval = th->run();
277+
thr->m_retval = thr->run();
228278

279+
thr->m_running = false;
229280
g_logger.deregisterThread();
230281

231-
th->running = false;
232-
#if __cplusplus < 201103L
233-
# ifdef _WIN32
234-
CloseHandle(th->thread);
235-
# endif
236282
return NULL;
237-
#endif
238283
}
239284

240285

241286
void Thread::setName(const std::string &name)
242287
{
243288
#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.
248293
prctl(PR_SET_NAME, name.c_str());
294+
249295
#elif defined(__FreeBSD__) || defined(__OpenBSD__)
296+
250297
pthread_set_name_np(pthread_self(), name.c_str());
298+
251299
#elif defined(__NetBSD__)
300+
252301
pthread_setname_np(pthread_self(), name.c_str());
302+
253303
#elif defined(__APPLE__)
304+
254305
pthread_setname_np(name.c_str());
306+
255307
#elif defined(_MSC_VER)
308+
256309
// Windows itself doesn't support thread names,
257310
// but the MSVC debugger does...
258311
THREADNAME_INFO info;
312+
259313
info.dwType = 0x1000;
260314
info.szName = name.c_str();
261315
info.dwThreadID = -1;
262316
info.dwFlags = 0;
317+
263318
__try {
264-
RaiseException(0x406D1388, 0, sizeof(info) / sizeof(DWORD), (ULONG_PTR *)&info);
319+
RaiseException(0x406D1388, 0,
320+
sizeof(info) / sizeof(DWORD), (ULONG_PTR *)&info);
265321
} __except (EXCEPTION_CONTINUE_EXECUTION) {
266322
}
323+
267324
#elif defined(_WIN32) || defined(__GNU__)
325+
268326
// These platforms are known to not support thread names.
269327
// Silently ignore the request.
328+
270329
#else
271330
#warning "Unrecognized platform, thread names will not be available."
272331
#endif
@@ -276,79 +335,120 @@ void Thread::setName(const std::string &name)
276335
unsigned int Thread::getNumberOfProcessors()
277336
{
278337
#if __cplusplus >= 201103L
338+
279339
return std::thread::hardware_concurrency();
340+
280341
#elif defined(_SC_NPROCESSORS_ONLN)
342+
281343
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+
286358
#elif defined(_GNU_SOURCE)
359+
287360
return get_nprocs();
361+
288362
#elif defined(_WIN32)
363+
289364
SYSTEM_INFO sysinfo;
290365
GetSystemInfo(&sysinfo);
291366
return sysinfo.dwNumberOfProcessors;
367+
292368
#elif defined(PTW32_VERSION) || defined(__hpux)
369+
293370
return pthread_num_processors_np();
371+
294372
#else
373+
295374
return 1;
375+
296376
#endif
297377
}
298378

299379

300-
bool Thread::bindToProcessor(unsigned int num)
380+
bool Thread::bindToProcessor(unsigned int proc_number)
301381
{
302382
#if defined(__ANDROID__)
383+
303384
return false;
385+
304386
#elif defined(_WIN32)
305-
return SetThreadAffinityMask(getThreadHandle(), 1 << num);
387+
388+
return SetThreadAffinityMask(m_thread_handle, 1 << proc_number);
389+
306390
#elif __FreeBSD_version >= 702106 || defined(__linux) || defined(linux)
391+
307392
cpu_set_t cpuset;
393+
308394
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+
312399
#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+
315403
#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+
317407
#elif defined(__hpux) || defined(hpux)
408+
318409
pthread_spu_t answer;
319410

320411
return pthread_processor_bind_np(PTHREAD_BIND_ADVISORY_NP,
321-
&answer, num, getThreadHandle()) == 0;
412+
&answer, proc_number, m_thread_handle) == 0;
413+
322414
#elif defined(__APPLE__)
415+
323416
struct thread_affinity_policy tapol;
324417

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;
327420
return thread_policy_set(threadport, THREAD_AFFINITY_POLICY,
328421
(thread_policy_t)&tapol,
329422
THREAD_AFFINITY_POLICY_COUNT) == KERN_SUCCESS;
423+
330424
#else
425+
331426
return false;
427+
332428
#endif
333429
}
334430

335431

336432
bool Thread::setPriority(int prio)
337433
{
338434
#if defined(_WIN32)
339-
return SetThreadPriority(getThreadHandle(), prio);
435+
436+
return SetThreadPriority(m_thread_handle, prio);
437+
340438
#else
439+
341440
struct sched_param sparam;
342441
int policy;
343442

344-
if (pthread_getschedparam(getThreadHandle(), &policy, &sparam) != 0)
443+
if (pthread_getschedparam(m_thread_handle, &policy, &sparam) != 0)
345444
return false;
346445

347446
int min = sched_get_priority_min(policy);
348447
int max = sched_get_priority_max(policy);
349448

350449
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+
352452
#endif
353453
}
354454

Diff for: ‎src/threading/thread.h

+103-58
Original file line numberDiff line numberDiff line change
@@ -28,91 +28,136 @@ DEALINGS IN THE SOFTWARE.
2828

2929
#include "threading/atomic.h"
3030
#include "threading/mutex.h"
31+
#include "threads.h"
3132

3233
#include <string>
33-
#if __cplusplus >= 201103L
34+
#if USE_CPP11_THREADS
3435
#include <thread>
3536
#endif
3637

37-
#ifndef _WIN32
38-
enum {
39-
THREAD_PRIORITY_LOWEST,
40-
THREAD_PRIORITY_BELOW_NORMAL,
41-
THREAD_PRIORITY_NORMAL,
42-
THREAD_PRIORITY_ABOVE_NORMAL,
43-
THREAD_PRIORITY_HIGHEST,
44-
};
38+
/*
39+
* On platforms using pthreads, these five priority classes correlate to
40+
* even divisions between the minimum and maximum reported thread priority.
41+
*/
42+
#if !defined(_WIN32)
43+
#define THREAD_PRIORITY_LOWEST 0
44+
#define THREAD_PRIORITY_BELOW_NORMAL 1
45+
#define THREAD_PRIORITY_NORMAL 2
46+
#define THREAD_PRIORITY_ABOVE_NORMAL 3
47+
#define THREAD_PRIORITY_HIGHEST 4
4548
#endif
4649

4750

48-
class Thread
49-
{
51+
class Thread {
5052
public:
51-
Thread(const std::string &name="Unnamed");
52-
virtual ~Thread() { kill(); }
53+
Thread(const std::string &name="");
54+
virtual ~Thread();
5355

56+
/*
57+
* Begins execution of a new thread at the pure virtual method Thread::run().
58+
* Execution of the thread is guaranteed to have started after this function
59+
* returns.
60+
*/
5461
bool start();
55-
inline void stop() { request_stop = true; }
56-
bool kill();
5762

58-
inline bool isRunning() { return running; }
59-
inline bool stopRequested() { return request_stop; }
60-
void *getReturnValue() { return running ? NULL : retval; }
61-
bool isSameThread();
63+
/*
64+
* Requests that the thread exit gracefully.
65+
* Returns immediately; thread execution is guaranteed to be complete after
66+
* a subsequent call to Thread::wait.
67+
*/
68+
bool stop();
6269

63-
static unsigned int getNumberOfProcessors();
64-
bool bindToProcessor(unsigned int);
65-
bool setPriority(int);
70+
/*
71+
* Immediately terminates the thread.
72+
* This should be used with extreme caution, as the thread will not have
73+
* any opportunity to release resources it may be holding (such as memory
74+
* or locks).
75+
*/
76+
bool kill();
6677

6778
/*
68-
* Wait for thread to finish.
69-
* Note: this does not stop a thread, you have to do this on your own.
79+
* Waits for thread to finish.
80+
* Note: This does not stop a thread, you have to do this on your own.
7081
* Returns immediately if the thread is not started.
7182
*/
7283
void wait();
7384

85+
/*
86+
* Returns true if the calling thread is this Thread object.
87+
*/
88+
bool isCurrentThread();
89+
90+
inline bool isRunning() { return m_running; }
91+
inline bool stopRequested() { return m_request_stop; }
92+
inline threadid_t getThreadId() { return m_thread_id; }
93+
inline threadhandle_t getThreadHandle() { return m_thread_handle; }
94+
95+
/*
96+
* Gets the thread return value.
97+
* Returns true if the thread has exited and the return value was available,
98+
* or false if the thread has yet to finish.
99+
*/
100+
bool getReturnValue(void **ret);
101+
102+
/*
103+
* Binds (if possible, otherwise sets the affinity of) the thread to the
104+
* specific processor specified by proc_number.
105+
*/
106+
bool bindToProcessor(unsigned int proc_number);
107+
108+
/*
109+
* Sets the thread priority to the specified priority.
110+
*
111+
* prio can be one of: THREAD_PRIORITY_LOWEST, THREAD_PRIORITY_BELOW_NORMAL,
112+
* THREAD_PRIORITY_NORMAL, THREAD_PRIORITY_ABOVE_NORMAL, THREAD_PRIORITY_HIGHEST.
113+
* On Windows, any of the other priorites as defined by SetThreadPriority
114+
* are supported as well.
115+
*
116+
* Note that it may be necessary to first set the threading policy or
117+
* scheduling algorithm to one that supports thread priorities if not
118+
* supported by default, otherwise this call will have no effect.
119+
*/
120+
bool setPriority(int prio);
121+
122+
/*
123+
* Sets the currently executing thread's name to where supported; useful
124+
* for debugging.
125+
*/
74126
static void setName(const std::string &name);
75127

128+
/*
129+
* Returns the number of processors/cores configured and active on this machine.
130+
*/
131+
static unsigned int getNumberOfProcessors();
132+
76133
protected:
77-
std::string name;
134+
std::string m_name;
78135

79136
virtual void *run() = 0;
80137

81138
private:
82-
void setName() { setName(name); }
83-
84-
void *retval;
85-
Atomic<bool> request_stop;
86-
Atomic<bool> running;
87-
Mutex continue_mutex;
88-
89-
#if __cplusplus >= 201103L
90-
static void theThread(Thread *th);
91-
92-
std::thread *thread;
93-
std::thread::native_handle_type getThreadHandle() const
94-
{ return thread->native_handle(); }
95-
#else
96-
# if defined(WIN32) || defined(_WIN32_WCE)
97-
# ifdef _WIN32_WCE
98-
DWORD thread_id;
99-
static DWORD WINAPI theThread(void *param);
100-
# else
101-
UINT thread_id;
102-
static UINT __stdcall theThread(void *param);
103-
# endif
104-
105-
HANDLE thread;
106-
HANDLE getThreadHandle() const { return thread; }
107-
# else // pthread
108-
static void *theThread(void *param);
109-
110-
pthread_t thread;
111-
pthread_t getThreadHandle() const { return thread; }
112-
113-
Atomic<bool> started;
114-
# endif
139+
void *m_retval;
140+
Atomic<bool> m_request_stop;
141+
Atomic<bool> m_running;
142+
Mutex m_continue_mutex;
143+
144+
threadid_t m_thread_id;
145+
threadhandle_t m_thread_handle;
146+
147+
void cleanup();
148+
149+
static ThreadStartFunc threadProc;
150+
151+
#ifdef _AIX
152+
// For AIX, there does not exist any mapping from pthread_t to tid_t
153+
// available to us, so we maintain one ourselves. This is set on thread start.
154+
tid_t m_kernel_thread_id;
155+
#endif
156+
157+
#if USE_CPP11_THREADS
158+
std::thread *m_thread_obj;
115159
#endif
160+
116161
};
117162

118163
#endif

0 commit comments

Comments
 (0)
Please sign in to comment.