Subversion Repositories AndroidProjects

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
244 chris 1
#ifndef __SEXY_SMARTPTR_H__
2
#define __SEXY_SMARTPTR_H__
3
#include "Common.h"
4
 
5
#pragma pack(push,8) // need 8 byte alignment for InterlockedIncrement
6
 
7
namespace Sexy
8
{
9
 
10
///////////////////////////////////////////////////////////////////////////////
11
///////////////////////////////////////////////////////////////////////////////
12
 
13
class RefCount
14
{
15
private:
16
        mutable long mRefCount;
17
 
18
protected:
19
        // The compiler allows a derived destructor to be called if it's not explicitly declared 
20
        // even if the parent destructor is private, so I make the parent destructor protected so that 
21
        // derived classes can make their destructors protected as well.  (They get an error if the 
22
        // parent destructor is private.)
23
        virtual ~RefCount() {}
24
 
25
public:
26
        RefCount() : mRefCount(0) {}
27
 
28
        const RefCount* CreateRef() const
29
        {
30
                InterlockedIncrement(&mRefCount);
31
                return this;
32
        }
33
 
34
        void Release()
35
        {
36
                if(InterlockedDecrement(&mRefCount)<=0)
37
                        delete this;
38
        }
39
 
40
        // You might want to assign one reference counted object to another simply to copy
41
        // the member variables of one to the other, but you certainly don't want to copy
42
        // the reference counts!
43
        RefCount(const RefCount&) : mRefCount(0) {}
44
        RefCount& operator=(const RefCount&) { return *this; }
45
 
46
        unsigned long GetRefCount() { return mRefCount; }      
47
};
48
 
49
///////////////////////////////////////////////////////////////////////////////
50
///////////////////////////////////////////////////////////////////////////////
51
 
52
// Const smart pointer.  Automatically performs reference counting on objects which
53
// implement the CreateRef and Release interface.  Allows const access to underlying object.
54
template <class T> class ConstSmartPtr
55
{
56
protected:
57
        T *p;
58
 
59
public:
60
        ConstSmartPtr() : p(NULL) {}
61
 
62
        // Copy constructor.  Assign and add reference to underlying object.
63
        ConstSmartPtr(const T* theObject) : p((T*)(theObject?theObject->CreateRef():NULL)) {}
64
        ConstSmartPtr(const ConstSmartPtr& theCopy) : p((T*)(theCopy?theCopy.p->CreateRef():NULL)){}
65
 
66
        // Destructor.  Remove reference to underlying object.
67
        ~ConstSmartPtr() { if(p!=NULL) p->Release(); }
68
 
69
        // Arrow operator allows ConstSmartPtr to be treated like actual pointer.
70
        const T* operator->() const { return p; }
71
 
72
        // Type case operator allows ConstSmartPtr to be cast to const T*,
73
        operator const T*() const { return p; }
74
 
75
        // Assignment operator.  Release old underlying object if not null.  Add reference to new object.
76
        const T* operator=(const T* thePtr)
77
        {
78
                if(p!=thePtr) // prevent self-assignment
79
                {
80
                        if(p!=NULL) p->Release();
81
                        p = (T*)(thePtr?thePtr->CreateRef():NULL);
82
                }
83
 
84
                return thePtr;
85
        }      
86
 
87
        const ConstSmartPtr& operator=(const ConstSmartPtr& theCopy)
88
        {
89
                operator=(theCopy.get());
90
                return *this;
91
        }
92
 
93
        // Allow comparions just like normal pointer.
94
        bool operator==(const T* thePtr) const { return p==thePtr; }
95
        bool operator!=(const T* thePtr) const { return p!=thePtr; }
96
        bool operator<(const T *thePtr) const { return p < thePtr; }
97
 
98
        // Accessor to actual object
99
        const T* get() const { return p; }
100
 
101
        struct Comp { bool operator()(const ConstSmartPtr &a, const ConstSmartPtr &b) const { return a.get()<b.get(); } };
102
};
103
 
104
 
105
// Smart pointer.  Automatically performs reference counting on objects which
106
// implement the CreateRef and Release interface.  Allows non-const access to underlying object.
107
template <class T> class SmartPtr : public ConstSmartPtr<T>
108
{
109
public:
110
        SmartPtr() {}
111
        SmartPtr(T* theObject) : ConstSmartPtr<T>(theObject){}
112
        SmartPtr(const SmartPtr& theCopy) : ConstSmartPtr<T>(theCopy.p) {}
113
 
114
        const SmartPtr& operator=(const SmartPtr& theCopy)
115
        {
116
                ConstSmartPtr<T>::operator=(theCopy.get());
117
                return *this;
118
        }
119
 
120
        T* operator=(T* thePtr)
121
        {
122
                ConstSmartPtr<T>::operator =(thePtr);
123
                return thePtr;
124
        }
125
 
126
 
127
        T* operator->() const { return p; }
128
        operator T*() const { return p; }
129
 
130
        T* get() const { return p; }
131
};
132
 
133
///////////////////////////////////////////////////////////////////////////////
134
///////////////////////////////////////////////////////////////////////////////
135
 
136
typedef SmartPtr<RefCount> RefCountPtr;
137
 
138
} // namespace Sexy
139
 
140
#pragma pack(pop)
141
 
142
// Helper macro to forward declare reference counted classes along with their smart pointer definitions
143
#define SEXY_PTR_FORWARD(X) class X; typedef SmartPtr<X> X##Ptr
144
#define SEXY_PTR_FORWARDNS(X) class X; typedef Sexy::SmartPtr<X> X##Ptr
145
 
146
#endif