The Windows Processes and Threads 24

 

 

 

 

 

Using Thread Local Storage Program Example

 

Thread local storage (TLS) enables multiple threads of the same process to use an index allocated by the TlsAlloc() function to store and retrieve a value that is local to the thread. In this example, an index is allocated when the process starts. When each thread starts, it allocates a block of dynamic memory and stores a pointer to this memory in the TLS slot using the TlsSetValue() function. The CommonFunc() function uses the TlsGetValue() function to access the data associated with the index that is local to the calling thread. Before each thread terminates, it releases its dynamic memory. Before the process terminates, it calls TlsFree() to release the index.

Create a new empty Win32 console application project. Give a suitable project name and change the project location if needed.

 

Using Thread Local Storage Program Example: Creating new Win32 C++ console application project in Visual C++ .NET

 

Then, add the source file and give it a suitable name.

 

Using Thread Local Storage Program Example: Adding new C++ source file for C++ source code to the existing C++ project

 

Next, add the following source code.

 

#include <windows.h>

#include <stdio.h>

 

#define THREADCOUNT 5

 

// Global variable

DWORD dwTlsIndex;

// Prototype

void ErrorExit(LPWSTR);

 

void CommonFunc(void)

{

   LPVOID lpvData;

  

   // Retrieve a data pointer for the current thread's TLS

   lpvData = TlsGetValue(dwTlsIndex);

   if ((lpvData == 0) && (GetLastError() != ERROR_SUCCESS))

         ErrorExit(L"TlsGetValue() error");

   else

         wprintf(L"TlsGetValue() is OK!\n");

  

   // Use the data stored for the current thread

   wprintf(L"common: Current thread Id is %d: Its data pointer, lpvData = %lx\n", GetCurrentThreadId(), lpvData);

 

   Sleep(5000);

}

 

DWORD WINAPI ThreadFunc(void)

{

   LPVOID lpvData;

  

   // Initialize the TLS index for this thread

   // Allocates the specified number of bytes from the heap

   lpvData = (LPVOID)LocalAlloc(LPTR, 256);

 

   if(lpvData == NULL)

         wprintf(L"LocalAlloc() failed, error %d\n", GetLastError());

   else

         wprintf(L"Heap memory has been successfully allocated!\n");

 

   if (!TlsSetValue(dwTlsIndex, lpvData))

      ErrorExit(L"TlsSetValue() error");

   else

         wprintf(L"TlsSetValue() is OK lol!\n");

 

   wprintf(L"\nThread Id %d: lpvData = %lx\n", GetCurrentThreadId(), lpvData);

 

   CommonFunc();

  

   // Release the dynamic memory before the thread returns

   lpvData = TlsGetValue(dwTlsIndex);

 

   if (lpvData != 0)

      LocalFree((HLOCAL)lpvData);

   else

         wprintf(L"lpvData already freed!\n");

 

   return 0;

}

 

int wmain(int argc, WCHAR **argv)

{

   DWORD IDThread;

   HANDLE hThread[THREADCOUNT];

   int i;

   DWORD Ret;

  

   // Allocate a TLS index

   if ((dwTlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES)

         ErrorExit(L"TlsAlloc() failed");

   else

         wprintf(L"TlsAlloc() is OK!\n");

  

   // Create multiple threads

   for (i = 0; i < THREADCOUNT; i++)

   {

      hThread[i] = CreateThread(NULL, // default security attributes

         0,                           // use default stack size

         (LPTHREAD_START_ROUTINE) ThreadFunc, // thread function

         NULL,                    // no thread function argument

         0,                       // use default creation flags

         &IDThread);              // returns thread identifier

       

        // Check the return value for success.

      if (hThread[i] == NULL)

              ErrorExit(L"CreateThread() error\n");

        else

              wprintf(L"CreateThread() #%u is OK. Thread ID is %u\n", i, IDThread);

   }

 

   for (i = 0; i < THREADCOUNT; i++)

   {

         Ret = WaitForSingleObject(hThread[i], INFINITE);

         wprintf(L"The WaitForSingleObject() return value is 0X%.8x\n", Ret);

   }

 

   if(TlsFree(dwTlsIndex) != 0)

         wprintf(L"The TLS index, dwTlsIndex was released!\n");

   else

         wprintf(L"Failed to released TLS index, dwTlsIndex, error %d\n", GetLastError());

 

   return 0;

}

 

void ErrorExit(LPWSTR lpszMessage)

{

   fwprintf_s(stderr, L"%s\n", lpszMessage);

   ExitProcess(0);

}

 

Build and run the project. The following screenshot is a sample output.

 

Using Thread Local Storage Program Example: A sample console program output in action

 

 

 

< Processes & Threads 23 | Win32 Process & Thread Programming | Win32 Programming | Processes & Threads 25 >