#include <MemoryPool.h>
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. | |
FreeHeader * | largest_free_ |
Pointer to largest free index. | |
FreeIndex | free_index_ |
Index of free nodex. | |
Friends | |
class | ::MemoryPoolTest |
Definition at line 161 of file MemoryPool.h.
anonymous enum [private] |
Definition at line 198 of file MemoryPool.h.
00198 { 00199 min_free_size = sizeof(FreeHeader) 00200 };
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 }
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 }
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; }
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 }
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_); }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
size_t OpenDDS::DCPS::MemoryPool::size | ( | void | ) | const [inline] |
Definition at line 186 of file MemoryPool.h.
00186 { return pool_size_; }
friend class ::MemoryPoolTest [friend] |
Definition at line 162 of file MemoryPool.h.
Index of free nodex.
Definition at line 196 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 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().
const size_t OpenDDS::DCPS::MemoryPool::min_alloc_size_ [private] |
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().
const size_t OpenDDS::DCPS::MemoryPool::pool_size_ [private] |
Configured pool size.
Definition at line 191 of file MemoryPool.h.
Referenced by MemoryPool(), pool_alloc(), and pool_free().