SheafSystem  0.0.0.0
pool.impl.h
1 
2 //
3 // Copyright (c) 2014 Limit Point Systems, Inc.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 
18 // Interface for class POOL
19 
20 #ifndef POOL_IMPL_H
21 #define POOL_IMPL_H
22 
23 #ifndef SHEAF_DLL_SPEC_H
24 #include "SheafSystem/sheaf_dll_spec.h"
25 #endif
26 
27 #ifndef POOL_H
28 #include "SheafSystem/pool.h"
29 #endif
30 
31 #ifndef ASSERT_CONTRACT_H
32 #include "SheafSystem/assert_contract.h"
33 #endif
34 
35 #ifndef STD_IOMANIP_H
36 #include "SheafSystem/std_iomanip.h"
37 #endif
38 
39 #ifndef ZN_TO_BOOL_H
40 #include "SheafSystem/zn_to_bool.h"
41 #endif
42 
43 namespace sheaf
44 {
45 
46 template <typename T, int EXTENSION_FACTOR>
47 bool
49 invariant() const
50 {
51  bool result = true;
52 
53  // _pool and _is_allocated same size
54 
55  invariance(_pool.ub() == _is_allocated->ub());
56 
58 
59  return result;
60 }
61 
62 template <typename T, int EXTENSION_FACTOR>
65 index_ub() const
66 {
67  // Preconditions:
68 
69  // Body:
70 
71  index_type result(_pool.ub());
72 
73  // Postconditions:
74 
75  ensure(result >= 0);
76 
77  // return:
78 
79  return result;
80 }
81 
82 template <typename T, int EXTENSION_FACTOR>
83 bool
86 {
87  return (0 <= xitem) && (xitem < _pool.ub());
88 }
89 
90 template <typename T, int EXTENSION_FACTOR>
91 int
93 free_ct() const
94 {
95  return _free_ct;
96 }
97 
98 template <typename T, int EXTENSION_FACTOR>
101 free_list() const
102 {
103  return _free_list;
104 }
105 
106 template <typename T, int EXTENSION_FACTOR>
107 int
110 {
111  return _allocated_ct;
112 }
113 
114 template <typename T, int EXTENSION_FACTOR>
115 bool
118 {
119  bool result;
120 
121  // Preconditions:
122 
123  require(index_in_bounds(xindex));
124 
125  // Body:
126 
127  result = (*_is_allocated)[xindex];
128 
129  // Postconditions:
130 
131  // Exit:
132 
133  return result;
134 }
135 
136 template <typename T, int EXTENSION_FACTOR>
140 {
141  // Preconditions:
142 
143  // Body:
144 
145  index_iterator result(_is_allocated);
146 
147  // Postconditions:
148 
149  ensure(invariant());
150 
151  // Exit
152 
153  return result;
154 }
155 
156 template <typename T, int EXTENSION_FACTOR>
160 {
161  if(!is_valid(_free_list))
162  {
163  // Free list is empty, extend the pool.
164 
165  pod_index_type new_index_ub(EXTENSION_FACTOR*_pool.ub());
166 
167  extend_to(new_index_ub);
168  }
169 
170  pod_index_type result = _free_list;
171 
172  if(is_valid(result))
173  {
174  // Have valid result, remove it from the free list.
175 
176  _free_list = _pool[result]->next();
177  --_free_ct;
178  ++_allocated_ct;
179  _is_allocated->put(result, true);
180 
181  // Make sure no interaction between use of next
182  // by free list and other uses of next..
183 
184  _pool[result]->put_next(invalid_pod_index());
185 
186  }
187 
188  // postconditions:
189 
190  ensure(is_allocated(result));
191  ensure(unexecutable(free_ct() == old free_ct() - 1));
192  ensure(unexecutable(allocated_ct() == old allocated_ct() + 1));
193 
194  return result;
195 }
196 
197 template <typename T, int EXTENSION_FACTOR>
198 void
201 {
202  // Preconditions
203 
204  require(is_allocated(xindex));
205 
206  // Body:
207 
208  T* item = _pool.item(xindex);
209 
210  item->put_next(_free_list);
211  _free_list = xindex;
212  ++_free_ct;
213  _is_allocated->put(xindex, false);
214  --_allocated_ct;
215 
216  // Postconditions:
217 
218  ensure(!is_allocated(xindex));
219  ensure(unexecutable(free_ct() == old free_ct() + 1));
220  ensure(unexecutable(allocated_ct() == old allocated_ct() - 1));
221 
222  // Exit:
223 
224  return;
225 }
226 
227 template <typename T, int EXTENSION_FACTOR>
230 {
231  // Preconditions:
232 
233  require(xub >= 0);
234 
235  // Body:
236 
237  _free_ct = 0;
238  _free_list = invalid_pod_index();
239  _allocated_ct = 0;
240  _is_allocated = new zn_to_bool(xub);
241 
242  extend_to(xub);
243 
244  // Postconditions:
245 
246  ensure(index_ub() == xub);
247  ensure(free_ct() == xub);
248  ensure(free_list() == 0);
249  ensure(allocated_ct() == 0);
250 
251  // Exit:
252 
253  return;
254 }
255 
256 template <typename T, int EXTENSION_FACTOR>
259 {
260  // Clear the chunk list and delete all the chunks.
261 
262  while(!_chunk_list.empty())
263  {
264  T* lchunk = _chunk_list.front();
265  delete [] lchunk;
266  _chunk_list.pop_front();
267  }
268 
269  // Delete the is_allocated bit vector
270 
271  delete _is_allocated;
272 
273 }
274 
275 template <typename T, int EXTENSION_FACTOR>
276 T &
279 {
280 
281  // preconditions:
282 
283  require(index_in_bounds(xindex));
284 
285  // body:
286 
287  T& result = *(_pool.item(xindex));
288 
289  // postconditions:
290 
291  return result;
292 }
293 
294 template <typename T, int EXTENSION_FACTOR>
295 T &
298 {
299 
300  // preconditions:
301 
302  require(index_in_bounds(xindex));
303 
304  // body:
305 
306  T& result = *(_pool[xindex]);
307 
308  // postconditions:
309 
310  return result;
311 }
312 
313 template <typename T, int EXTENSION_FACTOR>
314 void
317 {
318  // Preconditions:
319 
320  require(xub > 0);
321  require(xub > index_ub());
322 
323  // Body:
324 
325  pod_index_type old_index_ub = index_ub();
326 
327  pod_index_type old_pool_ub = _pool.ub();
328  pod_index_type new_pool_ub = xub;
329 
330  // Allocate a new chunk of storage.
331 
332  size_type lchunk_size = new_pool_ub - old_pool_ub;
333  T* lchunk = new T[lchunk_size];
334  _chunk_list.push_front(lchunk);
335 
336  // Extend the pool.
337 
338  _pool.reserve(new_pool_ub);
339 
340  // Initialize the new members of the pool
341  // to point into the new chunk.
342 
343  T* lmbr_ptr = lchunk;
344  for(int i=0; i<lchunk_size; i++)
345  {
346  _pool.push_back(lmbr_ptr++);
347  }
348 
349  // Extend _is_allocated
350 
351  _is_allocated->extend_to(new_pool_ub);
352 
353  // Tie the new members together into a list;
354  // each the new member is linked to the next one,
355  // except the last, which is terminated.
356 
357  pod_index_type last_new_mbr_id(xub);
358  --last_new_mbr_id;
359 
360  assertion(last_new_mbr_id >= old_index_ub);
361 
362  for(pod_index_type i = old_index_ub; i < last_new_mbr_id;)
363  {
364  pod_index_type old_i = i;
365  _pool.item(old_i)->put_next(++i);
366  }
367  _pool.item(last_new_mbr_id)->put_next(invalid_pod_index());
368 
369  // Append the new member list to the free list.
370 
371  if (!is_valid(_free_list))
372  {
373  // Free list is empty;
374  // make it point to the new member list.
375 
376  _free_list = old_index_ub;
377  }
378  else
379  {
380  // Free list is not empty;
381  // find the end of it.
382 
383  pod_index_type last_free_mbr = _free_list;
384  while(is_valid(_pool.item(last_free_mbr)->next()))
385  {
386  last_free_mbr = _pool.item(last_free_mbr)->next();
387  }
388 
389  // Append the new member list.
390 
391  _pool.item(last_free_mbr)->put_next(old_index_ub);
392  }
393 
394  // Update the free count.
395 
396  _free_ct += (new_pool_ub - old_pool_ub);
397 
398  // Postconditions:
399 
400  // Exit:
401 
402  return;
403 }
404 
405 
406 template <typename T, int EXTENSION_FACTOR>
407 void
409 print() const
410 {
411  print(std::cout);
412 }
413 
414 template <typename T, int EXTENSION_FACTOR>
415 void
417 print(std::ostream &os) const
418 {
419 
420  os << std::endl;
421 
422  os << "pool "
423  << std::hex
424  << (void *)this
425  << std::dec
426  << " free_ct = "
427  << _free_ct
428  << " allocated_ct = "
429  << _allocated_ct
430  << " free_list = "
431  << _free_list
432  << std::endl
433  << std::endl;
434 
435  for (pod_index_type i = 0; i < _pool.ub(); ++i)
436  {
437  os << "member: " << std::setw(5) << i << " ";
438  os << *(_pool[i]);
439  os << std::endl;
440  }
441 
442 
443  return;
444 }
445 
446 
447 // ===========================================================
448 // NON-MEMBER FUNCTIONS
449 // ===========================================================
450 
451 template <typename T, int EXTENSION_FACTOR>
452 size_t
453 deep_size(const pool<T, EXTENSION_FACTOR>& xpool, bool xinclude_shallow)
454 {
455  size_t result;
456 
457  // Preconditions:
458 
459  //require(T is not a pointer);
460 
461  // Body:
462 
463  result = xinclude_shallow ? sizeof(xpool) : 0;
464 
465  // Cast away the constness so we can access the methods of class pool.
466 
467  pool<T, EXTENSION_FACTOR>& lpool = const_cast<pool<T, EXTENSION_FACTOR>&>(xpool);
468 
469  // Add the sizeof size of both the allocated and free items.
470 
471  pod_index_type lindex_ub = lpool.index_ub();
472  result += lindex_ub*sizeof(T);
473 
474  // Add the "deep_size"s of all of the allocsted items.
475 
476  for(pod_index_type i=0; i<lindex_ub; ++i)
477  {
478  if(lpool.is_allocated(i))
479  {
480  result += deep_size(lpool.item(i), false);
481  }
482  }
483 
484  // Class pool has no public access to the singly_linked_list and zn_to_bool type data
485  // members, so we are unable to add any additional contributions from them.
486 
487  // Calculate the total memory used by data member _chunk_list
488  // of type singly_linked_list<T*> not including that already counted above.
489 
490  // Best guess for singly linked list deep size.
491 
492  result += lpool._chunk_list.size()*(sizeof(T*) + sizeof(void*));
493 
494  // Calculate the total memory used by data member _is_allocated
495  // of type zn_to_bool*.
496 
497  if(lpool._is_allocated != 0)
498  {
499  result += deep_size(*(lpool._is_allocated), true);
500  }
501 
502  // Postconditions:
503 
504  ensure(result >= 0);
505 
506  // Exit
507 
508  return result;
509 }
510 
511 } // namespace sheaf
512 
513 #endif // ifndef POOL_IMPL_H
int free_ct() const
The size of free list.
Definition: pool.impl.h:93
index_iterator allocated_iterator() const
An iterator over allocated items in the pool.
Definition: pool.impl.h:139
bool is_allocated(pod_index_type xindex) const
True if xindex is allocated.
Definition: pool.impl.h:117
bool invariant() const
Class invariant.
Definition: pool.impl.h:49
unsigned long int size_type
An unsigned integral type used to represent sizes and capacities.
Definition: pool.h:115
A map from Zn (the integers mod n) to bools. A characteristic function used to represent subsets of Z...
Definition: zn_to_bool.h:52
void deallocate(pod_index_type xindex)
Deallocate item at xindex.
Definition: pool.impl.h:200
int allocated_ct() const
The size of allocated list.
Definition: pool.impl.h:109
pod_index_type index_ub() const
The upper bound on the index for members of the pool.
Definition: pool.impl.h:65
A reallocatable pool of objects of type T. Objects in the pool are either "allocated" or linked toget...
Definition: pool.h:55
~pool()
Destructor.
Definition: pool.impl.h:258
SHEAF_DLL_SPEC size_t deep_size(const dof_descriptor_array &xp, bool xinclude_shallow=true)
The deep size of the referenced object of type dof_descriptor_array.
Iterates over the subset of Zn defined by the characteristic function host().
int_type pod_index_type
The plain old data index type.
Definition: pod_types.h:49
pod_index_type index_type
The containers index type.
Definition: pool.h:104
void print() const
Prints the data members of this on cout. Intended for use debugging.
Definition: pool.impl.h:409
T & item(pod_index_type xindex)
A pointer to the pool item at xindex.
Definition: pool.impl.h:278
Namespace for the sheaves component of the sheaf system.
bool index_in_bounds(pod_index_type xindex) const
True if xindex is in bounds.
Definition: pool.impl.h:85
pool(pod_index_type xub)
Creates an instance with xub upper bound.
Definition: pool.impl.h:229
SHEAF_DLL_SPEC bool is_valid(pod_index_type xpod_index)
True if an only if xpod_index is valid.
Definition: pod_types.cc:37
SHEAF_DLL_SPEC pod_index_type invalid_pod_index()
The invalid pod index value.
Definition: pod_types.cc:31
pod_index_type free_list() const
The head of the free list.
Definition: pool.impl.h:101
T & operator[](pod_index_type xindex)
A reference to the pool item at xindex.
Definition: pool.impl.h:297
pod_index_type allocate()
Allocate next available index from free list.
Definition: pool.impl.h:159