一、动态TLS:
a) DWORD TlsAlloc();
u 该函数使系统对进程中的位标志进行扫描,找出一个FREE标志,并转换为INUSE,返回标志的索引。如果找不到FREE标志,返回TLS_OUT_OF_INDEXES(0XFFFFFFFF)。
u 而且,如果这个索引位置已经分配了内存,会删除内存,并置0。
b) 将值放入本线程的数组中(不能放入其他线程的数组):
BOOL TlsSetValue( // 调用成功,返回TRUE
DWORD dwTlsIndex, // TlsAlloc返回值
PVOID pvTlsValue); // 任意值
c) 从线程的数组中检索一个值(仅调用线程的数组):
PVOID TlsGetValue(DWORD dwTlsIndex);
d) 当所有线程不再需要保留TLS时隙的位置时,释放:
BOOL TlsFree(DWORD dwTlsIndex);
进程的位标志数组将INUSE设置为FREE。
二、使用动态TLS:
通常,DLL在使用DLL_PROCESS_ATTACH标志调用DllMain时,调用TlsAlloc;用DLL_PROCESS_DETACH调用DllMain时调用TlsFree。例:
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
DWORD g_dwTlsIndex ; // 假设他正确使用TlsAlloc初始化
……
void MyFunc(PSOMESTRUCT pSomeStruct){
if(pSomeStruct != NULL){ // 设置值?
if(TlsGetValue(g_dwTlsIndex) == NULL){ // 查看是否已分配了空间保存数据?
// 没有分配空间
TlsSetValue(g_dwTlsIndex, HeapAlloc(GetProcessHeap(), 0, sizeof(*pSomeStruct));
}
// 此时,已经肯定分配了存储空间。保存数据
memcpy(TlsGetValue(g_dwTlsIndex), pSomeStruct, sizeof(*pSomeStruct));
} else { // 取回值
// 获取保存数据的地址
pSomeStruct = (PSOMESTRUCT)TlsGetValue(g_dwTlsIndex);
…… // 使用数据
}
}
//////////////////////////////////////////////////// End of xample ///////////////////////////////////////////////////////
三、静态TLS:(更容易使用,不需调用任何函数)
比如,你需要每个线程的起始时间:
__declspec(thread) DWORD gt_dwStartTime = 0;
u __declspec(thread)使编译时,把变量放入自己的节中(.tls节)。变量必须为函数内(外)的全局或静态变量(不能为局部变量)。
u 系统在程序或DLL加载时,查看.tls节,并为节内的数据分配内存;卸载时回收。
u 但是,运行期显示加载的DLL没有进行初始化。
u 这样会使程序变大,系统负担加重。
本文详细介绍了Windows环境下线程本地存储(TLS)的两种形式:动态TLS和静态TLS。动态TLS通过API函数实现线程特有数据的分配与释放,而静态TLS则通过编译器属性自动完成。文章还给出了具体的代码示例。
460

被折叠的 条评论
为什么被折叠?



