Rheolef  7.2
an efficient C++ finite element environment
heap_allocator.h
Go to the documentation of this file.
1 #ifndef _RHEOLEF_HEAP_ALLOCATOR_H
2 #define _RHEOLEF_HEAP_ALLOCATOR_H
23 
24 #include <memory>
25 #include <limits>
26 #include "rheolef/compiler.h"
27 #include "rheolef/pretty_name.h"
28 
29 namespace rheolef {
30 
31 /*Class:man
32 NAME: heap_allocator - heap-based allocator
33 DESCRIPTION:
34  Heap allocators are generally used when there is a lot of allocation and deallocation
35  of small objects.
36  For instance, this is often the case when dealing with @code{std::list} and @code{std::map}.
37 
38  Heap-based allocator is conform to the STL specification of allocators.
39  It does not "free" the memory until the heap is destroyed.
40 
41  This allocator handles an a priori unlimited area of memory: a sequence
42  of growing chunks are allocated.
43  For a limited memory handler in the same spirit, see "stack_allocator"(9).
44 EXAMPLE:
45  @example
46  typedef map <size_t, double, less<size_t>, heap_allocator<pair<size_t,double> > > map_type;
47  map_type a;
48  a.insert (make_pair (0, 3.14));
49  a.insert (make_pair (1, 1.17));
50  for (map_type::iterator iter = a.begin(), last = a.end(); iter != last; iter++) @{
51  cout << (*iter).first << " " << (*iter).second << endl;
52  @}
53  @end example
54 SEE ALSO: "stack_allocator"(9).
55 AUTHORS:
56  LJK-IMAG, 38041 Grenoble cedex 9, France
57  | Pierre.Saramito@imag.fr
58 DATE: 15 december 2010
59 End:
60 */
61 } // namespace rheolef
62 
63 #ifndef _RHEOLEF_USE_HEAP_ALLOCATOR
64 namespace rheolef {
65 template<class T> using heap_allocator = std::allocator<T>;
66 } // namespace rheolef
67 #else // _RHEOLEF_USE_HEAP_ALLOCATOR
68 
69 namespace rheolef {
70 
71 //<verbatim:
72 template <typename T>
74 protected:
75  struct handler_type; // forward declaration:
76 public:
77 
78 // typedefs:
79 
80  typedef size_t size_type;
81  typedef std::ptrdiff_t difference_type;
82  typedef T* pointer;
83  typedef const T* const_pointer;
84  typedef T& reference;
85  typedef const T& const_reference;
86  typedef T value_type;
87 
88 // constructors:
89 
90  heap_allocator() throw()
91  : handler (new handler_type)
92  {
93  }
94  heap_allocator (const heap_allocator& ha) throw()
95  : handler (ha.handler)
96  {
98  }
99  template <typename U>
100  heap_allocator (const heap_allocator<U>& ha) throw()
101  : handler ((typename heap_allocator<T>::handler_type*)(ha.handler))
102  {
104  }
105  ~heap_allocator() throw()
106  {
107  check_macro (handler != NULL, "unexpected null mem_info");
108  if (--handler->reference_count == 0) delete handler;
109  }
110  // Rebind to allocators of other types
111  template <typename U>
112  struct rebind {
114  };
115 
116 // assignment:
117 
119  {
120  handler = ha.handler;
122  return *this;
123  }
124 
125 // utility functions:
126 
127  pointer address (reference r) const { return &r; }
128  const_pointer address (const_reference c) const { return &c; }
129  size_type max_size() const { return std::numeric_limits<size_t>::max() / sizeof(T); }
130 
131 // in-place construction/destruction
132 
134  {
135  // placement new operator:
136  new( reinterpret_cast<void*>(p) ) T(c);
137  }
138  // C++ 2011: default construct a value of type T at the location referenced by p
139  void construct (pointer p) { new ( reinterpret_cast<void*>(p) ) T(); }
140 
142  {
143  // call destructor directly:
144  (p)->~T();
145  }
146 
147 // allocate raw memory
148 
149  pointer allocate (size_type n, const void* = NULL)
150  {
151  return pointer (handler->raw_allocate (n*sizeof(T)));
152  }
154  {
155  // No need to free heap memory
156  }
157  const handler_type* get_handler() const {
158  return handler;
159  }
160 
161 // data:
162 
163 protected:
165  template <typename U> friend class heap_allocator;
166 };
167 //>verbatim:
168 
169 // Comparison
170 template <typename T1>
171 bool operator== (const heap_allocator<T1>& lhs, const heap_allocator<T1>& rhs) throw()
172 {
173  return lhs.get_handler() == rhs.get_handler();
174 }
175 template <typename T1>
176 bool operator!= (const heap_allocator<T1>& lhs, const heap_allocator<T1>& rhs) throw()
177 {
178  return lhs.get_handler() != rhs.get_handler();
179 }
180 
181 // ==========================================================================
182 // heap_allocation::handler class implementation
183 // ==========================================================================
184 template<class T>
186 
187 // cstors:
188  handler_type ();
189  ~handler_type();
190 // modifier:
191  unsigned char* raw_allocate (size_type size);
192 // data:
193  std::list<std::vector<unsigned char> > heap;
197  static const size_type heap_block_size_init = 512*sizeof(T);
198 };
199 template<class T>
200 inline
202  : heap (),
203  heap_block_size (heap_block_size_init),
204  heap_block_last_free (0),
205  reference_count (1)
206 {
207  heap.push_front (std::vector<unsigned char>(heap_block_size));
208 }
209 template<class T>
210 inline
211 unsigned char*
213 {
214  if (heap_block_last_free + size > heap_block_size) {
215  heap_block_size = std::max (size, 2*heap_block_size);
216  heap.push_front (std::vector<unsigned char>(heap_block_size));
217  heap_block_last_free = 0;
218  }
219  std::vector<unsigned char>& block = *(heap.begin());
220  unsigned char* p = &(block [heap_block_last_free]);
221  heap_block_last_free += size;
222  return p;
223 }
224 template<class T>
225 inline
227 {
228  heap.erase (heap.begin(), heap.end());
229 }
230 
231 }// namespace rheolef
232 
233 // ==========================================================================
234 // std::allocator_traits
235 // ==========================================================================
236 namespace std {
237 
238 template <class T>
239 struct allocator_traits<rheolef::heap_allocator<T>> {
240 // typedefs
241 
243  using value_type = T;
244  using pointer = T*;
245  using const_pointer = typename std::pointer_traits<pointer>::rebind<const value_type>;
246  using void_pointer = typename std::pointer_traits<pointer>::rebind<void>;
247  using const_void_pointer = typename std::pointer_traits<pointer>::rebind<const void>;
248  using difference_type = typename std::pointer_traits<pointer>::difference_type;
249  using size_type = typename std::make_unsigned<difference_type>::type;
250  using propagate_on_container_copy_assignment = std::false_type;
251  using propagate_on_container_move_assignment = std::false_type;
252  using propagate_on_container_swap = std::false_type;
253  using is_always_equal = typename std::is_empty<rheolef::heap_allocator<T>>::type;
254  template <class U>
256 
257 // members
258 
259  static pointer allocate (allocator_type& a, size_type n) { return a.allocate(n); }
260  static void deallocate (allocator_type& a, pointer p, size_type n) { a.deallocate (p, n); }
261  static void construct (allocator_type& a, pointer p) { a.construct (p); }
262  static void construct (allocator_type& a, pointer p, const T& c) { a.construct (p,c); }
263  template <class U>
264  static void destroy (allocator_type& a, U* p) {}
265  static size_type max_size(const allocator_type& a ) { return std::numeric_limits<size_type>::mqx(); }allocator_type&
266 };
267 
268 } // namespace std
269 #endif // _RHEOLEF_USE_HEAP_ALLOCATOR
270 #endif // _RHEOLEF_HEAP_ALLOCATOR_H
heap_allocator(const heap_allocator &ha)
pointer allocate(size_type n, const void *=NULL)
pointer address(reference r) const
void construct(pointer p, const_reference c)
void construct(pointer p)
const handler_type * get_handler() const
size_type max_size() const
void destroy(pointer p)
heap_allocator(const heap_allocator< U > &ha)
std::ptrdiff_t difference_type
void deallocate(pointer p, size_type n)
const_pointer address(const_reference c) const
heap_allocator & operator=(const heap_allocator &ha)
rheolef::std type
std::allocator< T > heap_allocator
Expr1::float_type T
Definition: field_expr.h:230
check_macro(expr1.have_homogeneous_space(Xh1), "dual(expr1,expr2); expr1 should have homogeneous space. HINT: use dual(interpolate(Xh, expr1),expr2)")
This file is part of Rheolef.
bool operator==(const heap_allocator< T1 > &lhs, const heap_allocator< T1 > &rhs)
bool operator!=(const heap_allocator< T1 > &lhs, const heap_allocator< T1 > &rhs)
Definition: sphere.icc:25
unsigned char * raw_allocate(size_type size)
std::list< std::vector< unsigned char > > heap
typename std::pointer_traits< pointer >::difference_type difference_type
typename std::pointer_traits< pointer >::rebind< const void > const_void_pointer
typename std::pointer_traits< pointer >::rebind< const value_type > const_pointer
static void deallocate(allocator_type &a, pointer p, size_type n)
typename std::pointer_traits< pointer >::rebind< void > void_pointer
static void construct(allocator_type &a, pointer p, const T &c)
static pointer allocate(allocator_type &a, size_type n)
typename std::make_unsigned< difference_type >::type size_type
static size_type max_size(const allocator_type &a)
static void construct(allocator_type &a, pointer p)
typename std::is_empty< rheolef::heap_allocator< T > >::type is_always_equal
static void destroy(allocator_type &a, U *p)