0023393: Improve usability of OSD_MAllocHook::CollectBySize
[occt.git] / src / OSD / OSD_MAllocHook.hxx
1 // Created on: 2011-02-03
2 // Created by: Mikhail SAZONOV
3 // Copyright (c) 2011-2012 OPEN CASCADE SAS
4 //
5 // The content of this file is subject to the Open CASCADE Technology Public
6 // License Version 6.5 (the "License"). You may not use the content of this file
7 // except in compliance with the License. Please obtain a copy of the License
8 // at http://www.opencascade.org and read it completely before using this file.
9 //
10 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12 //
13 // The Original Code and all software distributed under the License is
14 // distributed on an "AS IS" basis, without warranty of any kind, and the
15 // Initial Developer hereby disclaims all such warranties, including without
16 // limitation, any warranties of merchantability, fitness for a particular
17 // purpose or non-infringement. Please see the License for the specific terms
18 // and conditions governing the rights and limitations under the License.
19
20
21 #ifndef _OSD_MAllocHook_HeaderFile
22 #define _OSD_MAllocHook_HeaderFile
23
24 #include <Standard_TypeDef.hxx>
25 #include <Standard_Mutex.hxx>
26 #include <stdio.h>
27
28 /**
29  * This class provides the possibility to set callback for memory
30  * allocation/deallocation.
31  * On MS Windows, it works only in Debug builds. It relies on the
32  * debug CRT function _CrtSetAllocHook (see MSDN for help).
33  */
34 class OSD_MAllocHook
35 {
36 public:
37   /**
38    * Interface of a class that should handle allocation/deallocation events
39    */
40   class Callback
41   {
42   public:
43     //! Allocation event handler
44     /**
45      * It is called when allocation is done
46      * @param theSize
47      *   the size of the memory block in bytes
48      * @param theRequestNum
49      *   the allocation order number of the memory block
50      */
51     virtual void AllocEvent
52                    (size_t      theSize,
53                     long        theRequestNum) = 0;
54
55     //! Freeing event handler
56     /**
57      * It is called when the block is freed
58      * @param theData
59      *   the pointer to the user data section of the memory block
60      * @param theSize
61      *   the size of the memory block in bytes
62      * @param theRequestNum
63      *   the allocation order number of the memory block
64      */
65     virtual void FreeEvent
66                    (void*       theData,
67                     size_t      theSize,
68                     long        theRequestNum) = 0;
69   };
70
71   /**
72    * Implementation of the handler that collects all events
73    * to the log file. It contains the method to generate the report
74    * from the log file.
75    */
76   class LogFileHandler: public Callback
77   {
78   public:
79     //! Constructor
80     Standard_EXPORT LogFileHandler();
81
82     //! Destructor
83     Standard_EXPORT ~LogFileHandler();
84
85     //! Create the file and start collecting events.
86     //! Return false if the file with the given name cannot be created.
87     Standard_EXPORT Standard_Boolean Open(const char* theFileName);
88
89     //! Close the file and stop collecting events
90     Standard_EXPORT void Close();
91
92     //! Make synthesized report on the given log file.
93     /**
94      * Generate an easy to use report in the
95      * new file with the given name, taking the given log file as input.
96      * If theIncludeAlive is true then
97      * include into the report the alive allocation numbers.
98      */
99     Standard_EXPORT static Standard_Boolean MakeReport
100                    (const char* theLogFile,
101                     const char* theOutFile,
102                     const Standard_Boolean theIncludeAlive = Standard_False);
103
104     Standard_EXPORT virtual void AllocEvent(size_t, long);
105     Standard_EXPORT virtual void FreeEvent(void*, size_t, long);
106
107   private:
108     FILE*          myLogFile;
109     Standard_Mutex myMutex;
110     size_t         myBreakSize;
111   };
112
113   /**
114    * Implementation of the handler that collects numbers of
115    * allocations/deallocations for each block size directly in the memory.
116    */
117   class CollectBySize: public Callback
118   {
119   public:
120     //! Constructor
121     Standard_EXPORT CollectBySize();
122
123     //! Destructor
124     Standard_EXPORT ~CollectBySize();
125
126     //! Reset the buffer and start collecting events.
127     Standard_EXPORT void Reset();
128
129     //! Write report in the given file.
130     Standard_EXPORT Standard_Boolean MakeReport(const char* theOutFile);
131
132     Standard_EXPORT virtual void AllocEvent(size_t, long);
133     Standard_EXPORT virtual void FreeEvent(void*, size_t, long);
134
135   public:
136     struct Numbers
137     {
138       int nbAlloc;
139       int nbFree;
140       int nbLeftPeak;
141       Numbers() : nbAlloc(0), nbFree(0), nbLeftPeak(0) {}
142     };
143     
144     static const size_t myMaxAllocSize; //!< maximum tracked size
145
146     Standard_Mutex myMutex;             //!< used for thread-safe access
147     Numbers*       myArray;             //!< indexed from 0 to myMaxAllocSize-1
148     ptrdiff_t      myTotalLeftSize;     //!< currently remained allocated size
149     size_t         myTotalPeakSize;     //!< maxium cumulative allocated size
150     size_t         myBreakSize;
151   };
152
153   //! Set handler of allocation/deallocation events
154   /**
155    * You can pass here any implementation. For easy start, you can try
156    * with the predefined handler LogFileHandler, which static instance 
157    * is returned by GetLogFileHandler().
158    * To clear the handler, pass NULL here.
159    */
160   Standard_EXPORT static void SetCallback
161                    (Callback* theCB);
162
163   //! Get current handler of allocation/deallocation events
164   Standard_EXPORT static Callback* GetCallback();
165
166   //! Get static instance of LogFileHandler handler
167   Standard_EXPORT static LogFileHandler* GetLogFileHandler();
168
169   //! Get static instance of CollectBySize handler
170   Standard_EXPORT static CollectBySize* GetCollectBySize();
171 };
172
173 #endif /* _OSD_MAllocHook_HeaderFile */