mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-04-02 17:46:22 +03:00
OCC22143 Optimization of memory usage and developing tools for catching memory leaks in OCCT-based applications
This commit is contained in:
parent
416cd0b7ae
commit
23be742115
@ -6,6 +6,7 @@
|
||||
|
||||
#include <NCollection_BaseAllocator.hxx>
|
||||
#include <NCollection_DataMap.hxx>
|
||||
#include <NCollection_Map.hxx>
|
||||
#include <NCollection_List.hxx>
|
||||
#include <Standard_Mutex.hxx>
|
||||
|
||||
@ -50,10 +51,10 @@ static Handle(NCollection_BaseAllocator) theAllocInit =
|
||||
NCollection_BaseAllocator::CommonBaseAllocator();
|
||||
|
||||
//=======================================================================
|
||||
//function : StandardCallBack
|
||||
//purpose : Callback function to register alloc/free calls
|
||||
/**
|
||||
* Structure for collecting statistics about blocks of one size
|
||||
*/
|
||||
//=======================================================================
|
||||
|
||||
struct StorageInfo
|
||||
{
|
||||
Standard_Size roundSize;
|
||||
@ -65,29 +66,157 @@ struct StorageInfo
|
||||
: roundSize(theSize), nbAlloc(0), nbFree(0) {}
|
||||
};
|
||||
|
||||
static NCollection_DataMap<Standard_Size, StorageInfo> StorageMap;
|
||||
//=======================================================================
|
||||
/**
|
||||
* Static data map (block_size -> StorageInfo)
|
||||
*/
|
||||
//=======================================================================
|
||||
static NCollection_DataMap<Standard_Size, StorageInfo>& StorageMap()
|
||||
{
|
||||
static NCollection_IncAllocator TheAlloc;
|
||||
static NCollection_DataMap<Standard_Size, StorageInfo>
|
||||
TheMap (1, & TheAlloc);
|
||||
return TheMap;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
/**
|
||||
* Static data map (address -> AllocationID)
|
||||
*/
|
||||
//=======================================================================
|
||||
static NCollection_DataMap<Standard_Address, Standard_Size>& StorageIDMap()
|
||||
{
|
||||
static NCollection_IncAllocator TheAlloc;
|
||||
static NCollection_DataMap<Standard_Address, Standard_Size>
|
||||
TheMap (1, & TheAlloc);
|
||||
return TheMap;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
/**
|
||||
* Static map (AllocationID)
|
||||
*/
|
||||
//=======================================================================
|
||||
static NCollection_Map<Standard_Size>& StorageIDSet()
|
||||
{
|
||||
static NCollection_IncAllocator TheAlloc;
|
||||
static NCollection_Map<Standard_Size> TheMap (1, & TheAlloc);
|
||||
return TheMap;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
/**
|
||||
* Exported value to set the block size for which it is required
|
||||
* collecting alive allocation IDs.
|
||||
* The method NCollection_BaseAllocator::PrintMemUsageStatistics
|
||||
* dumps all alive IDs into the file alive.d in the current directory.
|
||||
*/
|
||||
//=======================================================================
|
||||
Standard_EXPORT Standard_Size& StandardCallBack_CatchSize()
|
||||
{
|
||||
static Standard_Size Value = 0;
|
||||
return Value;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
/**
|
||||
* Exported value to set the allocation ID for which it is required
|
||||
* to set a breakpoint on the moment of allocation or freeing.
|
||||
* See the method NCollection_BaseAllocator::StandardCallBack
|
||||
* where the value StandardCallBack_CatchID() is compared to the current ID.
|
||||
* There you can place a break point at the stub assignment statement "a =".
|
||||
*/
|
||||
//=======================================================================
|
||||
Standard_EXPORT Standard_Size& StandardCallBack_CatchID()
|
||||
{
|
||||
static Standard_Size Value = 0;
|
||||
return Value;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
/**
|
||||
* Static value of the current allocation ID. It provides unique
|
||||
* numbering of allocation events.
|
||||
*/
|
||||
//=======================================================================
|
||||
static Standard_Size CurrentID = 0;
|
||||
|
||||
//=======================================================================
|
||||
/**
|
||||
* Exported function to reset the callback system to the initial state
|
||||
*/
|
||||
//=======================================================================
|
||||
Standard_EXPORT void StandardCallBack_Reset()
|
||||
{
|
||||
StorageMap().Clear();
|
||||
StorageIDMap().Clear();
|
||||
StorageIDSet().Clear();
|
||||
CurrentID = 0;
|
||||
StandardCallBack_CatchSize() = 0;
|
||||
StandardCallBack_CatchID() = 0;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : StandardCallBack
|
||||
//purpose : Callback function to register alloc/free calls
|
||||
//=======================================================================
|
||||
|
||||
void NCollection_BaseAllocator::StandardCallBack
|
||||
(const Standard_Boolean theIsAlloc,
|
||||
const Standard_Address /*theStorage*/,
|
||||
const Standard_Address theStorage,
|
||||
const Standard_Size theRoundSize,
|
||||
const Standard_Size /*theSize*/)
|
||||
{
|
||||
static int aLock = 0;
|
||||
if (aLock)
|
||||
return;
|
||||
aLock = 1;
|
||||
if (!StorageMap.IsBound(theRoundSize))
|
||||
static Standard_Mutex aMutex;
|
||||
Standard_Boolean isReentrant = Standard::IsReentrant();
|
||||
if (isReentrant)
|
||||
aMutex.Lock();
|
||||
// statistics by storage size
|
||||
NCollection_DataMap<Standard_Size, StorageInfo>& aStMap = StorageMap();
|
||||
if (!aStMap.IsBound(theRoundSize))
|
||||
{
|
||||
StorageInfo aEmpty(theRoundSize);
|
||||
StorageMap.Bind(theRoundSize, aEmpty);
|
||||
aStMap.Bind(theRoundSize, aEmpty);
|
||||
}
|
||||
StorageInfo& aInfo = StorageMap(theRoundSize);
|
||||
StorageInfo& aInfo = aStMap(theRoundSize);
|
||||
if (theIsAlloc)
|
||||
aInfo.nbAlloc++;
|
||||
else
|
||||
aInfo.nbFree++;
|
||||
aLock = 0;
|
||||
|
||||
if (theRoundSize == StandardCallBack_CatchSize())
|
||||
{
|
||||
// statistics by alive objects
|
||||
NCollection_DataMap<Standard_Address, Standard_Size>& aStIDMap = StorageIDMap();
|
||||
NCollection_Map<Standard_Size>& aStIDSet = StorageIDSet();
|
||||
int a;
|
||||
if (theIsAlloc)
|
||||
{
|
||||
aStIDMap.Bind(theStorage, ++CurrentID);
|
||||
aStIDSet.Add(CurrentID);
|
||||
if (CurrentID == StandardCallBack_CatchID())
|
||||
{
|
||||
// Place for break point for allocation of investigated ID
|
||||
a = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (aStIDMap.IsBound(theStorage))
|
||||
{
|
||||
Standard_Size anID = aStIDMap(theStorage);
|
||||
aStIDSet.Remove(anID);
|
||||
if (anID == StandardCallBack_CatchID())
|
||||
{
|
||||
// Place for break point for freeing of investigated ID
|
||||
a = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isReentrant)
|
||||
aMutex.Unlock();
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
@ -100,7 +229,7 @@ void NCollection_BaseAllocator::PrintMemUsageStatistics()
|
||||
// sort by roundsize
|
||||
NCollection_List<StorageInfo> aColl;
|
||||
NCollection_List<StorageInfo>::Iterator itLst;
|
||||
NCollection_DataMap<Standard_Size, StorageInfo>::Iterator itMap(StorageMap);
|
||||
NCollection_DataMap<Standard_Size, StorageInfo>::Iterator itMap(StorageMap());
|
||||
for (; itMap.More(); itMap.Next())
|
||||
{
|
||||
for (itLst.Init(aColl); itLst.More(); itLst.Next())
|
||||
@ -114,20 +243,34 @@ void NCollection_BaseAllocator::PrintMemUsageStatistics()
|
||||
Standard_Size aTotAlloc = 0;
|
||||
Standard_Size aTotLeft = 0;
|
||||
// print
|
||||
printf("%12s %12s %12s %12s %12s\n",
|
||||
"BlockSize", "NbAllocated", "NbLeft", "Allocated", "Left");
|
||||
FILE * ff = fopen("memstat.d", "wt");
|
||||
if (ff == NULL)
|
||||
{
|
||||
cout << "failure writing file memstat.d" << endl;
|
||||
return;
|
||||
}
|
||||
fprintf(ff, "%12s %12s %12s %12s %12s\n",
|
||||
"BlockSize", "NbAllocated", "NbLeft", "Allocated", "Left");
|
||||
for (itLst.Init(aColl); itLst.More(); itLst.Next())
|
||||
{
|
||||
const StorageInfo& aInfo = itLst.Value();
|
||||
Standard_Integer nbLeft = aInfo.nbAlloc - aInfo.nbFree;
|
||||
Standard_Size aSizeAlloc = aInfo.nbAlloc * aInfo.roundSize;
|
||||
Standard_Size aSizeLeft = nbLeft * aInfo.roundSize;
|
||||
printf("%12d %12d %12d %12d %12d\n", aInfo.roundSize,
|
||||
aInfo.nbAlloc, nbLeft, aSizeAlloc, aSizeLeft);
|
||||
fprintf(ff, "%12d %12d %12d %12d %12d\n", aInfo.roundSize,
|
||||
aInfo.nbAlloc, nbLeft, aSizeAlloc, aSizeLeft);
|
||||
aTotAlloc += aSizeAlloc;
|
||||
aTotLeft += aSizeLeft;
|
||||
}
|
||||
printf("%12s %12s %12s %12d %12d\n", "Total:", "", "",
|
||||
aTotAlloc, aTotLeft);
|
||||
fflush(stdout);
|
||||
fprintf(ff, "%12s %12s %12s %12d %12d\n", "Total:", "", "",
|
||||
aTotAlloc, aTotLeft);
|
||||
|
||||
if (!StorageIDSet().IsEmpty())
|
||||
{
|
||||
fprintf(ff, "Alive allocation numbers of size=%d\n", StandardCallBack_CatchSize());
|
||||
NCollection_Map<Standard_Size>::Iterator itMap1(StorageIDSet());
|
||||
for (; itMap1.More(); itMap1.Next())
|
||||
fprintf(ff, "%d\n", itMap1.Key());
|
||||
}
|
||||
fclose(ff);
|
||||
}
|
||||
|
@ -87,8 +87,11 @@ void NCollection_BaseList::PPrepend (NCollection_BaseList& theOther)
|
||||
{
|
||||
if (this == &theOther || theOther.IsEmpty())
|
||||
return;
|
||||
|
||||
theOther.myLast->Next() = myFirst;
|
||||
|
||||
if (IsEmpty())
|
||||
myLast = theOther.myLast;
|
||||
else
|
||||
theOther.myLast->Next() = myFirst;
|
||||
myFirst = theOther.myFirst;
|
||||
theOther.myFirst = theOther.myLast = NULL;
|
||||
|
||||
|
@ -48,10 +48,12 @@ NCollection_BaseVector::~NCollection_BaseVector()
|
||||
|
||||
void NCollection_BaseVector::Clear()
|
||||
{
|
||||
for (Standard_Integer i = 0; i < myCapacity; i++)
|
||||
myData[i].Reinit (0, 0);
|
||||
myLength = 0;
|
||||
myNBlocks = 0;
|
||||
if (myLength > 0) {
|
||||
for (Standard_Integer i = 0; i < myCapacity; i++)
|
||||
myData[i].Reinit (0, 0);
|
||||
myLength = 0;
|
||||
myNBlocks = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
@ -104,7 +106,7 @@ NCollection_BaseVector& NCollection_BaseVector::operator =
|
||||
for (Standard_Integer i = 0; i < myCapacity; i++)
|
||||
myData[i].Reinit (0, 0);
|
||||
myDataFree (* this, myData);
|
||||
myCapacity = myIncrement + myLength / myIncrement;
|
||||
myCapacity = GetCapacity(myIncrement) + myLength / myIncrement;
|
||||
myData = myDataInit (* this, myCapacity, NULL, 0);
|
||||
// }
|
||||
return * this;
|
||||
@ -141,7 +143,7 @@ void * NCollection_BaseVector::ExpandV (const Standard_Integer theIndex)
|
||||
myNBlocks + 1 + (theIndex - myLength) / myIncrement;
|
||||
if (myCapacity < nNewBlock) {
|
||||
// Reallocate the array myData
|
||||
do myCapacity += myIncrement; while (myCapacity <= nNewBlock);
|
||||
do myCapacity += GetCapacity(myIncrement); while (myCapacity <= nNewBlock);
|
||||
MemBlock * aNewData = myDataInit (* this, myCapacity, myData, myNBlocks);
|
||||
myDataFree (* this, myData);
|
||||
myData = aNewData;
|
||||
|
@ -8,6 +8,7 @@
|
||||
#define NCollection_BaseVector_HeaderFile
|
||||
|
||||
#include <Standard_TypeDef.hxx>
|
||||
#include <NCollection_BaseAllocator.hxx>
|
||||
#include <stddef.h>
|
||||
|
||||
#if !defined No_Exception && !defined No_Standard_OutOfRange
|
||||
@ -19,6 +20,13 @@
|
||||
#pragma warning(disable:4355)
|
||||
#endif
|
||||
|
||||
// this value defines the number of blocks that are reserved
|
||||
// when the capacity of vector is increased
|
||||
inline Standard_Integer GetCapacity (const Standard_Integer theIncrement)
|
||||
{
|
||||
return Max(theIncrement/8, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Class NCollection_BaseVector - base for generic vector
|
||||
*/
|
||||
@ -28,17 +36,20 @@ class NCollection_BaseVector
|
||||
// ------------ Class MemBlock ------------
|
||||
class MemBlock {
|
||||
protected:
|
||||
MemBlock ()
|
||||
: myFirstInd(0), myLength(0), mySize(0), myData(0L) {}
|
||||
MemBlock (NCollection_BaseAllocator* theAlloc)
|
||||
: myAlloc(theAlloc),
|
||||
myFirstInd(0), myLength(0), mySize(0), myData(0L) {}
|
||||
MemBlock (const Standard_Integer theFirstInd,
|
||||
const Standard_Integer theLength)
|
||||
: myFirstInd(theFirstInd), myLength(0), mySize(theLength), myData(0L) {}
|
||||
virtual ~MemBlock () {}
|
||||
const Standard_Integer theLength,
|
||||
NCollection_BaseAllocator* theAlloc)
|
||||
: myAlloc(theAlloc),
|
||||
myFirstInd(theFirstInd), myLength(0), mySize(theLength), myData(0L) {}
|
||||
virtual void Reinit (const Standard_Integer,
|
||||
const size_t) {}
|
||||
Standard_Integer FirstIndex () const { return myFirstInd; }
|
||||
size_t Size () const { return mySize; }
|
||||
public:
|
||||
virtual ~MemBlock () {}
|
||||
void SetLength (const size_t theLen)
|
||||
{ myLength = theLen; }
|
||||
size_t Length () const { return myLength; }
|
||||
@ -51,6 +62,7 @@ class NCollection_BaseVector
|
||||
Standard_Integer myFirstInd;
|
||||
size_t myLength;
|
||||
size_t mySize;
|
||||
NCollection_BaseAllocator * myAlloc;
|
||||
void * myData;
|
||||
friend class NCollection_BaseVector;
|
||||
};
|
||||
@ -96,11 +108,11 @@ class NCollection_BaseVector
|
||||
NCollection_BaseVector (const size_t theSize,
|
||||
const Standard_Integer theInc,
|
||||
FuncPtrDataInit theDataInit,
|
||||
FuncPtrDataFree theDataFree)
|
||||
FuncPtrDataFree theDataFree)
|
||||
: myItemSize (theSize),
|
||||
myIncrement (theInc),
|
||||
myLength (0),
|
||||
myCapacity (theInc),
|
||||
myCapacity (GetCapacity(myIncrement)),
|
||||
myNBlocks (0),
|
||||
myData (theDataInit (* this, myCapacity, NULL, 0)),
|
||||
myDataInit (theDataInit),
|
||||
@ -114,11 +126,11 @@ class NCollection_BaseVector
|
||||
//! Copy constructor
|
||||
NCollection_BaseVector (const NCollection_BaseVector& theOther,
|
||||
FuncPtrDataInit theDataInit,
|
||||
FuncPtrDataFree theDataFree)
|
||||
FuncPtrDataFree theDataFree)
|
||||
: myItemSize (theOther.myItemSize),
|
||||
myIncrement (theOther.myIncrement),
|
||||
myLength (theOther.Length()),
|
||||
myCapacity (theOther.myIncrement+theOther.Length()/theOther.myIncrement),
|
||||
myCapacity (GetCapacity(myIncrement)+theOther.Length()/theOther.myIncrement),
|
||||
myNBlocks (1 + (theOther.Length() - 1)/theOther.myIncrement),
|
||||
myData (theDataInit (* this, myCapacity, NULL, 0)),
|
||||
myDataInit (theDataInit),
|
||||
|
@ -4,6 +4,9 @@
|
||||
// Copyright: Open Cascade 2002
|
||||
|
||||
#include <NCollection_IncAllocator.hxx>
|
||||
#include <NCollection_DataMap.hxx>
|
||||
#include <NCollection_Map.hxx>
|
||||
#include <Standard_Mutex.hxx>
|
||||
#include <Standard_OutOfMemory.hxx>
|
||||
#include <stdio.h>
|
||||
|
||||
@ -16,6 +19,129 @@ IMPLEMENT_STANDARD_RTTIEXT (NCollection_IncAllocator,NCollection_BaseAllocator)
|
||||
|
||||
#define MaxLookup 16
|
||||
|
||||
static Standard_Boolean IS_DEBUG = Standard_False;
|
||||
|
||||
//=======================================================================
|
||||
/**
|
||||
* Static data map (address -> AllocatorID)
|
||||
*/
|
||||
//=======================================================================
|
||||
static NCollection_DataMap<Standard_Address, Standard_Size>& StorageIDMap()
|
||||
{
|
||||
static NCollection_DataMap<Standard_Address, Standard_Size> TheMap;
|
||||
return TheMap;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
/**
|
||||
* Static map (AllocatorID)
|
||||
*/
|
||||
//=======================================================================
|
||||
static NCollection_Map<Standard_Size>& StorageIDSet()
|
||||
{
|
||||
static NCollection_Map<Standard_Size> TheMap;
|
||||
return TheMap;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : IncAllocator_SetDebugFlag
|
||||
//purpose : Turn on/off debugging of memory allocation
|
||||
//=======================================================================
|
||||
|
||||
Standard_EXPORT void IncAllocator_SetDebugFlag(const Standard_Boolean theDebug)
|
||||
{
|
||||
IS_DEBUG = theDebug;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
/**
|
||||
* Static value of the current allocation ID. It provides unique
|
||||
* numbering of allocators.
|
||||
*/
|
||||
//=======================================================================
|
||||
static Standard_Size CurrentID = 0;
|
||||
static Standard_Size CATCH_ID = 0;
|
||||
|
||||
//=======================================================================
|
||||
//function : Debug_Create
|
||||
//purpose : Store the allocator address in the internal maps
|
||||
//=======================================================================
|
||||
|
||||
static void Debug_Create(Standard_Address theAlloc)
|
||||
{
|
||||
static Standard_Mutex aMutex;
|
||||
Standard_Boolean isReentrant = Standard::IsReentrant();
|
||||
if (isReentrant)
|
||||
aMutex.Lock();
|
||||
StorageIDMap().Bind(theAlloc, ++CurrentID);
|
||||
StorageIDSet().Add(CurrentID);
|
||||
if (isReentrant)
|
||||
aMutex.Unlock();
|
||||
if (CurrentID == CATCH_ID)
|
||||
{
|
||||
// Place for break point for creation of investigated allocator
|
||||
int a = 1;
|
||||
}
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : Debug_Destroy
|
||||
//purpose : Forget the allocator address from the internal maps
|
||||
//=======================================================================
|
||||
|
||||
static void Debug_Destroy(Standard_Address theAlloc)
|
||||
{
|
||||
static Standard_Mutex aMutex;
|
||||
Standard_Boolean isReentrant = Standard::IsReentrant();
|
||||
if (isReentrant)
|
||||
aMutex.Lock();
|
||||
if (StorageIDMap().IsBound(theAlloc))
|
||||
{
|
||||
Standard_Size anID = StorageIDMap()(theAlloc);
|
||||
StorageIDSet().Remove(anID);
|
||||
StorageIDMap().UnBind(theAlloc);
|
||||
}
|
||||
if (isReentrant)
|
||||
aMutex.Unlock();
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : IncAllocator_PrintAlive
|
||||
//purpose : Outputs the alive numbers to the file inc_alive.d
|
||||
//=======================================================================
|
||||
|
||||
Standard_EXPORT void IncAllocator_PrintAlive()
|
||||
{
|
||||
if (!StorageIDSet().IsEmpty())
|
||||
{
|
||||
FILE * ff = fopen("inc_alive.d", "wt");
|
||||
if (ff == NULL)
|
||||
{
|
||||
cout << "failure writing file inc_alive.d" << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(ff, "Alive IncAllocators (number, size in Kb)\n");
|
||||
NCollection_DataMap<Standard_Address, Standard_Size>::Iterator
|
||||
itMap(StorageIDMap());
|
||||
Standard_Size aTotSize = 0;
|
||||
Standard_Integer nbAlloc = 0;
|
||||
for (; itMap.More(); itMap.Next())
|
||||
{
|
||||
NCollection_IncAllocator* anAlloc =
|
||||
static_cast<NCollection_IncAllocator*>(itMap.Key());
|
||||
Standard_Size anID = itMap.Value();
|
||||
Standard_Size aSize = anAlloc->GetMemSize();
|
||||
aTotSize += aSize;
|
||||
nbAlloc++;
|
||||
fprintf(ff, "%-8d %8.1f\n", anID, double(aSize)/1024);
|
||||
}
|
||||
fprintf(ff, "Total:\n%-8d %8.1f\n", nbAlloc, double(aTotSize)/1024);
|
||||
fclose(ff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : NCollection_IncAllocator()
|
||||
//purpose : Constructor
|
||||
@ -25,12 +151,17 @@ NCollection_IncAllocator::NCollection_IncAllocator (const size_t theBlockSize)
|
||||
{
|
||||
#ifdef ALLOC_TRACK_USAGE
|
||||
printf ("\n..NCollection_IncAllocator: Created (%x)\n",this);
|
||||
#endif
|
||||
#ifdef DEB
|
||||
if (IS_DEBUG)
|
||||
Debug_Create(this);
|
||||
#endif
|
||||
const size_t aSize = IMEM_SIZE(sizeof(IBlock)) +
|
||||
IMEM_SIZE((theBlockSize > 2*sizeof(IBlock)) ? theBlockSize : 24600);
|
||||
IBlock * const aBlock = (IBlock *) malloc (aSize * sizeof(aligned_t));
|
||||
myFirstBlock = aBlock;
|
||||
mySize = aSize;
|
||||
myMemSize = aSize * sizeof(aligned_t);
|
||||
if (aBlock == NULL)
|
||||
Standard_OutOfMemory::Raise("NCollection_IncAllocator: out of memory");
|
||||
aBlock -> p_free_space = (aligned_t *) IMEM_ALIGN (&aBlock[1]);
|
||||
@ -45,6 +176,10 @@ NCollection_IncAllocator::NCollection_IncAllocator (const size_t theBlockSize)
|
||||
|
||||
NCollection_IncAllocator::~NCollection_IncAllocator ()
|
||||
{
|
||||
#ifdef DEB
|
||||
if (IS_DEBUG)
|
||||
Debug_Destroy(this);
|
||||
#endif
|
||||
Clean();
|
||||
free (myFirstBlock);
|
||||
}
|
||||
@ -175,6 +310,7 @@ void NCollection_IncAllocator::Clean ()
|
||||
}
|
||||
myFirstBlock -> p_next = NULL;
|
||||
}
|
||||
myMemSize = 0;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
@ -201,6 +337,7 @@ void NCollection_IncAllocator::Reset (const Standard_Boolean doReleaseMem)
|
||||
}
|
||||
} else {
|
||||
IBlock * aNext = aBlock -> p_next;
|
||||
myMemSize -= (aBlock -> p_end_block - (aligned_t *) aBlock) * sizeof (aligned_t);
|
||||
free (aBlock);
|
||||
aBlock = aNext;
|
||||
}
|
||||
@ -214,13 +351,14 @@ void NCollection_IncAllocator::Reset (const Standard_Boolean doReleaseMem)
|
||||
|
||||
size_t NCollection_IncAllocator::GetMemSize () const
|
||||
{
|
||||
size_t aResult = 0;
|
||||
IBlock * aBlock = myFirstBlock;
|
||||
while (aBlock) {
|
||||
aResult += (aBlock -> p_end_block - (aligned_t *) aBlock);
|
||||
aBlock = aBlock -> p_next;
|
||||
}
|
||||
return aResult * sizeof (aligned_t);
|
||||
// size_t aResult = 0;
|
||||
// IBlock * aBlock = myFirstBlock;
|
||||
// while (aBlock) {
|
||||
// aResult += (aBlock -> p_end_block - (aligned_t *) aBlock);
|
||||
// aBlock = aBlock -> p_next;
|
||||
// }
|
||||
// return aResult * sizeof (aligned_t);
|
||||
return myMemSize;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
@ -238,6 +376,7 @@ void * NCollection_IncAllocator::allocateNewBlock (const size_t cSize)
|
||||
aBlock -> p_next = myFirstBlock;
|
||||
myFirstBlock = aBlock;
|
||||
aResult = (aligned_t *) IMEM_ALIGN(&aBlock[1]);
|
||||
myMemSize += aSz * sizeof(aligned_t);
|
||||
}
|
||||
else
|
||||
Standard_OutOfMemory::Raise("NCollection_IncAllocator: out of memory");
|
||||
|
@ -41,7 +41,7 @@ class NCollection_IncAllocator : public NCollection_BaseAllocator
|
||||
//! Free a previously allocated memory. Does nothing
|
||||
Standard_EXPORT virtual void Free (void *anAddress);
|
||||
|
||||
//! Diagnostic method, returns the number of bytes totally allocated
|
||||
//! Diagnostic method, returns the total allocated size
|
||||
Standard_EXPORT size_t GetMemSize () const;
|
||||
|
||||
//! Destructor (calls Clean() internally)
|
||||
@ -96,6 +96,7 @@ class NCollection_IncAllocator : public NCollection_BaseAllocator
|
||||
// --------- PROTECTED FIELDS ---------
|
||||
IBlock * myFirstBlock;
|
||||
size_t mySize;
|
||||
size_t myMemSize;
|
||||
|
||||
public:
|
||||
// Declaration of CASCADE RTTI
|
||||
|
@ -267,7 +267,7 @@ template <class TheObjType, class TheBndType> class NCollection_UBTree
|
||||
* return
|
||||
* Number of objects accepted
|
||||
*/
|
||||
Standard_Integer Select (Selector& theSelector) const
|
||||
virtual Standard_Integer Select (Selector& theSelector) const
|
||||
{ return (IsEmpty() ? 0 : Select (Root(), theSelector)); }
|
||||
|
||||
/**
|
||||
@ -454,6 +454,9 @@ class _HUBTREE : public _HPARENT \
|
||||
\
|
||||
_HUBTREE () : myTree(new UBTree) {} \
|
||||
/* Empty constructor */ \
|
||||
_HUBTREE (const Handle_NCollection_BaseAllocator& theAlloc) \
|
||||
: myTree(new UBTree(theAlloc)) {} \
|
||||
/* Constructor */ \
|
||||
\
|
||||
/* Access to the methods of UBTree */ \
|
||||
\
|
||||
|
@ -48,8 +48,8 @@ template <class TheItemType> class NCollection_Vector
|
||||
: public NCollection_BaseCollection<TheItemType>,
|
||||
public NCollection_BaseVector
|
||||
{
|
||||
// **************** Implementation of the Iterator interface.
|
||||
public:
|
||||
typedef TheItemType TheItemTypeD;
|
||||
// ----------------------------------------------------------------------
|
||||
//! Nested class MemBlock
|
||||
class MemBlock : public NCollection_BaseVector::MemBlock
|
||||
@ -57,33 +57,61 @@ template <class TheItemType> class NCollection_Vector
|
||||
public:
|
||||
void * operator new (size_t, void * theAddress) { return theAddress; }
|
||||
//! Empty constructor
|
||||
MemBlock () : NCollection_BaseVector::MemBlock(0,0) {}
|
||||
MemBlock (NCollection_BaseAllocator* theAlloc)
|
||||
: NCollection_BaseVector::MemBlock(0,0,theAlloc)
|
||||
{}
|
||||
//! Constructor
|
||||
MemBlock (const Standard_Integer theFirstInd,
|
||||
const Standard_Integer theSize)
|
||||
: NCollection_BaseVector::MemBlock (theFirstInd, theSize)
|
||||
{ myData = new TheItemType [theSize]; }
|
||||
const Standard_Integer theSize,
|
||||
NCollection_BaseAllocator* theAlloc)
|
||||
: NCollection_BaseVector::MemBlock (theFirstInd, theSize, theAlloc)
|
||||
{
|
||||
myData = myAlloc->Allocate(theSize * sizeof(TheItemType));
|
||||
for (size_t i=0; i < theSize; i++)
|
||||
new (&((TheItemType *) myData)[i]) TheItemType;
|
||||
}
|
||||
//! Copy constructor
|
||||
MemBlock (const MemBlock& theOther)
|
||||
: NCollection_BaseVector::MemBlock (theOther.FirstIndex(),theOther.Size())
|
||||
: NCollection_BaseVector::MemBlock (theOther.FirstIndex(),theOther.Size(),
|
||||
theOther.myAlloc)
|
||||
{
|
||||
myLength = theOther.Length();
|
||||
myData = new TheItemType [Size()];
|
||||
for (size_t i=0; i < Length(); i++)
|
||||
((TheItemType *) myData)[i] = theOther.Value(i);
|
||||
myData = myAlloc->Allocate(Size() * sizeof(TheItemType));
|
||||
size_t i;
|
||||
for (i=0; i < Length(); i++)
|
||||
new (&((TheItemType *) myData)[i]) TheItemType(theOther.Value(i));
|
||||
for (; i < Size(); i++)
|
||||
new (&((TheItemType *) myData)[i]) TheItemType;
|
||||
}
|
||||
//! Reinit
|
||||
virtual void Reinit (const Standard_Integer theFirst,
|
||||
const size_t theSize)
|
||||
{
|
||||
if (myData) delete [] (TheItemType *) myData;
|
||||
myData = (theSize > 0) ? new TheItemType [theSize] : NULL;
|
||||
if (myData) {
|
||||
for (size_t i=0; i < mySize; i++)
|
||||
((TheItemType *) myData)[i].~TheItemTypeD();
|
||||
myAlloc->Free(myData);
|
||||
myData = NULL;
|
||||
}
|
||||
if (theSize > 0) {
|
||||
myData = myAlloc->Allocate(theSize * sizeof(TheItemType));
|
||||
for (size_t i=0; i < theSize; i++)
|
||||
new (&((TheItemType *) myData)[i]) TheItemType;
|
||||
}
|
||||
myFirstInd = theFirst;
|
||||
mySize = theSize;
|
||||
myLength = 0;
|
||||
}
|
||||
//! Destructor
|
||||
virtual ~MemBlock () { if (myData) delete [] (TheItemType *) myData; }
|
||||
virtual ~MemBlock ()
|
||||
{
|
||||
if (myData) {
|
||||
for (size_t i=0; i < Size(); i++)
|
||||
((TheItemType *) myData)[i].~TheItemTypeD();
|
||||
myAlloc->Free(myData);
|
||||
myData = NULL;
|
||||
}
|
||||
}
|
||||
//! Operator () const
|
||||
const TheItemType& Value (const Standard_Integer theIndex) const
|
||||
{ return ((TheItemType *) myData) [theIndex]; }
|
||||
@ -263,7 +291,7 @@ template <class TheItemType> class NCollection_Vector
|
||||
i = aSize;
|
||||
}
|
||||
while (i < aCapacity)
|
||||
new (&aData[i++]) MemBlock;
|
||||
new (&aData[i++]) MemBlock(aSelf.myAllocator.operator->());
|
||||
return aData;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user