⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 memory_algorithm_test_template.hpp

📁 Boost provides free peer-reviewed portable C++ source libraries. We emphasize libraries that work
💻 HPP
📖 第 1 页 / 共 2 页
字号:
////////////////////////////////////////////////////////////////////////////////// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost// Software License, Version 1.0. (See accompanying file// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)//// See http://www.boost.org/libs/interprocess for documentation.////////////////////////////////////////////////////////////////////////////////#ifndef BOOST_INTERPROCESS_TEST_MEMORY_ALGORITHM_TEST_TEMPLATE_HEADER#define BOOST_INTERPROCESS_TEST_MEMORY_ALGORITHM_TEST_TEMPLATE_HEADER#include <boost/interprocess/detail/config_begin.hpp>#include <vector>#include <iostream>#include <new>#include <utility>#include <cstring>   //std::memset#include <cstdio>    //std::removenamespace boost { namespace interprocess { namespace test {enum deallocation_type { DirectDeallocation, InverseDeallocation, MixedDeallocation, EndDeallocationType };//This test allocates until there is no more memory//and after that deallocates all in the inverse ordertemplate<class Allocator>bool test_allocation(Allocator &a){   for( deallocation_type t = DirectDeallocation      ; t != EndDeallocationType      ; t = (deallocation_type)((int)t + 1)){      std::vector<void*> buffers;      std::size_t free_memory = a.get_free_memory();      for(int i = 0; true; ++i){         void *ptr = a.allocate(i, std::nothrow);         if(!ptr)            break;         std::size_t size = a.size(ptr);         std::memset(ptr, 0, size);         buffers.push_back(ptr);      }      switch(t){         case DirectDeallocation:         {            for(int j = 0, max = (int)buffers.size()               ;j < max               ;++j){               a.deallocate(buffers[j]);            }         }         break;         case InverseDeallocation:         {            for(int j = (int)buffers.size()               ;j--               ;){               a.deallocate(buffers[j]);            }         }         break;         case MixedDeallocation:         {            for(int j = 0, max = (int)buffers.size()               ;j < max               ;++j){               int pos = (j%4)*((int)buffers.size())/4;               a.deallocate(buffers[pos]);               buffers.erase(buffers.begin()+pos);            }         }         break;         default:         break;      }      bool ok = free_memory == a.get_free_memory() &&                a.all_memory_deallocated() && a.check_sanity();      if(!ok)  return ok;   }   return true;}//This test allocates until there is no more memory//and after that tries to shrink all the buffers to the//half of the original sizetemplate<class Allocator>bool test_allocation_shrink(Allocator &a){   std::vector<void*> buffers;   //Allocate buffers with extra memory   for(int i = 0; true; ++i){      void *ptr = a.allocate(i*2, std::nothrow);      if(!ptr)         break;      std::size_t size = a.size(ptr);      std::memset(ptr, 0, size);      buffers.push_back(ptr);   }   //Now shrink to half   for(int i = 0, max = (int)buffers.size()      ;i < max      ; ++i){      std::size_t received_size;      if(a.template allocation_command<char>         ( shrink_in_place | nothrow_allocation, i*2         , i, received_size, static_cast<char*>(buffers[i])).first){         if(received_size > std::size_t(i*2)){            return false;         }         if(received_size < std::size_t(i)){            return false;         }         std::memset(buffers[i], 0, a.size(buffers[i]));      }   }      //Deallocate it in non sequential order   for(int j = 0, max = (int)buffers.size()      ;j < max      ;++j){      int pos = (j%4)*((int)buffers.size())/4;      a.deallocate(buffers[pos]);      buffers.erase(buffers.begin()+pos);   }   return a.all_memory_deallocated() && a.check_sanity();}//This test allocates until there is no more memory//and after that tries to expand all the buffers to//avoid the wasted internal fragmentationtemplate<class Allocator>bool test_allocation_expand(Allocator &a){   std::vector<void*> buffers;   //Allocate buffers with extra memory   for(int i = 0; true; ++i){      void *ptr = a.allocate(i, std::nothrow);      if(!ptr)         break;      std::size_t size = a.size(ptr);      std::memset(ptr, 0, size);      buffers.push_back(ptr);   }   //Now try to expand to the double of the size   for(int i = 0, max = (int)buffers.size()      ;i < max      ;++i){      std::size_t received_size;      std::size_t min_size = i+1;      std::size_t preferred_size = i*2;      preferred_size = min_size > preferred_size ? min_size : preferred_size;      while(a.template allocation_command<char>         ( expand_fwd | nothrow_allocation, min_size         , preferred_size, received_size, static_cast<char*>(buffers[i])).first){         //Check received size is bigger than minimum         if(received_size < min_size){            return false;         }         //Now, try to expand further         min_size       = received_size+1;         preferred_size = min_size*2;      }   }      //Deallocate it in non sequential order   for(int j = 0, max = (int)buffers.size()      ;j < max      ;++j){      int pos = (j%4)*((int)buffers.size())/4;      a.deallocate(buffers[pos]);      buffers.erase(buffers.begin()+pos);   }   return a.all_memory_deallocated() && a.check_sanity();}//This test allocates until there is no more memory//and after that tries to expand all the buffers to//avoid the wasted internal fragmentationtemplate<class Allocator>bool test_allocation_shrink_and_expand(Allocator &a){   std::vector<void*> buffers;   std::vector<std::size_t> received_sizes;   std::vector<bool>        size_reduced;   //Allocate buffers wand store received sizes   for(int i = 0; true; ++i){      std::size_t received_size;      void *ptr = a.template allocation_command<char>         ( allocate_new | nothrow_allocation, i, i*2, received_size).first;      if(!ptr){         ptr = a.template allocation_command<char>            ( allocate_new | nothrow_allocation, 1, i*2, received_size).first;         if(!ptr)            break;      }      buffers.push_back(ptr);      received_sizes.push_back(received_size);   }   //Now shrink to half   for(int i = 0, max = (int)buffers.size()      ; i < max      ; ++i){      std::size_t received_size;      if(a.template allocation_command<char>         ( shrink_in_place | nothrow_allocation, received_sizes[i]         , i, received_size, static_cast<char*>(buffers[i])).first){         if(received_size > std::size_t(received_sizes[i])){            return false;         }         if(received_size < std::size_t(i)){            return false;         }         size_reduced.push_back(received_size != received_sizes[i]);      }   }   //Now try to expand to the original size   for(int i = 0, max = (int)buffers.size()      ;i < max      ;++i){      std::size_t received_size;      std::size_t request_size = received_sizes[i];      if(a.template allocation_command<char>         ( expand_fwd | nothrow_allocation, request_size         , request_size, received_size, static_cast<char*>(buffers[i])).first){         if(received_size != received_sizes[i]){            return false;         }      }      else{         return false;      }   }      //Deallocate it in non sequential order   for(int j = 0, max = (int)buffers.size()      ;j < max      ;++j){      int pos = (j%4)*((int)buffers.size())/4;      a.deallocate(buffers[pos]);      buffers.erase(buffers.begin()+pos);   }   return a.all_memory_deallocated() && a.check_sanity();}//This test allocates until there is no more memory//and after that deallocates the odd buffers to//make room for expansions. The expansion will probably//success since the deallocation left room for that.template<class Allocator>bool test_allocation_deallocation_expand(Allocator &a){   std::vector<void*> buffers;   //Allocate buffers with extra memory   for(int i = 0; true; ++i){      void *ptr = a.allocate(i, std::nothrow);      if(!ptr)         break;      std::size_t size = a.size(ptr);      std::memset(ptr, 0, size);      buffers.push_back(ptr);   }   //Now deallocate the half of the blocks   //so expand maybe can merge new free blocks   for(int i = 0, max = (int)buffers.size()      ;i < max      ;++i){      if(i%2){         a.deallocate(buffers[i]);         buffers[i] = 0;      }   }   //Now try to expand to the double of the size   for(int i = 0, max = (int)buffers.size()      ;i < max      ;++i){      //      if(buffers[i]){         std::size_t received_size;         std::size_t min_size = i+1;         std::size_t preferred_size = i*2;         preferred_size = min_size > preferred_size ? min_size : preferred_size;         while(a.template allocation_command<char>            ( expand_fwd | nothrow_allocation, min_size            , preferred_size, received_size, static_cast<char*>(buffers[i])).first){            //Check received size is bigger than minimum            if(received_size < min_size){               return false;            }            //Now, try to expand further            min_size       = received_size+1;            preferred_size = min_size*2;         }      }   }      //Now erase null values from the vector   buffers.erase( std::remove(buffers.begin(), buffers.end(), static_cast<void*>(0))                , buffers.end());   //Deallocate it in non sequential order   for(int j = 0, max = (int)buffers.size()      ;j < max      ;++j){      int pos = (j%4)*((int)buffers.size())/4;      a.deallocate(buffers[pos]);      buffers.erase(buffers.begin()+pos);   }   return a.all_memory_deallocated() && a.check_sanity();}//This test allocates until there is no more memory//and after that deallocates all except the last.//If the allocation algorithm is a bottom-up algorithm//the last buffer will be in the end of the segment.//Then the test will start expanding backwards, until//the buffer fills all the memorytemplate<class Allocator>bool test_allocation_with_reuse(Allocator &a){   //We will repeat this test for different sized elements   for(int sizeof_object = 1; sizeof_object < 20; ++sizeof_object){      std::vector<void*> buffers;      //Allocate buffers with extra memory      for(int i = 0; true; ++i){         void *ptr = a.allocate(i*sizeof_object, std::nothrow);         if(!ptr)            break;         std::size_t size = a.size(ptr);         std::memset(ptr, 0, size);         buffers.push_back(ptr);      }            //Now deallocate all except the latest      //Now try to expand to the double of the sizeof_object      for(int i = 0, max = (int)buffers.size() - 1         ;i < max         ;++i){         a.deallocate(buffers[i]);      }      //Save the unique buffer and clear vector      void *ptr = buffers.back();      buffers.clear();      //Now allocate with reuse      std::size_t received_size = 0;      for(int i = 0; true; ++i){         std::size_t min_size = (received_size + 1);         std::size_t prf_size = (received_size + (i+1)*2);         std::pair<void*, bool> ret = a.raw_allocation_command            ( expand_bwd | nothrow_allocation, min_size            , prf_size, received_size, static_cast<char*>(ptr), sizeof_object);         if(!ret.first)            break;         //If we have memory, this must be a buffer reuse         if(!ret.second)            return 1;         if(received_size < min_size)            return 1;         ptr = ret.first;      }      //There is only a single block so deallocate it      a.deallocate(ptr);            if(!a.all_memory_deallocated() || !a.check_sanity())         return false;   }   return true;}//This test allocates memory with different alignments//and checks returned memory is aligned.template<class Allocator>bool test_aligned_allocation(Allocator &a){   //Allocate aligned buffers in a loop   //and then deallocate it   bool continue_loop = true;   for(unsigned int i = 1; continue_loop; i <<= 1){      for(unsigned int j = 1; true; j <<= 1){         void *ptr = a.allocate_aligned(i-1, j, std::nothrow);         if(!ptr){            if(j == 1)               continue_loop = false;            break;         }                  if(((std::size_t)ptr & (j - 1)) != 0)            return false;         a.deallocate(ptr);         if(!a.all_memory_deallocated() || !a.check_sanity()){            return false;         }      }   }   return a.all_memory_deallocated() && a.check_sanity();}//This test allocates memory with different alignments//and checks returned memory is aligned.template<class Allocator>bool test_continuous_aligned_allocation(Allocator &a){   std::vector<void*> buffers;   //Allocate aligned buffers in a loop   //and then deallocate it   bool continue_loop = true;   for(unsigned i = 1; continue_loop && i; i <<= 1){      for(unsigned int j = 1; j; j <<= 1){         for(bool any_allocated = false; 1;){            void *ptr = a.allocate_aligned(i-1, j, std::nothrow);            buffers.push_back(ptr);            if(!ptr){               if(j == 1 && !any_allocated){                  continue_loop = false;               }               break;            }            else{               any_allocated = true;            }                        if(((std::size_t)ptr & (j - 1)) != 0)               return false;         }         //Deallocate all         for(unsigned int k = (int)buffers.size(); k--;){            a.deallocate(buffers[k]);         }         buffers.clear();         if(!a.all_memory_deallocated() && a.check_sanity())            return false;         if(!continue_loop)            break;      }   }   return a.all_memory_deallocated() && a.check_sanity();}//This test allocates memory, writes it with a non-zero value and//tests zero_free_memory initializes to zero for the next allocationtemplate<class Allocator>bool test_clear_free_memory(Allocator &a){   std::vector<void*> buffers;   //Allocate memory   for(int i = 0; true; ++i){      void *ptr = a.allocate(i, std::nothrow);      if(!ptr)         break;      std::size_t size = a.size(ptr);      std::memset(ptr, 1, size);      buffers.push_back(ptr);   }   //Mark it   for(int i = 0, max = buffers.size(); i < max; ++i){      std::memset(buffers[i], 1, i);   }   //Deallocate all   for(int j = (int)buffers.size()      ;j--      ;){      a.deallocate(buffers[j]);   }   buffers.clear();   if(!a.all_memory_deallocated() && a.check_sanity())      return false;   //Now clear all free memory   a.zero_free_memory();   if(!a.all_memory_deallocated() && a.check_sanity())      return false;   //Now test all allocated memory is zero   //Allocate memory   for(int i = 0; true; ++i){      void *ptr = a.allocate(i, std::nothrow);      if(!ptr)         break;      buffers.push_back(ptr);   }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -