1 /* 2 3 refobj.hpp 4 5 Created by DHM for Headhunter; copied into AVP 6 7 Reference-counted base class to be used by e.g. strings 8 9 */ 10 11 #ifndef _refobj 12 #define _refobj 1 13 14 15 #ifndef __fail_h 16 #include "fail.h" 17 #endif 18 19 20 21 #ifdef __cplusplus 22 extern "C" { 23 #endif 24 25 26 /* Version settings *****************************************************/ 27 #define TrackReferenceCounted No 28 /* 29 This is a debug option that has a fair amount of run-time 30 cost. 31 32 It maintains a list of all reference-counted objects, and 33 data on when references were added or released. 34 35 Data on a particular object can be sent to a log file; 36 there is a function to do this for all that exist. 37 */ 38 39 /* Macros ***************************************************************/ 40 41 #if TrackReferenceCounted 42 #define R_AddRef() imp_R_AddRef(__FILE__,__LINE__) 43 #define R_Release() imp_R_Release(__FILE__,__LINE__) 44 #endif 45 46 /* Imported globals *****************************************************/ 47 48 extern char const* refobj_fail_addref; 49 extern char const* refobj_fail_release; 50 extern char const* refobj_fail_destructor; 51 52 53 /* Type definitions *****************************************************/ 54 class R_DumpContext; // fully declared in DCONTEXT.HPP 55 56 class RefCountObject_TrackData; // fully declared within REFOBJ.CPP 57 58 class RefCountObject 59 { 60 // {{{ Private data 61 private: 62 int RefCount; 63 64 #if TrackReferenceCounted 65 RefCountObject_TrackData* pTrackData; 66 // done as a non-NULL pointer rather than a ref so as to hide 67 // definition (avoiding compiler dependency) 68 #endif 69 70 // }}} 71 72 73 // {{{ Private functions 74 private: 75 // Private fns for the tracking system are complex and defined in REFOBJ.CPP 76 #if TrackReferenceCounted 77 void Track_Construct(void); 78 void Track_R_AddRef(char* theFilename, int theLineNum); 79 void Track_R_Release(char* theFilename, int theLineNum); 80 void Track_Destroy(void); 81 #endif 82 // }}} 83 84 public: RefCountObject()85 RefCountObject() : 86 #if TrackReferenceCounted 87 pTrackData(NULL), 88 #endif 89 RefCount(1) 90 { 91 #if TrackReferenceCounted 92 Track_Construct(); 93 #endif 94 } 95 96 #if TrackReferenceCounted imp_R_AddRef(char * theFilename,int theLineNum)97 void imp_R_AddRef(char* theFilename, int theLineNum) 98 { 99 #ifndef NDEBUG 100 if ( RefCount <= 0) 101 { 102 fail(refobj_fail_addref); 103 } 104 #endif 105 RefCount++; 106 107 Track_R_AddRef(theFilename,theLineNum); 108 } 109 imp_R_Release(char * theFilename,int theLineNum)110 void imp_R_Release(char* theFilename, int theLineNum) 111 { 112 #ifndef NDEBUG 113 if ( RefCount <= 0) 114 { 115 fail(refobj_fail_release); 116 } 117 #endif 118 119 Track_R_Release(theFilename,theLineNum); 120 121 if ( (--RefCount) == 0 ) 122 { 123 delete this; 124 } 125 } 126 #else R_AddRef(void)127 void R_AddRef(void) 128 { 129 #ifndef NDEBUG 130 if ( RefCount <= 0) 131 { 132 fail(refobj_fail_addref); 133 } 134 #endif 135 RefCount++; 136 } 137 R_Release(void)138 void R_Release(void) 139 { 140 #ifndef NDEBUG 141 if ( RefCount <= 0) 142 { 143 fail(refobj_fail_release); 144 } 145 #endif 146 147 if ( (--RefCount) == 0 ) 148 { 149 delete this; 150 } 151 } 152 #endif 153 154 #if debug CheckRef() const155 int CheckRef() const 156 { 157 return RefCount; 158 } 159 // Handy way to examine reference count for debugging only 160 #endif 161 162 #if TrackReferenceCounted 163 virtual void DumpIDForReferenceDump(R_DumpContext& theContext) const = 0; 164 void ReferenceDump(R_DumpContext& theContext) const; 165 static void DumpAll(R_DumpContext& theContext); 166 #endif 167 168 protected: 169 // Destructors must be protected; only derived classes may use the 170 // destructor and (we hope) only in the R_Release() method: ~RefCountObject()171 virtual ~RefCountObject() 172 { 173 #ifndef NDEBUG 174 if ( RefCount != 0 ) 175 { 176 fail(refobj_fail_destructor); 177 } 178 #endif 179 180 #if TrackReferenceCounted 181 Track_Destroy(); 182 #endif 183 } 184 }; 185 186 187 188 /* Exported globals *****************************************************/ 189 190 /* Function prototypes **************************************************/ 191 192 193 194 /* End of the header ****************************************************/ 195 196 197 #ifdef __cplusplus 198 }; 199 #endif 200 201 #endif 202