00001 // Filename: pointerTo.h 00002 // Created by: drose (23Oct98) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved 00008 // 00009 // All use of this software is subject to the terms of the Panda 3d 00010 // Software license. You should have received a copy of this license 00011 // along with this source code; you will also find a current copy of 00012 // the license at http://www.panda3d.org/license.txt . 00013 // 00014 // To contact the maintainers of this program write to 00015 // panda3d@yahoogroups.com . 00016 // 00017 //////////////////////////////////////////////////////////////////// 00018 00019 #ifndef POINTERTO_H 00020 #define POINTERTO_H 00021 00022 //////////////////////////////////////////////////////////////////// 00023 // 00024 // This file defines the classes PointerTo and ConstPointerTo (and 00025 // their abbreviations, PT and CPT). These should be used in place of 00026 // traditional C-style pointers wherever implicit reference counting 00027 // is desired. 00028 // 00029 // The syntax is: instead of: 00030 // 00031 // PointerTo<MyClass> p; MyClass *p; 00032 // PT(MyClass) p; 00033 // 00034 // ConstPointerTo<MyClass> p; const MyClass *p; 00035 // CPT(MyClass) p; 00036 // 00037 // PointerTo and ConstPointerTo will automatically increment the 00038 // object's reference count while the pointer is kept. When the 00039 // PointerTo object is reassigned or goes out of scope, the reference 00040 // count is automatically decremented. If the reference count reaches 00041 // zero, the object is freed. 00042 // 00043 // Note that const PointerTo<MyClass> is different from 00044 // ConstPointerTo<MyClass>. A const PointerTo may not reassign its 00045 // pointer, but it may still modify the contents at that address. On 00046 // the other hand, a ConstPointerTo may reassign its pointer at will, 00047 // but may not modify the contents. It is like the difference between 00048 // (MyClass * const) and (const MyClass *). 00049 // 00050 // In order to use PointerTo, it is necessary that the thing pointed 00051 // to--MyClass in the above example--either inherits from 00052 // ReferenceCount, or is a proxy built with RefCountProxy or 00053 // RefCountObj (see referenceCount.h). However, also see 00054 // PointerToArray, which does not have this restriction. 00055 // 00056 // It is crucial that the PointerTo object is only used to refer to 00057 // objects allocated from the free store, for which delete is a 00058 // sensible thing to do. If you assign a PointerTo to an automatic 00059 // variable (allocated from the stack, for instance), bad things will 00060 // certainly happen when the reference count reaches zero and it tries 00061 // to delete it. 00062 // 00063 // It's also important to remember that, as always, a virtual 00064 // destructor is required if you plan to support polymorphism. That 00065 // is, if you define a PointerTo to some base type, and assign to it 00066 // instances of a class derived from that base class, the base class 00067 // must have a virtual destructor in order to properly destruct the 00068 // derived object when it is deleted. 00069 // 00070 //////////////////////////////////////////////////////////////////// 00071 00072 #include <pandabase.h> 00073 00074 #include "referenceCount.h" 00075 #include "typedef.h" 00076 #include "memoryUsage.h" 00077 #include "config_express.h" 00078 00079 00080 //////////////////////////////////////////////////////////////////// 00081 // Class : PointerToBase 00082 // Description : This is the base class for PointerTo and 00083 // ConstPointerTo. Don't try to use it directly; use 00084 // either derived class instead. 00085 //////////////////////////////////////////////////////////////////// 00086 template <class T> 00087 class PointerToBase { 00088 public: 00089 typedef T To; 00090 00091 protected: 00092 INLINE PointerToBase(To *ptr); 00093 INLINE PointerToBase(const PointerToBase<T> ©); 00094 INLINE ~PointerToBase(); 00095 00096 void reassign(To *ptr); 00097 00098 INLINE void reassign(const PointerToBase<To> ©); 00099 00100 To *_ptr; 00101 00102 // No assignment or retrieval functions are declared in 00103 // PointerToBase, because we will have to specialize on const 00104 // vs. non-const later. 00105 00106 public: 00107 // These comparison functions are common to all things PointerTo, so 00108 // they're defined up here. 00109 #ifndef CPPPARSER 00110 #ifndef WIN32_VC 00111 INLINE bool operator == (const To *other) const; 00112 INLINE bool operator != (const To *other) const; 00113 INLINE bool operator > (const To *other) const; 00114 INLINE bool operator <= (const To *other) const; 00115 INLINE bool operator >= (const To *other) const; 00116 INLINE bool operator == (To *other) const; 00117 INLINE bool operator != (To *other) const; 00118 INLINE bool operator > (To *other) const; 00119 INLINE bool operator <= (To *other) const; 00120 INLINE bool operator >= (To *other) const; 00121 00122 INLINE bool operator == (const PointerToBase<To> &other) const; 00123 INLINE bool operator != (const PointerToBase<To> &other) const; 00124 INLINE bool operator > (const PointerToBase<To> &other) const; 00125 INLINE bool operator <= (const PointerToBase<To> &other) const; 00126 INLINE bool operator >= (const PointerToBase<To> &other) const; 00127 #endif // WIN32_VC 00128 INLINE bool operator < (const To *other) const; 00129 INLINE bool operator < (const PointerToBase<To> &other) const; 00130 #endif // CPPPARSER 00131 00132 PUBLISHED: 00133 INLINE bool is_null() const; 00134 INLINE void clear(); 00135 00136 void output(ostream &out) const; 00137 }; 00138 00139 template<class T> 00140 INLINE ostream &operator <<(ostream &out, const PointerToBase<T> &pointer) { 00141 pointer.output(out); 00142 return out; 00143 } 00144 00145 //////////////////////////////////////////////////////////////////// 00146 // Class : PointerTo 00147 // Description : PointerTo is a template class which implements a 00148 // smart pointer to an object derived from 00149 // ReferenceCount. 00150 //////////////////////////////////////////////////////////////////// 00151 template <class T> 00152 class PointerTo : public PointerToBase<T> { 00153 public: 00154 typedef TYPENAME PointerToBase<T>::To To; 00155 PUBLISHED: 00156 INLINE PointerTo(To *ptr = (To *)NULL); 00157 INLINE PointerTo(const PointerTo<T> ©); 00158 00159 public: 00160 INLINE To &operator *() const; 00161 INLINE To *operator -> () const; 00162 INLINE operator TYPENAME PointerToBase<T>::To *() const; 00163 00164 PUBLISHED: 00165 // When downcasting to a derived class from a PointerTo<BaseClass>, 00166 // C++ would normally require you to cast twice: once to an actual 00167 // BaseClass pointer, and then again to your desired pointer. You 00168 // can use the handy function p() to avoid this first cast and make 00169 // your code look a bit cleaner. 00170 00171 // e.g. instead of (MyType *)(BaseClass *)ptr, use (MyType *)ptr.p() 00172 00173 // If your base class is a derivative of TypedObject, you might want 00174 // to use the DCAST macro defined in typedObject.h instead, 00175 // e.g. DCAST(MyType, ptr). This provides a clean downcast that 00176 // doesn't require .p() or any double-casting, and it can be 00177 // run-time checked for correctness. 00178 INLINE To *p() const; 00179 00180 INLINE PointerTo<T> &operator = (To *ptr); 00181 INLINE PointerTo<T> &operator = (const PointerTo<T> ©); 00182 00183 // These functions normally wouldn't need to be redefined here, but 00184 // we do so anyway just to help out interrogate (which doesn't seem 00185 // to want to automatically export the PointerToBase class). When 00186 // this works again in interrogate, we can remove these. 00187 INLINE bool is_null() const { return PointerToBase<T>::is_null(); } 00188 INLINE void clear() { PointerToBase<T>::clear(); } 00189 }; 00190 00191 00192 //////////////////////////////////////////////////////////////////// 00193 // Class : ConstPointerTo 00194 // Description : A ConstPointerTo is similar to a PointerTo, except it 00195 // keeps a const pointer to the thing. 00196 // 00197 // (Actually, it keeps a non-const pointer, because it 00198 // must be allowed to adjust the reference counts, and 00199 // it must be able to delete it when the reference count 00200 // goes to zero. But it presents only a const pointer 00201 // to the outside world.) 00202 // 00203 // Notice that a PointerTo may be assigned to a 00204 // ConstPointerTo, but a ConstPointerTo may not be 00205 // assigned to a PointerTo. 00206 //////////////////////////////////////////////////////////////////// 00207 template <class T> 00208 class ConstPointerTo : public PointerToBase<T> { 00209 public: 00210 typedef TYPENAME PointerToBase<T>::To To; 00211 PUBLISHED: 00212 INLINE ConstPointerTo(const To *ptr = (const To *)NULL); 00213 INLINE ConstPointerTo(const PointerTo<T> ©); 00214 INLINE ConstPointerTo(const ConstPointerTo<T> ©); 00215 00216 public: 00217 INLINE const To &operator *() const; 00218 INLINE const To *operator -> () const; 00219 INLINE operator const TYPENAME PointerToBase<T>::To *() const; 00220 00221 PUBLISHED: 00222 INLINE const To *p() const; 00223 00224 INLINE ConstPointerTo<T> &operator = (const To *ptr); 00225 INLINE ConstPointerTo<T> &operator = (const ConstPointerTo<T> ©); 00226 INLINE ConstPointerTo<T> &operator = (const PointerTo<T> ©); 00227 00228 // These functions normally wouldn't need to be redefined here, but 00229 // we do so anyway just to help out interrogate (which doesn't seem 00230 // to want to automatically export the PointerToBase class). When 00231 // this works again in interrogate, we can remove these. 00232 INLINE bool is_null() const { return PointerToBase<T>::is_null(); } 00233 INLINE void clear() { PointerToBase<T>::clear(); } 00234 }; 00235 00236 00237 // Finally, we'll define a couple of handy abbreviations to save on 00238 // all that wasted typing time. 00239 00240 #define PT(type) PointerTo< type > 00241 #define CPT(type) ConstPointerTo< type > 00242 00243 #include "pointerTo.I" 00244 00245 #endif