MIRA
PoolAllocator.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2012 by
3  * MetraLabs GmbH (MLAB), GERMANY
4  * and
5  * Neuroinformatics and Cognitive Robotics Labs (NICR) at TU Ilmenau, GERMANY
6  * All rights reserved.
7  *
8  * Contact: info@mira-project.org
9  *
10  * Commercial Usage:
11  * Licensees holding valid commercial licenses may use this file in
12  * accordance with the commercial license agreement provided with the
13  * software or, alternatively, in accordance with the terms contained in
14  * a written agreement between you and MLAB or NICR.
15  *
16  * GNU General Public License Usage:
17  * Alternatively, this file may be used under the terms of the GNU
18  * General Public License version 3.0 as published by the Free Software
19  * Foundation and appearing in the file LICENSE.GPL3 included in the
20  * packaging of this file. Please review the following information to
21  * ensure the GNU General Public License version 3.0 requirements will be
22  * met: http://www.gnu.org/copyleft/gpl.html.
23  * Alternatively you may (at your option) use any later version of the GNU
24  * General Public License if such license has been publicly approved by
25  * MLAB and NICR (or its successors, if any).
26  *
27  * IN NO EVENT SHALL "MLAB" OR "NICR" BE LIABLE TO ANY PARTY FOR DIRECT,
28  * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF
29  * THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF "MLAB" OR
30  * "NICR" HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  * "MLAB" AND "NICR" SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
33  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
34  * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
35  * ON AN "AS IS" BASIS, AND "MLAB" AND "NICR" HAVE NO OBLIGATION TO
36  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR MODIFICATIONS.
37  */
38 
47 #ifndef _MIRA_POOLALLOCATOR_H_
48 #define _MIRA_POOLALLOCATOR_H_
49 
50 #include <assert.h>
51 #include <malloc.h> // for malloc and free
52 
53 #ifndef Q_MOC_RUN
54 #include <boost/noncopyable.hpp>
55 #endif
56 
57 #include <platform/Types.h>
58 #include <utils/Foreach.h>
59 #include <error/Exceptions.h>
60 
61 namespace mira {
62 
64 
91 template <typename T>
92 class PoolAllocator : boost::noncopyable
93 {
94 public:
95 
96  // STL conform typedefs
97 
99  typedef T value_type;
100 
102  typedef std::size_t size_type;
103 
105  typedef std::ptrdiff_t difference_type;
106 
108  typedef T* pointer;
109 
111  typedef T& reference;
112 
114  typedef const T* const_pointer;
115 
117  typedef const T& const_reference;
118 
119 
120 public:
121 
134  PoolAllocator(size_type poolCapacity=32, bool growPools=true, size_type itemSize=sizeof(T)) :
135  mFreeList(NULL), mNextCapacity(poolCapacity), mAllocatedBytes(0), mGrowPools(growPools) {
136  mItemSize = itemSize > sizeof(FreeListItem*) ? itemSize : sizeof(FreeListItem*);
137  newBlock();
138  }
139 
142  // free our memory blocks
143  foreach(uint8* p, mMemoryBlocks)
144  free(p);
145  }
146 
147  PoolAllocator(PoolAllocator&& other) noexcept :
148  mFreeList(NULL), mItemSize(0), mNextCapacity(0), mAllocatedBytes(0), mGrowPools(false) {
149  swap(other);
150  }
151 
152  PoolAllocator& operator=(PoolAllocator&& other) noexcept {
153  swap(other);
154  return *this;
155  }
156 
157 
158  void swap(PoolAllocator& other)
159  {
160  std::swap(mMemoryBlocks, other.mMemoryBlocks);
161  std::swap(mFreeList, other.mFreeList);
162  std::swap(mItemSize, other.mItemSize);
163  std::swap(mNextCapacity, other.mNextCapacity);
164  std::swap(mAllocatedBytes, other.mAllocatedBytes);
165  std::swap(mGrowPools, other.mGrowPools);
166  }
167 
168 public: // Interface to get memory usage
170  {
171  return mAllocatedBytes;
172  }
173 
175  {
176  return mAllocatedBytes - unusedMemory();
177  }
178 
180  {
181  size_type freeBytes = 0;
182  FreeListItem* curr = mFreeList;
183  while(curr)
184  {
185  freeBytes += mItemSize;
186  curr = curr->next;
187  }
188  return freeBytes;
189  }
190 
191 public:
192 
193  // STL conform interface:
194 
196  pointer address ( reference x ) const {
197  return &x;
198  }
199 
202  return &x;
203  }
204 
212  return 1;
213  }
214 
219  return mItemSize;
220  }
221 
229  pointer allocate (size_type n, const void* hint = 0) {
230  if(n!=1)
231  return NULL;
232 
233  uint8* memory = NULL;
234 
235  // we have no more free chunks, reserve a new block
236  if(mFreeList==NULL)
237  newBlock();
238 
239  assert(mFreeList!=NULL);
240 
241  // take first element of free list
242  memory = reinterpret_cast<uint8*>(mFreeList);
243  // next element becomes new head
244  mFreeList = mFreeList->next;
245 
246  return (pointer) memory;
247  }
248 
252  T* obj = new(p) T(val); // placement new
253  }
254 
256  void destroy(T* p) {
257  p->~T();
258  }
259 
263  if(p==NULL)
264  return;
265  assert(n==1);
266  // the deallocated memory will become a free list item
267  FreeListItem* item = reinterpret_cast<FreeListItem*>(p);
268 
269  // and it becomes the new head of that list (next points to the current head)
270  item->next = mFreeList;
271  mFreeList = item;
272  }
273 
283  T* construct() {
284  T* obj = allocate(1);
285  return new(obj) T();
286  }
287 
297  T* obj = allocate(1);
298  return new(obj) T(val);
299  }
300 
307  void destruct(pointer p) {
308  if(p==NULL)
309  return;
310  destroy(p);
311  deallocate(p,1);
312  }
313 
314 private:
315 
316  // creates a new big memory block
317  void newBlock() {
318  const size_type blockSize = mNextCapacity * mItemSize;
319  uint8* currentBlock = (uint8*) malloc(blockSize);
320  if(currentBlock==NULL)
321  MIRA_THROW(XBadAlloc, "Failed to allocate "
322  << blockSize << " bytes of memory");
323 
324  // build free list within the allocated block
325  FreeListItem* oldHead = mFreeList;
326 
327  // head of new free list
328  uint8* p = currentBlock;
329  FreeListItem* l = reinterpret_cast<FreeListItem*>(p);
330  mFreeList = l;
331  p+=mItemSize;
332 
333  // each element links to the next one
334  for(size_type i=1; i<mNextCapacity; ++i, p+=mItemSize)
335  {
336  l->next = reinterpret_cast<FreeListItem*>(p);
337  l = l->next;
338  }
339  l->next = oldHead;
340 
341  mMemoryBlocks.push_back(currentBlock);
342  mAllocatedBytes += blockSize;
343 
344  if(mGrowPools)
345  mNextCapacity = mNextCapacity*2;
346  }
347 
348 private:
349 
350  std::list<uint8*> mMemoryBlocks;
351 
352  struct FreeListItem {
353  FreeListItem* next;
354  };
355  FreeListItem* mFreeList;
356 
357  size_type mItemSize;
358  size_type mNextCapacity;
359  size_type mAllocatedBytes;
360  bool mGrowPools;
361 };
362 
364 
365 } // namespace
366 
367 #endif
pointer allocate(size_type n, const void *hint=0)
Allocate a block of storage and returns the pointer, note that the object is not constructed.
Definition: PoolAllocator.h:229
Macro for iterating over all elements in a container.
T & reference
Reference to element.
Definition: PoolAllocator.h:111
Typedefs for OS independent basic data types.
T * construct(const_reference val)
Allocates a new feature and returns its pointer This method is provided for convenience.
Definition: PoolAllocator.h:296
size_type itemSize() const MIRA_NOEXCEPT_OR_NOTHROW
Returns the size of each item in bytes.
Definition: PoolAllocator.h:218
specialize cv::DataType for our ImgPixel and inherit from cv::DataType<Vec>
Definition: IOService.h:67
Provides a pool allocator that is compatible to STL allocators.
Definition: PoolAllocator.h:92
size_type unusedMemory() const
Definition: PoolAllocator.h:179
void destroy(T *p)
Destroy an object. Notice that this does not deallocate space for the element.
Definition: PoolAllocator.h:256
void construct(pointer p, const_reference val)
Constructs an object of type T on the location p using its copy constructor to initialize its value t...
Definition: PoolAllocator.h:251
size_type allocatedMemory() const
Definition: PoolAllocator.h:169
std::size_t size_type
Quantities of elements.
Definition: PoolAllocator.h:102
T * pointer
Pointer to element.
Definition: PoolAllocator.h:108
#define MIRA_THROW(ex, msg)
Macro for throwing an exception.
Definition: Exception.h:81
size_type max_size() const MIRA_NOEXCEPT_OR_NOTHROW
Returns the maximum number of elements of type T (the template parameter) that could be allocated by ...
Definition: PoolAllocator.h:211
void destruct(pointer p)
Destroys the object and deallocates the memory.
Definition: PoolAllocator.h:307
void deallocate(pointer p, size_type n)
Releases a block of storage previously allocated with member allocate and not yet released...
Definition: PoolAllocator.h:262
std::ptrdiff_t difference_type
Difference between two pointers.
Definition: PoolAllocator.h:105
Commonly used exception classes.
T * construct()
Allocates and constructs a new object and returns its pointer.
Definition: PoolAllocator.h:283
#define MIRA_NOEXCEPT_OR_NOTHROW
Definition: NoExcept.h:99
const T & const_reference
Constant reference to element.
Definition: PoolAllocator.h:117
~PoolAllocator()
Destructor.
Definition: PoolAllocator.h:141
PoolAllocator(size_type poolCapacity=32, bool growPools=true, size_type itemSize=sizeof(T))
Creates a new PoolAllocator.
Definition: PoolAllocator.h:134
PoolAllocator & operator=(PoolAllocator &&other) noexcept
Definition: PoolAllocator.h:152
pointer address(reference x) const
Returns the address of x.
Definition: PoolAllocator.h:196
T value_type
Element type.
Definition: PoolAllocator.h:99
size_type usedMemory() const
Definition: PoolAllocator.h:174
const_pointer address(const_reference x) const
Returns the address of x.
Definition: PoolAllocator.h:201
void swap(PoolAllocator &other)
Definition: PoolAllocator.h:158
PoolAllocator(PoolAllocator &&other) noexcept
Definition: PoolAllocator.h:147
const T * const_pointer
Reference to element.
Definition: PoolAllocator.h:114