Salome HOME
5e5f0d289d275eff3d2c3d10a6b99d80b88d400d
[modules/smesh.git] / src / SMDS / ObjectPool.hxx
1 // Copyright (C) 2010-2016  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #ifndef _OBJECTPOOL_HXX_
21 #define _OBJECTPOOL_HXX_
22
23 #include <vector>
24 //#include <stack>
25 #include <iostream>
26
27 namespace
28 {
29   // assure deallocation of memory of a vector
30   template<class Y> void clearVector(std::vector<Y>& v )
31   {
32     std::vector<Y> emptyVec; v.swap( emptyVec );
33   }
34 }
35
36 template<class X> class ObjectPool
37 {
38
39 private:
40   std::vector<X*> _chunkList;
41   std::vector<bool> _freeList;
42   int _nextFree;
43   int _maxAvail;
44   int _chunkSize;
45   int _maxOccupied;
46   int _nbHoles;
47   int _lastDelChunk;
48
49   int getNextFree()
50   {
51     // Don't iterate on the _freeList if all the "holes"
52     // are filled. Go straight to the last occupied ID + 1
53     if ( _nbHoles == 0 )
54       return std::min(_maxOccupied + 1, _maxAvail);
55     
56     for (int i = _nextFree; i < _maxAvail; i++)
57       if (_freeList[i] == true)
58         {
59           return i;
60           break;
61         }
62     return _maxAvail;
63   }
64
65   void checkDelete(int chunkId)
66   {
67     int i0 = _chunkSize * chunkId;
68     int i1 = _chunkSize * (chunkId + 1);
69     for (int i = i0; i < i1; i++)
70       if (_freeList[i] == false)
71         return;
72     std::cerr << "a chunk to delete" << std::endl;
73     // compactage des vecteurs un peu lourd, pas necessaire
74     //X* chunk = _chunkList[chunkId];
75     //delete [] chunk;
76   }
77
78 public:
79   ObjectPool(int nblk)
80   {
81     _chunkSize = nblk;
82     _nextFree = 0;
83     _maxAvail = 0;
84     _maxOccupied = 0;
85     _nbHoles = 0;
86     _chunkList.clear();
87     _freeList.clear();
88     _lastDelChunk = 0;
89   }
90
91   virtual ~ObjectPool()
92   {
93     for (size_t i = 0; i < _chunkList.size(); i++)
94       delete[] _chunkList[i];
95   }
96
97   X* getNew()
98   {
99     X *obj = 0;
100     _nextFree = getNextFree();
101     if (_nextFree == _maxAvail)
102       {
103         X* newChunk = new X[_chunkSize];
104         _chunkList.push_back(newChunk);
105         _freeList.insert(_freeList.end(), _chunkSize, true);
106         _maxAvail += _chunkSize;
107         _freeList[_nextFree] = false;
108         obj = newChunk; // &newChunk[0];
109       }
110     else
111       {
112         int chunkId = _nextFree / _chunkSize;
113         int rank = _nextFree - chunkId * _chunkSize;
114         _freeList[_nextFree] = false;
115         obj = _chunkList[chunkId] + rank; // &_chunkList[chunkId][rank];
116       }
117     if (_nextFree < _maxOccupied)
118       {
119         _nbHoles-=1;
120       }
121     else
122       {
123         _maxOccupied = _nextFree;
124       }
125     //obj->init();
126     return obj;
127   }
128
129   void destroy(X* obj)
130   {
131     size_t i = 0;
132     if ( obj >= _chunkList[ _lastDelChunk ] &&
133          obj <  _chunkList[ _lastDelChunk ] + _chunkSize )
134       i = _lastDelChunk;
135     else
136       for ( ; i < _chunkList.size(); i++ )
137       {
138         if ( obj >= _chunkList[ i ] &&
139              obj <  _chunkList[ i ] + _chunkSize )
140           break;
141       }
142     X*    chunk = _chunkList[i];
143     long adrobj = (long) (obj);
144     long adrmin = (long) (chunk);
145     int  rank   = (adrobj - adrmin) / sizeof(X);
146     int  toFree = i * _chunkSize + rank;
147     _freeList[toFree] = true;
148     if (toFree < _nextFree)
149       _nextFree = toFree;
150     if (toFree < _maxOccupied)
151       _nbHoles += 1;
152     _lastDelChunk = i;
153     //obj->clean();
154     //checkDelete(i); compactage non fait
155   }
156
157   void clear()
158   {
159     _nextFree = 0;
160     _maxAvail = 0;
161     _maxOccupied = 0;
162     _nbHoles = 0;
163     _lastDelChunk = 0;
164     for (size_t i = 0; i < _chunkList.size(); i++)
165       delete[] _chunkList[i];
166     clearVector( _chunkList );
167     clearVector( _freeList );
168   }
169
170   //  void destroy(int toFree)
171   //  {
172   //    // no control 0<= toFree < _freeList.size()
173   //    _freeList[toFree] = true;
174   //    if (toFree < _nextFree)
175   //      _nextFree = toFree;
176   //  }
177
178 };
179
180 #endif