OCC22143 Optimization of memory usage and developing tools for catching memory leaks...
authorMSV <>
Thu, 28 Apr 2011 15:26:43 +0000 (15:26 +0000)
committerbugmaster <bugmaster@opencascade.com>
Mon, 5 Mar 2012 15:28:00 +0000 (19:28 +0400)
src/NCollection/NCollection_BaseAllocator.cxx
src/NCollection/NCollection_BaseList.cxx
src/NCollection/NCollection_BaseVector.cxx
src/NCollection/NCollection_BaseVector.hxx
src/NCollection/NCollection_IncAllocator.cxx
src/NCollection/NCollection_IncAllocator.hxx
src/NCollection/NCollection_UBTree.hxx
src/NCollection/NCollection_Vector.hxx

index 3e9c209..1fae714 100755 (executable)
@@ -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);
 }
index eac7a63..945b1e5 100755 (executable)
@@ -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;
 
index 5b86bdb..f830bbb 100755 (executable)
@@ -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;
index 6da8f74..bf1d147 100755 (executable)
@@ -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
 #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),
index 4929ef1..ad4ed24 100755 (executable)
@@ -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");
index 6cfbcec..807263b 100755 (executable)
@@ -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
index a21e5f9..3999278 100755 (executable)
@@ -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 */                                 \
                                                                         \
index a922b1f..fa687d3 100755 (executable)
@@ -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;
   }