// This is a part of the Microsoft Foundation Classes C++ library. // Copyright (C) 1992-1995 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/process local data class CProcessLocalObject; 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... }; inline CSimpleList::CSimpleList(int nNextOffset) { m_pHead = NULL; m_nNextOffset = nNextOffset; } inline void CSimpleList::Construct(int nNextOffset) { ASSERT(m_pHead == NULL); m_nNextOffset = nNextOffset; } inline BOOL CSimpleList::IsEmpty() const { return m_pHead == NULL; } inline void** CSimpleList::GetNextPtr(void* p) const { ASSERT(p != NULL); return (void**)((BYTE*)p+m_nNextOffset); } inline void CSimpleList::RemoveAll() { m_pHead = NULL; } inline void* CSimpleList::GetHead() const { return m_pHead; } inline void* CSimpleList::GetNext(void* prevElement) const { return *GetNextPtr(prevElement); } template 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(BOOL bThreadLocal); // Operations int AllocSlot(); void FreeSlot(int nSlot); void* GetValue(int nSlot); void SetValue(int nSlot, void* pValue); void DeleteValues(HINSTANCE hInst); // delete all values in process/thread void AssignInstance(HINSTANCE hInst); // Implementation DWORD m_tlsIndex; // used if bThreadLocal == TRUE CThreadData* m_pData; // used if bThreadLocal == FALSE 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 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; } ~CThreadSlotData(); }; class 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); #endif virtual ~CNoTrackObject() { } }; class CThreadLocalObject { public: // Attributes CNoTrackObject* GetData(CNoTrackObject* (AFXAPI* pfnCreateObject)()); CNoTrackObject* GetDataNA(); // Implementation int m_nSlot; ~CThreadLocalObject(); }; class CProcessLocalObject { public: // Attributes CNoTrackObject* GetData(CNoTrackObject* (AFXAPI* pfnCreateObject)()); CNoTrackObject* GetDataNA(); // Implementation int m_nSlot; ~CProcessLocalObject(); }; template class CThreadLocal : public CThreadLocalObject { // Attributes public: inline TYPE* GetData() { TYPE* pData = (TYPE*)CThreadLocalObject::GetData(&CreateObject); ASSERT(pData != NULL); return pData; } inline TYPE* GetDataNA() { TYPE* pData = (TYPE*)CThreadLocalObject::GetDataNA(); return pData; } inline operator TYPE*() { return GetData(); } inline TYPE* operator->() { return GetData(); } // Implementation public: static CNoTrackObject* AFXAPI CreateObject() { return new TYPE; } }; #define THREAD_LOCAL(class_name, ident_name) \ AFX_DATADEF CThreadLocal ident_name; #define EXTERN_THREAD_LOCAL(class_name, ident_name) \ extern AFX_DATA THREAD_LOCAL(class_name, ident_name) template class CProcessLocal : public CProcessLocalObject { // Attributes public: inline TYPE* GetData() { TYPE* pData = (TYPE*)CProcessLocalObject::GetData(&CreateObject); ASSERT(pData != NULL); return pData; } inline TYPE* GetDataNA() { TYPE* pData = (TYPE*)CProcessLocalObject::GetDataNA(); return pData; } inline operator TYPE*() { return GetData(); } inline TYPE* operator->() { return GetData(); } // Implementation public: static CNoTrackObject* AFXAPI CreateObject() { return new TYPE; } }; #define PROCESS_LOCAL(class_name, ident_name) \ AFX_DATADEF CProcessLocal 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); void AFXAPI AfxTlsAddRef(); void AFXAPI AfxTlsRelease(); #ifdef _AFX_PACKING #pragma pack(pop) #endif #undef AFX_DATA #define AFX_DATA #endif //__AFXTLS_H__ /////////////////////////////////////////////////////////////////////////////