0024510: Remove unused local variables
[occt.git] / src / NCollection / NCollection_BaseAllocator.cxx
CommitLineData
b311480e 1// Created on: 2002-04-12
2// Created by: Alexander KARTOMIN (akm)
973c2be1 3// Copyright (c) 2002-2014 OPEN CASCADE SAS
b311480e 4//
973c2be1 5// This file is part of Open CASCADE Technology software library.
b311480e 6//
973c2be1 7// This library is free software; you can redistribute it and / or modify it
8// under the terms of the GNU Lesser General Public version 2.1 as published
9// by the Free Software Foundation, with special exception defined in the file
10// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11// distribution for complete text of the license and disclaimer of any warranty.
b311480e 12//
973c2be1 13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
b311480e 15
7fd59977 16// Purpose: Implementation of the BaseAllocator class
17
18#include <NCollection_BaseAllocator.hxx>
19#include <NCollection_DataMap.hxx>
23be7421 20#include <NCollection_Map.hxx>
7fd59977 21#include <NCollection_List.hxx>
22#include <Standard_Mutex.hxx>
64531d9c 23#include <fstream>
24#include <iomanip>
7fd59977 25
26IMPLEMENT_STANDARD_HANDLE(NCollection_BaseAllocator,MMgt_TShared)
27IMPLEMENT_STANDARD_RTTIEXT(NCollection_BaseAllocator,MMgt_TShared)
28
29//=======================================================================
30//function : Allocate
31//purpose : Standard allocation
32//=======================================================================
33
34void* NCollection_BaseAllocator::Allocate(const size_t size)
35{
36 return Standard::Allocate(size);
37}
38
39//=======================================================================
40//function : Free
41//purpose : Standard deallocation
42//=======================================================================
43
44void NCollection_BaseAllocator::Free(void *anAddress)
45{
547702a1 46 if (anAddress) Standard::Free(anAddress);
7fd59977 47}
48
49//=======================================================================
50//function : CommonBaseAllocator
51//purpose : Creates the only one BaseAllocator
52//=======================================================================
53
54const Handle(NCollection_BaseAllocator)&
55 NCollection_BaseAllocator::CommonBaseAllocator(void)
56{
57 static Handle(NCollection_BaseAllocator) pAllocator =
58 new NCollection_BaseAllocator;
59 return pAllocator;
60}
61
62// global variable to ensure that allocator will be created during loading the library
63static Handle(NCollection_BaseAllocator) theAllocInit =
64 NCollection_BaseAllocator::CommonBaseAllocator();
65
66//=======================================================================
23be7421
M
67/**
68 * Structure for collecting statistics about blocks of one size
69 */
7fd59977 70//=======================================================================
7fd59977 71struct StorageInfo
72{
73 Standard_Size roundSize;
74 int nbAlloc;
75 int nbFree;
76 StorageInfo()
77 : roundSize(0), nbAlloc(0), nbFree(0) {}
78 StorageInfo(Standard_Size theSize)
79 : roundSize(theSize), nbAlloc(0), nbFree(0) {}
80};
81
23be7421
M
82//=======================================================================
83/**
84 * Static data map (block_size -> StorageInfo)
85 */
86//=======================================================================
87static NCollection_DataMap<Standard_Size, StorageInfo>& StorageMap()
88{
89 static NCollection_IncAllocator TheAlloc;
90 static NCollection_DataMap<Standard_Size, StorageInfo>
91 TheMap (1, & TheAlloc);
92 return TheMap;
93}
94
95//=======================================================================
96/**
97 * Static data map (address -> AllocationID)
98 */
99//=======================================================================
100static NCollection_DataMap<Standard_Address, Standard_Size>& StorageIDMap()
101{
102 static NCollection_IncAllocator TheAlloc;
103 static NCollection_DataMap<Standard_Address, Standard_Size>
104 TheMap (1, & TheAlloc);
105 return TheMap;
106}
107
108//=======================================================================
109/**
110 * Static map (AllocationID)
111 */
112//=======================================================================
113static NCollection_Map<Standard_Size>& StorageIDSet()
114{
115 static NCollection_IncAllocator TheAlloc;
116 static NCollection_Map<Standard_Size> TheMap (1, & TheAlloc);
117 return TheMap;
118}
119
120//=======================================================================
121/**
122 * Exported value to set the block size for which it is required
123 * collecting alive allocation IDs.
124 * The method NCollection_BaseAllocator::PrintMemUsageStatistics
125 * dumps all alive IDs into the file alive.d in the current directory.
126 */
127//=======================================================================
128Standard_EXPORT Standard_Size& StandardCallBack_CatchSize()
129{
130 static Standard_Size Value = 0;
131 return Value;
132}
133
134//=======================================================================
135/**
136 * Exported value to set the allocation ID for which it is required
137 * to set a breakpoint on the moment of allocation or freeing.
138 * See the method NCollection_BaseAllocator::StandardCallBack
139 * where the value StandardCallBack_CatchID() is compared to the current ID.
140 * There you can place a break point at the stub assignment statement "a =".
141 */
142//=======================================================================
143Standard_EXPORT Standard_Size& StandardCallBack_CatchID()
144{
145 static Standard_Size Value = 0;
146 return Value;
147}
148
149//=======================================================================
150/**
151 * Static value of the current allocation ID. It provides unique
152 * numbering of allocation events.
153 */
154//=======================================================================
155static Standard_Size CurrentID = 0;
156
157//=======================================================================
158/**
159 * Exported function to reset the callback system to the initial state
160 */
161//=======================================================================
162Standard_EXPORT void StandardCallBack_Reset()
163{
164 StorageMap().Clear();
165 StorageIDMap().Clear();
166 StorageIDSet().Clear();
167 CurrentID = 0;
168 StandardCallBack_CatchSize() = 0;
169 StandardCallBack_CatchID() = 0;
170}
171
96a95605
DB
172namespace {
173 // dummy function for break point
174 inline void place_for_break_point () {}
175};
176
23be7421
M
177//=======================================================================
178//function : StandardCallBack
179//purpose : Callback function to register alloc/free calls
180//=======================================================================
7fd59977 181
182void NCollection_BaseAllocator::StandardCallBack
183 (const Standard_Boolean theIsAlloc,
23be7421 184 const Standard_Address theStorage,
7fd59977 185 const Standard_Size theRoundSize,
186 const Standard_Size /*theSize*/)
187{
23be7421 188 static Standard_Mutex aMutex;
bd0c22ce 189 aMutex.Lock();
23be7421
M
190 // statistics by storage size
191 NCollection_DataMap<Standard_Size, StorageInfo>& aStMap = StorageMap();
192 if (!aStMap.IsBound(theRoundSize))
7fd59977 193 {
194 StorageInfo aEmpty(theRoundSize);
23be7421 195 aStMap.Bind(theRoundSize, aEmpty);
7fd59977 196 }
23be7421 197 StorageInfo& aInfo = aStMap(theRoundSize);
7fd59977 198 if (theIsAlloc)
199 aInfo.nbAlloc++;
200 else
201 aInfo.nbFree++;
23be7421
M
202
203 if (theRoundSize == StandardCallBack_CatchSize())
204 {
205 // statistics by alive objects
206 NCollection_DataMap<Standard_Address, Standard_Size>& aStIDMap = StorageIDMap();
207 NCollection_Map<Standard_Size>& aStIDSet = StorageIDSet();
23be7421
M
208 if (theIsAlloc)
209 {
210 aStIDMap.Bind(theStorage, ++CurrentID);
211 aStIDSet.Add(CurrentID);
212 if (CurrentID == StandardCallBack_CatchID())
213 {
214 // Place for break point for allocation of investigated ID
96a95605 215 place_for_break_point();
23be7421
M
216 }
217 }
218 else
219 {
220 if (aStIDMap.IsBound(theStorage))
221 {
222 Standard_Size anID = aStIDMap(theStorage);
223 aStIDSet.Remove(anID);
224 if (anID == StandardCallBack_CatchID())
225 {
226 // Place for break point for freeing of investigated ID
96a95605 227 place_for_break_point();
23be7421
M
228 }
229 }
230 }
231 }
232
bd0c22ce 233 aMutex.Unlock();
7fd59977 234}
235
236//=======================================================================
237//function : PrintMemUsageStatistics
238//purpose : Prints memory usage statistics cumulated by StandardCallBack
239//=======================================================================
240
241void NCollection_BaseAllocator::PrintMemUsageStatistics()
242{
243 // sort by roundsize
244 NCollection_List<StorageInfo> aColl;
245 NCollection_List<StorageInfo>::Iterator itLst;
23be7421 246 NCollection_DataMap<Standard_Size, StorageInfo>::Iterator itMap(StorageMap());
7fd59977 247 for (; itMap.More(); itMap.Next())
248 {
249 for (itLst.Init(aColl); itLst.More(); itLst.Next())
250 if (itMap.Value().roundSize < itLst.Value().roundSize)
251 break;
252 if (itLst.More())
253 aColl.InsertBefore(itMap.Value(), itLst);
254 else
255 aColl.Append(itMap.Value());
256 }
257 Standard_Size aTotAlloc = 0;
258 Standard_Size aTotLeft = 0;
64531d9c 259
7fd59977 260 // print
64531d9c 261 std::ofstream aFileOut ("memstat.d", std::ios_base::trunc | std::ios_base::out);
262 if (!aFileOut.is_open())
23be7421 263 {
64531d9c 264 std::cout << "failure writing file memstat.d" << std::endl;
23be7421
M
265 return;
266 }
64531d9c 267 aFileOut.imbue (std::locale ("C"));
268
269 // header
270 aFileOut << std::setw(20) << "BlockSize" << ' '
271 << std::setw(12) << "NbAllocated" << ' '
272 << std::setw(12) << "NbLeft" << ' '
273 << std::setw(20) << "Allocated" << ' '
274 << std::setw(20) << "Left" << '\n';
275
276 // body
7fd59977 277 for (itLst.Init(aColl); itLst.More(); itLst.Next())
278 {
279 const StorageInfo& aInfo = itLst.Value();
280 Standard_Integer nbLeft = aInfo.nbAlloc - aInfo.nbFree;
281 Standard_Size aSizeAlloc = aInfo.nbAlloc * aInfo.roundSize;
282 Standard_Size aSizeLeft = nbLeft * aInfo.roundSize;
64531d9c 283
284 aFileOut << std::setw(20) << aInfo.roundSize << ' '
285 << std::setw(12) << aInfo.nbAlloc << ' '
286 << std::setw(12) << nbLeft << ' '
287 << std::setw(20) << aSizeAlloc << ' '
288 << std::setw(20) << aSizeLeft << '\n';
289
7fd59977 290 aTotAlloc += aSizeAlloc;
64531d9c 291 aTotLeft += aSizeLeft;
7fd59977 292 }
64531d9c 293
294 // footer
295 aFileOut << std::setw(20) << "Total:" << ' '
296 << std::setw(12) << "" << ' '
297 << std::setw(12) << "" << ' '
298 << std::setw(20) << aTotAlloc << ' '
299 << std::setw(20) << aTotLeft << '\n';
23be7421
M
300
301 if (!StorageIDSet().IsEmpty())
302 {
64531d9c 303 aFileOut << "Alive allocation numbers of size=" << StandardCallBack_CatchSize() << '\n';
304 for (NCollection_Map<Standard_Size>::Iterator itMap1(StorageIDSet()); itMap1.More(); itMap1.Next())
305 {
306 aFileOut << itMap1.Key() << '\n';
307 }
23be7421 308 }
64531d9c 309 aFileOut.close();
7fd59977 310}