4
#include "NObjectType.h"
8
class NThreadSafeCounter
11
NThreadSafeCounter() {m_Counter = 0;}
12
NThreadSafeCounter(t_integer i) {m_Counter = i;}
13
t_integer Increment();
14
t_integer Decrement();
15
t_integer Set(t_integer i);
16
t_integer GetValue() const;
17
t_integer operator ++ ();
18
t_integer operator -- ();
19
t_bool operator == (t_integer i);
24
class NCriticalSection
27
//! Initialize critical section.
29
Initialize critical section.
31
NCriticalSection() { InitializeCriticalSection(&m_lock); }
33
//! Destroy critical section.
35
Destroy critical section.
37
~NCriticalSection() { DeleteCriticalSection(&m_lock); }
39
//! Enter critical section.
41
Enter critical section. This function is made const so it can be used without restriction.
42
For that matter, m_lock is made mutable.
46
EnterCriticalSection(&m_lock);
49
//! Leave critical section.
51
Leave critical section. This function is made const so it can be used without restriction.
52
For that matter, m_lock is made mutable.
56
LeaveCriticalSection(&m_lock);
60
//! Prohibit copy constructor.
62
Prohibit copy constructor.
64
NCriticalSection(const NCriticalSection&);
65
//! Prohibit assignment operator.
67
Prohibit assignment operator.
69
NCriticalSection& operator=(const NCriticalSection&);
71
mutable CRITICAL_SECTION m_lock;
76
Takes a critical section object as parameter of the constructor.
77
The constructor locks the critical section.
78
The destructor unlocks the critical section.
83
//! The constructor locks the critical section object.
85
The constructor locks the critical section object.
86
@param LockObject Critical section object.
88
NScopeLock(NCriticalSection* CriticalSectionObject)
89
: m_CriticalSectionObject(CriticalSectionObject)
91
nuxAssert(m_CriticalSectionObject);
92
m_CriticalSectionObject->Lock();
95
//! The destructor unlocks the critical section object.
97
The destructor unlocks the critical section object.
101
nuxAssert(m_CriticalSectionObject);
102
m_CriticalSectionObject->Unlock();
106
//! Prohibit default constructor.
108
Prohibit default constructor.
112
//! Prohibit copy constructor.
114
Prohibit copy constructor.
116
NScopeLock(const NScopeLock& ScopeLockObject);
118
//! Prohibit assignment operator.
120
Prohibit assignment operator.
122
NScopeLock& operator=(const NScopeLock& ScopeLockObject) { return *this; }
124
//! Critical section Object.
126
Critical section Object.
128
NCriticalSection* m_CriticalSectionObject;
131
class NThreadLocalStorage
137
InvalidTLS = 0xFFFFFFFF
140
typedef void (*TLS_ShutdownCallback)();
142
static BOOL m_TLSUsed[NbTLS];
143
static t_u32 m_TLSIndex[NbTLS];
144
static TLS_ShutdownCallback m_TLSCallbacks[NbTLS];
146
static void Initialize();
147
static void Shutdown();
148
static BOOL RegisterTLS(t_u32 index, TLS_ShutdownCallback shutdownCallback);
149
static void ThreadInit();
150
static void ThreadShutdown();
154
template<class T> static inline T GetData(t_u32 index)
156
nuxAssert(sizeof(T) <= sizeof(size_t));
157
nuxAssert(index < NbTLS);
158
nuxAssert(m_TLSUsed[index]);
160
// T and (unsigned long) can be of different sizes
161
// but this limits the use of GetData to classes without copy constructors
167
temp.v = TlsGetValue(m_TLSIndex[index]);
171
template<class T> static inline void SetData(t_u32 index, T value)
173
nuxAssert(sizeof(T) <= sizeof(size_t));
174
nuxAssert(index < NbTLS);
175
nuxAssert(m_TLSUsed[index]);
177
// T and (unsigned long) can be of different sizes
178
// but this limits the use of GetData to classes without copy constructors
184
BOOL b = TlsSetValue(m_TLSIndex[index], temp.v);
185
nuxAssertMsg(b, TEXT("[NThreadLocalStorage::SetData] TlsSetValue returned FALSE."));
189
#define inlDeclareThreadLocalStorage(type, index, name) \
190
struct ThreadLocalStorageDef##name { enum Const { Index = index}; };\
191
inline type GetTLS_##name() { return nux::NThreadLocalStorage::GetData<type>(ThreadLocalStorageDef##name::Index); }\
192
inline void SetTLS_##name(type value) { nux::NThreadLocalStorage::SetData<type>(ThreadLocalStorageDef##name::Index, value); }
194
#define inlRegisterThreadLocalIndex(index, name, shutdownCallback) \
195
nuxVerifyExpr(index == ThreadLocalStorageDef##name::Index); \
196
nuxVerifyExpr(nux::NThreadLocalStorage::RegisterTLS(index, shutdownCallback))
198
#define inlGetThreadLocalStorage(name) GetTLS_##name()
199
#define inlSetThreadLocalStorage(name, value) SetTLS_##name(value)
201
#ifdef POP_CHECK_THREADS
202
#define nuxAssertInsideThread(threadtype) nuxAssert( inlGetThreadLocalStorage(ThreadType) == threadtype)
203
#define nuxAssertInsideThread2(threadtype1, threadtype2) nuxAssert( inlGetThreadLocalStorage(ThreadType) == threadtype1 || popGetThreadLocalData(ThreadType) == threadtype2)
204
#define nuxAssertNotInsideThread(threadtype) nuxAssert( inlGetThreadLocalStorage(ThreadType) != threadtype)
206
#define nuxAssertInsideThread(threadtype) ((void) 0)
207
#define nuxAssertInsideThread2(threadtype1, threadtype2) ((void) 0)
208
#define nuxAssertNotInsideThread(threadtype) ((void) 0)
211
void SetWin32ThreadName(DWORD dwThreadID, LPCSTR szThreadName);
222
THREAD_SUSPEND_ERROR,
226
// http://www.codeguru.com/cpp/misc/misc/threadsprocesses/article.php/c3793/
229
DECLARE_ROOT_OBJECT_TYPE(NThread);
232
Info: Default Constructor
237
Info: Plug Constructor
239
Use this to migrate/port existing worker threads to objects immediately
240
Although you lose the benefits of ThreadCTOR and ThreadDTOR.
242
NThread(LPTHREAD_START_ROUTINE lpExternalRoutine);
245
Info: Default Destructor
247
I think it is wise to destroy the thread even if it is running,
248
when the main thread reaches here.
253
Info: Starts the thread.
255
This function starts the thread pointed by m_pThreadFunc with default attributes
257
virtual ThreadState Start( void* arg = NULL );
260
Info: Stops the thread.
262
This function stops the current thread.
263
We can force kill a thread which results in a TerminateThread.
265
virtual ThreadState Stop ( bool bForceKill = false );
267
ThreadState Suspend();
268
ThreadState Resume();
269
ThreadState ResumeStart();
270
ThreadState ResumeExit();
273
Info: Starts the thread.
275
This function starts the thread pointed by m_pThreadFunc with default attributes
277
t_u32 GetExitCode() const;
280
Info: Attaches a Thread Function
282
Used primarily for porting but can serve in developing generic thread objects
284
void Attach( LPTHREAD_START_ROUTINE lpThreadFunc ){
285
m_pThreadFunc = lpThreadFunc;
289
Info: Detaches the Attached Thread Function
291
Detaches the Attached Thread Function, If any.
292
by resetting the thread function pointer to EntryPoint1
296
m_pThreadFunc = NThread::EntryPoint;
299
HANDLE GetThreadHandle();
303
ThreadState GetThreadState() const;
304
void SetThreadState(ThreadState state);
306
void SetThreadName(const TCHAR* ThreadName);
307
const NString& GetThreadName() const;
310
NString m_ThreadName;
312
volatile ThreadState m_ThreadState;
315
Info: DONT override this method.
317
This function is like a standard template.
318
Override if you are sure of what you are doing.
320
In C++ the entry function of a thread cannot be a normal member function of a class.
321
However, it can be a static member function of a class. This is what we will use as the entry point.
322
There is a gotcha here though. Static member functions do not have access to the this pointer of a C++ object.
323
They can only access static data. Fortunately, there is way to do it. Thread entry point functions take a void * as
324
a parameter so that the caller can typecast any data and pass in to the thread. We will use this to pass this to
325
the static function. The static function will then typecast the void * and use it to call a non static member function
327
static DWORD WINAPI EntryPoint(void* pArg);
330
Info: Override this method.
332
This function should contain the body/code of your thread.
333
Notice the signature is similar to that of any worker thread function
334
except for the calling convention.
336
virtual t_u32 Run(void* /* arg */ )
337
{ return m_ThreadCtx.m_dwExitCode; }
340
Info: Constructor-like function.
342
Will be called by EntryPoint before executing the thread body.
343
Override this function to provide your extra initialization.
345
NOTE: do not confuse it with the classes constructor
346
@return TRUE if the thread can continue running the program. If FALSE is returned, the thread won't execute the main body Run() and will exit without calling ThreadDtor.
348
virtual bool ThreadCtor(){return true;}
351
Info: Destructor-like function.
353
Will be called by EntryPoint after executing the thread body.
354
Override this function to provide your extra destruction.
356
NOTE: do not confuse it with the classes constructor
357
@return TRUE if this function executed without problems.
359
virtual bool ThreadDtor(){return true;}
363
Info: Thread Context Inner Class
365
Every thread object needs to be associated with a set of values.
366
like UserData Pointer, Handle, Thread ID etc.
368
NOTE: This class can be enhanced to varying functionalities
370
* Members to hold StackSize
371
* SECURITY_ATTRIBUTES member.
377
memset(this, 0, sizeof(this));
384
HANDLE m_hThread; // The Thread Handle
385
volatile t_u32 m_dwTID; // The Thread ID
386
void* m_pUserData; // The user data pointer
387
void* m_pParent; // The this pointer of the parent NThread object
388
t_u32 m_dwExitCode; // The Exit Code of the thread
396
Info: Members of NThread
398
NThreadContext m_ThreadCtx; // The Thread Context member
399
LPTHREAD_START_ROUTINE m_pThreadFunc; // The Worker Thread Function Pointer
403
// DWORD WINAPI Threaded(void* lpData);
405
// class CDemoThread : public CThread
407
// virtual t_u32 Run( void* /* arg */ )
411
// printf("Threaded Object Code \n");
421
// SleepEx(15 * 1000, FALSE);
424
// // A Sample Code for porting existent code of Threaded function
425
// CThread t1(Threaded), t2;
426
// t2.Attach(Threaded);
429
// SleepEx(15 * 1000, FALSE);
434
// DWORD WINAPI Threaded( void* /* lpData */ )
438
// printf("worker threaded code");