2025-11-27 16:46:48 +09:00

382 lines
13 KiB
C++

// ==========================================================================
// Template Specification : COXSPtr
// ==========================================================================
// Header file : OXSPtr.h
// //////////////////////////////////////////////////////////////////////////
// Properties:
// NO Abstract class (does not have any objects)
// NO Derived from
// NO Is a Cwnd.
// NO Two stage creation (constructor & Create())
// NO Has a message map
// NO Needs a resource (template)
// NO Persistent objects (saveable on disk)
// YES Uses exceptions
// (CMemoryException by NULL-pointer dereference)
// //////////////////////////////////////////////////////////////////////////
// Desciption :
// This class works together with CObject derived classesto provide
// a solution for smart pointers and objects
// All access to the object must be done through its smart pointer
// Normally construction of the object is done together with the
// smart pointer. So when a smart pointer is constructed it also constructs
// the object
// When you specify NULL as parameter when construcing a smart pointer
// it will not construct an object
// The lifetime of objects is ruled by reference counting
// When no references to the object exists it will be deleted.
// You can remove the reference to an object explicitely by assigning
// NULL to the smart pointer
// You can also construct a new object explicitely by assigning the special value
// NEW_OBJECT to it.
// Apart from construction and destruction everything that can be done with a
// normal (dumb) pointer can also be done with a smart pointer
// Remark:
// The runtime overhead of using a smart pointer instead of a dumb pointer
// are very minimal
// COXSPtr is a class with no base class and no virtual functions
// The size of a smart pointer thus equals the size of its members :
// two pointer (to the object and to the reference count).
// All access functions of COXSPtr are inline and are very short.
// E.g. operator-> just checks whether the pointer is not NULL
// and returns it then
// So computational overhead is minimal too.
// When you try to dereference a smart pointer that is NULL
// a CMemoryException will be thrown (and in DEBUG the function will ASSERT)
// Prerequisites (necessary conditions):
//
/////////////////////////////////////////////////////////////////////////////
#ifndef __OXSPTR_H__
#define __OXSPTR_H__
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#include "OXDllExt.h"
// Defining ENABLE_SMART_WRAPPER enables the possibility to wrap a smart pointer
// around an existing object. The locking functions are also available then.
// By default this is not defined and thus not enabled
// #define ENABLE_SMART_WRAPPER 1
// Defining DISABLE_SMART_DOWNCAST_TEST disnables the runtime test when a
// smart pointer is downcasted (from base class to derived class)
// By default this is not defined and thus enabled
// #define DISABLE_SMART_DOWNCAST_TEST 1
// Defining DISABLE_SMART_SERIALIZATION disnables the serialization functionality
// of a smart pointer (and groups)
// By default this is not defined and thus enabled
// #define DISABLE_SMART_SERIALIZATION 1
// Defining DISABLE_SMART_CHECK disables the runtime checks during Debug
// These checks include wrapping a smart pointer around an existing object,
// a smart pointer around a steck based object and cyclic graphs.
// By default this is not defined and thus enabled
// #define DISABLE_SMART_CHECK 1
// Use special creator object (NEW_OBJECT) that can be used in the
// constructor and assignment operator of a smart pointer
// to construct a new object
class OX_CLASS_DECL COXObjectCreator
{
// This class is only used to mark a special parameter
// during construction or assignment of a smart pointer
// No actual members are needed
};
extern OX_CLASS_DECL COXObjectCreator NEW_OBJECT;
template <class T> class OX_CLASS_DECL COXSPtr;
#ifndef DISABLE_SMART_SERIALIZATION
template <class T> CArchive& AFXAPI operator<<(CArchive& ar, const COXSPtr<T>& pSObj);
template <class T> CArchive& AFXAPI operator>>(CArchive& ar, COXSPtr<T>& pSObj);
#endif // DISABLE_SMART_SERIALIZATION
template <class T> class OX_CLASS_DECL COXSPtr
{
// Data members -------------------------------------------------------------
public:
protected:
T* m_pSmartObject;
LONG* m_pnReferenceCount;
private:
// Member functions ---------------------------------------------------------
public:
COXSPtr(const COXObjectCreator& objCreator = NEW_OBJECT);
// --- In : objCreator : NEW_OBJECT : Creates a new object
// --- Out :
// --- Returns :
// --- Effect : This constructs a smart pointer and it also
// creates the associated object
// This is the default constructor
// The only valid parameter is NEW_OBJECT
#ifndef ENABLE_SMART_WRAPPER
COXSPtr(const COXObjectCreator* pNull);
// --- In : pNull : NULL
// --- Out :
// --- Returns :
// --- Effect : This constructs a smart NULL pointer
// The only valid parameter is NULL
#else
COXSPtr(T* pSObj);
// --- In : pSObj : Pointer to the object
// around which this smart pointer will be created
// or NULL : Makes this a NULL-pointer
// --- Out :
// --- Returns :
// --- Effect : This constructs a smart pointer around an existing
// object or constructs a smart NULL pointer
// The object's lifetime is now decided by the smart pointer
// You should not delete the object directly
#endif // ENABLE_SMART_WRAPPER
COXSPtr(const COXSPtr& sPtr);
// --- In : sPtr : The smart pointer to be copied
// --- Out :
// --- Returns :
// --- Effect : Copy constructor
COXSPtr& operator=(const COXSPtr<T>& sPtr);
// --- In : sPtr : A smart pointer
// --- Out :
// --- Returns :
// --- Effect : Assignment operator
COXSPtr& operator=(const COXObjectCreator& objCreator);
// --- In : objCreator : NEW_OBJECT
// --- Out :
// --- Returns :
// --- Effect : Constructs a new object and assigns it to this smart pointer
// The only valid parameter is NEW_OBJECT
#ifndef ENABLE_SMART_WRAPPER
COXSPtr& operator=(const COXObjectCreator* pNull);
// --- In : pNull : NULL
// --- Out :
// --- Returns :
// --- Effect : Makes this smart pointer a smart NULL pointer
// The only valid parameter is NULL
#else
COXSPtr& operator=(T* pSObj);
// --- In : pSObj : A pointer to the object or NULL
// --- Out :
// --- Returns :
// --- Effect : Assignment operator
// If pSObj == NULL this smart pointer becomes a smart NULL pointer
// The object's lifetime is now decided by the smart pointer
// You should not delete the object directly
#endif // ENABLE_SMART_WRAPPER
T& operator*() const;
// throw(CMemoryException);
// --- In :
// --- Out :
// --- Returns : The object pointed to
// --- Effect : Dereference operator
T* operator->() const;
// throw(CMemoryException);
// --- In :
// --- Out :
// --- Returns : Pointer to the object
// --- Effect : Member operator
operator T*() const;
// --- In :
// --- Out :
// --- Returns :
// --- Effect : Conversion operator
BOOL operator!() const;
// --- In :
// --- Out :
// --- Returns : Whether this pointer points to NULL (TRUE) or to
// a valid object (FALSE)
// --- Effect :
BOOL operator==(T* pSObj) const;
// --- In : pSObj : Pointer to a smart element
// --- Out :
// --- Returns : Whether this pointer points to the specified
// object
// --- Effect :
BOOL operator!=(T* pSObj) const;
// --- In : pSObj : Pointer to a smart element
// --- Out :
// --- Returns : Whether this pointer does not point to the specified
// object
// --- Effect :
#ifndef DISABLE_SMART_SERIALIZATION
friend CArchive& AFXAPI operator<<(CArchive& ar, const COXSPtr<T>& pSObj);
// --- In : ar : Archive to store the object in
// pSObj : Object to store
// --- Out :
// --- Returns : The archive itself
// --- Effect : This functions serializes the object wrapped by this smart pointer
// Object I/O is pointer based to avoid added construction overhead and
// to support polymorphism
// Use the Serialize member function directly for embedded objects.
friend CArchive& AFXAPI operator>>(CArchive& ar, COXSPtr<T>& pSObj);
// --- In : ar : Archive to load the object from
// pSObj : Object pointer to load into
// --- Out :
// --- Returns : The archive itself
// --- Effect : This functions serializes the object into this smart pointer
// Object I/O is pointer based to avoid added construction overhead and
// to support polymorphism
// Use the Serialize member function directly for embedded objects.
#endif // DISABLE_SMART_SERIALIZATION
COXSPtr& PolyAssign(T* pSObj, LONG* pnReferenceCount);
// --- In : pSObj : Pointer to a T or T derived object
// pnReferenceCount : Pointer to its reference count
// --- Out :
// --- Returns : A smart pointer wrapping the object
// --- Effect : Assignment function, internally used for
// polymorphic assignment
// Do not call this function directly, use
// the operator <<= instead
LONG* GetRefCountAddress() const;
// --- In :
// --- Out :
// --- Returns : The address of the reference count of the object
// or NULL when smart null pointer
// --- Effect : Helper function, internally used for polymorphic assignment
// Do not call this function directly, use
// the operator <<= instead
#ifdef ENABLE_SMART_WRAPPER
// CAUTION : THE NEXT THREE FUNCTIONS ARE NOT INTENDED FOR NORMAL USE
// THEY DISABLE A LOT OF IMPORTANT FUNCTIONALITY AND
// SHOULD ONLY BE USED IN EXCEPTIONAL CIRCUMSTANCES
void Lock();
// --- In :
// --- Out :
// --- Returns :
// --- Effect : Locks all the smart pointers that point to the object
// this smart pointer points to
// Locking will disable automatic deletion when the
// reference count reaches 0
void Unlock();
// --- In :
// --- Out :
// --- Returns :
// --- Effect : Unlocks all the smart pointers that point to the object
// this smart pointer points to
// Unlocking will re-enable automatic deletion when the
// reference count reaches 0
BOOL IsLocked();
// --- In :
// --- Out :
// --- Returns : Whether the smart pointer is locked or not
// --- Effect :
#endif // ENABLE_SMART_WRAPPER
#ifdef _DEBUG
void AssertValid() const;
#endif // _DEBUG
~COXSPtr();
// --- In :
// --- Out :
// --- Returns :
// --- Effect : This destructs the pointer object
protected:
LONG Grab();
LONG Release();
private:
};
template <class BASE_T, class T>
inline COXSPtr<BASE_T>& SmartUpCast(COXSPtr<BASE_T>& pBaseObj, const COXSPtr<T>& pObj)
// --- In : pBaseObj : Smart pointer you want to assign to
// pObj : Smart pointer being assigned
// --- Out :
// --- Returns : The smart pointer assigned to
// --- Effect : This is the 'polymorphic assignemnt' operator
// A smart pointer wrapping a T object can be assigned to a
// smart pointer normally wrapping BASE_T object,
// if T* could be assigned to BASE_T*
// This means T must be derived from BASE_T
{
// The next line will generate a compiler error (cannot convert parameter 1 from ...)
// if T (pObj) is not derived from BASE_T (pBaseObj)
return pBaseObj.PolyAssign(pObj, pObj.GetRefCountAddress());
};
template <class BASE_T, class T>
inline COXSPtr<BASE_T>& operator<<=(COXSPtr<BASE_T>& pBaseObj, const COXSPtr<T>& pObj)
{
return SmartUpCast(pBaseObj, pObj);
};
template <class BASE_T, class T>
inline COXSPtr<T>& SmartDownCast(COXSPtr<T>& pObj, const COXSPtr<BASE_T>& pBaseObj)
// --- In : pObj : Smart pointer you want to assign to
// pBaseObj : Smart pointer being assigned
// --- Out :
// --- Returns : The smart pointer assigned to
// --- Effect : This is the 'cast assignemnt' operator
// A smart pointer wrapping a BASE_T object will be assigned to a
// smart pointer wrapping a T object,
// A runtime check will be performed, to check the validity
// When an incorrect cast is performed a smart NULL pointer is returned
{
#ifndef DISABLE_SMART_DOWNCAST_TEST
// The macro DYNAMIC_DOWNCAST does not work with templates, so we mimic that functionality
// ... Build a (temporary T object) just to get to the runtime class
COXSPtr<T> pDummyObj;
if (pBaseObj != NULL && !pBaseObj->IsKindOf(pDummyObj->GetRuntimeClass()))
{
TRACE(_T("SmartDownCast (Cast assignment) returning smart NULL pointer\n"));
return pObj.PolyAssign(NULL, NULL);
}
else
#endif // DISABLE_SMART_DOWNCAST_TEST
return pObj.PolyAssign((T*)(BASE_T*)pBaseObj, pBaseObj.GetRefCountAddress());
};
template <class BASE_T, class T>
inline COXSPtr<T>& operator>>=(COXSPtr<T>& pObj, const COXSPtr<BASE_T>& pBaseObj)
{
return SmartDownCast(pObj, pBaseObj);
};
#include "OXSPtr.inl"
#endif // __OXSPTR_H__
// ==========================================================================