9
#define INL_ATOMOP_ITERLOCKED_INCREMENT InterlockedIncrement64
10
#define INL_ATOMOP_ITERLOCKED_DECREMENT InterlockedDecrement64
11
#define INL_ATOMOP_ITERLOCKED_EXCHANGED InterlockedExchange64
12
#define INL_ATOMOP_ITERLOCKED_VALUE
14
#define INL_ATOMOP_ITERLOCKED_INCREMENT InterlockedIncrement
15
#define INL_ATOMOP_ITERLOCKED_DECREMENT InterlockedDecrement
16
#define INL_ATOMOP_ITERLOCKED_EXCHANGED InterlockedExchange
17
#define INL_ATOMOP_ITERLOCKED_VALUE
20
t_integer NThreadSafeCounter::Increment()
22
return INL_ATOMOP_ITERLOCKED_INCREMENT( &m_Counter );
24
t_integer NThreadSafeCounter::Decrement()
26
return INL_ATOMOP_ITERLOCKED_DECREMENT( &m_Counter );
28
t_integer NThreadSafeCounter::Set(t_integer i)
30
return INL_ATOMOP_ITERLOCKED_EXCHANGED( &m_Counter, i );
33
t_integer NThreadSafeCounter::GetValue() const
38
t_integer NThreadSafeCounter::operator ++ ()
43
t_integer NThreadSafeCounter::operator -- ()
48
t_bool NThreadSafeCounter::operator == (t_integer i)
50
return (m_Counter == i);
53
t_u32 NThreadLocalStorage::m_TLSIndex[NThreadLocalStorage::NbTLS];
54
BOOL NThreadLocalStorage::m_TLSUsed[NThreadLocalStorage::NbTLS];
55
NThreadLocalStorage::TLS_ShutdownCallback NThreadLocalStorage::m_TLSCallbacks[NThreadLocalStorage::NbTLS];
58
// http://msdn2.microsoft.com/en-us/library/xcb2z8hs(VS.80).aspx
60
// Usage: SetWin32ThreadName (-1, "MainThread");
62
#define MS_VC_EXCEPTION 0x406D1388
64
typedef struct tagTHREADNAME_INFO
66
DWORD dwType; // Must be 0x1000.
67
LPCSTR szName; // Pointer to name (in user addr space).
68
DWORD dwThreadID; // Thread ID (-1=caller thread).
69
DWORD dwFlags; // Reserved for future use, must be zero.
72
void SetWin32ThreadName(DWORD dwThreadID, LPCSTR szThreadName)
76
info.szName = szThreadName;
77
info.dwThreadID = dwThreadID;
82
RaiseException( MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(DWORD), (ULONG_PTR*)&info );
84
__except(EXCEPTION_CONTINUE_EXECUTION)
89
BOOL NThreadLocalStorage::RegisterTLS(t_u32 index, NThreadLocalStorage::TLS_ShutdownCallback shutdownCallback)
91
nuxAssert(!m_TLSUsed[index]);
93
if (!m_TLSUsed[index])
95
m_TLSIndex[index] = TlsAlloc();
96
if(m_TLSIndex[index] == TLS_OUT_OF_INDEXES)
98
nuxAssertMsg(0, TEXT("[NThreadLocalStorage::RegisterTLS] Out of TLS index."));
100
m_TLSUsed[index] = TRUE;
101
m_TLSCallbacks[index] = shutdownCallback;
110
void NThreadLocalStorage::Initialize()
112
Memset(m_TLSUsed, 0, sizeof(m_TLSUsed));
114
for (t_u32 i = 0; i < NThreadLocalStorage::NbTLS; i++)
116
// Fill the array with invalid values
117
m_TLSIndex[i] = NThreadLocalStorage::InvalidTLS; // invalid index
121
void NThreadLocalStorage::Shutdown()
126
void NThreadLocalStorage::ThreadInit()
130
void NThreadLocalStorage::ThreadShutdown()
132
TLS_ShutdownCallback *callback = m_TLSCallbacks;
133
for (t_u32 i = 0; i < NThreadLocalStorage::NbTLS; ++i, ++callback)
142
IMPLEMENT_ROOT_OBJECT_TYPE(NThread);
145
: m_ThreadState(THREADINIT)
147
m_pThreadFunc = NThread::EntryPoint; // Can call Detach() also.
150
NThread::NThread(LPTHREAD_START_ROUTINE lpExternalRoutine)
152
Attach(lpExternalRoutine);
157
CloseHandle(m_ThreadCtx.m_hThread);
160
ThreadState NThread::Start( void* arg )
162
if ( m_ThreadCtx.m_hThread == 0)
164
m_ThreadCtx.m_pUserData = arg;
165
m_ThreadCtx.m_hThread = CreateThread(NULL,
169
0 /*CREATE_SUSPENDED*/,
170
(LPDWORD)&m_ThreadCtx.m_dwTID);
172
if(m_ThreadCtx.m_hThread != 0)
175
m_ThreadState = THREADINIT;
176
m_ThreadCtx.m_dwExitCode = (t_u32)-1;
177
return m_ThreadState;
181
nuxDebugMsg(TEXT("[NThread::Start] Cannot start thread: %s"), inlGetSystemErrorMessage());
182
m_ThreadState = THREAD_START_ERROR;
183
return m_ThreadState;
187
return m_ThreadState;
190
ThreadState NThread::Stop( bool bForceKill )
193
// TerminateThread is used to cause a thread to exit. When this occurs, the target thread has no chance to execute any user-mode code and its initial stack is not deallocated. DLLs attached to the thread are not notified that the thread is terminating.
194
// TerminateThread is a dangerous function that should only be used in the most extreme cases. You should call TerminateThread only if you know exactly what the target thread is doing, and you control all of the code that the target thread could possibly be running at the time of the termination. For example, TerminateThread can result in the following problems:
195
// If the target thread owns a critical section, the critical section will not be released.
196
// If the target thread is allocating memory from the heap, the heap lock will not be released.
197
// If the target thread is executing certain kernel32 calls when it is terminated, the kernel32 state for the thread's process could be inconsistent.
198
// If the target thread is manipulating the global state of a shared DLL, the state of the DLL could be destroyed, affecting other users of the DLL.
200
// Attention: Calling Stop from another thread is not going to free the stack of this thread.
201
// the stack is freed only if the thread exits by itself.
202
if ( m_ThreadCtx.m_hThread )
204
GetExitCodeThread(m_ThreadCtx.m_hThread, (LPDWORD)&m_ThreadCtx.m_dwExitCode);
206
if ( m_ThreadCtx.m_dwExitCode == STILL_ACTIVE && bForceKill )
208
TerminateThread(m_ThreadCtx.m_hThread, t_u32(-1));
209
CloseHandle(m_ThreadCtx.m_hThread);
211
m_ThreadCtx.m_hThread = NULL;
213
m_ThreadState = THREADSTOP;
214
return m_ThreadState;
217
ThreadState NThread::Suspend()
219
unsigned int ret = SuspendThread(m_ThreadCtx.m_hThread);
220
if(ret == 0xFFFFFFFF)
222
nuxDebugMsg(TEXT("[NThread::Suspend] Cannot suspend thread: %s"), inlGetSystemErrorMessage());
223
return THREAD_SUSPEND_ERROR;
225
m_ThreadState = THREADSUSPENDED;
226
return m_ThreadState;
229
ThreadState NThread::Resume()
231
unsigned int ret = ResumeThread(m_ThreadCtx.m_hThread);
232
if(ret == 0xFFFFFFFF)
234
nuxDebugMsg(TEXT("[NThread::Suspend] Cannot resume thread: %s"), inlGetSystemErrorMessage());
235
return THREAD_RESUME_ERROR;
239
// If the return value is 1, the specified thread was suspended but was restarted.
240
m_ThreadState = THREADRUNNING;
244
// If the return value is greater than 1, the specified thread is still suspended.
245
m_ThreadState = THREADSUSPENDED;
247
return m_ThreadState;
250
// go from suspended to thread start
251
ThreadState NThread::ResumeStart()
253
m_ThreadState = THREADINIT;
254
unsigned int ret = ResumeThread(m_ThreadCtx.m_hThread);
255
if(ret == 0xFFFFFFFF)
257
nuxDebugMsg(TEXT("[NThread::ResumeExit] Cannot resume thread: %s"), inlGetSystemErrorMessage());
258
return THREAD_RESUME_ERROR;
262
// If the return value is 1, the specified thread was suspended but was restarted.
263
m_ThreadState = THREADINIT;
267
nuxAssert(0); // should not happen
268
// If the return value is greater than 1, the specified thread is still suspended.
269
m_ThreadState = THREADINIT;
271
return m_ThreadState;
274
// go from suspended to thread exit
275
ThreadState NThread::ResumeExit()
277
m_ThreadState = THREADSTOP;
278
unsigned int ret = ResumeThread(m_ThreadCtx.m_hThread);
279
if(ret == 0xFFFFFFFF)
281
nuxDebugMsg(TEXT("[NThread::ResumeExit] Cannot resume thread: %s"), inlGetSystemErrorMessage());
282
return THREAD_RESUME_ERROR;
286
// If the return value is 1, the specified thread was suspended but was restarted.
287
m_ThreadState = THREADSTOP;
291
nuxAssert(0); // should not happen
292
// If the return value is greater than 1, the specified thread is still suspended.
293
m_ThreadState = THREADSTOP;
295
return m_ThreadState;
298
DWORD WINAPI NThread::EntryPoint(void* pArg)
300
NThread *pParent = reinterpret_cast<NThread*>(pArg);
303
nuxDebugMsg(TEXT("[NThread::EntryPoint] Invalid pointer. The thread will exit."));
307
if(!pParent->ThreadCtor())
309
// return another message saying the thread could not execute due to error in ThreadCtor;
313
pParent->Run( pParent->m_ThreadCtx.m_pUserData );
314
pParent->ThreadDtor();
319
t_u32 NThread::GetExitCode() const
321
if ( m_ThreadCtx.m_hThread )
322
GetExitCodeThread(m_ThreadCtx.m_hThread, (LPDWORD)&m_ThreadCtx.m_dwExitCode);
323
return m_ThreadCtx.m_dwExitCode;
326
HANDLE NThread::GetThreadHandle()
328
return m_ThreadCtx.m_hThread;
331
t_u32 NThread::GetThreadId()
333
return (t_u32)m_ThreadCtx.m_dwTID;
336
ThreadState NThread::GetThreadState() const
338
return m_ThreadState;
341
void NThread::SetThreadState(ThreadState state)
343
m_ThreadState = state;
346
void NThread::SetThreadName(const TCHAR* ThreadName)
348
SetWin32ThreadName(GetThreadId(), TCHAR_TO_ANSI(ThreadName));
349
m_ThreadName = ThreadName;
352
const NString& NThread::GetThreadName() const