Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/OgreMain/include/OgreMemoryManager.h @ 5

Last change on this file since 5 was 5, checked in by anonymous, 17 years ago

=hoffentlich gehts jetzt

File size: 16.8 KB
Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4(Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org/
6
7Copyright (c) 2000-2006 Torus Knot Software Ltd
8Also see acknowledgements in Readme.html
9
10This program is free software; you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation; either version 2 of the License, or (at your option) any later
13version.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public License along with
20this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://www.gnu.org/copyleft/lesser.txt.
23
24You may alternatively use this source under the terms of a specific version of
25the OGRE Unrestricted License provided you have obtained such a license from
26Torus Knot Software Ltd.
27-----------------------------------------------------------------------------
28*/
29//---- ORIGINAL COPYRIGHT FOLLOWS -------------------------------------------
30// ---------------------------------------------------------------------------------------------------------------------------------
31// Copyright 2000, Paul Nettle. All rights reserved.
32//
33// You are free to use this source code in any commercial or non-commercial product.
34//
35// mmgr.cpp - Memory manager & tracking software
36//
37// The most recent version of this software can be found at: ftp://ftp.GraphicsPapers.com/pub/ProgrammingTools/MemoryManagers/
38//
39// [NOTE: Best when viewed with 8-character tabs]
40//
41// ---------------------------------------------------------------------------------------------------------------------------------
42#ifndef __MemoryManager_H__
43#define __MemoryManager_H__
44
45#include "OgrePlatform.h"
46#include "OgreStdHeaders.h"
47
48namespace Ogre {
49
50    /** @page memory_manager The memory manager information page
51       
52                @subsection desc Description
53                        The memory manager is a class that handles memory (de)allocation requests.
54        @par
55            This class works like a wrapper between the actual C memory allocation
56            functions (*alloc, free) and the memory (de)allocation requests of the
57            application.
58        @par
59            Why would such a class be needed? First of all, because we had some
60            major issues with memory getting misued (read: deleted) over DLL
61            boundaries. One thing this memory manager does is solve the problem by
62            allocating all the memory in the OgreMain.dll/so process.
63        @par
64            Another use would be leak detection and memory misuse detection. With
65            a custom memory manager, calls to new/delete and *alloc/free could be
66            overseed and logged.
67        @par
68            Yet another use is the optimization of memory allocation for certain
69            object types. One of the most common examples is a small object
70            allocator.
71                @subsection types Manager types
72                        There actually are two classes, one is the standard memory manager
73                        which only addresses memory allocation problems when deallocating
74                        across processes.
75                @par
76                        The other is a modified version of the debugging memory manager written
77                        by Paul 'MidNight' Nettle (aka. the Fluid Studios Memory Manager).
78                        Obviously, the second one should be used only when debugging your
79                        application as it adds some visible overhead.
80                @par
81                        You can switch between the two memory managers by setting the value of
82                        the OGRE_DEBUG_MEMORY_MANAGER macro in OgreConfig.h
83        @subsection notes Implementation Note
84            The class contains a static member of type MemoryManager. That is
85            because we want the memory manager to be created even before we
86            override the new([])/delete([]) operators.
87                @subsection see See also
88                        <a href="http://www.flipcode.com/cgi-bin/msg.cgi?showThread=12September2000-PresentingAMemoryManager&forum=askmid&id=-1">Paul Nettle's Memory Manager page at flipCode</a> - you can get the original source form here.
89    */
90
91#if OGRE_DEBUG_MEMORY_MANAGER && OGRE_DEBUG_MODE
92
93#ifndef __FUNCTION__
94#define __FUNCTION__ "???"
95#endif
96
97}
98
99//-----------------------------------------------------------------------------
100// We have to declare the global new([])/delete([]) operators before declaring
101// the Ogre::MemoryManager class since it lists them as friend functions
102void *operator new(size_t reportedSize);
103void *operator new[](size_t reportedSize);
104void operator delete(void *reportedAddress);
105void operator delete[](void *reportedAddress);
106//-----------------------------------------------------------------------------
107
108namespace Ogre {
109
110    /** For internal use only.
111        \internal.
112        @remarks
113            This structure holds the allocation tracking information. So,
114            for each allocation made, the overhead this memory manager adds
115            is the size of this structure, the lengths of the names of the
116            file and function in which the allocation was made and the
117            padding size (which can be adjusted).
118    */
119    typedef struct tag_au
120    {
121        size_t actualSize;
122        size_t reportedSize;
123
124        void *actualAddress;
125        void *reportedAddress;
126
127        char sourceFile[40];
128        char sourceFunc[40];
129
130        unsigned int sourceLine;
131        unsigned int allocationType;
132
133        bool breakOnDealloc;
134        bool breakOnRealloc;
135
136        unsigned int allocationNumber;
137        unsigned int processID;
138
139        struct tag_au *next;
140        struct tag_au *prev;
141    } sAllocUnit;
142
143    typedef struct
144    {
145        size_t totalReportedMemory;
146        size_t totalActualMemory;
147
148        size_t peakReportedMemory;
149        size_t peakActualMemory;
150
151        size_t accumulatedReportedMemory;
152        size_t accumulatedActualMemory;
153        size_t accumulatedAllocUnitCount;
154
155        size_t totalAllocUnitCount;
156        size_t peakAllocUnitCount;
157    } sMStats;
158   
159    enum
160    {
161        m_alloc_unknown        = 0,
162        m_alloc_new            = 1,
163        m_alloc_new_array      = 2,
164        m_alloc_malloc         = 3,
165        m_alloc_calloc         = 4,
166        m_alloc_realloc        = 5,
167        m_alloc_delete         = 6,
168        m_alloc_delete_array   = 7,
169        m_alloc_free           = 8
170    };
171
172        /** See the \ref memory_manager.
173        */
174    class _OgreExport MemoryManager
175    {
176        friend void * ::operator new(size_t);
177        friend void * ::operator new[](size_t);
178        friend void ::operator delete(void*);
179        friend void ::operator delete[](void*);
180
181    public:
182        static MemoryManager& instance(void);
183
184    private:
185        /// This is used in the process tracking part of the memory manager.
186        unsigned m_uProcessIDs;
187        /// This is set to true when deinitialization takes place.
188        bool m_bDeinitTime;
189
190#ifndef __BORLANDC__
191    private:
192#else
193    public:
194#endif
195        //-------------------------------------------------------------------------
196        // Wrappers for the new/delete functions       
197        void *op_new_sc( size_t reportedSize, unsigned processID );
198        void *op_new_vc( size_t reportedSize, unsigned processID );
199
200        void *op_new_sc( size_t reportedSize, const char *sourceFile, int sourceLine, unsigned processID );
201        void *op_new_vc( size_t reportedSize, const char *sourceFile, int sourceLine, unsigned processID );
202
203        void op_del_sc( void *reportedAddress, unsigned processID );
204        void op_del_vc( void *reportedAddress, unsigned processID );
205        //-------------------------------------------------------------------------
206
207        /** This function is intended for internal use only.
208            \internal
209            @remarks
210                This function is used to return an unique handle for each process
211                calling it. The returned unsigned int is then passed to the memory
212                manager every time a re/de/allocation request is made, in order
213                to check that deallocations don't occur in processes other than the
214                ones in which allcations were made and so on.
215            @par
216                Actually, the problem of re/de/allocating in other processes was
217                solved with the addition of the new memory manager, but you may
218                want to limit the occurence of such events anyway, and this function
219                helps you do just that.
220        */
221        unsigned _getProcessID();
222
223    public:
224        MemoryManager();
225        ~MemoryManager();
226
227        //-------------------------------------------------------------------------
228        // Used by the macros     
229        void setOwner(const char *file, const unsigned int line, const char *func);
230        //-------------------------------------------------------------------------
231
232        //-------------------------------------------------------------------------
233        // Allocation breakpoints       
234        bool &breakOnRealloc(void *reportedAddress);
235        bool &breakOnDealloc( void *reportedAddress );
236        void breakOnAlloc( unsigned int count );
237        //-------------------------------------------------------------------------
238
239        //-------------------------------------------------------------------------
240        // The meat & potatoes of the memory tracking software
241
242        /** This function is intended for internal use only.
243            \internal
244            @remarks
245                This function is the actual memory allocator and acts as a bridge
246                between OGRE and the C/C++ alloc/calloc functions.
247            @par
248                While memory allocation requests are made trough this function,
249                the tracking of memory addresses is possible. Therefore, attempting
250                to deallocate a portion of memory that was not allocated using
251                this function will result in a warning given by the deallocator,
252                dllocMem.
253        */
254        void * allocMem(
255            const char *sourceFile, 
256            const unsigned int sourceLine, 
257            const char *sourceFunc,
258            const unsigned int allocationType, 
259            const size_t reportedSize, 
260            const unsigned processID );
261
262        /** This function is intended for internal use only.
263            \internal
264            @remarks
265                This function is the actual memory reallocator and acts as a bridge
266                between OGRE and the C/C++ realloc function.
267            @par
268                While memory reallocation requests are made trough this function,
269                the tracking of memory addresses is possible. Therefore, attempting
270                to deallocate a portion of memory that was not reallocated using
271                this function will result in a warning given by the deallocator,
272                dllocMem.
273            @par
274                As well, trying to reallocate memory that was not allocated using
275                mallc/calloc will result in a warning.
276        */
277        void * rllocMem(
278            const char *sourceFile, 
279            const unsigned int sourceLine, 
280            const char *sourceFunc,
281            const unsigned int reallocationType, 
282            const size_t reportedSize, 
283            void *reportedAddress, 
284            const unsigned processID );
285
286        /** This function is intended for internal use only.
287            \internal
288            @remarks
289                This function is the actual memory deallocator and acts as a
290                bridge between OGRE and the C/C++ free function.
291            @par
292                While memory deallocation requests are made trough this function,
293                the tracking of memory addresses is possible. Therefore, attempting
294                to deallocate a portion of memory that was not allocated using
295                allocMem or rllocMem, trying to deallocate memory that was
296                allocated with malloc using delete (and the corresponding
297                permutations) or trying to deallocate memory allocated from from
298                process will result in a warning.
299            @note
300                Actually, memory can be allocated in one process and deallocated
301                in another, since the actual (de)allocation takes place in the
302                memory space of the OgreMain library.
303            @par
304                Tracking this kind of (possible) errors exists because users may
305                want to write their own memory allocator later on or they'd like
306                to get rid of OGRE's memory allocator.
307        */
308        void dllocMem(
309            const char *sourceFile, 
310            const unsigned int sourceLine, 
311            const char *sourceFunc,
312            const unsigned int deallocationType, 
313            const void *reportedAddress, 
314            const unsigned processID );
315        //-------------------------------------------------------------------------
316
317        //-------------------------------------------------------------------------
318        // Utilitarian functions       
319        bool validateAddr(const void *reportedAddress);
320        bool validateAlloc(const sAllocUnit *allocUnit);
321        bool validateAllAllocs();
322        //-------------------------------------------------------------------------
323
324        //-------------------------------------------------------------------------
325        // Unused RAM calculations       
326        unsigned int calcUnused( const sAllocUnit *allocUnit );
327        unsigned int calcAllUnused();
328        //-------------------------------------------------------------------------
329
330        //-------------------------------------------------------------------------
331        // Logging and reporting       
332        void dumpAllocUnit( const sAllocUnit *allocUnit, const char *prefix = "" );
333        void dumpMemReport( const char *filename = "memreport.log", const bool overwrite = true );
334        sMStats getMemStats();           
335        //-------------------------------------------------------------------------       
336    };
337}
338
339/** This variable exists separately in each module that links to the OGRE library
340    and is used to track the ID of the current process from the perspective
341    of the memory manager.
342    @see
343        unsigned Ogre::MemoryManager::_getProcessID()
344*/
345static unsigned gProcessID = 0;
346
347// When compiling in Visual C++ (occuring in VS2005 Express but not for VC 7.1) with
348// managed C++, should put the new([])/delete([]) overrides inside unmanaged context,
349// otherwise Visual C++ will link with overridden version of new([]) and CRT version
350// of delete([]), thus, mess up both of OGRE memory manager and CRT memory manager.
351#if defined(__cplusplus_cli)
352#pragma managed(push, off)
353#endif
354//-----------------------------------------------------------------------------
355// Overridden global new([])/delete([]) functions
356//
357inline void *operator new(size_t reportedSize)
358{
359    if( !gProcessID )
360        gProcessID = Ogre::MemoryManager::instance()._getProcessID();
361    return Ogre::MemoryManager::instance().op_new_sc( reportedSize, gProcessID );
362}
363inline void *operator new[](size_t reportedSize)
364{
365    if( !gProcessID )
366        gProcessID = Ogre::MemoryManager::instance()._getProcessID();
367    return Ogre::MemoryManager::instance().op_new_vc( reportedSize, gProcessID );
368}
369
370inline void operator delete(void *reportedAddress)
371{
372    Ogre::MemoryManager::instance().op_del_sc( reportedAddress, gProcessID );   
373}
374inline void operator delete[](void *reportedAddress)
375{
376    Ogre::MemoryManager::instance().op_del_vc( reportedAddress, gProcessID );
377}
378//-----------------------------------------------------------------------------
379#if defined(__cplusplus_cli)
380#pragma managed(pop)
381#endif
382
383//-----------------------------------------------------------------------------
384// This header adds the *alloc/free macros, wrapping the C functions
385#include "OgreMemoryMacros.h"
386//-----------------------------------------------------------------------------
387
388#else
389
390        /** See the \ref memory_manager.
391        */
392    class _OgreExport MemoryManager
393    {
394    public:
395        static MemoryManager& instance(void);
396
397        MemoryManager();
398        ~MemoryManager();
399
400        /** Memory allocator - uses plain old malloc.
401        */
402        void *allocMem( const char *szFile, size_t uLine, size_t count ) throw ( );
403
404        /** Memory re-allocator - uses plain old realloc.
405        */
406        void *rllocMem( const char *szFile, size_t uLine, void *ptr , size_t count ) throw ( );
407
408        /** Memory allocator - uses plain old calloc.
409        */
410        void *cllocMem( const char *szFile, size_t uLine, size_t num, size_t size ) throw ( );
411
412        /** Memory de-allocator - uses plain old free.
413        */
414        void dllocMem( const char *szFile, size_t uLine, void *ptr ) throw ( );
415    };
416
417}
418
419#endif
420
421#endif
422
Note: See TracBrowser for help on using the repository browser.