Salome HOME
Copyrights update 2015.
[modules/smesh.git] / src / SMDS / ObjectPool.hxx
1 // Copyright (C) 2010-2015  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
48   int getNextFree()
49   {
50     // Don't iterate on the _freeList if all the "holes"
51     // are filled. Go straight to the last occupied ID + 1
52     if ( _nbHoles == 0 )
53       return std::min(_maxOccupied + 1, _maxAvail);
54     
55     for (int i = _nextFree; i < _maxAvail; i++)
56       if (_freeList[i] == true)
57         {
58           return i;
59           break;
60         }
61     return _maxAvail;
62   }
63
64   void checkDelete(int chunkId)
65   {
66     int i0 = _chunkSize * chunkId;
67     int i1 = _chunkSize * (chunkId + 1);
68     for (int i = i0; i < i1; i++)
69       if (_freeList[i] == false)
70         return;
71     std::cerr << "a chunk to delete" << std::endl;
72     // compactage des vecteurs un peu lourd, pas necessaire
73     //X* chunk = _chunkList[chunkId];
74     //delete [] chunk;
75   }
76
77 public:
78   ObjectPool(int nblk)
79   {
80     _chunkSize = nblk;
81     _nextFree = 0;
82     _maxAvail = 0;
83     _maxOccupied = 0;
84     _nbHoles = 0;
85     _chunkList.clear();
86     _freeList.clear();
87   }
88
89   virtual ~ObjectPool()
90   {
91     for (size_t i = 0; i < _chunkList.size(); i++)
92       delete[] _chunkList[i];
93   }
94
95   X* getNew()
96   {
97     X *obj = 0;
98     _nextFree = getNextFree();
99     if (_nextFree == _maxAvail)
100       {
101         X* newChunk = new X[_chunkSize];
102         _chunkList.push_back(newChunk);
103         _freeList.insert(_freeList.end(), _chunkSize, true);
104         _maxAvail += _chunkSize;
105         _freeList[_nextFree] = false;
106         obj = newChunk; // &newChunk[0];
107       }
108     else
109       {
110         int chunkId = _nextFree / _chunkSize;
111         int rank = _nextFree - chunkId * _chunkSize;
112         _freeList[_nextFree] = false;
113         obj = _chunkList[chunkId] + rank; // &_chunkList[chunkId][rank];
114       }
115     if (_nextFree < _maxOccupied)
116       {
117         _nbHoles-=1;
118       }
119     else
120       {
121         _maxOccupied = _nextFree;
122       }
123     //obj->init();
124     return obj;
125   }
126
127   void destroy(X* obj)
128   {
129     long adrobj = (long) (obj);
130     for (size_t i = 0; i < _chunkList.size(); i++)
131       {
132         X* chunk = _chunkList[i];
133         long adrmin = (long) (chunk);
134         if (adrobj < adrmin)
135           continue;
136         long adrmax = (long) (chunk + _chunkSize);
137         if (adrobj >= adrmax)
138           continue;
139         int rank = (adrobj - adrmin) / sizeof(X);
140         int toFree = i * _chunkSize + rank;
141         _freeList[toFree] = true;
142         if (toFree < _nextFree)
143           _nextFree = toFree;
144         if (toFree < _maxOccupied)
145           _nbHoles += 1;
146         //obj->clean();
147         //checkDelete(i); compactage non fait
148         break;
149       }
150   }
151
152   void clear()
153   {
154     _nextFree = 0;
155     _maxAvail = 0;
156     _maxOccupied = 0;
157     _nbHoles = 0;
158     for (size_t i = 0; i < _chunkList.size(); i++)
159       delete[] _chunkList[i];
160     clearVector( _chunkList );
161     clearVector( _freeList );
162   }
163
164   //  void destroy(int toFree)
165   //  {
166   //    // no control 0<= toFree < _freeList.size()
167   //    _freeList[toFree] = true;
168   //    if (toFree < _nextFree)
169   //      _nextFree = toFree;
170   //  }
171
172 };
173
174 #endif