#ifndef _AFXTLS_H_
#define _AFXTLS_H_
#include <windows.h>
class CNoTrackObject // new delete 从堆中申请内存
{
public:
//CNoTrackObject();
virtual ~CNoTrackObject()
{
}
void* operator new(size_t nsize)
{
void* p = GlobalAlloc(GPTR, nsize);
return p;
}
void operator delete(void *p)
{
if (nullptr != p)
{
GlobalFree(p);
}
}
private:
};
struct CThreadData: public CNoTrackObject //生成一个ThreadData
{
public:
CThreadData* m_pNext;
int m_NCount;
LPVOID* m_data;
CThreadData()
{
m_pNext = nullptr;
m_NCount = 0;
m_data = nullptr;
}
};
struct CSlotData
{
DWORD dwFlags;
HINSTANCE hInst;
};
class CSimpleList
{
public:
CSimpleList(int NextSize = 0);
~CSimpleList();
void Construcr(int NextSizeoffset);
BOOL IsEmpty() const;
void AddHead(void *p);
void RemoveAll();
void* GetHead() const;
void* GetNext(void *p)const;
BOOL Remove(void *p);
private:
void* m_pHead;
size_t m_NextOffset;
void** GetNextPrt(void *p) const;
};
template <class TYPE>
class CTypeSimpleList :public CSimpleList
{
public:
CTypeSimpleList(int NextSize = 0) :CSimpleList(NextSize)
{
}
void AddHead(TYPE p);
TYPE GetHead();
TYPE GetNext(TYPE p);
BOOL Remove(TYPE p);
operator TYPE()
{
return (TYPE)(CSimpleList::GetHead());
}
};
template<class TYPE>
void CTypeSimpleList<TYPE>::AddHead(TYPE p)
{
AddHead((void*)p);
}
template<class TYPE>
TYPE CTypeSimpleList<TYPE>::GetHead()
{
return (TYPE)(CSimpleList::GetHead());
}
template<class TYPE>
TYPE CTypeSimpleList<TYPE>::GetNext(TYPE p)
{
return (TYPE)(CSimpleList::GetNext((void*)p));
}
template<class TYPE>
BOOL CTypeSimpleList<TYPE>::Remove(TYPE p)
{
return (TYPE)(CSimpleList::Remove((void*)p));
}
class CThreadSlotData
{
public:
CThreadSlotData();
//提供给用户接口
int AllocSlot();
void FreeSlot(int nSlot);
void SetValue(int nSlot, void* pValue);
void DeleteValue(HINSTANCE hInst, BOOL IsAll = FALSE);
void* GetThreadValue(int nslot);
//private:
DWORD m_tlsIndex;
int m_nAlloc; //pslotdata array size
int m_nRecover;
int m_nMax;
CSlotData* m_pSlotData;
CTypeSimpleList<CThreadData*> m_list;
CRITICAL_SECTION m_cs;
void* operator new(size_t nsize, void *p)
{
return p;
}
void DeleteValues(CThreadData* pData, HINSTANCE hinst);
~CThreadSlotData();
};
typedef CNoTrackObject* (*fnCreateObject)();
class CThreadLocalObject
{
public:
CNoTrackObject* GetData(fnCreateObject pfnCreateObject);
CNoTrackObject* GetDataNA();
DWORD m_nslot;
~CThreadLocalObject();
};
template<class TYPE>
class CThreadLocal : public CThreadLocalObject
{
public:
TYPE* GetData()
{
fnCreateObject lpfnCreateObject = (fnCreateObject)CreateObject;
TYPE* pData = (TYPE*)CThreadLocalObject::GetData(&lpfnCreateObject);
return pData;
}
TYPE* GetDataNA()
{
TYPE* pData = (TYPE*)CThreadLocalObject::GetDataNA();
return pData;
}
operator TYPE*()
{
return GetData();
}
TYPE* operator->()
{
return GetData();
}
static LPVOID CreateObject()
{
return new TYPE;
}
};
struct CMyThreadData: public CNoTrackObject
{
int m_nslotdata;
};
void CreateThreadCount();
#endif
#include "ctls.h"
#include "common.h"
BYTE __AfxThreadData[sizeof(CThreadSlotData)];
CThreadSlotData* _AfxThreadData;
const int SLOT_USED = 0x01;
CSimpleList::CSimpleList(int NextOffset)
{
m_pHead = nullptr;
m_NextOffset = NextOffset;
}
void CSimpleList::Construcr(int NextSizeoffset)
{
m_NextOffset = NextSizeoffset;
}
CSimpleList::~CSimpleList()
{
}
BOOL CSimpleList::IsEmpty() const
{
if (m_pHead)
{
return FALSE;
}
return TRUE;
}
void* CSimpleList::GetHead() const
{
return m_pHead;
}
void* CSimpleList::GetNext(void* p) const
{
return *GetNextPrt(p);
}
void CSimpleList::RemoveAll()
{
m_pHead = nullptr;
}
void** CSimpleList::GetNextPrt(void *p) const
{
return (void**)((BYTE*)p + m_NextOffset);
}
void CSimpleList::AddHead(void *p)
{
*GetNextPrt(p) = m_pHead;
m_pHead = p;
}
BOOL CSimpleList::Remove(void *p)
{
if (!p)
{
return FALSE;
}
if (p == m_pHead)
{
m_pHead = *(GetNextPrt(p));
}
else
{
void* PTest = m_pHead;
while (PTest != NULL && p !=(GetNext(PTest)))
{
PTest = GetNext(PTest);
}
if (PTest)
{
*GetNextPrt(PTest) = *(GetNextPrt(p));
return FALSE;
}
}
return FALSE;
}
//
CThreadSlotData::CThreadSlotData()
{
m_list.Construcr(offsetof(CThreadData, m_pNext));
m_nMax = 0;
m_nAlloc = 0;
m_nRecover = 1;
m_pSlotData = nullptr;
m_tlsIndex = TlsAlloc();
InitializeCriticalSection(&m_cs);
}
int CThreadSlotData::AllocSlot()
{
EnterCriticalSection(&m_cs);
int nalloc = m_nAlloc;
int nslot = m_nRecover;
if (nslot >= nalloc || m_pSlotData[nslot].dwFlags & SLOT_USED)
{
for (nslot =1; nslot < nalloc && m_pSlotData[nslot].dwFlags& SLOT_USED; ++nslot)
{
}
if (nslot >= nalloc)
{
//增加全局数组的大小
int nNewAlloc = nalloc + 32;
HGLOBAL hslotdata;
if (m_pSlotData == nullptr)
{
hslotdata = GlobalAlloc(GMEM_MOVEABLE, nNewAlloc * sizeof(CSlotData));
}
else
{
hslotdata = GlobalHandle(m_pSlotData);
GlobalUnlock(hslotdata);
hslotdata = GlobalReAlloc(m_pSlotData, nNewAlloc * sizeof(CSlotData), GMEM_MOVEABLE);
}
CSlotData* pslotdata = (CSlotData*)::GlobalLock(hslotdata);
memset(pslotdata + m_nAlloc, 0, (nNewAlloc - m_nAlloc)*(sizeof(CSlotData)));
m_nAlloc = nNewAlloc;
m_pSlotData = pslotdata;
}
}
if (nslot >= m_nAlloc)
{
m_nMax = nslot + 1;
}
m_pSlotData[nslot].dwFlags = SLOT_USED;
m_nRecover = nslot + 1;
LeaveCriticalSection(&m_cs);
return nslot;
}
void* CThreadSlotData::GetThreadValue(int nslot)
{
CThreadData* pdata = (CThreadData*)TlsGetValue(m_tlsIndex);
if (pdata == nullptr || nslot >= pdata->m_NCount)
{
return nullptr;
}
return pdata->m_data[nslot];
}
void CThreadSlotData::FreeSlot(int nSlot)
{
EnterCriticalSection(&m_cs);
CThreadData* pData = m_list;
while (pData != NULL)
{
if (nSlot < pData->m_NCount)
{
delete (CNoTrackObject*)pData->m_data[nSlot];
pData->m_data[nSlot] = nullptr;
}
pData = pData->m_pNext;
}
m_pSlotData[nSlot].dwFlags = ~SLOT_USED;
LeaveCriticalSection(&m_cs);
}
void CThreadSlotData::SetValue(int nSlot, void* pValue)
{
CThreadData* pData = (CThreadData*)TlsGetValue(m_tlsIndex);
if (pData == nullptr ||nSlot >= pData->m_NCount && pValue != nullptr)
{
if (nullptr == pData)
{
pData = new CThreadData;
pData->m_NCount = 0;
pData->m_pNext = nullptr;
EnterCriticalSection(&m_cs);
m_list.AddHead(pData);
LeaveCriticalSection(&m_cs);
}
if (pData->m_data == nullptr)
{
pData->m_data = (void**)GlobalAlloc(LMEM_FIXED, m_nMax * sizeof(LPVOID));
}
else
{
pData->m_data = (void**)GlobalReAlloc(pData->m_data, m_nMax * sizeof(LPVOID), LMEM_MOVEABLE);
}
memset(pData->m_data + pData->m_NCount, 0, (m_nMax - pData->m_NCount) * sizeof(LPVOID));
pData->m_NCount = m_nMax;
TlsSetValue(m_tlsIndex, pData);
}
pData->m_data[nSlot] = pValue;
pData->m_data[nSlot] = pValue;
}
void CThreadSlotData::DeleteValue(HINSTANCE hInst, BOOL IsAll/* = FALSE*/)
{
EnterCriticalSection(&m_cs);
if (IsAll)
{
CThreadData* pData = (CThreadData*)(TlsGetValue(m_tlsIndex));
if (pData != nullptr)
{
DeleteValues(pData, hInst);
}
}
else
{
CThreadData* pData = (CThreadData*)(m_list.GetHead());
while (pData != nullptr)
{
CThreadData* pNext = pData->m_pNext;
DeleteValues(pData, hInst);
pData = pNext;
}
}
LeaveCriticalSection(&m_cs);
}
void CThreadSlotData::DeleteValues(CThreadData* pData, HINSTANCE hinst)
{
EnterCriticalSection(&m_cs);
BOOL IsDelete = TRUE;
for (auto i = 0; i < pData->m_NCount; ++i)
{
if (hinst != nullptr && m_pSlotData[i].hInst == hinst)
{
delete (CNoTrackObject*)pData->m_data;
pData->m_data = nullptr;
}
else
{
if (pData->m_data[i] != nullptr)
{
IsDelete = FALSE;
}
}
}
LeaveCriticalSection(&m_cs);
if (IsDelete)
{
EnterCriticalSection(&m_cs);
m_list.Remove(pData);
LeaveCriticalSection(&m_cs);
LocalFree(pData->m_data);
delete pData;
TlsSetValue(m_tlsIndex, nullptr);
}
}
CThreadSlotData::~CThreadSlotData()
{
CThreadData* pData = m_list;
while (pData != nullptr)
{
CThreadData* pNext = pData->m_pNext;
DeleteValues(pData, nullptr);
pData = pNext;
}
if (m_tlsIndex != DWORD(-1))
{
TlsFree(m_tlsIndex);
}
if (m_pSlotData != nullptr)
{
HGLOBAL hSlotData = GlobalHandle(m_pSlotData);
GlobalUnlock(hSlotData);
GlobalFree(m_pSlotData);
}
DeleteCriticalSection(&m_cs);
}
CNoTrackObject* CThreadLocalObject::GetData(fnCreateObject pfnCreateObject)
{
if (0 == m_nslot)
{
if (_AfxThreadData ==nullptr)
{
_AfxThreadData = new (__AfxThreadData)CThreadSlotData;
}
m_nslot = _AfxThreadData->AllocSlot();
}
CNoTrackObject* pValue = (CNoTrackObject*)_AfxThreadData->GetThreadValue(m_nslot);
if (nullptr == pValue)
{
pValue = (*pfnCreateObject)();
_AfxThreadData->SetValue(m_nslot, pValue);
}
return pValue;
}
CNoTrackObject* CThreadLocalObject::GetDataNA()
{
if (m_nslot == 0 || _AfxThreadData == 0)
{
return nullptr;
}
return (CNoTrackObject*)_AfxThreadData->GetThreadValue(m_nslot);
}
CThreadLocalObject::~CThreadLocalObject()
{
if (m_nslot!= 0 && _AfxThreadData != nullptr)
{
_AfxThreadData->FreeSlot(m_nslot);
}
m_nslot = 0;
}
//THREAD_LOCAL(CMyThreadData, g_myThreadData)
CThreadLocal<CMyThreadData> g_MyThreadData;
void ShowData()
{
cout << "Thread ID" << g_MyThreadData->m_nslotdata << endl;
}
UINT _stdcall ThreadFun(LPVOID lparam)
{
g_MyThreadData->m_nslotdata = (int)lparam;
ShowData();
return 0;
}
void CreateThreadCount()
{
HANDLE h_hand[10];
UINT uid;
for (auto i = 0; i < 10; ++i)
{
_beginthreadex(nullptr, 0, ThreadFun, (void*)i, 0, &uid);
}
WaitForMultipleObjects(10, h_hand, TRUE, INFINITE);
for (auto i = 0; i < 10; ++i)
{
CloseHandle(h_hand[i]);
}
}