Subversion Repositories AndroidProjects

Rev

Blame | Last modification | View Log | RSS feed

#ifndef __SEXY_SMARTPTR_H__
#define __SEXY_SMARTPTR_H__
#include "Common.h"

#pragma pack(push,8) // need 8 byte alignment for InterlockedIncrement

namespace Sexy
{

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

class RefCount
{
private:
        mutable long mRefCount;

protected:
        // The compiler allows a derived destructor to be called if it's not explicitly declared
        // even if the parent destructor is private, so I make the parent destructor protected so that
        // derived classes can make their destructors protected as well.  (They get an error if the
        // parent destructor is private.)
        virtual ~RefCount() {}

public:
        RefCount() : mRefCount(0) {}

        const RefCount* CreateRef() const
        {
                InterlockedIncrement(&mRefCount);
                return this;
        }
       
        void Release()
        {
                if(InterlockedDecrement(&mRefCount)<=0)
                        delete this;
        }

        // You might want to assign one reference counted object to another simply to copy
        // the member variables of one to the other, but you certainly don't want to copy
        // the reference counts!
        RefCount(const RefCount&) : mRefCount(0) {}
        RefCount& operator=(const RefCount&) { return *this; }

        unsigned long GetRefCount() { return mRefCount; }      
};

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

// Const smart pointer.  Automatically performs reference counting on objects which
// implement the CreateRef and Release interface.  Allows const access to underlying object.
template <class T> class ConstSmartPtr
{
protected:
        T *p;

public:
        ConstSmartPtr() : p(NULL) {}

        // Copy constructor.  Assign and add reference to underlying object.
        ConstSmartPtr(const T* theObject) : p((T*)(theObject?theObject->CreateRef():NULL)) {}
        ConstSmartPtr(const ConstSmartPtr& theCopy) : p((T*)(theCopy?theCopy.p->CreateRef():NULL)){}

        // Destructor.  Remove reference to underlying object.
        ~ConstSmartPtr() { if(p!=NULL) p->Release(); }

        // Arrow operator allows ConstSmartPtr to be treated like actual pointer.
        const T* operator->() const { return p; }

        // Type case operator allows ConstSmartPtr to be cast to const T*,
        operator const T*() const { return p; }

        // Assignment operator.  Release old underlying object if not null.  Add reference to new object.
        const T* operator=(const T* thePtr)
        {
                if(p!=thePtr) // prevent self-assignment
                {
                        if(p!=NULL) p->Release();
                        p = (T*)(thePtr?thePtr->CreateRef():NULL);
                }

                return thePtr;
        }      

        const ConstSmartPtr& operator=(const ConstSmartPtr& theCopy)
        {
                operator=(theCopy.get());
                return *this;
        }

        // Allow comparions just like normal pointer.
        bool operator==(const T* thePtr) const { return p==thePtr; }
        bool operator!=(const T* thePtr) const { return p!=thePtr; }
        bool operator<(const T *thePtr) const { return p < thePtr; }

        // Accessor to actual object
        const T* get() const { return p; }

        struct Comp { bool operator()(const ConstSmartPtr &a, const ConstSmartPtr &b) const { return a.get()<b.get(); } };
};


// Smart pointer.  Automatically performs reference counting on objects which
// implement the CreateRef and Release interface.  Allows non-const access to underlying object.
template <class T> class SmartPtr : public ConstSmartPtr<T>
{
public:
        SmartPtr() {}
        SmartPtr(T* theObject) : ConstSmartPtr<T>(theObject){}
        SmartPtr(const SmartPtr& theCopy) : ConstSmartPtr<T>(theCopy.p) {}

        const SmartPtr& operator=(const SmartPtr& theCopy)
        {
                ConstSmartPtr<T>::operator=(theCopy.get());
                return *this;
        }

        T* operator=(T* thePtr)
        {
                ConstSmartPtr<T>::operator =(thePtr);
                return thePtr;
        }


        T* operator->() const { return p; }
        operator T*() const { return p; }

        T* get() const { return p; }
};

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

typedef SmartPtr<RefCount> RefCountPtr;

} // namespace Sexy

#pragma pack(pop)

// Helper macro to forward declare reference counted classes along with their smart pointer definitions
#define SEXY_PTR_FORWARD(X) class X; typedef SmartPtr<X> X##Ptr
#define SEXY_PTR_FORWARDNS(X) class X; typedef Sexy::SmartPtr<X> X##Ptr

#endif