You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
180 lines
6.5 KiB
180 lines
6.5 KiB
#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 <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
|
|
#include "fusiontrace.h"
|
|
#include "csxspreservelasterror.h" // Most destructors should use this.
|
|
#include "fusionheap.h"
|
|
#include <typeinfo.h>
|
|
|
|
//
|
|
// 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<T>
|
|
//
|
|
|
|
template <typename T>
|
|
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 <typename T, typename /*Derived*/, typename TTypeHelper = CSmartPtrBaseTypeHelper<T> >
|
|
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 <typename T, typename TTypeHelper = CSmartPtrBaseTypeHelper<T> >
|
|
class CSmartPtr : public CSmartPtrBase<T, CSmartPtr>
|
|
{
|
|
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<T, CSmartPtr> Base;
|
|
CSmartPtr(const CSmartPtr&); // deliberately not implemented
|
|
operator=(const CSmartPtr&); // deliberately not implemented
|
|
};
|
|
|
|
template <typename T>
|
|
class CSmartArrayPtr : public CSmartPtrBase<T, CSmartArrayPtr>
|
|
{
|
|
typedef CSmartPtrBase<T, CSmartArrayPtr> 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 <typename T, void (*pfnDestructor)(T *)>
|
|
class CSmartPtrWithNamedDestructorHelper
|
|
{
|
|
public:
|
|
static void DeleteSingleton(T *pt) { CSxsPreserveLastError ple; (*pfnDestructor)(pt); ple.Restore(); }
|
|
};
|
|
|
|
template <
|
|
typename T,
|
|
void (*pfnDestructor)(T *),
|
|
typename TTypeHelper = CSmartPtrWithNamedDestructorHelper<T, pfnDestructor> >
|
|
class CSmartPtrWithNamedDestructor : public CSmartPtrBase<T, CSmartPtrWithNamedDestructor, TTypeHelper>
|
|
{
|
|
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<T, CSmartPtrWithNamedDestructor, TTypeHelper> Base;
|
|
CSmartPtrWithNamedDestructor(const CSmartPtrWithNamedDestructor &r); // deliberately not implemented
|
|
operator=(const CSmartPtrWithNamedDestructor &r); // deliberately not implemented
|
|
};
|
|
|
|
#endif // !defined(_FUSION_INC_SMARTPTR_H_INCLUDED_)
|