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

 min_free_size = sizeof(FreeHeader)
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 159 of file MemoryPool.h.


Member Enumeration Documentation

anonymous enum [private]

Enumerator:
min_free_size 

Definition at line 196 of file MemoryPool.h.

00196        {
00197     min_free_size = sizeof(FreeHeader)
00198   };


Constructor & Destructor Documentation

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

Definition at line 298 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().

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

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

Definition at line 318 of file MemoryPool.cpp.

References pool_ptr_.

00319 {
00320 #ifndef OPENDDS_SAFETY_PROFILE
00321   delete [] pool_ptr_;
00322 #endif
00323 }


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 181 of file MemoryPool.h.

Referenced by pool_alloc().

00181                                                        {
00182      return (size + granularity - 1) / granularity * granularity; }

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

Definition at line 494 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().

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

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

Does the pool include a given pointer

Definition at line 166 of file MemoryPool.h.

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

00166                                  {
00167      return (pool_ptr_ <= ptr) && (ptr < pool_ptr_ + pool_size_); }

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

Definition at line 463 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().

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

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

Definition at line 406 of file MemoryPool.cpp.

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

Referenced by pool_free().

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

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

Definition at line 542 of file MemoryPool.cpp.

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

Referenced by join_free_allocs().

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

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

Definition at line 551 of file MemoryPool.cpp.

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

Referenced by join_free_allocs().

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

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

Low water mark of maximum available bytes for an allocation

Definition at line 326 of file MemoryPool.cpp.

References lwm_free_bytes_.

00327 {
00328   return lwm_free_bytes_;
00329 }

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

Allocate size bytes from the pool

Definition at line 332 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().

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

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 374 of file MemoryPool.cpp.

References header, includes(), join_free_allocs(), pool_ptr_, and pool_size_.

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

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

Definition at line 436 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().

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

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

Definition at line 184 of file MemoryPool.h.

00184 { return pool_size_; }


Friends And Related Function Documentation

friend class ::MemoryPoolTest [friend]

Definition at line 160 of file MemoryPool.h.


Member Data Documentation

FreeIndex OpenDDS::DCPS::MemoryPool::free_index_ [private]

Index of free nodex.

Definition at line 194 of file MemoryPool.h.

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

const size_t OpenDDS::DCPS::MemoryPool::granularity_ [private]

Configured granularity.

Definition at line 187 of file MemoryPool.h.

Referenced by pool_alloc().

FreeHeader* OpenDDS::DCPS::MemoryPool::largest_free_ [private]

Pointer to largest free index.

Definition at line 193 of file MemoryPool.h.

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

size_t OpenDDS::DCPS::MemoryPool::lwm_free_bytes_ [private]

Low water mark of available bytes.

Definition at line 190 of file MemoryPool.h.

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

const size_t OpenDDS::DCPS::MemoryPool::min_alloc_size_ [private]

Aligned minimum allocation size.

Definition at line 188 of file MemoryPool.h.

Referenced by pool_alloc().

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

Pointer to pool.

Definition at line 191 of file MemoryPool.h.

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

const size_t OpenDDS::DCPS::MemoryPool::pool_size_ [private]

Configured pool size.

Definition at line 189 of file MemoryPool.h.

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


The documentation for this class was generated from the following files:
Generated on Fri Feb 12 20:06:19 2016 for OpenDDS by  doxygen 1.4.7