__thread Variables Verses TlsAlloc.

The following limitations apply to variables declared using the __thread keyword.

The __thread keyword cannot be used with variables that require runtime initialisation.

e.g.    __thread int lval = 0;   //legal
        __thread string strval("example");    //illegal

The __thread keyword cannot be used in a DLL, for this reason TlsAlloc / TlsSetData / TlsGetData provide a more versatile method for defining thread specific variables in a WIN32 program.


Usage:

TlsAlloc is a once per instance initialisation that returns an index used for TlsSetData / TlsGetData.

TlsSetData is a once per thread initialisation, used to store a pointer to that thread's data.

Example:

The following example uses a class object to store thread specific data. Access to this data is via a couple of macros which effectively hide the data access mechanism from the rest of your code. The example provides for two thread specific variables, a long value and a string class instance. Both can be run time initialised and both are accessed via macros which return references to the actual thread specific objects. The code is highly adaptable and can store any number of thread specific variables, the code will also cope with DLL's that are loaded after a new thread has been created by a process, and doesn't therefore receive a DLL_THREAD_ATTACH notification in it's DllEntryPoint.

CUT HERE***********MYTHREAD.H***************CUT HERE

#if !defined(__MYTHREAD_H)
#define __MYTHREAD_H

//Access macros
//Use these to access thread specific data

#define strval GetStrVal()
#define lval GetLVal()

//Access functions
//These are the actual functions which return 
//references to the thread specific data:

string& GetStrVal();
long & GetLVal();

//Cleanup functions
//must be called  on DLL_PROCESS_DETACH and DLL_THREAD_DETACH:

void ReleaseProcessData();
void ReleaseThreadData();

#endif

CUT HERE***********END OF MYTHREAD.H***********CUT HERE

CUT HERE***********MYTHREAD.CPP*****************CUT HERE

#include <cstring.h>
#include "mythread.h"

/***************************************************************

Thread specific data handled here, no need for any other module
to see TThreadData.

***************************************************************/

class TThreadData
{
public:
        TThreadData();
        ~TThreadData();
        string strval;
        long lval;
};

TThreadData::TThreadData()
{
        //run time initialisation goes here.
        strval = "some text";
        lval  =  foo();
}

TThreadData::~TThreadData()
{
        //Cleanup of thread specific objects goes here.
}

Index = 0;
bool Initialised = 0;

TThreadData*  GetThreadData()
{
        if(!Initialised)
        {
                Index = TlsAlloc();
                Initialised = true;
        }
        TThreadData* data = (TThreadData*)TlsGetValue(Index);
        if(!data)
        {
                data = new TThreadData();
                TlsSetValue(Index, data);
        }
        return data;
}

//Cleanup functions
//ReleaseThreadData must be called on each DLL_THREAD_DETACH
//ReleaseProcessData must be called on each DLL_PROCESS_DETACH.

void ReleaseThreadData()
{
        delete GetThreadData();
}

void ReleaseProcessData()
{
        delete GetThreadData();
        TlsFree(Index);
}

//Actual access functions:

string& GetStrVal()
{
        return GetThreadData()->strval;
}

long& GetLVal()
{
        return GetThreadData()->lval;
}

CUT HERE*************END OF MYTHREAD.CPP**********CUT HERE


Back to home page....


Copyright Dr J. Maddock.

Last Updated: 23 May 1997