Panda3D
|
00001 // Filename: referenceCount.h 00002 // Created by: drose (23Oct98) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #ifndef REFERENCECOUNT_H 00016 #define REFERENCECOUNT_H 00017 00018 #include "pandabase.h" 00019 #include "weakReferenceList.h" 00020 #include "typedObject.h" 00021 #include "memoryUsage.h" 00022 #include "memoryBase.h" 00023 #include "config_express.h" 00024 #include "atomicAdjust.h" 00025 #include "numeric_types.h" 00026 #include "deletedChain.h" 00027 00028 #include <stdlib.h> 00029 00030 #ifdef HAVE_RTTI 00031 #include <typeinfo> 00032 #endif 00033 00034 //////////////////////////////////////////////////////////////////// 00035 // Class : ReferenceCount 00036 // Description : A base class for all things that want to be 00037 // reference-counted. ReferenceCount works in 00038 // conjunction with PointerTo to automatically delete 00039 // objects when the last pointer to them goes away. 00040 //////////////////////////////////////////////////////////////////// 00041 class EXPCL_PANDAEXPRESS ReferenceCount : public MemoryBase { 00042 protected: 00043 INLINE ReferenceCount(); 00044 INLINE ReferenceCount(const ReferenceCount &); 00045 INLINE void operator = (const ReferenceCount &); 00046 00047 public: 00048 virtual INLINE ~ReferenceCount(); 00049 00050 PUBLISHED: 00051 INLINE int get_ref_count() const; 00052 INLINE void ref() const; 00053 virtual INLINE bool unref() const; 00054 00055 INLINE bool test_ref_count_integrity() const; 00056 INLINE bool test_ref_count_nonzero() const; 00057 00058 public: 00059 INLINE void local_object(); 00060 INLINE bool has_weak_list() const; 00061 INLINE WeakReferenceList *get_weak_list() const; 00062 00063 INLINE void weak_ref(WeakPointerToVoid *ptv); 00064 INLINE void weak_unref(WeakPointerToVoid *ptv); 00065 00066 protected: 00067 bool do_test_ref_count_integrity() const; 00068 bool do_test_ref_count_nonzero() const; 00069 00070 private: 00071 void create_weak_list(); 00072 00073 private: 00074 enum { 00075 // We use this value as a flag to indicate an object has been 00076 // indicated as a local object, and should not be deleted except 00077 // by its own destructor. Really, any nonzero value would do, but 00078 // having a large specific number makes the sanity checks easier. 00079 local_ref_count = 10000000, 00080 00081 // This value is used as a flag to indicate that an object has 00082 // just been deleted, and you're looking at deallocated memory. 00083 // It's not guaranteed to stick around, of course (since the 00084 // deleted memory might be repurposed for anything else, including 00085 // a new object), but if you ever do encounter this value in a 00086 // reference count field, you screwed up. 00087 deleted_ref_count = -100, 00088 }; 00089 00090 AtomicAdjust::Integer _ref_count; 00091 AtomicAdjust::Pointer _weak_list; // WeakReferenceList * 00092 00093 public: 00094 static TypeHandle get_class_type() { 00095 return _type_handle; 00096 } 00097 static void init_type() { 00098 register_type(_type_handle, "ReferenceCount"); 00099 } 00100 00101 private: 00102 static TypeHandle _type_handle; 00103 }; 00104 00105 template<class RefCountType> 00106 INLINE void unref_delete(RefCountType *ptr); 00107 00108 //////////////////////////////////////////////////////////////////// 00109 // Class : RefCountProxy 00110 // Description : A "proxy" to use to make a reference-countable object 00111 // whenever the object cannot inherit from 00112 // ReferenceCount for some reason. RefCountPr<MyClass> 00113 // can be treated as an instance of MyClass directly, 00114 // for the most part, except that it can be reference 00115 // counted. 00116 // 00117 // If you want to declare a RefCountProxy to something 00118 // that does not have get_class_type(), you will have to 00119 // define a template specialization on 00120 // _get_type_handle() and _do_init_type(), as in 00121 // typedObject.h. 00122 //////////////////////////////////////////////////////////////////// 00123 template<class Base> 00124 class RefCountProxy : public ReferenceCount { 00125 public: 00126 INLINE RefCountProxy(); 00127 INLINE RefCountProxy(const Base ©); 00128 00129 INLINE operator Base &(); 00130 INLINE operator const Base &() const; 00131 00132 static TypeHandle get_class_type() { 00133 return _type_handle; 00134 } 00135 static void init_type(); 00136 00137 private: 00138 Base _base; 00139 static TypeHandle _type_handle; 00140 }; 00141 00142 00143 //////////////////////////////////////////////////////////////////// 00144 // Class : RefCountObj 00145 // Description : Another kind of proxy, similar to RefCountProxy. 00146 // This one works by inheriting from the indicated base 00147 // type, giving it an is-a relation instead of a has-a 00148 // relation. As such, it's a little more robust, but 00149 // only works when the base type is, in fact, a class. 00150 //////////////////////////////////////////////////////////////////// 00151 template<class Base> 00152 class RefCountObj : public ReferenceCount, public Base { 00153 public: 00154 INLINE RefCountObj(); 00155 INLINE RefCountObj(const Base ©); 00156 ALLOC_DELETED_CHAIN(RefCountObj<Base>); 00157 00158 static TypeHandle get_class_type() { 00159 return _type_handle; 00160 } 00161 static void init_type(); 00162 00163 private: 00164 static TypeHandle _type_handle; 00165 }; 00166 00167 #include "referenceCount.I" 00168 00169 #endif