Dune Core Modules (2.3.1)

poolallocator.hh
Go to the documentation of this file.
1// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2// vi: set et ts=4 sw=2 sts=2:
3// $Id$
4#ifndef DUNE_COMMON_POOLALLOCATOR_HH
5#define DUNE_COMMON_POOLALLOCATOR_HH
6
11#include "alignment.hh"
12#include "static_assert.hh"
13#include "lcm.hh"
14#include <typeinfo>
15#include <iostream>
16#include <cassert>
17#include <new>
18
19//forward declarations.
20
21// we need to know the test function to declare it friend
22template<std::size_t size, typename T>
23struct testPoolMain;
24
25namespace Dune
26{
27
28 template<typename T, std::size_t s>
29 class Pool;
30
31 template<typename T, std::size_t s>
32 class PoolAllocator;
33
34}
35
36namespace std
37{
38 /*
39 template<class T, std::size_t S>
40 inline ostream& operator<<(ostream& os, Dune::Pool<T,S>& pool)
41 {
42 os<<"pool="<<&pool<<" allocated_="<<pool.allocated_;
43 return os;
44 }
45
46 template<class T, std::size_t S>
47 inline ostream& operator<<(ostream& os, Dune::PoolAllocator<T,S>& pool)
48 {
49 os<<pool.memoryPool_<<std::endl;
50 return os;
51 }
52 */
53}
54
55
56namespace Dune
57{
88 template<class T, std::size_t s>
89 class Pool
90 {
91 // make the test function friend
92 friend struct ::testPoolMain<s,T>;
93
94 //friend std::ostream& std::operator<<<>(std::ostream&,Pool<T,s>&);
95 template< class, std::size_t > friend class PoolAllocator;
96
97 private:
98
100 struct Reference
101 {
102 Reference *next_;
103 };
104
105 public:
106
108 typedef T MemberType;
109 enum
110 {
114 unionSize = ((sizeof(MemberType) < sizeof(Reference)) ?
115 sizeof(Reference) : sizeof(MemberType)),
116
121 size = ((sizeof(MemberType) <= s && sizeof(Reference) <= s) ?
123
129
136 alignedSize = ((unionSize % alignment == 0) ?
137 unionSize :
139
147 chunkSize = ((size % alignment == 0) ?
148 size : ((size / alignment + 1)* alignment))
150
155 };
156
157 private:
159 struct Chunk
160 {
161
162 //friend int testPool<s,T>();
163
165 char chunk_[chunkSize];
166
171 char* memory_;
172
174 Chunk *next_;
175
179 Chunk()
180 {
181 // Make sure the alignment is correct!
182 // long long should be 64bit safe!
183 unsigned long long lmemory = reinterpret_cast<unsigned long long>(chunk_);
184 if(lmemory % alignment != 0)
185 lmemory = (lmemory / alignment + 1)
186 * alignment;
187
188 memory_ = reinterpret_cast<char *>(lmemory);
189 }
190 };
191
192 public:
194 inline Pool();
196 inline ~Pool();
201 inline void* allocate();
206 inline void free(void* o);
207
211 inline void print(std::ostream& os);
212
213 private:
214
215 // Prevent Copying!
216 Pool(const Pool<MemberType,s>&);
217
218 void operator=(const Pool<MemberType,s>& pool) const;
220 inline void grow();
222 Reference *head_;
224 Chunk *chunks_;
225 /* @brief The number of currently allocated elements. */
226 //size_t allocated_;
227
228 };
229
247 template<class T, std::size_t s>
249 {
250 //friend std::ostream& std::operator<<<>(std::ostream&,PoolAllocator<T,s>&);
251
252 public:
256 typedef T value_type;
257
258 enum
259 {
264 size=s*sizeof(value_type)
265 };
266
270 typedef T* pointer;
271
275 typedef const T* const_pointer;
276
280 typedef T& reference;
281
285 typedef const T& const_reference;
286
290 typedef std::size_t size_type;
291
295 typedef std::ptrdiff_t difference_type;
296
300 inline PoolAllocator();
301
305 template<typename U, std::size_t u>
307 {
308 // we allow copying but never copy the pool
309 // to have a clear ownership of allocated pointers.
310 }
311
314 {
315 // we allow copying but never copy the pool
316 // to have a clear ownership of allocated pointers.
317 // For this behaviour we have to implement
318 // the copy constructor, because the default
319 // one would copy the pool and deallocation
320 // of it would break.
321 }
328 inline pointer allocate(std::size_t n, const_pointer hint=0);
329
337 inline void deallocate(pointer p, std::size_t n);
338
344 inline void construct(pointer p, const_reference value);
345
350 inline void destroy(pointer p);
351
355 inline pointer address(reference x) const { return &x; }
356
357
361 inline const_pointer address(const_reference x) const { return &x; }
362
366 inline int max_size() const throw(){ return 1;}
367
371 template<class U>
372 struct rebind
373 {
375 };
376
379
380 private:
384 PoolType memoryPool_;
385 };
386
387 // specialization for void
388 template <std::size_t s>
389 class PoolAllocator<void,s>
390 {
391 public:
392 typedef void* pointer;
393 typedef const void* const_pointer;
394 // reference to void members are impossible.
395 typedef void value_type;
396 template <class U> struct rebind
397 {
398 typedef PoolAllocator<U,s> other;
399 };
400 };
401
402
403 template<typename T1, std::size_t t1, typename T2, std::size_t t2>
404 bool operator==(const PoolAllocator<T1,t1>&, const PoolAllocator<T2,t2>&)
405 {
406 return false;
407 }
408
409
410 template<typename T1, std::size_t t1, typename T2, std::size_t t2>
411 bool operator!=(const PoolAllocator<T1,t1>&, const PoolAllocator<T2,t2>&)
412 {
413 return true;
414 }
415
416 template<typename T, std::size_t t1, std::size_t t2>
417 bool operator==(const PoolAllocator<T,t1>& p1, const PoolAllocator<T,t2>& p2)
418 {
419 return &p1==&p2;
420 }
421
422
423 template<typename T, std::size_t t1, std::size_t t2>
424 bool operator!=(const PoolAllocator<T,t1>& p1, const PoolAllocator<T,t2>& p2)
425 {
426 return &p1 != &p2;
427 }
428
429 template<typename T, std::size_t t1, std::size_t t2>
430 bool operator==(const PoolAllocator<void,t1>&, const PoolAllocator<T,t2>&)
431 {
432 return false;
433 }
434
435
436 template<typename T, std::size_t t1, std::size_t t2>
437 bool operator!=(const PoolAllocator<void,t1>&, const PoolAllocator<T,t2>&)
438 {
439 return true;
440 }
441
442 template<std::size_t t1, std::size_t t2>
443 bool operator==(const PoolAllocator<void,t1>& p1, const PoolAllocator<void,t2>& p2)
444 {
445 return &p1==&p2;
446 }
447
448 template<std::size_t t1, std::size_t t2>
449 bool operator!=(const PoolAllocator<void,t1>& p1, const PoolAllocator<void,t2>& p2)
450 {
451 return &p1!=&p2;
452 }
453
454 template<class T, std::size_t S>
456 : head_(0), chunks_(0) //, allocated_(0)
457 {
458 dune_static_assert(sizeof(T)<=unionSize, "Library Error: type T is too big");
459 dune_static_assert(sizeof(Reference)<=unionSize, "Library Error: type of referene is too big");
460 dune_static_assert(unionSize<=alignedSize, "Library Error: alignedSize too small");
461 dune_static_assert(sizeof(T)<=chunkSize, "Library Error: chunkSize must be able to hold at least one value");
462 dune_static_assert(sizeof(Reference)<=chunkSize, "Library Error: chunkSize must be able to hold at least one reference");
463 dune_static_assert((chunkSize - (alignment - 1)) % alignment == 0, "Library Error: compiler cannot calculate!");
464 dune_static_assert(elements>=1, "Library Error: we need to hold at least one element!");
465 dune_static_assert(elements*alignedSize<=chunkSize, "Library Error: aligned elements must fit into chuck!");
466 }
467
468 template<class T, std::size_t S>
470 {
471 /*
472 if(allocated_!=0)
473 std::cerr<<"There are still "<<allocated_<<" allocated elements by the Pool<"<<typeid(T).name()<<","<<S<<"> "
474 <<static_cast<void*>(this)<<"! This is a memory leak and might result in segfaults"
475 <<std::endl;
476 */
477 // delete the allocated chunks.
478 Chunk *current=chunks_;
479
480 while(current!=0)
481 {
482 Chunk *tmp = current;
483 current = current->next_;
484 delete tmp;
485 }
486 }
487
488 template<class T, std::size_t S>
489 inline void Pool<T,S>::print(std::ostream& os)
490 {
491 Chunk* current=chunks_;
492 while(current) {
493 os<<current<<" ";
494 current=current->next_;
495 }
496 os<<current<<" ";
497 }
498
499 template<class T, std::size_t S>
500 inline void Pool<T,S>::grow()
501 {
502 Chunk *newChunk = new Chunk;
503 newChunk->next_ = chunks_;
504 chunks_ = newChunk;
505
506 char* start = chunks_->memory_;
507 char* last = &start[elements*alignedSize];
508 Reference* ref = new (start) (Reference);
509
510 // grow is only called if head==0,
511 assert(!head_);
512
513 head_ = ref;
514
515 for(char* element=start+alignedSize; element<last; element=element+alignedSize) {
516 Reference* next = new (element) (Reference);
517 ref->next_ = next;
518 ref = next;
519 }
520 ref->next_=0;
521 }
522
523 template<class T, std::size_t S>
524 inline void Pool<T,S>::free(void* b)
525 {
526 if(b) {
527#ifndef NDEBUG
528 Chunk* current=chunks_;
529 while(current) {
530 if(static_cast<void*>(&current->chunk_)<=b &&
531 static_cast<void*>((&current->chunk_)+chunkSize)>b)
532 break;
533 current=current->next_;
534 }
535 if(!current)
536 throw std::bad_alloc();
537#endif
538 Reference* freed = static_cast<Reference*>(b);
539 freed->next_ = head_;
540 head_ = freed;
541 //--allocated_;
542 }
543 else
544 {
545 std::cerr<< "Tried to free null pointer! "<<b<<std::endl;
546 throw std::bad_alloc();
547 }
548 }
549
550 template<class T, std::size_t S>
551 inline void* Pool<T,S>::allocate()
552 {
553 if(!head_)
554 grow();
555
556 Reference* p = head_;
557 head_ = p->next_;
558 //++allocated_;
559 return p;
560 }
561
562 template<class T, std::size_t s>
564 { }
565
566 template<class T, std::size_t s>
567 inline typename PoolAllocator<T,s>::pointer
569 {
570 if(n==1)
571 return static_cast<T*>(memoryPool_.allocate());
572 else
573 throw std::bad_alloc();
574 }
575
576 template<class T, std::size_t s>
577 inline void PoolAllocator<T,s>::deallocate(pointer p, std::size_t n)
578 {
579 for(size_t i=0; i<n; i++)
580 memoryPool_.free(p++);
581 }
582
583 template<class T, std::size_t s>
585 {
586 ::new (static_cast<void*>(p))T(value);
587 }
588
589 template<class T, std::size_t s>
591 {
592 p->~T();
593 }
594
596}
597#endif
This file implements a template class to determine alignment requirements of types at compile time.
An allocator managing a pool of objects for reuse.
Definition: poolallocator.hh:249
Pool< T, size > PoolType
The type of the memory pool we use.
Definition: poolallocator.hh:378
const_pointer address(const_reference x) const
Convert a reference to a pointer.
Definition: poolallocator.hh:361
int max_size() const
Not correctly implemented, yet!
Definition: poolallocator.hh:366
const T & const_reference
The constant reference type.
Definition: poolallocator.hh:285
std::size_t size_type
The size type.
Definition: poolallocator.hh:290
T value_type
Type of the values we construct and allocate.
Definition: poolallocator.hh:256
@ size
The number of objects to fit into one memory chunk allocated.
Definition: poolallocator.hh:264
T & reference
The reference type.
Definition: poolallocator.hh:280
PoolAllocator(const PoolAllocator &)
Copy constructor that does not copy the memory pool.
Definition: poolallocator.hh:313
const T * const_pointer
The constant pointer type.
Definition: poolallocator.hh:275
pointer address(reference x) const
Convert a reference to a pointer.
Definition: poolallocator.hh:355
T * pointer
The pointer type.
Definition: poolallocator.hh:270
PoolAllocator(const PoolAllocator< U, u > &)
Copy Constructor that does not copy the memory pool.
Definition: poolallocator.hh:306
std::ptrdiff_t difference_type
The difference_type.
Definition: poolallocator.hh:295
A memory pool of objects.
Definition: poolallocator.hh:90
@ elements
The number of element each chunk can hold.
Definition: poolallocator.hh:154
@ chunkSize
The size of each chunk memory chunk.
Definition: poolallocator.hh:147
@ unionSize
The size of a union of Reference and MemberType.
Definition: poolallocator.hh:114
@ alignment
The alignment that suits both the MemberType and the Reference (i.e. their least common multiple).
Definition: poolallocator.hh:128
@ size
Size requirement. At least one object has to stored.
Definition: poolallocator.hh:121
@ alignedSize
The aligned size of the type.
Definition: poolallocator.hh:136
T MemberType
The type of object we allocate memory for.
Definition: poolallocator.hh:108
void construct(pointer p, const_reference value)
Construct an object.
Definition: poolallocator.hh:584
void free(void *o)
Free an object.
Definition: poolallocator.hh:524
~Pool()
Destructor.
Definition: poolallocator.hh:469
void * allocate()
Get a new or recycled object.
Definition: poolallocator.hh:551
void print(std::ostream &os)
Print elements in pool for debugging.
Definition: poolallocator.hh:489
pointer allocate(std::size_t n, const_pointer hint=0)
Allocates objects.
Definition: poolallocator.hh:568
Pool()
Constructor.
Definition: poolallocator.hh:455
void deallocate(pointer p, std::size_t n)
Free objects.
Definition: poolallocator.hh:577
void destroy(pointer p)
Destroy an object without freeing memory.
Definition: poolallocator.hh:590
PoolAllocator()
Constructor.
Definition: poolallocator.hh:563
#define dune_static_assert(COND, MSG)
Helper template so that compilation fails if condition is not true.
Definition: static_assert.hh:79
EnableIfInterOperable< T1, T2, bool >::type operator==(const ForwardIteratorFacade< T1, V1, R1, D > &lhs, const ForwardIteratorFacade< T2, V2, R2, D > &rhs)
Checks for equality.
Definition: iteratorfacades.hh:231
EnableIfInterOperable< T1, T2, bool >::type operator!=(const ForwardIteratorFacade< T1, V1, R1, D > &lhs, const ForwardIteratorFacade< T2, V2, R2, D > &rhs)
Checks for inequality.
Definition: iteratorfacades.hh:253
Statically compute the least common multiple of two integers.
Dune namespace.
Definition: alignment.hh:14
STL namespace.
Fallback implementation of the C++0x static_assert feature.
Calculates the alignment requirement of a type.
Definition: alignment.hh:100
Calculate the least common multiple of two numbers.
Definition: lcm.hh:31
Rebind the allocator to another type.
Definition: poolallocator.hh:373
Get the 'const' version of a reference to a mutable object.
Definition: genericiterator.hh:86
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Jul 15, 22:36, 2024)