Rheolef  7.2
an efficient C++ finite element environment
Loading...
Searching...
No Matches
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
29namespace rheolef {
30
31/*Class:man
32NAME: heap_allocator - heap-based allocator
33DESCRIPTION:
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).
44EXAMPLE:
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
54SEE ALSO: "stack_allocator"(9).
55AUTHORS:
56 LJK-IMAG, 38041 Grenoble cedex 9, France
57 | Pierre.Saramito@imag.fr
58DATE: 15 december 2010
59End:
60*/
61} // namespace rheolef
62
63#ifndef _RHEOLEF_USE_HEAP_ALLOCATOR
64namespace rheolef {
65template<class T> using heap_allocator = std::allocator<T>;
66} // namespace rheolef
67#else // _RHEOLEF_USE_HEAP_ALLOCATOR
68
69namespace rheolef {
70
71//<verbatim:
72template <typename T>
73class heap_allocator {
74protected:
75 struct handler_type; // forward declaration:
76public:
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 {
97 ++handler->reference_count;
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 {
103 ++handler->reference_count;
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 {
113 typedef heap_allocator<U> other;
114 };
115
116// assignment:
117
118 heap_allocator& operator= (const heap_allocator& ha)
119 {
120 handler = ha.handler;
121 ++handler->reference_count;
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
133 void construct (pointer p, const_reference c)
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
141 void destroy (pointer p)
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 }
153 void deallocate (pointer p, size_type n)
154 {
155 // No need to free heap memory
156 }
157 const handler_type* get_handler() const {
158 return handler;
159 }
160
161// data:
162
163protected:
164 handler_type* handler;
165 template <typename U> friend class heap_allocator;
166};
167//>verbatim:
168
169// Comparison
170template <typename T1>
171bool operator== (const heap_allocator<T1>& lhs, const heap_allocator<T1>& rhs) throw()
172{
173 return lhs.get_handler() == rhs.get_handler();
174}
175template <typename T1>
176bool 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// ==========================================================================
184template<class T>
185struct heap_allocator<T>::handler_type {
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;
194 size_type heap_block_size;
195 size_type heap_block_last_free;
196 size_type reference_count;
197 static const size_type heap_block_size_init = 512*sizeof(T);
198};
199template<class T>
200inline
201heap_allocator<T>::handler_type::handler_type()
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}
209template<class T>
210inline
211unsigned char*
212heap_allocator<T>::handler_type::raw_allocate (size_type size)
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}
224template<class T>
225inline
226heap_allocator<T>::handler_type::~handler_type()
227{
228 heap.erase (heap.begin(), heap.end());
229}
230
231}// namespace rheolef
232
233// ==========================================================================
234// std::allocator_traits
235// ==========================================================================
236namespace std {
237
238template <class T>
239struct allocator_traits<rheolef::heap_allocator<T>> {
240// typedefs
241
242 using allocator_type = rheolef::heap_allocator<T>;
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>
255 using rebind_alloc = rheolef::heap_allocator<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
field::size_type size_type
Definition branch.cc:430
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 stack_allocator< T1 > &lhs, const stack_allocator< T1 > &rhs)
bool operator==(const stack_allocator< T1 > &lhs, const stack_allocator< T1 > &rhs)
Definition sphere.icc:25