Listing 2: The test program using the TLS proxy class

#include <iostream>
#include <string>
#include <process.h>
#include "DataProxy.h"

class Counter
{
public:
    Counter(const std::string &name);
    Counter &operator+=(int);
    int getValue() const;
    const std::string &getName() const;

private:
    std::string    name;
    int            n;
};

inline Counter::Counter(const std::string &p_name) : 
    name(p_name), n(0)
{
}

Counter &Counter::operator+=(int rh)
{
    n += rh;
    return *this;
}

int Counter::getValue() const
{
    return n;
}

const std::string &Counter::getName() const
{
    return name;
}

DataProxy<Counter> CounterProxy;

// A function that uses a singleton. In a single threaded environment
// everything was fine. When we move the architecture change to 
// facilitate a multithreaded environment we are using CounterProxy 
// instead to make it appear as every thread instance has its own 
// data.
void PrintResult()
{
    std::cout << CounterProxy->getValue() << CounterProxy->getName() 
              << std::endl; 
    *CounterProxy += (CounterProxy->getValue() % 2) ? 1 : 2;    
}

DWORD WINAPI ThreadFunction1(LPVOID param)
{
    Counter counter("ThreadFunction1");

    CounterProxy.setData(&counter);    
    for (int i = 0;i < 100;i++)
    {
        PrintResult();
        Sleep(100);
    }
    return 0;
}

DWORD WINAPI ThreadFunction2(LPVOID param)
{
    Counter counter("ThreadFunction2");

    CounterProxy.setData(&counter);
    for (int i = 0;i < 100;i++)
    {
        PrintResult();
        Sleep(200);
    }    
    return 0;
}

int main(int argc, char* argv[])
{
    const int N_THREADS = 2;
    DWORD dwThreadId;
    HANDLE hThread[N_THREADS]; 
    
    hThread[0] =        
        CreateThread(NULL,0,::ThreadFunction1,NULL,0,&dwThreadId)   
    hThread[1] =
        CreateThread(NULL,0,::ThreadFunction2,NULL,0,&dwThreadId)
    WaitForMultipleObjects(N_THREADS,hThread,TRUE,INFINITE);
    CloseHandle(hThread[0]);
    CloseHandle(hThread[1]);
    return 0;
}

— End of Listing —