尽量少使用全局变量和静态变量,尽量用栈上变量,也可用动态TLS和静态TLS
数据与对象实例关联起来如SetWindowWord / SetWindowLong 将数据与窗口关联起来
进程中每个线程都有TLS_MINIMUM_AVAILABLE个PVOID值的数组,,一旦一个线程预订了一个索引,进程内所有正在运行或将创建的线程都不能再使用这个索引
DWORD TlsAlloc();TlsSetValueTlsGetValueTlsFree(DWORD index);
对DLL使用TLS,TlsAlloc放在DLL_PROCESS_ATTACH,TlsFree放在DLL_PROCESS_DETACH。 而index作为全局变量,但index不能其他用处会涉及多线程问题。
// dll project
// testdll.h
#ifdef TESTDLL_EXPORTS#define TESTDLL_API __declspec(dllexport)#else#define TESTDLL_API __declspec(dllimport)#endif#include <Windows.h>
typedef struct _SomeStruct{DWORD index;DWORD tid;char buf[256];}SomeStruct,*PSomeStruct;
TESTDLL_API PSomeStruct Fun(PSomeStruct pSomeStruct);
//testdll.cpp
#include "testdll.h"#include <iostream>#include <Windows.h>
DWORD g_dwTlsIndex;BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ){switch (ul_reason_for_call){case DLL_PROCESS_ATTACH:{g_dwTlsIndex = TlsAlloc();std::cout << "case DLL_PROCESS_ATTACH: TlsAlloc:" << g_dwTlsIndex << std::endl;}break;case DLL_THREAD_ATTACH:break;case DLL_THREAD_DETACH:break;case DLL_PROCESS_DETACH:{TlsFree(g_dwTlsIndex);std::cout << "case DLL_PROCESS_DETACH: TlsFree:" << g_dwTlsIndex << std::endl;}break;}return TRUE;}
TESTDLL_API PSomeStruct Fun(PSomeStruct pSomeStruct){if( pSomeStruct != NULL ){pSomeStruct->index = g_dwTlsIndex;if( TlsGetValue(g_dwTlsIndex) == NULL ){TlsSetValue(g_dwTlsIndex,HeapAlloc(GetProcessHeap(),0,sizeof(*pSomeStruct)));}memcpy(TlsGetValue(g_dwTlsIndex),pSomeStruct,sizeof(*pSomeStruct));return NULL;}else{return (PSomeStruct)TlsGetValue(g_dwTlsIndex);}}
//test project
//main.cpp
#include <Windows.h>#include "testdll\testdll.h"#include <iostream>#include <process.h>
unsigned __stdcall SecondThreadFunc( void* pArguments )
{DWORD tid = GetCurrentThreadId();SomeStruct ss = {0,tid,""};memcpy(ss.buf,pArguments,strlen((const char*)pArguments));Fun(&ss);
while(true){PSomeStruct pget =Fun(NULL);std::cout << "tlsindex:" << pget->index << " tid:" << tid << " buf:" << pget->buf << std::endl;Sleep(2000);}
_endthreadex( 0 ); return 0;}
int wmain(int argc, wchar_t* argv[]){DWORD tid = GetCurrentThreadId();SomeStruct ss = {0,tid,"11111111"};Fun(&ss);PSomeStruct pget =Fun(NULL);std::cout << "tlsindex:" << pget->index << " tid:" << tid << " buf:" << pget->buf << std::endl;HANDLE hThread1,hThread2; unsigned threadID;char *str1 = "first thread value";char *str2 = "second thread value";hThread1 = (HANDLE)_beginthreadex( NULL, 0, SecondThreadFunc, str1, 0, &threadID );hThread2 = (HANDLE)_beginthreadex( NULL, 0, SecondThreadFunc, str2, 0, &threadID );
WaitForSingleObject( hThread1, INFINITE );WaitForSingleObject( hThread2, INFINITE );
CloseHandle( hThread1 );CloseHandle( hThread2 );return 0;}
//test result:
note: TLS 不要用多个索引存放一个数组,不如一个索引存放一个数组指针。
只要有信心,人永远不会挫败