1 /*******************************************************************
2 *
3 * DESCRIPTION: refobj.cpp
4 *
5 * AUTHOR: David Malcolm
6 *
7 * HISTORY: Created 15/9/97
8 *
9 *******************************************************************/
10
11 /* Includes ********************************************************/
12 #include "3dc.h"
13 #include "refobj.hpp"
14
15 #if TrackReferenceCounted
16 #include "dcontext.hpp"
17
18 #ifndef list_template_hpp
19 #include "list_tem.hpp"
20 #endif
21 #endif
22
23 #define UseLocalAssert Yes
24 #include "ourasert.h"
25
26 /* Version settings ************************************************/
27 #if TrackReferenceCounted
28 #define OutputRefCountLogOnExit Yes
29
30
31 #if OutputRefCountLogOnExit
32 #include "debuglog.hpp"
33 #endif
34
35
36 #endif
37
38 /* Constants *******************************************************/
39
40 /* Macros **********************************************************/
41
42 /* Imported function prototypes ************************************/
43
44 /* Imported data ***************************************************/
45 #ifdef __cplusplus
46 extern "C"
47 {
48 #endif
49 #if 0
50 extern OurBool DaveDebugOn;
51 extern FDIEXTENSIONTAG FDIET_Dummy;
52 extern IFEXTENSIONTAG IFET_Dummy;
53 extern FDIQUAD FDIQuad_WholeScreen;
54 extern FDIPOS FDIPos_Origin;
55 extern IFOBJECTLOCATION IFObjLoc_Origin;
56 extern UncompressedGlobalPlotAtomID UGPAID_StandardNull;
57 extern IFCOLOUR IFColour_Dummy;
58 extern IFVECTOR IFVec_Zero;
59 #endif
60 #ifdef __cplusplus
61 };
62 #endif
63
64
65
66 /* Exported globals ************************************************/
67 char const* refobj_fail_addref = "Failure in R_AddRef()\n";
68 char const* refobj_fail_release = "Failure in R_Release()\n";
69 char const* refobj_fail_destructor = "Failure in Destructor()\n";
70
71 /* Internal type definitions ***************************************/
72 #if TrackReferenceCounted
73 class RefCountObject_TrackData
74 {
75 public:
76 enum transtype
77 {
78 tt_addref,
79 tt_release
80 };
81
82 private:
83 class ReferenceTransaction
84 {
85 public:
86 void Dump( R_DumpContext& theContext ) const;
87
88 private:
89 char* Filename;
90 int LineNum;
91 enum transtype Type;
92
93 protected:
ReferenceTransaction(char * theFilename,int theLineNum,enum transtype theType)94 ReferenceTransaction(char* theFilename, int theLineNum, enum transtype theType) :
95 Filename(theFilename),
96 LineNum(theLineNum),
97 Type(theType)
98 {}
99 };
100
101 class Transaction_R_AddRef : public ReferenceTransaction
102 {
103 public:
Transaction_R_AddRef(char * theFilename,int theLineNum)104 Transaction_R_AddRef(char* theFilename, int theLineNum) :
105 ReferenceTransaction(theFilename, theLineNum, tt_addref)
106 {}
107 };
108
109 class Transaction_R_Release : public ReferenceTransaction
110 {
111 public:
Transaction_R_Release(char * theFilename,int theLineNum)112 Transaction_R_Release(char* theFilename, int theLineNum) :
113 ReferenceTransaction(theFilename, theLineNum, tt_release)
114 {}
115 };
116
117 public:
118 static void DumpAll(R_DumpContext& theContext);
119
120 RefCountObject_TrackData(RefCountObject *const pRCObj, char* theFilename, int theLineNum);
121 ~RefCountObject_TrackData();
122
123 void Track_R_AddRef(char* theFilename, int theLineNum);
124 void Track_R_Release(char* theFilename, int theLineNum);
125
126 void DumpTransactions( R_DumpContext& theContext ) const;
127
128 private:
129 RefCountObject *const pRCObj_Val;
130 char* constructionFilename;
131 int constructionLineNum;
132 List<ReferenceTransaction*> List_pTransaction;
133
134 private:
135 /*
136 Maintain various global stuff.
137 This is all held together as a BSS object so that we can be sure that we call
138 the log-on-exit in the destructor before destroying the records of what hasn't
139 been fully released.
140
141 We maintain a list of all reference counted objects, which the class RefCountObject
142 has indirect access to.
143
144 */
145 class Globals
146 {
147 friend class RefCountObject_TrackData;
148
149 private:
150 List<RefCountObject*> List_pRCObj;
151 #if OutputRefCountLogOnExit
152 char* filename;
153 #endif
154 public:
155 #if OutputRefCountLogOnExit
Globals(char * theFilename)156 Globals(char* theFilename) :
157 filename(theFilename),
158 #else
159 Globals() :
160 #endif
161 List_pRCObj()
162 {
163 }
164 ~Globals();
165
166 };
167
168 static Globals theGlobals;
169 };
170
171
172 static RefCountObject_TrackData :: Globals RefCountObject_TrackData :: theGlobals
173 (
174 #if OutputRefCountLogOnExit
175 "REFDUMP.TXT"
176 #endif
177 );
178
179 #if 0
180 static List<RefCountObject*> RefCountObject_TrackData :: TheList :: List_pRCObj;
181 #endif
182
183
184
185 #endif
186 /* Internal function prototypes ************************************/
187
188 /* Internal globals ************************************************/
189
190 /* Exported function definitions ***********************************/
191
192 // class RefCountObject
193 #if TrackReferenceCounted
Track_Construct(void)194 void RefCountObject :: Track_Construct(void)
195 {
196 GLOBALASSERT( pTrackData == NULL );
197
198 pTrackData = new RefCountObject_TrackData(this,"unknown file",666);
199 }
200
Track_R_AddRef(char * theFilename,int theLineNum)201 void RefCountObject :: Track_R_AddRef(char* theFilename, int theLineNum)
202 {
203 GLOBALASSERT( pTrackData );
204
205 pTrackData -> Track_R_AddRef(theFilename,theLineNum);
206 }
207
Track_R_Release(char * theFilename,int theLineNum)208 void RefCountObject :: Track_R_Release(char* theFilename, int theLineNum)
209 {
210 GLOBALASSERT( pTrackData );
211
212 pTrackData -> Track_R_Release(theFilename,theLineNum);
213 }
214
Track_Destroy(void)215 void RefCountObject :: Track_Destroy(void)
216 {
217 GLOBALASSERT( pTrackData );
218
219 delete pTrackData;
220 }
221
ReferenceDump(R_DumpContext & theContext) const222 void RefCountObject :: ReferenceDump(R_DumpContext& theContext) const
223 {
224 GLOBALASSERT( pTrackData );
225
226 DumpIDForReferenceDump(theContext);
227
228 pTrackData -> DumpTransactions(theContext);
229 }
230
DumpAll(R_DumpContext & theContext)231 static void RefCountObject :: DumpAll(R_DumpContext& theContext)
232 {
233 RefCountObject_TrackData :: DumpAll(theContext);
234 }
235 #endif // TrackReferenceCounted
236 /* Internal function definitions ***********************************/
237 #if TrackReferenceCounted
238 // class RefCountObject_TrackData
239 // class RefCountObject_TrackData :: ReferenceTransaction
240 // public:
Dump(R_DumpContext & theContext) const241 void RefCountObject_TrackData :: ReferenceTransaction :: Dump( R_DumpContext& theContext ) const
242 {
243 char* Action =
244 (
245 ( Type == tt_addref)
246 ?
247 "R_AddRef()"
248 :
249 "R_Release()"
250 );
251
252 theContext.dprintf("-- %s in file \"%s\" at line %i\n",Action,Filename,LineNum);
253 }
254
255 // public:
DumpAll(R_DumpContext & theContext)256 static void RefCountObject_TrackData :: DumpAll(R_DumpContext& theContext)
257 {
258 theContext . dprintf
259 (
260 "RefCountObject::DumpAll(); num objects=%i\n",
261 theGlobals . List_pRCObj . size()
262 );
263
264 for
265 (
266 CLIF<RefCountObject*> oi(&theGlobals . List_pRCObj);
267 !oi . done();
268 oi . next()
269 )
270 {
271 GLOBALASSERT(oi());
272 oi() -> ReferenceDump(theContext);
273 }
274 }
RefCountObject_TrackData(RefCountObject * const pRCObj,char * theFilename,int theLineNum)275 RefCountObject_TrackData :: RefCountObject_TrackData(RefCountObject *const pRCObj,char* theFilename, int theLineNum) :
276 pRCObj_Val(pRCObj),
277 List_pTransaction(),
278 constructionFilename(theFilename),
279 constructionLineNum(theLineNum)
280 {
281 theGlobals . List_pRCObj . add_entry(pRCObj_Val);
282 }
283
~RefCountObject_TrackData()284 RefCountObject_TrackData :: ~RefCountObject_TrackData()
285 {
286 while ( List_pTransaction . size() > 0)
287 {
288 List_pTransaction . delete_first_entry();
289 }
290
291 theGlobals . List_pRCObj . delete_entry(pRCObj_Val);
292
293 }
294
Track_R_AddRef(char * theFilename,int theLineNum)295 void RefCountObject_TrackData :: Track_R_AddRef(char* theFilename, int theLineNum)
296 {
297 List_pTransaction . add_entry_end
298 (
299 new Transaction_R_AddRef(theFilename,theLineNum)
300 );
301 }
302
Track_R_Release(char * theFilename,int theLineNum)303 void RefCountObject_TrackData :: Track_R_Release(char* theFilename, int theLineNum)
304 {
305 List_pTransaction . add_entry_end
306 (
307 new Transaction_R_Release(theFilename,theLineNum)
308 );
309 }
310
DumpTransactions(R_DumpContext & theContext) const311 void RefCountObject_TrackData :: DumpTransactions( R_DumpContext& theContext) const
312 {
313 theContext . dprintf("-- Constructed in \"%s\" at line %i\n",constructionFilename,constructionLineNum);
314 for
315 (
316 CLIF<ReferenceTransaction*> oi(&List_pTransaction);
317 !oi . done();
318 oi . next()
319 )
320 {
321 oi() -> Dump(theContext);
322 }
323 }
324
325 // private:
326
327 #if OutputRefCountLogOnExit
328 // We put one of these in the BSS segment so that its destructor
329 // gets called at exit. The destructor writes all the info
330 // to a log file
331 // class Globals
~Globals()332 RefCountObject_TrackData :: Globals :: ~Globals()
333 {
334 LogFile theLogFile(filename);
335 RefCountObject :: DumpAll(theLogFile);
336 }
337 #endif
338
339 #endif // TrackReferenceCounted
340