text: // 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__
  
  /////////////////////////////////////////////////////////////////////////////
  