1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
|
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
// When in MSVC, the debugger provides "thread naming" by catching special exceptions. Interface here:
#ifdef _MSC_VER
//
// Usage: SetThreadName (-1, "MainThread");
//
// Code adapted from MSDN: http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
const DWORD MS_VC_EXCEPTION = 0x406D1388;
#pragma pack(push, 8)
typedef struct tagTHREADNAME_INFO
{
DWORD dwType; // Must be 0x1000.
LPCSTR szName; // Pointer to name (in user addr space).
DWORD dwThreadID; // Thread ID (-1 = caller thread).
DWORD dwFlags; // Reserved for future use, must be zero.
} THREADNAME_INFO;
#pragma pack(pop)
static void SetThreadName(DWORD dwThreadID, const char * threadName)
{
THREADNAME_INFO info;
info.dwType = 0x1000;
info.szName = threadName;
info.dwThreadID = dwThreadID;
info.dwFlags = 0;
__try
{
RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR *)&info);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
}
}
#endif // _MSC_VER
cThread::cThread( ThreadFunc a_ThreadFunction, void* a_Param, const char* a_ThreadName /* = 0 */)
: m_ThreadFunction( a_ThreadFunction)
, m_Param( a_Param)
, m_Event( new cEvent())
, m_StopEvent( 0)
{
if (a_ThreadName)
{
m_ThreadName.assign(a_ThreadName);
}
}
cThread::~cThread()
{
delete m_Event;
m_Event = NULL;
if (m_StopEvent)
{
m_StopEvent->Wait();
delete m_StopEvent;
m_StopEvent = NULL;
}
}
void cThread::Start( bool a_bWaitOnDelete /* = true */)
{
if (a_bWaitOnDelete)
m_StopEvent = new cEvent();
#ifndef _WIN32
pthread_t SndThread;
if (pthread_create( &SndThread, NULL, MyThread, this))
LOGERROR("ERROR: Could not create thread!");
#else
DWORD ThreadID = 0;
HANDLE hThread = CreateThread(NULL // security
, 0 // stack size
, (LPTHREAD_START_ROUTINE) MyThread // function name
, this // parameters
, 0 // flags
, &ThreadID); // thread id
CloseHandle( hThread);
#ifdef _MSC_VER
if (!m_ThreadName.empty())
{
SetThreadName(ThreadID, m_ThreadName.c_str());
}
#endif // _MSC_VER
#endif
// Wait until thread has actually been created
m_Event->Wait();
}
#ifdef _WIN32
unsigned long cThread::MyThread(void* a_Param)
#else
void *cThread::MyThread( void *a_Param)
#endif
{
cThread* self = (cThread*)a_Param;
cEvent* StopEvent = self->m_StopEvent;
ThreadFunc* ThreadFunction = self->m_ThreadFunction;
void* ThreadParam = self->m_Param;
// Set event to let other thread know this thread has been created and it's safe to delete the cThread object
self->m_Event->Set();
ThreadFunction( ThreadParam);
if (StopEvent) StopEvent->Set();
return 0;
}
|