Salome HOME
23514: EDF 16031 - SMESH freezes
[modules/smesh.git] / src / SMDS / ObjectPool.hxx
index e664c260c5283a6d94ed89e4eb107bb5ca742f42..ef514b353b0388fdcf4b61eb0cb8924a1742327e 100644 (file)
@@ -1,9 +1,9 @@
-// Copyright (C) 2010-2013  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2010-2016  CEA/DEN, EDF R&D, OPEN CASCADE
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
 // License as published by the Free Software Foundation; either
-// version 2.1 of the License.
+// version 2.1 of the License, or (at your option) any later version.
 //
 // This library is distributed in the hope that it will be useful,
 // but WITHOUT ANY WARRANTY; without even the implied warranty of
 #define _OBJECTPOOL_HXX_
 
 #include <vector>
-//#include <stack>
 #include <iostream>
 
+#include "SMDS_Iterator.hxx"
+
 namespace
 {
   // assure deallocation of memory of a vector
@@ -33,17 +34,22 @@ namespace
   }
 }
 
+template<class X> class ObjectPoolIterator;
+
 template<class X> class ObjectPool
 {
 
 private:
-  std::vector<X*> _chunkList;
+  std::vector<X*>   _chunkList;
   std::vector<bool> _freeList;
-  int _nextFree;
-  int _maxAvail;
-  int _chunkSize;
-  int _maxOccupied;
-  int _nbHoles;
+  int               _nextFree;    // either the 1st hole or last added
+  int               _maxAvail;    // nb allocated elements
+  int               _chunkSize;
+  int               _maxOccupied; // max used ID
+  int               _nbHoles;
+  int               _lastDelChunk;
+
+  friend class ObjectPoolIterator<X>;
 
   int getNextFree()
   {
@@ -75,13 +81,14 @@ private:
   }
 
 public:
-  ObjectPool(int nblk)
+  ObjectPool(int nblk = 1024)
   {
-    _chunkSize = nblk;
-    _nextFree = 0;
-    _maxAvail = 0;
-    _maxOccupied = 0;
-    _nbHoles = 0;
+    _chunkSize    = nblk;
+    _nextFree     = 0;
+    _maxAvail     = 0;
+    _maxOccupied  = -1;
+    _nbHoles      = 0;
+    _lastDelChunk = 0;
     _chunkList.clear();
     _freeList.clear();
   }
@@ -103,16 +110,16 @@ public:
         _freeList.insert(_freeList.end(), _chunkSize, true);
         _maxAvail += _chunkSize;
         _freeList[_nextFree] = false;
-        obj = newChunk; // &newChunk[0];
+        obj = newChunk;
       }
     else
       {
         int chunkId = _nextFree / _chunkSize;
         int rank = _nextFree - chunkId * _chunkSize;
         _freeList[_nextFree] = false;
-        obj = _chunkList[chunkId] + rank; // &_chunkList[chunkId][rank];
+        obj = _chunkList[chunkId] + rank;
       }
-    if (_nextFree < _maxOccupied)
+    if (_nextFree <= _maxOccupied)
       {
         _nbHoles-=1;
       }
@@ -120,33 +127,35 @@ public:
       {
         _maxOccupied = _nextFree;
       }
-    //obj->init();
     return obj;
   }
 
   void destroy(X* obj)
   {
-    long adrobj = (long) (obj);
-    for (size_t i = 0; i < _chunkList.size(); i++)
+    size_t i = 0;
+    if ( obj >= _chunkList[ _lastDelChunk ] &&
+         obj <  _chunkList[ _lastDelChunk ] + _chunkSize )
+      i = _lastDelChunk;
+    else
+      for ( ; i < _chunkList.size(); i++ )
       {
-        X* chunk = _chunkList[i];
-        long adrmin = (long) (chunk);
-        if (adrobj < adrmin)
-          continue;
-        long adrmax = (long) (chunk + _chunkSize);
-        if (adrobj >= adrmax)
-          continue;
-        int rank = (adrobj - adrmin) / sizeof(X);
-        int toFree = i * _chunkSize + rank;
-        _freeList[toFree] = true;
-        if (toFree < _nextFree)
-          _nextFree = toFree;
-        if (toFree < _maxOccupied)
-          _nbHoles += 1;
-        //obj->clean();
-        //checkDelete(i); compactage non fait
-        break;
+        if ( obj >= _chunkList[ i ] &&
+             obj <  _chunkList[ i ] + _chunkSize )
+          break;
       }
+    X*    chunk = _chunkList[i];
+    long adrobj = (long) (obj);
+    long adrmin = (long) (chunk);
+    int  rank   = (adrobj - adrmin) / sizeof(X);
+    int  toFree = i * _chunkSize + rank;
+    _freeList[toFree] = true;
+    if (toFree < _nextFree)
+      _nextFree = toFree;
+    if (toFree < _maxOccupied)
+      ++_nbHoles;
+    else
+      --_maxOccupied;
+    _lastDelChunk = i;
   }
 
   void clear()
@@ -155,12 +164,44 @@ public:
     _maxAvail = 0;
     _maxOccupied = 0;
     _nbHoles = 0;
+    _lastDelChunk = 0;
     for (size_t i = 0; i < _chunkList.size(); i++)
       delete[] _chunkList[i];
     clearVector( _chunkList );
     clearVector( _freeList );
   }
 
+  // nb allocated elements
+  size_t size() const
+  {
+    return _freeList.size();
+  }
+
+  // nb used elements
+  size_t nbElements() const
+  {
+    return _maxOccupied + 1 - _nbHoles;
+  }
+
+  // return an element w/o any check
+  const X* operator[]( size_t i ) const // i < size()
+  {
+    int chunkId = i / _chunkSize;
+    int    rank = i - chunkId * _chunkSize;
+    return _chunkList[ chunkId ] + rank;
+  }
+
+  // return only being used element
+  const X* at( size_t i ) const // i < size()
+  {
+    if ( i >= size() || _freeList[ i ] )
+      return 0;
+
+    int chunkId = i / _chunkSize;
+    int    rank = i - chunkId * _chunkSize;
+    return _chunkList[ chunkId ] + rank;
+  }
+
   //  void destroy(int toFree)
   //  {
   //    // no control 0<= toFree < _freeList.size()
@@ -171,4 +212,41 @@ public:
 
 };
 
+template<class X> class ObjectPoolIterator : public SMDS_Iterator<const X*>
+{
+  const ObjectPool<X>& _pool;
+  int                  _i, _nbFound;
+public:
+
+  ObjectPoolIterator( const ObjectPool<X>& pool ) : _pool( pool ), _i( 0 ), _nbFound( 0 )
+  {
+    if ( more() && _pool._freeList[ _i ] == true )
+    {
+      next();
+      --_nbFound;
+    }
+  }
+
+  virtual bool more()
+  {
+    return ( _i <= _pool._maxOccupied && _nbFound < (int)_pool.nbElements() );
+  }
+
+  virtual const X* next()
+  {
+    const X* x = 0;
+    if ( more() )
+    {
+      x = _pool[ _i ];
+
+      ++_nbFound;
+
+      for ( ++_i; _i <= _pool._maxOccupied; ++_i )
+        if ( _pool._freeList[ _i ] == false )
+          break;
+    }
+    return x;
+  }
+};
+
 #endif