René Nyffenegger's collection of things on the web
René Nyffenegger on Oracle - Most wanted - Feedback -
 

TLS Under Windows

#include <windows.h>
#include <process.h>

#include <iostream>

using namespace std;

struct threadGlobal {
  int x;
  int y;
};

CRITICAL_SECTION cs_out;
CRITICAL_SECTION cs_g;
CRITICAL_SECTION cs_l;
CRITICAL_SECTION cs_tl;
CRITICAL_SECTION cs_tgv;

DWORD tlsIndex;

int global = 0;

void l() {
  static int localStatic = 0;

  EnterCriticalSection(&cs_l);
  localStatic ++;
  LeaveCriticalSection(&cs_l);

  EnterCriticalSection(&cs_tgv);
  threadGlobal* tgv = 
    (threadGlobal*) TlsGetValue(tlsIndex);

  tgv->x ++;
  tgv->y ++;
  LeaveCriticalSection(&cs_tgv);


  EnterCriticalSection(&cs_out);
  cout << " l: " << localStatic << ", tgx: " << tgv->x << endl << flush;
  LeaveCriticalSection(&cs_out);
}

void g() {
  EnterCriticalSection(&cs_g);
  global++;
  LeaveCriticalSection(&cs_g);

  EnterCriticalSection(&cs_tgv);
  threadGlobal* tgv = 
    (threadGlobal*) TlsGetValue(tlsIndex);

  tgv->x ++;
  tgv->y ++;
  LeaveCriticalSection(&cs_tgv);

  EnterCriticalSection(&cs_out);
  cout << " g: " << global << ", tgx: " << tgv->x << endl << flush;
  LeaveCriticalSection(&cs_out);
}

void tg() {
  EnterCriticalSection(&cs_tgv);
  threadGlobal* tgv = 
    (threadGlobal*) TlsGetValue(tlsIndex);

  tgv->x=0;
  tgv->y=0;
  LeaveCriticalSection(&cs_tgv);
}

void tl() {
  __declspec (thread) static int threadLocalStatic = 0;

  EnterCriticalSection(&cs_tl);
  threadLocalStatic++;
  LeaveCriticalSection(&cs_tl);

  EnterCriticalSection(&cs_tgv);
  threadGlobal* tgv = 
    (threadGlobal*) TlsGetValue(tlsIndex);

  tgv->x ++;
  tgv->y ++;
  LeaveCriticalSection(&cs_tgv);

  EnterCriticalSection(&cs_out);
  cout << "tl: " << threadLocalStatic << ", tgx: " << tgv->x << endl << flush;
  LeaveCriticalSection(&cs_out);
}

unsigned int __stdcall TF(void*) {
  TlsSetValue(
    tlsIndex,
    GlobalAlloc(GPTR,sizeof(threadGlobal))
  );
 
  tg();
  l();
  g();
  tl();
  
  return 0;
}

int main(int argc, char* argv[]) {
  HANDLE hT[2];

  InitializeCriticalSection(&cs_l);
  InitializeCriticalSection(&cs_g);
  InitializeCriticalSection(&cs_tl);
  InitializeCriticalSection(&cs_tgv);
  InitializeCriticalSection(&cs_out);

  tlsIndex = TlsAlloc();

  hT[0] = (HANDLE) _beginthreadex(0,0,TF,0,0,0);
  hT[1] = (HANDLE) _beginthreadex(0,0,TF,0,0,0);

  WaitForMultipleObjects(2,hT,TRUE,INFINITE);

  DeleteCriticalSection(&cs_l );
  DeleteCriticalSection(&cs_tl);
  DeleteCriticalSection(&cs_g );
  DeleteCriticalSection(&cs_tgv);
  DeleteCriticalSection(&cs_out);


  GlobalFree(TlsGetValue(tlsIndex));
  TlsFree(tlsIndex);

	return 0;
}
The output is:
 l: 1, tgx: 1
 g: 1, tgx: 2
 l: 2, tgx: 1
 g: 2, tgx: 2
tl: 1, tgx: 3
tl: 1, tgx: 3