#include <MemoryPool.h>
Collaboration diagram for OpenDDS::DCPS::MemoryPool:
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. | |
FreeHeader * | largest_free_ |
Pointer to largest free index. | |
FreeIndex | free_index_ |
Index of free nodex. | |
Friends | |
class | ::MemoryPoolTest |
Definition at line 159 of file MemoryPool.h.
anonymous enum [private] |
Definition at line 196 of file MemoryPool.h.
00196 { 00197 min_free_size = sizeof(FreeHeader) 00198 };
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 }
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] |
friend class ::MemoryPoolTest [friend] |
Definition at line 160 of file MemoryPool.h.
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] |
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().