windows-nt/Source/XPSP1/NT/multimedia/directx/dplay/dnet/common/threadlocalptrs.h
2020-09-26 16:20:57 +08:00

214 lines
7.3 KiB
C

/*==========================================================================
*
* Copyright (C) 2001 Microsoft Corporation. All Rights Reserved.
*
* File: threadlocalptrs.h
* Content: Thread local pointer macros
*
* History:
* Date By Reason
* ==== == ======
* 03/21/2001 vanceo Created.
***************************************************************************/
#ifndef __THREADLOCALPTRS_H__
#define __THREADLOCALPTRS_H__
//**********************************************************************
// Structure definitions
//**********************************************************************
typedef struct _THREADLOCAL_HEADER THREADLOCAL_HEADER, * PTHREADLOCAL_HEADER;
struct _THREADLOCAL_HEADER
{
PTHREADLOCAL_HEADER pNext; // pointer to next allocated threadlocal structure header
PTHREADLOCAL_HEADER pPrev; // pointer to previous allocated threadlocal structure header
DWORD dwThreadID; // ID of thread that owns this header
//
// The actual thread local pointer structure follows this.
//
};
//**********************************************************************
// Macro definitions
//**********************************************************************
//
// Global thread local pointer declarations.
//
#define DECLARE_THREADLOCALPTRS(pointers) extern DWORD g_dw##pointers##TlsIndex;\
extern DNCRITICAL_SECTION g_csAllocated##pointers;\
extern PTHREADLOCAL_HEADER g_pAllocated##pointers;\
\
struct pointers
//
// Thread local pointer storage, define in only one location.
//
#define IMPL_THREADLOCALPTRS(pointers) DWORD g_dw##pointers##TlsIndex = -1;\
DNCRITICAL_SECTION g_csAllocated##pointers;\
PTHREADLOCAL_HEADER g_pAllocated##pointers = NULL
//
// Thread local pointer initialization, call only once (DLL_PROCESS_ATTACH),
// returns TRUE if successful, FALSE otherwise.
//
#define INIT_THREADLOCALPTRS(pointers) g_pAllocated##pointers = NULL, g_dw##pointers##TlsIndex = TlsAlloc(), ((g_dw##pointers##TlsIndex != -1) ? DNInitializeCriticalSection(&g_csAllocated##pointers) : FALSE)
//
// Total thread local pointer cleanup, call only once (DLL_PROCESS_DETACH).
//
#define DEINIT_THREADLOCALPTRS(pointers, pfnCleanup) {\
PTHREADLOCAL_HEADER pNext;\
\
\
if (g_dw##pointers##TlsIndex != -1)\
{\
DNDeleteCriticalSection(&g_csAllocated##pointers);\
\
TlsFree(g_dw##pointers##TlsIndex);\
g_dw##pointers##TlsIndex = -1;\
}\
\
while (g_pAllocated##pointers != NULL)\
{\
pNext = g_pAllocated##pointers->pNext;\
pfnCleanup((pointers *) (g_pAllocated##pointers + 1), g_pAllocated##pointers->dwThreadID);\
DNFree(g_pAllocated##pointers);\
g_pAllocated##pointers = pNext;\
}\
}
//
// Cleanup only current thread's local pointers (DLL_THREAD_DETACH).
//
#define RELEASE_CURRENTTHREAD_LOCALPTRS(pointers, pfnCleanup) {\
PTHREADLOCAL_HEADER pHeader;\
PTHREADLOCAL_HEADER pNext;\
\
\
pHeader = (PTHREADLOCAL_HEADER) TlsGetValue(g_dw##pointers##TlsIndex);\
if (pHeader != NULL)\
{\
DNEnterCriticalSection(&g_csAllocated##pointers);\
\
pNext = pHeader->pNext;\
if (pHeader->pPrev != NULL)\
{\
pHeader->pPrev->pNext = pNext;\
}\
if (pNext != NULL)\
{\
pNext->pPrev = pHeader->pPrev;\
}\
\
if (pHeader == g_pAllocated##pointers)\
{\
g_pAllocated##pointers = pNext;\
}\
\
DNLeaveCriticalSection(&g_csAllocated##pointers);\
\
DNASSERT(pHeader->dwThreadID == GetCurrentThreadId());\
pfnCleanup((pointers *) (pHeader + 1), pHeader->dwThreadID);\
DNFree(pHeader);\
}\
}
//
// Thread local pointer retrieval function.
//
#define GET_THREADLOCALPTR(pointers, name, pptr) {\
PTHREADLOCAL_HEADER pHeader;\
\
\
pHeader = (PTHREADLOCAL_HEADER) TlsGetValue(g_dw##pointers##TlsIndex);\
if (pHeader == NULL)\
{\
DPFX(DPFPREP, 9, "No header for " #name ".");\
(*pptr) = NULL;\
}\
else\
{\
DPFX(DPFPREP, 9, "Found header 0x%p, returning " #name " 0x%p.", pHeader, ((pointers *) (pHeader + 1))->name);\
(*pptr) = ((pointers *) (pHeader + 1))->name;\
}\
}
//
// Thread local pointer storage function.
//
#define SET_THREADLOCALPTR(pointers, name, ptr, pfResult) {\
PTHREADLOCAL_HEADER pHeader;\
\
\
pHeader = (PTHREADLOCAL_HEADER) TlsGetValue(g_dw##pointers##TlsIndex);\
if (pHeader == NULL)\
{\
pHeader = (PTHREADLOCAL_HEADER) DNMalloc(sizeof(THREADLOCAL_HEADER) + sizeof(pointers));\
if (pHeader == NULL)\
{\
(*pfResult) = FALSE;\
}\
else\
{\
memset(pHeader, 0, (sizeof(THREADLOCAL_HEADER) + sizeof(pointers)));\
pHeader->dwThreadID = GetCurrentThreadId();\
((pointers *) (pHeader + 1))->name = ptr;\
\
if (! TlsSetValue(g_dw##pointers##TlsIndex, pHeader))\
{\
DPFX(DPFPREP, 9, "Couldn't set thread local storage 0x%p!", pHeader);\
DNFree(pHeader);\
(*pfResult) = FALSE;\
}\
else\
{\
DPFX(DPFPREP, 9, "Setting 0x%p " #name " to 0x%p (create).", pHeader, ptr);\
\
DNEnterCriticalSection(&g_csAllocated##pointers);\
pHeader->pNext = g_pAllocated##pointers;\
if (g_pAllocated##pointers != NULL)\
{\
DNASSERT(g_pAllocated##pointers##->pPrev == NULL);\
g_pAllocated##pointers##->pPrev = pHeader;\
}\
g_pAllocated##pointers = pHeader;\
DNLeaveCriticalSection(&g_csAllocated##pointers);\
\
(*pfResult) = TRUE;\
}\
}\
}\
else\
{\
DPFX(DPFPREP, 9, "Setting 0x%p " #name " to 0x%p (existing).", pHeader, ptr);\
DNASSERT(((pointers *) (pHeader + 1))->name == NULL);\
((pointers *) (pHeader + 1))->name = ptr;\
(*pfResult) = TRUE;\
}\
}
#endif // __THREADLOCALPTRS_H__