OpenDDS::DCPS::MemoryPool Class Reference

#include <MemoryPool.h>

Collaboration diagram for OpenDDS::DCPS::MemoryPool:
Collaboration graph
[legend]

List of all members.

Public Member Functions

 MemoryPool (unsigned int pool_size, size_t granularity=8)
 ~MemoryPool ()
bool includes (void *ptr) const
void * pool_alloc (size_t size)
bool pool_free (void *ptr)
size_t lwm_free_bytes () const
size_t size () const

Static Public Member Functions

static size_t align (size_t size, size_t granularity)

Private Types

enum  { min_free_size = sizeof(FreeHeader) }

Private Member Functions

void remove_free_alloc (FreeHeader *block_to_alloc)
void insert_free_alloc (FreeHeader *block_freed)
void join_free_allocs (FreeHeader *block_freed)
unsigned char * allocate (FreeHeader *free_block, size_t alloc_size)
bool joinable_next (FreeHeader *freed)
bool joinable_prev (FreeHeader *freed)

Private Attributes

const size_t granularity_
 Configured granularity.
const size_t min_alloc_size_
 Aligned minimum allocation size.
const size_t pool_size_
 Configured pool size.
size_t lwm_free_bytes_
 Low water mark of available bytes.
unsigned char * pool_ptr_
 Pointer to pool.
FreeHeaderlargest_free_
 Pointer to largest free index.
FreeIndex free_index_
 Index of free nodex.

Friends

class ::MemoryPoolTest

Detailed Description

Definition at line 161 of file MemoryPool.h.


Member Enumeration Documentation

anonymous enum [private]
Enumerator:
min_free_size 

Definition at line 198 of file MemoryPool.h.

00198        {
00199     min_free_size = sizeof(FreeHeader)
00200   };


Constructor & Destructor Documentation

OpenDDS::DCPS::MemoryPool::MemoryPool ( unsigned int  pool_size,
size_t  granularity = 8 
) [explicit]

Definition at line 300 of file MemoryPool.cpp.

References free_index_, OpenDDS::DCPS::FreeIndex::init(), OpenDDS::DCPS::FreeHeader::init_free_block(), largest_free_, lwm_free_bytes_, pool_ptr_, pool_size_, and OpenDDS::DCPS::AllocHeader::size().

00301 : granularity_(align(granularity, 8))
00302 , min_alloc_size_(align(min_free_size - sizeof(AllocHeader), granularity_))
00303 , pool_size_(align(pool_size, granularity_))
00304 , pool_ptr_(new unsigned char[pool_size_])
00305 , largest_free_(NULL)
00306 , free_index_(largest_free_)
00307 {
00308   AllocHeader* the_pool = new (pool_ptr_) AllocHeader();
00309   FreeHeader* first_free = reinterpret_cast<FreeHeader*>(the_pool);
00310   first_free->init_free_block(static_cast<unsigned int>(pool_size_));
00311   largest_free_ = first_free;
00312   free_index_.init(first_free);
00313   lwm_free_bytes_ = largest_free_->size();
00314 #if defined(WITH_VALGRIND)
00315   VALGRIND_MAKE_MEM_NOACCESS(pool_ptr_, pool_size_);
00316   VALGRIND_CREATE_MEMPOOL(pool_ptr_, 0, false);
00317 #endif
00318 }

Here is the call graph for this function:

OpenDDS::DCPS::MemoryPool::~MemoryPool (  ) 

Definition at line 320 of file MemoryPool.cpp.

References pool_ptr_.

00321 {
00322 #ifndef OPENDDS_SAFETY_PROFILE
00323   delete [] pool_ptr_;
00324 #endif
00325 }


Member Function Documentation

static size_t OpenDDS::DCPS::MemoryPool::align ( size_t  size,
size_t  granularity 
) [inline, static]

Calculate aligned size of allocation

Definition at line 183 of file MemoryPool.h.

Referenced by pool_alloc().

00183                                                        {
00184      return (size + granularity - 1) / granularity * granularity; }

Here is the caller graph for this function:

unsigned char * OpenDDS::DCPS::MemoryPool::allocate ( FreeHeader free_block,
size_t  alloc_size 
) [private]

Definition at line 496 of file MemoryPool.cpp.

References includes(), insert_free_alloc(), min_free_size, OpenDDS::DCPS::AllocHeader::next_adjacent(), OpenDDS::DCPS::AllocHeader::ptr(), remove_free_alloc(), OpenDDS::DCPS::AllocHeader::set_allocated(), OpenDDS::DCPS::AllocHeader::set_prev_size(), OpenDDS::DCPS::AllocHeader::set_size(), and OpenDDS::DCPS::AllocHeader::size().

Referenced by pool_alloc().

00497 {
00498   size_t free_block_size = free_block->size();
00499   size_t remainder = free_block_size - alloc_size;
00500 
00501   // May not be enough room for another allocation
00502   if (remainder < min_free_size) {
00503     alloc_size = free_block_size; // use it all
00504     remainder = 0;
00505   }
00506 
00507   // If we are NOT allocating the whole block
00508   if (remainder) {
00509     // Account for header here - won't overflow due to check, above
00510     remainder -= sizeof(AllocHeader);
00511 
00512     // Adjust current adjacent block (after free block)
00513     AllocHeader* next_adjacent = free_block->next_adjacent();
00514     if (includes(next_adjacent)) {
00515       next_adjacent->set_prev_size(static_cast<int>(alloc_size));
00516     }
00517 
00518     // Always remove, resize, and reinsert to make sure free list and free
00519     // index are in sync
00520     remove_free_alloc(free_block);
00521     free_block->set_size(remainder);
00522     insert_free_alloc(free_block);
00523 
00524     // After resize, can use next_adjacent() to safely get to the end of the
00525     // resized block.
00526     // Taking free memory and allocating, so invoke constructor
00527     AllocHeader* alloc_block = new(free_block->next_adjacent()) AllocHeader();
00528 
00529     // Allocate adjacent block (at end of existing block)
00530     alloc_block->set_size(alloc_size);
00531     alloc_block->set_allocated();
00532     alloc_block->set_prev_size(static_cast<int>(remainder));
00533     return alloc_block->ptr();
00534   // Else we ARE allocating the whole block
00535   } else {
00536     free_block->set_allocated();
00537     // remove free_block from free list
00538     remove_free_alloc(free_block);
00539     return free_block->ptr();
00540   }
00541 }

Here is the call graph for this function:

Here is the caller graph for this function:

bool OpenDDS::DCPS::MemoryPool::includes ( void *  ptr  )  const [inline]

Does the pool include a given pointer

Definition at line 168 of file MemoryPool.h.

Referenced by allocate(), join_free_allocs(), joinable_next(), joinable_prev(), and pool_free().

00168                                  {
00169      return (pool_ptr_ <= ptr) && (ptr < pool_ptr_ + pool_size_); }

Here is the caller graph for this function:

void OpenDDS::DCPS::MemoryPool::insert_free_alloc ( FreeHeader block_freed  )  [private]

Definition at line 465 of file MemoryPool.cpp.

References OpenDDS::DCPS::FreeIndex::add(), OpenDDS::DCPS::FreeIndex::find(), free_index_, largest_free_, pool_ptr_, OpenDDS::DCPS::FreeHeader::set_larger_free(), OpenDDS::DCPS::FreeHeader::set_smaller_free(), OpenDDS::DCPS::AllocHeader::size(), and OpenDDS::DCPS::FreeHeader::smaller_free().

Referenced by allocate(), and join_free_allocs().

00466 {
00467   // Find free alloc freed size or larger
00468   FreeHeader* alloc = free_index_.find(freed->size(), pool_ptr_);
00469   // If found
00470   if (alloc) {
00471     FreeHeader* smaller = alloc->smaller_free(pool_ptr_);
00472 
00473     // Insert into list
00474     freed->set_larger_free(alloc, pool_ptr_);
00475     alloc->set_smaller_free(freed, pool_ptr_);
00476     if (smaller) {
00477       smaller->set_larger_free(freed, pool_ptr_);
00478       freed->set_smaller_free(smaller, pool_ptr_);
00479     }
00480   // Else freed the largest alloc
00481   } else {
00482     if (freed != largest_free_) {
00483       freed->set_smaller_free(largest_free_, pool_ptr_);
00484       if (largest_free_) {
00485         largest_free_->set_larger_free(freed, pool_ptr_);
00486       }
00487       largest_free_ = freed;
00488     }
00489   }
00490 
00491   // Insert and replace alloc if necessary
00492   free_index_.add(freed);
00493 }

Here is the call graph for this function:

Here is the caller graph for this function:

void OpenDDS::DCPS::MemoryPool::join_free_allocs ( FreeHeader block_freed  )  [private]

Definition at line 408 of file MemoryPool.cpp.

References includes(), insert_free_alloc(), OpenDDS::DCPS::AllocHeader::join_next(), joinable_next(), joinable_prev(), OpenDDS::DCPS::AllocHeader::next_adjacent(), OpenDDS::DCPS::AllocHeader::prev_adjacent(), remove_free_alloc(), OpenDDS::DCPS::AllocHeader::set_prev_size(), and OpenDDS::DCPS::AllocHeader::size().

Referenced by pool_free().

00409 {
00410   // Check adjacent
00411   if (joinable_next(freed)) {
00412     FreeHeader* next_free = reinterpret_cast<FreeHeader*>(freed->next_adjacent());
00413     remove_free_alloc(next_free);
00414     freed->join_next();
00415     // Adjust psize of adjacent
00416     AllocHeader* next = freed->next_adjacent();
00417     if (includes(next)) {
00418       next->set_prev_size(freed->size());
00419     }
00420   }
00421   if (joinable_prev(freed)) {
00422     FreeHeader* prev_free = reinterpret_cast<FreeHeader*>(freed->prev_adjacent());
00423     remove_free_alloc(prev_free);
00424     // Join prev with freed
00425     prev_free->join_next();
00426     insert_free_alloc(prev_free);
00427     // Adjust psize of adjacent
00428     AllocHeader* next = prev_free->next_adjacent();
00429     if (includes(next)) {
00430       next->set_prev_size(prev_free->size());
00431     }
00432   } else {
00433     insert_free_alloc(freed);
00434   }
00435 }

Here is the call graph for this function:

Here is the caller graph for this function:

bool OpenDDS::DCPS::MemoryPool::joinable_next ( FreeHeader freed  )  [private]

Definition at line 544 of file MemoryPool.cpp.

References includes(), OpenDDS::DCPS::AllocHeader::is_free(), and OpenDDS::DCPS::AllocHeader::next_adjacent().

Referenced by join_free_allocs().

00545 {
00546   AllocHeader* next_alloc = freed->next_adjacent();
00547   return freed->is_free() &&
00548          includes(next_alloc) &&
00549          next_alloc->is_free();
00550 }

Here is the call graph for this function:

Here is the caller graph for this function:

bool OpenDDS::DCPS::MemoryPool::joinable_prev ( FreeHeader freed  )  [private]

Definition at line 553 of file MemoryPool.cpp.

References includes(), OpenDDS::DCPS::AllocHeader::is_free(), and OpenDDS::DCPS::AllocHeader::prev_adjacent().

Referenced by join_free_allocs().

00554 {
00555   AllocHeader* prev_alloc = freed->prev_adjacent();
00556   return freed->is_free() &&
00557          includes(prev_alloc) &&
00558          prev_alloc->is_free();
00559 }

Here is the call graph for this function:

Here is the caller graph for this function:

size_t OpenDDS::DCPS::MemoryPool::lwm_free_bytes (  )  const

Low water mark of maximum available bytes for an allocation

Definition at line 328 of file MemoryPool.cpp.

References lwm_free_bytes_.

00329 {
00330   return lwm_free_bytes_;
00331 }

void * OpenDDS::DCPS::MemoryPool::pool_alloc ( size_t  size  ) 

Allocate size bytes from the pool

Definition at line 334 of file MemoryPool.cpp.

References align(), allocate(), OpenDDS::DCPS::FreeIndex::find(), free_index_, granularity_, largest_free_, lwm_free_bytes_, min_alloc_size_, pool_ptr_, pool_size_, and OpenDDS::DCPS::AllocHeader::size().

00335 {
00336 #if defined(WITH_VALGRIND)
00337   VALGRIND_DISABLE_ADDR_ERROR_REPORTING_IN_RANGE(pool_ptr_, pool_size_);
00338 #endif
00339 
00340   // Pointer to return
00341   unsigned char* block = NULL;
00342 
00343   // Round up to 8-byte boundary
00344   size_t aligned_size = align(size, granularity_);
00345 
00346   if (aligned_size < min_alloc_size_) {
00347     aligned_size = min_alloc_size_;
00348   }
00349 
00350   // The block to allocate from
00351   FreeHeader* block_to_alloc = free_index_.find(aligned_size, pool_ptr_);
00352 
00353   if (block_to_alloc) {
00354     block = allocate(block_to_alloc, aligned_size);
00355   }
00356 
00357   // Update lwm
00358   size_t largest_free_bytes = largest_free_ ? largest_free_->size() : 0;
00359   if (largest_free_bytes < lwm_free_bytes_) {
00360     lwm_free_bytes_ = largest_free_bytes;
00361   }
00362 
00363 #ifdef VALIDATE_MEMORY_POOL
00364   validate_pool(*this, false);
00365 #endif
00366 
00367 #if defined(WITH_VALGRIND)
00368   VALGRIND_ENABLE_ADDR_ERROR_REPORTING_IN_RANGE(pool_ptr_, pool_size_);
00369   VALGRIND_MEMPOOL_ALLOC(pool_ptr_, block, size);
00370 #endif
00371 
00372   return block;
00373 }

Here is the call graph for this function:

bool OpenDDS::DCPS::MemoryPool::pool_free ( void *  ptr  ) 

Attempt to free an allocation. Return true if allocation is managed by this pool (and thus was freed).

Definition at line 376 of file MemoryPool.cpp.

References header, includes(), join_free_allocs(), pool_ptr_, pool_size_, and OpenDDS::DCPS::FreeHeader::set_free().

00377 {
00378   bool freed = false;
00379   if (ptr && includes(ptr)) {
00380 #if defined(WITH_VALGRIND)
00381     VALGRIND_DISABLE_ADDR_ERROR_REPORTING_IN_RANGE(pool_ptr_, pool_size_);
00382 #endif
00383 
00384     FreeHeader* header = reinterpret_cast<FreeHeader*>(
00385         reinterpret_cast<AllocHeader*>(ptr) - 1);
00386 
00387     // Free header
00388     header->set_free();
00389 
00390     join_free_allocs(header);
00391 
00392 #ifdef VALIDATE_MEMORY_POOL
00393     validate_pool(*this, false);
00394 #endif
00395 
00396     freed = true;
00397 
00398 #if defined(WITH_VALGRIND)
00399     VALGRIND_DISABLE_ADDR_ERROR_REPORTING_IN_RANGE(pool_ptr_, pool_size_);
00400     VALGRIND_MEMPOOL_FREE(pool_ptr_, ptr);
00401 #endif
00402   }
00403 
00404   return freed;
00405 }

Here is the call graph for this function:

void OpenDDS::DCPS::MemoryPool::remove_free_alloc ( FreeHeader block_to_alloc  )  [private]

Definition at line 438 of file MemoryPool.cpp.

References free_index_, OpenDDS::DCPS::FreeHeader::larger_free(), largest_free_, pool_ptr_, OpenDDS::DCPS::FreeIndex::remove(), OpenDDS::DCPS::FreeHeader::set_larger_free(), OpenDDS::DCPS::FreeHeader::set_smaller_free(), and OpenDDS::DCPS::FreeHeader::smaller_free().

Referenced by allocate(), and join_free_allocs().

00439 {
00440   FreeHeader* smaller = block_to_alloc->smaller_free(pool_ptr_);
00441   FreeHeader* larger = block_to_alloc->larger_free(pool_ptr_);
00442 
00443   block_to_alloc->set_smaller_free(NULL, NULL);
00444   block_to_alloc->set_larger_free(NULL, NULL);
00445 
00446   // If this was the largest free alloc
00447   if (block_to_alloc == largest_free_) {
00448     // It no longer is
00449     largest_free_ = smaller;
00450   }
00451 
00452   if (larger) {
00453     larger->set_smaller_free(smaller, pool_ptr_);
00454   }
00455 
00456   if (smaller) {
00457     smaller->set_larger_free(larger, pool_ptr_);
00458   }
00459 
00460   // Remove from free index
00461   free_index_.remove(block_to_alloc, larger);
00462 }

Here is the call graph for this function:

Here is the caller graph for this function:

size_t OpenDDS::DCPS::MemoryPool::size ( void   )  const [inline]

Definition at line 186 of file MemoryPool.h.

00186 { return pool_size_; }


Friends And Related Function Documentation

friend class ::MemoryPoolTest [friend]

Definition at line 162 of file MemoryPool.h.


Member Data Documentation

Index of free nodex.

Definition at line 196 of file MemoryPool.h.

Referenced by insert_free_alloc(), MemoryPool(), pool_alloc(), and remove_free_alloc().

Configured granularity.

Definition at line 189 of file MemoryPool.h.

Referenced by pool_alloc().

Pointer to largest free index.

Definition at line 195 of file MemoryPool.h.

Referenced by insert_free_alloc(), MemoryPool(), pool_alloc(), and remove_free_alloc().

Low water mark of available bytes.

Definition at line 192 of file MemoryPool.h.

Referenced by lwm_free_bytes(), MemoryPool(), and pool_alloc().

Aligned minimum allocation size.

Definition at line 190 of file MemoryPool.h.

Referenced by pool_alloc().

unsigned char* OpenDDS::DCPS::MemoryPool::pool_ptr_ [private]

Pointer to pool.

Definition at line 193 of file MemoryPool.h.

Referenced by insert_free_alloc(), MemoryPool(), pool_alloc(), pool_free(), remove_free_alloc(), and ~MemoryPool().

Configured pool size.

Definition at line 191 of file MemoryPool.h.

Referenced by MemoryPool(), pool_alloc(), and pool_free().


The documentation for this class was generated from the following files:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 10 Aug 2018 for OpenDDS by  doxygen 1.6.1