OpenDDS  Snapshot(2023/04/07-19:43)
Public Member Functions | Static Public Member Functions | Private Types | Private Member Functions | Private Attributes | Friends | List of all members
OpenDDS::DCPS::MemoryPool Class Reference

#include <MemoryPool.h>

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

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. More...
 
const size_t min_alloc_size_
 Aligned minimum allocation size. More...
 
const size_t pool_size_
 Configured pool size. More...
 
size_t lwm_free_bytes_
 Low water mark of available bytes. More...
 
unsigned char * pool_ptr_
 Pointer to pool. More...
 
FreeHeaderlargest_free_
 Pointer to largest free index. More...
 
FreeIndex free_index_
 Index of free nodex. More...
 

Friends

class Test::MemoryPoolTest
 

Detailed Description

Definition at line 162 of file MemoryPool.h.

Member Enumeration Documentation

◆ anonymous enum

anonymous enum
private
Enumerator
min_free_size 

Definition at line 199 of file MemoryPool.h.

199  {
200  min_free_size = sizeof(FreeHeader)
201  };

Constructor & Destructor Documentation

◆ MemoryPool()

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().

301 : granularity_(align(granularity, 8))
302 , min_alloc_size_(align(min_free_size - sizeof(AllocHeader), granularity_))
303 , pool_size_(align(pool_size, granularity_))
304 , pool_ptr_(new unsigned char[pool_size_])
305 , largest_free_(NULL)
307 {
308  AllocHeader* the_pool = new (pool_ptr_) AllocHeader();
309  FreeHeader* first_free = reinterpret_cast<FreeHeader*>(the_pool);
310  first_free->init_free_block(static_cast<unsigned int>(pool_size_));
311  largest_free_ = first_free;
312  free_index_.init(first_free);
314 #if defined(WITH_VALGRIND)
315  VALGRIND_MAKE_MEM_NOACCESS(pool_ptr_, pool_size_);
316  VALGRIND_CREATE_MEMPOOL(pool_ptr_, 0, false);
317 #endif
318 }
const size_t min_alloc_size_
Aligned minimum allocation size.
Definition: MemoryPool.h:191
static size_t align(size_t size, size_t granularity)
Definition: MemoryPool.h:184
unsigned char * pool_ptr_
Pointer to pool.
Definition: MemoryPool.h:194
unsigned int size() const
Definition: MemoryPool.h:30
void init(FreeHeader *init_free_block)
Definition: MemoryPool.cpp:198
FreeHeader * largest_free_
Pointer to largest free index.
Definition: MemoryPool.h:196
FreeIndex free_index_
Index of free nodex.
Definition: MemoryPool.h:197
const size_t granularity_
Configured granularity.
Definition: MemoryPool.h:190
const size_t pool_size_
Configured pool size.
Definition: MemoryPool.h:192
size_t lwm_free_bytes_
Low water mark of available bytes.
Definition: MemoryPool.h:193

◆ ~MemoryPool()

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

Definition at line 320 of file MemoryPool.cpp.

References pool_ptr_.

321 {
322 #ifndef OPENDDS_SAFETY_PROFILE
323  delete [] pool_ptr_;
324 #endif
325 }
unsigned char * pool_ptr_
Pointer to pool.
Definition: MemoryPool.h:194

Member Function Documentation

◆ align()

static size_t OpenDDS::DCPS::MemoryPool::align ( size_t  size,
size_t  granularity 
)
inlinestatic

Calculate aligned size of allocation

Definition at line 184 of file MemoryPool.h.

Referenced by pool_alloc().

184  {
185  return (size + granularity - 1) / granularity * granularity; }

◆ allocate()

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().

497 {
498  size_t free_block_size = free_block->size();
499  size_t remainder = free_block_size - alloc_size;
500 
501  // May not be enough room for another allocation
502  if (remainder < min_free_size) {
503  alloc_size = free_block_size; // use it all
504  remainder = 0;
505  }
506 
507  // If we are NOT allocating the whole block
508  if (remainder) {
509  // Account for header here - won't overflow due to check, above
510  remainder -= sizeof(AllocHeader);
511 
512  // Adjust current adjacent block (after free block)
513  AllocHeader* next_adjacent = free_block->next_adjacent();
514  if (includes(next_adjacent)) {
515  next_adjacent->set_prev_size(static_cast<int>(alloc_size));
516  }
517 
518  // Always remove, resize, and reinsert to make sure free list and free
519  // index are in sync
520  remove_free_alloc(free_block);
521  free_block->set_size(remainder);
522  insert_free_alloc(free_block);
523 
524  // After resize, can use next_adjacent() to safely get to the end of the
525  // resized block.
526  // Taking free memory and allocating, so invoke constructor
527  AllocHeader* alloc_block = new(free_block->next_adjacent()) AllocHeader();
528 
529  // Allocate adjacent block (at end of existing block)
530  alloc_block->set_size(alloc_size);
531  alloc_block->set_allocated();
532  alloc_block->set_prev_size(static_cast<int>(remainder));
533  return alloc_block->ptr();
534  // Else we ARE allocating the whole block
535  } else {
536  free_block->set_allocated();
537  // remove free_block from free list
538  remove_free_alloc(free_block);
539  return free_block->ptr();
540  }
541 }
void remove_free_alloc(FreeHeader *block_to_alloc)
Definition: MemoryPool.cpp:438
void insert_free_alloc(FreeHeader *block_freed)
Definition: MemoryPool.cpp:465
bool includes(void *ptr) const
Definition: MemoryPool.h:169

◆ includes()

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

Does the pool include a given pointer

Definition at line 169 of file MemoryPool.h.

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

169  {
170  return (pool_ptr_ <= ptr) && (ptr < pool_ptr_ + pool_size_); }
unsigned char * pool_ptr_
Pointer to pool.
Definition: MemoryPool.h:194
const size_t pool_size_
Configured pool size.
Definition: MemoryPool.h:192

◆ insert_free_alloc()

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().

466 {
467  // Find free alloc freed size or larger
468  FreeHeader* alloc = free_index_.find(freed->size(), pool_ptr_);
469  // If found
470  if (alloc) {
471  FreeHeader* smaller = alloc->smaller_free(pool_ptr_);
472 
473  // Insert into list
474  freed->set_larger_free(alloc, pool_ptr_);
475  alloc->set_smaller_free(freed, pool_ptr_);
476  if (smaller) {
477  smaller->set_larger_free(freed, pool_ptr_);
478  freed->set_smaller_free(smaller, pool_ptr_);
479  }
480  // Else freed the largest alloc
481  } else {
482  if (freed != largest_free_) {
483  freed->set_smaller_free(largest_free_, pool_ptr_);
484  if (largest_free_) {
486  }
487  largest_free_ = freed;
488  }
489  }
490 
491  // Insert and replace alloc if necessary
492  free_index_.add(freed);
493 }
FreeHeader * find(size_t size, unsigned char *base)
Definition: MemoryPool.cpp:209
FreeHeader * smaller_free(unsigned char *pool_base) const
Definition: MemoryPool.cpp:108
void set_larger_free(FreeHeader *prev, unsigned char *pool_base)
Definition: MemoryPool.cpp:138
void add(FreeHeader *free_block)
Definition: MemoryPool.cpp:168
unsigned char * pool_ptr_
Pointer to pool.
Definition: MemoryPool.h:194
FreeHeader * largest_free_
Pointer to largest free index.
Definition: MemoryPool.h:196
FreeIndex free_index_
Index of free nodex.
Definition: MemoryPool.h:197

◆ join_free_allocs()

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().

409 {
410  // Check adjacent
411  if (joinable_next(freed)) {
412  FreeHeader* next_free = reinterpret_cast<FreeHeader*>(freed->next_adjacent());
413  remove_free_alloc(next_free);
414  freed->join_next();
415  // Adjust psize of adjacent
416  AllocHeader* next = freed->next_adjacent();
417  if (includes(next)) {
418  next->set_prev_size(freed->size());
419  }
420  }
421  if (joinable_prev(freed)) {
422  FreeHeader* prev_free = reinterpret_cast<FreeHeader*>(freed->prev_adjacent());
423  remove_free_alloc(prev_free);
424  // Join prev with freed
425  prev_free->join_next();
426  insert_free_alloc(prev_free);
427  // Adjust psize of adjacent
428  AllocHeader* next = prev_free->next_adjacent();
429  if (includes(next)) {
430  next->set_prev_size(prev_free->size());
431  }
432  } else {
433  insert_free_alloc(freed);
434  }
435 }
void remove_free_alloc(FreeHeader *block_to_alloc)
Definition: MemoryPool.cpp:438
void insert_free_alloc(FreeHeader *block_freed)
Definition: MemoryPool.cpp:465
bool includes(void *ptr) const
Definition: MemoryPool.h:169
bool joinable_prev(FreeHeader *freed)
Definition: MemoryPool.cpp:553
bool joinable_next(FreeHeader *freed)
Definition: MemoryPool.cpp:544

◆ joinable_next()

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().

545 {
546  AllocHeader* next_alloc = freed->next_adjacent();
547  return freed->is_free() &&
548  includes(next_alloc) &&
549  next_alloc->is_free();
550 }
bool includes(void *ptr) const
Definition: MemoryPool.h:169

◆ joinable_prev()

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

◆ lwm_free_bytes()

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_.

329 {
330  return lwm_free_bytes_;
331 }
size_t lwm_free_bytes_
Low water mark of available bytes.
Definition: MemoryPool.h:193

◆ pool_alloc()

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().

335 {
336 #if defined(WITH_VALGRIND)
337  VALGRIND_DISABLE_ADDR_ERROR_REPORTING_IN_RANGE(pool_ptr_, pool_size_);
338 #endif
339 
340  // Pointer to return
341  unsigned char* block = NULL;
342 
343  // Round up to 8-byte boundary
344  size_t aligned_size = align(size, granularity_);
345 
346  if (aligned_size < min_alloc_size_) {
347  aligned_size = min_alloc_size_;
348  }
349 
350  // The block to allocate from
351  FreeHeader* block_to_alloc = free_index_.find(aligned_size, pool_ptr_);
352 
353  if (block_to_alloc) {
354  block = allocate(block_to_alloc, aligned_size);
355  }
356 
357  // Update lwm
358  size_t largest_free_bytes = largest_free_ ? largest_free_->size() : 0;
359  if (largest_free_bytes < lwm_free_bytes_) {
360  lwm_free_bytes_ = largest_free_bytes;
361  }
362 
363 #ifdef VALIDATE_MEMORY_POOL
364  validate_pool(*this, false);
365 #endif
366 
367 #if defined(WITH_VALGRIND)
368  VALGRIND_ENABLE_ADDR_ERROR_REPORTING_IN_RANGE(pool_ptr_, pool_size_);
369  VALGRIND_MEMPOOL_ALLOC(pool_ptr_, block, size);
370 #endif
371 
372  return block;
373 }
FreeHeader * find(size_t size, unsigned char *base)
Definition: MemoryPool.cpp:209
const size_t min_alloc_size_
Aligned minimum allocation size.
Definition: MemoryPool.h:191
static size_t align(size_t size, size_t granularity)
Definition: MemoryPool.h:184
unsigned char * allocate(FreeHeader *free_block, size_t alloc_size)
Definition: MemoryPool.cpp:496
unsigned char * pool_ptr_
Pointer to pool.
Definition: MemoryPool.h:194
unsigned int size() const
Definition: MemoryPool.h:30
FreeHeader * largest_free_
Pointer to largest free index.
Definition: MemoryPool.h:196
FreeIndex free_index_
Index of free nodex.
Definition: MemoryPool.h:197
const size_t granularity_
Configured granularity.
Definition: MemoryPool.h:190
const size_t pool_size_
Configured pool size.
Definition: MemoryPool.h:192
size_t lwm_free_bytes_
Low water mark of available bytes.
Definition: MemoryPool.h:193

◆ pool_free()

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().

377 {
378  bool freed = false;
379  if (ptr && includes(ptr)) {
380 #if defined(WITH_VALGRIND)
381  VALGRIND_DISABLE_ADDR_ERROR_REPORTING_IN_RANGE(pool_ptr_, pool_size_);
382 #endif
383 
384  FreeHeader* header = reinterpret_cast<FreeHeader*>(
385  reinterpret_cast<AllocHeader*>(ptr) - 1);
386 
387  // Free header
388  header->set_free();
389 
390  join_free_allocs(header);
391 
392 #ifdef VALIDATE_MEMORY_POOL
393  validate_pool(*this, false);
394 #endif
395 
396  freed = true;
397 
398 #if defined(WITH_VALGRIND)
399  VALGRIND_DISABLE_ADDR_ERROR_REPORTING_IN_RANGE(pool_ptr_, pool_size_);
400  VALGRIND_MEMPOOL_FREE(pool_ptr_, ptr);
401 #endif
402  }
403 
404  return freed;
405 }
Christopher Diggins *renamed files *fixing compilation errors *adding Visual C project file *removed make Max Lybbert *removed references to missing and unused header
Definition: CHANGELOG.txt:8
bool includes(void *ptr) const
Definition: MemoryPool.h:169
void join_free_allocs(FreeHeader *block_freed)
Definition: MemoryPool.cpp:408
unsigned char * pool_ptr_
Pointer to pool.
Definition: MemoryPool.h:194
const size_t pool_size_
Configured pool size.
Definition: MemoryPool.h:192

◆ remove_free_alloc()

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().

439 {
440  FreeHeader* smaller = block_to_alloc->smaller_free(pool_ptr_);
441  FreeHeader* larger = block_to_alloc->larger_free(pool_ptr_);
442 
443  block_to_alloc->set_smaller_free(NULL, NULL);
444  block_to_alloc->set_larger_free(NULL, NULL);
445 
446  // If this was the largest free alloc
447  if (block_to_alloc == largest_free_) {
448  // It no longer is
449  largest_free_ = smaller;
450  }
451 
452  if (larger) {
453  larger->set_smaller_free(smaller, pool_ptr_);
454  }
455 
456  if (smaller) {
457  smaller->set_larger_free(larger, pool_ptr_);
458  }
459 
460  // Remove from free index
461  free_index_.remove(block_to_alloc, larger);
462 }
void set_smaller_free(FreeHeader *next, unsigned char *pool_base)
Definition: MemoryPool.cpp:128
void remove(FreeHeader *free_block, FreeHeader *next_largest)
Definition: MemoryPool.cpp:181
unsigned char * pool_ptr_
Pointer to pool.
Definition: MemoryPool.h:194
FreeHeader * largest_free_
Pointer to largest free index.
Definition: MemoryPool.h:196
FreeIndex free_index_
Index of free nodex.
Definition: MemoryPool.h:197

◆ size()

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

Definition at line 187 of file MemoryPool.h.

187 { return pool_size_; }
const size_t pool_size_
Configured pool size.
Definition: MemoryPool.h:192

Friends And Related Function Documentation

◆ Test::MemoryPoolTest

friend class Test::MemoryPoolTest
friend

Definition at line 163 of file MemoryPool.h.

Member Data Documentation

◆ free_index_

FreeIndex OpenDDS::DCPS::MemoryPool::free_index_
private

Index of free nodex.

Definition at line 197 of file MemoryPool.h.

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

◆ granularity_

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

Configured granularity.

Definition at line 190 of file MemoryPool.h.

Referenced by pool_alloc().

◆ largest_free_

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

Pointer to largest free index.

Definition at line 196 of file MemoryPool.h.

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

◆ lwm_free_bytes_

size_t OpenDDS::DCPS::MemoryPool::lwm_free_bytes_
private

Low water mark of available bytes.

Definition at line 193 of file MemoryPool.h.

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

◆ min_alloc_size_

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

Aligned minimum allocation size.

Definition at line 191 of file MemoryPool.h.

Referenced by pool_alloc().

◆ pool_ptr_

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

Pointer to pool.

Definition at line 194 of file MemoryPool.h.

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

◆ pool_size_

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

Configured pool size.

Definition at line 192 of file MemoryPool.h.

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


The documentation for this class was generated from the following files: