#if !defined(_FUSION_INC_SMARTPTR_H_INCLUDED_) #define _FUSION_INC_SMARTPTR_H_INCLUDED_ /*++ Copyright (c) Microsoft Corporation Module Name: smartptr.h Abstract: Author: Jay Krell (a-JayK, JayKrell) October 2000 Revision History: --*/ #pragma once #include #include #include #include "fusiontrace.h" #include "csxspreservelasterror.h" // Most destructors should use this. #include "fusionheap.h" #include // // Need to flesh this out. // See \\cpvsbuild\Drops\v7.0\raw\current\vs\src\VSEE\lib\Memory\*Pointer*. // // // Split off into ATL style Base/TDerived to avoid compiler ICE; // Otherwise was void (*Delete)(T*) = SxsDelete // template class CSmartPtrBaseTypeHelper { public: #if DBG #define SXS_TYPE_NAME(t) (typeid(T).name()) #else #define SXS_TYPE_NAME(t) ("") #endif // DBG static T *AllocateSingleton(PCSTR pszFileName, int nLine) { return new(pszFileName, nLine, SXS_TYPE_NAME(T)) T; } static T *AllocateArray(SIZE_T n, PCSTR pszFileName, int nLine) { return new(pszFileName, nLine, SXS_TYPE_NAME(T)) T[n]; } #undef SXS_TYPE_NAME static void DeleteSingleton(T *pt) { CSxsPreserveLastError ple; delete pt; ple.Restore(); } static void DeleteArray(T *pt) { CSxsPreserveLastError ple; delete []pt; ple.Restore(); } }; // // Derived is never used. This is may be by accident or by design. // template > class CSmartPtrBase { typedef T *TPtr; typedef T const *TConstPtr; public: CSmartPtrBase() : m_p(NULL), m_fDelete(false) { } ~CSmartPtrBase() { ASSERT_NTC(m_p == NULL); } operator TPtr () { return m_p; } operator TConstPtr () const { return m_p; } TPtr *operator&() { ASSERT_NTC(m_p == NULL); m_fDelete = true; return &m_p; } TPtr operator->() { return m_p; } TConstPtr operator->() const { return m_p; } // this stores null in m_p and returns its previous value TPtr Detach() { T *p = m_p; m_p = NULL; m_fDelete = false; return p; } TPtr DetachAndHold() { m_fDelete = false; return m_p; } void FinalizeSingletonBase() { if (m_p != NULL) { if (m_fDelete) TTypeHelper::DeleteSingleton(m_p); m_p = NULL; } } void FinalizeArrayBase() { if (m_p != NULL) { if (m_fDelete) TTypeHelper::DeleteArray(m_p); m_p = NULL; } } protected: T* m_p; bool m_fDelete; void AttachForDeleteBase(T *p) { ASSERT_NTC(m_p == NULL); if (m_p == NULL) { m_p = p; m_fDelete = true; } } void AttachNoDeleteBase(T *p) { ASSERT_NTC(m_p == NULL); if (m_p == NULL) { m_p = p; m_fDelete = false; } } BOOL Win32AllocateSingletonBase(PCSTR pszFileName, int nLine) { BOOL fSuccess = FALSE; ASSERT_NTC(m_p == NULL); if ((m_p = TTypeHelper::AllocateSingleton(pszFileName, nLine)) == NULL) goto Exit; m_fDelete = true; fSuccess = TRUE; Exit: return fSuccess; } BOOL Win32AllocateArrayBase(SIZE_T n, PCSTR pszFileName, int nLine) { FN_PROLOG_WIN32 INTERNAL_ERROR_CHECK(m_p == NULL); IFALLOCFAILED_EXIT(m_p = TTypeHelper::AllocateArray(n, pszFileName, nLine)); m_fDelete = true; FN_EPILOG } static void DeleteSingleton(T *p) { TTypeHelper::DeleteSingleton(p); } static void DeleteArray(T *p) { TTypeHelper::DeleteArray(p); } private: CSmartPtrBase(const CSmartPtrBase&); // deliberately not implemented void operator=(const CSmartPtrBase&); // deliberately not implemented }; template > class CSmartPtr : public CSmartPtrBase { public: CSmartPtr() : Base() { } ~CSmartPtr() { if (m_p != NULL) { if (m_fDelete) Base::DeleteSingleton(m_p); m_p = NULL; } } CSmartPtr &AttachForDelete(T* p) { Base::AttachForDeleteBase(p); return *this; } CSmartPtr &AttachNoDelete(T* p) { Base::AttachNoDeleteBase(p); return *this; } bool operator ==(const CSmartPtr &r) const { return m_p == r.m_p; } BOOL Win32Allocate(PCSTR pszFileName, int nLine) { return Base::Win32AllocateSingletonBase(pszFileName, nLine); } private: typedef CSmartPtrBase Base; CSmartPtr(const CSmartPtr&); // deliberately not implemented operator=(const CSmartPtr&); // deliberately not implemented }; template class CSmartArrayPtr : public CSmartPtrBase { typedef CSmartPtrBase Base; public: CSmartArrayPtr() : Base() { } ~CSmartArrayPtr() { if (m_p != NULL) { if (m_fDelete) Base::DeleteArray(m_p); m_p = NULL; } } CSmartArrayPtr &AttachForDelete(T *p) { Base::AttachForDelete(p); return *this; } CSmartArrayPtr &AttachNoDelete(T *p) { Base::AttachNoDelete(p); return *this; } bool operator ==(const CSmartArrayPtr &r) const { return m_p == r.m_p; } bool operator ==(T *prgt) const { return m_p == prgt; } BOOL Win32Allocate(SIZE_T n, PCSTR pszFileName, int nLine) { return Base::Win32AllocateArrayBase(n, pszFileName, nLine); } private: CSmartArrayPtr(const CSmartArrayPtr &); void operator =(const CSmartArrayPtr &); }; template class CSmartPtrWithNamedDestructorHelper { public: static void DeleteSingleton(T *pt) { CSxsPreserveLastError ple; (*pfnDestructor)(pt); ple.Restore(); } }; template < typename T, void (*pfnDestructor)(T *), typename TTypeHelper = CSmartPtrWithNamedDestructorHelper > class CSmartPtrWithNamedDestructor : public CSmartPtrBase { public: CSmartPtrWithNamedDestructor() : Base() { } ~CSmartPtrWithNamedDestructor() { if (m_p != NULL) { if (m_fDelete) Base::DeleteSingleton(m_p); m_p = NULL; } } CSmartPtrWithNamedDestructor &AttachForDelete(T* p) { Base::AttachForDeleteBase(p); return *this; } CSmartPtrWithNamedDestructor &AttachNoDelete(T* p) { Base::AttachNoDeleteBase(p); return *this; } bool operator ==(const CSmartPtrWithNamedDestructor &r) const { return m_p == r.m_p; } BOOL Win32Allocate(PCSTR pszFileName, int nLine) { return Base::Win32AllocateSingletonBase(pszFileName, nLine); } void Finalize() { Base::FinalizeSingletonBase(); } private: typedef CSmartPtrBase Base; CSmartPtrWithNamedDestructor(const CSmartPtrWithNamedDestructor &r); // deliberately not implemented operator=(const CSmartPtrWithNamedDestructor &r); // deliberately not implemented }; #endif // !defined(_FUSION_INC_SMARTPTR_H_INCLUDED_)