create tls

#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]);
    }
}
发布了25 篇原创文章 · 获赞 5 · 访问量 3215

猜你喜欢

转载自blog.csdn.net/Ellis1993/article/details/90893422
TLS