ama*_*ang 4 c++ windows thread-local-storage
例如,在多线程程序中:
struct TLSObject;
void foo()
{
TLSObject* p = TlsGetValue(slot);
if (p == 0) {
p = new TLSObject;
TlsSetValue(slot, p);
}
// doing something with p
}
Run Code Online (Sandbox Code Playgroud)
第一次在任何线程中调用foo()都会创建一个新的TLSObject。
我的问题是:如何删除TLSObject(如果我不使用boost :: thread和boost :: thread_specific_ptr)?
boost :: thread_specific_ptr可以在线程退出时执行清理工作,但是我想这取决于boost :: thread,不是针对普通的OS线程,而且它很慢。
好吧。对于 Windows Vista 及更高版本,正如 James McNellis 所说 - 我们可以使用FlsCallback。
对于DLL,我们可以只使用DllMain,如果reason参数等于DLL_THREAD_DETACH,我们就进行清理。另一种方法可能是使用 _pRawDllMain,它就像另一个 DllMain 一样,您可以从boost source找到它。
对于 EXE,我们可以使用 TLS 回调,请查看 此处和此处,当然还有boost 源。实际上,它在 Windows XP 上有效,但我发现优化可能会使其无效,因此要小心优化,或者显式引用您的回调函数的指针。
将下面的代码保存到tls.cpp并将其添加到您的项目中,无论是exe还是dll,它都可以工作。请注意,对于 Windows Vista 及更高版本上的 DLL,onThreadExit 函数可能会被调用两次 - 一次来自 dll_callback,一次来自 tls_callback。
#include <windows.h>
extern void onThreadExit();
static void NTAPI tls_callback(PVOID, DWORD reason, PVOID)
{
if (reason == DLL_THREAD_DETACH) {
onThreadExit();
}
}
static BOOL WINAPI dll_callback(LPVOID, DWORD reason, LPVOID)
{
if (reason == DLL_THREAD_DETACH) {
onThreadExit();
}
return TRUE;
}
#pragma section(".CRT$XLY",long,read)
extern "C" __declspec(allocate(".CRT$XLY")) PIMAGE_TLS_CALLBACK _xl_y = tls_callback;
extern "C"
{
extern BOOL (WINAPI * const _pRawDllMain)(HANDLE, DWORD, LPVOID) = &dll_callback;
}
#pragma comment(linker, "/INCLUDE:__tls_used")
#pragma comment(linker, "/INCLUDE:__xl_y")
Run Code Online (Sandbox Code Playgroud)
如果你觉得晦涩难懂,可以使用boost的at_thread_exit,复杂性就被隐藏了。事实上上面的代码是boost tls的简化版本。如果你不想使用 boost,在 Windows 系统上这是一个替代方案。
或者,更通用的方式:thread_local。
| 归档时间: |
|
| 查看次数: |
1534 次 |
| 最近记录: |