386 lines
10 KiB
C
386 lines
10 KiB
C
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Microsoft Windows
|
||
|
//
|
||
|
// Copyright (C) Microsoft Corporation, 1999 - 1999
|
||
|
//
|
||
|
// File: autoptr.h
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
#ifndef AUTOPTR_H_INCLUDED
|
||
|
#define AUTOPTR_H_INCLUDED
|
||
|
|
||
|
#ifndef ASSERT
|
||
|
#ifndef _INC_CRTDBG
|
||
|
#include <crtdbg.h>
|
||
|
#endif // _INC_CRTDBG
|
||
|
#define ASSERT(x) _ASSERT(x)
|
||
|
#endif // ASSERT
|
||
|
|
||
|
#include "cpputil.h"
|
||
|
|
||
|
/*+-------------------------------------------------------------------------*
|
||
|
* CAutoResourceManagementBase
|
||
|
*
|
||
|
* This is a base class that implements common functionality for the class
|
||
|
* of smart resource handlers which release resource when it's destroyed. All
|
||
|
* classes based on this class will behave identically, except the manner
|
||
|
* in which they release their resources.
|
||
|
*
|
||
|
* DeleterClass is typically the class that derives from CAutoResourceManagementBase,
|
||
|
* and must implement
|
||
|
*
|
||
|
* static void _Delete(ResourceType h);
|
||
|
*
|
||
|
* See CAutoPtr below for an example.
|
||
|
*--------------------------------------------------------------------------*/
|
||
|
|
||
|
template<typename ResourceType, typename DeleterClass>
|
||
|
class CAutoResourceManagementBase
|
||
|
{
|
||
|
typedef CAutoResourceManagementBase<ResourceType, DeleterClass> ThisClass;
|
||
|
typedef ThisClass Releaser;
|
||
|
|
||
|
DECLARE_NOT_COPIABLE (ThisClass)
|
||
|
DECLARE_NOT_ASSIGNABLE (ThisClass)
|
||
|
|
||
|
// protected ctor so only derived classes can intantiate
|
||
|
protected:
|
||
|
explicit CAutoResourceManagementBase(ResourceType h = 0) throw() : m_hResource(h) {}
|
||
|
|
||
|
public:
|
||
|
~CAutoResourceManagementBase() throw()
|
||
|
{
|
||
|
Delete();
|
||
|
}
|
||
|
|
||
|
void Attach(ResourceType p) throw()
|
||
|
{
|
||
|
ASSERT(m_hResource == NULL);
|
||
|
m_hResource = p;
|
||
|
}
|
||
|
|
||
|
ResourceType Detach() throw()
|
||
|
{
|
||
|
ResourceType const p = m_hResource;
|
||
|
m_hResource = NULL;
|
||
|
return p;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Returns the address of the pointer contained in this class.
|
||
|
* This is useful when using the COM/OLE interfaces to create
|
||
|
* allocate the object that this class manages.
|
||
|
*/
|
||
|
ResourceType* operator&() throw()
|
||
|
{
|
||
|
/*
|
||
|
* This object must be empty now, or the data pointed to will be leaked.
|
||
|
*/
|
||
|
ASSERT (m_hResource == NULL);
|
||
|
return &m_hResource;
|
||
|
}
|
||
|
|
||
|
operator ResourceType() const throw()
|
||
|
{
|
||
|
return m_hResource;
|
||
|
}
|
||
|
|
||
|
bool operator==(int p) const throw()
|
||
|
{
|
||
|
ASSERT(p == NULL);
|
||
|
return m_hResource == NULL;
|
||
|
}
|
||
|
|
||
|
bool operator!=(int p) const throw()
|
||
|
{
|
||
|
ASSERT(p == NULL);
|
||
|
return m_hResource != NULL;
|
||
|
}
|
||
|
|
||
|
bool operator!() const throw()
|
||
|
{
|
||
|
return m_hResource == NULL;
|
||
|
}
|
||
|
|
||
|
void Delete() throw()
|
||
|
{
|
||
|
if (m_hResource != NULL)
|
||
|
{
|
||
|
DeleterClass::_Delete (m_hResource);
|
||
|
m_hResource = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
ResourceType m_hResource;
|
||
|
}; // class CAutoResourceManagementBase
|
||
|
|
||
|
|
||
|
/*+-------------------------------------------------------------------------*
|
||
|
* CAutoPtrBase
|
||
|
*
|
||
|
* This is a base class that implements common functionality for the class
|
||
|
* of smart pointers which delete its pointee when it's destroyed. All
|
||
|
* classes based on this class will behave identically, except the manner
|
||
|
* in which they destroy their pointees.
|
||
|
*
|
||
|
* DeleterClass is typically the class that derives from CAutoPtrBase, and
|
||
|
* must implement
|
||
|
*
|
||
|
* static void _Delete(T* p);
|
||
|
*
|
||
|
* This template reuses CAutoResourceManagementBase to manage the pointer
|
||
|
*
|
||
|
* See CAutoPtr below for an example.
|
||
|
*--------------------------------------------------------------------------*/
|
||
|
|
||
|
template<typename T, typename DeleterClass>
|
||
|
class CAutoPtrBase : public CAutoResourceManagementBase<T*, DeleterClass>
|
||
|
{
|
||
|
typedef CAutoPtrBase<T, DeleterClass> ThisClass;
|
||
|
typedef CAutoResourceManagementBase<T*, DeleterClass> BaseClass;
|
||
|
typedef BaseClass Releaser;
|
||
|
|
||
|
DECLARE_NOT_COPIABLE (ThisClass)
|
||
|
DECLARE_NOT_ASSIGNABLE (ThisClass)
|
||
|
|
||
|
// protected ctor so only derived classes can intantiate
|
||
|
protected:
|
||
|
explicit CAutoPtrBase(T* p = 0) throw() : BaseClass(p) {}
|
||
|
|
||
|
public:
|
||
|
|
||
|
T& operator*() const throw()
|
||
|
{
|
||
|
T* ptr = *this; // use operator defined by the BaseClass for conversion
|
||
|
ASSERT(ptr != NULL);
|
||
|
return *ptr;
|
||
|
}
|
||
|
|
||
|
T* operator->() const throw()
|
||
|
{
|
||
|
T* ptr = *this; // use operator defined by the BaseClass for conversion
|
||
|
ASSERT(ptr != NULL);
|
||
|
return ptr;
|
||
|
}
|
||
|
|
||
|
}; // class CAutoPtrBase
|
||
|
|
||
|
|
||
|
/*+-------------------------------------------------------------------------*
|
||
|
* CAutoPtr
|
||
|
*
|
||
|
* CAutoPtrBase-based class that deletes pointers allocated with
|
||
|
* operator new.
|
||
|
*--------------------------------------------------------------------------*/
|
||
|
|
||
|
template<class T>
|
||
|
class CAutoPtr : public CAutoPtrBase<T, CAutoPtr<T> >
|
||
|
{
|
||
|
typedef CAutoPtrBase<T, CAutoPtr<T> > BaseClass;
|
||
|
friend BaseClass::Releaser;
|
||
|
|
||
|
public:
|
||
|
explicit CAutoPtr(T* p = 0) throw() : BaseClass(p)
|
||
|
{}
|
||
|
|
||
|
private:
|
||
|
// only CAutoPtrBase should call this
|
||
|
static void _Delete (T* p)
|
||
|
{
|
||
|
delete p;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
/*+-------------------------------------------------------------------------*
|
||
|
* CAutoArrayPtr
|
||
|
*
|
||
|
* CAutoPtrBase-based class that deletes pointers allocated with
|
||
|
* operator new[].
|
||
|
*--------------------------------------------------------------------------*/
|
||
|
|
||
|
template<class T>
|
||
|
class CAutoArrayPtr : public CAutoPtrBase<T, CAutoArrayPtr<T> >
|
||
|
{
|
||
|
typedef CAutoPtrBase<T, CAutoArrayPtr<T> > BaseClass;
|
||
|
friend BaseClass::Releaser;
|
||
|
|
||
|
public:
|
||
|
explicit CAutoArrayPtr(T* p = 0) throw() : BaseClass(p)
|
||
|
{}
|
||
|
|
||
|
private:
|
||
|
// only CAutoPtrBase should call this
|
||
|
static void _Delete (T* p)
|
||
|
{
|
||
|
delete[] p;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
/*+-------------------------------------------------------------------------*
|
||
|
* CCoTaskMemPtr
|
||
|
*
|
||
|
* CAutoPtrBase-based class that deletes pointers allocated with
|
||
|
* CoTaskMemAlloc.
|
||
|
*--------------------------------------------------------------------------*/
|
||
|
|
||
|
template<class T>
|
||
|
class CCoTaskMemPtr : public CAutoPtrBase<T, CCoTaskMemPtr<T> >
|
||
|
{
|
||
|
typedef CAutoPtrBase<T, CCoTaskMemPtr<T> > BaseClass;
|
||
|
friend BaseClass::Releaser;
|
||
|
|
||
|
public:
|
||
|
explicit CCoTaskMemPtr(T* p = 0) throw() : BaseClass(p)
|
||
|
{}
|
||
|
|
||
|
private:
|
||
|
// only CAutoPtrBase should call this
|
||
|
static void _Delete (T* p)
|
||
|
{
|
||
|
if (p != NULL)
|
||
|
CoTaskMemFree (p);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
/*+-------------------------------------------------------------------------*
|
||
|
* CAutoGlobalPtr
|
||
|
*
|
||
|
* CAutoPtrBase-based class that deletes pointers allocated with GlobalAlloc.
|
||
|
*--------------------------------------------------------------------------*/
|
||
|
|
||
|
template<class T>
|
||
|
class CAutoGlobalPtr : public CAutoPtrBase<T, CAutoGlobalPtr<T> >
|
||
|
{
|
||
|
typedef CAutoPtrBase<T, CAutoGlobalPtr<T> > BaseClass;
|
||
|
friend BaseClass::Releaser;
|
||
|
|
||
|
public:
|
||
|
explicit CAutoGlobalPtr(T* p = 0) throw() : BaseClass(p)
|
||
|
{}
|
||
|
|
||
|
private:
|
||
|
// only CAutoPtrBase should call this
|
||
|
static void _Delete (T* p)
|
||
|
{
|
||
|
if (p != NULL)
|
||
|
GlobalFree (p);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
/*+-------------------------------------------------------------------------*
|
||
|
* CAutoLocalPtr
|
||
|
*
|
||
|
* CAutoPtrBase-based class that deletes pointers allocated with LocalAlloc.
|
||
|
*--------------------------------------------------------------------------*/
|
||
|
|
||
|
template<class T>
|
||
|
class CAutoLocalPtr : public CAutoPtrBase<T, CAutoLocalPtr<T> >
|
||
|
{
|
||
|
typedef CAutoPtrBase<T, CAutoLocalPtr<T> > BaseClass;
|
||
|
friend BaseClass::Releaser;
|
||
|
|
||
|
public:
|
||
|
explicit CAutoLocalPtr(T* p = 0) throw() : BaseClass(p)
|
||
|
{}
|
||
|
|
||
|
private:
|
||
|
// only CAutoPtrBase should call this
|
||
|
static void _Delete (T* p)
|
||
|
{
|
||
|
if (p != NULL)
|
||
|
LocalFree (p);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
/*+-------------------------------------------------------------------------*
|
||
|
* CHeapAllocMemPtr
|
||
|
*
|
||
|
* CAutoPtrBase-based class that deletes pointers allocated from the process
|
||
|
* default heap with HeapAlloc.
|
||
|
*--------------------------------------------------------------------------*/
|
||
|
|
||
|
template<class T>
|
||
|
class CHeapAllocMemPtr : public CAutoPtrBase<T, CHeapAllocMemPtr<T> >
|
||
|
{
|
||
|
typedef CAutoPtrBase<T, CHeapAllocMemPtr<T> > BaseClass;
|
||
|
friend BaseClass::Releaser;
|
||
|
|
||
|
public:
|
||
|
explicit CHeapAllocMemPtr(T* p = 0) throw() : BaseClass(p)
|
||
|
{}
|
||
|
|
||
|
private:
|
||
|
// only CAutoPtrBase should call this
|
||
|
static void _Delete (T* p)
|
||
|
{
|
||
|
if (p != NULL)
|
||
|
HeapFree(::GetProcessHeap(), 0, p);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
/*+-------------------------------------------------------------------------*
|
||
|
* CAutoWin32Handle
|
||
|
*
|
||
|
* CAutoPtrBase-based class that closes HANDLE on destruction
|
||
|
*--------------------------------------------------------------------------*/
|
||
|
class CAutoWin32Handle : public CAutoResourceManagementBase<HANDLE, CAutoWin32Handle>
|
||
|
{
|
||
|
typedef CAutoResourceManagementBase<HANDLE, CAutoWin32Handle> BaseClass;
|
||
|
friend BaseClass::Releaser;
|
||
|
|
||
|
public:
|
||
|
explicit CAutoWin32Handle(HANDLE p = NULL) throw() : BaseClass(p) {}
|
||
|
|
||
|
bool IsValid()
|
||
|
{
|
||
|
return IsValid(*this); // use base class operator to convet to HANDLE
|
||
|
}
|
||
|
private:
|
||
|
static bool IsValid (HANDLE p)
|
||
|
{
|
||
|
return (p != NULL && p != INVALID_HANDLE_VALUE);
|
||
|
}
|
||
|
// only CAutoResourceManagementBase should call this
|
||
|
static void _Delete (HANDLE p)
|
||
|
{
|
||
|
if (IsValid(p))
|
||
|
CloseHandle(p);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/*+-------------------------------------------------------------------------*
|
||
|
* CAutoAssignOnExit
|
||
|
*
|
||
|
* instances of this template class assign the value in destructor.
|
||
|
*
|
||
|
* USAGE: Say you have variable "int g_status" which must be set to S_OK before
|
||
|
* you leave the function. To do so declare following in the function:
|
||
|
*
|
||
|
* CAutoAssignOnExit<int,S_OK> any_object_name(g_status);
|
||
|
*--------------------------------------------------------------------------*/
|
||
|
template<typename T, T value>
|
||
|
class CAutoAssignOnExit
|
||
|
{
|
||
|
T& m_rVariable; // variable, which needs to be modified in destructor
|
||
|
public:
|
||
|
// constructor
|
||
|
CAutoAssignOnExit( T& rVariable ) : m_rVariable(rVariable) {}
|
||
|
// destructor
|
||
|
~CAutoAssignOnExit()
|
||
|
{
|
||
|
// assign designated final value
|
||
|
m_rVariable = value;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
#endif // AUTOPTR_H_INCLUDED
|