simple_seq_fit_impl.hpp

来自「Boost provides free peer-reviewed portab」· HPP 代码 · 共 1,114 行 · 第 1/3 页

HPP
1,114
字号
      last  = block;      block = detail::get_pointer(block->m_next);   }   char *last_free_end_address   = reinterpret_cast<char*>(last) + last->m_size*Alignment;   if(last_free_end_address != (reinterpret_cast<char*>(this) + priv_block_end_offset())){      //there is an allocated block in the end of this block      //so no shrinking is possible      return;   }   //Check if have only 1 big free block   void *unique_block = 0;   if(!m_header.m_allocated){      assert(prev == root);      std::size_t ignore;      unique_block = priv_allocate(allocate_new, 0, 0, ignore).first;      if(!unique_block)         return;      last = detail::get_pointer(m_header.m_root.m_next);      assert(last_free_end_address == (reinterpret_cast<char*>(last) + last->m_size*Alignment));   }   std::size_t last_units = last->m_size;   std::size_t received_size;   void *addr = priv_check_and_allocate(last_units, prev, last, received_size);   (void)addr;   assert(addr);   assert(received_size == last_units*Alignment - AllocatedCtrlBytes);      //Shrink it   m_header.m_size /= Alignment;   m_header.m_size -= last->m_size;   m_header.m_size *= Alignment;   m_header.m_allocated -= last->m_size*Alignment;   if(unique_block)      priv_deallocate(unique_block);}template<class MutexFamily, class VoidPointer>inline void simple_seq_fit_impl<MutexFamily, VoidPointer>::   priv_mark_new_allocated_block(block_ctrl *new_block){   new_block->m_next = 0;}template<class MutexFamily, class VoidPointer>inlinetypename simple_seq_fit_impl<MutexFamily, VoidPointer>::block_ctrl *   simple_seq_fit_impl<MutexFamily, VoidPointer>::priv_get_block(const void *ptr){   return const_cast<block_ctrl*>(reinterpret_cast<const block_ctrl*>      (reinterpret_cast<const char*>(ptr) - AllocatedCtrlBytes));}template<class MutexFamily, class VoidPointer>inlinevoid *simple_seq_fit_impl<MutexFamily, VoidPointer>::      priv_get_user_buffer(const typename simple_seq_fit_impl<MutexFamily, VoidPointer>::block_ctrl *block){   return const_cast<char*>(reinterpret_cast<const char*>(block) + AllocatedCtrlBytes);}template<class MutexFamily, class VoidPointer>inline void simple_seq_fit_impl<MutexFamily, VoidPointer>::priv_add_segment(void *addr, std::size_t size){     algo_impl_t::assert_alignment(addr);   //Check size   assert(!(size < MinBlockSize));   if(size < MinBlockSize)      return;   //Construct big block using the new segment   block_ctrl *new_block   = static_cast<block_ctrl *>(addr);   new_block->m_size       = size/Alignment;   new_block->m_next       = 0;   //Simulate this block was previously allocated   m_header.m_allocated   += new_block->m_size*Alignment;    //Return block and insert it in the free block list   this->priv_deallocate(priv_get_user_buffer(new_block));}template<class MutexFamily, class VoidPointer>inline std::size_t simple_seq_fit_impl<MutexFamily, VoidPointer>::get_size()  const   {  return m_header.m_size;  }template<class MutexFamily, class VoidPointer>inline std::size_t simple_seq_fit_impl<MutexFamily, VoidPointer>::get_free_memory()  const{   return m_header.m_size - m_header.m_allocated -       algo_impl_t::multiple_of_units(sizeof(*this) + m_header.m_extra_hdr_bytes);}template<class MutexFamily, class VoidPointer>inline std::size_t simple_seq_fit_impl<MutexFamily, VoidPointer>::   get_min_size (std::size_t extra_hdr_bytes){   return detail::get_rounded_size(sizeof(simple_seq_fit_impl),Alignment) +          detail::get_rounded_size(extra_hdr_bytes,Alignment)          + MinBlockSize;}template<class MutexFamily, class VoidPointer>inline bool simple_seq_fit_impl<MutexFamily, VoidPointer>::    all_memory_deallocated(){   //-----------------------   boost::interprocess::scoped_lock<interprocess_mutex> guard(m_header);   //-----------------------   return m_header.m_allocated == 0 &&          detail::get_pointer(m_header.m_root.m_next->m_next) == &m_header.m_root;}template<class MutexFamily, class VoidPointer>inline void simple_seq_fit_impl<MutexFamily, VoidPointer>::zero_free_memory(){   //-----------------------   boost::interprocess::scoped_lock<interprocess_mutex> guard(m_header);   //-----------------------   block_ctrl *block = detail::get_pointer(m_header.m_root.m_next);   //Iterate through all free portions   do{      //Just clear user the memory part reserved for the user            std::memset( priv_get_user_buffer(block)                 , 0                 , block->get_user_bytes());      block = detail::get_pointer(block->m_next);   }   while(block != &m_header.m_root);}template<class MutexFamily, class VoidPointer>inline bool simple_seq_fit_impl<MutexFamily, VoidPointer>::    check_sanity(){   //-----------------------   boost::interprocess::scoped_lock<interprocess_mutex> guard(m_header);   //-----------------------   block_ctrl *block = detail::get_pointer(m_header.m_root.m_next);   std::size_t free_memory = 0;   //Iterate through all blocks obtaining their size   while(block != &m_header.m_root){      algo_impl_t::assert_alignment(block);      if(!algo_impl_t::check_alignment(block))         return false;      //Free blocks's next must be always valid      block_ctrl *next = detail::get_pointer(block->m_next);      if(!next){         return false;      }      free_memory += block->m_size*Alignment;      block = next;   }   //Check allocated bytes are less than size   if(m_header.m_allocated > m_header.m_size){      return false;   }   //Check free bytes are less than size   if(free_memory > m_header.m_size){      return false;   }   return true;}template<class MutexFamily, class VoidPointer>inline void* simple_seq_fit_impl<MutexFamily, VoidPointer>::   allocate(std::size_t nbytes){   //-----------------------   boost::interprocess::scoped_lock<interprocess_mutex> guard(m_header);   //-----------------------   std::size_t ignore;   return priv_allocate(allocate_new, nbytes, nbytes, ignore).first;}template<class MutexFamily, class VoidPointer>inline void* simple_seq_fit_impl<MutexFamily, VoidPointer>::   allocate_aligned(std::size_t nbytes, std::size_t alignment){     //-----------------------   boost::interprocess::scoped_lock<interprocess_mutex> guard(m_header);   //-----------------------   return algo_impl_t::      allocate_aligned(this, nbytes, alignment); }template<class MutexFamily, class VoidPointer>template<class T>inline std::pair<T*, bool> simple_seq_fit_impl<MutexFamily, VoidPointer>::   allocation_command  (allocation_type command,   std::size_t limit_size,                        std::size_t preferred_size,std::size_t &received_size,                         T *reuse_ptr){   std::pair<void*, bool> ret = priv_allocation_command      (command, limit_size, preferred_size, received_size, static_cast<void*>(reuse_ptr), sizeof(T));   BOOST_ASSERT(0 == ((std::size_t)ret.first % detail::alignment_of<T>::value));   return std::pair<T *, bool>(static_cast<T*>(ret.first), ret.second);}template<class MutexFamily, class VoidPointer>inline std::pair<void*, bool> simple_seq_fit_impl<MutexFamily, VoidPointer>::   raw_allocation_command  (allocation_type command,   std::size_t limit_objects,                        std::size_t preferred_objects,std::size_t &received_objects,                         void *reuse_ptr, std::size_t sizeof_object){   if(!sizeof_object)      return std::pair<void *, bool>(static_cast<void*>(0), 0);   if(command & try_shrink_in_place){      bool success = algo_impl_t::try_shrink         ( this, reuse_ptr, limit_objects*sizeof_object         , preferred_objects*sizeof_object, received_objects);      received_objects /= sizeof_object;      return std::pair<void *, bool> ((success ? reuse_ptr : 0), true);   }   return priv_allocation_command      (command, limit_objects, preferred_objects, received_objects, reuse_ptr, sizeof_object);}template<class MutexFamily, class VoidPointer>inline std::pair<void*, bool> simple_seq_fit_impl<MutexFamily, VoidPointer>::   priv_allocation_command (allocation_type command,   std::size_t limit_size,                       std::size_t preferred_size, std::size_t &received_size,                        void *reuse_ptr, std::size_t sizeof_object){   command &= ~expand_bwd;   if(!command)   return std::pair<void *, bool>(static_cast<void*>(0), false);   std::pair<void*, bool> ret;   std::size_t max_count = m_header.m_size/sizeof_object;   if(limit_size > max_count || preferred_size > max_count){      ret.first = 0; return ret;   }   std::size_t l_size = limit_size*sizeof_object;   std::size_t p_size = preferred_size*sizeof_object;   std::size_t r_size;   {      //-----------------------      boost::interprocess::scoped_lock<interprocess_mutex> guard(m_header);      //-----------------------      ret = priv_allocate(command, l_size, p_size, r_size, reuse_ptr);   }   received_size = r_size/sizeof_object;   return ret;}template<class MutexFamily, class VoidPointer>inline std::size_t simple_seq_fit_impl<MutexFamily, VoidPointer>::   size(const void *ptr) const{   //We need no synchronization since this block is not going   //to be modified   //Obtain the real size of the block   const block_ctrl *block = static_cast<const block_ctrl*>(priv_get_block(ptr));   return block->get_user_bytes();}template<class MutexFamily, class VoidPointer>void* simple_seq_fit_impl<MutexFamily, VoidPointer>::   priv_expand_both_sides(allocation_type command                         ,std::size_t min_size                         ,std::size_t preferred_size                         ,std::size_t &received_size                         ,void *reuse_ptr                         ,bool only_preferred_backwards){   typedef std::pair<block_ctrl *, block_ctrl *> prev_block_t;   block_ctrl *reuse = priv_get_block(reuse_ptr);   received_size = 0;   if(this->size(reuse_ptr) > min_size){      received_size = this->size(reuse_ptr);      return reuse_ptr;   }   if(command & expand_fwd){      if(priv_expand(reuse_ptr, min_size, preferred_size, received_size))         return reuse_ptr;   }   else{      received_size = this->size(reuse_ptr);   }   if(command & expand_bwd){      std::size_t extra_forward = !received_size ? 0 : received_size + BlockCtrlBytes;      prev_block_t prev_pair = priv_prev_block_if_free(reuse);      block_ctrl *prev = prev_pair.second;      if(!prev){         return 0;      }      std::size_t needs_backwards =          detail::get_rounded_size(preferred_size - extra_forward, Alignment);         if(!only_preferred_backwards){            max_value(detail::get_rounded_size(min_size - extra_forward, Alignment)                     ,min_value(prev->get_user_bytes(), needs_backwards));      }      //Check if previous block has enough size      if((prev->get_user_bytes()) >=  needs_backwards){         //Now take all next space. This will succeed         if(!priv_expand(reuse_ptr, received_size, received_size, received_size)){            assert(0);         }                  //We need a minimum size to split the previous one         if((prev->get_user_bytes() - needs_backwards) > 2*BlockCtrlBytes){             block_ctrl *new_block = reinterpret_cast<block_ctrl*>                  (reinterpret_cast<char*>(reuse) - needs_backwards - BlockCtrlBytes);            new_block->m_next = 0;            new_block->m_size =                BlockCtrlUnits + (needs_backwards + extra_forward)/Alignment;            prev->m_size =                (prev->get_total_bytes() - needs_backwards)/Alignment - BlockCtrlUnits;            received_size = needs_backwards + extra_forward;            m_header.m_allocated += needs_backwards + BlockCtrlBytes;            return priv_get_user_buffer(new_block);         }         else{            //Just merge the whole previous block            block_ctrl *prev_2_block = prev_pair.first;            //Update received size and allocation            received_size = extra_forward + prev->get_user_bytes();            m_header.m_allocated += prev->get_total_bytes();            //Now unlink it from previous block            prev_2_block->m_next = prev->m_next;            prev->m_size = reuse->m_size + prev->m_size;            prev->m_next = 0;            priv_get_user_buffer(prev);         }      }   }   return 0;}template<class MutexFamily, class VoidPointer>inline typename simple_seq_fit_impl<MutexFamily, VoidPointer>::multiallocation_iterator   simple_seq_fit_impl<MutexFamily, VoidPointer>::   allocate_many(std::size_t elem_bytes, std::size_t num_elements){   //-----------------------   boost::interprocess::scoped_lock<interprocess_mutex> guard(m_header);   //-----------------------   return algo_impl_t::      allocate_many(this, elem_bytes, num_elements);}template<class MutexFamily, class VoidPointer>inline void simple_seq_fit_impl<MutexFamily, VoidPointer>::   deallocate_many(typename simple_seq_fit_impl<MutexFamily, VoidPointer>::multiallocation_iterator it){   //-----------------------   boost::interprocess::scoped_lock<interprocess_mutex> guard(m_header);   //-----------------------   while(it){      void *addr = &*it;      ++it;      this->priv_deallocate(addr);   }}template<class MutexFamily, class VoidPointer>inline typename simple_seq_fit_impl<MutexFamily, VoidPointer>::multiallocation_iterator   simple_seq_fit_impl<MutexFamily, VoidPointer>::   allocate_many(const std::size_t *elem_sizes, std::size_t n_elements, std::size_t sizeof_element){

⌨️ 快捷键说明

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