Maybe you should use pthread_getspecific, pthread_setspecific and pthread_key_create to manage your per thread singleton.
According to "Windows VIA C/C++" by Richter and Nasarre (A must-have book for any C++ Windwos programmer) p.154:
Terminating a Thread
A thread can be terminated in four ways:
- The thread function returns. (This is highly recommended.)
- The thread kills itself by calling the ExitThread function. (Avoid this method.)
- A thread in the same process or in another one calls the TerminateThread function. (Avoid this method.)
- The process containing the thread terminates. (Avoid this method.)
The Thread Function Returns
You should always design your thread functions so that they return when you want the thread to terminate. This is the only way to guarantee that all your thread's resources are cleaned up properly.
Having your thread function return ensures the following:
- All C++ objects created in your thread function will be destroyed properly via their destructors.
- The operating system will properly free the memory used by the thread's stack.
- The system will set the thread's exit code (maintained in the thread's kernel object) to your thread function's return value.
- The system will decrement the usage count of the thread's kernel object.
The ExitThread Function
You can force your thread to terminate by having it call ExitThread:
VOID ExitThread(DWORD dwExitCode);
This function terminates the thread and causes the operating system to clean up all the operating system resources that were used by the thread. However, your C/C++ resources (such as C++ class objects) will not be destroyed. For this reason, it is much better to simply return from your thread function instead of calling ExitThread yourself.
Of course, you use ExitThread's dwExitCode parameter to tell the system what to set the thread's exit code to. The ExitThread function does not return a value because the thread has terminated and cannot execute any more code.
Note The recommended way to have a thread terminate is by having its thread function simply return (as described in the previous section). However, if you use the method described in this section, be aware that the ExitThread function is the Windows function that kills a thread. If you are writing C/C++ code, you should never call ExitThread. Instead, you should use the C++ run-time library function _endthreadex. If you do not use Microsoft's C++ compiler, your compiler vendor will have its own alternative to ExitThread. Whatever this alternative is, you must use it.
The TerminateThread Function
A call to TerminateThread also kills a thread:
BOOL TerminateThread( HANDLE hThread, DWORD dwExitCode);
Unlike ExitThread, which always kills the calling thread, TerminateThread can kill any thread. The hThread parameter identifies the handle of the thread to be terminated. When the thread terminates, its exit code becomes the value you passed as the dwExitCode parameter. Also, the thread's kernel object has its usage count decremented.
Note The TerminateThread function is asynchronous. That is, it tells the system that you want the thread to terminate but the thread is not guaranteed to be killed by the time the function returns. If you need to know for sure that the thread has terminated, you might want to call WaitForSingleObject or a similar function, passing the handle of the thread.
A well-designed application never uses this function because the thread being terminated receives no notification that it is dying. The thread cannot clean up properly, and it cannot prevent itself from being killed.
Note When a thread dies by returning or calling ExitThread, the stack for the thread is destroyed. However, if TerminateThread is used, the system does not destroy the thread's stack until the process that owned the thread terminates. Microsoft purposely implemented TerminateThread in this way. If other still-executing threads were to reference values on the forcibly killed thread's stack, these other threads would raise access violations. By leaving the killed thread's stack in memory, other threads can continue to execute just fine.
In addition, dynamic-link libraries (DLLs) usually receive notifications when a thread is terminating. If a thread is forcibly killed with TerminateThread, however, the DLLs do not receive this notification, which can prevent proper cleanup.
When a Thread Terminates
The following actions occur when a thread terminates:
All User object handles owned by the thread are freed. In Windows, most objects are owned by the process containing the thread that creates the objects. However, a thread owns two User objects: windows and hooks. When a thread dies, the system automatically destroys any windows and uninstalls any hooks that were created or installed by the thread. Other objects are destroyed only when the owning process terminates.
The thread's exit code changes from STILL_ACTIVE to the code passed to ExitThread or TerminateThread.
The state of the thread kernel object becomes signaled.
If the thread is the last active thread in the process, the system considers the process terminated as well.
The thread kernel object's usage count is decremented by 1.
When a thread terminates, its associated thread kernel object doesn't automatically become freed until all the outstanding references to the object are closed.
Once a thread is no longer running, there isn't much any other thread in the system can do with the thread's handle. However, these other threads can call GetExitCodeThread to check whether the thread identified by hThread has terminated and, if it has, determine its exit code:
BOOL GetExitCodeThread( HANDLE hThread, PDWORD pdwExitCode);
The exit code value is returned in the DWORD pointed to by pdwExitCode. If the thread hasn't terminated when GetExitCodeThread is called, the function fills the DWORD with the STILL_ACTIVE identifier (defined as 0x103). If the function is successful, TRUE is returned.