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