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 —