pomelozero的专栏

尽量少使用全局变量和静态变量,尽量用栈上变量,也可用动态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 不要用多个索引存放一个数组,不如一个索引存放一个数组指针。

只要有信心,人永远不会挫败

pomelozero的专栏

相关文章:

你感兴趣的文章:

标签云: