]> git.saurik.com Git - wxWidgets.git/blob - include/wx/memory.h
Take best fitting type for available memory measurement.
[wxWidgets.git] / include / wx / memory.h
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: memory.h
3 // Purpose: MDI classes
4 // Author: Arthur Seaton, Julian Smart
5 // Modified by:
6 // Created: 29/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) 1998 Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifndef _WX_MEMORYH__
13 #define _WX_MEMORYH__
14
15 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
16 #pragma interface "memory.h"
17 #endif
18
19 #include "wx/defs.h"
20 #include "wx/string.h"
21 #include "wx/msgout.h"
22
23 /*
24 The macro which will be expanded to include the file and line number
25 info, or to be a straight call to the new operator.
26 */
27
28 #if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
29
30 #include <stddef.h>
31
32 #ifdef __WXDEBUG__
33
34 WXDLLIMPEXP_BASE void * wxDebugAlloc(size_t size, wxChar * fileName, int lineNum, bool isObject, bool isVect = false);
35 WXDLLIMPEXP_BASE void wxDebugFree(void * buf, bool isVect = false);
36
37 //**********************************************************************************
38 /*
39 The global operator new used for everything apart from getting
40 dynamic storage within this function itself.
41 */
42
43 // We'll only do malloc and free for the moment: leave the interesting
44 // stuff for the wxObject versions.
45 // devik 2000-8-29: All new/delete ops are now inline because they can't
46 // be marked as dllexport/dllimport. It then leads to weird bugs when
47 // used on MSW as DLL
48
49 #if wxUSE_GLOBAL_MEMORY_OPERATORS
50
51 // Undefine temporarily (new is #defined in object.h) because we want to
52 // declare some new operators.
53 #ifdef new
54 #undef new
55 #endif
56
57 #if defined(__SUNCC__)
58 #define wxUSE_ARRAY_MEMORY_OPERATORS 0
59 #elif !( defined (__VISUALC__) && (__VISUALC__ <= 1020) ) || defined( __MWERKS__)
60 #define wxUSE_ARRAY_MEMORY_OPERATORS 1
61 #elif defined (__SGI_CC_)
62 // only supported by -n32 compilers
63 #ifndef __EDG_ABI_COMPATIBILITY_VERSION
64 #define wxUSE_ARRAY_MEMORY_OPERATORS 0
65 #endif
66 #elif !( defined (__VISUALC__) && (__VISUALC__ <= 1020) ) || defined( __MWERKS__)
67 #define wxUSE_ARRAY_MEMORY_OPERATORS 1
68 #else
69 // ::operator new[] is a recent C++ feature, so assume it's not supported
70 #define wxUSE_ARRAY_MEMORY_OPERATORS 0
71 #endif
72
73 void * operator new (size_t size, wxChar * fileName, int lineNum);
74
75 void * operator new (size_t size);
76
77 void operator delete (void * buf);
78
79 #if wxUSE_ARRAY_MEMORY_OPERATORS
80 void * operator new[] (size_t size);
81
82 void * operator new[] (size_t size, wxChar * fileName, int lineNum);
83
84 void operator delete[] (void * buf);
85 #endif
86
87 // VC++ 6.0 and MWERKS
88 #if ( defined(__VISUALC__) && (__VISUALC__ >= 1200) ) || defined(__MWERKS__)
89 inline void operator delete(void* pData, wxChar* /* fileName */, int /* lineNum */)
90 {
91 wxDebugFree(pData, false);
92 }
93 inline void operator delete[](void* pData, wxChar* /* fileName */, int /* lineNum */)
94 {
95 wxDebugFree(pData, true);
96 }
97 #endif // __VISUALC__>=1200
98 #endif // wxUSE_GLOBAL_MEMORY_OPERATORS
99 #endif // __WXDEBUG__
100
101 //**********************************************************************************
102
103 typedef unsigned int wxMarkerType;
104
105 /*
106 Define the struct which will be placed at the start of all dynamically
107 allocated memory.
108 */
109
110 class WXDLLIMPEXP_BASE wxMemStruct {
111
112 friend class WXDLLIMPEXP_BASE wxDebugContext; // access to the m_next pointer for list traversal.
113
114 public:
115 public:
116 int AssertList ();
117
118 size_t RequestSize () { return m_reqSize; }
119 wxMarkerType Marker () { return m_firstMarker; }
120
121 // When an object is deleted we set the id slot to a specific value.
122 inline void SetDeleted ();
123 inline int IsDeleted ();
124
125 int Append ();
126 int Unlink ();
127
128 // Used to determine if the object is really a wxMemStruct.
129 // Not a foolproof test by any means, but better than none I hope!
130 int AssertIt ();
131
132 // Do all validation on a node.
133 int ValidateNode ();
134
135 // Check the integrity of a node and of the list, node by node.
136 int CheckBlock ();
137 int CheckAllPrevious ();
138
139 // Print a single node.
140 void PrintNode ();
141
142 // Called when the memory linking functions get an error.
143 void ErrorMsg (const char *);
144 void ErrorMsg ();
145
146 inline void *GetActualData(void) const { return m_actualData; }
147
148 void Dump(void);
149
150 public:
151 // Check for underwriting. There are 2 of these checks. This one
152 // inside the struct and another right after the struct.
153 wxMarkerType m_firstMarker;
154
155 // File name and line number are from cpp.
156 wxChar* m_fileName;
157 int m_lineNum;
158
159 // The amount of memory requested by the caller.
160 size_t m_reqSize;
161
162 // Used to try to verify that we really are dealing with an object
163 // of the required class. Can be 1 of 2 values these indicating a valid
164 // wxMemStruct object, or a deleted wxMemStruct object.
165 wxMarkerType m_id;
166
167 wxMemStruct * m_prev;
168 wxMemStruct * m_next;
169
170 void * m_actualData;
171 bool m_isObject;
172 };
173
174
175 typedef void (wxMemStruct::*PmSFV) ();
176
177
178 /*
179 Debugging class. This will only have a single instance, but it's
180 a reasonable way to keep everything together and to make this
181 available for change if needed by someone else.
182 A lot of this stuff would be better off within the wxMemStruct class, but
183 it's stuff which we need to access at times when there is no wxMemStruct
184 object so we use this class instead. Think of it as a collection of
185 globals which have to do with the wxMemStruct class.
186 */
187
188 class WXDLLIMPEXP_BASE wxDebugContext {
189
190 protected:
191 // Used to set alignment for markers.
192 static size_t CalcAlignment ();
193
194 // Returns the amount of padding needed after something of the given
195 // size. This is so that when we cast pointers backwards and forwards
196 // the pointer value will be valid for a wxMarkerType.
197 static size_t GetPadding (const size_t size) ;
198
199 // Traverse the list.
200 static void TraverseList (PmSFV, wxMemStruct *from = NULL);
201
202 static int debugLevel;
203 static bool debugOn;
204
205 static int m_balign; // byte alignment
206 static int m_balignmask; // mask for performing byte alignment
207 public:
208 // Set a checkpoint to dump only the memory from
209 // a given point
210 static wxMemStruct *checkPoint;
211
212 wxDebugContext(void);
213 ~wxDebugContext(void);
214
215 static int GetLevel(void) { return debugLevel; }
216 static void SetLevel(int level) { debugLevel = level; }
217
218 static bool GetDebugMode(void) { return debugOn; }
219 static void SetDebugMode(bool flag) { debugOn = flag; }
220
221 static void SetCheckpoint(bool all = false);
222 static wxMemStruct *GetCheckpoint(void) { return checkPoint; }
223
224 // Calculated from the request size and any padding needed
225 // before the final marker.
226 static size_t PaddedSize (const size_t reqSize);
227
228 // Calc the total amount of space we need from the system
229 // to satisfy a caller request. This includes all padding.
230 static size_t TotSize (const size_t reqSize);
231
232 // Return valid pointers to offsets within the allocated memory.
233 static char * StructPos (const char * buf);
234 static char * MidMarkerPos (const char * buf);
235 static char * CallerMemPos (const char * buf);
236 static char * EndMarkerPos (const char * buf, const size_t size);
237
238 // Given a pointer to the start of the caller requested area
239 // return a pointer to the start of the entire alloc\'d buffer.
240 static char * StartPos (const char * caller);
241
242 // Access to the list.
243 static wxMemStruct * GetHead () { return m_head; }
244 static wxMemStruct * GetTail () { return m_tail; }
245
246 // Set the list sentinals.
247 static wxMemStruct * SetHead (wxMemStruct * st) { return (m_head = st); }
248 static wxMemStruct * SetTail (wxMemStruct * st) { return (m_tail = st); }
249
250 // If this is set then every new operation checks the validity
251 // of the all previous nodes in the list.
252 static bool GetCheckPrevious () { return m_checkPrevious; }
253 static void SetCheckPrevious (bool value) { m_checkPrevious = value; }
254
255 // Checks all nodes, or all nodes if checkAll is true
256 static int Check(bool checkAll = false);
257
258 // Print out the list of wxMemStruct nodes.
259 static bool PrintList(void);
260
261 // Dump objects
262 static bool Dump(void);
263
264 // Print statistics
265 static bool PrintStatistics(bool detailed = true);
266
267 // Print out the classes in the application.
268 static bool PrintClasses(void);
269
270 // Count the number of non-wxDebugContext-related objects
271 // that are outstanding
272 static int CountObjectsLeft(bool sinceCheckpoint = false);
273
274 // This function is used to output the dump
275 static void OutputDumpLine(const wxChar *szFormat, ...);
276
277 private:
278 // Store these here to allow access to the list without
279 // needing to have a wxMemStruct object.
280 static wxMemStruct* m_head;
281 static wxMemStruct* m_tail;
282
283 // Set to false if we're not checking all previous nodes when
284 // we do a new. Set to true when we are.
285 static bool m_checkPrevious;
286 };
287
288 // Final cleanup (e.g. deleting the log object and doing memory leak checking)
289 // will be delayed until all wxDebugContextDumpDelayCounter objects have been
290 // destructed. Adding one wxDebugContextDumpDelayCounter per file will delay
291 // memory leak checking until after destructing all global objects.
292 class WXDLLIMPEXP_BASE wxDebugContextDumpDelayCounter
293 {
294 public:
295 wxDebugContextDumpDelayCounter() {
296 sm_count++;
297 }
298
299 ~wxDebugContextDumpDelayCounter() {
300 sm_count--;
301 if(!sm_count) DoDump();
302 }
303 private:
304 void DoDump();
305 static int sm_count;
306 };
307
308 // make leak dump after all globals have been destructed
309 static wxDebugContextDumpDelayCounter wxDebugContextDumpDelayCounter_File;
310 #define WXDEBUG_DUMPDELAYCOUNTER \
311 static wxDebugContextDumpDelayCounter wxDebugContextDumpDelayCounter_Extra;
312
313 // Output a debug message, in a system dependent fashion.
314 void WXDLLIMPEXP_BASE wxTrace(const wxChar *fmt ...) ATTRIBUTE_PRINTF_1;
315 void WXDLLIMPEXP_BASE wxTraceLevel(int level, const wxChar *fmt ...) ATTRIBUTE_PRINTF_2;
316
317 #define WXTRACE wxTrace
318 #define WXTRACELEVEL wxTraceLevel
319
320 #else // (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
321
322 #define WXDEBUG_DUMPDELAYCOUNTER
323
324 // Borland C++ Builder 6 seems to have troubles with inline functions (see bug
325 // 819700)
326 #if 0
327 inline void wxTrace(const wxChar *WXUNUSED(fmt)) {}
328 inline void wxTraceLevel(int WXUNUSED(level), const wxChar *WXUNUSED(fmt)) {}
329 #else
330 #define wxTrace(fmt)
331 #define wxTraceLevel(l, fmt)
332 #endif
333
334 #define WXTRACE true ? (void)0 : wxTrace
335 #define WXTRACELEVEL true ? (void)0 : wxTraceLevel
336
337 #endif // (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
338
339 #endif
340 // _WX_MEMORYH__
341