diff options
Diffstat (limited to 'boost/interprocess/mem_algo')
6 files changed, 256 insertions, 1310 deletions
diff --git a/boost/interprocess/mem_algo/detail/mem_algo_common.hpp b/boost/interprocess/mem_algo/detail/mem_algo_common.hpp index 8af256aab9..87293d18fa 100644 --- a/boost/interprocess/mem_algo/detail/mem_algo_common.hpp +++ b/boost/interprocess/mem_algo/detail/mem_algo_common.hpp @@ -11,27 +11,32 @@ #ifndef BOOST_INTERPROCESS_DETAIL_MEM_ALGO_COMMON_HPP #define BOOST_INTERPROCESS_DETAIL_MEM_ALGO_COMMON_HPP -#if defined(_MSC_VER) +#ifndef BOOST_CONFIG_HPP +# include <boost/config.hpp> +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) # pragma once #endif #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> +// interprocess #include <boost/interprocess/interprocess_fwd.hpp> #include <boost/interprocess/containers/allocation_type.hpp> -#include <boost/interprocess/detail/utilities.hpp> -#include <boost/interprocess/detail/type_traits.hpp> +// interprocess/detail #include <boost/interprocess/detail/math_functions.hpp> -#include <boost/interprocess/detail/utilities.hpp> -#include <boost/move/utility_core.hpp> #include <boost/interprocess/detail/min_max.hpp> +#include <boost/interprocess/detail/type_traits.hpp> +#include <boost/interprocess/detail/utilities.hpp> +// container/detail #include <boost/container/detail/multiallocation_chain.hpp> -#include <boost/assert.hpp> +#include <boost/container/detail/placement_new.hpp> +// move +#include <boost/move/utility_core.hpp> +// other boost #include <boost/static_assert.hpp> -#include <algorithm> -#include <utility> -#include <iterator> #include <boost/assert.hpp> //!\file @@ -240,10 +245,11 @@ class memory_algorithm_common return 0; } - size_type real_size; + size_type real_size = nbytes; if(alignment <= Alignment){ + void *ignore_reuse = 0; return memory_algo->priv_allocate - (boost::interprocess::allocate_new, nbytes, nbytes, real_size).first; + (boost::interprocess::allocate_new, nbytes, real_size, ignore_reuse); } if(nbytes > UsableByPreviousChunk) @@ -268,8 +274,9 @@ class memory_algorithm_common ); //Now allocate the buffer - void *buffer = memory_algo->priv_allocate - (boost::interprocess::allocate_new, request, request, real_size).first; + real_size = request; + void *ignore_reuse = 0; + void *buffer = memory_algo->priv_allocate(boost::interprocess::allocate_new, request, real_size, ignore_reuse); if(!buffer){ return 0; } @@ -358,9 +365,9 @@ class memory_algorithm_common static bool try_shrink (MemoryAlgorithm *memory_algo, void *ptr - ,const size_type max_size, const size_type preferred_size - ,size_type &received_size) + ,const size_type max_size, size_type &received_size) { + size_type const preferred_size = received_size; (void)memory_algo; //Obtain the real block block_ctrl *block = memory_algo->priv_get_block(ptr); @@ -414,15 +421,14 @@ class memory_algorithm_common static bool shrink (MemoryAlgorithm *memory_algo, void *ptr - ,const size_type max_size, const size_type preferred_size - ,size_type &received_size) + ,const size_type max_size, size_type &received_size) { + size_type const preferred_size = received_size; //Obtain the real block block_ctrl *block = memory_algo->priv_get_block(ptr); size_type old_block_units = (size_type)block->m_size; - if(!try_shrink - (memory_algo, ptr, max_size, preferred_size, received_size)){ + if(!try_shrink(memory_algo, ptr, max_size, received_size)){ return false; } @@ -492,14 +498,15 @@ class memory_algorithm_common : memory_algo->priv_get_total_units(elem_sizes[low_idx]*sizeof_element); min_allocation = min_allocation*Alignment - AllocatedCtrlBytes + UsableByPreviousChunk; - size_type received_size; - std::pair<void *, bool> ret = memory_algo->priv_allocate - (boost::interprocess::allocate_new, min_allocation, total_bytes, received_size, 0); - if(!ret.first){ + size_type received_size = total_bytes; + void *ignore_reuse = 0; + void *ret = memory_algo->priv_allocate + (boost::interprocess::allocate_new, min_allocation, received_size, ignore_reuse); + if(!ret){ break; } - block_ctrl *block = memory_algo->priv_get_block(ret.first); + block_ctrl *block = memory_algo->priv_get_block(ret); size_type received_units = (size_type)block->m_size; char *block_address = reinterpret_cast<char*>(block); @@ -521,8 +528,8 @@ class memory_algorithm_common (total_used_units + elem_units + ((!sizeof_element) ? elem_units - : std::max(memory_algo->priv_get_total_units(elem_sizes[low_idx+1]*sizeof_element), ptr_size_units)) - ) > received_units){ + : max_value(memory_algo->priv_get_total_units(elem_sizes[low_idx+1]*sizeof_element), ptr_size_units)) + > received_units)){ //By default, the new block will use the rest of the buffer new_block->m_size = received_units - total_used_units; memory_algo->priv_mark_new_allocated_block(new_block); @@ -530,13 +537,12 @@ class memory_algorithm_common //If the remaining units are bigger than needed and we can //split it obtaining a new free memory block do it. if((received_units - total_used_units) >= (elem_units + MemoryAlgorithm::BlockCtrlUnits)){ - size_type shrunk_received; size_type shrunk_request = elem_units*Alignment - AllocatedCtrlBytes + UsableByPreviousChunk; + size_type shrunk_received = shrunk_request; bool shrink_ok = shrink (memory_algo ,memory_algo->priv_get_user_buffer(new_block) ,shrunk_request - ,shrunk_request ,shrunk_received); (void)shrink_ok; //Shrink must always succeed with passed parameters @@ -559,7 +565,7 @@ class memory_algorithm_common total_used_units += (size_type)new_block->m_size; //Check we have enough room to overwrite the intrusive pointer BOOST_ASSERT((new_block->m_size*Alignment - AllocatedCtrlUnits) >= sizeof(void_pointer)); - void_pointer p = new(memory_algo->priv_get_user_buffer(new_block))void_pointer(0); + void_pointer p = ::new(memory_algo->priv_get_user_buffer(new_block), boost_container_new_t())void_pointer(0); chain.push_back(p); ++low_idx; } diff --git a/boost/interprocess/mem_algo/detail/multi_simple_seq_fit.hpp b/boost/interprocess/mem_algo/detail/multi_simple_seq_fit.hpp deleted file mode 100644 index dd11bdbb50..0000000000 --- a/boost/interprocess/mem_algo/detail/multi_simple_seq_fit.hpp +++ /dev/null @@ -1,61 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2005-2011. 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_MULTI_SIMPLE_SEQ_FIT_HPP -#define BOOST_INTERPROCESS_MULTI_SIMPLE_SEQ_FIT_HPP - -#if defined(_MSC_VER) -# pragma once -#endif - -#include <boost/interprocess/detail/config_begin.hpp> -#include <boost/interprocess/detail/workaround.hpp> - -#include <boost/interprocess/interprocess_fwd.hpp> -#include <boost/interprocess/mem_algo/detail/simple_seq_fit_impl.hpp> -#include <boost/interprocess/intersegment_ptr.hpp> - -/*!\file - Describes sequential fit algorithm used to allocate objects in shared memory. -*/ - -namespace boost { - -namespace interprocess { - -/*!This class implements the simple sequential fit algorithm with a simply - linked list of free buffers.*/ -template<class MutexFamily, class VoidPtr> -class multi_simple_seq_fit - : public ipcdetail::simple_seq_fit_impl<MutexFamily, VoidPtr> -{ - typedef ipcdetail::simple_seq_fit_impl<MutexFamily, VoidPtr> base_t; - public: - /*!Constructor. "size" is the total size of the managed memory segment, - "extra_hdr_bytes" indicates the extra bytes beginning in the sizeof(multi_simple_seq_fit) - offset that the allocator should not use at all.*/ - multi_simple_seq_fit (size_type size, size_type extra_hdr_bytes) - : base_t(size, extra_hdr_bytes){} - - /*!Allocates bytes from existing segments. If there is no memory, it uses - the growing functor associated with the group to allocate a new segment. - If this fails, returns 0.*/ - void* allocate (size_type nbytes) - { return base_t::multi_allocate(nbytes); } -}; - -} //namespace interprocess { - -} //namespace boost { - -#include <boost/interprocess/detail/config_end.hpp> - -#endif //#ifndef BOOST_INTERPROCESS_MULTI_SIMPLE_SEQ_FIT_HPP - diff --git a/boost/interprocess/mem_algo/detail/multi_simple_seq_fit_impl.hpp b/boost/interprocess/mem_algo/detail/multi_simple_seq_fit_impl.hpp deleted file mode 100644 index c84d4e6fb7..0000000000 --- a/boost/interprocess/mem_algo/detail/multi_simple_seq_fit_impl.hpp +++ /dev/null @@ -1,983 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2005-2011. 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_MEM_ALGO_DETAIL_SIMPLE_SEQ_FIT_IMPL_HPP -#define BOOST_INTERPROCESS_MEM_ALGO_DETAIL_SIMPLE_SEQ_FIT_IMPL_HPP - -#if defined(_MSC_VER) -# pragma once -#endif - -#include <boost/interprocess/detail/config_begin.hpp> -#include <boost/interprocess/detail/workaround.hpp> - -#include <boost/intrusive/pointer_traits.hpp> - -#include <boost/interprocess/interprocess_fwd.hpp> -#include <boost/interprocess/containers/allocation_type.hpp> -#include <boost/interprocess/offset_ptr.hpp> -#include <boost/interprocess/sync/interprocess_mutex.hpp> -#include <boost/interprocess/exceptions.hpp> -#include <boost/interprocess/detail/utilities.hpp> -#include <boost/interprocess/detail/multi_segment_services.hpp> -#include <boost/type_traits/alignment_of.hpp> -#include <boost/type_traits/type_with_alignment.hpp> -#include <boost/interprocess/detail/min_max.hpp> -#include <boost/interprocess/sync/scoped_lock.hpp> -#include <boost/intrusive/pointer_traits.hpp> -#include <algorithm> -#include <utility> -#include <cstring> - -#include <boost/assert.hpp> -#include <new> - -/*!\file - Describes sequential fit algorithm used to allocate objects in shared memory. - This class is intended as a base class for single segment and multi-segment - implementations. -*/ - -namespace boost { - -namespace interprocess { - -namespace ipcdetail { - -/*!This class implements the simple sequential fit algorithm with a simply - linked list of free buffers. - This class is intended as a base class for single segment and multi-segment - implementations.*/ -template<class MutexFamily, class VoidPointer> -class simple_seq_fit_impl -{ - //Non-copyable - simple_seq_fit_impl(); - simple_seq_fit_impl(const simple_seq_fit_impl &); - simple_seq_fit_impl &operator=(const simple_seq_fit_impl &); - - public: - /*!Shared interprocess_mutex family used for the rest of the Interprocess framework*/ - typedef MutexFamily mutex_family; - /*!Pointer type to be used with the rest of the Interprocess framework*/ - typedef VoidPointer void_pointer; - - typedef typename boost::intrusive::pointer_traits<char_ptr>::difference_type difference_type; - typedef typename boost::make_unsigned<difference_type>::type size_type; - - - private: - struct block_ctrl; - typedef typename boost::intrusive:: - pointer_traits<void_pointer>::template - rebind_pointer<block_ctrl>::type block_ctrl_ptr; - - /*!Block control structure*/ - struct block_ctrl - { - /*!Offset pointer to the next block.*/ - block_ctrl_ptr m_next; - /*!This block's memory size (including block_ctrl - header) in BasicSize units*/ - size_type m_size; - - size_type get_user_bytes() const - { return this->m_size*Alignment - BlockCtrlBytes; } - - size_type get_total_bytes() const - { return this->m_size*Alignment; } - - static block_ctrl *get_block_from_addr(void *addr) - { - return reinterpret_cast<block_ctrl*> - (reinterpret_cast<char*>(addr) - BlockCtrlBytes); - } - - void *get_addr() const - { - return reinterpret_cast<block_ctrl*> - (reinterpret_cast<const char*>(this) + BlockCtrlBytes); - } - - }; - - /*!Shared interprocess_mutex to protect memory allocate/deallocate*/ - typedef typename MutexFamily::mutex_type interprocess_mutex; - - /*!This struct includes needed data and derives from - interprocess_mutex to allow EBO when using null interprocess_mutex*/ - struct header_t : public interprocess_mutex - { - /*!Pointer to the first free block*/ - block_ctrl m_root; - /*!Allocated bytes for internal checking*/ - size_type m_allocated; - /*!The size of the memory segment*/ - size_type m_size; - } m_header; - - public: - /*!Constructor. "size" is the total size of the managed memory segment, - "extra_hdr_bytes" indicates the extra bytes beginning in the sizeof(simple_seq_fit_impl) - offset that the allocator should not use at all.*/ - simple_seq_fit_impl (size_type size, size_type extra_hdr_bytes); - /*!Destructor.*/ - ~simple_seq_fit_impl(); - /*!Obtains the minimum size needed by the algorithm*/ - static size_type get_min_size (size_type extra_hdr_bytes); - - //Functions for single segment management - - /*!Allocates bytes, returns 0 if there is not more memory*/ - void* allocate (size_type nbytes); - - /*!Deallocates previously allocated bytes*/ - void deallocate (void *addr); - - /*!Returns the size of the memory segment*/ - size_type get_size() const; - - /*!Increases managed memory in extra_size bytes more*/ - void grow(size_type extra_size); - - /*!Returns true if all allocated memory has been deallocated*/ - bool all_memory_deallocated(); - - /*!Makes an internal sanity check and returns true if success*/ - bool check_sanity(); - - //!Initializes to zero all the memory that's not in use. - //!This function is normally used for security reasons. - void clear_free_memory(); - - std::pair<void *, bool> - allocation_command (boost::interprocess::allocation_type command, size_type limit_size, - size_type preferred_size,size_type &received_size, - void *reuse_ptr = 0, size_type backwards_multiple = 1); - - /*!Returns the size of the buffer previously allocated pointed by ptr*/ - size_type size(void *ptr) const; - - /*!Allocates aligned bytes, returns 0 if there is not more memory. - Alignment must be power of 2*/ - void* allocate_aligned (size_type nbytes, size_type alignment); - - /*!Allocates bytes, if there is no more memory, it executes functor - f(size_type) to allocate a new segment to manage. The functor returns - std::pair<void*, size_type> indicating the base address and size of - the new segment. If the new segment can't be allocated, allocate - it will return 0.*/ - void* multi_allocate(size_type nbytes); - - private: - /*!Real allocation algorithm with min allocation option*/ - std::pair<void *, bool> priv_allocate(boost::interprocess::allocation_type command - ,size_type min_size - ,size_type preferred_size - ,size_type &received_size - ,void *reuse_ptr = 0); - /*!Returns next block if it's free. - Returns 0 if next block is not free.*/ - block_ctrl *priv_next_block_if_free(block_ctrl *ptr); - - /*!Returns previous block's if it's free. - Returns 0 if previous block is not free.*/ - std::pair<block_ctrl*, block_ctrl*>priv_prev_block_if_free(block_ctrl *ptr); - - /*!Real expand function implementation*/ - bool priv_expand(void *ptr - ,size_type min_size, size_type preferred_size - ,size_type &received_size); - - /*!Real expand to both sides implementation*/ - void* priv_expand_both_sides(boost::interprocess::allocation_type command - ,size_type min_size - ,size_type preferred_size - ,size_type &received_size - ,void *reuse_ptr - ,bool only_preferred_backwards); - - /*!Real shrink function implementation*/ - bool priv_shrink(void *ptr - ,size_type max_size, size_type preferred_size - ,size_type &received_size); - - //!Real private aligned allocation function - void* priv_allocate_aligned (size_type nbytes, size_type alignment); - - /*!Checks if block has enough memory and splits/unlinks the block - returning the address to the users*/ - void* priv_check_and_allocate(size_type units - ,block_ctrl* prev - ,block_ctrl* block - ,size_type &received_size); - /*!Real deallocation algorithm*/ - void priv_deallocate(void *addr); - - /*!Makes a new memory portion available for allocation*/ - void priv_add_segment(void *addr, size_type size); - - static const std::size_t Alignment = ::boost::alignment_of<boost::ipcdetail::max_align>::value; - static const std::size_t BlockCtrlBytes = ipcdetail::ct_rounded_size<sizeof(block_ctrl), Alignment>::value; - static const std::size_t BlockCtrlSize = BlockCtrlBytes/Alignment; - static const std::size_t MinBlockSize = BlockCtrlSize + Alignment; - - public: - static const std::size_t PayloadPerAllocation = BlockCtrlBytes; -}; - -template<class MutexFamily, class VoidPointer> -inline simple_seq_fit_impl<MutexFamily, VoidPointer>:: - simple_seq_fit_impl(size_type size, size_type extra_hdr_bytes) -{ - //Initialize sizes and counters - m_header.m_allocated = 0; - m_header.m_size = size; - - //Initialize pointers - size_type block1_off = ipcdetail::get_rounded_size(sizeof(*this)+extra_hdr_bytes, Alignment); - m_header.m_root.m_next = reinterpret_cast<block_ctrl*> - (reinterpret_cast<char*>(this) + block1_off); - m_header.m_root.m_next->m_size = (size - block1_off)/Alignment; - m_header.m_root.m_next->m_next = &m_header.m_root; -} - -template<class MutexFamily, class VoidPointer> -inline simple_seq_fit_impl<MutexFamily, VoidPointer>::~simple_seq_fit_impl() -{ - //There is a memory leak! -// BOOST_ASSERT(m_header.m_allocated == 0); -// BOOST_ASSERT(m_header.m_root.m_next->m_next == block_ctrl_ptr(&m_header.m_root)); -} - -template<class MutexFamily, class VoidPointer> -inline void simple_seq_fit_impl<MutexFamily, VoidPointer>::grow(size_type extra_size) -{ - //Old highest address block's end offset - size_type old_end = m_header.m_size/Alignment*Alignment; - - //Update managed buffer's size - m_header.m_size += extra_size; - - //We need at least MinBlockSize blocks to create a new block - if((m_header.m_size - old_end) < MinBlockSize){ - return; - } - - //We'll create a new free block with extra_size bytes - block_ctrl *new_block = reinterpret_cast<block_ctrl*> - (reinterpret_cast<char*>(this) + old_end); - - new_block->m_next = 0; - new_block->m_size = (m_header.m_size - old_end)/Alignment; - m_header.m_allocated += new_block->m_size*Alignment; - this->priv_deallocate(reinterpret_cast<char*>(new_block) + BlockCtrlBytes); -} - -template<class MutexFamily, class VoidPointer> -inline void simple_seq_fit_impl<MutexFamily, VoidPointer>::priv_add_segment(void *addr, size_type size) -{ - //Check size - BOOST_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(reinterpret_cast<char*>(new_block) + BlockCtrlBytes); -} - -template<class MutexFamily, class VoidPointer> -inline typename simple_seq_fit_impl<MutexFamily, VoidPointer>::size_type -simple_seq_fit_impl<MutexFamily, VoidPointer>::get_size() const - { return m_header.m_size; } - -template<class MutexFamily, class VoidPointer> -inline typename simple_seq_fit_impl<MutexFamily, VoidPointer>::size_type -simple_seq_fit_impl<MutexFamily, VoidPointer>:: - get_min_size (size_type extra_hdr_bytes) -{ - return ipcdetail::get_rounded_size(sizeof(simple_seq_fit_impl)+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 && - ipcdetail::to_raw_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>::clear_free_memory() -{ - //----------------------- - boost::interprocess::scoped_lock<interprocess_mutex> guard(m_header); - //----------------------- - block_ctrl *block = ipcdetail::to_raw_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( reinterpret_cast<char*>(block) + BlockCtrlBytes - , 0 - , block->m_size*Alignment - BlockCtrlBytes); - block = ipcdetail::to_raw_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 = ipcdetail::to_raw_pointer(m_header.m_root.m_next); - - size_type free_memory = 0; - - //Iterate through all blocks obtaining their size - do{ - //Free blocks's next must be always valid - block_ctrl *next = ipcdetail::to_raw_pointer(block->m_next); - if(!next){ - return false; - } - free_memory += block->m_size*Alignment; - block = next; - } - while(block != &m_header.m_root); - - //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(size_type nbytes) -{ - //----------------------- - boost::interprocess::scoped_lock<interprocess_mutex> guard(m_header); - //----------------------- - size_type ignore; - return priv_allocate(boost::interprocess::allocate_new, nbytes, nbytes, ignore).first; -} - -template<class MutexFamily, class VoidPointer> -inline void* simple_seq_fit_impl<MutexFamily, VoidPointer>:: - allocate_aligned(size_type nbytes, size_type alignment) -{ - //----------------------- - boost::interprocess::scoped_lock<interprocess_mutex> guard(m_header); - //----------------------- - return priv_allocate_aligned(nbytes, alignment); -} - -template<class MutexFamily, class VoidPointer> -inline std::pair<void *, bool> simple_seq_fit_impl<MutexFamily, VoidPointer>:: - allocation_command (boost::interprocess::allocation_type command, size_type min_size, - size_type preferred_size,size_type &received_size, - void *reuse_ptr, size_type backwards_multiple) -{ - //----------------------- - boost::interprocess::scoped_lock<interprocess_mutex> guard(m_header); - //----------------------- - (void)backwards_multiple; - command &= ~boost::interprocess::expand_bwd; - if(!command) - return std::pair<void *, bool>(0, false); - return priv_allocate(command, min_size, preferred_size, received_size, reuse_ptr); -} - -template<class MutexFamily, class VoidPointer> -inline typename simple_seq_fit_impl<MutexFamily, VoidPointer>::size_type -simple_seq_fit_impl<MutexFamily, VoidPointer>:: - size(void *ptr) const -{ - //We need no synchronization since this block is not going - //to be modified - //Obtain the real size of the block - block_ctrl *block = reinterpret_cast<block_ctrl*> - (reinterpret_cast<char*>(ptr) - BlockCtrlBytes); - return block->m_size*Alignment - BlockCtrlBytes; -} - -template<class MutexFamily, class VoidPointer> -inline void* simple_seq_fit_impl<MutexFamily, VoidPointer>:: - multi_allocate(size_type nbytes) -{ - //----------------------- - boost::interprocess::scoped_lock<interprocess_mutex> guard(m_header); - //----------------------- - //Multisegment pointer. Let's try first the normal allocation - //since it's faster. - size_type ignore; - void *addr = this->priv_allocate(boost::interprocess::allocate_new, nbytes, nbytes, ignore).first; - if(!addr){ - //If this fails we will try the allocation through the segment - //creator. - size_type group, id; - //Obtain the segment group of this segment - void_pointer::get_group_and_id(this, group, id); - if(group == 0){ - //Ooops, group 0 is not valid. - return 0; - } - //Now obtain the polymorphic functor that creates - //new segments and try to allocate again. - boost::interprocess::multi_segment_services *p_services = - static_cast<boost::interprocess::multi_segment_services*> - (void_pointer::find_group_data(group)); - BOOST_ASSERT(p_services); - std::pair<void *, std::size_t> ret = - p_services->create_new_segment(MinBlockSize > nbytes ? MinBlockSize : nbytes); - if(ret.first){ - priv_add_segment(ret.first, ret.second); - addr = this->priv_allocate(boost::interprocess::allocate_new, nbytes, nbytes, ignore).first; - } - } - return addr; -} - -template<class MutexFamily, class VoidPointer> -void* simple_seq_fit_impl<MutexFamily, VoidPointer>:: - priv_expand_both_sides(boost::interprocess::allocation_type command - ,size_type min_size - ,size_type preferred_size - ,size_type &received_size - ,void *reuse_ptr - ,bool only_preferred_backwards) -{ - typedef std::pair<block_ctrl *, block_ctrl *> prev_block_t; - block_ctrl *reuse = block_ctrl::get_block_from_addr(reuse_ptr); - received_size = 0; - - if(this->size(reuse_ptr) > min_size){ - received_size = this->size(reuse_ptr); - return reuse_ptr; - } - - if(command & boost::interprocess::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 & boost::interprocess::expand_bwd){ - size_type 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; - } - - size_type needs_backwards = - ipcdetail::get_rounded_size(preferred_size - extra_forward, Alignment); - - if(!only_preferred_backwards){ - needs_backwards = - max_value(ipcdetail::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)){ - BOOST_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 = - BlockCtrlSize + (needs_backwards + extra_forward)/Alignment; - prev->m_size = - (prev->get_total_bytes() - needs_backwards)/Alignment - BlockCtrlSize; - received_size = needs_backwards + extra_forward; - m_header.m_allocated += needs_backwards + BlockCtrlBytes; - return new_block->get_addr(); - } - 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; - return prev->get_addr(); - } - } - } - return 0; -} - -template<class MutexFamily, class VoidPointer> -std::pair<void *, bool> simple_seq_fit_impl<MutexFamily, VoidPointer>:: - priv_allocate(boost::interprocess::allocation_type command - ,size_type limit_size - ,size_type preferred_size - ,size_type &received_size - ,void *reuse_ptr) -{ - if(command & boost::interprocess::shrink_in_place){ - bool success = - this->priv_shrink(reuse_ptr, limit_size, preferred_size, received_size); - return std::pair<void *, bool> ((success ? reuse_ptr : 0), true); - } - typedef std::pair<void *, bool> return_type; - received_size = 0; - - if(limit_size > preferred_size) - return return_type(0, false); - - //Number of units to request (including block_ctrl header) - size_type nunits = ipcdetail::get_rounded_size(preferred_size, Alignment)/Alignment + BlockCtrlSize; - - //Get the root and the first memory block - block_ctrl *prev = &m_header.m_root; - block_ctrl *block = ipcdetail::to_raw_pointer(prev->m_next); - block_ctrl *root = &m_header.m_root; - block_ctrl *biggest_block = 0; - block_ctrl *prev_biggest_block = 0; - size_type biggest_size = limit_size; - - //Expand in place - //reuse_ptr, limit_size, preferred_size, received_size - // - if(reuse_ptr && (command & (boost::interprocess::expand_fwd | boost::interprocess::expand_bwd))){ - void *ret = priv_expand_both_sides - (command, limit_size, preferred_size, received_size, reuse_ptr, true); - if(ret) - return return_type(ret, true); - } - - if(command & boost::interprocess::allocate_new){ - received_size = 0; - while(block != root){ - //Update biggest block pointers - if(block->m_size > biggest_size){ - prev_biggest_block = prev; - biggest_size = block->m_size; - biggest_block = block; - } - void *addr = this->priv_check_and_allocate(nunits, prev, block, received_size); - if(addr) return return_type(addr, false); - //Bad luck, let's check next block - prev = block; - block = ipcdetail::to_raw_pointer(block->m_next); - } - - //Bad luck finding preferred_size, now if we have any biggest_block - //try with this block - if(biggest_block){ - received_size = biggest_block->m_size*Alignment - BlockCtrlSize; - nunits = ipcdetail::get_rounded_size(limit_size, Alignment)/Alignment + BlockCtrlSize; - void *ret = this->priv_check_and_allocate - (nunits, prev_biggest_block, biggest_block, received_size); - if(ret) - return return_type(ret, false); - } - } - //Now try to expand both sides with min size - if(reuse_ptr && (command & (boost::interprocess::expand_fwd | boost::interprocess::expand_bwd))){ - return return_type(priv_expand_both_sides - (command, limit_size, preferred_size, received_size, reuse_ptr, false), true); - } - return return_type(0, false); -} - -template<class MutexFamily, class VoidPointer> -inline typename simple_seq_fit_impl<MutexFamily, VoidPointer>::block_ctrl * - simple_seq_fit_impl<MutexFamily, VoidPointer>:: - priv_next_block_if_free - (typename simple_seq_fit_impl<MutexFamily, VoidPointer>::block_ctrl *ptr) -{ - //Take the address where the next block should go - block_ctrl *next_block = reinterpret_cast<block_ctrl*> - (reinterpret_cast<char*>(ptr) + ptr->m_size*Alignment); - - //Check if the adjacent block is in the managed segment - size_type distance = (reinterpret_cast<char*>(next_block) - reinterpret_cast<char*>(this))/Alignment; - if(distance >= (m_header.m_size/Alignment)){ - //"next_block" does not exist so we can't expand "block" - return 0; - } - - if(!next_block->m_next) - return 0; - - return next_block; -} - -template<class MutexFamily, class VoidPointer> -inline - std::pair<typename simple_seq_fit_impl<MutexFamily, VoidPointer>::block_ctrl * - ,typename simple_seq_fit_impl<MutexFamily, VoidPointer>::block_ctrl *> - simple_seq_fit_impl<MutexFamily, VoidPointer>:: - priv_prev_block_if_free - (typename simple_seq_fit_impl<MutexFamily, VoidPointer>::block_ctrl *ptr) -{ - typedef std::pair<block_ctrl *, block_ctrl *> prev_pair_t; - //Take the address where the previous block should go - block_ctrl *root = &m_header.m_root; - block_ctrl *prev_2_block = root; - block_ctrl *prev_block = ipcdetail::to_raw_pointer(root->m_next); - while((reinterpret_cast<char*>(prev_block) + prev_block->m_size*Alignment) - != (reinterpret_cast<char*>(ptr)) - && prev_block != root){ - prev_2_block = prev_block; - prev_block = ipcdetail::to_raw_pointer(prev_block->m_next); - } - - if(prev_block == root || !prev_block->m_next) - return prev_pair_t(0, 0); - - //Check if the previous block is in the managed segment - size_type distance = (reinterpret_cast<char*>(prev_block) - reinterpret_cast<char*>(this))/Alignment; - if(distance >= (m_header.m_size/Alignment)){ - //"previous_block" does not exist so we can't expand "block" - return prev_pair_t(0, 0); - } - return prev_pair_t(prev_2_block, prev_block); -} - - -template<class MutexFamily, class VoidPointer> -inline bool simple_seq_fit_impl<MutexFamily, VoidPointer>:: - priv_expand (void *ptr - ,size_type min_size - ,size_type preferred_size - ,size_type &received_size) -{ - //Obtain the real size of the block - block_ctrl *block = reinterpret_cast<block_ctrl*> - (reinterpret_cast<char*>(ptr) - BlockCtrlBytes); - size_type old_block_size = block->m_size; - - //All used blocks' next is marked with 0 so check it - BOOST_ASSERT(block->m_next == 0); - - //Put this to a safe value - received_size = old_block_size*Alignment - BlockCtrlBytes; - - //Now translate it to Alignment units - min_size = ipcdetail::get_rounded_size(min_size, Alignment)/Alignment; - preferred_size = ipcdetail::get_rounded_size(preferred_size, Alignment)/Alignment; - - //Some parameter checks - if(min_size > preferred_size) - return false; - - size_type data_size = old_block_size - BlockCtrlSize; - - if(data_size >= min_size) - return true; - - block_ctrl *next_block = priv_next_block_if_free(block); - if(!next_block){ - return false; - } - - //Is "block" + "next_block" big enough? - size_type merged_size = old_block_size + next_block->m_size; - - //Now we can expand this block further than before - received_size = merged_size*Alignment - BlockCtrlBytes; - - if(merged_size < (min_size + BlockCtrlSize)){ - return false; - } - - //We can fill expand. Merge both blocks, - block->m_next = next_block->m_next; - block->m_size = merged_size; - - //Find the previous free block of next_block - block_ctrl *prev = &m_header.m_root; - while(ipcdetail::to_raw_pointer(prev->m_next) != next_block){ - prev = ipcdetail::to_raw_pointer(prev->m_next); - } - - //Now insert merged block in the free list - //This allows reusing allocation logic in this function - m_header.m_allocated -= old_block_size*Alignment; - prev->m_next = block; - - //Now use check and allocate to do the allocation logic - preferred_size += BlockCtrlSize; - size_type nunits = preferred_size < merged_size ? preferred_size : merged_size; - - //This must success since nunits is less than merged_size! - if(!this->priv_check_and_allocate (nunits, prev, block, received_size)){ - //Something very ugly is happening here. This is a bug - //or there is memory corruption - BOOST_ASSERT(0); - return false; - } - return true; -} - -template<class MutexFamily, class VoidPointer> -inline bool simple_seq_fit_impl<MutexFamily, VoidPointer>:: - priv_shrink (void *ptr - ,size_type max_size - ,size_type preferred_size - ,size_type &received_size) -{ - //Obtain the real size of the block - block_ctrl *block = reinterpret_cast<block_ctrl*> - (reinterpret_cast<char*>(ptr) - BlockCtrlBytes); - size_type block_size = block->m_size; - - //All used blocks' next is marked with 0 so check it - BOOST_ASSERT(block->m_next == 0); - - //Put this to a safe value - received_size = block_size*Alignment - BlockCtrlBytes; - - //Now translate it to Alignment units - max_size = max_size/Alignment; - preferred_size = ipcdetail::get_rounded_size(preferred_size, Alignment)/Alignment; - - //Some parameter checks - if(max_size < preferred_size) - return false; - - size_type data_size = block_size - BlockCtrlSize; - - if(data_size < preferred_size) - return false; - - if(data_size == preferred_size) - return true; - - //We must be able to create at least a new empty block - if((data_size - preferred_size) < BlockCtrlSize){ - return false; - } - - //Now we can just rewrite the size of the old buffer - block->m_size = preferred_size + BlockCtrlSize; - - //Update new size - received_size = preferred_size*Alignment; - - //We create the new block - block = reinterpret_cast<block_ctrl*> - (reinterpret_cast<char*>(block) + block->m_size*Alignment); - - //Write control data to simulate this new block was previously allocated - block->m_next = 0; - block->m_size = data_size - preferred_size; - - //Now deallocate the new block to insert it in the free list - this->priv_deallocate(reinterpret_cast<char*>(block)+BlockCtrlBytes); - return true; -} - -template<class MutexFamily, class VoidPointer> -inline void* simple_seq_fit_impl<MutexFamily, VoidPointer>:: - priv_allocate_aligned(size_type nbytes, size_type alignment) -{ - //Ensure power of 2 - if ((alignment & (alignment - size_type(1u))) != 0){ - //Alignment is not power of two - BOOST_ASSERT((alignment & (alignment - size_type(1u))) != 0); - return 0; - } - - size_type ignore; - if(alignment <= Alignment){ - return priv_allocate(boost::interprocess::allocate_new, nbytes, nbytes, ignore).first; - } - - size_type request = - nbytes + alignment + MinBlockSize*Alignment - BlockCtrlBytes; - void *buffer = priv_allocate(boost::interprocess::allocate_new, request, request, ignore).first; - if(!buffer) - return 0; - else if ((((std::size_t)(buffer)) % alignment) == 0) - return buffer; - - char *aligned_portion = reinterpret_cast<char*> - (reinterpret_cast<size_type>(static_cast<char*>(buffer) + alignment - 1) & -alignment); - - char *pos = ((aligned_portion - reinterpret_cast<char*>(buffer)) >= (MinBlockSize*Alignment)) ? - aligned_portion : (aligned_portion + alignment); - - block_ctrl *first = reinterpret_cast<block_ctrl*> - (reinterpret_cast<char*>(buffer) - BlockCtrlBytes); - - block_ctrl *second = reinterpret_cast<block_ctrl*>(pos - BlockCtrlBytes); - - size_type old_size = first->m_size; - - first->m_size = (reinterpret_cast<char*>(second) - reinterpret_cast<char*>(first))/Alignment; - second->m_size = old_size - first->m_size; - - //Write control data to simulate this new block was previously allocated - second->m_next = 0; - - //Now deallocate the new block to insert it in the free list - this->priv_deallocate(reinterpret_cast<char*>(first) + BlockCtrlBytes); - return reinterpret_cast<char*>(second) + BlockCtrlBytes; -} - -template<class MutexFamily, class VoidPointer> inline -void* simple_seq_fit_impl<MutexFamily, VoidPointer>::priv_check_and_allocate - (size_type nunits - ,typename simple_seq_fit_impl<MutexFamily, VoidPointer>::block_ctrl* prev - ,typename simple_seq_fit_impl<MutexFamily, VoidPointer>::block_ctrl* block - ,size_type &received_size) -{ - size_type upper_nunits = nunits + BlockCtrlSize; - bool found = false; - - if (block->m_size > upper_nunits){ - //This block is bigger than needed, split it in - //two blocks, the first's size will be (block->m_size-units) - //the second's size (units) - size_type total_size = block->m_size; - block->m_size = nunits; - block_ctrl *new_block = reinterpret_cast<block_ctrl*> - (reinterpret_cast<char*>(block) + Alignment*nunits); - new_block->m_size = total_size - nunits; - new_block->m_next = block->m_next; - prev->m_next = new_block; - found = true; - } - else if (block->m_size >= nunits){ - //This block has exactly the right size with an extra - //unusable extra bytes. - prev->m_next = block->m_next; - found = true; - } - - if(found){ - //We need block_ctrl for deallocation stuff, so - //return memory user can overwrite - m_header.m_allocated += block->m_size*Alignment; - received_size = block->m_size*Alignment - BlockCtrlBytes; - //Mark the block as allocated - block->m_next = 0; - //Check alignment - BOOST_ASSERT(((reinterpret_cast<char*>(block) - reinterpret_cast<char*>(this)) - % Alignment) == 0 ); - return reinterpret_cast<char*>(block) + BlockCtrlBytes; - } - return 0; -} - -template<class MutexFamily, class VoidPointer> -void simple_seq_fit_impl<MutexFamily, VoidPointer>::deallocate(void* addr) -{ - if(!addr) return; - //----------------------- - boost::interprocess::scoped_lock<interprocess_mutex> guard(m_header); - //----------------------- - return this->priv_deallocate(addr); -} - -template<class MutexFamily, class VoidPointer> -void simple_seq_fit_impl<MutexFamily, VoidPointer>::priv_deallocate(void* addr) -{ - if(!addr) return; - - //Let's get free block list. List is always sorted - //by memory address to allow block merging. - //Pointer next always points to the first - //(lower address) block - block_ctrl_ptr prev = &m_header.m_root; - block_ctrl_ptr pos = m_header.m_root.m_next; - block_ctrl_ptr block = reinterpret_cast<block_ctrl*> - (reinterpret_cast<char*>(addr) - BlockCtrlBytes); - - //All used blocks' next is marked with 0 so check it - BOOST_ASSERT(block->m_next == 0); - - //Check if alignment and block size are right - BOOST_ASSERT((reinterpret_cast<char*>(addr) - reinterpret_cast<char*>(this)) - % Alignment == 0 ); - - size_type total_size = Alignment*block->m_size; - BOOST_ASSERT(m_header.m_allocated >= total_size); - - //Update used memory count - m_header.m_allocated -= total_size; - - //Let's find the previous and the next block of the block to deallocate - //This ordering comparison must be done with original pointers - //types since their mapping to raw pointers can be different - //in each process - while((ipcdetail::to_raw_pointer(pos) != &m_header.m_root) && (block > pos)){ - prev = pos; - pos = pos->m_next; - } - - //Try to combine with upper block - if ((reinterpret_cast<char*>(ipcdetail::to_raw_pointer(block)) - + Alignment*block->m_size) == - reinterpret_cast<char*>(ipcdetail::to_raw_pointer(pos))){ - - block->m_size += pos->m_size; - block->m_next = pos->m_next; - } - else{ - block->m_next = pos; - } - - //Try to combine with lower block - if ((reinterpret_cast<char*>(ipcdetail::to_raw_pointer(prev)) - + Alignment*prev->m_size) == - reinterpret_cast<char*>(ipcdetail::to_raw_pointer(block))){ - prev->m_size += block->m_size; - prev->m_next = block->m_next; - } - else{ - prev->m_next = block; - } -} - -} //namespace ipcdetail { - -} //namespace interprocess { - -} //namespace boost { - -#include <boost/interprocess/detail/config_end.hpp> - -#endif //#ifndef BOOST_INTERPROCESS_MEM_ALGO_DETAIL_SIMPLE_SEQ_FIT_IMPL_HPP - diff --git a/boost/interprocess/mem_algo/detail/simple_seq_fit_impl.hpp b/boost/interprocess/mem_algo/detail/simple_seq_fit_impl.hpp index fa0e9caeb7..5c7a420b4a 100644 --- a/boost/interprocess/mem_algo/detail/simple_seq_fit_impl.hpp +++ b/boost/interprocess/mem_algo/detail/simple_seq_fit_impl.hpp @@ -11,7 +11,11 @@ #ifndef BOOST_INTERPROCESS_MEM_ALGO_DETAIL_SIMPLE_SEQ_FIT_IMPL_HPP #define BOOST_INTERPROCESS_MEM_ALGO_DETAIL_SIMPLE_SEQ_FIT_IMPL_HPP -#if defined(_MSC_VER) +#ifndef BOOST_CONFIG_HPP +# include <boost/config.hpp> +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) # pragma once #endif @@ -32,13 +36,10 @@ #include <boost/interprocess/sync/scoped_lock.hpp> #include <boost/intrusive/pointer_traits.hpp> #include <boost/interprocess/mem_algo/detail/mem_algo_common.hpp> -#include <boost/type_traits/alignment_of.hpp> -#include <boost/type_traits/type_with_alignment.hpp> -#include <algorithm> -#include <utility> +#include <boost/move/detail/type_traits.hpp> //make_unsigned, alignment_of +#include <boost/intrusive/detail/minimal_pair_header.hpp> #include <cstring> #include <boost/assert.hpp> -#include <new> //!\file //!Describes sequential fit algorithm used to allocate objects in shared memory. @@ -75,7 +76,7 @@ class simple_seq_fit_impl basic_multiallocation_chain<VoidPointer> multiallocation_chain; typedef typename boost::intrusive::pointer_traits<char_ptr>::difference_type difference_type; - typedef typename boost::make_unsigned<difference_type>::type size_type; + typedef typename boost::container::container_detail::make_unsigned<difference_type>::type size_type; private: @@ -192,15 +193,11 @@ class simple_seq_fit_impl void zero_free_memory(); template<class T> - std::pair<T *, bool> - allocation_command (boost::interprocess::allocation_type command, size_type limit_size, - size_type preferred_size,size_type &received_size, - T *reuse_ptr = 0); + T *allocation_command (boost::interprocess::allocation_type command, size_type limit_size, + size_type &prefer_in_recvd_out_size, T *&reuse); - std::pair<void *, bool> - raw_allocation_command (boost::interprocess::allocation_type command, size_type limit_size, - size_type preferred_size,size_type &received_size, - void *reuse_ptr = 0, size_type sizeof_object = 1); + void * raw_allocation_command (boost::interprocess::allocation_type command, size_type limit_size, + size_type &prefer_in_recvd_out_size, void *&reuse_ptr, size_type sizeof_object = 1); //!Returns the size of the buffer previously allocated pointed by ptr size_type size(const void *ptr) const; @@ -218,18 +215,15 @@ class simple_seq_fit_impl static block_ctrl *priv_get_block(const void *ptr); //!Real allocation algorithm with min allocation option - std::pair<void *, bool> priv_allocate(boost::interprocess::allocation_type command - ,size_type min_size - ,size_type preferred_size - ,size_type &received_size - ,void *reuse_ptr = 0); - - std::pair<void *, bool> priv_allocation_command(boost::interprocess::allocation_type command - ,size_type min_size - ,size_type preferred_size - ,size_type &received_size - ,void *reuse_ptr - ,size_type sizeof_object); + void * priv_allocate(boost::interprocess::allocation_type command + ,size_type min_size + ,size_type &prefer_in_recvd_out_size, void *&reuse_ptr); + + void * priv_allocation_command(boost::interprocess::allocation_type command + ,size_type min_size + ,size_type &prefer_in_recvd_out_size + ,void *&reuse_ptr + ,size_type sizeof_object); //!Returns the number of total units that a user buffer //!of "userbytes" bytes really occupies (including header) @@ -247,18 +241,14 @@ class simple_seq_fit_impl //!Returns previous block's if it's free. //!Returns 0 if previous block is not free. - std::pair<block_ctrl*, block_ctrl*>priv_prev_block_if_free(block_ctrl *ptr); + std::pair<block_ctrl*, block_ctrl*> priv_prev_block_if_free(block_ctrl *ptr); //!Real expand function implementation - bool priv_expand(void *ptr - ,size_type min_size, size_type preferred_size - ,size_type &received_size); + bool priv_expand(void *ptr, size_type min_size, size_type &prefer_in_recvd_out_size); //!Real expand to both sides implementation void* priv_expand_both_sides(boost::interprocess::allocation_type command - ,size_type min_size - ,size_type preferred_size - ,size_type &received_size + ,size_type min_size, size_type &prefer_in_recvd_out_size ,void *reuse_ptr ,bool only_preferred_backwards); @@ -280,7 +270,8 @@ class simple_seq_fit_impl void priv_mark_new_allocated_block(block_ctrl *block); public: - static const size_type Alignment = ::boost::alignment_of< ::boost::detail::max_align>::value; + static const size_type Alignment = ::boost::container::container_detail::alignment_of + < ::boost::container::container_detail::max_align_t>::value; private: static const size_type BlockCtrlBytes = ipcdetail::ct_rounded_size<sizeof(block_ctrl), Alignment>::value; static const size_type BlockCtrlUnits = BlockCtrlBytes/Alignment; @@ -409,8 +400,9 @@ void simple_seq_fit_impl<MutexFamily, VoidPointer>::shrink_to_fit() void *unique_block = 0; if(!m_header.m_allocated){ BOOST_ASSERT(prev == root); - size_type ignore; - unique_block = priv_allocate(boost::interprocess::allocate_new, 0, 0, ignore).first; + size_type ignore_recvd = 0; + void *ignore_reuse = 0; + unique_block = priv_allocate(boost::interprocess::allocate_new, 0, ignore_recvd, ignore_reuse); if(!unique_block) return; last = ipcdetail::to_raw_pointer(m_header.m_root.m_next); @@ -573,8 +565,9 @@ inline void* simple_seq_fit_impl<MutexFamily, VoidPointer>:: //----------------------- boost::interprocess::scoped_lock<interprocess_mutex> guard(m_header); //----------------------- - size_type ignore; - return priv_allocate(boost::interprocess::allocate_new, nbytes, nbytes, ignore).first; + size_type ignore_recvd = nbytes; + void *ignore_reuse = 0; + return priv_allocate(boost::interprocess::allocate_new, nbytes, ignore_recvd, ignore_reuse); } template<class MutexFamily, class VoidPointer> @@ -590,61 +583,66 @@ inline void* simple_seq_fit_impl<MutexFamily, VoidPointer>:: template<class MutexFamily, class VoidPointer> template<class T> -inline std::pair<T*, bool> simple_seq_fit_impl<MutexFamily, VoidPointer>:: +inline T* simple_seq_fit_impl<MutexFamily, VoidPointer>:: allocation_command (boost::interprocess::allocation_type command, size_type limit_size, - size_type preferred_size,size_type &received_size, - T *reuse_ptr) + size_type &prefer_in_recvd_out_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 % ::boost::alignment_of<T>::value)); - return std::pair<T *, bool>(static_cast<T*>(ret.first), ret.second); + void *raw_reuse = reuse_ptr; + void * const ret = priv_allocation_command + (command, limit_size, prefer_in_recvd_out_size, raw_reuse, sizeof(T)); + BOOST_ASSERT(0 == ((std::size_t)ret % ::boost::container::container_detail::alignment_of<T>::value)); + reuse_ptr = static_cast<T*>(raw_reuse); + return static_cast<T*>(ret); } template<class MutexFamily, class VoidPointer> -inline std::pair<void*, bool> simple_seq_fit_impl<MutexFamily, VoidPointer>:: - raw_allocation_command (boost::interprocess::allocation_type command, size_type limit_objects, - size_type preferred_objects,size_type &received_objects, - void *reuse_ptr, size_type sizeof_object) +inline void* simple_seq_fit_impl<MutexFamily, VoidPointer>:: + raw_allocation_command (boost::interprocess::allocation_type command, size_type limit_objects, + size_type &prefer_in_recvd_out_size, void *&reuse_ptr, size_type sizeof_object) { - if(!sizeof_object) - return std::pair<void *, bool>(static_cast<void*>(0), false); + size_type const preferred_objects = prefer_in_recvd_out_size; + if(!sizeof_object){ + return reuse_ptr = 0, static_cast<void*>(0); + } if(command & boost::interprocess::try_shrink_in_place){ + if(!reuse_ptr) return static_cast<void*>(0); + prefer_in_recvd_out_size = preferred_objects*sizeof_object; 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); + ( this, reuse_ptr, limit_objects*sizeof_object, prefer_in_recvd_out_size); + prefer_in_recvd_out_size /= sizeof_object; + return success ? reuse_ptr : 0; + } + else{ + return priv_allocation_command + (command, limit_objects, prefer_in_recvd_out_size, reuse_ptr, sizeof_object); } - 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>:: +inline void* simple_seq_fit_impl<MutexFamily, VoidPointer>:: priv_allocation_command (boost::interprocess::allocation_type command, size_type limit_size, - size_type preferred_size, size_type &received_size, - void *reuse_ptr, size_type sizeof_object) + size_type &prefer_in_recvd_out_size, void *&reuse_ptr, size_type sizeof_object) { + size_type const preferred_size = prefer_in_recvd_out_size; command &= ~boost::interprocess::expand_bwd; - if(!command) return std::pair<void *, bool>(static_cast<void*>(0), false); + if(!command){ + return reuse_ptr = 0, static_cast<void*>(0); + } - std::pair<void*, bool> ret; size_type max_count = m_header.m_size/sizeof_object; if(limit_size > max_count || preferred_size > max_count){ - ret.first = 0; return ret; + return reuse_ptr = 0, static_cast<void*>(0); } size_type l_size = limit_size*sizeof_object; - size_type p_size = preferred_size*sizeof_object; - size_type r_size; + size_type r_size = preferred_size*sizeof_object; + void *ret = 0; { //----------------------- boost::interprocess::scoped_lock<interprocess_mutex> guard(m_header); //----------------------- - ret = priv_allocate(command, l_size, p_size, r_size, reuse_ptr); + ret = priv_allocate(command, l_size, r_size, reuse_ptr); } - received_size = r_size/sizeof_object; + prefer_in_recvd_out_size = r_size/sizeof_object; return ret; } @@ -663,29 +661,29 @@ template<class MutexFamily, class VoidPointer> void* simple_seq_fit_impl<MutexFamily, VoidPointer>:: priv_expand_both_sides(boost::interprocess::allocation_type command ,size_type min_size - ,size_type preferred_size - ,size_type &received_size + ,size_type &prefer_in_recvd_out_size ,void *reuse_ptr ,bool only_preferred_backwards) { + size_type const preferred_size = prefer_in_recvd_out_size; typedef std::pair<block_ctrl *, block_ctrl *> prev_block_t; block_ctrl *reuse = priv_get_block(reuse_ptr); - received_size = 0; + prefer_in_recvd_out_size = 0; if(this->size(reuse_ptr) > min_size){ - received_size = this->size(reuse_ptr); + prefer_in_recvd_out_size = this->size(reuse_ptr); return reuse_ptr; } if(command & boost::interprocess::expand_fwd){ - if(priv_expand(reuse_ptr, min_size, preferred_size, received_size)) + if(priv_expand(reuse_ptr, min_size, prefer_in_recvd_out_size = preferred_size)) return reuse_ptr; } else{ - received_size = this->size(reuse_ptr); + prefer_in_recvd_out_size = this->size(reuse_ptr); } if(command & boost::interprocess::expand_bwd){ - size_type extra_forward = !received_size ? 0 : received_size + BlockCtrlBytes; + size_type extra_forward = !prefer_in_recvd_out_size ? 0 : prefer_in_recvd_out_size + BlockCtrlBytes; prev_block_t prev_pair = priv_prev_block_if_free(reuse); block_ctrl *prev = prev_pair.second; if(!prev){ @@ -703,7 +701,7 @@ void* simple_seq_fit_impl<MutexFamily, VoidPointer>:: //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)){ + if(!priv_expand(reuse_ptr, prefer_in_recvd_out_size, prefer_in_recvd_out_size)){ BOOST_ASSERT(0); } @@ -717,7 +715,7 @@ void* simple_seq_fit_impl<MutexFamily, VoidPointer>:: BlockCtrlUnits + (needs_backwards + extra_forward)/Alignment; prev->m_size = (prev->get_total_bytes() - needs_backwards)/Alignment - BlockCtrlUnits; - received_size = needs_backwards + extra_forward; + prefer_in_recvd_out_size = needs_backwards + extra_forward; m_header.m_allocated += needs_backwards + BlockCtrlBytes; return priv_get_user_buffer(new_block); } @@ -725,7 +723,7 @@ void* simple_seq_fit_impl<MutexFamily, VoidPointer>:: //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(); + prefer_in_recvd_out_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; @@ -761,23 +759,21 @@ simple_seq_fit_impl<MutexFamily, VoidPointer>:: } template<class MutexFamily, class VoidPointer> -std::pair<void *, bool> simple_seq_fit_impl<MutexFamily, VoidPointer>:: +void * simple_seq_fit_impl<MutexFamily, VoidPointer>:: priv_allocate(boost::interprocess::allocation_type command - ,size_type limit_size - ,size_type preferred_size - ,size_type &received_size - ,void *reuse_ptr) + ,size_type limit_size, size_type &prefer_in_recvd_out_size, void *&reuse_ptr) { + size_type const preferred_size = prefer_in_recvd_out_size; if(command & boost::interprocess::shrink_in_place){ - bool success = - algo_impl_t::shrink(this, reuse_ptr, limit_size, preferred_size, received_size); - return std::pair<void *, bool> ((success ? reuse_ptr : 0), true); + if(!reuse_ptr) return static_cast<void*>(0); + bool success = algo_impl_t::shrink(this, reuse_ptr, limit_size, prefer_in_recvd_out_size); + return success ? reuse_ptr : 0; } - typedef std::pair<void *, bool> return_type; - received_size = 0; + prefer_in_recvd_out_size = 0; - if(limit_size > preferred_size) - return return_type(static_cast<void*>(0), false); + if(limit_size > preferred_size){ + return reuse_ptr = 0, static_cast<void*>(0); + } //Number of units to request (including block_ctrl header) size_type nunits = ipcdetail::get_rounded_size(preferred_size, Alignment)/Alignment + BlockCtrlUnits; @@ -791,19 +787,16 @@ std::pair<void *, bool> simple_seq_fit_impl<MutexFamily, VoidPointer>:: size_type biggest_size = 0; //Expand in place - //reuse_ptr, limit_size, preferred_size, received_size - // if(reuse_ptr && (command & (boost::interprocess::expand_fwd | boost::interprocess::expand_bwd))){ - void *ret = priv_expand_both_sides - (command, limit_size, preferred_size, received_size, reuse_ptr, true); + void *ret = priv_expand_both_sides(command, limit_size, prefer_in_recvd_out_size = preferred_size, reuse_ptr, true); if(ret){ algo_impl_t::assert_alignment(ret); - return return_type(ret, true); + return ret; } } if(command & boost::interprocess::allocate_new){ - received_size = 0; + prefer_in_recvd_out_size = 0; while(block != root){ //Update biggest block pointers if(block->m_size > biggest_size){ @@ -812,10 +805,10 @@ std::pair<void *, bool> simple_seq_fit_impl<MutexFamily, VoidPointer>:: biggest_block = block; } algo_impl_t::assert_alignment(block); - void *addr = this->priv_check_and_allocate(nunits, prev, block, received_size); + void *addr = this->priv_check_and_allocate(nunits, prev, block, prefer_in_recvd_out_size); if(addr){ algo_impl_t::assert_alignment(addr); - return return_type(addr, false); + return reuse_ptr = 0, addr; } //Bad luck, let's check next block prev = block; @@ -826,25 +819,23 @@ std::pair<void *, bool> simple_seq_fit_impl<MutexFamily, VoidPointer>:: //try with this block if(biggest_block){ size_type limit_units = ipcdetail::get_rounded_size(limit_size, Alignment)/Alignment + BlockCtrlUnits; - if(biggest_block->m_size < limit_units) - return return_type(static_cast<void*>(0), false); - - received_size = biggest_block->m_size*Alignment - BlockCtrlUnits; + if(biggest_block->m_size < limit_units){ + return reuse_ptr = 0, static_cast<void*>(0); + } void *ret = this->priv_check_and_allocate - (biggest_block->m_size, prev_biggest_block, biggest_block, received_size); + (biggest_block->m_size, prev_biggest_block, biggest_block, prefer_in_recvd_out_size = biggest_block->m_size*Alignment - BlockCtrlUnits); BOOST_ASSERT(ret != 0); algo_impl_t::assert_alignment(ret); - return return_type(ret, false); + return reuse_ptr = 0, ret; } } //Now try to expand both sides with min size if(reuse_ptr && (command & (boost::interprocess::expand_fwd | boost::interprocess::expand_bwd))){ - return_type ret (priv_expand_both_sides - (command, limit_size, preferred_size, received_size, reuse_ptr, false), true); - algo_impl_t::assert_alignment(ret.first); + void *ret = priv_expand_both_sides (command, limit_size, prefer_in_recvd_out_size = preferred_size, reuse_ptr, false); + algo_impl_t::assert_alignment(ret); return ret; } - return return_type(static_cast<void*>(0), false); + return reuse_ptr = 0, static_cast<void*>(0); } template<class MutexFamily, class VoidPointer> inline @@ -917,11 +908,9 @@ inline template<class MutexFamily, class VoidPointer> inline bool simple_seq_fit_impl<MutexFamily, VoidPointer>:: - priv_expand (void *ptr - ,size_type min_size - ,size_type preferred_size - ,size_type &received_size) + priv_expand (void *ptr, size_type min_size, size_type &received_size) { + size_type preferred_size = received_size; //Obtain the real size of the block block_ctrl *block = reinterpret_cast<block_ctrl*>(priv_get_block(ptr)); size_type old_block_size = block->m_size; diff --git a/boost/interprocess/mem_algo/rbtree_best_fit.hpp b/boost/interprocess/mem_algo/rbtree_best_fit.hpp index fb04889c17..dc4307fe7b 100644 --- a/boost/interprocess/mem_algo/rbtree_best_fit.hpp +++ b/boost/interprocess/mem_algo/rbtree_best_fit.hpp @@ -11,42 +11,44 @@ #ifndef BOOST_INTERPROCESS_MEM_ALGO_RBTREE_BEST_FIT_HPP #define BOOST_INTERPROCESS_MEM_ALGO_RBTREE_BEST_FIT_HPP -#if defined(_MSC_VER) +#ifndef BOOST_CONFIG_HPP +# include <boost/config.hpp> +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) # pragma once #endif #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> -#include <boost/intrusive/pointer_traits.hpp> - +// interprocess +#include <boost/interprocess/containers/allocation_type.hpp> +#include <boost/interprocess/exceptions.hpp> #include <boost/interprocess/interprocess_fwd.hpp> #include <boost/interprocess/mem_algo/detail/mem_algo_common.hpp> -#include <boost/interprocess/containers/allocation_type.hpp> -#include <boost/container/detail/multiallocation_chain.hpp> #include <boost/interprocess/offset_ptr.hpp> -#include <boost/interprocess/exceptions.hpp> -#include <boost/interprocess/detail/utilities.hpp> +#include <boost/interprocess/sync/scoped_lock.hpp> +// interprocess/detail #include <boost/interprocess/detail/min_max.hpp> #include <boost/interprocess/detail/math_functions.hpp> #include <boost/interprocess/detail/type_traits.hpp> -#include <boost/interprocess/sync/scoped_lock.hpp> -#include <boost/type_traits/alignment_of.hpp> -#include <boost/type_traits/type_with_alignment.hpp> -#include <boost/type_traits/make_unsigned.hpp> +#include <boost/interprocess/detail/utilities.hpp> +// container +#include <boost/container/detail/multiallocation_chain.hpp> +// container/detail +#include <boost/container/detail/placement_new.hpp> +// move/detail +#include <boost/move/detail/type_traits.hpp> //make_unsigned, alignment_of +// intrusive #include <boost/intrusive/pointer_traits.hpp> +#include <boost/intrusive/set.hpp> +// other boost #include <boost/assert.hpp> #include <boost/static_assert.hpp> -#include <algorithm> -#include <utility> +// std #include <climits> #include <cstring> -#include <iterator> - -#include <boost/assert.hpp> -#include <new> - -#include <boost/intrusive/set.hpp> //#define BOOST_INTERPROCESS_RBTREE_BEST_FIT_ABI_V1_HPP //to maintain ABI compatible with the original version @@ -92,7 +94,7 @@ class rbtree_best_fit typedef ipcdetail::basic_multiallocation_chain<VoidPointer> multiallocation_chain; typedef typename boost::intrusive::pointer_traits<char_ptr>::difference_type difference_type; - typedef typename boost::make_unsigned<difference_type>::type size_type; + typedef typename boost::container::container_detail::make_unsigned<difference_type>::type size_type; #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) @@ -235,15 +237,12 @@ class rbtree_best_fit bool check_sanity(); template<class T> - std::pair<T *, bool> - allocation_command (boost::interprocess::allocation_type command, size_type limit_size, - size_type preferred_size,size_type &received_size, - T *reuse_ptr = 0); + T * allocation_command (boost::interprocess::allocation_type command, size_type limit_size, + size_type &prefer_in_recvd_out_size, T *&reuse); - std::pair<void *, bool> - raw_allocation_command (boost::interprocess::allocation_type command, size_type limit_object, - size_type preferred_object,size_type &received_object, - void *reuse_ptr = 0, size_type sizeof_object = 1); + void * raw_allocation_command (boost::interprocess::allocation_type command, size_type limit_object, + size_type &prefer_in_recvd_out_size, + void *&reuse_ptr, size_type sizeof_object = 1); //!Returns the size of the buffer previously allocated pointed by ptr size_type size(const void *ptr) const; @@ -260,19 +259,14 @@ class rbtree_best_fit block_ctrl *priv_end_block(); - std::pair<void*, bool> - priv_allocation_command(boost::interprocess::allocation_type command, size_type limit_size, - size_type preferred_size,size_type &received_size, - void *reuse_ptr, size_type sizeof_object); + void* priv_allocation_command(boost::interprocess::allocation_type command, size_type limit_size, + size_type &prefer_in_recvd_out_size, void *&reuse_ptr, size_type sizeof_object); //!Real allocation algorithm with min allocation option - std::pair<void *, bool> priv_allocate(boost::interprocess::allocation_type command - ,size_type limit_size - ,size_type preferred_size - ,size_type &received_size - ,void *reuse_ptr = 0 - ,size_type backwards_multiple = 1); + void * priv_allocate( boost::interprocess::allocation_type command + , size_type limit_size, size_type &prefer_in_recvd_out_size + , void *&reuse_ptr, size_type backwards_multiple = 1); //!Obtains the block control structure of the user buffer static block_ctrl *priv_get_block(const void *ptr); @@ -285,15 +279,12 @@ class rbtree_best_fit static size_type priv_get_total_units(size_type userbytes); //!Real expand function implementation - bool priv_expand(void *ptr - ,const size_type min_size, const size_type preferred_size - ,size_type &received_size); + bool priv_expand(void *ptr, const size_type min_size, size_type &prefer_in_recvd_out_size); //!Real expand to both sides implementation void* priv_expand_both_sides(boost::interprocess::allocation_type command ,size_type min_size - ,size_type preferred_size - ,size_type &received_size + ,size_type &prefer_in_recvd_out_size ,void *reuse_ptr ,bool only_preferred_backwards ,size_type backwards_multiple); @@ -340,7 +331,8 @@ class rbtree_best_fit public: static const size_type Alignment = !MemAlignment - ? size_type(::boost::alignment_of< ::boost::detail::max_align>::value) + ? size_type(::boost::container::container_detail::alignment_of + < ::boost::container::container_detail::max_align_t>::value) : size_type(MemAlignment) ; @@ -348,7 +340,7 @@ class rbtree_best_fit //Due to embedded bits in size, Alignment must be at least 4 BOOST_STATIC_ASSERT((Alignment >= 4)); //Due to rbtree size optimizations, Alignment must have at least pointer alignment - BOOST_STATIC_ASSERT((Alignment >= ::boost::alignment_of<void_pointer>::value)); + BOOST_STATIC_ASSERT((Alignment >= ::boost::container::container_detail::alignment_of<void_pointer>::value)); static const size_type AlignmentMask = (Alignment - 1); static const size_type BlockCtrlBytes = ipcdetail::ct_rounded_size<sizeof(block_ctrl), Alignment>::value; static const size_type BlockCtrlUnits = BlockCtrlBytes/Alignment; @@ -392,7 +384,7 @@ void rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>:: BOOST_ASSERT(segment_size >= (BlockCtrlBytes + EndCtrlBlockBytes)); //Initialize the first big block and the "end" node - block_ctrl *first_big_block = new(addr)block_ctrl; + block_ctrl *first_big_block = ::new(addr, boost_container_new_t())block_ctrl; first_big_block->m_size = segment_size/Alignment - EndCtrlBlockUnits; BOOST_ASSERT(first_big_block->m_size >= BlockCtrlUnits); @@ -540,8 +532,9 @@ void rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::shrink_to_fit() //Check if no memory is allocated between the first and last block if(priv_next_block(first_block) == old_end_block){ //If so check if we can allocate memory - size_type ignore; - unique_buffer = priv_allocate(boost::interprocess::allocate_new, 0, 0, ignore).first; + size_type ignore_recvd = 0; + void *ignore_reuse = 0; + unique_buffer = priv_allocate(boost::interprocess::allocate_new, 0, ignore_recvd, ignore_reuse); //If not, return, we can't shrink if(!unique_buffer) return; @@ -675,9 +668,9 @@ inline void* rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>:: //----------------------- boost::interprocess::scoped_lock<mutex_type> guard(m_header); //----------------------- - size_type ignore; - void * ret = priv_allocate(boost::interprocess::allocate_new, nbytes, nbytes, ignore).first; - return ret; + size_type ignore_recvd = nbytes; + void *ignore_reuse = 0; + return priv_allocate(boost::interprocess::allocate_new, nbytes, ignore_recvd, ignore_reuse); } template<class MutexFamily, class VoidPointer, std::size_t MemAlignment> @@ -692,48 +685,51 @@ inline void* rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>:: template<class MutexFamily, class VoidPointer, std::size_t MemAlignment> template<class T> -inline std::pair<T*, bool> rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>:: +inline T* rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>:: allocation_command (boost::interprocess::allocation_type command, size_type limit_size, - size_type preferred_size,size_type &received_size, - T *reuse_ptr) + size_type &prefer_in_recvd_out_size, T *&reuse) { - 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 % ::boost::alignment_of<T>::value)); - return std::pair<T *, bool>(static_cast<T*>(ret.first), ret.second); + void* raw_reuse = reuse; + void* const ret = priv_allocation_command(command, limit_size, prefer_in_recvd_out_size, raw_reuse, sizeof(T)); + reuse = static_cast<T*>(raw_reuse); + BOOST_ASSERT(0 == ((std::size_t)ret % ::boost::container::container_detail::alignment_of<T>::value)); + return static_cast<T*>(ret); } template<class MutexFamily, class VoidPointer, std::size_t MemAlignment> -inline std::pair<void*, bool> rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>:: +inline void* rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>:: raw_allocation_command (boost::interprocess::allocation_type command, size_type limit_objects, - size_type preferred_objects,size_type &received_objects, - void *reuse_ptr, size_type sizeof_object) + size_type &prefer_in_recvd_out_objects, void *&reuse_ptr, size_type sizeof_object) { + size_type const preferred_objects = prefer_in_recvd_out_objects; if(!sizeof_object) - return std::pair<void *, bool>(static_cast<void*>(0), false); + return reuse_ptr = 0, static_cast<void*>(0); if(command & boost::interprocess::try_shrink_in_place){ - bool success = algo_impl_t::try_shrink + if(!reuse_ptr) return static_cast<void*>(0); + const 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); + , prefer_in_recvd_out_objects = preferred_objects*sizeof_object); + prefer_in_recvd_out_objects /= sizeof_object; + return success ? reuse_ptr : 0; + } + else{ + return priv_allocation_command + (command, limit_objects, prefer_in_recvd_out_objects, reuse_ptr, sizeof_object); } - return priv_allocation_command - (command, limit_objects, preferred_objects, received_objects, reuse_ptr, sizeof_object); } template<class MutexFamily, class VoidPointer, std::size_t MemAlignment> -inline std::pair<void*, bool> rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>:: +inline void* rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>:: priv_allocation_command (boost::interprocess::allocation_type command, size_type limit_size, - size_type preferred_size,size_type &received_size, - void *reuse_ptr, size_type sizeof_object) + size_type &prefer_in_recvd_out_size, + void *&reuse_ptr, size_type sizeof_object) { - std::pair<void*, bool> ret; - size_type max_count = m_header.m_size/sizeof_object; + void* ret; + size_type const preferred_size = prefer_in_recvd_out_size; + size_type const max_count = m_header.m_size/sizeof_object; if(limit_size > max_count || preferred_size > max_count){ - ret.first = 0; return ret; + return reuse_ptr = 0, static_cast<void*>(0); } size_type l_size = limit_size*sizeof_object; size_type p_size = preferred_size*sizeof_object; @@ -742,9 +738,9 @@ inline std::pair<void*, bool> rbtree_best_fit<MutexFamily, VoidPointer, MemAlign //----------------------- boost::interprocess::scoped_lock<mutex_type> guard(m_header); //----------------------- - ret = priv_allocate(command, l_size, p_size, r_size, reuse_ptr, sizeof_object); + ret = priv_allocate(command, l_size, r_size = p_size, reuse_ptr, sizeof_object); } - received_size = r_size/sizeof_object; + prefer_in_recvd_out_size = r_size/sizeof_object; return ret; } @@ -788,20 +784,20 @@ template<class MutexFamily, class VoidPointer, std::size_t MemAlignment> void* rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>:: priv_expand_both_sides(boost::interprocess::allocation_type command ,size_type min_size - ,size_type preferred_size - ,size_type &received_size + ,size_type &prefer_in_recvd_out_size ,void *reuse_ptr ,bool only_preferred_backwards ,size_type backwards_multiple) { + size_type const preferred_size = prefer_in_recvd_out_size; algo_impl_t::assert_alignment(reuse_ptr); if(command & boost::interprocess::expand_fwd){ - if(priv_expand(reuse_ptr, min_size, preferred_size, received_size)) + if(priv_expand(reuse_ptr, min_size, prefer_in_recvd_out_size = preferred_size)) return reuse_ptr; } else{ - received_size = this->size(reuse_ptr); - if(received_size >= preferred_size || received_size >= min_size) + prefer_in_recvd_out_size = this->size(reuse_ptr); + if(prefer_in_recvd_out_size >= preferred_size || prefer_in_recvd_out_size >= min_size) return reuse_ptr; } @@ -835,7 +831,7 @@ void* rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>:: size_type lcm; if(!algo_impl_t::calculate_lcm_and_needs_backwards_lcmed ( backwards_multiple - , received_size + , prefer_in_recvd_out_size , only_preferred_backwards ? preferred_size : min_size , lcm, needs_backwards_aligned)){ return 0; @@ -846,10 +842,10 @@ void* rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>:: //Now take all next space. This will succeed if(command & boost::interprocess::expand_fwd){ size_type received_size2; - if(!priv_expand(reuse_ptr, received_size, received_size, received_size2)){ + if(!priv_expand(reuse_ptr, prefer_in_recvd_out_size, received_size2 = prefer_in_recvd_out_size)){ BOOST_ASSERT(0); } - BOOST_ASSERT(received_size == received_size2); + BOOST_ASSERT(prefer_in_recvd_out_size == received_size2); } //We need a minimum size to split the previous one if(prev_block->m_size >= (needs_backwards_aligned/Alignment + BlockCtrlUnits)){ @@ -858,7 +854,7 @@ void* rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>:: //Free old previous buffer new_block->m_size = - AllocatedCtrlUnits + (needs_backwards_aligned + (received_size - UsableByPreviousChunk))/Alignment; + AllocatedCtrlUnits + (needs_backwards_aligned + (prefer_in_recvd_out_size - UsableByPreviousChunk))/Alignment; BOOST_ASSERT(new_block->m_size >= BlockCtrlUnits); priv_mark_as_allocated_block(new_block); @@ -880,7 +876,7 @@ void* rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>:: } } - received_size = needs_backwards_aligned + received_size; + prefer_in_recvd_out_size = needs_backwards_aligned + prefer_in_recvd_out_size; m_header.m_allocated += needs_backwards_aligned; //Check alignment @@ -903,7 +899,7 @@ void* rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>:: //Just merge the whole previous block //prev_block->m_size*Alignment is multiple of lcm (and backwards_multiple) - received_size = received_size + (size_type)prev_block->m_size*Alignment; + prefer_in_recvd_out_size = prefer_in_recvd_out_size + (size_type)prev_block->m_size*Alignment; m_header.m_allocated += (size_type)prev_block->m_size*Alignment; //Now update sizes @@ -937,28 +933,25 @@ inline void rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>:: } template<class MutexFamily, class VoidPointer, std::size_t MemAlignment> -std::pair<void *, bool> rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>:: +void * rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>:: priv_allocate(boost::interprocess::allocation_type command ,size_type limit_size - ,size_type preferred_size - ,size_type &received_size - ,void *reuse_ptr + ,size_type &prefer_in_recvd_out_size + ,void *&reuse_ptr ,size_type backwards_multiple) { - //Remove me. Forbid backwards allocation - //command &= (~boost::interprocess::expand_bwd); - + size_type const preferred_size = prefer_in_recvd_out_size; if(command & boost::interprocess::shrink_in_place){ + if(!reuse_ptr) return static_cast<void*>(0); bool success = - algo_impl_t::shrink(this, reuse_ptr, limit_size, preferred_size, received_size); - return std::pair<void *, bool> ((success ? reuse_ptr : 0), true); + algo_impl_t::shrink(this, reuse_ptr, limit_size, prefer_in_recvd_out_size = preferred_size); + return success ? reuse_ptr : 0; } - typedef std::pair<void *, bool> return_type; - received_size = 0; + prefer_in_recvd_out_size = 0; if(limit_size > preferred_size) - return return_type(static_cast<void*>(0), false); + return reuse_ptr = 0, static_cast<void*>(0); //Number of units to request (including block_ctrl header) size_type preferred_units = priv_get_total_units(preferred_size); @@ -967,11 +960,12 @@ std::pair<void *, bool> rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>: size_type limit_units = priv_get_total_units(limit_size); //Expand in place + prefer_in_recvd_out_size = preferred_size; if(reuse_ptr && (command & (boost::interprocess::expand_fwd | boost::interprocess::expand_bwd))){ void *ret = priv_expand_both_sides - (command, limit_size, preferred_size, received_size, reuse_ptr, true, backwards_multiple); + (command, limit_size, prefer_in_recvd_out_size, reuse_ptr, true, backwards_multiple); if(ret) - return return_type(ret, true); + return ret; } if(command & boost::interprocess::allocate_new){ @@ -979,25 +973,24 @@ std::pair<void *, bool> rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>: imultiset_iterator it(m_header.m_imultiset.lower_bound(preferred_units, comp)); if(it != m_header.m_imultiset.end()){ - return return_type(this->priv_check_and_allocate - (preferred_units, ipcdetail::to_raw_pointer(&*it), received_size), false); + return reuse_ptr = 0, this->priv_check_and_allocate + (preferred_units, ipcdetail::to_raw_pointer(&*it), prefer_in_recvd_out_size); } if(it != m_header.m_imultiset.begin()&& (--it)->m_size >= limit_units){ - return return_type(this->priv_check_and_allocate - (it->m_size, ipcdetail::to_raw_pointer(&*it), received_size), false); + return reuse_ptr = 0, this->priv_check_and_allocate + (it->m_size, ipcdetail::to_raw_pointer(&*it), prefer_in_recvd_out_size); } } //Now try to expand both sides with min size if(reuse_ptr && (command & (boost::interprocess::expand_fwd | boost::interprocess::expand_bwd))){ - return return_type(priv_expand_both_sides - (command, limit_size, preferred_size, received_size, reuse_ptr, false, backwards_multiple), true); + return priv_expand_both_sides + (command, limit_size, prefer_in_recvd_out_size = preferred_size, reuse_ptr, false, backwards_multiple); } - - return return_type(static_cast<void*>(0), false); + return reuse_ptr = 0, static_cast<void*>(0); } template<class MutexFamily, class VoidPointer, std::size_t MemAlignment> @@ -1030,11 +1023,9 @@ rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>:: template<class MutexFamily, class VoidPointer, std::size_t MemAlignment> bool rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>:: - priv_expand (void *ptr - ,const size_type min_size - ,const size_type preferred_size - ,size_type &received_size) + priv_expand (void *ptr, const size_type min_size, size_type &prefer_in_recvd_out_size) { + size_type const preferred_size = prefer_in_recvd_out_size; //Obtain the real size of the block block_ctrl *block = priv_get_block(ptr); size_type old_block_units = block->m_size; @@ -1043,8 +1034,8 @@ bool rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>:: BOOST_ASSERT(priv_is_allocated_block(block)); //Put this to a safe value - received_size = (old_block_units - AllocatedCtrlUnits)*Alignment + UsableByPreviousChunk; - if(received_size >= preferred_size || received_size >= min_size) + prefer_in_recvd_out_size = (old_block_units - AllocatedCtrlUnits)*Alignment + UsableByPreviousChunk; + if(prefer_in_recvd_out_size >= preferred_size || prefer_in_recvd_out_size >= min_size) return true; //Now translate it to Alignment units @@ -1057,7 +1048,7 @@ bool rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>:: block_ctrl *next_block; if(priv_is_allocated_block(next_block = priv_next_block(block))){ - return received_size >= min_size ? true : false; + return prefer_in_recvd_out_size >= min_size; } algo_impl_t::assert_alignment(next_block); @@ -1068,7 +1059,7 @@ bool rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>:: const size_type merged_user_units = merged_units - AllocatedCtrlUnits; if(merged_user_units < min_user_units){ - received_size = merged_units*Alignment - UsableByPreviousChunk; + prefer_in_recvd_out_size = merged_units*Alignment - UsableByPreviousChunk; return false; } @@ -1103,8 +1094,8 @@ bool rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>:: m_header.m_imultiset.erase(old_next_block_it); } //This is the remaining block - block_ctrl *rem_block = new(reinterpret_cast<block_ctrl*> - (reinterpret_cast<char*>(block) + intended_units*Alignment))block_ctrl; + block_ctrl *rem_block = ::new(reinterpret_cast<block_ctrl*> + (reinterpret_cast<char*>(block) + intended_units*Alignment), boost_container_new_t())block_ctrl; rem_block->m_size = rem_units; algo_impl_t::assert_alignment(rem_block); BOOST_ASSERT(rem_block->m_size >= BlockCtrlUnits); @@ -1132,7 +1123,7 @@ bool rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>:: m_header.m_allocated += (merged_units - old_block_units)*Alignment; } priv_mark_as_allocated_block(block); - received_size = ((size_type)block->m_size - AllocatedCtrlUnits)*Alignment + UsableByPreviousChunk; + prefer_in_recvd_out_size = ((size_type)block->m_size - AllocatedCtrlUnits)*Alignment + UsableByPreviousChunk; return true; } @@ -1267,8 +1258,8 @@ void* rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::priv_check_and_al BOOST_ASSERT(block->m_size >= BlockCtrlUnits); //This is the remaining block - block_ctrl *rem_block = new(reinterpret_cast<block_ctrl*> - (reinterpret_cast<char*>(block) + Alignment*nunits))block_ctrl; + block_ctrl *rem_block = ::new(reinterpret_cast<block_ctrl*> + (reinterpret_cast<char*>(block) + Alignment*nunits), boost_container_new_t())block_ctrl; algo_impl_t::assert_alignment(rem_block); rem_block->m_size = block_old_size - nunits; BOOST_ASSERT(rem_block->m_size >= BlockCtrlUnits); diff --git a/boost/interprocess/mem_algo/simple_seq_fit.hpp b/boost/interprocess/mem_algo/simple_seq_fit.hpp index aaa5d37497..69813f41bc 100644 --- a/boost/interprocess/mem_algo/simple_seq_fit.hpp +++ b/boost/interprocess/mem_algo/simple_seq_fit.hpp @@ -11,7 +11,11 @@ #ifndef BOOST_INTERPROCESS_SIMPLE_SEQ_FIT_HPP #define BOOST_INTERPROCESS_SIMPLE_SEQ_FIT_HPP -#if defined(_MSC_VER) +#ifndef BOOST_CONFIG_HPP +# include <boost/config.hpp> +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) # pragma once #endif |