MemoryPool.cpp

Go to the documentation of this file.
00001 /*
00002  *
00003  *
00004  * Distributed under the OpenDDS License.
00005  * See: http://www.opendds.org/license.html
00006  */
00007 
00008 #include "DCPS/DdsDcps_pch.h"  ////Only the _pch include should start with DCPS/
00009 #include "MemoryPool.h"
00010 #include "PoolAllocator.h"
00011 #include "ace/Log_Msg.h"
00012 #include "ace/OS_NS_stdio.h"
00013 #include <stdexcept>
00014 #include <limits>
00015 #include <map>
00016 #include <cstring>
00017 
00018 #if defined(WITH_VALGRIND)
00019 #include "valgrind/memcheck.h"
00020 #endif
00021 
00022 #define TEST_CHECK(COND) \
00023   if (!( COND )) { \
00024     char msg[1024]; \
00025     ACE_OS::snprintf(msg, 1024, "%s: FAILED at %s:%d", #COND, __FILE__, __LINE__); \
00026     ACE_OS::printf("%s\n", msg); \
00027     throw std::runtime_error(msg); \
00028     return; \
00029   }
00030 
00031 OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL
00032 
00033 namespace OpenDDS {  namespace DCPS {
00034 
00035 AllocHeader::AllocHeader()
00036 : alloc_size_(0)
00037 , prev_size_(0)
00038 {
00039 }
00040 
00041 unsigned char*
00042 AllocHeader::ptr() const
00043 {
00044   const unsigned char* buff = reinterpret_cast<const unsigned char*>(this + 1);
00045   return const_cast<unsigned char*>(buff);
00046 }
00047 
00048 AllocHeader*
00049 AllocHeader::next_adjacent() {
00050   unsigned char* past_buffer_end = ptr() + size();
00051   return reinterpret_cast<AllocHeader*>(past_buffer_end);
00052 }
00053 
00054 AllocHeader*
00055 AllocHeader::prev_adjacent() {
00056   AllocHeader* result = NULL;
00057   if (prev_size_) {
00058     unsigned char* self = reinterpret_cast<unsigned char*>(this);
00059     unsigned char* prev_buffer_start = self - prev_size_;
00060     unsigned char* past_alloc = prev_buffer_start - sizeof(AllocHeader);
00061     result = reinterpret_cast<AllocHeader*>(past_alloc);
00062   }
00063   return result;
00064 }
00065 
00066 void
00067 AllocHeader::allocate(size_t size) {
00068   set_allocated();
00069   set_size(size);
00070 }
00071 
00072 void
00073 AllocHeader::set_size(size_t size)
00074 {
00075   if (is_free()) {
00076     size *= -1;
00077   }
00078   alloc_size_ = (int)size;
00079 }
00080 
00081 void
00082 AllocHeader::join_next() {
00083   // All unsigned, set_size will make negative if free (it is)
00084   size_t next_size = this->next_adjacent()->size();
00085   size_t joined_size = this->size() + next_size + sizeof(AllocHeader);
00086   this->set_size(joined_size);
00087 }
00088 
00089 void
00090 FreeHeader::init_free_block(unsigned int pool_size)
00091 {
00092   alloc_size_ = static_cast<int>(pool_size - sizeof(AllocHeader));
00093   prev_size_ = 0;
00094   set_free();
00095 }
00096 
00097 void
00098 FreeHeader::set_free()
00099 {
00100   // If this is newly freed
00101   if (!is_free()) {
00102     alloc_size_ *= -1;
00103     set_smaller_free(NULL, NULL);
00104     set_larger_free(NULL, NULL);
00105   }
00106 }
00107 FreeHeader*
00108 FreeHeader::smaller_free(unsigned char* pool_base) const
00109 {
00110   FreeHeader* result = NULL;
00111   if (offset_smaller_free_ != std::numeric_limits<size_t>::max()) {
00112     result = reinterpret_cast<FreeHeader*>(pool_base + offset_smaller_free_);
00113   }
00114   return result;
00115 }
00116 
00117 FreeHeader*
00118 FreeHeader::larger_free(unsigned char* pool_base) const
00119 {
00120   FreeHeader* result = NULL;
00121   if (offset_larger_free_ != std::numeric_limits<size_t>::max()) {
00122     result = reinterpret_cast<FreeHeader*>(pool_base + offset_larger_free_);
00123   }
00124   return result;
00125 }
00126 
00127 void
00128 FreeHeader::set_smaller_free(FreeHeader* next, unsigned char* pool_base)
00129 {
00130   if (next) {
00131     offset_smaller_free_ = reinterpret_cast<unsigned char*>(next) - pool_base;
00132   } else {
00133     offset_smaller_free_ = std::numeric_limits<size_t>::max();
00134   }
00135 }
00136 
00137 void
00138 FreeHeader::set_larger_free(FreeHeader* prev, unsigned char* pool_base)
00139 {
00140   if (prev) {
00141     offset_larger_free_ = reinterpret_cast<unsigned char*>(prev) - pool_base;
00142   } else {
00143     offset_larger_free_ = std::numeric_limits<size_t>::max();
00144   }
00145 }
00146 
00147 FreeIndexNode::FreeIndexNode()
00148 : size_(0)
00149 , limit_(0)
00150 , ptr_(0)
00151 {
00152 }
00153 
00154 void
00155 FreeIndexNode::set_sizes(size_t size, size_t limit)
00156 {
00157   size_ = size;
00158   limit_ = limit;
00159 }
00160 
00161 FreeIndex::FreeIndex(FreeHeader*& largest_free)
00162 : size_(0)
00163 , largest_free_(largest_free)
00164 {
00165 }
00166 
00167 void
00168 FreeIndex::add(FreeHeader* freed)
00169 {
00170   unsigned int index = node_index(freed->size());
00171   FreeIndexNode* node = nodes_ + index;
00172 
00173   // If the node is empty, or if freed is smaller or equal to the node's alloc
00174   if ((node->ptr() == NULL) || (node->ptr()->size() >= freed->size())) {
00175     // Use this alloc in the index
00176     node->set_ptr(freed);
00177   }
00178 }
00179 
00180 void
00181 FreeIndex::remove(FreeHeader* free_block, FreeHeader* larger)
00182 {
00183   unsigned int index = node_index(free_block->size());
00184   FreeIndexNode* node = nodes_ + index;
00185 
00186   // If the node points to the free block
00187   if (node->ptr() == free_block) {
00188     // If the larger can be used by this node
00189     if (larger && node->contains(larger->size())) {
00190       node->set_ptr(larger);
00191     } else {
00192       node->set_ptr(NULL);
00193     }
00194   }
00195 }
00196 
00197 void
00198 FreeIndex::init(FreeHeader* init_free_block)
00199 {
00200   size_t max = std::numeric_limits<size_t>::max();
00201   for (size_t size = min_index; size <= max_index; size *= 2) {
00202     nodes_[size_].set_sizes(size, (size == max_index) ? max  :  size*2);
00203     ++size_;
00204   }
00205   add(init_free_block);
00206 }
00207 
00208 FreeHeader*
00209 FreeIndex::find(size_t search_size, unsigned char* pool_base)
00210 {
00211   unsigned int index = node_index(search_size);
00212   FreeIndexNode* index_node = nodes_ + index;
00213 
00214   // Larger or equal to search_size
00215   FreeHeader* result = NULL;
00216   if (largest_free_ && (largest_free_->size() >= search_size)) {
00217     result = largest_free_;
00218 
00219     // Look from here and larger
00220     while (index_node < nodes_ + size_) {
00221       if (index_node->ptr() && index_node->ptr()->size() >= search_size) {
00222         result = index_node->ptr();
00223         break;
00224       }
00225       ++index_node;
00226     }
00227   }
00228 
00229   // Now traverse, searching for smaller than result
00230   while (result) {
00231     FreeHeader* smaller = result->smaller_free(pool_base);
00232     if (smaller && smaller->size() >= search_size) {
00233       result = smaller;
00234     } else {
00235       break;
00236     }
00237   }
00238 
00239   return result;
00240 }
00241 
00242 unsigned int
00243 FreeIndex::node_index(size_t size)
00244 {
00245   // Use shifting to perform log base 2 of size
00246   //   start by using min + 1 (+1 because min is a power of 2 whch is already
00247   //   one bit)
00248   size_t size_copy = size >> (min_index_pow + 1);
00249   unsigned int index = 0;
00250   unsigned int max_idx = max_index_pow - min_index_pow;
00251   while (size_copy && (index < max_idx)) {
00252     ++index;
00253     size_copy = size_copy >> 1;
00254   }
00255   return index;
00256 }
00257 
00258 #ifdef VALIDATE_MEMORY_POOL
00259 void
00260 FreeIndex::validate_index(FreeIndex& index, unsigned char* base, bool log)
00261 {
00262   if (log) {
00263     FreeIndexNode* node = index.nodes_;
00264     while (node < index.nodes_ + index.size_) {
00265       if (node->ptr()) {
00266         ACE_OS::printf("  IND[%4d] -> %4d\n", node->size(), node->ptr()->size());
00267       } else {
00268         ACE_OS::printf("  IND[%4d] -> NULL\n", node->size());
00269       }
00270       ++node;
00271     }
00272   }
00273 
00274   // Validate searches of each size
00275   for (size_t size = min_index; size <= max_index; size *= 2) {
00276     // Find size or larger
00277     FreeHeader* size_or_larger = index.find(size, base);
00278     if (size_or_larger) {
00279       TEST_CHECK(size_or_larger->size() >= size);
00280     }
00281   }
00282 
00283   // Validate each node points to a free block of the proper size;
00284   for (FreeIndexNode* node = index.nodes_; node < index.nodes_ + index.size_; ++node) {
00285     FreeHeader* block = node->ptr();
00286     if (block) {
00287       // node should point to a free block of the proper size;
00288       TEST_CHECK(node->contains(block->size()));
00289 
00290       FreeHeader* smaller = block;
00291       while ((smaller = smaller->smaller_free(base))) {
00292         // Anything smaller should be too small for this node
00293         TEST_CHECK(smaller->size() < node->size());
00294       }
00295     }
00296   }
00297 }
00298 #endif
00299 
00300 MemoryPool::MemoryPool(unsigned int pool_size, size_t granularity)
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 }
00319 
00320 MemoryPool::~MemoryPool()
00321 {
00322 #ifndef OPENDDS_SAFETY_PROFILE
00323   delete [] pool_ptr_;
00324 #endif
00325 }
00326 
00327 size_t
00328 MemoryPool::lwm_free_bytes() const
00329 {
00330   return lwm_free_bytes_;
00331 }
00332 
00333 void*
00334 MemoryPool::pool_alloc(size_t 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 }
00374 
00375 bool
00376 MemoryPool::pool_free(void* ptr)
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 }
00406 
00407 void
00408 MemoryPool::join_free_allocs(FreeHeader* freed)
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 }
00436 
00437 void
00438 MemoryPool::remove_free_alloc(FreeHeader* block_to_alloc)
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 }
00463 
00464 void
00465 MemoryPool::insert_free_alloc(FreeHeader* freed)
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 }
00494 
00495 unsigned char*
00496 MemoryPool::allocate(FreeHeader* free_block, size_t alloc_size)
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 }
00542 
00543 bool
00544 MemoryPool::joinable_next(FreeHeader* freed)
00545 {
00546   AllocHeader* next_alloc = freed->next_adjacent();
00547   return freed->is_free() &&
00548          includes(next_alloc) &&
00549          next_alloc->is_free();
00550 }
00551 
00552 bool
00553 MemoryPool::joinable_prev(FreeHeader* freed)
00554 {
00555   AllocHeader* prev_alloc = freed->prev_adjacent();
00556   return freed->is_free() &&
00557          includes(prev_alloc) &&
00558          prev_alloc->is_free();
00559 }
00560 
00561 #ifdef VALIDATE_MEMORY_POOL
00562 void
00563 MemoryPool::validate_pool(MemoryPool& pool, bool log) {
00564   AllocHeader* prev = 0;
00565   size_t allocated_bytes = 0;
00566   size_t free_bytes = 0;
00567   size_t oh_bytes = 0;
00568   size_t free_count = 0;
00569   unsigned char* pool_end = pool.pool_ptr_ + pool.pool_size_;
00570   bool prev_was_free;
00571   size_t index = 0;
00572 
00573   typedef std::map<FreeHeader*, int> FreeMap;
00574   FreeMap free_map;
00575   // Gather all free indices
00576   AllocHeader* alloc = reinterpret_cast<AllocHeader*>(pool.pool_ptr_);
00577   while (pool.includes(alloc)) {
00578     FreeHeader* free_header = alloc->is_free() ?
00579           reinterpret_cast<FreeHeader*>(alloc) : NULL;
00580     if (free_header) {
00581       free_map[free_header] = index;
00582     }
00583     alloc = alloc->next_adjacent();
00584     ++index;
00585   }
00586 
00587   index = 0;
00588   if (log) {
00589     ACE_OS::printf("Pool ptr %zx end %zx\n", (unsigned long)pool.pool_ptr_,
00590            (unsigned long)pool_end);
00591    }
00592 
00593   // Check all allocs in positional order and not overlapping
00594   alloc = reinterpret_cast<AllocHeader*>(pool.pool_ptr_);
00595   while (pool.includes(alloc)) {
00596     if (log) {
00597 
00598       int smlr_index = -1;
00599       int lrgr_index = -1;
00600       char lrgr_buff[32];
00601       char smlr_buff[32];
00602 
00603       FreeHeader* free_header = alloc->is_free() ?
00604             reinterpret_cast<FreeHeader*>(alloc) : NULL;
00605       if (free_header) {
00606         FreeMap::const_iterator found;
00607         found = free_map.find(free_header->smaller_free(pool.pool_ptr_));
00608         if (found != free_map.end()) {
00609           smlr_index = found->second;
00610           snprintf(smlr_buff, 32, "[%2d]", smlr_index); // preprocessed out
00611         }
00612         found = free_map.find(free_header->larger_free(pool.pool_ptr_));
00613         if (found != free_map.end()) {
00614           lrgr_index = found->second;
00615           snprintf(lrgr_buff, 32, "[%2d]", lrgr_index); // preprocessed out
00616         }
00617       }
00618       ACE_OS::printf(
00619         "Alloc[%zu] %s at %zx ptr %zx lg %s sm %s size %d psize %d\n",
00620         index++,
00621         alloc->is_free() ?
00622         (alloc == pool.largest_free_ ? "FREE!" : "free ")  : "     ",
00623         (unsigned long)alloc,
00624         (unsigned long)alloc->ptr(),
00625         lrgr_index >= 0 ? lrgr_buff : "[  ]",
00626         smlr_index >= 0 ? smlr_buff : "[  ]",
00627         alloc->size(),
00628         alloc->prev_size()
00629       );
00630     }
00631 
00632     TEST_CHECK(alloc->size());
00633     if (prev) {
00634       TEST_CHECK(prev->next_adjacent() == alloc);
00635       TEST_CHECK(alloc->prev_adjacent() == prev);
00636       // Validate  these are not consecutive free blocks
00637       TEST_CHECK(!(prev_was_free && alloc->is_free()));
00638     }
00639 
00640     if (!alloc->is_free()) {
00641       allocated_bytes += alloc->size();
00642       prev_was_free = false;
00643     } else {
00644       free_bytes += alloc->size();
00645       prev_was_free = true;
00646     }
00647     oh_bytes += sizeof(AllocHeader);
00648     prev = alloc;
00649     alloc = alloc->next_adjacent();
00650   }
00651   TEST_CHECK((unsigned char*)alloc == pool_end);
00652 
00653   TEST_CHECK(allocated_bytes + free_bytes + oh_bytes == pool.pool_size_);
00654 
00655   FreeIndex::validate_index(pool.free_index_, pool.pool_ptr_, log);
00656 
00657   size_t prev_size = 0;
00658   size_t free_bytes_in_list = 0;
00659   FreeHeader* free_alloc = NULL;
00660   FreeHeader* prev_free = NULL;
00661 
00662   // Check all free blocks in size order
00663   for (free_alloc = pool.largest_free_;
00664        free_alloc;
00665        free_alloc = free_alloc->smaller_free(pool.pool_ptr_)) {
00666     // Should be marked free
00667     TEST_CHECK(free_alloc->is_free());
00668     // Check for infinite loop
00669     TEST_CHECK(++free_count < 10000);
00670 
00671     // Sum bytes found
00672     free_bytes_in_list += free_alloc->size();
00673 
00674     // If not the first alloc
00675     if (prev_size) {
00676       TEST_CHECK(free_alloc->size() <= prev_size);
00677       TEST_CHECK(free_alloc->size() > 0);
00678     }
00679     prev_size = free_alloc->size();
00680     prev_free = free_alloc;
00681   }
00682 
00683   TEST_CHECK(free_bytes == free_bytes_in_list);
00684 
00685   // Try again from smallest to largest
00686   if (prev_free) {
00687     free_bytes_in_list = 0;
00688 
00689     for (free_alloc = prev_free;
00690          free_alloc;
00691          free_alloc = free_alloc->larger_free(pool.pool_ptr_)) {
00692       // Should be marked free
00693       TEST_CHECK(free_alloc->is_free());
00694 
00695       // Sum bytes found
00696       free_bytes_in_list += free_alloc->size();
00697 
00698       // If not the first alloc
00699       if (free_alloc != prev_free) {
00700         TEST_CHECK(free_alloc->size() >= prev_size);
00701         TEST_CHECK(free_alloc->size() > 0);
00702       }
00703       prev_size = free_alloc->size();
00704     }
00705     TEST_CHECK(free_bytes == free_bytes_in_list);
00706   }
00707 }
00708 #endif
00709 
00710 }}
00711 
00712 OPENDDS_END_VERSIONED_NAMESPACE_DECL
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 10 Aug 2018 for OpenDDS by  doxygen 1.6.1