+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);
+ }
+ }
+}
+