244 lines
6.4 KiB
C
244 lines
6.4 KiB
C
|
// This is a part of the Microsoft Foundation Classes C++ library.
|
||
|
// Copyright (C) 1992-1998 Microsoft Corporation
|
||
|
// All rights reserved.
|
||
|
//
|
||
|
// This source code is only intended as a supplement to the
|
||
|
// Microsoft Foundation Classes Reference and related
|
||
|
// electronic documentation provided with the library.
|
||
|
// See these sources for detailed information regarding the
|
||
|
// Microsoft Foundation Classes product.
|
||
|
|
||
|
#ifndef __AFXTLS_H__
|
||
|
#define __AFXTLS_H__
|
||
|
|
||
|
#ifdef _AFX_PACKING
|
||
|
#pragma pack(push, _AFX_PACKING)
|
||
|
#endif
|
||
|
|
||
|
#undef AFX_DATA
|
||
|
#define AFX_DATA AFX_CORE_DATA
|
||
|
|
||
|
// Classes declared in this file
|
||
|
|
||
|
class CSimpleList;
|
||
|
class CThreadSlotData; // for manipulationg thread local storage
|
||
|
class CThreadLocalObject; // for storing thread local data
|
||
|
class CProcessLocalObject; // for storing thread local data
|
||
|
class CNoTrackObject;
|
||
|
|
||
|
// template class CTypedSimpleList<>
|
||
|
// template class CThreadLocal<>
|
||
|
// template class CProcessLocal<>
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// CSimpleList (simple/small subset of CList)
|
||
|
|
||
|
class CSimpleList
|
||
|
{
|
||
|
public:
|
||
|
CSimpleList(int nNextOffset = 0);
|
||
|
void Construct(int nNextOffset);
|
||
|
|
||
|
// Operations
|
||
|
BOOL IsEmpty() const;
|
||
|
void AddHead(void* p);
|
||
|
void RemoveAll();
|
||
|
void* GetHead() const;
|
||
|
void* GetNext(void* p) const;
|
||
|
BOOL Remove(void* p);
|
||
|
|
||
|
// Implementation
|
||
|
void* m_pHead;
|
||
|
size_t m_nNextOffset;
|
||
|
|
||
|
void** GetNextPtr(void* p) const; // somewhat trusting...
|
||
|
};
|
||
|
|
||
|
AFX_INLINE CSimpleList::CSimpleList(int nNextOffset)
|
||
|
{ m_pHead = NULL; m_nNextOffset = nNextOffset; }
|
||
|
AFX_INLINE void CSimpleList::Construct(int nNextOffset)
|
||
|
{ ASSERT(m_pHead == NULL); m_nNextOffset = nNextOffset; }
|
||
|
AFX_INLINE BOOL CSimpleList::IsEmpty() const
|
||
|
{ return m_pHead == NULL; }
|
||
|
AFX_INLINE void** CSimpleList::GetNextPtr(void* p) const
|
||
|
{ ASSERT(p != NULL); return (void**)((BYTE*)p+m_nNextOffset); }
|
||
|
AFX_INLINE void CSimpleList::RemoveAll()
|
||
|
{ m_pHead = NULL; }
|
||
|
AFX_INLINE void* CSimpleList::GetHead() const
|
||
|
{ return m_pHead; }
|
||
|
AFX_INLINE void* CSimpleList::GetNext(void* prevElement) const
|
||
|
{ return *GetNextPtr(prevElement); }
|
||
|
|
||
|
template<class TYPE>
|
||
|
class CTypedSimpleList : public CSimpleList
|
||
|
{
|
||
|
public:
|
||
|
CTypedSimpleList(int nNextOffset = 0)
|
||
|
: CSimpleList(nNextOffset) { }
|
||
|
void AddHead(TYPE p)
|
||
|
{ CSimpleList::AddHead(p); }
|
||
|
TYPE GetHead()
|
||
|
{ return (TYPE)CSimpleList::GetHead(); }
|
||
|
TYPE GetNext(TYPE p)
|
||
|
{ return (TYPE)CSimpleList::GetNext(p); }
|
||
|
BOOL Remove(TYPE p)
|
||
|
{ return CSimpleList::Remove((TYPE)p); }
|
||
|
operator TYPE()
|
||
|
{ return (TYPE)CSimpleList::GetHead(); }
|
||
|
};
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// CThreadSlotData - manages owned array of "slots" for thread local storage
|
||
|
|
||
|
struct CThreadData; // private to implementation
|
||
|
struct CSlotData; // private to implementation
|
||
|
|
||
|
class CThreadSlotData
|
||
|
{
|
||
|
public:
|
||
|
CThreadSlotData();
|
||
|
|
||
|
// Operations
|
||
|
int AllocSlot();
|
||
|
void FreeSlot(int nSlot);
|
||
|
void* GetValue(int nSlot);
|
||
|
void SetValue(int nSlot, void* pValue);
|
||
|
// delete all values in process/thread
|
||
|
void DeleteValues(HINSTANCE hInst, BOOL bAll = FALSE);
|
||
|
// assign instance handle to just constructed slots
|
||
|
void AssignInstance(HINSTANCE hInst);
|
||
|
|
||
|
// Implementation
|
||
|
DWORD m_tlsIndex; // used to access system thread-local storage
|
||
|
|
||
|
int m_nAlloc; // number of slots allocated (in UINTs)
|
||
|
int m_nRover; // (optimization) for quick finding of free slots
|
||
|
int m_nMax; // size of slot table below (in bits)
|
||
|
CSlotData* m_pSlotData; // state of each slot (allocated or not)
|
||
|
CTypedSimpleList<CThreadData*> m_list; // list of CThreadData structures
|
||
|
CRITICAL_SECTION m_sect;
|
||
|
|
||
|
void* GetThreadValue(int nSlot); // special version for threads only!
|
||
|
void* PASCAL operator new(size_t, void* p)
|
||
|
{ return p; }
|
||
|
void DeleteValues(CThreadData* pData, HINSTANCE hInst);
|
||
|
~CThreadSlotData();
|
||
|
};
|
||
|
|
||
|
class AFX_NOVTABLE CNoTrackObject
|
||
|
{
|
||
|
public:
|
||
|
void* PASCAL operator new(size_t nSize);
|
||
|
void PASCAL operator delete(void*);
|
||
|
|
||
|
#if defined(_DEBUG) && !defined(_AFX_NO_DEBUG_CRT)
|
||
|
void* PASCAL operator new(size_t nSize, LPCSTR, int);
|
||
|
#if (_MSC_VER >= 1200) && (_MFC_VER >= 0x0600)
|
||
|
void PASCAL operator delete(void* pObject, LPCSTR, int);
|
||
|
#endif
|
||
|
#endif
|
||
|
virtual ~CNoTrackObject() { }
|
||
|
};
|
||
|
|
||
|
class AFX_NOVTABLE CThreadLocalObject
|
||
|
{
|
||
|
public:
|
||
|
// Attributes
|
||
|
CNoTrackObject* GetData(CNoTrackObject* (AFXAPI* pfnCreateObject)());
|
||
|
CNoTrackObject* GetDataNA();
|
||
|
|
||
|
// Implementation
|
||
|
int m_nSlot;
|
||
|
~CThreadLocalObject();
|
||
|
};
|
||
|
|
||
|
class AFX_NOVTABLE CProcessLocalObject
|
||
|
{
|
||
|
public:
|
||
|
// Attributes
|
||
|
CNoTrackObject* GetData(CNoTrackObject* (AFXAPI* pfnCreateObject)());
|
||
|
|
||
|
// Implementation
|
||
|
CNoTrackObject* volatile m_pObject;
|
||
|
~CProcessLocalObject();
|
||
|
};
|
||
|
|
||
|
template<class TYPE>
|
||
|
class CThreadLocal : public CThreadLocalObject
|
||
|
{
|
||
|
// Attributes
|
||
|
public:
|
||
|
AFX_INLINE TYPE* GetData()
|
||
|
{
|
||
|
TYPE* pData = (TYPE*)CThreadLocalObject::GetData(&CreateObject);
|
||
|
ASSERT(pData != NULL);
|
||
|
return pData;
|
||
|
}
|
||
|
AFX_INLINE TYPE* GetDataNA()
|
||
|
{
|
||
|
TYPE* pData = (TYPE*)CThreadLocalObject::GetDataNA();
|
||
|
return pData;
|
||
|
}
|
||
|
AFX_INLINE operator TYPE*()
|
||
|
{ return GetData(); }
|
||
|
AFX_INLINE TYPE* operator->()
|
||
|
{ return GetData(); }
|
||
|
|
||
|
// Implementation
|
||
|
public:
|
||
|
static CNoTrackObject* AFXAPI CreateObject()
|
||
|
{ return new TYPE; }
|
||
|
};
|
||
|
|
||
|
#define THREAD_LOCAL(class_name, ident_name) \
|
||
|
AFX_DATADEF CThreadLocal<class_name> ident_name;
|
||
|
#define EXTERN_THREAD_LOCAL(class_name, ident_name) \
|
||
|
extern AFX_DATA THREAD_LOCAL(class_name, ident_name)
|
||
|
|
||
|
template<class TYPE>
|
||
|
class CProcessLocal : public CProcessLocalObject
|
||
|
{
|
||
|
// Attributes
|
||
|
public:
|
||
|
AFX_INLINE TYPE* GetData()
|
||
|
{
|
||
|
TYPE* pData = (TYPE*)CProcessLocalObject::GetData(&CreateObject);
|
||
|
ASSERT(pData != NULL);
|
||
|
return pData;
|
||
|
}
|
||
|
AFX_INLINE TYPE* GetDataNA()
|
||
|
{ return (TYPE*)m_pObject; }
|
||
|
AFX_INLINE operator TYPE*()
|
||
|
{ return GetData(); }
|
||
|
AFX_INLINE TYPE* operator->()
|
||
|
{ return GetData(); }
|
||
|
|
||
|
// Implementation
|
||
|
public:
|
||
|
static CNoTrackObject* AFXAPI CreateObject()
|
||
|
{ return new TYPE; }
|
||
|
};
|
||
|
|
||
|
#define PROCESS_LOCAL(class_name, ident_name) \
|
||
|
AFX_DATADEF CProcessLocal<class_name> ident_name;
|
||
|
#define EXTERN_PROCESS_LOCAL(class_name, ident_name) \
|
||
|
extern AFX_DATA PROCESS_LOCAL(class_name, ident_name)
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
void AFXAPI AfxInitLocalData(HINSTANCE hInstInit);
|
||
|
void AFXAPI AfxTermLocalData(HINSTANCE hInstTerm, BOOL bAll = FALSE);
|
||
|
void AFXAPI AfxTlsAddRef();
|
||
|
void AFXAPI AfxTlsRelease();
|
||
|
|
||
|
#ifdef _AFX_PACKING
|
||
|
#pragma pack(pop)
|
||
|
#endif
|
||
|
|
||
|
#undef AFX_DATA
|
||
|
#define AFX_DATA
|
||
|
|
||
|
#endif //__AFXTLS_H__
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|