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