Listing 1: Per-thread Singleton class implementation
#include <windows.h> #include <iostream.h> // This class ensures that the thread specific instance gets // deleted as each thread exits. class ThreadSingletonDestroyer { public: ~ThreadSingletonDestroyer(); }; // This class implements the functionality needed for a thread // specific Singleton class. class ThreadSingleton { public: static ThreadSingleton* GetObject(); DWORD GetThreadID() { return m_ThreadID; } protected: ThreadSingleton(DWORD threadID) { m_ThreadID = threadID; } private: static DWORD m_ThreadIndex; DWORD m_ThreadID; static void DestroyObject(); friend ThreadSingletonDestroyer; }; DWORD ThreadSingleton :: m_ThreadIndex = -1; ThreadSingletonDestroyer :: ~ThreadSingletonDestroyer() { // Just call the function DestroyObject. ThreadSingleton :: DestroyObject(); } void ThreadSingleton :: DestroyObject() { // If the thread Index is not even initialized yet, it // means there have been no object created for this class // yet, just return. if(-1 == m_ThreadIndex) { return; } ThreadSingleton *obj = NULL; // If there is an object at the TLS index, delete it, // otherwise just return. obj = (ThreadSingleton*)TlsGetValue(m_ThreadIndex); if(NULL != obj) { delete obj; } } ThreadSingleton* ThreadSingleton :: GetObject() { ThreadSingleton *retVal = NULL; // This "if" block needs to be protected by a // CRITICAL_SECTION, left out for sake of clarity. if(-1 == m_ThreadIndex) { m_ThreadIndex = TlsAlloc(); if(-1 == m_ThreadIndex) { cout << "Error while calling TlsAlloc\n"; return NULL; } } // Try to get an object at the TLS index, but if we can't // then create one and put in the TLS location. retVal = (ThreadSingleton*)TlsGetValue(m_ThreadIndex); if(NULL == retVal) { retVal = new ThreadSingleton(GetCurrentThreadId()); TlsSetValue(m_ThreadIndex, retVal); } return retVal; } // This is the thread function, this function is called to // execute the thread created in "main". DWORD WINAPI ThreadMain(void*) { // This object's destructor will destroy the thread // specific singleton instance, upon the thread's exit. ThreadSingletonDestroyer tsDestroyer; ThreadSingleton *obj = ThreadSingleton :: GetObject(); cout <<"The thread ID is = " << obj->GetThreadID() << endl; return 0; } int main() { ThreadSingletonDestroyer tsDestroyer; DWORD dwThreadID; ThreadSingleton *obj = ThreadSingleton :: GetObject(); // Print the thread ID. cout <<"The thread ID is = " << obj->GetThreadID() << endl; HANDLE handle = CreateThread(NULL, 0, ThreadMain, NULL, 0, &dwThreadID); if(NULL == handle) { cout << "Error while creating a thread!\n"; return -1; } (void)WaitForSingleObject(handle, INFINITE); return 0; } End of Listing