[zz]from msdnThread Local Storage
All threads of a process share its virtual address space. The local variables of a function are unique to each thread that runs the function. However, the static and global variables are shared by all threads in the process. With thread local storage (TLS), you can provide unique data for each thread that the process can access using a global index. One thread allocates the index, which can be used by the other threads to retrieve the unique data associated with the index.
The constant TLS_MINIMUM_AVAILABLE defines the minimum number of TLS indexes available in each process. This minimum is guaranteed to be at least 64 for all systems. The limits are as follows:
System Limit Windows XP and Windows 2000 1088 indexes per process Windows 98/Me 80 indexes per process Windows NT and Windows 95 64 indexes per processWhen the threads are created, the system allocates an array of LPVOID values for TLS, which are initialized to NULL. Before an index can be used, it must be allocated by one of the threads. Each thread stores its data for a TLS index in a TLS slot in the array. If the data associated with an index will fit in an LPVOID value, you can store the data directly in the TLS slot. However, if you are using a large number of indexes in this way, it is better to allocate separate storage, consolidate the data, and minimize the number of TLS slots in use.
The following diagram illustrates how TLS works.
The process has two threads, Thread 1 and Thread 2. It allocates two indexes for use with TLS, gdwTlsIndex1 and gdwTlsIndex2. Each thread allocates two memory blocks (one for each index) in which to store the data, and stores the pointers to these memory blocks in the corresponding TLS slots. To access the data associated with an index, the thread retrieves the pointer to the memory block from the TLS slot and stores it in the lpvData local variable.
It is ideal to use TLS in a dynamic-link library (DLL). Use the following steps to implement TLS in a DLL:
- Declare a global variable to contain the TLS index. For example: static DWORD gdwTlsIndex;
- Use the function during initialization to allocate the TLS index. For example, include the following call in the function during DLL_PROCESS_ATTACH: gdwTlsIndex = TlsAlloc();
- For each thread using the TLS index, allocate memory for the data, then use the function to store the address of the memory block in the TLS slot associated with the index. For example, include the following code in your DllMain during DLL_THREAD_ATTACH: LPVOID lpvBuffer;lpvBuffer = (LPVOID) LocalAlloc(LPTR, 256);TlsSetValue(gdwTlsIndex, lpvBuffer);
- When a function requires access to the data associated with a TLS index, specify the index in a call to the function. This retrieves the contents of the TLS slot for the calling thread, which in this case is a pointer to the memory block for the data. For example, include the following code in any of the functions in your DLL: LPVOID lpvData;lpvData = TlsGetValue(gdwTlsIndex);
- When each thread no longer needs to use a TLS index, it must free the memory whose pointer is stored in the TLS slot. When all threads have finished using a TLS index, use the function to free the index. For example, use the following code in your DllMain during DLL_THREAD_DETACH: lpvBuffer = TlsGetValue(gdwTlsIndex);LocalFree((HLOCAL) lpvBuffer);
and the following code during DLL_PROCESS_DETACH:
TlsFree(gdwTlsIndex);
For examples illustrating the use of thread local storage, see and .