#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