stabilize build system: depends, installer, boost/bdb fixes, cross targets groundwork
This commit is contained in:
@@ -0,0 +1,349 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2013. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_ADAPTIVE_POOL_HPP
|
||||
#define BOOST_CONTAINER_ADAPTIVE_POOL_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/detail/config_begin.hpp>
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
#include <boost/container/container_fwd.hpp>
|
||||
#include <boost/container/detail/version_type.hpp>
|
||||
#include <boost/container/throw_exception.hpp>
|
||||
#include <boost/container/detail/adaptive_node_pool.hpp>
|
||||
#include <boost/container/detail/multiallocation_chain.hpp>
|
||||
#include <boost/container/detail/mpl.hpp>
|
||||
#include <boost/container/detail/dlmalloc.hpp>
|
||||
#include <boost/container/detail/singleton.hpp>
|
||||
#include <boost/container/detail/placement_new.hpp>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/move/utility_core.hpp>
|
||||
#include <cstddef>
|
||||
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
|
||||
//!An STL node allocator that uses a modified DLMalloc as memory
|
||||
//!source.
|
||||
//!
|
||||
//!This node allocator shares a segregated storage between all instances
|
||||
//!of adaptive_pool with equal sizeof(T).
|
||||
//!
|
||||
//!NodesPerBlock is the number of nodes allocated at once when the allocator
|
||||
//!needs runs out of nodes. MaxFreeBlocks is the maximum number of totally free blocks
|
||||
//!that the adaptive node pool will hold. The rest of the totally free blocks will be
|
||||
//!deallocated to the memory manager.
|
||||
//!
|
||||
//!OverheadPercent is the (approximated) maximum size overhead (1-20%) of the allocator:
|
||||
//!(memory usable for nodes / total memory allocated from the memory allocator)
|
||||
template < class T
|
||||
, std::size_t NodesPerBlock BOOST_CONTAINER_DOCONLY(= ADP_nodes_per_block)
|
||||
, std::size_t MaxFreeBlocks BOOST_CONTAINER_DOCONLY(= ADP_max_free_blocks)
|
||||
, std::size_t OverheadPercent BOOST_CONTAINER_DOCONLY(= ADP_overhead_percent)
|
||||
BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I unsigned Version)
|
||||
>
|
||||
class adaptive_pool
|
||||
{
|
||||
//!If Version is 1, the allocator is a STL conforming allocator. If Version is 2,
|
||||
//!the allocator offers advanced expand in place and burst allocation capabilities.
|
||||
public:
|
||||
typedef unsigned int allocation_type;
|
||||
typedef adaptive_pool
|
||||
<T, NodesPerBlock, MaxFreeBlocks, OverheadPercent
|
||||
BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I Version)
|
||||
> self_t;
|
||||
|
||||
static const std::size_t nodes_per_block = NodesPerBlock;
|
||||
static const std::size_t max_free_blocks = MaxFreeBlocks;
|
||||
static const std::size_t overhead_percent = OverheadPercent;
|
||||
static const std::size_t real_nodes_per_block = NodesPerBlock;
|
||||
|
||||
BOOST_CONTAINER_DOCIGN(BOOST_STATIC_ASSERT((Version <=2)));
|
||||
|
||||
public:
|
||||
//-------
|
||||
typedef T value_type;
|
||||
typedef T * pointer;
|
||||
typedef const T * const_pointer;
|
||||
typedef typename ::boost::container::
|
||||
container_detail::unvoid_ref<T>::type reference;
|
||||
typedef typename ::boost::container::
|
||||
container_detail::unvoid_ref<const T>::type const_reference;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
|
||||
typedef boost::container::container_detail::
|
||||
version_type<self_t, Version> version;
|
||||
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
typedef boost::container::container_detail::
|
||||
basic_multiallocation_chain<void*> multiallocation_chain_void;
|
||||
typedef boost::container::container_detail::
|
||||
transform_multiallocation_chain
|
||||
<multiallocation_chain_void, T> multiallocation_chain;
|
||||
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
//!Obtains adaptive_pool from
|
||||
//!adaptive_pool
|
||||
template<class T2>
|
||||
struct rebind
|
||||
{
|
||||
typedef adaptive_pool
|
||||
< T2
|
||||
, NodesPerBlock
|
||||
, MaxFreeBlocks
|
||||
, OverheadPercent
|
||||
BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I Version)
|
||||
> other;
|
||||
};
|
||||
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
private:
|
||||
//!Not assignable from related adaptive_pool
|
||||
template<class T2, unsigned Version2, std::size_t N2, std::size_t F2>
|
||||
adaptive_pool& operator=
|
||||
(const adaptive_pool<T2, Version2, N2, F2>&);
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
public:
|
||||
//!Default constructor
|
||||
adaptive_pool() BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{}
|
||||
|
||||
//!Copy constructor from other adaptive_pool.
|
||||
adaptive_pool(const adaptive_pool &) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{}
|
||||
|
||||
//!Copy constructor from related adaptive_pool.
|
||||
template<class T2>
|
||||
adaptive_pool
|
||||
(const adaptive_pool<T2, NodesPerBlock, MaxFreeBlocks, OverheadPercent
|
||||
BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I Version)> &) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{}
|
||||
|
||||
//!Destructor
|
||||
~adaptive_pool() BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{}
|
||||
|
||||
//!Returns the number of elements that could be allocated.
|
||||
//!Never throws
|
||||
size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return size_type(-1)/sizeof(T); }
|
||||
|
||||
//!Allocate memory for an array of count elements.
|
||||
//!Throws std::bad_alloc if there is no enough memory
|
||||
pointer allocate(size_type count, const void * = 0)
|
||||
{
|
||||
if(BOOST_UNLIKELY(count > this->max_size()))
|
||||
boost::container::throw_bad_alloc();
|
||||
|
||||
if(Version == 1 && count == 1){
|
||||
typedef typename container_detail::shared_adaptive_node_pool
|
||||
<sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> shared_pool_t;
|
||||
typedef container_detail::singleton_default<shared_pool_t> singleton_t;
|
||||
return pointer(static_cast<T*>(singleton_t::instance().allocate_node()));
|
||||
}
|
||||
else{
|
||||
return static_cast<pointer>(dlmalloc_malloc(count*sizeof(T)));
|
||||
}
|
||||
}
|
||||
|
||||
//!Deallocate allocated memory.
|
||||
//!Never throws
|
||||
void deallocate(const pointer &ptr, size_type count) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{
|
||||
(void)count;
|
||||
if(Version == 1 && count == 1){
|
||||
typedef container_detail::shared_adaptive_node_pool
|
||||
<sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> shared_pool_t;
|
||||
typedef container_detail::singleton_default<shared_pool_t> singleton_t;
|
||||
singleton_t::instance().deallocate_node(ptr);
|
||||
}
|
||||
else{
|
||||
dlmalloc_free(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
pointer allocation_command(allocation_type command,
|
||||
size_type limit_size,
|
||||
size_type &prefer_in_recvd_out_size,
|
||||
pointer &reuse)
|
||||
{
|
||||
pointer ret = this->priv_allocation_command(command, limit_size, prefer_in_recvd_out_size, reuse);
|
||||
if(BOOST_UNLIKELY(!ret && !(command & BOOST_CONTAINER_NOTHROW_ALLOCATION)))
|
||||
boost::container::throw_bad_alloc();
|
||||
return ret;
|
||||
}
|
||||
|
||||
//!Returns maximum the number of objects the previously allocated memory
|
||||
//!pointed by p can hold.
|
||||
size_type size(pointer p) const BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return dlmalloc_size(p); }
|
||||
|
||||
//!Allocates just one object. Memory allocated with this function
|
||||
//!must be deallocated only with deallocate_one().
|
||||
//!Throws bad_alloc if there is no enough memory
|
||||
pointer allocate_one()
|
||||
{
|
||||
typedef container_detail::shared_adaptive_node_pool
|
||||
<sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> shared_pool_t;
|
||||
typedef container_detail::singleton_default<shared_pool_t> singleton_t;
|
||||
return (pointer)singleton_t::instance().allocate_node();
|
||||
}
|
||||
|
||||
//!Allocates many elements of size == 1.
|
||||
//!Elements must be individually deallocated with deallocate_one()
|
||||
void allocate_individual(std::size_t num_elements, multiallocation_chain &chain)
|
||||
{
|
||||
typedef container_detail::shared_adaptive_node_pool
|
||||
<sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> shared_pool_t;
|
||||
typedef container_detail::singleton_default<shared_pool_t> singleton_t;
|
||||
singleton_t::instance().allocate_nodes(num_elements, static_cast<typename shared_pool_t::multiallocation_chain&>(chain));
|
||||
//typename shared_pool_t::multiallocation_chain ch;
|
||||
//singleton_t::instance().allocate_nodes(num_elements, ch);
|
||||
//chain.incorporate_after
|
||||
//(chain.before_begin(), (T*)&*ch.begin(), (T*)&*ch.last(), ch.size());
|
||||
}
|
||||
|
||||
//!Deallocates memory previously allocated with allocate_one().
|
||||
//!You should never use deallocate_one to deallocate memory allocated
|
||||
//!with other functions different from allocate_one(). Never throws
|
||||
void deallocate_one(pointer p) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{
|
||||
typedef container_detail::shared_adaptive_node_pool
|
||||
<sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> shared_pool_t;
|
||||
typedef container_detail::singleton_default<shared_pool_t> singleton_t;
|
||||
singleton_t::instance().deallocate_node(p);
|
||||
}
|
||||
|
||||
void deallocate_individual(multiallocation_chain &chain) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{
|
||||
typedef container_detail::shared_adaptive_node_pool
|
||||
<sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> shared_pool_t;
|
||||
typedef container_detail::singleton_default<shared_pool_t> singleton_t;
|
||||
//typename shared_pool_t::multiallocation_chain ch(&*chain.begin(), &*chain.last(), chain.size());
|
||||
//singleton_t::instance().deallocate_nodes(ch);
|
||||
singleton_t::instance().deallocate_nodes(chain);
|
||||
}
|
||||
|
||||
//!Allocates many elements of size elem_size.
|
||||
//!Elements must be individually deallocated with deallocate()
|
||||
void allocate_many(size_type elem_size, std::size_t n_elements, multiallocation_chain &chain)
|
||||
{
|
||||
BOOST_STATIC_ASSERT(( Version > 1 ));/*
|
||||
dlmalloc_memchain ch;
|
||||
BOOST_CONTAINER_MEMCHAIN_INIT(&ch);
|
||||
if(BOOST_UNLIKELY(!dlmalloc_multialloc_nodes(n_elements, elem_size*sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &ch))){
|
||||
boost::container::throw_bad_alloc();
|
||||
}
|
||||
chain.incorporate_after(chain.before_begin()
|
||||
,(T*)BOOST_CONTAINER_MEMCHAIN_FIRSTMEM(&ch)
|
||||
,(T*)BOOST_CONTAINER_MEMCHAIN_LASTMEM(&ch)
|
||||
,BOOST_CONTAINER_MEMCHAIN_SIZE(&ch) );*/
|
||||
if(BOOST_UNLIKELY(!dlmalloc_multialloc_nodes
|
||||
(n_elements, elem_size*sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, reinterpret_cast<dlmalloc_memchain *>(&chain)))){
|
||||
boost::container::throw_bad_alloc();
|
||||
}
|
||||
}
|
||||
|
||||
//!Allocates n_elements elements, each one of size elem_sizes[i]
|
||||
//!Elements must be individually deallocated with deallocate()
|
||||
void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain)
|
||||
{
|
||||
BOOST_STATIC_ASSERT(( Version > 1 ));/*
|
||||
dlmalloc_memchain ch;
|
||||
BOOST_CONTAINER_MEMCHAIN_INIT(&ch);
|
||||
if(BOOST_UNLIKELY(!dlmalloc_multialloc_arrays(n_elements, elem_sizes, sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &ch))){
|
||||
boost::container::throw_bad_alloc();
|
||||
}
|
||||
chain.incorporate_after(chain.before_begin()
|
||||
,(T*)BOOST_CONTAINER_MEMCHAIN_FIRSTMEM(&ch)
|
||||
,(T*)BOOST_CONTAINER_MEMCHAIN_LASTMEM(&ch)
|
||||
,BOOST_CONTAINER_MEMCHAIN_SIZE(&ch) );*/
|
||||
if(BOOST_UNLIKELY(!dlmalloc_multialloc_arrays
|
||||
(n_elements, elem_sizes, sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, reinterpret_cast<dlmalloc_memchain *>(&chain)))){
|
||||
boost::container::throw_bad_alloc();
|
||||
}
|
||||
}
|
||||
|
||||
void deallocate_many(multiallocation_chain &chain) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{/*
|
||||
dlmalloc_memchain ch;
|
||||
void *beg(&*chain.begin()), *last(&*chain.last());
|
||||
size_t size(chain.size());
|
||||
BOOST_CONTAINER_MEMCHAIN_INIT_FROM(&ch, beg, last, size);
|
||||
dlmalloc_multidealloc(&ch);*/
|
||||
dlmalloc_multidealloc(reinterpret_cast<dlmalloc_memchain *>(&chain));
|
||||
}
|
||||
|
||||
//!Deallocates all free blocks of the pool
|
||||
static void deallocate_free_blocks() BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{
|
||||
typedef container_detail::shared_adaptive_node_pool
|
||||
<sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> shared_pool_t;
|
||||
typedef container_detail::singleton_default<shared_pool_t> singleton_t;
|
||||
singleton_t::instance().deallocate_free_blocks();
|
||||
}
|
||||
|
||||
//!Swaps allocators. Does not throw. If each allocator is placed in a
|
||||
//!different memory segment, the result is undefined.
|
||||
friend void swap(adaptive_pool &, adaptive_pool &) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{}
|
||||
|
||||
//!An allocator always compares to true, as memory allocated with one
|
||||
//!instance can be deallocated by another instance
|
||||
friend bool operator==(const adaptive_pool &, const adaptive_pool &) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return true; }
|
||||
|
||||
//!An allocator always compares to false, as memory allocated with one
|
||||
//!instance can be deallocated by another instance
|
||||
friend bool operator!=(const adaptive_pool &, const adaptive_pool &) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return false; }
|
||||
|
||||
private:
|
||||
pointer priv_allocation_command
|
||||
(allocation_type command, std::size_t limit_size
|
||||
,size_type &prefer_in_recvd_out_size, pointer &reuse_ptr)
|
||||
{
|
||||
std::size_t const preferred_size = prefer_in_recvd_out_size;
|
||||
dlmalloc_command_ret_t ret = {0 , 0};
|
||||
if(BOOST_UNLIKELY(limit_size > this->max_size() || preferred_size > this->max_size())){
|
||||
return pointer();
|
||||
}
|
||||
std::size_t l_size = limit_size*sizeof(T);
|
||||
std::size_t p_size = preferred_size*sizeof(T);
|
||||
std::size_t r_size;
|
||||
{
|
||||
void* reuse_ptr_void = reuse_ptr;
|
||||
ret = dlmalloc_allocation_command(command, sizeof(T), l_size, p_size, &r_size, reuse_ptr_void);
|
||||
reuse_ptr = ret.second ? static_cast<T*>(reuse_ptr_void) : 0;
|
||||
}
|
||||
prefer_in_recvd_out_size = r_size/sizeof(T);
|
||||
return (pointer)ret.first;
|
||||
}
|
||||
};
|
||||
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_ADAPTIVE_POOL_HPP
|
||||
@@ -0,0 +1,368 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2007-2013. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_ALLOCATOR_HPP
|
||||
#define BOOST_CONTAINER_ALLOCATOR_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/detail/config_begin.hpp>
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
#include <boost/container/container_fwd.hpp>
|
||||
#include <boost/container/detail/version_type.hpp>
|
||||
#include <boost/container/throw_exception.hpp>
|
||||
#include <boost/container/detail/dlmalloc.hpp>
|
||||
#include <boost/container/detail/multiallocation_chain.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <cstddef>
|
||||
#include <cassert>
|
||||
|
||||
//!\file
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
template<unsigned Version, unsigned int AllocationDisableMask>
|
||||
class allocator<void, Version, AllocationDisableMask>
|
||||
{
|
||||
typedef allocator<void, Version, AllocationDisableMask> self_t;
|
||||
public:
|
||||
typedef void value_type;
|
||||
typedef void * pointer;
|
||||
typedef const void* const_pointer;
|
||||
typedef int & reference;
|
||||
typedef const int & const_reference;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef boost::container::container_detail::
|
||||
version_type<self_t, Version> version;
|
||||
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
typedef boost::container::container_detail::
|
||||
basic_multiallocation_chain<void*> multiallocation_chain;
|
||||
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
//!Obtains an allocator that allocates
|
||||
//!objects of type T2
|
||||
template<class T2>
|
||||
struct rebind
|
||||
{
|
||||
typedef allocator< T2
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
, Version, AllocationDisableMask
|
||||
#endif
|
||||
> other;
|
||||
};
|
||||
|
||||
//!Default constructor
|
||||
//!Never throws
|
||||
allocator()
|
||||
{}
|
||||
|
||||
//!Constructor from other allocator.
|
||||
//!Never throws
|
||||
allocator(const allocator &)
|
||||
{}
|
||||
|
||||
//!Constructor from related allocator.
|
||||
//!Never throws
|
||||
template<class T2>
|
||||
allocator(const allocator<T2, Version, AllocationDisableMask> &)
|
||||
{}
|
||||
};
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
//! This class is an extended STL-compatible that offers advanced allocation mechanism
|
||||
//!(in-place expansion, shrinking, burst-allocation...)
|
||||
//!
|
||||
//! This allocator is a wrapper around a modified DLmalloc.
|
||||
//! If Version is 1, the allocator is a STL conforming allocator. If Version is 2,
|
||||
//! the allocator offers advanced expand in place and burst allocation capabilities.
|
||||
//!
|
||||
//! AllocationDisableMask works only if Version is 2 and it can be an inclusive OR
|
||||
//! of allocation types the user wants to disable.
|
||||
template< class T
|
||||
, unsigned Version BOOST_CONTAINER_DOCONLY(=2)
|
||||
, unsigned int AllocationDisableMask BOOST_CONTAINER_DOCONLY(=0)>
|
||||
class allocator
|
||||
{
|
||||
typedef unsigned int allocation_type;
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
private:
|
||||
|
||||
//Self type
|
||||
typedef allocator<T, Version, AllocationDisableMask> self_t;
|
||||
|
||||
//Not assignable from related allocator
|
||||
template<class T2, unsigned int Version2, unsigned int AllocationDisableMask2>
|
||||
allocator& operator=(const allocator<T2, Version2, AllocationDisableMask2>&);
|
||||
|
||||
static const unsigned int ForbiddenMask =
|
||||
BOOST_CONTAINER_ALLOCATE_NEW | BOOST_CONTAINER_EXPAND_BWD | BOOST_CONTAINER_EXPAND_FWD ;
|
||||
|
||||
//The mask can't disable all the allocation types
|
||||
BOOST_STATIC_ASSERT(( (AllocationDisableMask & ForbiddenMask) != ForbiddenMask ));
|
||||
|
||||
//The mask is only valid for version 2 allocators
|
||||
BOOST_STATIC_ASSERT(( Version != 1 || (AllocationDisableMask == 0) ));
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef T * pointer;
|
||||
typedef const T * const_pointer;
|
||||
typedef T & reference;
|
||||
typedef const T & const_reference;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
|
||||
typedef boost::container::container_detail::
|
||||
version_type<self_t, Version> version;
|
||||
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
typedef boost::container::container_detail::
|
||||
basic_multiallocation_chain<void*> void_multiallocation_chain;
|
||||
|
||||
typedef boost::container::container_detail::
|
||||
transform_multiallocation_chain
|
||||
<void_multiallocation_chain, T> multiallocation_chain;
|
||||
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
//!Obtains an allocator that allocates
|
||||
//!objects of type T2
|
||||
template<class T2>
|
||||
struct rebind
|
||||
{
|
||||
typedef allocator<T2, Version, AllocationDisableMask> other;
|
||||
};
|
||||
|
||||
//!Default constructor
|
||||
//!Never throws
|
||||
allocator() BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{}
|
||||
|
||||
//!Constructor from other allocator.
|
||||
//!Never throws
|
||||
allocator(const allocator &) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{}
|
||||
|
||||
//!Constructor from related allocator.
|
||||
//!Never throws
|
||||
template<class T2>
|
||||
allocator(const allocator<T2
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
, Version, AllocationDisableMask
|
||||
#endif
|
||||
> &) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{}
|
||||
|
||||
//!Allocates memory for an array of count elements.
|
||||
//!Throws std::bad_alloc if there is no enough memory
|
||||
//!If Version is 2, this allocated memory can only be deallocated
|
||||
//!with deallocate() or (for Version == 2) deallocate_many()
|
||||
pointer allocate(size_type count, const void * hint= 0)
|
||||
{
|
||||
(void)hint;
|
||||
if(count > this->max_size())
|
||||
boost::container::throw_bad_alloc();
|
||||
void *ret = dlmalloc_malloc(count*sizeof(T));
|
||||
if(!ret)
|
||||
boost::container::throw_bad_alloc();
|
||||
return static_cast<pointer>(ret);
|
||||
}
|
||||
|
||||
//!Deallocates previously allocated memory.
|
||||
//!Never throws
|
||||
void deallocate(pointer ptr, size_type) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ dlmalloc_free(ptr); }
|
||||
|
||||
//!Returns the maximum number of elements that could be allocated.
|
||||
//!Never throws
|
||||
size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return size_type(-1)/sizeof(T); }
|
||||
|
||||
//!Swaps two allocators, does nothing
|
||||
//!because this allocator is stateless
|
||||
friend void swap(self_t &, self_t &) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{}
|
||||
|
||||
//!An allocator always compares to true, as memory allocated with one
|
||||
//!instance can be deallocated by another instance
|
||||
friend bool operator==(const allocator &, const allocator &) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return true; }
|
||||
|
||||
//!An allocator always compares to false, as memory allocated with one
|
||||
//!instance can be deallocated by another instance
|
||||
friend bool operator!=(const allocator &, const allocator &) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return false; }
|
||||
|
||||
//!An advanced function that offers in-place expansion shrink to fit and new allocation
|
||||
//!capabilities. Memory allocated with this function can only be deallocated with deallocate()
|
||||
//!or deallocate_many().
|
||||
//!This function is available only with Version == 2
|
||||
pointer allocation_command(allocation_type command,
|
||||
size_type limit_size,
|
||||
size_type &prefer_in_recvd_out_size,
|
||||
pointer &reuse)
|
||||
{
|
||||
BOOST_STATIC_ASSERT(( Version > 1 ));
|
||||
const allocation_type mask(AllocationDisableMask);
|
||||
command &= ~mask;
|
||||
pointer ret = this->priv_allocation_command(command, limit_size, prefer_in_recvd_out_size, reuse);
|
||||
if(!ret && !(command & BOOST_CONTAINER_NOTHROW_ALLOCATION))
|
||||
boost::container::throw_bad_alloc();
|
||||
return ret;
|
||||
}
|
||||
|
||||
//!Returns maximum the number of objects the previously allocated memory
|
||||
//!pointed by p can hold.
|
||||
//!Memory must not have been allocated with
|
||||
//!allocate_one or allocate_individual.
|
||||
//!This function is available only with Version == 2
|
||||
size_type size(pointer p) const BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{
|
||||
BOOST_STATIC_ASSERT(( Version > 1 ));
|
||||
return dlmalloc_size(p);
|
||||
}
|
||||
|
||||
//!Allocates just one object. Memory allocated with this function
|
||||
//!must be deallocated only with deallocate_one().
|
||||
//!Throws bad_alloc if there is no enough memory
|
||||
//!This function is available only with Version == 2
|
||||
pointer allocate_one()
|
||||
{
|
||||
BOOST_STATIC_ASSERT(( Version > 1 ));
|
||||
return this->allocate(1);
|
||||
}
|
||||
|
||||
//!Allocates many elements of size == 1.
|
||||
//!Elements must be individually deallocated with deallocate_one()
|
||||
//!This function is available only with Version == 2
|
||||
void allocate_individual(std::size_t num_elements, multiallocation_chain &chain)
|
||||
{
|
||||
BOOST_STATIC_ASSERT(( Version > 1 ));
|
||||
this->allocate_many(1, num_elements, chain);
|
||||
}
|
||||
|
||||
//!Deallocates memory previously allocated with allocate_one().
|
||||
//!You should never use deallocate_one to deallocate memory allocated
|
||||
//!with other functions different from allocate_one() or allocate_individual.
|
||||
//Never throws
|
||||
void deallocate_one(pointer p) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{
|
||||
BOOST_STATIC_ASSERT(( Version > 1 ));
|
||||
return this->deallocate(p, 1);
|
||||
}
|
||||
|
||||
//!Deallocates memory allocated with allocate_one() or allocate_individual().
|
||||
//!This function is available only with Version == 2
|
||||
void deallocate_individual(multiallocation_chain &chain) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{
|
||||
BOOST_STATIC_ASSERT(( Version > 1 ));
|
||||
return this->deallocate_many(chain);
|
||||
}
|
||||
|
||||
//!Allocates many elements of size elem_size.
|
||||
//!Elements must be individually deallocated with deallocate()
|
||||
//!This function is available only with Version == 2
|
||||
void allocate_many(size_type elem_size, std::size_t n_elements, multiallocation_chain &chain)
|
||||
{
|
||||
BOOST_STATIC_ASSERT(( Version > 1 ));/*
|
||||
dlmalloc_memchain ch;
|
||||
BOOST_CONTAINER_MEMCHAIN_INIT(&ch);
|
||||
if(!dlmalloc_multialloc_nodes(n_elements, elem_size*sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &ch)){
|
||||
boost::container::throw_bad_alloc();
|
||||
}
|
||||
chain.incorporate_after(chain.before_begin()
|
||||
,(T*)BOOST_CONTAINER_MEMCHAIN_FIRSTMEM(&ch)
|
||||
,(T*)BOOST_CONTAINER_MEMCHAIN_LASTMEM(&ch)
|
||||
,BOOST_CONTAINER_MEMCHAIN_SIZE(&ch) );*/
|
||||
if(!dlmalloc_multialloc_nodes(n_elements, elem_size*sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, reinterpret_cast<dlmalloc_memchain *>(&chain))){
|
||||
boost::container::throw_bad_alloc();
|
||||
}
|
||||
}
|
||||
|
||||
//!Allocates n_elements elements, each one of size elem_sizes[i]
|
||||
//!Elements must be individually deallocated with deallocate()
|
||||
//!This function is available only with Version == 2
|
||||
void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain)
|
||||
{
|
||||
BOOST_STATIC_ASSERT(( Version > 1 ));
|
||||
dlmalloc_memchain ch;
|
||||
BOOST_CONTAINER_MEMCHAIN_INIT(&ch);
|
||||
if(!dlmalloc_multialloc_arrays(n_elements, elem_sizes, sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &ch)){
|
||||
boost::container::throw_bad_alloc();
|
||||
}
|
||||
chain.incorporate_after(chain.before_begin()
|
||||
,(T*)BOOST_CONTAINER_MEMCHAIN_FIRSTMEM(&ch)
|
||||
,(T*)BOOST_CONTAINER_MEMCHAIN_LASTMEM(&ch)
|
||||
,BOOST_CONTAINER_MEMCHAIN_SIZE(&ch) );
|
||||
/*
|
||||
if(!dlmalloc_multialloc_arrays(n_elements, elem_sizes, sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, reinterpret_cast<dlmalloc_memchain *>(&chain))){
|
||||
boost::container::throw_bad_alloc();
|
||||
}*/
|
||||
}
|
||||
|
||||
//!Deallocates several elements allocated by
|
||||
//!allocate_many(), allocate(), or allocation_command().
|
||||
//!This function is available only with Version == 2
|
||||
void deallocate_many(multiallocation_chain &chain) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{
|
||||
BOOST_STATIC_ASSERT(( Version > 1 ));
|
||||
dlmalloc_memchain ch;
|
||||
void *beg(&*chain.begin()), *last(&*chain.last());
|
||||
size_t size(chain.size());
|
||||
BOOST_CONTAINER_MEMCHAIN_INIT_FROM(&ch, beg, last, size);
|
||||
dlmalloc_multidealloc(&ch);
|
||||
//dlmalloc_multidealloc(reinterpret_cast<dlmalloc_memchain *>(&chain));
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
pointer priv_allocation_command
|
||||
(allocation_type command, std::size_t limit_size
|
||||
,size_type &prefer_in_recvd_out_size
|
||||
,pointer &reuse_ptr)
|
||||
{
|
||||
std::size_t const preferred_size = prefer_in_recvd_out_size;
|
||||
dlmalloc_command_ret_t ret = {0 , 0};
|
||||
if((limit_size > this->max_size()) | (preferred_size > this->max_size())){
|
||||
return pointer();
|
||||
}
|
||||
std::size_t l_size = limit_size*sizeof(T);
|
||||
std::size_t p_size = preferred_size*sizeof(T);
|
||||
std::size_t r_size;
|
||||
{
|
||||
void* reuse_ptr_void = reuse_ptr;
|
||||
ret = dlmalloc_allocation_command(command, sizeof(T), l_size, p_size, &r_size, reuse_ptr_void);
|
||||
reuse_ptr = ret.second ? static_cast<T*>(reuse_ptr_void) : 0;
|
||||
}
|
||||
prefer_in_recvd_out_size = r_size/sizeof(T);
|
||||
return (pointer)ret.first;
|
||||
}
|
||||
};
|
||||
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_CONTAINER_ALLOCATOR_HPP
|
||||
|
||||
@@ -0,0 +1,477 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Pablo Halpern 2009. 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)
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2011-2013. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#ifndef BOOST_CONTAINER_ALLOCATOR_ALLOCATOR_TRAITS_HPP
|
||||
#define BOOST_CONTAINER_ALLOCATOR_ALLOCATOR_TRAITS_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/detail/config_begin.hpp>
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
|
||||
// container
|
||||
#include <boost/container/container_fwd.hpp>
|
||||
#include <boost/container/detail/mpl.hpp>
|
||||
#include <boost/container/detail/type_traits.hpp> //is_empty
|
||||
#include <boost/container/detail/placement_new.hpp>
|
||||
#ifndef BOOST_CONTAINER_DETAIL_STD_FWD_HPP
|
||||
#include <boost/container/detail/std_fwd.hpp>
|
||||
#endif
|
||||
// intrusive
|
||||
#include <boost/intrusive/pointer_traits.hpp>
|
||||
#include <boost/intrusive/detail/mpl.hpp>
|
||||
// move
|
||||
#include <boost/move/utility_core.hpp>
|
||||
// move/detail
|
||||
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
#include <boost/move/detail/fwd_macros.hpp>
|
||||
#endif
|
||||
// other boost
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME allocate
|
||||
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace container_detail {
|
||||
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
|
||||
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 2
|
||||
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 2
|
||||
#include <boost/intrusive/detail/has_member_function_callable_with.hpp>
|
||||
|
||||
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME destroy
|
||||
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace container_detail {
|
||||
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
|
||||
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 1
|
||||
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 1
|
||||
#include <boost/intrusive/detail/has_member_function_callable_with.hpp>
|
||||
|
||||
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME construct
|
||||
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace container_detail {
|
||||
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
|
||||
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 1
|
||||
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 9
|
||||
#include <boost/intrusive/detail/has_member_function_callable_with.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
template<class Allocator>
|
||||
class small_vector_allocator;
|
||||
|
||||
namespace allocator_traits_detail {
|
||||
|
||||
BOOST_INTRUSIVE_HAS_STATIC_MEMBER_FUNC_SIGNATURE(has_max_size, max_size)
|
||||
BOOST_INTRUSIVE_HAS_STATIC_MEMBER_FUNC_SIGNATURE(has_select_on_container_copy_construction, select_on_container_copy_construction)
|
||||
|
||||
} //namespace allocator_traits_detail {
|
||||
|
||||
namespace container_detail {
|
||||
|
||||
//workaround needed for C++03 compilers with no construct()
|
||||
//supporting rvalue references
|
||||
template<class Allocator>
|
||||
struct is_std_allocator
|
||||
{ static const bool value = false; };
|
||||
|
||||
template<class T>
|
||||
struct is_std_allocator< std::allocator<T> >
|
||||
{ static const bool value = true; };
|
||||
|
||||
template<class T>
|
||||
struct is_std_allocator< small_vector_allocator< std::allocator<T> > >
|
||||
{ static const bool value = true; };
|
||||
|
||||
template<class Allocator>
|
||||
struct is_not_std_allocator
|
||||
{ static const bool value = !is_std_allocator<Allocator>::value; };
|
||||
|
||||
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(pointer)
|
||||
BOOST_INTRUSIVE_INSTANTIATE_EVAL_DEFAULT_TYPE_TMPLT(const_pointer)
|
||||
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(reference)
|
||||
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(const_reference)
|
||||
BOOST_INTRUSIVE_INSTANTIATE_EVAL_DEFAULT_TYPE_TMPLT(void_pointer)
|
||||
BOOST_INTRUSIVE_INSTANTIATE_EVAL_DEFAULT_TYPE_TMPLT(const_void_pointer)
|
||||
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(size_type)
|
||||
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(propagate_on_container_copy_assignment)
|
||||
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(propagate_on_container_move_assignment)
|
||||
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(propagate_on_container_swap)
|
||||
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(is_always_equal)
|
||||
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(difference_type)
|
||||
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(is_partially_propagable)
|
||||
|
||||
} //namespace container_detail {
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
//! The class template allocator_traits supplies a uniform interface to all allocator types.
|
||||
//! This class is a C++03-compatible implementation of std::allocator_traits
|
||||
template <typename Allocator>
|
||||
struct allocator_traits
|
||||
{
|
||||
//allocator_type
|
||||
typedef Allocator allocator_type;
|
||||
//value_type
|
||||
typedef typename allocator_type::value_type value_type;
|
||||
|
||||
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
//! Allocator::pointer if such a type exists; otherwise, value_type*
|
||||
//!
|
||||
typedef unspecified pointer;
|
||||
//! Allocator::const_pointer if such a type exists ; otherwise, pointer_traits<pointer>::rebind<const
|
||||
//!
|
||||
typedef see_documentation const_pointer;
|
||||
//! Non-standard extension
|
||||
//! Allocator::reference if such a type exists; otherwise, value_type&
|
||||
typedef see_documentation reference;
|
||||
//! Non-standard extension
|
||||
//! Allocator::const_reference if such a type exists ; otherwise, const value_type&
|
||||
typedef see_documentation const_reference;
|
||||
//! Allocator::void_pointer if such a type exists ; otherwise, pointer_traits<pointer>::rebind<void>.
|
||||
//!
|
||||
typedef see_documentation void_pointer;
|
||||
//! Allocator::const_void_pointer if such a type exists ; otherwis e, pointer_traits<pointer>::rebind<const
|
||||
//!
|
||||
typedef see_documentation const_void_pointer;
|
||||
//! Allocator::difference_type if such a type exists ; otherwise, pointer_traits<pointer>::difference_type.
|
||||
//!
|
||||
typedef see_documentation difference_type;
|
||||
//! Allocator::size_type if such a type exists ; otherwise, make_unsigned<difference_type>::type
|
||||
//!
|
||||
typedef see_documentation size_type;
|
||||
//! Allocator::propagate_on_container_copy_assignment if such a type exists, otherwise a type
|
||||
//! with an internal constant static boolean member <code>value</code> == false.
|
||||
typedef see_documentation propagate_on_container_copy_assignment;
|
||||
//! Allocator::propagate_on_container_move_assignment if such a type exists, otherwise a type
|
||||
//! with an internal constant static boolean member <code>value</code> == false.
|
||||
typedef see_documentation propagate_on_container_move_assignment;
|
||||
//! Allocator::propagate_on_container_swap if such a type exists, otherwise a type
|
||||
//! with an internal constant static boolean member <code>value</code> == false.
|
||||
typedef see_documentation propagate_on_container_swap;
|
||||
//! Allocator::is_always_equal if such a type exists, otherwise a type
|
||||
//! with an internal constant static boolean member <code>value</code> == is_empty<Allocator>::value
|
||||
typedef see_documentation is_always_equal;
|
||||
//! Allocator::is_partially_propagable if such a type exists, otherwise a type
|
||||
//! with an internal constant static boolean member <code>value</code> == false
|
||||
//! <b>Note</b>: Non-standard extension used to implement `small_vector_allocator`.
|
||||
typedef see_documentation is_partially_propagable;
|
||||
//! Defines an allocator: Allocator::rebind<T>::other if such a type exists; otherwise, Allocator<T, Args>
|
||||
//! if Allocator is a class template instantiation of the form Allocator<U, Args>, where Args is zero or
|
||||
//! more type arguments ; otherwise, the instantiation of rebind_alloc is ill-formed.
|
||||
//!
|
||||
//! In C++03 compilers <code>rebind_alloc</code> is a struct derived from an allocator
|
||||
//! deduced by previously detailed rules.
|
||||
template <class T> using rebind_alloc = see_documentation;
|
||||
|
||||
//! In C++03 compilers <code>rebind_traits</code> is a struct derived from
|
||||
//! <code>allocator_traits<OtherAlloc></code>, where <code>OtherAlloc</code> is
|
||||
//! the allocator deduced by rules explained in <code>rebind_alloc</code>.
|
||||
template <class T> using rebind_traits = allocator_traits<rebind_alloc<T> >;
|
||||
|
||||
//! Non-standard extension: Portable allocator rebind for C++03 and C++11 compilers.
|
||||
//! <code>type</code> is an allocator related to Allocator deduced deduced by rules explained in <code>rebind_alloc</code>.
|
||||
template <class T>
|
||||
struct portable_rebind_alloc
|
||||
{ typedef see_documentation type; };
|
||||
#else
|
||||
//pointer
|
||||
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Allocator,
|
||||
pointer, value_type*)
|
||||
pointer;
|
||||
//const_pointer
|
||||
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_EVAL_DEFAULT(boost::container::container_detail::, Allocator,
|
||||
const_pointer, typename boost::intrusive::pointer_traits<pointer>::template
|
||||
rebind_pointer<const value_type>)
|
||||
const_pointer;
|
||||
//reference
|
||||
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Allocator,
|
||||
reference, typename container_detail::unvoid_ref<value_type>::type)
|
||||
reference;
|
||||
//const_reference
|
||||
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Allocator,
|
||||
const_reference, typename container_detail::unvoid_ref<const value_type>::type)
|
||||
const_reference;
|
||||
//void_pointer
|
||||
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_EVAL_DEFAULT(boost::container::container_detail::, Allocator,
|
||||
void_pointer, typename boost::intrusive::pointer_traits<pointer>::template
|
||||
rebind_pointer<void>)
|
||||
void_pointer;
|
||||
//const_void_pointer
|
||||
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_EVAL_DEFAULT(boost::container::container_detail::, Allocator,
|
||||
const_void_pointer, typename boost::intrusive::pointer_traits<pointer>::template
|
||||
rebind_pointer<const void>)
|
||||
const_void_pointer;
|
||||
//difference_type
|
||||
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Allocator,
|
||||
difference_type, std::ptrdiff_t)
|
||||
difference_type;
|
||||
//size_type
|
||||
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Allocator,
|
||||
size_type, std::size_t)
|
||||
size_type;
|
||||
//propagate_on_container_copy_assignment
|
||||
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Allocator,
|
||||
propagate_on_container_copy_assignment, container_detail::false_type)
|
||||
propagate_on_container_copy_assignment;
|
||||
//propagate_on_container_move_assignment
|
||||
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Allocator,
|
||||
propagate_on_container_move_assignment, container_detail::false_type)
|
||||
propagate_on_container_move_assignment;
|
||||
//propagate_on_container_swap
|
||||
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Allocator,
|
||||
propagate_on_container_swap, container_detail::false_type)
|
||||
propagate_on_container_swap;
|
||||
//is_always_equal
|
||||
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Allocator,
|
||||
is_always_equal, container_detail::is_empty<Allocator>)
|
||||
is_always_equal;
|
||||
//is_partially_propagable
|
||||
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Allocator,
|
||||
is_partially_propagable, container_detail::false_type)
|
||||
is_partially_propagable;
|
||||
|
||||
//rebind_alloc & rebind_traits
|
||||
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
|
||||
//C++11
|
||||
template <typename T> using rebind_alloc = typename boost::intrusive::pointer_rebind<Allocator, T>::type;
|
||||
template <typename T> using rebind_traits = allocator_traits< rebind_alloc<T> >;
|
||||
#else // #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
|
||||
//Some workaround for C++03 or C++11 compilers with no template aliases
|
||||
template <typename T>
|
||||
struct rebind_alloc : boost::intrusive::pointer_rebind<Allocator,T>::type
|
||||
{
|
||||
typedef typename boost::intrusive::pointer_rebind<Allocator,T>::type Base;
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
template <typename... Args>
|
||||
rebind_alloc(BOOST_FWD_REF(Args)... args) : Base(boost::forward<Args>(args)...) {}
|
||||
#else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
#define BOOST_CONTAINER_ALLOCATOR_TRAITS_REBIND_ALLOC(N) \
|
||||
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N\
|
||||
explicit rebind_alloc(BOOST_MOVE_UREF##N) : Base(BOOST_MOVE_FWD##N){}\
|
||||
//
|
||||
BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_ALLOCATOR_TRAITS_REBIND_ALLOC)
|
||||
#undef BOOST_CONTAINER_ALLOCATOR_TRAITS_REBIND_ALLOC
|
||||
#endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct rebind_traits
|
||||
: allocator_traits<typename boost::intrusive::pointer_rebind<Allocator, T>::type>
|
||||
{};
|
||||
#endif // #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
|
||||
|
||||
//portable_rebind_alloc
|
||||
template <class T>
|
||||
struct portable_rebind_alloc
|
||||
{ typedef typename boost::intrusive::pointer_rebind<Allocator, T>::type type; };
|
||||
#endif //BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
//! <b>Returns</b>: <code>a.allocate(n)</code>
|
||||
//!
|
||||
BOOST_CONTAINER_FORCEINLINE static pointer allocate(Allocator &a, size_type n)
|
||||
{ return a.allocate(n); }
|
||||
|
||||
//! <b>Returns</b>: <code>a.deallocate(p, n)</code>
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing
|
||||
BOOST_CONTAINER_FORCEINLINE static void deallocate(Allocator &a, pointer p, size_type n)
|
||||
{ a.deallocate(p, n); }
|
||||
|
||||
//! <b>Effects</b>: calls <code>a.allocate(n, p)</code> if that call is well-formed;
|
||||
//! otherwise, invokes <code>a.allocate(n)</code>
|
||||
BOOST_CONTAINER_FORCEINLINE static pointer allocate(Allocator &a, size_type n, const_void_pointer p)
|
||||
{
|
||||
const bool value = boost::container::container_detail::
|
||||
has_member_function_callable_with_allocate
|
||||
<Allocator, const size_type, const const_void_pointer>::value;
|
||||
container_detail::bool_<value> flag;
|
||||
return allocator_traits::priv_allocate(flag, a, n, p);
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: calls <code>a.destroy(p)</code> if that call is well-formed;
|
||||
//! otherwise, invokes <code>p->~T()</code>.
|
||||
template<class T>
|
||||
BOOST_CONTAINER_FORCEINLINE static void destroy(Allocator &a, T*p) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{
|
||||
typedef T* destroy_pointer;
|
||||
const bool value = boost::container::container_detail::
|
||||
has_member_function_callable_with_destroy
|
||||
<Allocator, const destroy_pointer>::value;
|
||||
container_detail::bool_<value> flag;
|
||||
allocator_traits::priv_destroy(flag, a, p);
|
||||
}
|
||||
|
||||
//! <b>Returns</b>: <code>a.max_size()</code> if that expression is well-formed; otherwise,
|
||||
//! <code>numeric_limits<size_type>::max()</code>.
|
||||
BOOST_CONTAINER_FORCEINLINE static size_type max_size(const Allocator &a) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{
|
||||
const bool value = allocator_traits_detail::has_max_size<Allocator, size_type (Allocator::*)() const>::value;
|
||||
container_detail::bool_<value> flag;
|
||||
return allocator_traits::priv_max_size(flag, a);
|
||||
}
|
||||
|
||||
//! <b>Returns</b>: <code>a.select_on_container_copy_construction()</code> if that expression is well-formed;
|
||||
//! otherwise, a.
|
||||
BOOST_CONTAINER_FORCEINLINE static BOOST_CONTAINER_DOC1ST(Allocator,
|
||||
typename container_detail::if_c
|
||||
< allocator_traits_detail::has_select_on_container_copy_construction<Allocator BOOST_MOVE_I Allocator (Allocator::*)() const>::value
|
||||
BOOST_MOVE_I Allocator BOOST_MOVE_I const Allocator & >::type)
|
||||
select_on_container_copy_construction(const Allocator &a)
|
||||
{
|
||||
const bool value = allocator_traits_detail::has_select_on_container_copy_construction
|
||||
<Allocator, Allocator (Allocator::*)() const>::value;
|
||||
container_detail::bool_<value> flag;
|
||||
return allocator_traits::priv_select_on_container_copy_construction(flag, a);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
//! <b>Effects</b>: calls <code>a.construct(p, std::forward<Args>(args)...)</code> if that call is well-formed;
|
||||
//! otherwise, invokes <code>::new (static_cast<void*>(p)) T(std::forward<Args>(args)...)</code>
|
||||
template <class T, class ...Args>
|
||||
BOOST_CONTAINER_FORCEINLINE static void construct(Allocator & a, T* p, BOOST_FWD_REF(Args)... args)
|
||||
{
|
||||
static const bool value = ::boost::move_detail::and_
|
||||
< container_detail::is_not_std_allocator<Allocator>
|
||||
, boost::container::container_detail::has_member_function_callable_with_construct
|
||||
< Allocator, T*, Args... >
|
||||
>::value;
|
||||
container_detail::bool_<value> flag;
|
||||
allocator_traits::priv_construct(flag, a, p, ::boost::forward<Args>(args)...);
|
||||
}
|
||||
#endif
|
||||
|
||||
//! <b>Returns</b>: <code>a.storage_is_unpropagable(p)</code> if is_partially_propagable::value is true; otherwise,
|
||||
//! <code>false</code>.
|
||||
BOOST_CONTAINER_FORCEINLINE static bool storage_is_unpropagable(const Allocator &a, pointer p) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{
|
||||
container_detail::bool_<is_partially_propagable::value> flag;
|
||||
return allocator_traits::priv_storage_is_unpropagable(flag, a, p);
|
||||
}
|
||||
|
||||
//! <b>Returns</b>: <code>true</code> if <code>is_always_equal::value == true</code>, otherwise,
|
||||
//! <code>a == b</code>.
|
||||
BOOST_CONTAINER_FORCEINLINE static bool equal(const Allocator &a, const Allocator &b) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{
|
||||
container_detail::bool_<is_always_equal::value> flag;
|
||||
return allocator_traits::priv_equal(flag, a, b);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
private:
|
||||
BOOST_CONTAINER_FORCEINLINE static pointer priv_allocate(container_detail::true_type, Allocator &a, size_type n, const_void_pointer p)
|
||||
{ return a.allocate(n, p); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE static pointer priv_allocate(container_detail::false_type, Allocator &a, size_type n, const_void_pointer)
|
||||
{ return a.allocate(n); }
|
||||
|
||||
template<class T>
|
||||
BOOST_CONTAINER_FORCEINLINE static void priv_destroy(container_detail::true_type, Allocator &a, T* p) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ a.destroy(p); }
|
||||
|
||||
template<class T>
|
||||
BOOST_CONTAINER_FORCEINLINE static void priv_destroy(container_detail::false_type, Allocator &, T* p) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ p->~T(); (void)p; }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE static size_type priv_max_size(container_detail::true_type, const Allocator &a) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return a.max_size(); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE static size_type priv_max_size(container_detail::false_type, const Allocator &) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return size_type(-1)/sizeof(value_type); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE static Allocator priv_select_on_container_copy_construction(container_detail::true_type, const Allocator &a)
|
||||
{ return a.select_on_container_copy_construction(); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE static const Allocator &priv_select_on_container_copy_construction(container_detail::false_type, const Allocator &a) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return a; }
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
template<class T, class ...Args>
|
||||
BOOST_CONTAINER_FORCEINLINE static void priv_construct(container_detail::true_type, Allocator &a, T *p, BOOST_FWD_REF(Args) ...args)
|
||||
{ a.construct( p, ::boost::forward<Args>(args)...); }
|
||||
|
||||
template<class T, class ...Args>
|
||||
BOOST_CONTAINER_FORCEINLINE static void priv_construct(container_detail::false_type, Allocator &, T *p, BOOST_FWD_REF(Args) ...args)
|
||||
{ ::new((void*)p, boost_container_new_t()) T(::boost::forward<Args>(args)...); }
|
||||
#else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
public:
|
||||
|
||||
#define BOOST_CONTAINER_ALLOCATOR_TRAITS_CONSTRUCT_IMPL(N) \
|
||||
template<class T BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
|
||||
BOOST_CONTAINER_FORCEINLINE static void construct(Allocator &a, T *p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
|
||||
{\
|
||||
static const bool value = ::boost::move_detail::and_ \
|
||||
< container_detail::is_not_std_allocator<Allocator> \
|
||||
, boost::container::container_detail::has_member_function_callable_with_construct \
|
||||
< Allocator, T* BOOST_MOVE_I##N BOOST_MOVE_FWD_T##N > \
|
||||
>::value; \
|
||||
container_detail::bool_<value> flag;\
|
||||
(priv_construct)(flag, a, p BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
|
||||
}\
|
||||
//
|
||||
BOOST_MOVE_ITERATE_0TO8(BOOST_CONTAINER_ALLOCATOR_TRAITS_CONSTRUCT_IMPL)
|
||||
#undef BOOST_CONTAINER_ALLOCATOR_TRAITS_CONSTRUCT_IMPL
|
||||
|
||||
private:
|
||||
/////////////////////////////////
|
||||
// priv_construct
|
||||
/////////////////////////////////
|
||||
#define BOOST_CONTAINER_ALLOCATOR_TRAITS_PRIV_CONSTRUCT_IMPL(N) \
|
||||
template<class T BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
|
||||
BOOST_CONTAINER_FORCEINLINE static void priv_construct(container_detail::true_type, Allocator &a, T *p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
|
||||
{ a.construct( p BOOST_MOVE_I##N BOOST_MOVE_FWD##N ); }\
|
||||
\
|
||||
template<class T BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
|
||||
BOOST_CONTAINER_FORCEINLINE static void priv_construct(container_detail::false_type, Allocator &, T *p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
|
||||
{ ::new((void*)p, boost_container_new_t()) T(BOOST_MOVE_FWD##N); }\
|
||||
//
|
||||
BOOST_MOVE_ITERATE_0TO8(BOOST_CONTAINER_ALLOCATOR_TRAITS_PRIV_CONSTRUCT_IMPL)
|
||||
#undef BOOST_CONTAINER_ALLOCATOR_TRAITS_PRIV_CONSTRUCT_IMPL
|
||||
|
||||
#endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
template<class T>
|
||||
BOOST_CONTAINER_FORCEINLINE static void priv_construct(container_detail::false_type, Allocator &, T *p, const ::boost::container::default_init_t&)
|
||||
{ ::new((void*)p, boost_container_new_t()) T; }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE static bool priv_storage_is_unpropagable(container_detail::true_type, const Allocator &a, pointer p)
|
||||
{ return a.storage_is_unpropagable(p); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE static bool priv_storage_is_unpropagable(container_detail::false_type, const Allocator &, pointer)
|
||||
{ return false; }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE static bool priv_equal(container_detail::true_type, const Allocator &, const Allocator &)
|
||||
{ return true; }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE static bool priv_equal(container_detail::false_type, const Allocator &a, const Allocator &b)
|
||||
{ return a == b; }
|
||||
|
||||
#endif //#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
};
|
||||
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif // ! defined(BOOST_CONTAINER_ALLOCATOR_ALLOCATOR_TRAITS_HPP)
|
||||
@@ -0,0 +1,317 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2014. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_CONTAINER_FWD_HPP
|
||||
#define BOOST_CONTAINER_CONTAINER_FWD_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
//! \file
|
||||
//! This header file forward declares the following containers:
|
||||
//! - boost::container::vector
|
||||
//! - boost::container::stable_vector
|
||||
//! - boost::container::static_vector
|
||||
//! - boost::container::small_vector
|
||||
//! - boost::container::slist
|
||||
//! - boost::container::list
|
||||
//! - boost::container::set
|
||||
//! - boost::container::multiset
|
||||
//! - boost::container::map
|
||||
//! - boost::container::multimap
|
||||
//! - boost::container::flat_set
|
||||
//! - boost::container::flat_multiset
|
||||
//! - boost::container::flat_map
|
||||
//! - boost::container::flat_multimap
|
||||
//! - boost::container::basic_string
|
||||
//! - boost::container::string
|
||||
//! - boost::container::wstring
|
||||
//!
|
||||
//! Forward declares the following allocators:
|
||||
//! - boost::container::allocator
|
||||
//! - boost::container::node_allocator
|
||||
//! - boost::container::adaptive_pool
|
||||
//!
|
||||
//! Forward declares the following polymorphic resource classes:
|
||||
//! - boost::container::pmr::memory_resource
|
||||
//! - boost::container::pmr::polymorphic_allocator
|
||||
//! - boost::container::pmr::monotonic_buffer_resource
|
||||
//! - boost::container::pmr::pool_options
|
||||
//! - boost::container::pmr::unsynchronized_pool_resource
|
||||
//! - boost::container::pmr::synchronized_pool_resource
|
||||
//!
|
||||
//! And finally it defines the following types
|
||||
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
//Std forward declarations
|
||||
#ifndef BOOST_CONTAINER_DETAIL_STD_FWD_HPP
|
||||
#include <boost/container/detail/std_fwd.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost{
|
||||
namespace intrusive{
|
||||
namespace detail{
|
||||
//Create namespace to avoid compilation errors
|
||||
}}}
|
||||
|
||||
namespace boost{ namespace container{ namespace container_detail{
|
||||
namespace bi = boost::intrusive;
|
||||
namespace bid = boost::intrusive::detail;
|
||||
}}}
|
||||
|
||||
namespace boost{ namespace container{ namespace pmr{
|
||||
namespace bi = boost::intrusive;
|
||||
namespace bid = boost::intrusive::detail;
|
||||
}}}
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Containers
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
|
||||
//! Enumeration used to configure ordered associative containers
|
||||
//! with a concrete tree implementation.
|
||||
enum tree_type_enum
|
||||
{
|
||||
red_black_tree,
|
||||
avl_tree,
|
||||
scapegoat_tree,
|
||||
splay_tree
|
||||
};
|
||||
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
template<class T>
|
||||
class new_allocator;
|
||||
|
||||
template <class T
|
||||
,class Allocator = new_allocator<T> >
|
||||
class vector;
|
||||
|
||||
template <class T
|
||||
,class Allocator = new_allocator<T> >
|
||||
class stable_vector;
|
||||
|
||||
template <class T, std::size_t Capacity>
|
||||
class static_vector;
|
||||
|
||||
template < class T, std::size_t N
|
||||
, class Allocator= new_allocator<T> >
|
||||
class small_vector;
|
||||
|
||||
template <class T
|
||||
,class Allocator = new_allocator<T> >
|
||||
class deque;
|
||||
|
||||
template <class T
|
||||
,class Allocator = new_allocator<T> >
|
||||
class list;
|
||||
|
||||
template <class T
|
||||
,class Allocator = new_allocator<T> >
|
||||
class slist;
|
||||
|
||||
template<tree_type_enum TreeType, bool OptimizeSize>
|
||||
struct tree_opt;
|
||||
|
||||
typedef tree_opt<red_black_tree, true> tree_assoc_defaults;
|
||||
|
||||
template <class Key
|
||||
,class Compare = std::less<Key>
|
||||
,class Allocator = new_allocator<Key>
|
||||
,class Options = tree_assoc_defaults >
|
||||
class set;
|
||||
|
||||
template <class Key
|
||||
,class Compare = std::less<Key>
|
||||
,class Allocator = new_allocator<Key>
|
||||
,class Options = tree_assoc_defaults >
|
||||
class multiset;
|
||||
|
||||
template <class Key
|
||||
,class T
|
||||
,class Compare = std::less<Key>
|
||||
,class Allocator = new_allocator<std::pair<const Key, T> >
|
||||
,class Options = tree_assoc_defaults >
|
||||
class map;
|
||||
|
||||
template <class Key
|
||||
,class T
|
||||
,class Compare = std::less<Key>
|
||||
,class Allocator = new_allocator<std::pair<const Key, T> >
|
||||
,class Options = tree_assoc_defaults >
|
||||
class multimap;
|
||||
|
||||
template <class Key
|
||||
,class Compare = std::less<Key>
|
||||
,class Allocator = new_allocator<Key> >
|
||||
class flat_set;
|
||||
|
||||
template <class Key
|
||||
,class Compare = std::less<Key>
|
||||
,class Allocator = new_allocator<Key> >
|
||||
class flat_multiset;
|
||||
|
||||
template <class Key
|
||||
,class T
|
||||
,class Compare = std::less<Key>
|
||||
,class Allocator = new_allocator<std::pair<Key, T> > >
|
||||
class flat_map;
|
||||
|
||||
template <class Key
|
||||
,class T
|
||||
,class Compare = std::less<Key>
|
||||
,class Allocator = new_allocator<std::pair<Key, T> > >
|
||||
class flat_multimap;
|
||||
|
||||
template <class CharT
|
||||
,class Traits = std::char_traits<CharT>
|
||||
,class Allocator = new_allocator<CharT> >
|
||||
class basic_string;
|
||||
|
||||
typedef basic_string
|
||||
<char
|
||||
,std::char_traits<char>
|
||||
,new_allocator<char> >
|
||||
string;
|
||||
|
||||
typedef basic_string
|
||||
<wchar_t
|
||||
,std::char_traits<wchar_t>
|
||||
,new_allocator<wchar_t> >
|
||||
wstring;
|
||||
|
||||
static const std::size_t ADP_nodes_per_block = 256u;
|
||||
static const std::size_t ADP_max_free_blocks = 2u;
|
||||
static const std::size_t ADP_overhead_percent = 1u;
|
||||
static const std::size_t ADP_only_alignment = 0u;
|
||||
|
||||
template < class T
|
||||
, std::size_t NodesPerBlock = ADP_nodes_per_block
|
||||
, std::size_t MaxFreeBlocks = ADP_max_free_blocks
|
||||
, std::size_t OverheadPercent = ADP_overhead_percent
|
||||
, unsigned Version = 2
|
||||
>
|
||||
class adaptive_pool;
|
||||
|
||||
template < class T
|
||||
, unsigned Version = 2
|
||||
, unsigned int AllocationDisableMask = 0>
|
||||
class allocator;
|
||||
|
||||
static const std::size_t NodeAlloc_nodes_per_block = 256u;
|
||||
|
||||
template
|
||||
< class T
|
||||
, std::size_t NodesPerBlock = NodeAlloc_nodes_per_block
|
||||
, std::size_t Version = 2>
|
||||
class node_allocator;
|
||||
|
||||
namespace pmr {
|
||||
|
||||
class memory_resource;
|
||||
|
||||
template<class T>
|
||||
class polymorphic_allocator;
|
||||
|
||||
class monotonic_buffer_resource;
|
||||
|
||||
struct pool_options;
|
||||
|
||||
template <class Allocator>
|
||||
class resource_adaptor_imp;
|
||||
|
||||
class unsynchronized_pool_resource;
|
||||
|
||||
class synchronized_pool_resource;
|
||||
|
||||
} //namespace pmr {
|
||||
|
||||
#else
|
||||
|
||||
//! Default options for tree-based associative containers
|
||||
//! - tree_type<red_black_tree>
|
||||
//! - optimize_size<true>
|
||||
typedef implementation_defined tree_assoc_defaults;
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
//! Type used to tag that the input range is
|
||||
//! guaranteed to be ordered
|
||||
struct ordered_range_t
|
||||
{};
|
||||
|
||||
//! Value used to tag that the input range is
|
||||
//! guaranteed to be ordered
|
||||
static const ordered_range_t ordered_range = ordered_range_t();
|
||||
|
||||
//! Type used to tag that the input range is
|
||||
//! guaranteed to be ordered and unique
|
||||
struct ordered_unique_range_t
|
||||
: public ordered_range_t
|
||||
{};
|
||||
|
||||
//! Value used to tag that the input range is
|
||||
//! guaranteed to be ordered and unique
|
||||
static const ordered_unique_range_t ordered_unique_range = ordered_unique_range_t();
|
||||
|
||||
//! Type used to tag that the inserted values
|
||||
//! should be default initialized
|
||||
struct default_init_t
|
||||
{};
|
||||
|
||||
//! Value used to tag that the inserted values
|
||||
//! should be default initialized
|
||||
static const default_init_t default_init = default_init_t();
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
//! Type used to tag that the inserted values
|
||||
//! should be value initialized
|
||||
struct value_init_t
|
||||
{};
|
||||
|
||||
//! Value used to tag that the inserted values
|
||||
//! should be value initialized
|
||||
static const value_init_t value_init = value_init_t();
|
||||
|
||||
namespace container_detail_really_deep_namespace {
|
||||
|
||||
//Otherwise, gcc issues a warning of previously defined
|
||||
//anonymous_instance and unique_instance
|
||||
struct dummy
|
||||
{
|
||||
dummy()
|
||||
{
|
||||
(void)ordered_range;
|
||||
(void)ordered_unique_range;
|
||||
(void)default_init;
|
||||
}
|
||||
};
|
||||
|
||||
} //detail_really_deep_namespace {
|
||||
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
}} //namespace boost { namespace container {
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_CONTAINER_FWD_HPP
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,166 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2013. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_DETAIL_ADAPTIVE_NODE_POOL_HPP
|
||||
#define BOOST_CONTAINER_DETAIL_ADAPTIVE_NODE_POOL_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/detail/config_begin.hpp>
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
|
||||
#include <boost/intrusive/set.hpp>
|
||||
#include <boost/container/detail/multiallocation_chain.hpp>
|
||||
#include <boost/container/detail/pool_common_alloc.hpp>
|
||||
#include <boost/container/detail/mutex.hpp>
|
||||
#include <boost/container/detail/adaptive_node_pool_impl.hpp>
|
||||
#include <boost/container/detail/multiallocation_chain.hpp>
|
||||
#include <boost/container/detail/type_traits.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
#include <cmath>
|
||||
#include <cassert>
|
||||
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace container_detail {
|
||||
|
||||
template<bool AlignOnly>
|
||||
struct select_private_adaptive_node_pool_impl
|
||||
{
|
||||
typedef boost::container::container_detail::
|
||||
private_adaptive_node_pool_impl
|
||||
< fake_segment_manager
|
||||
, unsigned(AlignOnly)*::boost::container::adaptive_pool_flag::align_only
|
||||
| ::boost::container::adaptive_pool_flag::size_ordered | ::boost::container::adaptive_pool_flag::address_ordered
|
||||
> type;
|
||||
};
|
||||
|
||||
//!Pooled memory allocator using an smart adaptive pool. Includes
|
||||
//!a reference count but the class does not delete itself, this is
|
||||
//!responsibility of user classes. Node size (NodeSize) and the number of
|
||||
//!nodes allocated per block (NodesPerBlock) are known at compile time.
|
||||
template< std::size_t NodeSize
|
||||
, std::size_t NodesPerBlock
|
||||
, std::size_t MaxFreeBlocks
|
||||
, std::size_t OverheadPercent
|
||||
>
|
||||
class private_adaptive_node_pool
|
||||
: public select_private_adaptive_node_pool_impl<(OverheadPercent == 0)>::type
|
||||
{
|
||||
typedef typename select_private_adaptive_node_pool_impl<OverheadPercent == 0>::type base_t;
|
||||
//Non-copyable
|
||||
private_adaptive_node_pool(const private_adaptive_node_pool &);
|
||||
private_adaptive_node_pool &operator=(const private_adaptive_node_pool &);
|
||||
|
||||
public:
|
||||
typedef typename base_t::multiallocation_chain multiallocation_chain;
|
||||
static const std::size_t nodes_per_block = NodesPerBlock;
|
||||
|
||||
//!Constructor. Never throws
|
||||
private_adaptive_node_pool()
|
||||
: base_t(0
|
||||
, NodeSize
|
||||
, NodesPerBlock
|
||||
, MaxFreeBlocks
|
||||
, (unsigned char)OverheadPercent)
|
||||
{}
|
||||
};
|
||||
|
||||
//!Pooled memory allocator using adaptive pool. Includes
|
||||
//!a reference count but the class does not delete itself, this is
|
||||
//!responsibility of user classes. Node size (NodeSize) and the number of
|
||||
//!nodes allocated per block (NodesPerBlock) are known at compile time
|
||||
template< std::size_t NodeSize
|
||||
, std::size_t NodesPerBlock
|
||||
, std::size_t MaxFreeBlocks
|
||||
, std::size_t OverheadPercent
|
||||
>
|
||||
class shared_adaptive_node_pool
|
||||
: public private_adaptive_node_pool
|
||||
<NodeSize, NodesPerBlock, MaxFreeBlocks, OverheadPercent>
|
||||
{
|
||||
private:
|
||||
typedef private_adaptive_node_pool
|
||||
<NodeSize, NodesPerBlock, MaxFreeBlocks, OverheadPercent> private_node_allocator_t;
|
||||
public:
|
||||
typedef typename private_node_allocator_t::multiallocation_chain multiallocation_chain;
|
||||
|
||||
//!Constructor. Never throws
|
||||
shared_adaptive_node_pool()
|
||||
: private_node_allocator_t(){}
|
||||
|
||||
//!Destructor. Deallocates all allocated blocks. Never throws
|
||||
~shared_adaptive_node_pool()
|
||||
{}
|
||||
|
||||
//!Allocates array of count elements. Can throw std::bad_alloc
|
||||
void *allocate_node()
|
||||
{
|
||||
//-----------------------
|
||||
scoped_lock<default_mutex> guard(mutex_);
|
||||
//-----------------------
|
||||
return private_node_allocator_t::allocate_node();
|
||||
}
|
||||
|
||||
//!Deallocates an array pointed by ptr. Never throws
|
||||
void deallocate_node(void *ptr)
|
||||
{
|
||||
//-----------------------
|
||||
scoped_lock<default_mutex> guard(mutex_);
|
||||
//-----------------------
|
||||
private_node_allocator_t::deallocate_node(ptr);
|
||||
}
|
||||
|
||||
//!Allocates a singly linked list of n nodes ending in null pointer.
|
||||
//!can throw std::bad_alloc
|
||||
void allocate_nodes(const std::size_t n, multiallocation_chain &chain)
|
||||
{
|
||||
//-----------------------
|
||||
scoped_lock<default_mutex> guard(mutex_);
|
||||
//-----------------------
|
||||
return private_node_allocator_t::allocate_nodes(n, chain);
|
||||
}
|
||||
|
||||
void deallocate_nodes(multiallocation_chain &chain)
|
||||
{
|
||||
//-----------------------
|
||||
scoped_lock<default_mutex> guard(mutex_);
|
||||
//-----------------------
|
||||
private_node_allocator_t::deallocate_nodes(chain);
|
||||
}
|
||||
|
||||
//!Deallocates all the free blocks of memory. Never throws
|
||||
void deallocate_free_blocks()
|
||||
{
|
||||
//-----------------------
|
||||
scoped_lock<default_mutex> guard(mutex_);
|
||||
//-----------------------
|
||||
private_node_allocator_t::deallocate_free_blocks();
|
||||
}
|
||||
|
||||
private:
|
||||
default_mutex mutex_;
|
||||
};
|
||||
|
||||
} //namespace container_detail {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DETAIL_ADAPTIVE_NODE_POOL_HPP
|
||||
+885
@@ -0,0 +1,885 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2013. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_DETAIL_ADAPTIVE_NODE_POOL_IMPL_HPP
|
||||
#define BOOST_CONTAINER_DETAIL_ADAPTIVE_NODE_POOL_IMPL_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/detail/config_begin.hpp>
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
|
||||
// container
|
||||
#include <boost/container/container_fwd.hpp>
|
||||
#include <boost/container/throw_exception.hpp>
|
||||
// container/detail
|
||||
#include <boost/container/detail/pool_common.hpp>
|
||||
#include <boost/container/detail/iterator.hpp>
|
||||
#include <boost/container/detail/iterator_to_raw_pointer.hpp>
|
||||
#include <boost/container/detail/math_functions.hpp>
|
||||
#include <boost/container/detail/mpl.hpp>
|
||||
#include <boost/container/detail/to_raw_pointer.hpp>
|
||||
#include <boost/container/detail/type_traits.hpp>
|
||||
// intrusive
|
||||
#include <boost/intrusive/pointer_traits.hpp>
|
||||
#include <boost/intrusive/set.hpp>
|
||||
#include <boost/intrusive/list.hpp>
|
||||
#include <boost/intrusive/slist.hpp>
|
||||
// other
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/core/no_exceptions_support.hpp>
|
||||
#include <cstddef>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
|
||||
namespace adaptive_pool_flag {
|
||||
|
||||
static const unsigned int none = 0u;
|
||||
static const unsigned int align_only = 1u << 0u;
|
||||
static const unsigned int size_ordered = 1u << 1u;
|
||||
static const unsigned int address_ordered = 1u << 2u;
|
||||
|
||||
} //namespace adaptive_pool_flag{
|
||||
|
||||
namespace container_detail {
|
||||
|
||||
template<class size_type>
|
||||
struct hdr_offset_holder_t
|
||||
{
|
||||
hdr_offset_holder_t(size_type offset = 0)
|
||||
: hdr_offset(offset)
|
||||
{}
|
||||
size_type hdr_offset;
|
||||
};
|
||||
|
||||
template<class SizeType, unsigned int Flags>
|
||||
struct less_func;
|
||||
|
||||
template<class SizeType>
|
||||
struct less_func<SizeType, adaptive_pool_flag::none>
|
||||
{
|
||||
static bool less(SizeType, SizeType, const void *, const void *)
|
||||
{ return true; }
|
||||
};
|
||||
|
||||
template<class SizeType>
|
||||
struct less_func<SizeType, adaptive_pool_flag::size_ordered>
|
||||
{
|
||||
static bool less(SizeType ls, SizeType rs, const void *, const void *)
|
||||
{ return ls < rs; }
|
||||
};
|
||||
|
||||
template<class SizeType>
|
||||
struct less_func<SizeType, adaptive_pool_flag::address_ordered>
|
||||
{
|
||||
static bool less(SizeType, SizeType, const void *la, const void *ra)
|
||||
{ return &la < &ra; }
|
||||
};
|
||||
|
||||
template<class SizeType>
|
||||
struct less_func<SizeType, adaptive_pool_flag::size_ordered | adaptive_pool_flag::address_ordered>
|
||||
{
|
||||
static bool less(SizeType ls, SizeType rs, const void *la, const void *ra)
|
||||
{ return (ls < rs) || ((ls == rs) && (la < ra)); }
|
||||
};
|
||||
|
||||
template<class VoidPointer, class SizeType, bool ordered>
|
||||
struct block_container_traits
|
||||
{
|
||||
typedef typename bi::make_set_base_hook
|
||||
< bi::void_pointer<VoidPointer>
|
||||
, bi::optimize_size<true>
|
||||
, bi::link_mode<bi::normal_link> >::type hook_t;
|
||||
|
||||
template<class T>
|
||||
struct container
|
||||
{
|
||||
typedef typename bi::make_multiset
|
||||
<T, bi::base_hook<hook_t>, bi::size_type<SizeType> >::type type;
|
||||
};
|
||||
|
||||
template<class Container>
|
||||
static void reinsert_was_used(Container &container, typename Container::reference v, bool)
|
||||
{
|
||||
typedef typename Container::const_iterator const_block_iterator;
|
||||
const const_block_iterator this_block
|
||||
(Container::s_iterator_to(const_cast<typename Container::const_reference>(v)));
|
||||
const_block_iterator next_block(this_block);
|
||||
if(++next_block != container.cend()){
|
||||
if(this_block->free_nodes.size() > next_block->free_nodes.size()){
|
||||
container.erase(this_block);
|
||||
container.insert(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<class Container>
|
||||
static void insert_was_empty(Container &container, typename Container::value_type &v, bool)
|
||||
{
|
||||
container.insert(v);
|
||||
}
|
||||
|
||||
template<class Container>
|
||||
static void erase_first(Container &container)
|
||||
{
|
||||
container.erase(container.cbegin());
|
||||
}
|
||||
|
||||
template<class Container>
|
||||
static void erase_last(Container &container)
|
||||
{
|
||||
container.erase(--container.cend());
|
||||
}
|
||||
};
|
||||
|
||||
template<class VoidPointer, class SizeType>
|
||||
struct block_container_traits<VoidPointer, SizeType, false>
|
||||
{
|
||||
typedef typename bi::make_list_base_hook
|
||||
< bi::void_pointer<VoidPointer>
|
||||
, bi::link_mode<bi::normal_link> >::type hook_t;
|
||||
|
||||
template<class T>
|
||||
struct container
|
||||
{
|
||||
typedef typename bi::make_list
|
||||
<T, bi::base_hook<hook_t>, bi::size_type<SizeType>, bi::constant_time_size<false> >::type type;
|
||||
};
|
||||
|
||||
template<class Container>
|
||||
static void reinsert_was_used(Container &container, typename Container::value_type &v, bool is_full)
|
||||
{
|
||||
if(is_full){
|
||||
container.erase(Container::s_iterator_to(v));
|
||||
container.push_back(v);
|
||||
}
|
||||
}
|
||||
|
||||
template<class Container>
|
||||
static void insert_was_empty(Container &container, typename Container::value_type &v, bool is_full)
|
||||
{
|
||||
if(is_full){
|
||||
container.push_back(v);
|
||||
}
|
||||
else{
|
||||
container.push_front(v);
|
||||
}
|
||||
}
|
||||
|
||||
template<class Container>
|
||||
static void erase_first(Container &container)
|
||||
{
|
||||
container.pop_front();
|
||||
}
|
||||
|
||||
template<class Container>
|
||||
static void erase_last(Container &container)
|
||||
{
|
||||
container.pop_back();
|
||||
}
|
||||
};
|
||||
|
||||
template<class MultiallocationChain, class VoidPointer, class SizeType, unsigned int Flags>
|
||||
struct adaptive_pool_types
|
||||
{
|
||||
typedef VoidPointer void_pointer;
|
||||
static const bool ordered = (Flags & (adaptive_pool_flag::size_ordered | adaptive_pool_flag::address_ordered)) != 0;
|
||||
typedef block_container_traits<VoidPointer, SizeType, ordered> block_container_traits_t;
|
||||
typedef typename block_container_traits_t::hook_t hook_t;
|
||||
typedef hdr_offset_holder_t<SizeType> hdr_offset_holder;
|
||||
static const unsigned int order_flags = Flags & (adaptive_pool_flag::size_ordered | adaptive_pool_flag::address_ordered);
|
||||
typedef MultiallocationChain free_nodes_t;
|
||||
|
||||
struct block_info_t
|
||||
: public hdr_offset_holder,
|
||||
public hook_t
|
||||
{
|
||||
//An intrusive list of free node from this block
|
||||
free_nodes_t free_nodes;
|
||||
friend bool operator <(const block_info_t &l, const block_info_t &r)
|
||||
{
|
||||
return less_func<SizeType, order_flags>::
|
||||
less(l.free_nodes.size(), r.free_nodes.size(), &l , &r);
|
||||
}
|
||||
|
||||
friend bool operator ==(const block_info_t &l, const block_info_t &r)
|
||||
{ return &l == &r; }
|
||||
};
|
||||
typedef typename block_container_traits_t:: template container<block_info_t>::type block_container_t;
|
||||
};
|
||||
|
||||
template<class size_type>
|
||||
inline size_type calculate_alignment
|
||||
( size_type overhead_percent, size_type real_node_size
|
||||
, size_type hdr_size, size_type hdr_offset_size, size_type payload_per_allocation)
|
||||
{
|
||||
//to-do: handle real_node_size != node_size
|
||||
const size_type divisor = overhead_percent*real_node_size;
|
||||
const size_type dividend = hdr_offset_size*100;
|
||||
size_type elements_per_subblock = (dividend - 1)/divisor + 1;
|
||||
size_type candidate_power_of_2 =
|
||||
upper_power_of_2(elements_per_subblock*real_node_size + hdr_offset_size);
|
||||
bool overhead_satisfied = false;
|
||||
//Now calculate the wors-case overhead for a subblock
|
||||
const size_type max_subblock_overhead = hdr_size + payload_per_allocation;
|
||||
while(!overhead_satisfied){
|
||||
elements_per_subblock = (candidate_power_of_2 - max_subblock_overhead)/real_node_size;
|
||||
const size_type overhead_size = candidate_power_of_2 - elements_per_subblock*real_node_size;
|
||||
if(overhead_size*100/candidate_power_of_2 < overhead_percent){
|
||||
overhead_satisfied = true;
|
||||
}
|
||||
else{
|
||||
candidate_power_of_2 <<= 1;
|
||||
}
|
||||
}
|
||||
return candidate_power_of_2;
|
||||
}
|
||||
|
||||
template<class size_type>
|
||||
inline void calculate_num_subblocks
|
||||
(size_type alignment, size_type real_node_size, size_type elements_per_block
|
||||
, size_type &num_subblocks, size_type &real_num_node, size_type overhead_percent
|
||||
, size_type hdr_size, size_type hdr_offset_size, size_type payload_per_allocation)
|
||||
{
|
||||
const size_type hdr_subblock_elements = (alignment - hdr_size - payload_per_allocation)/real_node_size;
|
||||
size_type elements_per_subblock = (alignment - hdr_offset_size)/real_node_size;
|
||||
size_type possible_num_subblock = (elements_per_block - 1)/elements_per_subblock + 1;
|
||||
while(((possible_num_subblock-1)*elements_per_subblock + hdr_subblock_elements) < elements_per_block){
|
||||
++possible_num_subblock;
|
||||
}
|
||||
elements_per_subblock = (alignment - hdr_offset_size)/real_node_size;
|
||||
bool overhead_satisfied = false;
|
||||
while(!overhead_satisfied){
|
||||
const size_type total_data = (elements_per_subblock*(possible_num_subblock-1) + hdr_subblock_elements)*real_node_size;
|
||||
const size_type total_size = alignment*possible_num_subblock;
|
||||
if((total_size - total_data)*100/total_size < overhead_percent){
|
||||
overhead_satisfied = true;
|
||||
}
|
||||
else{
|
||||
++possible_num_subblock;
|
||||
}
|
||||
}
|
||||
num_subblocks = possible_num_subblock;
|
||||
real_num_node = (possible_num_subblock-1)*elements_per_subblock + hdr_subblock_elements;
|
||||
}
|
||||
|
||||
template<class SegmentManagerBase, unsigned int Flags>
|
||||
class private_adaptive_node_pool_impl
|
||||
{
|
||||
//Non-copyable
|
||||
private_adaptive_node_pool_impl();
|
||||
private_adaptive_node_pool_impl(const private_adaptive_node_pool_impl &);
|
||||
private_adaptive_node_pool_impl &operator=(const private_adaptive_node_pool_impl &);
|
||||
typedef private_adaptive_node_pool_impl this_type;
|
||||
|
||||
typedef typename SegmentManagerBase::void_pointer void_pointer;
|
||||
static const typename SegmentManagerBase::
|
||||
size_type PayloadPerAllocation = SegmentManagerBase::PayloadPerAllocation;
|
||||
//Flags
|
||||
//align_only
|
||||
static const bool AlignOnly = (Flags & adaptive_pool_flag::align_only) != 0;
|
||||
typedef bool_<AlignOnly> IsAlignOnly;
|
||||
typedef true_ AlignOnlyTrue;
|
||||
typedef false_ AlignOnlyFalse;
|
||||
//size_ordered
|
||||
static const bool SizeOrdered = (Flags & adaptive_pool_flag::size_ordered) != 0;
|
||||
typedef bool_<SizeOrdered> IsSizeOrdered;
|
||||
typedef true_ SizeOrderedTrue;
|
||||
typedef false_ SizeOrderedFalse;
|
||||
//address_ordered
|
||||
static const bool AddressOrdered = (Flags & adaptive_pool_flag::address_ordered) != 0;
|
||||
typedef bool_<AddressOrdered> IsAddressOrdered;
|
||||
typedef true_ AddressOrderedTrue;
|
||||
typedef false_ AddressOrderedFalse;
|
||||
|
||||
public:
|
||||
typedef typename SegmentManagerBase::multiallocation_chain multiallocation_chain;
|
||||
typedef typename SegmentManagerBase::size_type size_type;
|
||||
|
||||
private:
|
||||
typedef adaptive_pool_types
|
||||
<multiallocation_chain, void_pointer, size_type, Flags> adaptive_pool_types_t;
|
||||
typedef typename adaptive_pool_types_t::free_nodes_t free_nodes_t;
|
||||
typedef typename adaptive_pool_types_t::block_info_t block_info_t;
|
||||
typedef typename adaptive_pool_types_t::block_container_t block_container_t;
|
||||
typedef typename adaptive_pool_types_t::block_container_traits_t block_container_traits_t;
|
||||
typedef typename block_container_t::iterator block_iterator;
|
||||
typedef typename block_container_t::const_iterator const_block_iterator;
|
||||
typedef typename adaptive_pool_types_t::hdr_offset_holder hdr_offset_holder;
|
||||
|
||||
static const size_type MaxAlign = alignment_of<void_pointer>::value;
|
||||
static const size_type HdrSize = ((sizeof(block_info_t)-1)/MaxAlign+1)*MaxAlign;
|
||||
static const size_type HdrOffsetSize = ((sizeof(hdr_offset_holder)-1)/MaxAlign+1)*MaxAlign;
|
||||
|
||||
public:
|
||||
//!Segment manager typedef
|
||||
typedef SegmentManagerBase segment_manager_base_type;
|
||||
|
||||
//!Constructor from a segment manager. Never throws
|
||||
private_adaptive_node_pool_impl
|
||||
( segment_manager_base_type *segment_mngr_base
|
||||
, size_type node_size
|
||||
, size_type nodes_per_block
|
||||
, size_type max_free_blocks
|
||||
, unsigned char overhead_percent
|
||||
)
|
||||
: m_max_free_blocks(max_free_blocks)
|
||||
, m_real_node_size(lcm(node_size, size_type(alignment_of<void_pointer>::value)))
|
||||
//Round the size to a power of two value.
|
||||
//This is the total memory size (including payload) that we want to
|
||||
//allocate from the general-purpose allocator
|
||||
, m_real_block_alignment
|
||||
(AlignOnly ?
|
||||
upper_power_of_2(HdrSize + m_real_node_size*nodes_per_block) :
|
||||
calculate_alignment( (size_type)overhead_percent, m_real_node_size
|
||||
, HdrSize, HdrOffsetSize, PayloadPerAllocation))
|
||||
//This is the real number of nodes per block
|
||||
, m_num_subblocks(0)
|
||||
, m_real_num_node(AlignOnly ? (m_real_block_alignment - PayloadPerAllocation - HdrSize)/m_real_node_size : 0)
|
||||
//General purpose allocator
|
||||
, mp_segment_mngr_base(segment_mngr_base)
|
||||
, m_block_container()
|
||||
, m_totally_free_blocks(0)
|
||||
{
|
||||
if(!AlignOnly){
|
||||
calculate_num_subblocks
|
||||
( m_real_block_alignment
|
||||
, m_real_node_size
|
||||
, nodes_per_block
|
||||
, m_num_subblocks
|
||||
, m_real_num_node
|
||||
, (size_type)overhead_percent
|
||||
, HdrSize
|
||||
, HdrOffsetSize
|
||||
, PayloadPerAllocation);
|
||||
}
|
||||
}
|
||||
|
||||
//!Destructor. Deallocates all allocated blocks. Never throws
|
||||
~private_adaptive_node_pool_impl()
|
||||
{ this->priv_clear(); }
|
||||
|
||||
size_type get_real_num_node() const
|
||||
{ return m_real_num_node; }
|
||||
|
||||
//!Returns the segment manager. Never throws
|
||||
segment_manager_base_type* get_segment_manager_base()const
|
||||
{ return container_detail::to_raw_pointer(mp_segment_mngr_base); }
|
||||
|
||||
//!Allocates array of count elements. Can throw
|
||||
void *allocate_node()
|
||||
{
|
||||
this->priv_invariants();
|
||||
//If there are no free nodes we allocate a new block
|
||||
if(!m_block_container.empty()){
|
||||
//We take the first free node the multiset can't be empty
|
||||
free_nodes_t &free_nodes = m_block_container.begin()->free_nodes;
|
||||
BOOST_ASSERT(!free_nodes.empty());
|
||||
const size_type free_nodes_count = free_nodes.size();
|
||||
void *first_node = container_detail::to_raw_pointer(free_nodes.pop_front());
|
||||
if(free_nodes.empty()){
|
||||
block_container_traits_t::erase_first(m_block_container);
|
||||
}
|
||||
m_totally_free_blocks -= static_cast<size_type>(free_nodes_count == m_real_num_node);
|
||||
this->priv_invariants();
|
||||
return first_node;
|
||||
}
|
||||
else{
|
||||
multiallocation_chain chain;
|
||||
this->priv_append_from_new_blocks(1, chain, IsAlignOnly());
|
||||
return container_detail::to_raw_pointer(chain.pop_front());
|
||||
}
|
||||
}
|
||||
|
||||
//!Deallocates an array pointed by ptr. Never throws
|
||||
void deallocate_node(void *pElem)
|
||||
{
|
||||
this->priv_invariants();
|
||||
block_info_t &block_info = *this->priv_block_from_node(pElem);
|
||||
BOOST_ASSERT(block_info.free_nodes.size() < m_real_num_node);
|
||||
|
||||
//We put the node at the beginning of the free node list
|
||||
block_info.free_nodes.push_back(void_pointer(pElem));
|
||||
|
||||
//The loop reinserts all blocks except the last one
|
||||
this->priv_reinsert_block(block_info, block_info.free_nodes.size() == 1);
|
||||
this->priv_deallocate_free_blocks(m_max_free_blocks);
|
||||
this->priv_invariants();
|
||||
}
|
||||
|
||||
//!Allocates n nodes.
|
||||
//!Can throw
|
||||
void allocate_nodes(const size_type n, multiallocation_chain &chain)
|
||||
{
|
||||
size_type i = 0;
|
||||
BOOST_TRY{
|
||||
this->priv_invariants();
|
||||
while(i != n){
|
||||
//If there are no free nodes we allocate all needed blocks
|
||||
if (m_block_container.empty()){
|
||||
this->priv_append_from_new_blocks(n - i, chain, IsAlignOnly());
|
||||
BOOST_ASSERT(m_block_container.empty() || (++m_block_container.cbegin() == m_block_container.cend()));
|
||||
BOOST_ASSERT(chain.size() == n);
|
||||
break;
|
||||
}
|
||||
free_nodes_t &free_nodes = m_block_container.begin()->free_nodes;
|
||||
const size_type free_nodes_count_before = free_nodes.size();
|
||||
m_totally_free_blocks -= static_cast<size_type>(free_nodes_count_before == m_real_num_node);
|
||||
const size_type num_left = n-i;
|
||||
const size_type num_elems = (num_left < free_nodes_count_before) ? num_left : free_nodes_count_before;
|
||||
typedef typename free_nodes_t::iterator free_nodes_iterator;
|
||||
|
||||
if(num_left < free_nodes_count_before){
|
||||
const free_nodes_iterator it_bbeg(free_nodes.before_begin());
|
||||
free_nodes_iterator it_bend(it_bbeg);
|
||||
for(size_type j = 0; j != num_elems; ++j){
|
||||
++it_bend;
|
||||
}
|
||||
free_nodes_iterator it_end = it_bend; ++it_end;
|
||||
free_nodes_iterator it_beg = it_bbeg; ++it_beg;
|
||||
free_nodes.erase_after(it_bbeg, it_end, num_elems);
|
||||
chain.incorporate_after(chain.last(), &*it_beg, &*it_bend, num_elems);
|
||||
//chain.splice_after(chain.last(), free_nodes, it_bbeg, it_bend, num_elems);
|
||||
BOOST_ASSERT(!free_nodes.empty());
|
||||
}
|
||||
else{
|
||||
const free_nodes_iterator it_beg(free_nodes.begin()), it_bend(free_nodes.last());
|
||||
free_nodes.clear();
|
||||
chain.incorporate_after(chain.last(), &*it_beg, &*it_bend, num_elems);
|
||||
block_container_traits_t::erase_first(m_block_container);
|
||||
}
|
||||
i += num_elems;
|
||||
}
|
||||
}
|
||||
BOOST_CATCH(...){
|
||||
this->deallocate_nodes(chain);
|
||||
BOOST_RETHROW
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
this->priv_invariants();
|
||||
}
|
||||
|
||||
//!Deallocates a linked list of nodes. Never throws
|
||||
void deallocate_nodes(multiallocation_chain &nodes)
|
||||
{
|
||||
this->priv_invariants();
|
||||
//To take advantage of node locality, wait until two
|
||||
//nodes belong to different blocks. Only then reinsert
|
||||
//the block of the first node in the block tree.
|
||||
//Cache of the previous block
|
||||
block_info_t *prev_block_info = 0;
|
||||
|
||||
//If block was empty before this call, it's not already
|
||||
//inserted in the block tree.
|
||||
bool prev_block_was_empty = false;
|
||||
typedef typename free_nodes_t::iterator free_nodes_iterator;
|
||||
{
|
||||
const free_nodes_iterator itbb(nodes.before_begin()), ite(nodes.end());
|
||||
free_nodes_iterator itf(nodes.begin()), itbf(itbb);
|
||||
size_type splice_node_count = size_type(-1);
|
||||
while(itf != ite){
|
||||
void *pElem = container_detail::to_raw_pointer(container_detail::iterator_to_raw_pointer(itf));
|
||||
block_info_t &block_info = *this->priv_block_from_node(pElem);
|
||||
BOOST_ASSERT(block_info.free_nodes.size() < m_real_num_node);
|
||||
++splice_node_count;
|
||||
|
||||
//If block change is detected calculate the cached block position in the tree
|
||||
if(&block_info != prev_block_info){
|
||||
if(prev_block_info){ //Make sure we skip the initial "dummy" cache
|
||||
free_nodes_iterator it(itbb); ++it;
|
||||
nodes.erase_after(itbb, itf, splice_node_count);
|
||||
prev_block_info->free_nodes.incorporate_after(prev_block_info->free_nodes.last(), &*it, &*itbf, splice_node_count);
|
||||
this->priv_reinsert_block(*prev_block_info, prev_block_was_empty);
|
||||
splice_node_count = 0;
|
||||
}
|
||||
//Update cache with new data
|
||||
prev_block_was_empty = block_info.free_nodes.empty();
|
||||
prev_block_info = &block_info;
|
||||
}
|
||||
itbf = itf;
|
||||
++itf;
|
||||
}
|
||||
}
|
||||
if(prev_block_info){
|
||||
//The loop reinserts all blocks except the last one
|
||||
const free_nodes_iterator itfirst(nodes.begin()), itlast(nodes.last());
|
||||
const size_type splice_node_count = nodes.size();
|
||||
nodes.clear();
|
||||
prev_block_info->free_nodes.incorporate_after(prev_block_info->free_nodes.last(), &*itfirst, &*itlast, splice_node_count);
|
||||
this->priv_reinsert_block(*prev_block_info, prev_block_was_empty);
|
||||
this->priv_invariants();
|
||||
this->priv_deallocate_free_blocks(m_max_free_blocks);
|
||||
}
|
||||
}
|
||||
|
||||
void deallocate_free_blocks()
|
||||
{ this->priv_deallocate_free_blocks(0); }
|
||||
|
||||
size_type num_free_nodes()
|
||||
{
|
||||
typedef typename block_container_t::const_iterator citerator;
|
||||
size_type count = 0;
|
||||
citerator it (m_block_container.begin()), itend(m_block_container.end());
|
||||
for(; it != itend; ++it){
|
||||
count += it->free_nodes.size();
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
void swap(private_adaptive_node_pool_impl &other)
|
||||
{
|
||||
BOOST_ASSERT(m_max_free_blocks == other.m_max_free_blocks);
|
||||
BOOST_ASSERT(m_real_node_size == other.m_real_node_size);
|
||||
BOOST_ASSERT(m_real_block_alignment == other.m_real_block_alignment);
|
||||
BOOST_ASSERT(m_real_num_node == other.m_real_num_node);
|
||||
std::swap(mp_segment_mngr_base, other.mp_segment_mngr_base);
|
||||
std::swap(m_totally_free_blocks, other.m_totally_free_blocks);
|
||||
m_block_container.swap(other.m_block_container);
|
||||
}
|
||||
|
||||
//Deprecated, use deallocate_free_blocks
|
||||
void deallocate_free_chunks()
|
||||
{ this->priv_deallocate_free_blocks(0); }
|
||||
|
||||
private:
|
||||
|
||||
void priv_deallocate_free_blocks(size_type max_free_blocks)
|
||||
{ //Trampoline function to ease inlining
|
||||
if(m_totally_free_blocks > max_free_blocks){
|
||||
this->priv_deallocate_free_blocks_impl(max_free_blocks);
|
||||
}
|
||||
}
|
||||
|
||||
void priv_deallocate_free_blocks_impl(size_type max_free_blocks)
|
||||
{
|
||||
this->priv_invariants();
|
||||
//Now check if we've reached the free nodes limit
|
||||
//and check if we have free blocks. If so, deallocate as much
|
||||
//as we can to stay below the limit
|
||||
multiallocation_chain chain;
|
||||
{
|
||||
const const_block_iterator itend = m_block_container.cend();
|
||||
const_block_iterator it = itend;
|
||||
--it;
|
||||
size_type totally_free_blocks = m_totally_free_blocks;
|
||||
|
||||
for( ; totally_free_blocks > max_free_blocks; --totally_free_blocks){
|
||||
BOOST_ASSERT(it->free_nodes.size() == m_real_num_node);
|
||||
void *addr = priv_first_subblock_from_block(const_cast<block_info_t*>(&*it));
|
||||
--it;
|
||||
block_container_traits_t::erase_last(m_block_container);
|
||||
chain.push_front(void_pointer(addr));
|
||||
}
|
||||
BOOST_ASSERT((m_totally_free_blocks - max_free_blocks) == chain.size());
|
||||
m_totally_free_blocks = max_free_blocks;
|
||||
}
|
||||
this->mp_segment_mngr_base->deallocate_many(chain);
|
||||
}
|
||||
|
||||
void priv_reinsert_block(block_info_t &prev_block_info, const bool prev_block_was_empty)
|
||||
{
|
||||
//Cache the free nodes from the block
|
||||
const size_type this_block_free_nodes = prev_block_info.free_nodes.size();
|
||||
const bool is_full = this_block_free_nodes == m_real_num_node;
|
||||
|
||||
//Update free block count
|
||||
m_totally_free_blocks += static_cast<size_type>(is_full);
|
||||
if(prev_block_was_empty){
|
||||
block_container_traits_t::insert_was_empty(m_block_container, prev_block_info, is_full);
|
||||
}
|
||||
else{
|
||||
block_container_traits_t::reinsert_was_used(m_block_container, prev_block_info, is_full);
|
||||
}
|
||||
}
|
||||
|
||||
class block_destroyer;
|
||||
friend class block_destroyer;
|
||||
|
||||
class block_destroyer
|
||||
{
|
||||
public:
|
||||
block_destroyer(const this_type *impl, multiallocation_chain &chain)
|
||||
: mp_impl(impl), m_chain(chain)
|
||||
{}
|
||||
|
||||
void operator()(typename block_container_t::pointer to_deallocate)
|
||||
{ return this->do_destroy(to_deallocate, IsAlignOnly()); }
|
||||
|
||||
private:
|
||||
void do_destroy(typename block_container_t::pointer to_deallocate, AlignOnlyTrue)
|
||||
{
|
||||
BOOST_ASSERT(to_deallocate->free_nodes.size() == mp_impl->m_real_num_node);
|
||||
m_chain.push_back(to_deallocate);
|
||||
}
|
||||
|
||||
void do_destroy(typename block_container_t::pointer to_deallocate, AlignOnlyFalse)
|
||||
{
|
||||
BOOST_ASSERT(to_deallocate->free_nodes.size() == mp_impl->m_real_num_node);
|
||||
BOOST_ASSERT(0 == to_deallocate->hdr_offset);
|
||||
hdr_offset_holder *hdr_off_holder =
|
||||
mp_impl->priv_first_subblock_from_block(container_detail::to_raw_pointer(to_deallocate));
|
||||
m_chain.push_back(hdr_off_holder);
|
||||
}
|
||||
|
||||
const this_type *mp_impl;
|
||||
multiallocation_chain &m_chain;
|
||||
};
|
||||
|
||||
//This macro will activate invariant checking. Slow, but helpful for debugging the code.
|
||||
//#define BOOST_CONTAINER_ADAPTIVE_NODE_POOL_CHECK_INVARIANTS
|
||||
void priv_invariants()
|
||||
#ifdef BOOST_CONTAINER_ADAPTIVE_NODE_POOL_CHECK_INVARIANTS
|
||||
#undef BOOST_CONTAINER_ADAPTIVE_NODE_POOL_CHECK_INVARIANTS
|
||||
{
|
||||
const const_block_iterator itend(m_block_container.end());
|
||||
|
||||
{ //We iterate through the block tree to free the memory
|
||||
const_block_iterator it(m_block_container.begin());
|
||||
|
||||
if(it != itend){
|
||||
for(++it; it != itend; ++it){
|
||||
const_block_iterator prev(it);
|
||||
--prev;
|
||||
BOOST_ASSERT(*prev < *it);
|
||||
(void)prev; (void)it;
|
||||
}
|
||||
}
|
||||
}
|
||||
{ //Check that the total free nodes are correct
|
||||
const_block_iterator it(m_block_container.cbegin());
|
||||
size_type total_free_nodes = 0;
|
||||
for(; it != itend; ++it){
|
||||
total_free_nodes += it->free_nodes.size();
|
||||
}
|
||||
BOOST_ASSERT(total_free_nodes >= m_totally_free_blocks*m_real_num_node);
|
||||
}
|
||||
{ //Check that the total totally free blocks are correct
|
||||
BOOST_ASSERT(m_block_container.size() >= m_totally_free_blocks);
|
||||
const_block_iterator it = m_block_container.cend();
|
||||
size_type total_free_blocks = m_totally_free_blocks;
|
||||
while(total_free_blocks--){
|
||||
BOOST_ASSERT((--it)->free_nodes.size() == m_real_num_node);
|
||||
}
|
||||
}
|
||||
|
||||
if(!AlignOnly){
|
||||
//Check that header offsets are correct
|
||||
const_block_iterator it = m_block_container.begin();
|
||||
for(; it != itend; ++it){
|
||||
hdr_offset_holder *hdr_off_holder = this->priv_first_subblock_from_block(const_cast<block_info_t *>(&*it));
|
||||
for(size_type i = 0, max = m_num_subblocks; i < max; ++i){
|
||||
const size_type offset = reinterpret_cast<char*>(const_cast<block_info_t *>(&*it)) - reinterpret_cast<char*>(hdr_off_holder);
|
||||
BOOST_ASSERT(hdr_off_holder->hdr_offset == offset);
|
||||
BOOST_ASSERT(0 == ((size_type)hdr_off_holder & (m_real_block_alignment - 1)));
|
||||
BOOST_ASSERT(0 == (hdr_off_holder->hdr_offset & (m_real_block_alignment - 1)));
|
||||
hdr_off_holder = reinterpret_cast<hdr_offset_holder *>(reinterpret_cast<char*>(hdr_off_holder) + m_real_block_alignment);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
{} //empty
|
||||
#endif
|
||||
|
||||
//!Deallocates all used memory. Never throws
|
||||
void priv_clear()
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
block_iterator it = m_block_container.begin();
|
||||
block_iterator itend = m_block_container.end();
|
||||
size_type n_free_nodes = 0;
|
||||
for(; it != itend; ++it){
|
||||
//Check for memory leak
|
||||
BOOST_ASSERT(it->free_nodes.size() == m_real_num_node);
|
||||
++n_free_nodes;
|
||||
}
|
||||
BOOST_ASSERT(n_free_nodes == m_totally_free_blocks);
|
||||
#endif
|
||||
//Check for memory leaks
|
||||
this->priv_invariants();
|
||||
multiallocation_chain chain;
|
||||
m_block_container.clear_and_dispose(block_destroyer(this, chain));
|
||||
this->mp_segment_mngr_base->deallocate_many(chain);
|
||||
m_totally_free_blocks = 0;
|
||||
}
|
||||
|
||||
block_info_t *priv_block_from_node(void *node, AlignOnlyFalse) const
|
||||
{
|
||||
hdr_offset_holder *hdr_off_holder =
|
||||
reinterpret_cast<hdr_offset_holder*>((std::size_t)node & size_type(~(m_real_block_alignment - 1)));
|
||||
BOOST_ASSERT(0 == ((std::size_t)hdr_off_holder & (m_real_block_alignment - 1)));
|
||||
BOOST_ASSERT(0 == (hdr_off_holder->hdr_offset & (m_real_block_alignment - 1)));
|
||||
block_info_t *block = reinterpret_cast<block_info_t *>
|
||||
(reinterpret_cast<char*>(hdr_off_holder) + hdr_off_holder->hdr_offset);
|
||||
BOOST_ASSERT(block->hdr_offset == 0);
|
||||
return block;
|
||||
}
|
||||
|
||||
block_info_t *priv_block_from_node(void *node, AlignOnlyTrue) const
|
||||
{
|
||||
return (block_info_t *)((std::size_t)node & std::size_t(~(m_real_block_alignment - 1)));
|
||||
}
|
||||
|
||||
block_info_t *priv_block_from_node(void *node) const
|
||||
{ return this->priv_block_from_node(node, IsAlignOnly()); }
|
||||
|
||||
hdr_offset_holder *priv_first_subblock_from_block(block_info_t *block) const
|
||||
{ return this->priv_first_subblock_from_block(block, IsAlignOnly()); }
|
||||
|
||||
hdr_offset_holder *priv_first_subblock_from_block(block_info_t *block, AlignOnlyFalse) const
|
||||
{
|
||||
hdr_offset_holder *const hdr_off_holder = reinterpret_cast<hdr_offset_holder*>
|
||||
(reinterpret_cast<char*>(block) - (m_num_subblocks-1)*m_real_block_alignment);
|
||||
BOOST_ASSERT(hdr_off_holder->hdr_offset == size_type(reinterpret_cast<char*>(block) - reinterpret_cast<char*>(hdr_off_holder)));
|
||||
BOOST_ASSERT(0 == ((std::size_t)hdr_off_holder & (m_real_block_alignment - 1)));
|
||||
BOOST_ASSERT(0 == (hdr_off_holder->hdr_offset & (m_real_block_alignment - 1)));
|
||||
return hdr_off_holder;
|
||||
}
|
||||
|
||||
hdr_offset_holder *priv_first_subblock_from_block(block_info_t *block, AlignOnlyTrue) const
|
||||
{
|
||||
return reinterpret_cast<hdr_offset_holder*>(block);
|
||||
}
|
||||
|
||||
void priv_dispatch_block_chain_or_free
|
||||
( multiallocation_chain &chain, block_info_t &c_info, size_type num_node
|
||||
, char *mem_address, size_type total_elements, bool insert_block_if_free)
|
||||
{
|
||||
BOOST_ASSERT(chain.size() <= total_elements);
|
||||
//First add all possible nodes to the chain
|
||||
const size_type left = total_elements - chain.size();
|
||||
const size_type max_chain = (num_node < left) ? num_node : left;
|
||||
mem_address = static_cast<char *>(container_detail::to_raw_pointer
|
||||
(chain.incorporate_after(chain.last(), void_pointer(mem_address), m_real_node_size, max_chain)));
|
||||
//Now store remaining nodes in the free list
|
||||
if(const size_type max_free = num_node - max_chain){
|
||||
free_nodes_t & free_nodes = c_info.free_nodes;
|
||||
free_nodes.incorporate_after(free_nodes.last(), void_pointer(mem_address), m_real_node_size, max_free);
|
||||
if(insert_block_if_free){
|
||||
m_block_container.push_front(c_info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//!Allocates a several blocks of nodes. Can throw
|
||||
void priv_append_from_new_blocks(size_type min_elements, multiallocation_chain &chain, AlignOnlyTrue)
|
||||
{
|
||||
BOOST_ASSERT(m_block_container.empty());
|
||||
BOOST_ASSERT(min_elements > 0);
|
||||
const size_type n = (min_elements - 1)/m_real_num_node + 1;
|
||||
const size_type real_block_size = m_real_block_alignment - PayloadPerAllocation;
|
||||
const size_type total_elements = chain.size() + min_elements;
|
||||
for(size_type i = 0; i != n; ++i){
|
||||
//We allocate a new NodeBlock and put it the last
|
||||
//element of the tree
|
||||
char *mem_address = static_cast<char*>
|
||||
(mp_segment_mngr_base->allocate_aligned(real_block_size, m_real_block_alignment));
|
||||
if(!mem_address){
|
||||
//In case of error, free memory deallocating all nodes (the new ones allocated
|
||||
//in this function plus previously stored nodes in chain).
|
||||
this->deallocate_nodes(chain);
|
||||
throw_bad_alloc();
|
||||
}
|
||||
block_info_t &c_info = *new(mem_address)block_info_t();
|
||||
mem_address += HdrSize;
|
||||
if(i != (n-1)){
|
||||
chain.incorporate_after(chain.last(), void_pointer(mem_address), m_real_node_size, m_real_num_node);
|
||||
}
|
||||
else{
|
||||
this->priv_dispatch_block_chain_or_free(chain, c_info, m_real_num_node, mem_address, total_elements, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void priv_append_from_new_blocks(size_type min_elements, multiallocation_chain &chain, AlignOnlyFalse)
|
||||
{
|
||||
BOOST_ASSERT(m_block_container.empty());
|
||||
BOOST_ASSERT(min_elements > 0);
|
||||
const size_type n = (min_elements - 1)/m_real_num_node + 1;
|
||||
const size_type real_block_size = m_real_block_alignment*m_num_subblocks - PayloadPerAllocation;
|
||||
const size_type elements_per_subblock = (m_real_block_alignment - HdrOffsetSize)/m_real_node_size;
|
||||
const size_type hdr_subblock_elements = (m_real_block_alignment - HdrSize - PayloadPerAllocation)/m_real_node_size;
|
||||
const size_type total_elements = chain.size() + min_elements;
|
||||
|
||||
for(size_type i = 0; i != n; ++i){
|
||||
//We allocate a new NodeBlock and put it the last
|
||||
//element of the tree
|
||||
char *mem_address = static_cast<char*>
|
||||
(mp_segment_mngr_base->allocate_aligned(real_block_size, m_real_block_alignment));
|
||||
if(!mem_address){
|
||||
//In case of error, free memory deallocating all nodes (the new ones allocated
|
||||
//in this function plus previously stored nodes in chain).
|
||||
this->deallocate_nodes(chain);
|
||||
throw_bad_alloc();
|
||||
}
|
||||
//First initialize header information on the last subblock
|
||||
char *hdr_addr = mem_address + m_real_block_alignment*(m_num_subblocks-1);
|
||||
block_info_t &c_info = *new(hdr_addr)block_info_t();
|
||||
//Some structural checks
|
||||
BOOST_ASSERT(static_cast<void*>(&static_cast<hdr_offset_holder&>(c_info).hdr_offset) ==
|
||||
static_cast<void*>(&c_info)); (void)c_info;
|
||||
if(i != (n-1)){
|
||||
for( size_type subblock = 0, maxsubblock = m_num_subblocks - 1
|
||||
; subblock < maxsubblock
|
||||
; ++subblock, mem_address += m_real_block_alignment){
|
||||
//Initialize header offset mark
|
||||
new(mem_address) hdr_offset_holder(size_type(hdr_addr - mem_address));
|
||||
chain.incorporate_after
|
||||
(chain.last(), void_pointer(mem_address + HdrOffsetSize), m_real_node_size, elements_per_subblock);
|
||||
}
|
||||
chain.incorporate_after(chain.last(), void_pointer(hdr_addr + HdrSize), m_real_node_size, hdr_subblock_elements);
|
||||
}
|
||||
else{
|
||||
for( size_type subblock = 0, maxsubblock = m_num_subblocks - 1
|
||||
; subblock < maxsubblock
|
||||
; ++subblock, mem_address += m_real_block_alignment){
|
||||
//Initialize header offset mark
|
||||
new(mem_address) hdr_offset_holder(size_type(hdr_addr - mem_address));
|
||||
this->priv_dispatch_block_chain_or_free
|
||||
(chain, c_info, elements_per_subblock, mem_address + HdrOffsetSize, total_elements, false);
|
||||
}
|
||||
this->priv_dispatch_block_chain_or_free
|
||||
(chain, c_info, hdr_subblock_elements, hdr_addr + HdrSize, total_elements, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
typedef typename boost::intrusive::pointer_traits
|
||||
<void_pointer>::template rebind_pointer<segment_manager_base_type>::type segment_mngr_base_ptr_t;
|
||||
const size_type m_max_free_blocks;
|
||||
const size_type m_real_node_size;
|
||||
//Round the size to a power of two value.
|
||||
//This is the total memory size (including payload) that we want to
|
||||
//allocate from the general-purpose allocator
|
||||
const size_type m_real_block_alignment;
|
||||
size_type m_num_subblocks;
|
||||
//This is the real number of nodes per block
|
||||
//const
|
||||
size_type m_real_num_node;
|
||||
segment_mngr_base_ptr_t mp_segment_mngr_base; //Segment manager
|
||||
block_container_t m_block_container; //Intrusive block list
|
||||
size_type m_totally_free_blocks; //Free blocks
|
||||
};
|
||||
|
||||
} //namespace container_detail {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DETAIL_ADAPTIVE_NODE_POOL_IMPL_HPP
|
||||
@@ -0,0 +1,41 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2014-2015. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#ifndef BOOST_CONTAINER_DETAIL_ADDRESSOF_HPP
|
||||
#define BOOST_CONTAINER_DETAIL_ADDRESSOF_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace container_detail {
|
||||
|
||||
template <typename T>
|
||||
BOOST_CONTAINER_FORCEINLINE T* addressof(T& obj)
|
||||
{
|
||||
return static_cast<T*>(
|
||||
static_cast<void*>(
|
||||
const_cast<char*>(
|
||||
&reinterpret_cast<const volatile char&>(obj)
|
||||
)));
|
||||
}
|
||||
|
||||
} //namespace container_detail {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DETAIL_ADDRESSOF_HPP
|
||||
@@ -0,0 +1,477 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2008-2013. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_ADVANCED_INSERT_INT_HPP
|
||||
#define BOOST_CONTAINER_ADVANCED_INSERT_INT_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/detail/config_begin.hpp>
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
|
||||
// container
|
||||
#include <boost/container/allocator_traits.hpp>
|
||||
// container/detail
|
||||
#include <boost/container/detail/copy_move_algo.hpp>
|
||||
#include <boost/container/detail/destroyers.hpp>
|
||||
#include <boost/container/detail/mpl.hpp>
|
||||
#include <boost/container/detail/type_traits.hpp>
|
||||
#include <boost/container/detail/iterator.hpp>
|
||||
#include <boost/container/detail/iterators.hpp>
|
||||
#include <boost/container/detail/iterator_to_raw_pointer.hpp>
|
||||
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
#include <boost/move/detail/fwd_macros.hpp>
|
||||
#endif
|
||||
// move
|
||||
#include <boost/move/utility_core.hpp>
|
||||
// other
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/core/no_exceptions_support.hpp>
|
||||
|
||||
namespace boost { namespace container { namespace container_detail {
|
||||
|
||||
template<class Allocator, class FwdIt, class Iterator>
|
||||
struct move_insert_range_proxy
|
||||
{
|
||||
typedef typename allocator_traits<Allocator>::size_type size_type;
|
||||
typedef typename allocator_traits<Allocator>::value_type value_type;
|
||||
|
||||
explicit move_insert_range_proxy(FwdIt first)
|
||||
: first_(first)
|
||||
{}
|
||||
|
||||
void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n)
|
||||
{
|
||||
this->first_ = ::boost::container::uninitialized_move_alloc_n_source
|
||||
(a, this->first_, n, p);
|
||||
}
|
||||
|
||||
void copy_n_and_update(Allocator &, Iterator p, size_type n)
|
||||
{
|
||||
this->first_ = ::boost::container::move_n_source(this->first_, n, p);
|
||||
}
|
||||
|
||||
FwdIt first_;
|
||||
};
|
||||
|
||||
|
||||
template<class Allocator, class FwdIt, class Iterator>
|
||||
struct insert_range_proxy
|
||||
{
|
||||
typedef typename allocator_traits<Allocator>::size_type size_type;
|
||||
typedef typename allocator_traits<Allocator>::value_type value_type;
|
||||
|
||||
explicit insert_range_proxy(FwdIt first)
|
||||
: first_(first)
|
||||
{}
|
||||
|
||||
void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n)
|
||||
{
|
||||
this->first_ = ::boost::container::uninitialized_copy_alloc_n_source(a, this->first_, n, p);
|
||||
}
|
||||
|
||||
void copy_n_and_update(Allocator &, Iterator p, size_type n)
|
||||
{
|
||||
this->first_ = ::boost::container::copy_n_source(this->first_, n, p);
|
||||
}
|
||||
|
||||
FwdIt first_;
|
||||
};
|
||||
|
||||
|
||||
template<class Allocator, class Iterator>
|
||||
struct insert_n_copies_proxy
|
||||
{
|
||||
typedef typename allocator_traits<Allocator>::size_type size_type;
|
||||
typedef typename allocator_traits<Allocator>::value_type value_type;
|
||||
|
||||
explicit insert_n_copies_proxy(const value_type &v)
|
||||
: v_(v)
|
||||
{}
|
||||
|
||||
void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n) const
|
||||
{ boost::container::uninitialized_fill_alloc_n(a, v_, n, p); }
|
||||
|
||||
void copy_n_and_update(Allocator &, Iterator p, size_type n) const
|
||||
{
|
||||
for (; 0 < n; --n, ++p){
|
||||
*p = v_;
|
||||
}
|
||||
}
|
||||
|
||||
const value_type &v_;
|
||||
};
|
||||
|
||||
template<class Allocator, class Iterator>
|
||||
struct insert_value_initialized_n_proxy
|
||||
{
|
||||
typedef ::boost::container::allocator_traits<Allocator> alloc_traits;
|
||||
typedef typename allocator_traits<Allocator>::size_type size_type;
|
||||
typedef typename allocator_traits<Allocator>::value_type value_type;
|
||||
|
||||
void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n) const
|
||||
{ boost::container::uninitialized_value_init_alloc_n(a, n, p); }
|
||||
|
||||
void copy_n_and_update(Allocator &, Iterator, size_type) const
|
||||
{ BOOST_ASSERT(false); }
|
||||
};
|
||||
|
||||
template<class Allocator, class Iterator>
|
||||
struct insert_default_initialized_n_proxy
|
||||
{
|
||||
typedef ::boost::container::allocator_traits<Allocator> alloc_traits;
|
||||
typedef typename allocator_traits<Allocator>::size_type size_type;
|
||||
typedef typename allocator_traits<Allocator>::value_type value_type;
|
||||
|
||||
void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n) const
|
||||
{ boost::container::uninitialized_default_init_alloc_n(a, n, p); }
|
||||
|
||||
void copy_n_and_update(Allocator &, Iterator, size_type) const
|
||||
{ BOOST_ASSERT(false); }
|
||||
};
|
||||
|
||||
template<class Allocator, class Iterator>
|
||||
struct insert_copy_proxy
|
||||
{
|
||||
typedef boost::container::allocator_traits<Allocator> alloc_traits;
|
||||
typedef typename alloc_traits::size_type size_type;
|
||||
typedef typename alloc_traits::value_type value_type;
|
||||
|
||||
explicit insert_copy_proxy(const value_type &v)
|
||||
: v_(v)
|
||||
{}
|
||||
|
||||
void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n) const
|
||||
{
|
||||
BOOST_ASSERT(n == 1); (void)n;
|
||||
alloc_traits::construct( a, iterator_to_raw_pointer(p), v_);
|
||||
}
|
||||
|
||||
void copy_n_and_update(Allocator &, Iterator p, size_type n) const
|
||||
{
|
||||
BOOST_ASSERT(n == 1); (void)n;
|
||||
*p =v_;
|
||||
}
|
||||
|
||||
const value_type &v_;
|
||||
};
|
||||
|
||||
|
||||
template<class Allocator, class Iterator>
|
||||
struct insert_move_proxy
|
||||
{
|
||||
typedef boost::container::allocator_traits<Allocator> alloc_traits;
|
||||
typedef typename alloc_traits::size_type size_type;
|
||||
typedef typename alloc_traits::value_type value_type;
|
||||
|
||||
explicit insert_move_proxy(value_type &v)
|
||||
: v_(v)
|
||||
{}
|
||||
|
||||
void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n) const
|
||||
{
|
||||
BOOST_ASSERT(n == 1); (void)n;
|
||||
alloc_traits::construct( a, iterator_to_raw_pointer(p), ::boost::move(v_) );
|
||||
}
|
||||
|
||||
void copy_n_and_update(Allocator &, Iterator p, size_type n) const
|
||||
{
|
||||
BOOST_ASSERT(n == 1); (void)n;
|
||||
*p = ::boost::move(v_);
|
||||
}
|
||||
|
||||
value_type &v_;
|
||||
};
|
||||
|
||||
template<class It, class Allocator>
|
||||
insert_move_proxy<Allocator, It> get_insert_value_proxy(BOOST_RV_REF(typename boost::container::iterator_traits<It>::value_type) v)
|
||||
{
|
||||
return insert_move_proxy<Allocator, It>(v);
|
||||
}
|
||||
|
||||
template<class It, class Allocator>
|
||||
insert_copy_proxy<Allocator, It> get_insert_value_proxy(const typename boost::container::iterator_traits<It>::value_type &v)
|
||||
{
|
||||
return insert_copy_proxy<Allocator, It>(v);
|
||||
}
|
||||
|
||||
}}} //namespace boost { namespace container { namespace container_detail {
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
#include <boost/container/detail/variadic_templates_tools.hpp>
|
||||
#include <boost/move/utility_core.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace container_detail {
|
||||
|
||||
template<class Allocator, class Iterator, class ...Args>
|
||||
struct insert_nonmovable_emplace_proxy
|
||||
{
|
||||
typedef boost::container::allocator_traits<Allocator> alloc_traits;
|
||||
typedef typename alloc_traits::size_type size_type;
|
||||
typedef typename alloc_traits::value_type value_type;
|
||||
|
||||
typedef typename build_number_seq<sizeof...(Args)>::type index_tuple_t;
|
||||
|
||||
explicit insert_nonmovable_emplace_proxy(BOOST_FWD_REF(Args)... args)
|
||||
: args_(args...)
|
||||
{}
|
||||
|
||||
void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n)
|
||||
{ this->priv_uninitialized_copy_some_and_update(a, index_tuple_t(), p, n); }
|
||||
|
||||
private:
|
||||
template<std::size_t ...IdxPack>
|
||||
void priv_uninitialized_copy_some_and_update(Allocator &a, const index_tuple<IdxPack...>&, Iterator p, size_type n)
|
||||
{
|
||||
BOOST_ASSERT(n == 1); (void)n;
|
||||
alloc_traits::construct( a, iterator_to_raw_pointer(p), ::boost::forward<Args>(get<IdxPack>(this->args_))... );
|
||||
}
|
||||
|
||||
protected:
|
||||
tuple<Args&...> args_;
|
||||
};
|
||||
|
||||
template<class Allocator, class Iterator, class ...Args>
|
||||
struct insert_emplace_proxy
|
||||
: public insert_nonmovable_emplace_proxy<Allocator, Iterator, Args...>
|
||||
{
|
||||
typedef insert_nonmovable_emplace_proxy<Allocator, Iterator, Args...> base_t;
|
||||
typedef boost::container::allocator_traits<Allocator> alloc_traits;
|
||||
typedef typename base_t::value_type value_type;
|
||||
typedef typename base_t::size_type size_type;
|
||||
typedef typename base_t::index_tuple_t index_tuple_t;
|
||||
|
||||
explicit insert_emplace_proxy(BOOST_FWD_REF(Args)... args)
|
||||
: base_t(::boost::forward<Args>(args)...)
|
||||
{}
|
||||
|
||||
void copy_n_and_update(Allocator &a, Iterator p, size_type n)
|
||||
{ this->priv_copy_some_and_update(a, index_tuple_t(), p, n); }
|
||||
|
||||
private:
|
||||
|
||||
template<std::size_t ...IdxPack>
|
||||
void priv_copy_some_and_update(Allocator &a, const index_tuple<IdxPack...>&, Iterator p, size_type n)
|
||||
{
|
||||
BOOST_ASSERT(n ==1); (void)n;
|
||||
typename aligned_storage<sizeof(value_type), alignment_of<value_type>::value>::type v;
|
||||
value_type *vp = static_cast<value_type *>(static_cast<void *>(&v));
|
||||
alloc_traits::construct(a, vp,
|
||||
::boost::forward<Args>(get<IdxPack>(this->args_))...);
|
||||
BOOST_TRY{
|
||||
*p = ::boost::move(*vp);
|
||||
}
|
||||
BOOST_CATCH(...){
|
||||
alloc_traits::destroy(a, vp);
|
||||
BOOST_RETHROW
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
alloc_traits::destroy(a, vp);
|
||||
}
|
||||
};
|
||||
|
||||
//Specializations to avoid an unneeded temporary when emplacing from a single argument o type value_type
|
||||
template<class Allocator, class Iterator>
|
||||
struct insert_emplace_proxy<Allocator, Iterator, typename boost::container::allocator_traits<Allocator>::value_type>
|
||||
: public insert_move_proxy<Allocator, Iterator>
|
||||
{
|
||||
explicit insert_emplace_proxy(typename boost::container::allocator_traits<Allocator>::value_type &&v)
|
||||
: insert_move_proxy<Allocator, Iterator>(v)
|
||||
{}
|
||||
};
|
||||
|
||||
//We use "add_const" here as adding "const" only confuses MSVC12(and maybe later) provoking
|
||||
//compiler error C2752 ("more than one partial specialization matches").
|
||||
//Any problem is solvable with an extra layer of indirection? ;-)
|
||||
template<class Allocator, class Iterator>
|
||||
struct insert_emplace_proxy<Allocator, Iterator
|
||||
, typename boost::container::container_detail::add_const<typename boost::container::allocator_traits<Allocator>::value_type>::type
|
||||
>
|
||||
: public insert_copy_proxy<Allocator, Iterator>
|
||||
{
|
||||
explicit insert_emplace_proxy(const typename boost::container::allocator_traits<Allocator>::value_type &v)
|
||||
: insert_copy_proxy<Allocator, Iterator>(v)
|
||||
{}
|
||||
};
|
||||
|
||||
template<class Allocator, class Iterator>
|
||||
struct insert_emplace_proxy<Allocator, Iterator, typename boost::container::allocator_traits<Allocator>::value_type &>
|
||||
: public insert_copy_proxy<Allocator, Iterator>
|
||||
{
|
||||
explicit insert_emplace_proxy(const typename boost::container::allocator_traits<Allocator>::value_type &v)
|
||||
: insert_copy_proxy<Allocator, Iterator>(v)
|
||||
{}
|
||||
};
|
||||
|
||||
template<class Allocator, class Iterator>
|
||||
struct insert_emplace_proxy<Allocator, Iterator
|
||||
, typename boost::container::container_detail::add_const<typename boost::container::allocator_traits<Allocator>::value_type>::type &
|
||||
>
|
||||
: public insert_copy_proxy<Allocator, Iterator>
|
||||
{
|
||||
explicit insert_emplace_proxy(const typename boost::container::allocator_traits<Allocator>::value_type &v)
|
||||
: insert_copy_proxy<Allocator, Iterator>(v)
|
||||
{}
|
||||
};
|
||||
|
||||
}}} //namespace boost { namespace container { namespace container_detail {
|
||||
|
||||
#else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
#include <boost/container/detail/value_init.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace container_detail {
|
||||
|
||||
#define BOOST_CONTAINER_ADVANCED_INSERT_INT_CODE(N) \
|
||||
template< class Allocator, class Iterator BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
|
||||
struct insert_nonmovable_emplace_proxy##N\
|
||||
{\
|
||||
typedef boost::container::allocator_traits<Allocator> alloc_traits;\
|
||||
typedef typename alloc_traits::size_type size_type;\
|
||||
typedef typename alloc_traits::value_type value_type;\
|
||||
\
|
||||
explicit insert_nonmovable_emplace_proxy##N(BOOST_MOVE_UREF##N)\
|
||||
BOOST_MOVE_COLON##N BOOST_MOVE_FWD_INIT##N {}\
|
||||
\
|
||||
void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n)\
|
||||
{\
|
||||
BOOST_ASSERT(n == 1); (void)n;\
|
||||
alloc_traits::construct(a, iterator_to_raw_pointer(p) BOOST_MOVE_I##N BOOST_MOVE_MFWD##N);\
|
||||
}\
|
||||
\
|
||||
void copy_n_and_update(Allocator &, Iterator, size_type)\
|
||||
{ BOOST_ASSERT(false); }\
|
||||
\
|
||||
protected:\
|
||||
BOOST_MOVE_MREF##N\
|
||||
};\
|
||||
\
|
||||
template< class Allocator, class Iterator BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
|
||||
struct insert_emplace_proxy_arg##N\
|
||||
: insert_nonmovable_emplace_proxy##N< Allocator, Iterator BOOST_MOVE_I##N BOOST_MOVE_TARG##N >\
|
||||
{\
|
||||
typedef insert_nonmovable_emplace_proxy##N\
|
||||
< Allocator, Iterator BOOST_MOVE_I##N BOOST_MOVE_TARG##N > base_t;\
|
||||
typedef typename base_t::value_type value_type;\
|
||||
typedef typename base_t::size_type size_type;\
|
||||
typedef boost::container::allocator_traits<Allocator> alloc_traits;\
|
||||
\
|
||||
explicit insert_emplace_proxy_arg##N(BOOST_MOVE_UREF##N)\
|
||||
: base_t(BOOST_MOVE_FWD##N){}\
|
||||
\
|
||||
void copy_n_and_update(Allocator &a, Iterator p, size_type n)\
|
||||
{\
|
||||
BOOST_ASSERT(n == 1); (void)n;\
|
||||
typename aligned_storage<sizeof(value_type), alignment_of<value_type>::value>::type v;\
|
||||
BOOST_ASSERT((((size_type)(&v)) % alignment_of<value_type>::value) == 0);\
|
||||
value_type *vp = static_cast<value_type *>(static_cast<void *>(&v));\
|
||||
alloc_traits::construct(a, vp BOOST_MOVE_I##N BOOST_MOVE_MFWD##N);\
|
||||
BOOST_TRY{\
|
||||
*p = ::boost::move(*vp);\
|
||||
}\
|
||||
BOOST_CATCH(...){\
|
||||
alloc_traits::destroy(a, vp);\
|
||||
BOOST_RETHROW\
|
||||
}\
|
||||
BOOST_CATCH_END\
|
||||
alloc_traits::destroy(a, vp);\
|
||||
}\
|
||||
};\
|
||||
//
|
||||
BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_ADVANCED_INSERT_INT_CODE)
|
||||
#undef BOOST_CONTAINER_ADVANCED_INSERT_INT_CODE
|
||||
|
||||
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
|
||||
//Specializations to avoid an unneeded temporary when emplacing from a single argument o type value_type
|
||||
template<class Allocator, class Iterator>
|
||||
struct insert_emplace_proxy_arg1<Allocator, Iterator, ::boost::rv<typename boost::container::allocator_traits<Allocator>::value_type> >
|
||||
: public insert_move_proxy<Allocator, Iterator>
|
||||
{
|
||||
explicit insert_emplace_proxy_arg1(typename boost::container::allocator_traits<Allocator>::value_type &v)
|
||||
: insert_move_proxy<Allocator, Iterator>(v)
|
||||
{}
|
||||
};
|
||||
|
||||
template<class Allocator, class Iterator>
|
||||
struct insert_emplace_proxy_arg1<Allocator, Iterator, typename boost::container::allocator_traits<Allocator>::value_type>
|
||||
: public insert_copy_proxy<Allocator, Iterator>
|
||||
{
|
||||
explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<Allocator>::value_type &v)
|
||||
: insert_copy_proxy<Allocator, Iterator>(v)
|
||||
{}
|
||||
};
|
||||
|
||||
#else //e.g. MSVC10 & MSVC11
|
||||
|
||||
//Specializations to avoid an unneeded temporary when emplacing from a single argument o type value_type
|
||||
template<class Allocator, class Iterator>
|
||||
struct insert_emplace_proxy_arg1<Allocator, Iterator, typename boost::container::allocator_traits<Allocator>::value_type>
|
||||
: public insert_move_proxy<Allocator, Iterator>
|
||||
{
|
||||
explicit insert_emplace_proxy_arg1(typename boost::container::allocator_traits<Allocator>::value_type &&v)
|
||||
: insert_move_proxy<Allocator, Iterator>(v)
|
||||
{}
|
||||
};
|
||||
|
||||
//We use "add_const" here as adding "const" only confuses MSVC10&11 provoking
|
||||
//compiler error C2752 ("more than one partial specialization matches").
|
||||
//Any problem is solvable with an extra layer of indirection? ;-)
|
||||
template<class Allocator, class Iterator>
|
||||
struct insert_emplace_proxy_arg1<Allocator, Iterator
|
||||
, typename boost::container::container_detail::add_const<typename boost::container::allocator_traits<Allocator>::value_type>::type
|
||||
>
|
||||
: public insert_copy_proxy<Allocator, Iterator>
|
||||
{
|
||||
explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<Allocator>::value_type &v)
|
||||
: insert_copy_proxy<Allocator, Iterator>(v)
|
||||
{}
|
||||
};
|
||||
|
||||
template<class Allocator, class Iterator>
|
||||
struct insert_emplace_proxy_arg1<Allocator, Iterator, typename boost::container::allocator_traits<Allocator>::value_type &>
|
||||
: public insert_copy_proxy<Allocator, Iterator>
|
||||
{
|
||||
explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<Allocator>::value_type &v)
|
||||
: insert_copy_proxy<Allocator, Iterator>(v)
|
||||
{}
|
||||
};
|
||||
|
||||
template<class Allocator, class Iterator>
|
||||
struct insert_emplace_proxy_arg1<Allocator, Iterator
|
||||
, typename boost::container::container_detail::add_const<typename boost::container::allocator_traits<Allocator>::value_type>::type &
|
||||
>
|
||||
: public insert_copy_proxy<Allocator, Iterator>
|
||||
{
|
||||
explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<Allocator>::value_type &v)
|
||||
: insert_copy_proxy<Allocator, Iterator>(v)
|
||||
{}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
}}} //namespace boost { namespace container { namespace container_detail {
|
||||
|
||||
#endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_ADVANCED_INSERT_INT_HPP
|
||||
@@ -0,0 +1,35 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2014-2014.
|
||||
//
|
||||
// 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_DETAIL_ALGORITHM_HPP
|
||||
#define BOOST_CONTAINER_DETAIL_ALGORITHM_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/intrusive/detail/algorithm.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
|
||||
using boost::intrusive::algo_equal;
|
||||
using boost::intrusive::algo_lexicographical_compare;
|
||||
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DETAIL_ALGORITHM_HPP
|
||||
@@ -0,0 +1,60 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2014-2015. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#ifndef BOOST_CONTAINER_DETAIL_ALLOC_TRAITS_HPP
|
||||
#define BOOST_CONTAINER_DETAIL_ALLOC_TRAITS_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
// move
|
||||
#include <boost/move/adl_move_swap.hpp>
|
||||
#include <boost/move/utility_core.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace container_detail {
|
||||
|
||||
template<class AllocatorType>
|
||||
inline void swap_alloc(AllocatorType &, AllocatorType &, container_detail::false_type)
|
||||
BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{}
|
||||
|
||||
template<class AllocatorType>
|
||||
inline void swap_alloc(AllocatorType &l, AllocatorType &r, container_detail::true_type)
|
||||
{ boost::adl_move_swap(l, r); }
|
||||
|
||||
template<class AllocatorType>
|
||||
inline void assign_alloc(AllocatorType &, const AllocatorType &, container_detail::false_type)
|
||||
BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{}
|
||||
|
||||
template<class AllocatorType>
|
||||
inline void assign_alloc(AllocatorType &l, const AllocatorType &r, container_detail::true_type)
|
||||
{ l = r; }
|
||||
|
||||
template<class AllocatorType>
|
||||
inline void move_alloc(AllocatorType &, AllocatorType &, container_detail::false_type)
|
||||
BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{}
|
||||
|
||||
template<class AllocatorType>
|
||||
inline void move_alloc(AllocatorType &l, AllocatorType &r, container_detail::true_type)
|
||||
{ l = ::boost::move(r); }
|
||||
|
||||
} //namespace container_detail {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DETAIL_ALLOC_TRAITS_HPP
|
||||
@@ -0,0 +1,314 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2013. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#ifndef BOOST_CONTAINER_ALLOC_LIB_EXT_H
|
||||
#define BOOST_CONTAINER_ALLOC_LIB_EXT_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable : 4127)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*!An forward iterator to traverse the elements of a memory chain container.*/
|
||||
typedef struct multialloc_node_impl
|
||||
{
|
||||
struct multialloc_node_impl *next_node_ptr;
|
||||
} boost_cont_memchain_node;
|
||||
|
||||
|
||||
/*!An forward iterator to traverse the elements of a memory chain container.*/
|
||||
typedef struct multialloc_it_impl
|
||||
{
|
||||
boost_cont_memchain_node *node_ptr;
|
||||
} boost_cont_memchain_it;
|
||||
|
||||
/*!Memory chain: A container holding memory portions allocated by boost_cont_multialloc_nodes
|
||||
and boost_cont_multialloc_arrays functions.*/
|
||||
typedef struct boost_cont_memchain_impl
|
||||
{
|
||||
size_t num_mem;
|
||||
boost_cont_memchain_node root_node;
|
||||
boost_cont_memchain_node *last_node_ptr;
|
||||
} boost_cont_memchain;
|
||||
|
||||
/*!Advances the iterator one position so that it points to the next element in the memory chain*/
|
||||
#define BOOST_CONTAINER_MEMIT_NEXT(IT) (IT.node_ptr = IT.node_ptr->next_node_ptr)
|
||||
|
||||
/*!Returns the address of the memory chain currently pointed by the iterator*/
|
||||
#define BOOST_CONTAINER_MEMIT_ADDR(IT) ((void*)IT.node_ptr)
|
||||
|
||||
/*!Initializer for an iterator pointing to the position before the first element*/
|
||||
#define BOOST_CONTAINER_MEMCHAIN_BEFORE_BEGIN_IT(PMEMCHAIN) { &((PMEMCHAIN)->root_node) }
|
||||
|
||||
/*!Initializer for an iterator pointing to the first element*/
|
||||
#define BOOST_CONTAINER_MEMCHAIN_BEGIN_IT(PMEMCHAIN) {(PMEMCHAIN)->root_node.next_node_ptr }
|
||||
|
||||
/*!Initializer for an iterator pointing to the last element*/
|
||||
#define BOOST_CONTAINER_MEMCHAIN_LAST_IT(PMEMCHAIN) {(PMEMCHAIN)->last_node_ptr }
|
||||
|
||||
/*!Initializer for an iterator pointing to one past the last element (end iterator)*/
|
||||
#define BOOST_CONTAINER_MEMCHAIN_END_IT(PMEMCHAIN) {(boost_cont_memchain_node *)0 }
|
||||
|
||||
/*!True if IT is the end iterator, false otherwise*/
|
||||
#define BOOST_CONTAINER_MEMCHAIN_IS_END_IT(PMEMCHAIN, IT) (!(IT).node_ptr)
|
||||
|
||||
/*!The address of the first memory portion hold by the memory chain*/
|
||||
#define BOOST_CONTAINER_MEMCHAIN_FIRSTMEM(PMEMCHAIN)((void*)((PMEMCHAIN)->root_node.next_node_ptr))
|
||||
|
||||
/*!The address of the last memory portion hold by the memory chain*/
|
||||
#define BOOST_CONTAINER_MEMCHAIN_LASTMEM(PMEMCHAIN) ((void*)((PMEMCHAIN)->last_node_ptr))
|
||||
|
||||
/*!The number of memory portions hold by the memory chain*/
|
||||
#define BOOST_CONTAINER_MEMCHAIN_SIZE(PMEMCHAIN) ((PMEMCHAIN)->num_mem)
|
||||
|
||||
/*!Initializes the memory chain from the first memory portion, the last memory
|
||||
portion and number of portions obtained from another memory chain*/
|
||||
#define BOOST_CONTAINER_MEMCHAIN_INIT_FROM(PMEMCHAIN, FIRST, LAST, NUM)\
|
||||
(PMEMCHAIN)->last_node_ptr = (boost_cont_memchain_node *)(LAST), \
|
||||
(PMEMCHAIN)->root_node.next_node_ptr = (boost_cont_memchain_node *)(FIRST), \
|
||||
(PMEMCHAIN)->num_mem = (NUM);\
|
||||
/**/
|
||||
|
||||
/*!Default initializes a memory chain. Postconditions: begin iterator is end iterator,
|
||||
the number of portions is zero.*/
|
||||
#define BOOST_CONTAINER_MEMCHAIN_INIT(PMEMCHAIN)\
|
||||
((PMEMCHAIN)->root_node.next_node_ptr = 0, (PMEMCHAIN)->last_node_ptr = &((PMEMCHAIN)->root_node), (PMEMCHAIN)->num_mem = 0)\
|
||||
/**/
|
||||
|
||||
/*!True if the memory chain is empty (holds no memory portions*/
|
||||
#define BOOST_CONTAINER_MEMCHAIN_EMPTY(PMEMCHAIN)\
|
||||
((PMEMCHAIN)->num_mem == 0)\
|
||||
/**/
|
||||
|
||||
/*!Inserts a new memory portions in the front of the chain*/
|
||||
#define BOOST_CONTAINER_MEMCHAIN_PUSH_BACK(PMEMCHAIN, MEM)\
|
||||
do{\
|
||||
boost_cont_memchain *____chain____ = (PMEMCHAIN);\
|
||||
boost_cont_memchain_node *____tmp_mem____ = (boost_cont_memchain_node *)(MEM);\
|
||||
____chain____->last_node_ptr->next_node_ptr = ____tmp_mem____;\
|
||||
____tmp_mem____->next_node_ptr = 0;\
|
||||
____chain____->last_node_ptr = ____tmp_mem____;\
|
||||
++____chain____->num_mem;\
|
||||
}while(0)\
|
||||
/**/
|
||||
|
||||
/*!Inserts a new memory portions in the back of the chain*/
|
||||
#define BOOST_CONTAINER_MEMCHAIN_PUSH_FRONT(PMEMCHAIN, MEM)\
|
||||
do{\
|
||||
boost_cont_memchain *____chain____ = (PMEMCHAIN);\
|
||||
boost_cont_memchain_node *____tmp_mem____ = (boost_cont_memchain_node *)(MEM);\
|
||||
boost_cont_memchain *____root____ = &((PMEMCHAIN)->root_node);\
|
||||
if(!____chain____->root_node.next_node_ptr){\
|
||||
____chain____->last_node_ptr = ____tmp_mem____;\
|
||||
}\
|
||||
boost_cont_memchain_node *____old_first____ = ____root____->next_node_ptr;\
|
||||
____tmp_mem____->next_node_ptr = ____old_first____;\
|
||||
____root____->next_node_ptr = ____tmp_mem____;\
|
||||
++____chain____->num_mem;\
|
||||
}while(0)\
|
||||
/**/
|
||||
|
||||
/*!Erases the memory portion after the portion pointed by BEFORE_IT from the memory chain*/
|
||||
/*!Precondition: BEFORE_IT must be a valid iterator of the memory chain and it can't be the end iterator*/
|
||||
#define BOOST_CONTAINER_MEMCHAIN_ERASE_AFTER(PMEMCHAIN, BEFORE_IT)\
|
||||
do{\
|
||||
boost_cont_memchain *____chain____ = (PMEMCHAIN);\
|
||||
boost_cont_memchain_node *____prev_node____ = (BEFORE_IT).node_ptr;\
|
||||
boost_cont_memchain_node *____erase_node____ = ____prev_node____->next_node_ptr;\
|
||||
if(____chain____->last_node_ptr == ____erase_node____){\
|
||||
____chain____->last_node_ptr = &____chain____->root_node;\
|
||||
}\
|
||||
____prev_node____->next_node_ptr = ____erase_node____->next_node_ptr;\
|
||||
--____chain____->num_mem;\
|
||||
}while(0)\
|
||||
/**/
|
||||
|
||||
/*!Erases the first portion from the memory chain.
|
||||
Precondition: the memory chain must not be empty*/
|
||||
#define BOOST_CONTAINER_MEMCHAIN_POP_FRONT(PMEMCHAIN)\
|
||||
do{\
|
||||
boost_cont_memchain *____chain____ = (PMEMCHAIN);\
|
||||
boost_cont_memchain_node *____prev_node____ = &____chain____->root_node;\
|
||||
boost_cont_memchain_node *____erase_node____ = ____prev_node____->next_node_ptr;\
|
||||
if(____chain____->last_node_ptr == ____erase_node____){\
|
||||
____chain____->last_node_ptr = &____chain____->root_node;\
|
||||
}\
|
||||
____prev_node____->next_node_ptr = ____erase_node____->next_node_ptr;\
|
||||
--____chain____->num_mem;\
|
||||
}while(0)\
|
||||
/**/
|
||||
|
||||
/*!Joins two memory chains inserting the portions of the second chain at the back of the first chain*/
|
||||
/*
|
||||
#define BOOST_CONTAINER_MEMCHAIN_SPLICE_BACK(PMEMCHAIN, PMEMCHAIN2)\
|
||||
do{\
|
||||
boost_cont_memchain *____chain____ = (PMEMCHAIN);\
|
||||
boost_cont_memchain *____chain2____ = (PMEMCHAIN2);\
|
||||
if(!____chain2____->root_node.next_node_ptr){\
|
||||
break;\
|
||||
}\
|
||||
else if(!____chain____->first_mem){\
|
||||
____chain____->first_mem = ____chain2____->first_mem;\
|
||||
____chain____->last_node_ptr = ____chain2____->last_node_ptr;\
|
||||
____chain____->num_mem = ____chain2____->num_mem;\
|
||||
BOOST_CONTAINER_MEMCHAIN_INIT(*____chain2____);\
|
||||
}\
|
||||
else{\
|
||||
____chain____->last_node_ptr->next_node_ptr = ____chain2____->first_mem;\
|
||||
____chain____->last_node_ptr = ____chain2____->last_node_ptr;\
|
||||
____chain____->num_mem += ____chain2____->num_mem;\
|
||||
}\
|
||||
}while(0)\*/
|
||||
/**/
|
||||
|
||||
/*!Joins two memory chains inserting the portions of the second chain at the back of the first chain*/
|
||||
#define BOOST_CONTAINER_MEMCHAIN_INCORPORATE_AFTER(PMEMCHAIN, BEFORE_IT, FIRST, BEFORELAST, NUM)\
|
||||
do{\
|
||||
boost_cont_memchain *____chain____ = (PMEMCHAIN);\
|
||||
boost_cont_memchain_node *____pnode____ = (BEFORE_IT).node_ptr;\
|
||||
boost_cont_memchain_node *____next____ = ____pnode____->next_node_ptr;\
|
||||
boost_cont_memchain_node *____first____ = (boost_cont_memchain_node *)(FIRST);\
|
||||
boost_cont_memchain_node *____blast____ = (boost_cont_memchain_node *)(BEFORELAST);\
|
||||
size_t ____num____ = (NUM);\
|
||||
if(!____num____){\
|
||||
break;\
|
||||
}\
|
||||
if(____pnode____ == ____chain____->last_node_ptr){\
|
||||
____chain____->last_node_ptr = ____blast____;\
|
||||
}\
|
||||
____pnode____->next_node_ptr = ____first____;\
|
||||
____blast____->next_node_ptr = ____next____;\
|
||||
____chain____->num_mem += ____num____;\
|
||||
}while(0)\
|
||||
/**/
|
||||
|
||||
/*!Indicates the all elements allocated by boost_cont_multialloc_nodes or boost_cont_multialloc_arrays
|
||||
must be contiguous.*/
|
||||
#define DL_MULTIALLOC_ALL_CONTIGUOUS ((size_t)(-1))
|
||||
|
||||
/*!Indicates the number of contiguous elements allocated by boost_cont_multialloc_nodes or boost_cont_multialloc_arrays
|
||||
should be selected by those functions.*/
|
||||
#define DL_MULTIALLOC_DEFAULT_CONTIGUOUS ((size_t)(0))
|
||||
|
||||
typedef struct boost_cont_malloc_stats_impl
|
||||
{
|
||||
size_t max_system_bytes;
|
||||
size_t system_bytes;
|
||||
size_t in_use_bytes;
|
||||
} boost_cont_malloc_stats_t;
|
||||
|
||||
typedef unsigned int allocation_type;
|
||||
|
||||
enum
|
||||
{
|
||||
// constants for allocation commands
|
||||
BOOST_CONTAINER_ALLOCATE_NEW = 0X01,
|
||||
BOOST_CONTAINER_EXPAND_FWD = 0X02,
|
||||
BOOST_CONTAINER_EXPAND_BWD = 0X04,
|
||||
BOOST_CONTAINER_SHRINK_IN_PLACE = 0X08,
|
||||
BOOST_CONTAINER_NOTHROW_ALLOCATION = 0X10,
|
||||
// BOOST_CONTAINER_ZERO_MEMORY = 0X20,
|
||||
BOOST_CONTAINER_TRY_SHRINK_IN_PLACE = 0X40,
|
||||
BOOST_CONTAINER_EXPAND_BOTH = BOOST_CONTAINER_EXPAND_FWD | BOOST_CONTAINER_EXPAND_BWD,
|
||||
BOOST_CONTAINER_EXPAND_OR_NEW = BOOST_CONTAINER_ALLOCATE_NEW | BOOST_CONTAINER_EXPAND_BOTH
|
||||
};
|
||||
|
||||
//#define BOOST_CONTAINERDLMALLOC__FOOTERS
|
||||
#ifndef BOOST_CONTAINERDLMALLOC__FOOTERS
|
||||
enum { BOOST_CONTAINER_ALLOCATION_PAYLOAD = sizeof(size_t) };
|
||||
#else
|
||||
enum { BOOST_CONTAINER_ALLOCATION_PAYLOAD = sizeof(size_t)*2 };
|
||||
#endif
|
||||
|
||||
typedef struct boost_cont_command_ret_impl
|
||||
{
|
||||
void *first;
|
||||
int second;
|
||||
}boost_cont_command_ret_t;
|
||||
|
||||
size_t boost_cont_size(const void *p);
|
||||
|
||||
void* boost_cont_malloc(size_t bytes);
|
||||
|
||||
void boost_cont_free(void* mem);
|
||||
|
||||
void* boost_cont_memalign(size_t bytes, size_t alignment);
|
||||
|
||||
int boost_cont_multialloc_nodes
|
||||
(size_t n_elements, size_t elem_size, size_t contiguous_elements, boost_cont_memchain *pchain);
|
||||
|
||||
int boost_cont_multialloc_arrays
|
||||
(size_t n_elements, const size_t *sizes, size_t sizeof_element, size_t contiguous_elements, boost_cont_memchain *pchain);
|
||||
|
||||
void boost_cont_multidealloc(boost_cont_memchain *pchain);
|
||||
|
||||
size_t boost_cont_footprint();
|
||||
|
||||
size_t boost_cont_allocated_memory();
|
||||
|
||||
size_t boost_cont_chunksize(const void *p);
|
||||
|
||||
int boost_cont_all_deallocated();
|
||||
|
||||
boost_cont_malloc_stats_t boost_cont_malloc_stats();
|
||||
|
||||
size_t boost_cont_in_use_memory();
|
||||
|
||||
int boost_cont_trim(size_t pad);
|
||||
|
||||
int boost_cont_mallopt(int parameter_number, int parameter_value);
|
||||
|
||||
int boost_cont_grow
|
||||
(void* oldmem, size_t minbytes, size_t maxbytes, size_t *received);
|
||||
|
||||
int boost_cont_shrink
|
||||
(void* oldmem, size_t minbytes, size_t maxbytes, size_t *received, int do_commit);
|
||||
|
||||
void* boost_cont_alloc
|
||||
(size_t minbytes, size_t preferred_bytes, size_t *received_bytes);
|
||||
|
||||
int boost_cont_malloc_check();
|
||||
|
||||
boost_cont_command_ret_t boost_cont_allocation_command
|
||||
( allocation_type command
|
||||
, size_t sizeof_object
|
||||
, size_t limit_objects
|
||||
, size_t preferred_objects
|
||||
, size_t *received_objects
|
||||
, void *reuse_ptr
|
||||
);
|
||||
|
||||
void *boost_cont_sync_create();
|
||||
|
||||
void boost_cont_sync_destroy(void *sync);
|
||||
|
||||
int boost_cont_sync_lock(void *sync);
|
||||
|
||||
void boost_cont_sync_unlock(void *sync);
|
||||
|
||||
int boost_cont_global_sync_lock();
|
||||
|
||||
void boost_cont_global_sync_unlock();
|
||||
|
||||
#ifdef __cplusplus
|
||||
} //extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (pop)
|
||||
#endif
|
||||
|
||||
|
||||
#endif //#define BOOST_CONTAINERDLMALLOC__EXT_H
|
||||
@@ -0,0 +1,58 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2013. 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/container for documentation.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_ALLOCATION_TYPE_HPP
|
||||
#define BOOST_CONTAINER_ALLOCATION_TYPE_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/detail/config_begin.hpp>
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
enum allocation_type_v
|
||||
{
|
||||
// constants for allocation commands
|
||||
allocate_new_v = 0x01,
|
||||
expand_fwd_v = 0x02,
|
||||
expand_bwd_v = 0x04,
|
||||
// expand_both = expand_fwd | expand_bwd,
|
||||
// expand_or_new = allocate_new | expand_both,
|
||||
shrink_in_place_v = 0x08,
|
||||
nothrow_allocation_v = 0x10,
|
||||
zero_memory_v = 0x20,
|
||||
try_shrink_in_place_v = 0x40
|
||||
};
|
||||
|
||||
typedef unsigned int allocation_type;
|
||||
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
static const allocation_type allocate_new = (allocation_type)allocate_new_v;
|
||||
static const allocation_type expand_fwd = (allocation_type)expand_fwd_v;
|
||||
static const allocation_type expand_bwd = (allocation_type)expand_bwd_v;
|
||||
static const allocation_type shrink_in_place = (allocation_type)shrink_in_place_v;
|
||||
static const allocation_type try_shrink_in_place= (allocation_type)try_shrink_in_place_v;
|
||||
static const allocation_type nothrow_allocation = (allocation_type)nothrow_allocation_v;
|
||||
static const allocation_type zero_memory = (allocation_type)zero_memory_v;
|
||||
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_CONTAINER_ALLOCATION_TYPE_HPP
|
||||
+162
@@ -0,0 +1,162 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2012-2013. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_DETAIL_ALLOCATOR_VERSION_TRAITS_HPP
|
||||
#define BOOST_CONTAINER_DETAIL_ALLOCATOR_VERSION_TRAITS_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/detail/config_begin.hpp>
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
|
||||
#include <boost/container/allocator_traits.hpp> //allocator_traits
|
||||
#include <boost/container/throw_exception.hpp>
|
||||
#include <boost/container/detail/multiallocation_chain.hpp> //multiallocation_chain
|
||||
#include <boost/container/detail/version_type.hpp> //version_type
|
||||
#include <boost/container/detail/allocation_type.hpp> //allocation_type
|
||||
#include <boost/container/detail/mpl.hpp> //integral_constant
|
||||
#include <boost/intrusive/pointer_traits.hpp> //pointer_traits
|
||||
#include <boost/core/no_exceptions_support.hpp> //BOOST_TRY
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace container_detail {
|
||||
|
||||
template<class Allocator, unsigned Version = boost::container::container_detail::version<Allocator>::value>
|
||||
struct allocator_version_traits
|
||||
{
|
||||
typedef ::boost::container::container_detail::integral_constant
|
||||
<unsigned, Version> alloc_version;
|
||||
|
||||
typedef typename Allocator::multiallocation_chain multiallocation_chain;
|
||||
|
||||
typedef typename boost::container::allocator_traits<Allocator>::pointer pointer;
|
||||
typedef typename boost::container::allocator_traits<Allocator>::size_type size_type;
|
||||
|
||||
//Node allocation interface
|
||||
static pointer allocate_one(Allocator &a)
|
||||
{ return a.allocate_one(); }
|
||||
|
||||
static void deallocate_one(Allocator &a, const pointer &p)
|
||||
{ a.deallocate_one(p); }
|
||||
|
||||
static void allocate_individual(Allocator &a, size_type n, multiallocation_chain &m)
|
||||
{ return a.allocate_individual(n, m); }
|
||||
|
||||
static void deallocate_individual(Allocator &a, multiallocation_chain &holder)
|
||||
{ a.deallocate_individual(holder); }
|
||||
|
||||
static pointer allocation_command(Allocator &a, allocation_type command,
|
||||
size_type limit_size, size_type &prefer_in_recvd_out_size, pointer &reuse)
|
||||
{ return a.allocation_command(command, limit_size, prefer_in_recvd_out_size, reuse); }
|
||||
};
|
||||
|
||||
template<class Allocator>
|
||||
struct allocator_version_traits<Allocator, 1>
|
||||
{
|
||||
typedef ::boost::container::container_detail::integral_constant
|
||||
<unsigned, 1> alloc_version;
|
||||
|
||||
typedef typename boost::container::allocator_traits<Allocator>::pointer pointer;
|
||||
typedef typename boost::container::allocator_traits<Allocator>::size_type size_type;
|
||||
typedef typename boost::container::allocator_traits<Allocator>::value_type value_type;
|
||||
|
||||
typedef typename boost::intrusive::pointer_traits<pointer>::
|
||||
template rebind_pointer<void>::type void_ptr;
|
||||
typedef container_detail::basic_multiallocation_chain
|
||||
<void_ptr> multialloc_cached_counted;
|
||||
typedef boost::container::container_detail::
|
||||
transform_multiallocation_chain
|
||||
< multialloc_cached_counted, value_type> multiallocation_chain;
|
||||
|
||||
//Node allocation interface
|
||||
static pointer allocate_one(Allocator &a)
|
||||
{ return a.allocate(1); }
|
||||
|
||||
static void deallocate_one(Allocator &a, const pointer &p)
|
||||
{ a.deallocate(p, 1); }
|
||||
|
||||
static void deallocate_individual(Allocator &a, multiallocation_chain &holder)
|
||||
{
|
||||
size_type n = holder.size();
|
||||
typename multiallocation_chain::iterator it = holder.begin();
|
||||
while(n--){
|
||||
pointer p = boost::intrusive::pointer_traits<pointer>::pointer_to(*it);
|
||||
++it;
|
||||
a.deallocate(p, 1);
|
||||
}
|
||||
}
|
||||
|
||||
struct allocate_individual_rollback
|
||||
{
|
||||
allocate_individual_rollback(Allocator &a, multiallocation_chain &chain)
|
||||
: mr_a(a), mp_chain(&chain)
|
||||
{}
|
||||
|
||||
~allocate_individual_rollback()
|
||||
{
|
||||
if(mp_chain)
|
||||
allocator_version_traits::deallocate_individual(mr_a, *mp_chain);
|
||||
}
|
||||
|
||||
void release()
|
||||
{
|
||||
mp_chain = 0;
|
||||
}
|
||||
|
||||
Allocator &mr_a;
|
||||
multiallocation_chain * mp_chain;
|
||||
};
|
||||
|
||||
static void allocate_individual(Allocator &a, size_type n, multiallocation_chain &m)
|
||||
{
|
||||
allocate_individual_rollback rollback(a, m);
|
||||
while(n--){
|
||||
m.push_front(a.allocate(1));
|
||||
}
|
||||
rollback.release();
|
||||
}
|
||||
|
||||
static pointer allocation_command(Allocator &a, allocation_type command,
|
||||
size_type, size_type &prefer_in_recvd_out_size, pointer &reuse)
|
||||
{
|
||||
pointer ret = pointer();
|
||||
if(BOOST_UNLIKELY(!(command & allocate_new) && !(command & nothrow_allocation))){
|
||||
throw_logic_error("version 1 allocator without allocate_new flag");
|
||||
}
|
||||
else{
|
||||
BOOST_TRY{
|
||||
ret = a.allocate(prefer_in_recvd_out_size);
|
||||
}
|
||||
BOOST_CATCH(...){
|
||||
if(!(command & nothrow_allocation)){
|
||||
BOOST_RETHROW
|
||||
}
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
reuse = pointer();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
} //namespace container_detail {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif // ! defined(BOOST_CONTAINER_DETAIL_ALLOCATOR_VERSION_TRAITS_HPP)
|
||||
@@ -0,0 +1,51 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2007-2013. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#ifndef BOOST_CONTAINER_DETAIL_AUTO_LINK_HPP_INCLUDED
|
||||
#define BOOST_CONTAINER_DETAIL_AUTO_LINK_HPP_INCLUDED
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
//Define BOOST_CONTAINER_DYNAMIC_LINKING which is independent from BOOST_*_NO_LIB
|
||||
//and is needed is some tests that need to disable some checks (like operator new replacements)
|
||||
//that don't work across DLL boundaries
|
||||
#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_CONTAINER_DYN_LINK)
|
||||
# define BOOST_CONTAINER_DYNAMIC_LINKING
|
||||
#endif
|
||||
|
||||
//
|
||||
// Automatically link to the correct build variant where possible.
|
||||
//
|
||||
#if !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_CONTAINER_NO_LIB) && !defined(BOOST_CONTAINER_SOURCE)
|
||||
//
|
||||
// Set the name of our library, this will get undef'ed by auto_link.hpp
|
||||
// once it's done with it:
|
||||
//
|
||||
#define BOOST_LIB_NAME boost_container
|
||||
|
||||
//
|
||||
// If we're importing code from a dll, then tell auto_link.hpp about it:
|
||||
//
|
||||
#if defined(BOOST_CONTAINER_DYNAMIC_LINKING)
|
||||
# define BOOST_DYN_LINK
|
||||
#endif
|
||||
|
||||
//
|
||||
// And include the header that does the work:
|
||||
//
|
||||
#include <boost/config/auto_link.hpp>
|
||||
#endif // auto-linking disabled
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DETAIL_AUTO_LINK_HPP_INCLUDED
|
||||
@@ -0,0 +1,139 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_DETAIL_BLOCK_LIST_HEADER
|
||||
#define BOOST_CONTAINER_DETAIL_BLOCK_LIST_HEADER
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/detail/config_begin.hpp>
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
#include <boost/container/container_fwd.hpp>
|
||||
#include <boost/container/pmr/memory_resource.hpp>
|
||||
#include <boost/container/throw_exception.hpp>
|
||||
#include <boost/intrusive/circular_list_algorithms.hpp>
|
||||
#include <boost/move/detail/type_traits.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace pmr {
|
||||
|
||||
struct list_node
|
||||
{
|
||||
list_node *next;
|
||||
list_node *previous;
|
||||
};
|
||||
|
||||
struct list_node_traits
|
||||
{
|
||||
typedef list_node node;
|
||||
typedef list_node* node_ptr;
|
||||
typedef const list_node* const_node_ptr;
|
||||
|
||||
static node_ptr get_next(const_node_ptr n)
|
||||
{ return n->next; }
|
||||
|
||||
static node_ptr get_previous(const_node_ptr n)
|
||||
{ return n->previous; }
|
||||
|
||||
static void set_next(const node_ptr & n, const node_ptr & next)
|
||||
{ n->next = next; }
|
||||
|
||||
static void set_previous(const node_ptr & n, const node_ptr & previous)
|
||||
{ n->previous = previous; }
|
||||
};
|
||||
|
||||
struct block_list_header
|
||||
: public list_node
|
||||
{
|
||||
std::size_t size;
|
||||
};
|
||||
|
||||
typedef bi::circular_list_algorithms<list_node_traits> list_algo;
|
||||
|
||||
|
||||
template<class DerivedFromBlockListHeader = block_list_header>
|
||||
class block_list_base
|
||||
{
|
||||
list_node m_list;
|
||||
|
||||
static const std::size_t MaxAlignMinus1 = memory_resource::max_align-1u;
|
||||
|
||||
public:
|
||||
|
||||
static const std::size_t header_size = std::size_t(sizeof(DerivedFromBlockListHeader) + MaxAlignMinus1) & std::size_t(~MaxAlignMinus1);
|
||||
|
||||
explicit block_list_base()
|
||||
{ list_algo::init_header(&m_list); }
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
block_list_base(const block_list_base&) = delete;
|
||||
block_list_base operator=(const block_list_base&) = delete;
|
||||
#else
|
||||
private:
|
||||
block_list_base (const block_list_base&);
|
||||
block_list_base operator=(const block_list_base&);
|
||||
public:
|
||||
#endif
|
||||
|
||||
~block_list_base()
|
||||
{}
|
||||
|
||||
void *allocate(std::size_t size, memory_resource &mr)
|
||||
{
|
||||
if((size_t(-1) - header_size) < size)
|
||||
throw_bad_alloc();
|
||||
void *p = mr.allocate(size+header_size);
|
||||
block_list_header &mb = *::new((void*)p) DerivedFromBlockListHeader;
|
||||
mb.size = size+header_size;
|
||||
list_algo::link_after(&m_list, &mb);
|
||||
return (char *)p + header_size;
|
||||
}
|
||||
|
||||
void deallocate(void *p, memory_resource &mr) BOOST_NOEXCEPT
|
||||
{
|
||||
DerivedFromBlockListHeader *pheader = static_cast<DerivedFromBlockListHeader*>
|
||||
(static_cast<void*>((char*)p - header_size));
|
||||
list_algo::unlink(pheader);
|
||||
const std::size_t size = pheader->size;
|
||||
static_cast<DerivedFromBlockListHeader*>(pheader)->~DerivedFromBlockListHeader();
|
||||
mr.deallocate(pheader, size, memory_resource::max_align);
|
||||
}
|
||||
|
||||
void release(memory_resource &mr) BOOST_NOEXCEPT
|
||||
{
|
||||
list_node *n = list_algo::node_traits::get_next(&m_list);
|
||||
while(n != &m_list){
|
||||
DerivedFromBlockListHeader &d = static_cast<DerivedFromBlockListHeader&>(*n);
|
||||
n = list_algo::node_traits::get_next(n);
|
||||
std::size_t size = d.size;
|
||||
d.~DerivedFromBlockListHeader();
|
||||
mr.deallocate(reinterpret_cast<char*>(&d), size, memory_resource::max_align);
|
||||
}
|
||||
list_algo::init_header(&m_list);
|
||||
}
|
||||
};
|
||||
|
||||
} //namespace pmr {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_CONTAINER_DETAIL_BLOCK_LIST_HEADER
|
||||
@@ -0,0 +1,157 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_DETAIL_BLOCK_SLIST_HEADER
|
||||
#define BOOST_CONTAINER_DETAIL_BLOCK_SLIST_HEADER
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
|
||||
#include <boost/container/detail/config_begin.hpp>
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
#include <boost/container/container_fwd.hpp>
|
||||
#include <boost/container/pmr/memory_resource.hpp>
|
||||
#include <boost/container/throw_exception.hpp>
|
||||
|
||||
#include <boost/move/detail/type_traits.hpp>
|
||||
#include <boost/intrusive/linear_slist_algorithms.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace pmr {
|
||||
|
||||
struct slist_node
|
||||
{
|
||||
slist_node *next;
|
||||
};
|
||||
|
||||
struct slist_node_traits
|
||||
{
|
||||
typedef slist_node node;
|
||||
typedef slist_node* node_ptr;
|
||||
typedef const slist_node* const_node_ptr;
|
||||
|
||||
static node_ptr get_next(const_node_ptr n)
|
||||
{ return n->next; }
|
||||
|
||||
static void set_next(const node_ptr & n, const node_ptr & next)
|
||||
{ n->next = next; }
|
||||
};
|
||||
|
||||
struct block_slist_header
|
||||
: public slist_node
|
||||
{
|
||||
std::size_t size;
|
||||
};
|
||||
|
||||
typedef bi::linear_slist_algorithms<slist_node_traits> slist_algo;
|
||||
|
||||
template<class DerivedFromBlockSlistHeader = block_slist_header>
|
||||
class block_slist_base
|
||||
{
|
||||
slist_node m_slist;
|
||||
|
||||
static const std::size_t MaxAlignMinus1 = memory_resource::max_align-1u;
|
||||
|
||||
public:
|
||||
|
||||
static const std::size_t header_size = std::size_t(sizeof(DerivedFromBlockSlistHeader) + MaxAlignMinus1) & std::size_t(~MaxAlignMinus1);
|
||||
|
||||
explicit block_slist_base()
|
||||
{ slist_algo::init_header(&m_slist); }
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
block_slist_base(const block_slist_base&) = delete;
|
||||
block_slist_base operator=(const block_slist_base&) = delete;
|
||||
#else
|
||||
private:
|
||||
block_slist_base (const block_slist_base&);
|
||||
block_slist_base operator=(const block_slist_base&);
|
||||
public:
|
||||
#endif
|
||||
|
||||
~block_slist_base()
|
||||
{}
|
||||
|
||||
void *allocate(std::size_t size, memory_resource &mr)
|
||||
{
|
||||
if((size_t(-1) - header_size) < size)
|
||||
throw_bad_alloc();
|
||||
void *p = mr.allocate(size+header_size);
|
||||
block_slist_header &mb = *::new((void*)p) DerivedFromBlockSlistHeader;
|
||||
mb.size = size+header_size;
|
||||
slist_algo::link_after(&m_slist, &mb);
|
||||
return (char *)p + header_size;
|
||||
}
|
||||
|
||||
void release(memory_resource &mr) BOOST_NOEXCEPT
|
||||
{
|
||||
slist_node *n = slist_algo::node_traits::get_next(&m_slist);
|
||||
while(n){
|
||||
DerivedFromBlockSlistHeader &d = static_cast<DerivedFromBlockSlistHeader&>(*n);
|
||||
n = slist_algo::node_traits::get_next(n);
|
||||
std::size_t size = d.block_slist_header::size;
|
||||
d.~DerivedFromBlockSlistHeader();
|
||||
mr.deallocate(reinterpret_cast<char*>(&d), size, memory_resource::max_align);
|
||||
}
|
||||
slist_algo::init_header(&m_slist);
|
||||
}
|
||||
};
|
||||
|
||||
class block_slist
|
||||
: public block_slist_base<>
|
||||
{
|
||||
memory_resource &m_upstream_rsrc;
|
||||
|
||||
public:
|
||||
|
||||
explicit block_slist(memory_resource &upstream_rsrc)
|
||||
: block_slist_base<>(), m_upstream_rsrc(upstream_rsrc)
|
||||
{}
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
block_slist(const block_slist&) = delete;
|
||||
block_slist operator=(const block_slist&) = delete;
|
||||
#else
|
||||
private:
|
||||
block_slist (const block_slist&);
|
||||
block_slist operator=(const block_slist&);
|
||||
public:
|
||||
#endif
|
||||
|
||||
~block_slist()
|
||||
{ this->release(); }
|
||||
|
||||
void *allocate(std::size_t size)
|
||||
{ return this->block_slist_base<>::allocate(size, m_upstream_rsrc); }
|
||||
|
||||
void release() BOOST_NOEXCEPT
|
||||
{ return this->block_slist_base<>::release(m_upstream_rsrc); }
|
||||
|
||||
memory_resource& upstream_resource() const BOOST_NOEXCEPT
|
||||
{ return m_upstream_rsrc; }
|
||||
};
|
||||
|
||||
} //namespace pmr {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_CONTAINER_DETAIL_BLOCK_SLIST_HEADER
|
||||
@@ -0,0 +1,74 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2014-2014. 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/container for documentation.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_DETAIL_COMPARE_FUNCTORS_HPP
|
||||
#define BOOST_CONTAINER_DETAIL_COMPARE_FUNCTORS_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
|
||||
template<class Allocator>
|
||||
class equal_to_value
|
||||
{
|
||||
typedef typename Allocator::value_type value_type;
|
||||
const value_type &t_;
|
||||
|
||||
public:
|
||||
explicit equal_to_value(const value_type &t)
|
||||
: t_(t)
|
||||
{}
|
||||
|
||||
bool operator()(const value_type &t)const
|
||||
{ return t_ == t; }
|
||||
};
|
||||
|
||||
template<class Node, class Pred>
|
||||
struct value_to_node_compare
|
||||
: Pred
|
||||
{
|
||||
typedef Pred predicate_type;
|
||||
typedef Node node_type;
|
||||
|
||||
value_to_node_compare()
|
||||
: Pred()
|
||||
{}
|
||||
|
||||
explicit value_to_node_compare(Pred pred)
|
||||
: Pred(pred)
|
||||
{}
|
||||
|
||||
bool operator()(const Node &a, const Node &b) const
|
||||
{ return static_cast<const Pred&>(*this)(a.get_data(), b.get_data()); }
|
||||
|
||||
bool operator()(const Node &a) const
|
||||
{ return static_cast<const Pred&>(*this)(a.get_data()); }
|
||||
|
||||
bool operator()(const Node &a, const Node &b)
|
||||
{ return static_cast<Pred&>(*this)(a.get_data(), b.get_data()); }
|
||||
|
||||
bool operator()(const Node &a)
|
||||
{ return static_cast<Pred&>(*this)(a.get_data()); }
|
||||
|
||||
predicate_type & predicate() { return static_cast<predicate_type&>(*this); }
|
||||
const predicate_type & predicate() const { return static_cast<predicate_type&>(*this); }
|
||||
};
|
||||
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //BOOST_CONTAINER_DETAIL_COMPARE_FUNCTORS_HPP
|
||||
@@ -0,0 +1,53 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2013. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#ifndef BOOST_CONTAINER_CONTAINER_DETAIL_CONFIG_INCLUDED
|
||||
#define BOOST_CONTAINER_CONTAINER_DETAIL_CONFIG_INCLUDED
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
#include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#endif //BOOST_CONTAINER_CONTAINER_DETAIL_CONFIG_INCLUDED
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable : 4127) // conditional expression is constant
|
||||
#pragma warning (disable : 4146) // unary minus operator applied to unsigned type, result still unsigned
|
||||
#pragma warning (disable : 4197) // top-level volatile in cast is ignored
|
||||
#pragma warning (disable : 4244) // possible loss of data
|
||||
#pragma warning (disable : 4251) // "identifier" : class "type" needs to have dll-interface to be used by clients of class "type2"
|
||||
#pragma warning (disable : 4267) // conversion from "X" to "Y", possible loss of data
|
||||
#pragma warning (disable : 4275) // non DLL-interface classkey "identifier" used as base for DLL-interface classkey "identifier"
|
||||
#pragma warning (disable : 4284) // odd return type for operator->
|
||||
#pragma warning (disable : 4290) // C++ exception specification ignored except to indicate a function is not __declspec(nothrow)
|
||||
#pragma warning (disable : 4324) // structure was padded due to __declspec(align(
|
||||
#pragma warning (disable : 4345) // behavior change: an object of POD type constructed with an initializer of the form () will be default-initialized
|
||||
#pragma warning (disable : 4355) // "this" : used in base member initializer list
|
||||
#pragma warning (disable : 4503) // "identifier" : decorated name length exceeded, name was truncated
|
||||
#pragma warning (disable : 4510) // default constructor could not be generated
|
||||
#pragma warning (disable : 4511) // copy constructor could not be generated
|
||||
#pragma warning (disable : 4512) // assignment operator could not be generated
|
||||
#pragma warning (disable : 4514) // unreferenced inline removed
|
||||
#pragma warning (disable : 4521) // Disable "multiple copy constructors specified"
|
||||
#pragma warning (disable : 4522) // "class" : multiple assignment operators specified
|
||||
#pragma warning (disable : 4541) // 'typeid' used on polymorphic type '' with /GR-; unpredictable behavior may result
|
||||
#pragma warning (disable : 4584) // X is already a base-class of Y
|
||||
#pragma warning (disable : 4610) // struct can never be instantiated - user defined constructor required
|
||||
#pragma warning (disable : 4671) // the copy constructor is inaccessible
|
||||
#pragma warning (disable : 4673) // throwing '' the following types will not be considered at the catch site
|
||||
#pragma warning (disable : 4675) // "method" should be declared "static" and have exactly one parameter
|
||||
#pragma warning (disable : 4702) // unreachable code
|
||||
#pragma warning (disable : 4706) // assignment within conditional expression
|
||||
#pragma warning (disable : 4710) // function not inlined
|
||||
#pragma warning (disable : 4714) // "function": marked as __forceinline not inlined
|
||||
#pragma warning (disable : 4711) // function selected for automatic inline expansion
|
||||
#pragma warning (disable : 4786) // identifier truncated in debug info
|
||||
#pragma warning (disable : 4996) // "function": was declared deprecated
|
||||
|
||||
#endif //BOOST_MSVC
|
||||
@@ -0,0 +1,13 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2013. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#if defined BOOST_MSVC
|
||||
#pragma warning (pop)
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2014-2014.
|
||||
//
|
||||
// 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_DETAIL_CONSTRUCT_IN_PLACE_HPP
|
||||
#define BOOST_CONTAINER_DETAIL_CONSTRUCT_IN_PLACE_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/allocator_traits.hpp>
|
||||
#include <boost/container/detail/iterators.hpp>
|
||||
#include <boost/container/detail/value_init.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
|
||||
//In place construction
|
||||
|
||||
template<class Allocator, class T, class InpIt>
|
||||
BOOST_CONTAINER_FORCEINLINE void construct_in_place(Allocator &a, T* dest, InpIt source)
|
||||
{ boost::container::allocator_traits<Allocator>::construct(a, dest, *source); }
|
||||
|
||||
template<class Allocator, class T, class U, class D>
|
||||
BOOST_CONTAINER_FORCEINLINE void construct_in_place(Allocator &a, T *dest, value_init_construct_iterator<U, D>)
|
||||
{
|
||||
boost::container::allocator_traits<Allocator>::construct(a, dest);
|
||||
}
|
||||
|
||||
template <class T, class Difference>
|
||||
class default_init_construct_iterator;
|
||||
|
||||
template<class Allocator, class T, class U, class D>
|
||||
BOOST_CONTAINER_FORCEINLINE void construct_in_place(Allocator &a, T *dest, default_init_construct_iterator<U, D>)
|
||||
{
|
||||
boost::container::allocator_traits<Allocator>::construct(a, dest, default_init);
|
||||
}
|
||||
|
||||
template <class T, class EmplaceFunctor, class Difference>
|
||||
class emplace_iterator;
|
||||
|
||||
template<class Allocator, class T, class U, class EF, class D>
|
||||
BOOST_CONTAINER_FORCEINLINE void construct_in_place(Allocator &a, T *dest, emplace_iterator<U, EF, D> ei)
|
||||
{
|
||||
ei.construct_in_place(a, dest);
|
||||
}
|
||||
|
||||
//Assignment
|
||||
|
||||
template<class DstIt, class InpIt>
|
||||
BOOST_CONTAINER_FORCEINLINE void assign_in_place(DstIt dest, InpIt source)
|
||||
{ *dest = *source; }
|
||||
|
||||
template<class DstIt, class U, class D>
|
||||
BOOST_CONTAINER_FORCEINLINE void assign_in_place(DstIt dest, value_init_construct_iterator<U, D>)
|
||||
{
|
||||
container_detail::value_init<U> val;
|
||||
*dest = boost::move(val.get());
|
||||
}
|
||||
|
||||
template <class DstIt, class Difference>
|
||||
class default_init_construct_iterator;
|
||||
|
||||
template<class DstIt, class U, class D>
|
||||
BOOST_CONTAINER_FORCEINLINE void assign_in_place(DstIt dest, default_init_construct_iterator<U, D>)
|
||||
{
|
||||
U u;
|
||||
*dest = boost::move(u);
|
||||
}
|
||||
|
||||
template <class T, class EmplaceFunctor, class Difference>
|
||||
class emplace_iterator;
|
||||
|
||||
template<class DstIt, class U, class EF, class D>
|
||||
BOOST_CONTAINER_FORCEINLINE void assign_in_place(DstIt dest, emplace_iterator<U, EF, D> ei)
|
||||
{
|
||||
ei.assign_in_place(dest);
|
||||
}
|
||||
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DETAIL_CONSTRUCT_IN_PLACE_HPP
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,378 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2013.
|
||||
//
|
||||
// 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_DESTROYERS_HPP
|
||||
#define BOOST_CONTAINER_DESTROYERS_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/detail/config_begin.hpp>
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
|
||||
#include <boost/container/allocator_traits.hpp>
|
||||
#include <boost/container/detail/to_raw_pointer.hpp>
|
||||
#include <boost/container/detail/version_type.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace container_detail {
|
||||
|
||||
//!A deleter for scoped_ptr that deallocates the memory
|
||||
//!allocated for an object using a STL allocator.
|
||||
template <class Allocator>
|
||||
struct scoped_deallocator
|
||||
{
|
||||
typedef allocator_traits<Allocator> allocator_traits_type;
|
||||
typedef typename allocator_traits_type::pointer pointer;
|
||||
typedef container_detail::integral_constant<unsigned,
|
||||
boost::container::container_detail::
|
||||
version<Allocator>::value> alloc_version;
|
||||
|
||||
private:
|
||||
void priv_deallocate(version_1)
|
||||
{ m_alloc.deallocate(m_ptr, 1); }
|
||||
|
||||
void priv_deallocate(version_2)
|
||||
{ m_alloc.deallocate_one(m_ptr); }
|
||||
|
||||
BOOST_MOVABLE_BUT_NOT_COPYABLE(scoped_deallocator)
|
||||
|
||||
public:
|
||||
|
||||
pointer m_ptr;
|
||||
Allocator& m_alloc;
|
||||
|
||||
scoped_deallocator(pointer p, Allocator& a)
|
||||
: m_ptr(p), m_alloc(a)
|
||||
{}
|
||||
|
||||
~scoped_deallocator()
|
||||
{ if (m_ptr)priv_deallocate(alloc_version()); }
|
||||
|
||||
scoped_deallocator(BOOST_RV_REF(scoped_deallocator) o)
|
||||
: m_ptr(o.m_ptr), m_alloc(o.m_alloc)
|
||||
{ o.release(); }
|
||||
|
||||
pointer get() const
|
||||
{ return m_ptr; }
|
||||
|
||||
void set(const pointer &p)
|
||||
{ m_ptr = p; }
|
||||
|
||||
void release()
|
||||
{ m_ptr = 0; }
|
||||
};
|
||||
|
||||
template <class Allocator>
|
||||
struct null_scoped_deallocator
|
||||
{
|
||||
typedef boost::container::allocator_traits<Allocator> AllocTraits;
|
||||
typedef typename AllocTraits::pointer pointer;
|
||||
typedef typename AllocTraits::size_type size_type;
|
||||
|
||||
null_scoped_deallocator(pointer, Allocator&, size_type)
|
||||
{}
|
||||
|
||||
void release()
|
||||
{}
|
||||
|
||||
pointer get() const
|
||||
{ return pointer(); }
|
||||
|
||||
void set(const pointer &)
|
||||
{}
|
||||
};
|
||||
|
||||
//!A deleter for scoped_ptr that deallocates the memory
|
||||
//!allocated for an array of objects using a STL allocator.
|
||||
template <class Allocator>
|
||||
struct scoped_array_deallocator
|
||||
{
|
||||
typedef boost::container::allocator_traits<Allocator> AllocTraits;
|
||||
typedef typename AllocTraits::pointer pointer;
|
||||
typedef typename AllocTraits::size_type size_type;
|
||||
|
||||
scoped_array_deallocator(pointer p, Allocator& a, size_type length)
|
||||
: m_ptr(p), m_alloc(a), m_length(length) {}
|
||||
|
||||
~scoped_array_deallocator()
|
||||
{ if (m_ptr) m_alloc.deallocate(m_ptr, m_length); }
|
||||
|
||||
void release()
|
||||
{ m_ptr = 0; }
|
||||
|
||||
private:
|
||||
pointer m_ptr;
|
||||
Allocator& m_alloc;
|
||||
size_type m_length;
|
||||
};
|
||||
|
||||
template <class Allocator>
|
||||
struct null_scoped_array_deallocator
|
||||
{
|
||||
typedef boost::container::allocator_traits<Allocator> AllocTraits;
|
||||
typedef typename AllocTraits::pointer pointer;
|
||||
typedef typename AllocTraits::size_type size_type;
|
||||
|
||||
null_scoped_array_deallocator(pointer, Allocator&, size_type)
|
||||
{}
|
||||
|
||||
void release()
|
||||
{}
|
||||
};
|
||||
|
||||
template <class Allocator>
|
||||
struct scoped_destroy_deallocator
|
||||
{
|
||||
typedef boost::container::allocator_traits<Allocator> AllocTraits;
|
||||
typedef typename AllocTraits::pointer pointer;
|
||||
typedef typename AllocTraits::size_type size_type;
|
||||
typedef container_detail::integral_constant<unsigned,
|
||||
boost::container::container_detail::
|
||||
version<Allocator>::value> alloc_version;
|
||||
|
||||
scoped_destroy_deallocator(pointer p, Allocator& a)
|
||||
: m_ptr(p), m_alloc(a) {}
|
||||
|
||||
~scoped_destroy_deallocator()
|
||||
{
|
||||
if(m_ptr){
|
||||
AllocTraits::destroy(m_alloc, container_detail::to_raw_pointer(m_ptr));
|
||||
priv_deallocate(m_ptr, alloc_version());
|
||||
}
|
||||
}
|
||||
|
||||
void release()
|
||||
{ m_ptr = 0; }
|
||||
|
||||
private:
|
||||
|
||||
void priv_deallocate(const pointer &p, version_1)
|
||||
{ AllocTraits::deallocate(m_alloc, p, 1); }
|
||||
|
||||
void priv_deallocate(const pointer &p, version_2)
|
||||
{ m_alloc.deallocate_one(p); }
|
||||
|
||||
pointer m_ptr;
|
||||
Allocator& m_alloc;
|
||||
};
|
||||
|
||||
|
||||
//!A deleter for scoped_ptr that destroys
|
||||
//!an object using a STL allocator.
|
||||
template <class Allocator>
|
||||
struct scoped_destructor_n
|
||||
{
|
||||
typedef boost::container::allocator_traits<Allocator> AllocTraits;
|
||||
typedef typename AllocTraits::pointer pointer;
|
||||
typedef typename AllocTraits::value_type value_type;
|
||||
typedef typename AllocTraits::size_type size_type;
|
||||
|
||||
scoped_destructor_n(pointer p, Allocator& a, size_type n)
|
||||
: m_p(p), m_a(a), m_n(n)
|
||||
{}
|
||||
|
||||
void release()
|
||||
{ m_p = 0; }
|
||||
|
||||
void increment_size(size_type inc)
|
||||
{ m_n += inc; }
|
||||
|
||||
void increment_size_backwards(size_type inc)
|
||||
{ m_n += inc; m_p -= inc; }
|
||||
|
||||
void shrink_forward(size_type inc)
|
||||
{ m_n -= inc; m_p += inc; }
|
||||
|
||||
~scoped_destructor_n()
|
||||
{
|
||||
if(!m_p) return;
|
||||
value_type *raw_ptr = container_detail::to_raw_pointer(m_p);
|
||||
while(m_n--){
|
||||
AllocTraits::destroy(m_a, raw_ptr++);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
pointer m_p;
|
||||
Allocator & m_a;
|
||||
size_type m_n;
|
||||
};
|
||||
|
||||
//!A deleter for scoped_ptr that destroys
|
||||
//!an object using a STL allocator.
|
||||
template <class Allocator>
|
||||
struct null_scoped_destructor_n
|
||||
{
|
||||
typedef boost::container::allocator_traits<Allocator> AllocTraits;
|
||||
typedef typename AllocTraits::pointer pointer;
|
||||
typedef typename AllocTraits::size_type size_type;
|
||||
|
||||
null_scoped_destructor_n(pointer, Allocator&, size_type)
|
||||
{}
|
||||
|
||||
void increment_size(size_type)
|
||||
{}
|
||||
|
||||
void increment_size_backwards(size_type)
|
||||
{}
|
||||
|
||||
void shrink_forward(size_type)
|
||||
{}
|
||||
|
||||
void release()
|
||||
{}
|
||||
};
|
||||
|
||||
template<class Allocator>
|
||||
class scoped_destructor
|
||||
{
|
||||
typedef boost::container::allocator_traits<Allocator> AllocTraits;
|
||||
public:
|
||||
typedef typename Allocator::value_type value_type;
|
||||
scoped_destructor(Allocator &a, value_type *pv)
|
||||
: pv_(pv), a_(a)
|
||||
{}
|
||||
|
||||
~scoped_destructor()
|
||||
{
|
||||
if(pv_){
|
||||
AllocTraits::destroy(a_, pv_);
|
||||
}
|
||||
}
|
||||
|
||||
void release()
|
||||
{ pv_ = 0; }
|
||||
|
||||
|
||||
void set(value_type *ptr) { pv_ = ptr; }
|
||||
|
||||
value_type *get() const { return pv_; }
|
||||
|
||||
private:
|
||||
value_type *pv_;
|
||||
Allocator &a_;
|
||||
};
|
||||
|
||||
|
||||
template<class Allocator>
|
||||
class value_destructor
|
||||
{
|
||||
typedef boost::container::allocator_traits<Allocator> AllocTraits;
|
||||
public:
|
||||
typedef typename Allocator::value_type value_type;
|
||||
value_destructor(Allocator &a, value_type &rv)
|
||||
: rv_(rv), a_(a)
|
||||
{}
|
||||
|
||||
~value_destructor()
|
||||
{
|
||||
AllocTraits::destroy(a_, &rv_);
|
||||
}
|
||||
|
||||
private:
|
||||
value_type &rv_;
|
||||
Allocator &a_;
|
||||
};
|
||||
|
||||
template <class Allocator>
|
||||
class allocator_destroyer
|
||||
{
|
||||
typedef boost::container::allocator_traits<Allocator> AllocTraits;
|
||||
typedef typename AllocTraits::value_type value_type;
|
||||
typedef typename AllocTraits::pointer pointer;
|
||||
typedef container_detail::integral_constant<unsigned,
|
||||
boost::container::container_detail::
|
||||
version<Allocator>::value> alloc_version;
|
||||
|
||||
private:
|
||||
Allocator & a_;
|
||||
|
||||
private:
|
||||
void priv_deallocate(const pointer &p, version_1)
|
||||
{ AllocTraits::deallocate(a_,p, 1); }
|
||||
|
||||
void priv_deallocate(const pointer &p, version_2)
|
||||
{ a_.deallocate_one(p); }
|
||||
|
||||
public:
|
||||
explicit allocator_destroyer(Allocator &a)
|
||||
: a_(a)
|
||||
{}
|
||||
|
||||
void operator()(const pointer &p)
|
||||
{
|
||||
AllocTraits::destroy(a_, container_detail::to_raw_pointer(p));
|
||||
this->priv_deallocate(p, alloc_version());
|
||||
}
|
||||
};
|
||||
|
||||
template <class Allocator>
|
||||
class allocator_destroyer_and_chain_builder
|
||||
{
|
||||
typedef allocator_traits<Allocator> allocator_traits_type;
|
||||
typedef typename allocator_traits_type::value_type value_type;
|
||||
typedef typename Allocator::multiallocation_chain multiallocation_chain;
|
||||
|
||||
Allocator & a_;
|
||||
multiallocation_chain &c_;
|
||||
|
||||
public:
|
||||
allocator_destroyer_and_chain_builder(Allocator &a, multiallocation_chain &c)
|
||||
: a_(a), c_(c)
|
||||
{}
|
||||
|
||||
void operator()(const typename Allocator::pointer &p)
|
||||
{
|
||||
allocator_traits<Allocator>::destroy(a_, container_detail::to_raw_pointer(p));
|
||||
c_.push_back(p);
|
||||
}
|
||||
};
|
||||
|
||||
template <class Allocator>
|
||||
class allocator_multialloc_chain_node_deallocator
|
||||
{
|
||||
typedef allocator_traits<Allocator> allocator_traits_type;
|
||||
typedef typename allocator_traits_type::value_type value_type;
|
||||
typedef typename Allocator::multiallocation_chain multiallocation_chain;
|
||||
typedef allocator_destroyer_and_chain_builder<Allocator> chain_builder;
|
||||
|
||||
Allocator & a_;
|
||||
multiallocation_chain c_;
|
||||
|
||||
public:
|
||||
allocator_multialloc_chain_node_deallocator(Allocator &a)
|
||||
: a_(a), c_()
|
||||
{}
|
||||
|
||||
chain_builder get_chain_builder()
|
||||
{ return chain_builder(a_, c_); }
|
||||
|
||||
~allocator_multialloc_chain_node_deallocator()
|
||||
{
|
||||
a_.deallocate_individual(c_);
|
||||
}
|
||||
};
|
||||
|
||||
} //namespace container_detail {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DESTROYERS_HPP
|
||||
+461
@@ -0,0 +1,461 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_DISPATCH_USES_ALLOCATOR_HPP
|
||||
#define BOOST_CONTAINER_DISPATCH_USES_ALLOCATOR_HPP
|
||||
|
||||
#if defined (_MSC_VER)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/detail/config_begin.hpp>
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
|
||||
#include <boost/container/allocator_traits.hpp>
|
||||
#include <boost/container/uses_allocator.hpp>
|
||||
|
||||
#include <boost/container/detail/addressof.hpp>
|
||||
#include <boost/container/detail/mpl.hpp>
|
||||
#include <boost/container/detail/pair.hpp>
|
||||
#include <boost/container/detail/type_traits.hpp>
|
||||
|
||||
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
#include <boost/move/detail/fwd_macros.hpp>
|
||||
#endif
|
||||
#include <boost/move/utility_core.hpp>
|
||||
|
||||
#include <boost/core/no_exceptions_support.hpp>
|
||||
|
||||
namespace boost { namespace container {
|
||||
|
||||
namespace container_detail {
|
||||
|
||||
|
||||
// Check if we can detect is_convertible using advanced SFINAE expressions
|
||||
#if !defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
//! Code inspired by Mathias Gaunard's is_convertible.cpp found in the Boost mailing list
|
||||
//! http://boost.2283326.n4.nabble.com/type-traits-is-constructible-when-decltype-is-supported-td3575452.html
|
||||
//! Thanks Mathias!
|
||||
|
||||
//With variadic templates, we need a single class to implement the trait
|
||||
template<class T, class ...Args>
|
||||
struct is_constructible
|
||||
{
|
||||
typedef char yes_type;
|
||||
struct no_type
|
||||
{ char padding[2]; };
|
||||
|
||||
template<std::size_t N>
|
||||
struct dummy;
|
||||
|
||||
template<class X>
|
||||
static decltype(X(boost::move_detail::declval<Args>()...), true_type()) test(int);
|
||||
|
||||
template<class X>
|
||||
static no_type test(...);
|
||||
|
||||
static const bool value = sizeof(test<T>(0)) == sizeof(yes_type);
|
||||
};
|
||||
|
||||
template <class T, class InnerAlloc, class ...Args>
|
||||
struct is_constructible_with_allocator_prefix
|
||||
: is_constructible<T, allocator_arg_t, InnerAlloc, Args...>
|
||||
{};
|
||||
|
||||
#else // #if !defined(BOOST_NO_SFINAE_EXPR) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
//Without advanced SFINAE expressions, we can't use is_constructible
|
||||
//so backup to constructible_with_allocator_xxx
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
template <class T, class InnerAlloc, class ...Args>
|
||||
struct is_constructible_with_allocator_prefix
|
||||
: constructible_with_allocator_prefix<T>
|
||||
{};
|
||||
|
||||
template <class T, class InnerAlloc, class ...Args>
|
||||
struct is_constructible_with_allocator_suffix
|
||||
: constructible_with_allocator_suffix<T>
|
||||
{};
|
||||
|
||||
#else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
template <class T, class InnerAlloc, BOOST_MOVE_CLASSDFLT9>
|
||||
struct is_constructible_with_allocator_prefix
|
||||
: constructible_with_allocator_prefix<T>
|
||||
{};
|
||||
|
||||
template <class T, class InnerAlloc, BOOST_MOVE_CLASSDFLT9>
|
||||
struct is_constructible_with_allocator_suffix
|
||||
: constructible_with_allocator_suffix<T>
|
||||
{};
|
||||
|
||||
#endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
#endif // #if !defined(BOOST_NO_SFINAE_EXPR)
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
template < typename ConstructAlloc
|
||||
, typename ArgAlloc
|
||||
, typename T
|
||||
, class ...Args
|
||||
>
|
||||
inline typename container_detail::enable_if_and
|
||||
< void
|
||||
, container_detail::is_not_pair<T>
|
||||
, container_detail::not_< uses_allocator<T, ArgAlloc> >
|
||||
>::type dispatch_uses_allocator
|
||||
( ConstructAlloc & construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, T* p, BOOST_FWD_REF(Args)...args)
|
||||
{
|
||||
(void)arg_alloc;
|
||||
allocator_traits<ConstructAlloc>::construct(construct_alloc, p, ::boost::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
// allocator_arg_t
|
||||
template < typename ConstructAlloc
|
||||
, typename ArgAlloc
|
||||
, typename T
|
||||
, class ...Args
|
||||
>
|
||||
inline typename container_detail::enable_if_and
|
||||
< void
|
||||
, container_detail::is_not_pair<T>
|
||||
, uses_allocator<T, ArgAlloc>
|
||||
, is_constructible_with_allocator_prefix<T, ArgAlloc, Args...>
|
||||
>::type dispatch_uses_allocator
|
||||
( ConstructAlloc& construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, T* p, BOOST_FWD_REF(Args) ...args)
|
||||
{
|
||||
allocator_traits<ConstructAlloc>::construct
|
||||
( construct_alloc, p, allocator_arg
|
||||
, ::boost::forward<ArgAlloc>(arg_alloc), ::boost::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
// allocator suffix
|
||||
template < typename ConstructAlloc
|
||||
, typename ArgAlloc
|
||||
, typename T
|
||||
, class ...Args
|
||||
>
|
||||
inline typename container_detail::enable_if_and
|
||||
< void
|
||||
, container_detail::is_not_pair<T>
|
||||
, uses_allocator<T, ArgAlloc>
|
||||
, container_detail::not_<is_constructible_with_allocator_prefix<T, ArgAlloc, Args...> >
|
||||
>::type dispatch_uses_allocator
|
||||
( ConstructAlloc& construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, T* p, BOOST_FWD_REF(Args)...args)
|
||||
{
|
||||
allocator_traits<ConstructAlloc>::construct
|
||||
(construct_alloc, p, ::boost::forward<Args>(args)..., ::boost::forward<ArgAlloc>(arg_alloc));
|
||||
}
|
||||
|
||||
#else //#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
#define BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE(N) \
|
||||
template <typename ConstructAlloc, typename ArgAlloc, typename T BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
|
||||
inline typename container_detail::enable_if_and\
|
||||
< void\
|
||||
, container_detail::is_not_pair<T>\
|
||||
, container_detail::not_<uses_allocator<T, ArgAlloc> >\
|
||||
>::type\
|
||||
dispatch_uses_allocator\
|
||||
(ConstructAlloc &construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, T* p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
|
||||
{\
|
||||
(void)arg_alloc;\
|
||||
allocator_traits<ConstructAlloc>::construct(construct_alloc, p BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
|
||||
}\
|
||||
//
|
||||
BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE)
|
||||
#undef BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE
|
||||
|
||||
#define BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE(N) \
|
||||
template < typename ConstructAlloc, typename ArgAlloc, typename T BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
|
||||
inline typename container_detail::enable_if_and\
|
||||
< void\
|
||||
, container_detail::is_not_pair<T>\
|
||||
, uses_allocator<T, ArgAlloc>\
|
||||
, is_constructible_with_allocator_prefix<T, ArgAlloc BOOST_MOVE_I##N BOOST_MOVE_TARG##N>\
|
||||
>::type\
|
||||
dispatch_uses_allocator\
|
||||
(ConstructAlloc& construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, T* p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
|
||||
{\
|
||||
allocator_traits<ConstructAlloc>::construct\
|
||||
(construct_alloc, p, allocator_arg, ::boost::forward<ArgAlloc>(arg_alloc) BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
|
||||
}\
|
||||
//
|
||||
BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE)
|
||||
#undef BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE
|
||||
|
||||
#define BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE(N) \
|
||||
template < typename ConstructAlloc, typename ArgAlloc, typename T BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
|
||||
inline typename container_detail::enable_if_and\
|
||||
< void\
|
||||
, container_detail::is_not_pair<T>\
|
||||
, uses_allocator<T, ArgAlloc>\
|
||||
, container_detail::not_<is_constructible_with_allocator_prefix<T, ArgAlloc BOOST_MOVE_I##N BOOST_MOVE_TARG##N> >\
|
||||
>::type\
|
||||
dispatch_uses_allocator\
|
||||
(ConstructAlloc& construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, T* p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
|
||||
{\
|
||||
allocator_traits<ConstructAlloc>::construct\
|
||||
(construct_alloc, p BOOST_MOVE_I##N BOOST_MOVE_FWD##N, ::boost::forward<ArgAlloc>(arg_alloc));\
|
||||
}\
|
||||
//
|
||||
BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE)
|
||||
#undef BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE
|
||||
|
||||
#endif //#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
template < typename ConstructAlloc
|
||||
, typename ArgAlloc
|
||||
, typename Pair
|
||||
> inline
|
||||
BOOST_CONTAINER_DOC1ST(void, typename container_detail::enable_if<container_detail::is_pair<Pair> >::type)
|
||||
dispatch_uses_allocator
|
||||
( ConstructAlloc & construct_alloc
|
||||
, BOOST_FWD_REF(ArgAlloc) arg_alloc
|
||||
, Pair* p)
|
||||
{
|
||||
(dispatch_uses_allocator)(construct_alloc, arg_alloc, container_detail::addressof(p->first));
|
||||
BOOST_TRY{
|
||||
(dispatch_uses_allocator)(construct_alloc, arg_alloc, container_detail::addressof(p->second));
|
||||
}
|
||||
BOOST_CATCH(...) {
|
||||
allocator_traits<ConstructAlloc>::destroy(construct_alloc, container_detail::addressof(p->first));
|
||||
BOOST_RETHROW
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
}
|
||||
|
||||
|
||||
template < typename ConstructAlloc
|
||||
, typename ArgAlloc
|
||||
, class Pair, class U, class V>
|
||||
BOOST_CONTAINER_DOC1ST(void, typename container_detail::enable_if<container_detail::is_pair<Pair> >::type)
|
||||
dispatch_uses_allocator
|
||||
( ConstructAlloc & construct_alloc
|
||||
, BOOST_FWD_REF(ArgAlloc) arg_alloc
|
||||
, Pair* p, BOOST_FWD_REF(U) x, BOOST_FWD_REF(V) y)
|
||||
{
|
||||
(dispatch_uses_allocator)(construct_alloc, arg_alloc, container_detail::addressof(p->first), ::boost::forward<U>(x));
|
||||
BOOST_TRY{
|
||||
(dispatch_uses_allocator)(construct_alloc, arg_alloc, container_detail::addressof(p->second), ::boost::forward<V>(y));
|
||||
}
|
||||
BOOST_CATCH(...){
|
||||
allocator_traits<ConstructAlloc>::destroy(construct_alloc, container_detail::addressof(p->first));
|
||||
BOOST_RETHROW
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
}
|
||||
|
||||
template < typename ConstructAlloc
|
||||
, typename ArgAlloc
|
||||
, class Pair, class Pair2>
|
||||
BOOST_CONTAINER_DOC1ST(void, typename container_detail::enable_if< container_detail::is_pair<Pair> >::type)
|
||||
dispatch_uses_allocator
|
||||
(ConstructAlloc & construct_alloc
|
||||
, BOOST_FWD_REF(ArgAlloc) arg_alloc
|
||||
, Pair* p, Pair2& x)
|
||||
{ (dispatch_uses_allocator)(construct_alloc, arg_alloc, p, x.first, x.second); }
|
||||
|
||||
template < typename ConstructAlloc
|
||||
, typename ArgAlloc
|
||||
, class Pair, class Pair2>
|
||||
typename container_detail::enable_if_and
|
||||
< void
|
||||
, container_detail::is_pair<Pair>
|
||||
, container_detail::not_<boost::move_detail::is_reference<Pair2> > >::type //This is needed for MSVC10 and ambiguous overloads
|
||||
dispatch_uses_allocator
|
||||
(ConstructAlloc & construct_alloc
|
||||
, BOOST_FWD_REF(ArgAlloc) arg_alloc
|
||||
, Pair* p, BOOST_RV_REF_BEG Pair2 BOOST_RV_REF_END x)
|
||||
{ (dispatch_uses_allocator)(construct_alloc, arg_alloc, p, ::boost::move(x.first), ::boost::move(x.second)); }
|
||||
|
||||
|
||||
//piecewise construction from boost::tuple
|
||||
#define BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_BOOST_TUPLE_CODE(N,M)\
|
||||
template< typename ConstructAlloc, typename ArgAlloc, class Pair \
|
||||
, template<class, class, class, class, class, class, class, class, class, class> class BoostTuple \
|
||||
BOOST_MOVE_I_IF(BOOST_MOVE_OR(N,M)) BOOST_MOVE_CLASS##N BOOST_MOVE_I_IF(BOOST_MOVE_AND(N,M)) BOOST_MOVE_CLASSQ##M > \
|
||||
typename container_detail::enable_if< container_detail::is_pair<Pair> >::type\
|
||||
dispatch_uses_allocator( ConstructAlloc & construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, Pair* pair, piecewise_construct_t\
|
||||
, BoostTuple<BOOST_MOVE_TARG##N BOOST_MOVE_I##N BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(10,N),::boost::tuples::null_type)> p\
|
||||
, BoostTuple<BOOST_MOVE_TARGQ##M BOOST_MOVE_I##M BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(10,M),::boost::tuples::null_type)> q)\
|
||||
{\
|
||||
(void)p; (void)q;\
|
||||
(dispatch_uses_allocator)\
|
||||
(construct_alloc, arg_alloc, container_detail::addressof(pair->first) BOOST_MOVE_I_IF(N) BOOST_MOVE_TMPL_GET##N);\
|
||||
BOOST_TRY{\
|
||||
(dispatch_uses_allocator)\
|
||||
(construct_alloc, arg_alloc, container_detail::addressof(pair->second) BOOST_MOVE_I_IF(M) BOOST_MOVE_TMPL_GETQ##M);\
|
||||
}\
|
||||
BOOST_CATCH(...) {\
|
||||
allocator_traits<ConstructAlloc>::destroy(construct_alloc, container_detail::addressof(pair->first));\
|
||||
BOOST_RETHROW\
|
||||
}\
|
||||
BOOST_CATCH_END\
|
||||
}\
|
||||
//
|
||||
BOOST_MOVE_ITER2D_0TOMAX(9, BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_BOOST_TUPLE_CODE)
|
||||
#undef BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_BOOST_TUPLE_CODE
|
||||
|
||||
//piecewise construction from Std Tuple
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
template< typename ConstructAlloc, typename ArgAlloc, class Pair
|
||||
, template<class ...> class Tuple, class... Args1, class... Args2, size_t... Indexes1, size_t... Indexes2>
|
||||
void dispatch_uses_allocator_index( ConstructAlloc & construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, Pair* pair
|
||||
, Tuple<Args1...>& t1, Tuple<Args2...>& t2, index_tuple<Indexes1...>, index_tuple<Indexes2...>)
|
||||
{
|
||||
(void)t1; (void)t2;
|
||||
(dispatch_uses_allocator)(construct_alloc, arg_alloc, container_detail::addressof(pair->first), ::boost::forward<Args1>(get<Indexes1>(t1))...);
|
||||
BOOST_TRY{
|
||||
(dispatch_uses_allocator)(construct_alloc, arg_alloc, container_detail::addressof(pair->second), ::boost::forward<Args2>(get<Indexes2>(t2))...);
|
||||
}
|
||||
BOOST_CATCH(...){
|
||||
allocator_traits<ConstructAlloc>::destroy(construct_alloc, container_detail::addressof(pair->first));
|
||||
BOOST_RETHROW
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
}
|
||||
|
||||
template< typename ConstructAlloc, typename ArgAlloc, class Pair
|
||||
, template<class ...> class Tuple, class... Args1, class... Args2>
|
||||
typename container_detail::enable_if< container_detail::is_pair<Pair> >::type
|
||||
dispatch_uses_allocator( ConstructAlloc & construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, Pair* pair, piecewise_construct_t
|
||||
, Tuple<Args1...> t1, Tuple<Args2...> t2)
|
||||
{
|
||||
(dispatch_uses_allocator_index)( construct_alloc, arg_alloc, pair, t1, t2
|
||||
, typename build_number_seq<sizeof...(Args1)>::type()
|
||||
, typename build_number_seq<sizeof...(Args2)>::type());
|
||||
}
|
||||
|
||||
#elif defined(BOOST_MSVC) && (_CPPLIB_VER == 520)
|
||||
|
||||
//MSVC 2010 tuple implementation
|
||||
#define BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2010_TUPLE_CODE(N,M)\
|
||||
template< typename ConstructAlloc, typename ArgAlloc, class Pair\
|
||||
, template<class, class, class, class, class, class, class, class, class, class> class StdTuple\
|
||||
BOOST_MOVE_I_IF(BOOST_MOVE_OR(N,M)) BOOST_MOVE_CLASS##N BOOST_MOVE_I_IF(BOOST_MOVE_AND(N,M)) BOOST_MOVE_CLASSQ##M > \
|
||||
typename container_detail::enable_if< container_detail::is_pair<Pair> >::type\
|
||||
dispatch_uses_allocator(ConstructAlloc & construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, Pair* pair, piecewise_construct_t\
|
||||
, StdTuple<BOOST_MOVE_TARG##N BOOST_MOVE_I##N BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(10,N),::std::tr1::_Nil)> p\
|
||||
, StdTuple<BOOST_MOVE_TARGQ##M BOOST_MOVE_I##M BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(10,M),::std::tr1::_Nil)> q)\
|
||||
{\
|
||||
(void)p; (void)q;\
|
||||
(dispatch_uses_allocator)\
|
||||
(construct_alloc, arg_alloc, container_detail::addressof(pair->first) BOOST_MOVE_I_IF(N) BOOST_MOVE_GET_IDX##N);\
|
||||
BOOST_TRY{\
|
||||
(dispatch_uses_allocator)\
|
||||
(construct_alloc, arg_alloc, container_detail::addressof(pair->second) BOOST_MOVE_I_IF(M) BOOST_MOVE_GET_IDXQ##M);\
|
||||
}\
|
||||
BOOST_CATCH(...) {\
|
||||
allocator_traits<ConstructAlloc>::destroy(construct_alloc, container_detail::addressof(pair->first));\
|
||||
BOOST_RETHROW\
|
||||
}\
|
||||
BOOST_CATCH_END\
|
||||
}\
|
||||
//
|
||||
BOOST_MOVE_ITER2D_0TOMAX(9, BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2010_TUPLE_CODE)
|
||||
#undef BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2010_TUPLE_CODE
|
||||
|
||||
#elif defined(BOOST_MSVC) && (_CPPLIB_VER == 540)
|
||||
#if _VARIADIC_MAX >= 9
|
||||
#define BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_MAX_IT 9
|
||||
#else
|
||||
#define BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_MAX_IT BOOST_MOVE_ADD(_VARIADIC_MAX, 1)
|
||||
#endif
|
||||
|
||||
//MSVC 2012 tuple implementation
|
||||
#define BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_CODE(N,M)\
|
||||
template< typename ConstructAlloc, typename ArgAlloc, class Pair\
|
||||
, template<BOOST_MOVE_REPEAT(_VARIADIC_MAX, class), class, class, class> class StdTuple \
|
||||
BOOST_MOVE_I_IF(BOOST_MOVE_OR(N,M)) BOOST_MOVE_CLASS##N BOOST_MOVE_I_IF(BOOST_MOVE_AND(N,M)) BOOST_MOVE_CLASSQ##M > \
|
||||
typename container_detail::enable_if< container_detail::is_pair<Pair> >::type\
|
||||
dispatch_uses_allocator\
|
||||
( ConstructAlloc & construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, Pair* pair, piecewise_construct_t\
|
||||
, StdTuple<BOOST_MOVE_TARG##N BOOST_MOVE_I##N BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(BOOST_MOVE_ADD(_VARIADIC_MAX, 3),N),::std::_Nil) > p\
|
||||
, StdTuple<BOOST_MOVE_TARGQ##M BOOST_MOVE_I##M BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(BOOST_MOVE_ADD(_VARIADIC_MAX, 3),M),::std::_Nil) > q)\
|
||||
{\
|
||||
(void)p; (void)q;\
|
||||
(dispatch_uses_allocator)\
|
||||
(construct_alloc, arg_alloc, container_detail::addressof(pair->first) BOOST_MOVE_I_IF(N) BOOST_MOVE_GET_IDX##N);\
|
||||
BOOST_TRY{\
|
||||
(dispatch_uses_allocator)\
|
||||
(construct_alloc, arg_alloc, container_detail::addressof(pair->second) BOOST_MOVE_I_IF(M) BOOST_MOVE_GET_IDXQ##M);\
|
||||
}\
|
||||
BOOST_CATCH(...) {\
|
||||
allocator_traits<ConstructAlloc>::destroy(construct_alloc, container_detail::addressof(pair->first));\
|
||||
BOOST_RETHROW\
|
||||
}\
|
||||
BOOST_CATCH_END\
|
||||
}\
|
||||
//
|
||||
BOOST_MOVE_ITER2D_0TOMAX(BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_MAX_IT, BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_CODE)
|
||||
#undef BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2010_TUPLE_CODE
|
||||
#undef BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_MAX_IT
|
||||
|
||||
#endif //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
template < typename ConstructAlloc
|
||||
, typename ArgAlloc
|
||||
, class Pair, class KeyType, class ... Args>
|
||||
typename container_detail::enable_if< container_detail::is_pair<Pair>, void >::type
|
||||
dispatch_uses_allocator
|
||||
(ConstructAlloc & construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, Pair* p, try_emplace_t, BOOST_FWD_REF(KeyType) k, BOOST_FWD_REF(Args) ...args)
|
||||
{
|
||||
(dispatch_uses_allocator)(construct_alloc, arg_alloc, container_detail::addressof(p->first), ::boost::forward<KeyType>(k));
|
||||
BOOST_TRY{
|
||||
(dispatch_uses_allocator)(construct_alloc, arg_alloc, container_detail::addressof(p->second), ::boost::forward<Args>(args)...);
|
||||
}
|
||||
BOOST_CATCH(...) {
|
||||
allocator_traits<ConstructAlloc>::destroy(construct_alloc, container_detail::addressof(p->first));
|
||||
BOOST_RETHROW
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define BOOST_CONTAINER_DISPATCH_USES_ALLOCATOR_PAIR_TRY_EMPLACE_CODE(N) \
|
||||
template <typename ConstructAlloc, typename ArgAlloc, class Pair, class KeyType BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
|
||||
inline typename container_detail::enable_if\
|
||||
< container_detail::is_pair<Pair>, void >::type\
|
||||
dispatch_uses_allocator\
|
||||
(ConstructAlloc &construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, Pair* p, try_emplace_t, \
|
||||
BOOST_FWD_REF(KeyType) k BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
|
||||
{\
|
||||
(dispatch_uses_allocator)(construct_alloc, arg_alloc, container_detail::addressof(p->first), ::boost::forward<KeyType>(k));\
|
||||
BOOST_TRY{\
|
||||
(dispatch_uses_allocator)(construct_alloc, arg_alloc, container_detail::addressof(p->second) BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
|
||||
}\
|
||||
BOOST_CATCH(...) {\
|
||||
allocator_traits<ConstructAlloc>::destroy(construct_alloc, container_detail::addressof(p->first));\
|
||||
BOOST_RETHROW\
|
||||
}\
|
||||
BOOST_CATCH_END\
|
||||
}\
|
||||
//
|
||||
BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_DISPATCH_USES_ALLOCATOR_PAIR_TRY_EMPLACE_CODE)
|
||||
#undef BOOST_CONTAINER_DISPATCH_USES_ALLOCATOR_PAIR_TRY_EMPLACE_CODE
|
||||
|
||||
#endif //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
} //namespace container_detail
|
||||
|
||||
}} // namespace boost { namespace container {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif // BOOST_CONTAINER_DISPATCH_USES_ALLOCATOR_HPP
|
||||
@@ -0,0 +1,103 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#ifndef BOOST_CONTAINER_DETAIL_ALLOC_LIB_HPP
|
||||
#define BOOST_CONTAINER_DETAIL_ALLOC_LIB_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/detail/config_begin.hpp>
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
#include <boost/container/detail/auto_link.hpp>
|
||||
|
||||
#include <boost/container/detail/alloc_lib.h>
|
||||
|
||||
namespace boost{
|
||||
namespace container{
|
||||
|
||||
typedef boost_cont_command_ret_t dlmalloc_command_ret_t;
|
||||
typedef boost_cont_memchain dlmalloc_memchain;
|
||||
typedef boost_cont_memchain_it dlmalloc_memchain_it;
|
||||
typedef boost_cont_malloc_stats_t dlmalloc_malloc_stats_t;
|
||||
|
||||
BOOST_CONTAINER_DECL size_t dlmalloc_size(const void *p);
|
||||
|
||||
BOOST_CONTAINER_DECL void* dlmalloc_malloc(size_t bytes);
|
||||
|
||||
BOOST_CONTAINER_DECL void dlmalloc_free(void* mem);
|
||||
|
||||
BOOST_CONTAINER_DECL void* dlmalloc_memalign(size_t bytes, size_t alignment);
|
||||
|
||||
BOOST_CONTAINER_DECL int dlmalloc_multialloc_nodes
|
||||
(size_t n_elements, size_t elem_size, size_t contiguous_elements, boost_cont_memchain *pchain);
|
||||
|
||||
BOOST_CONTAINER_DECL int dlmalloc_multialloc_arrays
|
||||
(size_t n_elements, const size_t *sizes, size_t sizeof_element, size_t contiguous_elements, boost_cont_memchain *pchain);
|
||||
|
||||
BOOST_CONTAINER_DECL void dlmalloc_multidealloc(boost_cont_memchain *pchain);
|
||||
|
||||
BOOST_CONTAINER_DECL size_t dlmalloc_footprint();
|
||||
|
||||
BOOST_CONTAINER_DECL size_t dlmalloc_allocated_memory();
|
||||
|
||||
BOOST_CONTAINER_DECL size_t dlmalloc_chunksize(const void *p);
|
||||
|
||||
BOOST_CONTAINER_DECL int dlmalloc_all_deallocated();
|
||||
|
||||
BOOST_CONTAINER_DECL boost_cont_malloc_stats_t dlmalloc_malloc_stats();
|
||||
|
||||
BOOST_CONTAINER_DECL size_t dlmalloc_in_use_memory();
|
||||
|
||||
BOOST_CONTAINER_DECL int dlmalloc_trim(size_t pad);
|
||||
|
||||
BOOST_CONTAINER_DECL int dlmalloc_mallopt(int parameter_number, int parameter_value);
|
||||
|
||||
BOOST_CONTAINER_DECL int dlmalloc_grow(void* oldmem, size_t minbytes, size_t maxbytes, size_t *received);
|
||||
|
||||
BOOST_CONTAINER_DECL int dlmalloc_shrink(void* oldmem, size_t minbytes, size_t maxbytes, size_t *received, int do_commit);
|
||||
|
||||
BOOST_CONTAINER_DECL void* dlmalloc_alloc(size_t minbytes, size_t preferred_bytes, size_t *received_bytes);
|
||||
|
||||
BOOST_CONTAINER_DECL int dlmalloc_malloc_check();
|
||||
|
||||
BOOST_CONTAINER_DECL boost_cont_command_ret_t dlmalloc_allocation_command
|
||||
( allocation_type command
|
||||
, size_t sizeof_object
|
||||
, size_t limit_objects
|
||||
, size_t preferred_objects
|
||||
, size_t *received_objects
|
||||
, void *reuse_ptr
|
||||
);
|
||||
|
||||
BOOST_CONTAINER_DECL int dlmalloc_mallopt(int param_number, int value);
|
||||
|
||||
BOOST_CONTAINER_DECL void *dlmalloc_sync_create();
|
||||
|
||||
BOOST_CONTAINER_DECL void dlmalloc_sync_destroy(void *sync);
|
||||
|
||||
BOOST_CONTAINER_DECL bool dlmalloc_sync_lock(void *sync);
|
||||
|
||||
BOOST_CONTAINER_DECL void dlmalloc_sync_unlock(void *sync);
|
||||
|
||||
BOOST_CONTAINER_DECL bool dlmalloc_global_sync_lock();
|
||||
|
||||
BOOST_CONTAINER_DECL void dlmalloc_global_sync_unlock();
|
||||
|
||||
} //namespace container{
|
||||
} //namespace boost{
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_CONTAINER_DETAIL_ALLOC_LIB_HPP
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,96 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2009-2013.
|
||||
//
|
||||
// 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/container for documentation.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// This code was modified from the code posted by Alexandre Courpron in his
|
||||
// article "Interface Detection" in The Code Project:
|
||||
// http://www.codeproject.com/KB/architecture/Detector.aspx
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright 2007 Alexandre Courpron
|
||||
//
|
||||
// Permission to use, copy, modify, redistribute and sell this software,
|
||||
// provided that this copyright notice appears on all copies of the software.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_DETAIL_FUNCTION_DETECTOR_HPP
|
||||
#define BOOST_CONTAINER_DETAIL_FUNCTION_DETECTOR_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/detail/config_begin.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace function_detector {
|
||||
|
||||
typedef char NotFoundType;
|
||||
struct StaticFunctionType { NotFoundType x [2]; };
|
||||
struct NonStaticFunctionType { NotFoundType x [3]; };
|
||||
|
||||
enum
|
||||
{ NotFound = 0,
|
||||
StaticFunction = sizeof( StaticFunctionType ) - sizeof( NotFoundType ),
|
||||
NonStaticFunction = sizeof( NonStaticFunctionType ) - sizeof( NotFoundType )
|
||||
};
|
||||
|
||||
} //namespace boost {
|
||||
} //namespace container {
|
||||
} //namespace function_detector {
|
||||
|
||||
#define BOOST_CONTAINER_CREATE_FUNCTION_DETECTOR(Identifier, InstantiationKey) \
|
||||
namespace boost { \
|
||||
namespace container { \
|
||||
namespace function_detector { \
|
||||
template < class T, \
|
||||
class NonStaticType, \
|
||||
class NonStaticConstType, \
|
||||
class StaticType > \
|
||||
class DetectMember_##InstantiationKey_##Identifier { \
|
||||
template < NonStaticType > \
|
||||
struct TestNonStaticNonConst ; \
|
||||
\
|
||||
template < NonStaticConstType > \
|
||||
struct TestNonStaticConst ; \
|
||||
\
|
||||
template < StaticType > \
|
||||
struct TestStatic ; \
|
||||
\
|
||||
template <class U > \
|
||||
static NonStaticFunctionType Test( TestNonStaticNonConst<&U::Identifier>*, int ); \
|
||||
\
|
||||
template <class U > \
|
||||
static NonStaticFunctionType Test( TestNonStaticConst<&U::Identifier>*, int ); \
|
||||
\
|
||||
template <class U> \
|
||||
static StaticFunctionType Test( TestStatic<&U::Identifier>*, int ); \
|
||||
\
|
||||
template <class U> \
|
||||
static NotFoundType Test( ... ); \
|
||||
public : \
|
||||
static const int check = NotFound + (sizeof(Test<T>(0, 0)) - sizeof(NotFoundType));\
|
||||
};\
|
||||
}}} //namespace boost::container::function_detector {
|
||||
|
||||
#define BOOST_CONTAINER_DETECT_FUNCTION(Class, InstantiationKey, ReturnType, Identifier, Params) \
|
||||
::boost::container::function_detector::DetectMember_##InstantiationKey_##Identifier< Class,\
|
||||
ReturnType (Class::*)Params,\
|
||||
ReturnType (Class::*)Params const,\
|
||||
ReturnType (*)Params \
|
||||
>::check
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //@ifndef BOOST_CONTAINER_DETAIL_FUNCTION_DETECTOR_HPP
|
||||
@@ -0,0 +1,57 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2016-2016. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#ifndef BOOST_CONTAINER_DETAIL_IS_SORTED_HPP
|
||||
#define BOOST_CONTAINER_DETAIL_IS_SORTED_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace container_detail {
|
||||
|
||||
template <class ForwardIterator, class Pred>
|
||||
bool is_sorted (ForwardIterator first, ForwardIterator last, Pred pred)
|
||||
{
|
||||
if(first != last){
|
||||
ForwardIterator next = first;
|
||||
while (++next != last){
|
||||
if(pred(*next, *first))
|
||||
return false;
|
||||
++first;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class ForwardIterator, class Pred>
|
||||
bool is_sorted_and_unique (ForwardIterator first, ForwardIterator last, Pred pred)
|
||||
{
|
||||
if(first != last){
|
||||
ForwardIterator next = first;
|
||||
while (++next != last){
|
||||
if(!pred(*first, *next))
|
||||
return false;
|
||||
++first;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} //namespace container_detail {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DETAIL_IS_SORTED_HPP
|
||||
@@ -0,0 +1,40 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2014-2014.
|
||||
//
|
||||
// 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_DETAIL_ITERATOR_HPP
|
||||
#define BOOST_CONTAINER_DETAIL_ITERATOR_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/intrusive/detail/iterator.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
|
||||
using ::boost::intrusive::iterator_traits;
|
||||
using ::boost::intrusive::iterator_distance;
|
||||
using ::boost::intrusive::iterator_advance;
|
||||
using ::boost::intrusive::iterator;
|
||||
using ::boost::intrusive::iterator_enable_if_tag;
|
||||
using ::boost::intrusive::iterator_disable_if_tag;
|
||||
using ::boost::intrusive::iterator_arrow_result;
|
||||
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DETAIL_ITERATORS_HPP
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2014-2015. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#ifndef BOOST_CONTAINER_DETAIL_ITERATOR_TO_RAW_POINTER_HPP
|
||||
#define BOOST_CONTAINER_DETAIL_ITERATOR_TO_RAW_POINTER_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/detail/iterator.hpp>
|
||||
#include <boost/container/detail/to_raw_pointer.hpp>
|
||||
#include <boost/intrusive/pointer_traits.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace container_detail {
|
||||
|
||||
template <class T>
|
||||
inline T* iterator_to_pointer(T* i)
|
||||
{ return i; }
|
||||
|
||||
template <class Iterator>
|
||||
inline typename boost::container::iterator_traits<Iterator>::pointer
|
||||
iterator_to_pointer(const Iterator &i)
|
||||
{ return i.operator->(); }
|
||||
|
||||
template <class Iterator>
|
||||
struct iterator_to_element_ptr
|
||||
{
|
||||
typedef typename boost::container::iterator_traits<Iterator>::pointer pointer;
|
||||
typedef typename boost::intrusive::pointer_traits<pointer>::element_type element_type;
|
||||
typedef element_type* type;
|
||||
};
|
||||
|
||||
template <class Iterator>
|
||||
inline typename iterator_to_element_ptr<Iterator>::type
|
||||
iterator_to_raw_pointer(const Iterator &i)
|
||||
{
|
||||
return ::boost::intrusive::detail::to_raw_pointer
|
||||
( ::boost::container::container_detail::iterator_to_pointer(i) );
|
||||
}
|
||||
|
||||
} //namespace container_detail {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DETAIL_ITERATOR_TO_RAW_POINTER_HPP
|
||||
@@ -0,0 +1,875 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2013.
|
||||
// (C) Copyright Gennaro Prota 2003 - 2004.
|
||||
//
|
||||
// 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_DETAIL_ITERATORS_HPP
|
||||
#define BOOST_CONTAINER_DETAIL_ITERATORS_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/detail/config_begin.hpp>
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
#include <boost/container/allocator_traits.hpp>
|
||||
#include <boost/container/detail/type_traits.hpp>
|
||||
#include <boost/container/detail/value_init.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/move/utility_core.hpp>
|
||||
#include <boost/intrusive/detail/reverse_iterator.hpp>
|
||||
|
||||
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
#include <boost/move/detail/fwd_macros.hpp>
|
||||
#else
|
||||
#include <boost/container/detail/variadic_templates_tools.hpp>
|
||||
#endif
|
||||
#include <boost/container/detail/iterator.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
|
||||
template <class T, class Difference = std::ptrdiff_t>
|
||||
class constant_iterator
|
||||
: public ::boost::container::iterator
|
||||
<std::random_access_iterator_tag, T, Difference, const T*, const T &>
|
||||
{
|
||||
typedef constant_iterator<T, Difference> this_type;
|
||||
|
||||
public:
|
||||
explicit constant_iterator(const T &ref, Difference range_size)
|
||||
: m_ptr(&ref), m_num(range_size){}
|
||||
|
||||
//Constructors
|
||||
constant_iterator()
|
||||
: m_ptr(0), m_num(0){}
|
||||
|
||||
constant_iterator& operator++()
|
||||
{ increment(); return *this; }
|
||||
|
||||
constant_iterator operator++(int)
|
||||
{
|
||||
constant_iterator result (*this);
|
||||
increment();
|
||||
return result;
|
||||
}
|
||||
|
||||
constant_iterator& operator--()
|
||||
{ decrement(); return *this; }
|
||||
|
||||
constant_iterator operator--(int)
|
||||
{
|
||||
constant_iterator result (*this);
|
||||
decrement();
|
||||
return result;
|
||||
}
|
||||
|
||||
friend bool operator== (const constant_iterator& i, const constant_iterator& i2)
|
||||
{ return i.equal(i2); }
|
||||
|
||||
friend bool operator!= (const constant_iterator& i, const constant_iterator& i2)
|
||||
{ return !(i == i2); }
|
||||
|
||||
friend bool operator< (const constant_iterator& i, const constant_iterator& i2)
|
||||
{ return i.less(i2); }
|
||||
|
||||
friend bool operator> (const constant_iterator& i, const constant_iterator& i2)
|
||||
{ return i2 < i; }
|
||||
|
||||
friend bool operator<= (const constant_iterator& i, const constant_iterator& i2)
|
||||
{ return !(i > i2); }
|
||||
|
||||
friend bool operator>= (const constant_iterator& i, const constant_iterator& i2)
|
||||
{ return !(i < i2); }
|
||||
|
||||
friend Difference operator- (const constant_iterator& i, const constant_iterator& i2)
|
||||
{ return i2.distance_to(i); }
|
||||
|
||||
//Arithmetic
|
||||
constant_iterator& operator+=(Difference off)
|
||||
{ this->advance(off); return *this; }
|
||||
|
||||
constant_iterator operator+(Difference off) const
|
||||
{
|
||||
constant_iterator other(*this);
|
||||
other.advance(off);
|
||||
return other;
|
||||
}
|
||||
|
||||
friend constant_iterator operator+(Difference off, const constant_iterator& right)
|
||||
{ return right + off; }
|
||||
|
||||
constant_iterator& operator-=(Difference off)
|
||||
{ this->advance(-off); return *this; }
|
||||
|
||||
constant_iterator operator-(Difference off) const
|
||||
{ return *this + (-off); }
|
||||
|
||||
const T& operator*() const
|
||||
{ return dereference(); }
|
||||
|
||||
const T& operator[] (Difference ) const
|
||||
{ return dereference(); }
|
||||
|
||||
const T* operator->() const
|
||||
{ return &(dereference()); }
|
||||
|
||||
private:
|
||||
const T * m_ptr;
|
||||
Difference m_num;
|
||||
|
||||
void increment()
|
||||
{ --m_num; }
|
||||
|
||||
void decrement()
|
||||
{ ++m_num; }
|
||||
|
||||
bool equal(const this_type &other) const
|
||||
{ return m_num == other.m_num; }
|
||||
|
||||
bool less(const this_type &other) const
|
||||
{ return other.m_num < m_num; }
|
||||
|
||||
const T & dereference() const
|
||||
{ return *m_ptr; }
|
||||
|
||||
void advance(Difference n)
|
||||
{ m_num -= n; }
|
||||
|
||||
Difference distance_to(const this_type &other)const
|
||||
{ return m_num - other.m_num; }
|
||||
};
|
||||
|
||||
template <class T, class Difference>
|
||||
class value_init_construct_iterator
|
||||
: public ::boost::container::iterator
|
||||
<std::random_access_iterator_tag, T, Difference, const T*, const T &>
|
||||
{
|
||||
typedef value_init_construct_iterator<T, Difference> this_type;
|
||||
|
||||
public:
|
||||
explicit value_init_construct_iterator(Difference range_size)
|
||||
: m_num(range_size){}
|
||||
|
||||
//Constructors
|
||||
value_init_construct_iterator()
|
||||
: m_num(0){}
|
||||
|
||||
value_init_construct_iterator& operator++()
|
||||
{ increment(); return *this; }
|
||||
|
||||
value_init_construct_iterator operator++(int)
|
||||
{
|
||||
value_init_construct_iterator result (*this);
|
||||
increment();
|
||||
return result;
|
||||
}
|
||||
|
||||
value_init_construct_iterator& operator--()
|
||||
{ decrement(); return *this; }
|
||||
|
||||
value_init_construct_iterator operator--(int)
|
||||
{
|
||||
value_init_construct_iterator result (*this);
|
||||
decrement();
|
||||
return result;
|
||||
}
|
||||
|
||||
friend bool operator== (const value_init_construct_iterator& i, const value_init_construct_iterator& i2)
|
||||
{ return i.equal(i2); }
|
||||
|
||||
friend bool operator!= (const value_init_construct_iterator& i, const value_init_construct_iterator& i2)
|
||||
{ return !(i == i2); }
|
||||
|
||||
friend bool operator< (const value_init_construct_iterator& i, const value_init_construct_iterator& i2)
|
||||
{ return i.less(i2); }
|
||||
|
||||
friend bool operator> (const value_init_construct_iterator& i, const value_init_construct_iterator& i2)
|
||||
{ return i2 < i; }
|
||||
|
||||
friend bool operator<= (const value_init_construct_iterator& i, const value_init_construct_iterator& i2)
|
||||
{ return !(i > i2); }
|
||||
|
||||
friend bool operator>= (const value_init_construct_iterator& i, const value_init_construct_iterator& i2)
|
||||
{ return !(i < i2); }
|
||||
|
||||
friend Difference operator- (const value_init_construct_iterator& i, const value_init_construct_iterator& i2)
|
||||
{ return i2.distance_to(i); }
|
||||
|
||||
//Arithmetic
|
||||
value_init_construct_iterator& operator+=(Difference off)
|
||||
{ this->advance(off); return *this; }
|
||||
|
||||
value_init_construct_iterator operator+(Difference off) const
|
||||
{
|
||||
value_init_construct_iterator other(*this);
|
||||
other.advance(off);
|
||||
return other;
|
||||
}
|
||||
|
||||
friend value_init_construct_iterator operator+(Difference off, const value_init_construct_iterator& right)
|
||||
{ return right + off; }
|
||||
|
||||
value_init_construct_iterator& operator-=(Difference off)
|
||||
{ this->advance(-off); return *this; }
|
||||
|
||||
value_init_construct_iterator operator-(Difference off) const
|
||||
{ return *this + (-off); }
|
||||
|
||||
//This pseudo-iterator's dereference operations have no sense since value is not
|
||||
//constructed until ::boost::container::construct_in_place is called.
|
||||
//So comment them to catch bad uses
|
||||
//const T& operator*() const;
|
||||
//const T& operator[](difference_type) const;
|
||||
//const T* operator->() const;
|
||||
|
||||
private:
|
||||
Difference m_num;
|
||||
|
||||
void increment()
|
||||
{ --m_num; }
|
||||
|
||||
void decrement()
|
||||
{ ++m_num; }
|
||||
|
||||
bool equal(const this_type &other) const
|
||||
{ return m_num == other.m_num; }
|
||||
|
||||
bool less(const this_type &other) const
|
||||
{ return other.m_num < m_num; }
|
||||
|
||||
const T & dereference() const
|
||||
{
|
||||
static T dummy;
|
||||
return dummy;
|
||||
}
|
||||
|
||||
void advance(Difference n)
|
||||
{ m_num -= n; }
|
||||
|
||||
Difference distance_to(const this_type &other)const
|
||||
{ return m_num - other.m_num; }
|
||||
};
|
||||
|
||||
template <class T, class Difference>
|
||||
class default_init_construct_iterator
|
||||
: public ::boost::container::iterator
|
||||
<std::random_access_iterator_tag, T, Difference, const T*, const T &>
|
||||
{
|
||||
typedef default_init_construct_iterator<T, Difference> this_type;
|
||||
|
||||
public:
|
||||
explicit default_init_construct_iterator(Difference range_size)
|
||||
: m_num(range_size){}
|
||||
|
||||
//Constructors
|
||||
default_init_construct_iterator()
|
||||
: m_num(0){}
|
||||
|
||||
default_init_construct_iterator& operator++()
|
||||
{ increment(); return *this; }
|
||||
|
||||
default_init_construct_iterator operator++(int)
|
||||
{
|
||||
default_init_construct_iterator result (*this);
|
||||
increment();
|
||||
return result;
|
||||
}
|
||||
|
||||
default_init_construct_iterator& operator--()
|
||||
{ decrement(); return *this; }
|
||||
|
||||
default_init_construct_iterator operator--(int)
|
||||
{
|
||||
default_init_construct_iterator result (*this);
|
||||
decrement();
|
||||
return result;
|
||||
}
|
||||
|
||||
friend bool operator== (const default_init_construct_iterator& i, const default_init_construct_iterator& i2)
|
||||
{ return i.equal(i2); }
|
||||
|
||||
friend bool operator!= (const default_init_construct_iterator& i, const default_init_construct_iterator& i2)
|
||||
{ return !(i == i2); }
|
||||
|
||||
friend bool operator< (const default_init_construct_iterator& i, const default_init_construct_iterator& i2)
|
||||
{ return i.less(i2); }
|
||||
|
||||
friend bool operator> (const default_init_construct_iterator& i, const default_init_construct_iterator& i2)
|
||||
{ return i2 < i; }
|
||||
|
||||
friend bool operator<= (const default_init_construct_iterator& i, const default_init_construct_iterator& i2)
|
||||
{ return !(i > i2); }
|
||||
|
||||
friend bool operator>= (const default_init_construct_iterator& i, const default_init_construct_iterator& i2)
|
||||
{ return !(i < i2); }
|
||||
|
||||
friend Difference operator- (const default_init_construct_iterator& i, const default_init_construct_iterator& i2)
|
||||
{ return i2.distance_to(i); }
|
||||
|
||||
//Arithmetic
|
||||
default_init_construct_iterator& operator+=(Difference off)
|
||||
{ this->advance(off); return *this; }
|
||||
|
||||
default_init_construct_iterator operator+(Difference off) const
|
||||
{
|
||||
default_init_construct_iterator other(*this);
|
||||
other.advance(off);
|
||||
return other;
|
||||
}
|
||||
|
||||
friend default_init_construct_iterator operator+(Difference off, const default_init_construct_iterator& right)
|
||||
{ return right + off; }
|
||||
|
||||
default_init_construct_iterator& operator-=(Difference off)
|
||||
{ this->advance(-off); return *this; }
|
||||
|
||||
default_init_construct_iterator operator-(Difference off) const
|
||||
{ return *this + (-off); }
|
||||
|
||||
//This pseudo-iterator's dereference operations have no sense since value is not
|
||||
//constructed until ::boost::container::construct_in_place is called.
|
||||
//So comment them to catch bad uses
|
||||
//const T& operator*() const;
|
||||
//const T& operator[](difference_type) const;
|
||||
//const T* operator->() const;
|
||||
|
||||
private:
|
||||
Difference m_num;
|
||||
|
||||
void increment()
|
||||
{ --m_num; }
|
||||
|
||||
void decrement()
|
||||
{ ++m_num; }
|
||||
|
||||
bool equal(const this_type &other) const
|
||||
{ return m_num == other.m_num; }
|
||||
|
||||
bool less(const this_type &other) const
|
||||
{ return other.m_num < m_num; }
|
||||
|
||||
const T & dereference() const
|
||||
{
|
||||
static T dummy;
|
||||
return dummy;
|
||||
}
|
||||
|
||||
void advance(Difference n)
|
||||
{ m_num -= n; }
|
||||
|
||||
Difference distance_to(const this_type &other)const
|
||||
{ return m_num - other.m_num; }
|
||||
};
|
||||
|
||||
|
||||
template <class T, class Difference = std::ptrdiff_t>
|
||||
class repeat_iterator
|
||||
: public ::boost::container::iterator
|
||||
<std::random_access_iterator_tag, T, Difference, T*, T&>
|
||||
{
|
||||
typedef repeat_iterator<T, Difference> this_type;
|
||||
public:
|
||||
explicit repeat_iterator(T &ref, Difference range_size)
|
||||
: m_ptr(&ref), m_num(range_size){}
|
||||
|
||||
//Constructors
|
||||
repeat_iterator()
|
||||
: m_ptr(0), m_num(0){}
|
||||
|
||||
this_type& operator++()
|
||||
{ increment(); return *this; }
|
||||
|
||||
this_type operator++(int)
|
||||
{
|
||||
this_type result (*this);
|
||||
increment();
|
||||
return result;
|
||||
}
|
||||
|
||||
this_type& operator--()
|
||||
{ increment(); return *this; }
|
||||
|
||||
this_type operator--(int)
|
||||
{
|
||||
this_type result (*this);
|
||||
increment();
|
||||
return result;
|
||||
}
|
||||
|
||||
friend bool operator== (const this_type& i, const this_type& i2)
|
||||
{ return i.equal(i2); }
|
||||
|
||||
friend bool operator!= (const this_type& i, const this_type& i2)
|
||||
{ return !(i == i2); }
|
||||
|
||||
friend bool operator< (const this_type& i, const this_type& i2)
|
||||
{ return i.less(i2); }
|
||||
|
||||
friend bool operator> (const this_type& i, const this_type& i2)
|
||||
{ return i2 < i; }
|
||||
|
||||
friend bool operator<= (const this_type& i, const this_type& i2)
|
||||
{ return !(i > i2); }
|
||||
|
||||
friend bool operator>= (const this_type& i, const this_type& i2)
|
||||
{ return !(i < i2); }
|
||||
|
||||
friend Difference operator- (const this_type& i, const this_type& i2)
|
||||
{ return i2.distance_to(i); }
|
||||
|
||||
//Arithmetic
|
||||
this_type& operator+=(Difference off)
|
||||
{ this->advance(off); return *this; }
|
||||
|
||||
this_type operator+(Difference off) const
|
||||
{
|
||||
this_type other(*this);
|
||||
other.advance(off);
|
||||
return other;
|
||||
}
|
||||
|
||||
friend this_type operator+(Difference off, const this_type& right)
|
||||
{ return right + off; }
|
||||
|
||||
this_type& operator-=(Difference off)
|
||||
{ this->advance(-off); return *this; }
|
||||
|
||||
this_type operator-(Difference off) const
|
||||
{ return *this + (-off); }
|
||||
|
||||
T& operator*() const
|
||||
{ return dereference(); }
|
||||
|
||||
T& operator[] (Difference ) const
|
||||
{ return dereference(); }
|
||||
|
||||
T *operator->() const
|
||||
{ return &(dereference()); }
|
||||
|
||||
private:
|
||||
T * m_ptr;
|
||||
Difference m_num;
|
||||
|
||||
void increment()
|
||||
{ --m_num; }
|
||||
|
||||
void decrement()
|
||||
{ ++m_num; }
|
||||
|
||||
bool equal(const this_type &other) const
|
||||
{ return m_num == other.m_num; }
|
||||
|
||||
bool less(const this_type &other) const
|
||||
{ return other.m_num < m_num; }
|
||||
|
||||
T & dereference() const
|
||||
{ return *m_ptr; }
|
||||
|
||||
void advance(Difference n)
|
||||
{ m_num -= n; }
|
||||
|
||||
Difference distance_to(const this_type &other)const
|
||||
{ return m_num - other.m_num; }
|
||||
};
|
||||
|
||||
template <class T, class EmplaceFunctor, class Difference /*= std::ptrdiff_t*/>
|
||||
class emplace_iterator
|
||||
: public ::boost::container::iterator
|
||||
<std::random_access_iterator_tag, T, Difference, const T*, const T &>
|
||||
{
|
||||
typedef emplace_iterator this_type;
|
||||
|
||||
public:
|
||||
typedef Difference difference_type;
|
||||
BOOST_CONTAINER_FORCEINLINE explicit emplace_iterator(EmplaceFunctor&e)
|
||||
: m_num(1), m_pe(&e){}
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE emplace_iterator()
|
||||
: m_num(0), m_pe(0){}
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE this_type& operator++()
|
||||
{ increment(); return *this; }
|
||||
|
||||
this_type operator++(int)
|
||||
{
|
||||
this_type result (*this);
|
||||
increment();
|
||||
return result;
|
||||
}
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE this_type& operator--()
|
||||
{ decrement(); return *this; }
|
||||
|
||||
this_type operator--(int)
|
||||
{
|
||||
this_type result (*this);
|
||||
decrement();
|
||||
return result;
|
||||
}
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE friend bool operator== (const this_type& i, const this_type& i2)
|
||||
{ return i.equal(i2); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE friend bool operator!= (const this_type& i, const this_type& i2)
|
||||
{ return !(i == i2); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE friend bool operator< (const this_type& i, const this_type& i2)
|
||||
{ return i.less(i2); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE friend bool operator> (const this_type& i, const this_type& i2)
|
||||
{ return i2 < i; }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE friend bool operator<= (const this_type& i, const this_type& i2)
|
||||
{ return !(i > i2); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE friend bool operator>= (const this_type& i, const this_type& i2)
|
||||
{ return !(i < i2); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE friend difference_type operator- (const this_type& i, const this_type& i2)
|
||||
{ return i2.distance_to(i); }
|
||||
|
||||
//Arithmetic
|
||||
BOOST_CONTAINER_FORCEINLINE this_type& operator+=(difference_type off)
|
||||
{ this->advance(off); return *this; }
|
||||
|
||||
this_type operator+(difference_type off) const
|
||||
{
|
||||
this_type other(*this);
|
||||
other.advance(off);
|
||||
return other;
|
||||
}
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE friend this_type operator+(difference_type off, const this_type& right)
|
||||
{ return right + off; }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE this_type& operator-=(difference_type off)
|
||||
{ this->advance(-off); return *this; }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE this_type operator-(difference_type off) const
|
||||
{ return *this + (-off); }
|
||||
|
||||
private:
|
||||
//This pseudo-iterator's dereference operations have no sense since value is not
|
||||
//constructed until ::boost::container::construct_in_place is called.
|
||||
//So comment them to catch bad uses
|
||||
const T& operator*() const;
|
||||
const T& operator[](difference_type) const;
|
||||
const T* operator->() const;
|
||||
|
||||
public:
|
||||
template<class Allocator>
|
||||
void construct_in_place(Allocator &a, T* ptr)
|
||||
{ (*m_pe)(a, ptr); }
|
||||
|
||||
template<class DestIt>
|
||||
void assign_in_place(DestIt dest)
|
||||
{ (*m_pe)(dest); }
|
||||
|
||||
private:
|
||||
difference_type m_num;
|
||||
EmplaceFunctor * m_pe;
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE void increment()
|
||||
{ --m_num; }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE void decrement()
|
||||
{ ++m_num; }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE bool equal(const this_type &other) const
|
||||
{ return m_num == other.m_num; }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE bool less(const this_type &other) const
|
||||
{ return other.m_num < m_num; }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE const T & dereference() const
|
||||
{
|
||||
static T dummy;
|
||||
return dummy;
|
||||
}
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE void advance(difference_type n)
|
||||
{ m_num -= n; }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE difference_type distance_to(const this_type &other)const
|
||||
{ return difference_type(m_num - other.m_num); }
|
||||
};
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
template<class ...Args>
|
||||
struct emplace_functor
|
||||
{
|
||||
typedef typename container_detail::build_number_seq<sizeof...(Args)>::type index_tuple_t;
|
||||
|
||||
emplace_functor(BOOST_FWD_REF(Args)... args)
|
||||
: args_(args...)
|
||||
{}
|
||||
|
||||
template<class Allocator, class T>
|
||||
BOOST_CONTAINER_FORCEINLINE void operator()(Allocator &a, T *ptr)
|
||||
{ emplace_functor::inplace_impl(a, ptr, index_tuple_t()); }
|
||||
|
||||
template<class DestIt>
|
||||
BOOST_CONTAINER_FORCEINLINE void operator()(DestIt dest)
|
||||
{ emplace_functor::inplace_impl(dest, index_tuple_t()); }
|
||||
|
||||
private:
|
||||
template<class Allocator, class T, std::size_t ...IdxPack>
|
||||
BOOST_CONTAINER_FORCEINLINE void inplace_impl(Allocator &a, T* ptr, const container_detail::index_tuple<IdxPack...>&)
|
||||
{
|
||||
allocator_traits<Allocator>::construct
|
||||
(a, ptr, ::boost::forward<Args>(container_detail::get<IdxPack>(args_))...);
|
||||
}
|
||||
|
||||
template<class DestIt, std::size_t ...IdxPack>
|
||||
BOOST_CONTAINER_FORCEINLINE void inplace_impl(DestIt dest, const container_detail::index_tuple<IdxPack...>&)
|
||||
{
|
||||
typedef typename boost::container::iterator_traits<DestIt>::value_type value_type;
|
||||
value_type && tmp= value_type(::boost::forward<Args>(container_detail::get<IdxPack>(args_))...);
|
||||
*dest = ::boost::move(tmp);
|
||||
}
|
||||
|
||||
container_detail::tuple<Args&...> args_;
|
||||
};
|
||||
|
||||
template<class ...Args>
|
||||
struct emplace_functor_type
|
||||
{
|
||||
typedef emplace_functor<Args...> type;
|
||||
};
|
||||
|
||||
#else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
//Partial specializations cannot match argument list for primary template, so add an extra argument
|
||||
template <BOOST_MOVE_CLASSDFLT9, class Dummy = void>
|
||||
struct emplace_functor_type;
|
||||
|
||||
#define BOOST_MOVE_ITERATOR_EMPLACE_FUNCTOR_CODE(N) \
|
||||
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
|
||||
struct emplace_functor##N\
|
||||
{\
|
||||
explicit emplace_functor##N( BOOST_MOVE_UREF##N )\
|
||||
BOOST_MOVE_COLON##N BOOST_MOVE_FWD_INIT##N{}\
|
||||
\
|
||||
template<class Allocator, class T>\
|
||||
void operator()(Allocator &a, T *ptr)\
|
||||
{ allocator_traits<Allocator>::construct(a, ptr BOOST_MOVE_I##N BOOST_MOVE_MFWD##N); }\
|
||||
\
|
||||
template<class DestIt>\
|
||||
void operator()(DestIt dest)\
|
||||
{\
|
||||
typedef typename boost::container::iterator_traits<DestIt>::value_type value_type;\
|
||||
BOOST_MOVE_IF(N, value_type tmp(BOOST_MOVE_MFWD##N), container_detail::value_init<value_type> tmp) ;\
|
||||
*dest = ::boost::move(const_cast<value_type &>(BOOST_MOVE_IF(N, tmp, tmp.get())));\
|
||||
}\
|
||||
\
|
||||
BOOST_MOVE_MREF##N\
|
||||
};\
|
||||
\
|
||||
template <BOOST_MOVE_CLASS##N>\
|
||||
struct emplace_functor_type<BOOST_MOVE_TARG##N>\
|
||||
{\
|
||||
typedef emplace_functor##N BOOST_MOVE_LT##N BOOST_MOVE_TARG##N BOOST_MOVE_GT##N type;\
|
||||
};\
|
||||
//
|
||||
|
||||
BOOST_MOVE_ITERATE_0TO9(BOOST_MOVE_ITERATOR_EMPLACE_FUNCTOR_CODE)
|
||||
|
||||
#undef BOOST_MOVE_ITERATOR_EMPLACE_FUNCTOR_CODE
|
||||
|
||||
#endif
|
||||
|
||||
namespace container_detail {
|
||||
|
||||
template<class T>
|
||||
struct has_iterator_category
|
||||
{
|
||||
struct two { char _[2]; };
|
||||
|
||||
template <typename X>
|
||||
static char test(int, typename X::iterator_category*);
|
||||
|
||||
template <typename X>
|
||||
static two test(int, ...);
|
||||
|
||||
static const bool value = (1 == sizeof(test<T>(0, 0)));
|
||||
};
|
||||
|
||||
|
||||
template<class T, bool = has_iterator_category<T>::value >
|
||||
struct is_input_iterator
|
||||
{
|
||||
static const bool value = is_same<typename T::iterator_category, std::input_iterator_tag>::value;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct is_input_iterator<T, false>
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct is_not_input_iterator
|
||||
{
|
||||
static const bool value = !is_input_iterator<T>::value;
|
||||
};
|
||||
|
||||
template<class T, bool = has_iterator_category<T>::value >
|
||||
struct is_forward_iterator
|
||||
{
|
||||
static const bool value = is_same<typename T::iterator_category, std::forward_iterator_tag>::value;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct is_forward_iterator<T, false>
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template<class T, bool = has_iterator_category<T>::value >
|
||||
struct is_bidirectional_iterator
|
||||
{
|
||||
static const bool value = is_same<typename T::iterator_category, std::bidirectional_iterator_tag>::value;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct is_bidirectional_iterator<T, false>
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template<class IINodeType>
|
||||
struct iiterator_node_value_type {
|
||||
typedef typename IINodeType::value_type type;
|
||||
};
|
||||
|
||||
template<class IIterator>
|
||||
struct iiterator_types
|
||||
{
|
||||
typedef typename IIterator::value_type it_value_type;
|
||||
typedef typename iiterator_node_value_type<it_value_type>::type value_type;
|
||||
typedef typename boost::container::iterator_traits<IIterator>::pointer it_pointer;
|
||||
typedef typename boost::container::iterator_traits<IIterator>::difference_type difference_type;
|
||||
typedef typename ::boost::intrusive::pointer_traits<it_pointer>::
|
||||
template rebind_pointer<value_type>::type pointer;
|
||||
typedef typename ::boost::intrusive::pointer_traits<it_pointer>::
|
||||
template rebind_pointer<const value_type>::type const_pointer;
|
||||
typedef typename ::boost::intrusive::
|
||||
pointer_traits<pointer>::reference reference;
|
||||
typedef typename ::boost::intrusive::
|
||||
pointer_traits<const_pointer>::reference const_reference;
|
||||
typedef typename IIterator::iterator_category iterator_category;
|
||||
};
|
||||
|
||||
template<class IIterator, bool IsConst>
|
||||
struct iterator_types
|
||||
{
|
||||
typedef typename ::boost::container::iterator
|
||||
< typename iiterator_types<IIterator>::iterator_category
|
||||
, typename iiterator_types<IIterator>::value_type
|
||||
, typename iiterator_types<IIterator>::difference_type
|
||||
, typename iiterator_types<IIterator>::const_pointer
|
||||
, typename iiterator_types<IIterator>::const_reference> type;
|
||||
};
|
||||
|
||||
template<class IIterator>
|
||||
struct iterator_types<IIterator, false>
|
||||
{
|
||||
typedef typename ::boost::container::iterator
|
||||
< typename iiterator_types<IIterator>::iterator_category
|
||||
, typename iiterator_types<IIterator>::value_type
|
||||
, typename iiterator_types<IIterator>::difference_type
|
||||
, typename iiterator_types<IIterator>::pointer
|
||||
, typename iiterator_types<IIterator>::reference> type;
|
||||
};
|
||||
|
||||
template<class IIterator, bool IsConst>
|
||||
class iterator_from_iiterator
|
||||
{
|
||||
typedef typename iterator_types<IIterator, IsConst>::type types_t;
|
||||
|
||||
public:
|
||||
typedef typename types_t::pointer pointer;
|
||||
typedef typename types_t::reference reference;
|
||||
typedef typename types_t::difference_type difference_type;
|
||||
typedef typename types_t::iterator_category iterator_category;
|
||||
typedef typename types_t::value_type value_type;
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE iterator_from_iiterator()
|
||||
: m_iit()
|
||||
{}
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE explicit iterator_from_iiterator(IIterator iit) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
: m_iit(iit)
|
||||
{}
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE iterator_from_iiterator(iterator_from_iiterator<IIterator, false> const& other) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
: m_iit(other.get())
|
||||
{}
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE iterator_from_iiterator& operator++() BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ ++this->m_iit; return *this; }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE iterator_from_iiterator operator++(int) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{
|
||||
iterator_from_iiterator result (*this);
|
||||
++this->m_iit;
|
||||
return result;
|
||||
}
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE iterator_from_iiterator& operator--() BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{
|
||||
//If the iterator_from_iiterator is not a bidirectional iterator, operator-- should not exist
|
||||
BOOST_STATIC_ASSERT((is_bidirectional_iterator<iterator_from_iiterator>::value));
|
||||
--this->m_iit; return *this;
|
||||
}
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE iterator_from_iiterator operator--(int) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{
|
||||
iterator_from_iiterator result (*this);
|
||||
--this->m_iit;
|
||||
return result;
|
||||
}
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE friend bool operator== (const iterator_from_iiterator& l, const iterator_from_iiterator& r) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return l.m_iit == r.m_iit; }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE friend bool operator!= (const iterator_from_iiterator& l, const iterator_from_iiterator& r) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return !(l == r); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE reference operator*() const BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return this->m_iit->get_data(); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE pointer operator->() const BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return ::boost::intrusive::pointer_traits<pointer>::pointer_to(this->operator*()); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE const IIterator &get() const BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return this->m_iit; }
|
||||
|
||||
private:
|
||||
IIterator m_iit;
|
||||
};
|
||||
|
||||
} //namespace container_detail {
|
||||
|
||||
using ::boost::intrusive::reverse_iterator;
|
||||
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DETAIL_ITERATORS_HPP
|
||||
@@ -0,0 +1,123 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Stephen Cleary 2000.
|
||||
// (C) Copyright Ion Gaztanaga 2007-2013.
|
||||
//
|
||||
// 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/container for documentation.
|
||||
//
|
||||
// This file is a slightly modified file from Boost.Pool
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_DETAIL_MATH_FUNCTIONS_HPP
|
||||
#define BOOST_CONTAINER_DETAIL_MATH_FUNCTIONS_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/detail/config_begin.hpp>
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
|
||||
#include <climits>
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace container_detail {
|
||||
|
||||
// Greatest common divisor and least common multiple
|
||||
|
||||
//
|
||||
// gcd is an algorithm that calculates the greatest common divisor of two
|
||||
// integers, using Euclid's algorithm.
|
||||
//
|
||||
// Pre: A > 0 && B > 0
|
||||
// Recommended: A > B
|
||||
template <typename Integer>
|
||||
inline Integer gcd(Integer A, Integer B)
|
||||
{
|
||||
do
|
||||
{
|
||||
const Integer tmp(B);
|
||||
B = A % B;
|
||||
A = tmp;
|
||||
} while (B != 0);
|
||||
|
||||
return A;
|
||||
}
|
||||
|
||||
//
|
||||
// lcm is an algorithm that calculates the least common multiple of two
|
||||
// integers.
|
||||
//
|
||||
// Pre: A > 0 && B > 0
|
||||
// Recommended: A > B
|
||||
template <typename Integer>
|
||||
inline Integer lcm(const Integer & A, const Integer & B)
|
||||
{
|
||||
Integer ret = A;
|
||||
ret /= gcd(A, B);
|
||||
ret *= B;
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename Integer>
|
||||
inline Integer log2_ceil(const Integer & A)
|
||||
{
|
||||
Integer i = 0;
|
||||
Integer power_of_2 = 1;
|
||||
|
||||
while(power_of_2 < A){
|
||||
power_of_2 <<= 1;
|
||||
++i;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
template <typename Integer>
|
||||
inline Integer upper_power_of_2(const Integer & A)
|
||||
{
|
||||
Integer power_of_2 = 1;
|
||||
|
||||
while(power_of_2 < A){
|
||||
power_of_2 <<= 1;
|
||||
}
|
||||
return power_of_2;
|
||||
}
|
||||
|
||||
//This function uses binary search to discover the
|
||||
//highest set bit of the integer
|
||||
inline std::size_t floor_log2 (std::size_t x)
|
||||
{
|
||||
const std::size_t Bits = sizeof(std::size_t)*CHAR_BIT;
|
||||
const bool Size_t_Bits_Power_2= !(Bits & (Bits-1));
|
||||
BOOST_STATIC_ASSERT(((Size_t_Bits_Power_2)== true));
|
||||
|
||||
std::size_t n = x;
|
||||
std::size_t log2 = 0;
|
||||
|
||||
for(std::size_t shift = Bits >> 1; shift; shift >>= 1){
|
||||
std::size_t tmp = n >> shift;
|
||||
if (tmp)
|
||||
log2 += shift, n = tmp;
|
||||
}
|
||||
|
||||
return log2;
|
||||
}
|
||||
|
||||
} // namespace container_detail
|
||||
} // namespace container
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,37 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2013. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#ifndef BOOST_CONTAINER_DETAIL_MIN_MAX_HPP
|
||||
#define BOOST_CONTAINER_DETAIL_MIN_MAX_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace container_detail {
|
||||
|
||||
template<class T>
|
||||
const T &max_value(const T &a, const T &b)
|
||||
{ return a > b ? a : b; }
|
||||
|
||||
template<class T>
|
||||
const T &min_value(const T &a, const T &b)
|
||||
{ return a < b ? a : b; }
|
||||
|
||||
} //namespace container_detail {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DETAIL_MIN_MAX_HPP
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2014-2015
|
||||
//
|
||||
// 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/container for documentation.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#ifndef BOOST_CONTAINER_DETAIL_MINIMAL_CHAR_TRAITS_HEADER_HPP
|
||||
#define BOOST_CONTAINER_DETAIL_MINIMAL_CHAR_TRAITS_HEADER_HPP
|
||||
#
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
#
|
||||
#//Try to avoid including <string>, as it's quite big
|
||||
#if defined(_MSC_VER) && defined(BOOST_DINKUMWARE_STDLIB)
|
||||
#include <iosfwd> //Dinkum libraries for MSVC define std::char_traits there
|
||||
#elif defined(BOOST_GNU_STDLIB)
|
||||
#include <bits/char_traits.h>
|
||||
#else
|
||||
#include <string> //Fallback
|
||||
#endif
|
||||
|
||||
#endif //BOOST_CONTAINER_DETAIL_MINIMAL_CHAR_TRAITS_HEADER_HPP
|
||||
@@ -0,0 +1,86 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2013.
|
||||
//
|
||||
// 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_CONTAINER_DETAIL_MPL_HPP
|
||||
#define BOOST_CONTAINER_CONTAINER_DETAIL_MPL_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/detail/config_begin.hpp>
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
#include <boost/move/detail/type_traits.hpp>
|
||||
#include <boost/intrusive/detail/mpl.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace container_detail {
|
||||
|
||||
using boost::move_detail::integral_constant;
|
||||
using boost::move_detail::true_type;
|
||||
using boost::move_detail::false_type;
|
||||
using boost::move_detail::enable_if_c;
|
||||
using boost::move_detail::enable_if;
|
||||
using boost::move_detail::enable_if_convertible;
|
||||
using boost::move_detail::disable_if_c;
|
||||
using boost::move_detail::disable_if;
|
||||
using boost::move_detail::disable_if_convertible;
|
||||
using boost::move_detail::is_convertible;
|
||||
using boost::move_detail::if_c;
|
||||
using boost::move_detail::if_;
|
||||
using boost::move_detail::identity;
|
||||
using boost::move_detail::bool_;
|
||||
using boost::move_detail::true_;
|
||||
using boost::move_detail::false_;
|
||||
using boost::move_detail::yes_type;
|
||||
using boost::move_detail::no_type;
|
||||
using boost::move_detail::bool_;
|
||||
using boost::move_detail::true_;
|
||||
using boost::move_detail::false_;
|
||||
using boost::move_detail::unvoid_ref;
|
||||
using boost::move_detail::and_;
|
||||
using boost::move_detail::or_;
|
||||
using boost::move_detail::not_;
|
||||
using boost::move_detail::enable_if_and;
|
||||
using boost::move_detail::disable_if_and;
|
||||
using boost::move_detail::enable_if_or;
|
||||
using boost::move_detail::disable_if_or;
|
||||
|
||||
template <class FirstType>
|
||||
struct select1st
|
||||
{
|
||||
typedef FirstType type;
|
||||
|
||||
template<class T>
|
||||
const type& operator()(const T& x) const
|
||||
{ return x.first; }
|
||||
|
||||
template<class T>
|
||||
type& operator()(T& x)
|
||||
{ return const_cast<type&>(x.first); }
|
||||
};
|
||||
|
||||
} //namespace container_detail {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_CONTAINER_DETAIL_MPL_HPP
|
||||
|
||||
@@ -0,0 +1,298 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2013. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_DETAIL_MULTIALLOCATION_CHAIN_HPP
|
||||
#define BOOST_CONTAINER_DETAIL_MULTIALLOCATION_CHAIN_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/detail/config_begin.hpp>
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
// container
|
||||
#include <boost/container/container_fwd.hpp>
|
||||
// container/detail
|
||||
#include <boost/container/detail/to_raw_pointer.hpp>
|
||||
#include <boost/container/detail/transform_iterator.hpp>
|
||||
#include <boost/container/detail/type_traits.hpp>
|
||||
// intrusive
|
||||
#include <boost/intrusive/slist.hpp>
|
||||
#include <boost/intrusive/pointer_traits.hpp>
|
||||
// move
|
||||
#include <boost/move/utility_core.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace container_detail {
|
||||
|
||||
template<class VoidPointer>
|
||||
class basic_multiallocation_chain
|
||||
{
|
||||
private:
|
||||
typedef bi::slist_base_hook<bi::void_pointer<VoidPointer>
|
||||
,bi::link_mode<bi::normal_link>
|
||||
> node;
|
||||
|
||||
typedef typename boost::intrusive::pointer_traits
|
||||
<VoidPointer>::template rebind_pointer<char>::type char_ptr;
|
||||
typedef typename boost::intrusive::
|
||||
pointer_traits<char_ptr>::difference_type difference_type;
|
||||
|
||||
typedef bi::slist< node
|
||||
, bi::linear<true>
|
||||
, bi::cache_last<true>
|
||||
, bi::size_type<typename boost::container::container_detail::make_unsigned<difference_type>::type>
|
||||
> slist_impl_t;
|
||||
slist_impl_t slist_impl_;
|
||||
|
||||
typedef typename boost::intrusive::pointer_traits
|
||||
<VoidPointer>::template rebind_pointer<node>::type node_ptr;
|
||||
typedef typename boost::intrusive::
|
||||
pointer_traits<node_ptr> node_ptr_traits;
|
||||
|
||||
static node & to_node(const VoidPointer &p)
|
||||
{ return *static_cast<node*>(static_cast<void*>(container_detail::to_raw_pointer(p))); }
|
||||
|
||||
static VoidPointer from_node(node &n)
|
||||
{ return node_ptr_traits::pointer_to(n); }
|
||||
|
||||
static node_ptr to_node_ptr(const VoidPointer &p)
|
||||
{ return node_ptr_traits::static_cast_from(p); }
|
||||
|
||||
BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_multiallocation_chain)
|
||||
|
||||
public:
|
||||
|
||||
typedef VoidPointer void_pointer;
|
||||
typedef typename slist_impl_t::iterator iterator;
|
||||
typedef typename slist_impl_t::size_type size_type;
|
||||
|
||||
basic_multiallocation_chain()
|
||||
: slist_impl_()
|
||||
{}
|
||||
|
||||
basic_multiallocation_chain(const void_pointer &b, const void_pointer &before_e, size_type n)
|
||||
: slist_impl_(to_node_ptr(b), to_node_ptr(before_e), n)
|
||||
{}
|
||||
|
||||
basic_multiallocation_chain(BOOST_RV_REF(basic_multiallocation_chain) other)
|
||||
: slist_impl_(::boost::move(other.slist_impl_))
|
||||
{}
|
||||
|
||||
basic_multiallocation_chain& operator=(BOOST_RV_REF(basic_multiallocation_chain) other)
|
||||
{
|
||||
slist_impl_ = ::boost::move(other.slist_impl_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{ return slist_impl_.empty(); }
|
||||
|
||||
size_type size() const
|
||||
{ return slist_impl_.size(); }
|
||||
|
||||
iterator before_begin()
|
||||
{ return slist_impl_.before_begin(); }
|
||||
|
||||
iterator begin()
|
||||
{ return slist_impl_.begin(); }
|
||||
|
||||
iterator end()
|
||||
{ return slist_impl_.end(); }
|
||||
|
||||
iterator last()
|
||||
{ return slist_impl_.last(); }
|
||||
|
||||
void clear()
|
||||
{ slist_impl_.clear(); }
|
||||
|
||||
iterator insert_after(iterator it, void_pointer m)
|
||||
{ return slist_impl_.insert_after(it, to_node(m)); }
|
||||
|
||||
void push_front(const void_pointer &m)
|
||||
{ return slist_impl_.push_front(to_node(m)); }
|
||||
|
||||
void push_back(const void_pointer &m)
|
||||
{ return slist_impl_.push_back(to_node(m)); }
|
||||
|
||||
void_pointer pop_front()
|
||||
{
|
||||
node & n = slist_impl_.front();
|
||||
void_pointer ret = from_node(n);
|
||||
slist_impl_.pop_front();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void splice_after(iterator after_this, basic_multiallocation_chain &x, iterator before_b, iterator before_e, size_type n)
|
||||
{ slist_impl_.splice_after(after_this, x.slist_impl_, before_b, before_e, n); }
|
||||
|
||||
void splice_after(iterator after_this, basic_multiallocation_chain &x)
|
||||
{ slist_impl_.splice_after(after_this, x.slist_impl_); }
|
||||
|
||||
void erase_after(iterator before_b, iterator e, size_type n)
|
||||
{ slist_impl_.erase_after(before_b, e, n); }
|
||||
|
||||
void_pointer incorporate_after(iterator after_this, const void_pointer &b, size_type unit_bytes, size_type num_units)
|
||||
{
|
||||
typedef typename boost::intrusive::pointer_traits<char_ptr> char_pointer_traits;
|
||||
char_ptr elem = char_pointer_traits::static_cast_from(b);
|
||||
if(num_units){
|
||||
char_ptr prev_elem = elem;
|
||||
elem += unit_bytes;
|
||||
for(size_type i = 0; i != num_units-1; ++i, elem += unit_bytes){
|
||||
::new (container_detail::to_raw_pointer(prev_elem)) void_pointer(elem);
|
||||
prev_elem = elem;
|
||||
}
|
||||
slist_impl_.incorporate_after(after_this, to_node_ptr(b), to_node_ptr(prev_elem), num_units);
|
||||
}
|
||||
return elem;
|
||||
}
|
||||
|
||||
void incorporate_after(iterator after_this, void_pointer b, void_pointer before_e, size_type n)
|
||||
{ slist_impl_.incorporate_after(after_this, to_node_ptr(b), to_node_ptr(before_e), n); }
|
||||
|
||||
void swap(basic_multiallocation_chain &x)
|
||||
{ slist_impl_.swap(x.slist_impl_); }
|
||||
|
||||
static iterator iterator_to(const void_pointer &p)
|
||||
{ return slist_impl_t::s_iterator_to(to_node(p)); }
|
||||
|
||||
std::pair<void_pointer, void_pointer> extract_data()
|
||||
{
|
||||
std::pair<void_pointer, void_pointer> ret
|
||||
(slist_impl_.begin().operator->()
|
||||
,slist_impl_.last().operator->());
|
||||
slist_impl_.clear();
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct cast_functor
|
||||
{
|
||||
typedef typename container_detail::add_reference<T>::type result_type;
|
||||
template<class U>
|
||||
result_type operator()(U &ptr) const
|
||||
{ return *static_cast<T*>(static_cast<void*>(&ptr)); }
|
||||
};
|
||||
|
||||
template<class MultiallocationChain, class T>
|
||||
class transform_multiallocation_chain
|
||||
: public MultiallocationChain
|
||||
{
|
||||
private:
|
||||
BOOST_MOVABLE_BUT_NOT_COPYABLE(transform_multiallocation_chain)
|
||||
//transform_multiallocation_chain(const transform_multiallocation_chain &);
|
||||
//transform_multiallocation_chain & operator=(const transform_multiallocation_chain &);
|
||||
|
||||
typedef typename MultiallocationChain::void_pointer void_pointer;
|
||||
typedef typename boost::intrusive::pointer_traits
|
||||
<void_pointer> void_pointer_traits;
|
||||
typedef typename void_pointer_traits::template
|
||||
rebind_pointer<T>::type pointer;
|
||||
typedef typename boost::intrusive::pointer_traits
|
||||
<pointer> pointer_traits;
|
||||
|
||||
static pointer cast(const void_pointer &p)
|
||||
{ return pointer_traits::static_cast_from(p); }
|
||||
|
||||
public:
|
||||
typedef transform_iterator
|
||||
< typename MultiallocationChain::iterator
|
||||
, container_detail::cast_functor <T> > iterator;
|
||||
typedef typename MultiallocationChain::size_type size_type;
|
||||
|
||||
transform_multiallocation_chain()
|
||||
: MultiallocationChain()
|
||||
{}
|
||||
|
||||
transform_multiallocation_chain(BOOST_RV_REF(transform_multiallocation_chain) other)
|
||||
: MultiallocationChain(::boost::move(static_cast<MultiallocationChain&>(other)))
|
||||
{}
|
||||
|
||||
transform_multiallocation_chain(BOOST_RV_REF(MultiallocationChain) other)
|
||||
: MultiallocationChain(::boost::move(static_cast<MultiallocationChain&>(other)))
|
||||
{}
|
||||
|
||||
transform_multiallocation_chain& operator=(BOOST_RV_REF(transform_multiallocation_chain) other)
|
||||
{
|
||||
return static_cast<MultiallocationChain&>
|
||||
(this->MultiallocationChain::operator=(::boost::move(static_cast<MultiallocationChain&>(other))));
|
||||
}
|
||||
/*
|
||||
void push_front(const pointer &mem)
|
||||
{ holder_.push_front(mem); }
|
||||
|
||||
void push_back(const pointer &mem)
|
||||
{ return holder_.push_back(mem); }
|
||||
|
||||
void swap(transform_multiallocation_chain &other_chain)
|
||||
{ holder_.swap(other_chain.holder_); }
|
||||
|
||||
void splice_after(iterator after_this, transform_multiallocation_chain &x, iterator before_b, iterator before_e, size_type n)
|
||||
{ holder_.splice_after(after_this.base(), x.holder_, before_b.base(), before_e.base(), n); }
|
||||
|
||||
void incorporate_after(iterator after_this, pointer b, pointer before_e, size_type n)
|
||||
{ holder_.incorporate_after(after_this.base(), b, before_e, n); }
|
||||
*/
|
||||
pointer pop_front()
|
||||
{ return cast(this->MultiallocationChain::pop_front()); }
|
||||
/*
|
||||
bool empty() const
|
||||
{ return holder_.empty(); }
|
||||
|
||||
iterator before_begin()
|
||||
{ return iterator(holder_.before_begin()); }
|
||||
*/
|
||||
iterator begin()
|
||||
{ return iterator(this->MultiallocationChain::begin()); }
|
||||
/*
|
||||
iterator end()
|
||||
{ return iterator(holder_.end()); }
|
||||
|
||||
iterator last()
|
||||
{ return iterator(holder_.last()); }
|
||||
|
||||
size_type size() const
|
||||
{ return holder_.size(); }
|
||||
|
||||
void clear()
|
||||
{ holder_.clear(); }
|
||||
*/
|
||||
iterator insert_after(iterator it, pointer m)
|
||||
{ return iterator(this->MultiallocationChain::insert_after(it.base(), m)); }
|
||||
|
||||
static iterator iterator_to(const pointer &p)
|
||||
{ return iterator(MultiallocationChain::iterator_to(p)); }
|
||||
|
||||
std::pair<pointer, pointer> extract_data()
|
||||
{
|
||||
std::pair<void_pointer, void_pointer> data(this->MultiallocationChain::extract_data());
|
||||
return std::pair<pointer, pointer>(cast(data.first), cast(data.second));
|
||||
}
|
||||
/*
|
||||
MultiallocationChain &extract_multiallocation_chain()
|
||||
{ return holder_; }*/
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
// namespace container_detail {
|
||||
// namespace container {
|
||||
// namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_CONTAINER_DETAIL_MULTIALLOCATION_CHAIN_HPP
|
||||
@@ -0,0 +1,283 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Stephen Cleary 2000
|
||||
// (C) Copyright Ion Gaztanaga 2015-2017.
|
||||
//
|
||||
// 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_MUTEX_HPP
|
||||
#define BOOST_CONTAINER_MUTEX_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
//#define BOOST_CONTAINER_NO_MT
|
||||
//#define BOOST_CONTAINER_NO_SPINLOCKS
|
||||
|
||||
#include <boost/container/detail/config_begin.hpp>
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
|
||||
// Extremely Light-Weight wrapper classes for OS thread synchronization
|
||||
|
||||
#define BOOST_MUTEX_HELPER_NONE 0
|
||||
#define BOOST_MUTEX_HELPER_WIN32 1
|
||||
#define BOOST_MUTEX_HELPER_PTHREAD 2
|
||||
#define BOOST_MUTEX_HELPER_SPINLOCKS 3
|
||||
|
||||
#if !defined(BOOST_HAS_THREADS) && !defined(BOOST_NO_MT)
|
||||
# define BOOST_NO_MT
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_NO_MT) || defined(BOOST_CONTAINER_NO_MT)
|
||||
// No multithreading -> make locks into no-ops
|
||||
#define BOOST_MUTEX_HELPER BOOST_MUTEX_HELPER_NONE
|
||||
#else
|
||||
//Taken from dlmalloc
|
||||
#if !defined(BOOST_CONTAINER_NO_SPINLOCKS) && \
|
||||
((defined(__GNUC__) && \
|
||||
((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) || \
|
||||
defined(__i386__) || defined(__x86_64__))) || \
|
||||
(defined(_MSC_VER) && _MSC_VER>=1310))
|
||||
#define BOOST_MUTEX_HELPER BOOST_MUTEX_HELPER_SPINLOCKS
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_WINDOWS)
|
||||
#include <windows.h>
|
||||
#ifndef BOOST_MUTEX_HELPER
|
||||
#define BOOST_MUTEX_HELPER BOOST_MUTEX_HELPER_WIN32
|
||||
#endif
|
||||
#elif defined(BOOST_HAS_UNISTD_H)
|
||||
#include <unistd.h>
|
||||
#if !defined(BOOST_MUTEX_HELPER) && (defined(_POSIX_THREADS) || defined(BOOST_HAS_PTHREADS))
|
||||
#define BOOST_MUTEX_HELPER BOOST_MUTEX_HELPER_PTHREAD
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_MUTEX_HELPER
|
||||
#error Unable to determine platform mutex type; #define BOOST_NO_MT to assume single-threaded
|
||||
#endif
|
||||
|
||||
#if BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_NONE
|
||||
//...
|
||||
#elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_SPINLOCKS
|
||||
#if defined(_MSC_VER)
|
||||
#ifndef _M_AMD64
|
||||
/* These are already defined on AMD64 builds */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
long __cdecl _InterlockedCompareExchange(long volatile *Dest, long Exchange, long Comp);
|
||||
long __cdecl _InterlockedExchange(long volatile *Target, long Value);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif /* _M_AMD64 */
|
||||
#pragma intrinsic (_InterlockedCompareExchange)
|
||||
#pragma intrinsic (_InterlockedExchange)
|
||||
#define interlockedcompareexchange _InterlockedCompareExchange
|
||||
#define interlockedexchange _InterlockedExchange
|
||||
#elif defined(WIN32) && defined(__GNUC__)
|
||||
#define interlockedcompareexchange(a, b, c) __sync_val_compare_and_swap(a, c, b)
|
||||
#define interlockedexchange __sync_lock_test_and_set
|
||||
#endif /* Win32 */
|
||||
|
||||
/* First, define CAS_LOCK and CLEAR_LOCK on ints */
|
||||
/* Note CAS_LOCK defined to return 0 on success */
|
||||
|
||||
#if defined(__GNUC__)&& (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1))
|
||||
#define BOOST_CONTAINER_CAS_LOCK(sl) __sync_lock_test_and_set(sl, 1)
|
||||
#define BOOST_CONTAINER_CLEAR_LOCK(sl) __sync_lock_release(sl)
|
||||
|
||||
#elif (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)))
|
||||
/* Custom spin locks for older gcc on x86 */
|
||||
static inline int boost_container_x86_cas_lock(int *sl) {
|
||||
int ret;
|
||||
int val = 1;
|
||||
int cmp = 0;
|
||||
__asm__ __volatile__ ("lock; cmpxchgl %1, %2"
|
||||
: "=a" (ret)
|
||||
: "r" (val), "m" (*(sl)), "0"(cmp)
|
||||
: "memory", "cc");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void boost_container_x86_clear_lock(int* sl) {
|
||||
assert(*sl != 0);
|
||||
int prev = 0;
|
||||
int ret;
|
||||
__asm__ __volatile__ ("lock; xchgl %0, %1"
|
||||
: "=r" (ret)
|
||||
: "m" (*(sl)), "0"(prev)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
#define BOOST_CONTAINER_CAS_LOCK(sl) boost_container_x86_cas_lock(sl)
|
||||
#define BOOST_CONTAINER_CLEAR_LOCK(sl) boost_container_x86_clear_lock(sl)
|
||||
|
||||
#else /* Win32 MSC */
|
||||
#define BOOST_CONTAINER_CAS_LOCK(sl) interlockedexchange((long volatile*)sl, (long)1)
|
||||
#define BOOST_CONTAINER_CLEAR_LOCK(sl) interlockedexchange((long volatile*)sl, (long)0)
|
||||
#endif
|
||||
|
||||
/* How to yield for a spin lock */
|
||||
#define SPINS_PER_YIELD 63
|
||||
#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
|
||||
#define SLEEP_EX_DURATION 50 /* delay for yield/sleep */
|
||||
#define SPIN_LOCK_YIELD SleepEx(SLEEP_EX_DURATION, FALSE)
|
||||
#elif defined (__SVR4) && defined (__sun) /* solaris */
|
||||
#include <thread.h>
|
||||
#define SPIN_LOCK_YIELD thr_yield();
|
||||
#elif !defined(LACKS_SCHED_H)
|
||||
#include <sched.h>
|
||||
#define SPIN_LOCK_YIELD sched_yield();
|
||||
#else
|
||||
#define SPIN_LOCK_YIELD
|
||||
#endif /* ... yield ... */
|
||||
|
||||
#define BOOST_CONTAINER_SPINS_PER_YIELD 63
|
||||
inline int boost_interprocess_spin_acquire_lock(int *sl) {
|
||||
int spins = 0;
|
||||
while (*(volatile int *)sl != 0 ||
|
||||
BOOST_CONTAINER_CAS_LOCK(sl)) {
|
||||
if ((++spins & BOOST_CONTAINER_SPINS_PER_YIELD) == 0) {
|
||||
SPIN_LOCK_YIELD;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#define BOOST_CONTAINER_MLOCK_T int
|
||||
#define BOOST_CONTAINER_TRY_LOCK(sl) !BOOST_CONTAINER_CAS_LOCK(sl)
|
||||
#define BOOST_CONTAINER_RELEASE_LOCK(sl) BOOST_CONTAINER_CLEAR_LOCK(sl)
|
||||
#define BOOST_CONTAINER_ACQUIRE_LOCK(sl) (BOOST_CONTAINER_CAS_LOCK(sl)? boost_interprocess_spin_acquire_lock(sl) : 0)
|
||||
#define BOOST_MOVE_INITIAL_LOCK(sl) (*sl = 0)
|
||||
#define BOOST_CONTAINER_DESTROY_LOCK(sl) (0)
|
||||
#elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_WIN32
|
||||
//
|
||||
#elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_PTHREAD
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace container_detail {
|
||||
|
||||
#if BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_NONE
|
||||
class null_mutex
|
||||
{
|
||||
private:
|
||||
null_mutex(const null_mutex &);
|
||||
void operator=(const null_mutex &);
|
||||
|
||||
public:
|
||||
null_mutex() { }
|
||||
|
||||
static void lock() { }
|
||||
static void unlock() { }
|
||||
};
|
||||
|
||||
typedef null_mutex default_mutex;
|
||||
#elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_SPINLOCKS
|
||||
|
||||
class spin_mutex
|
||||
{
|
||||
private:
|
||||
BOOST_CONTAINER_MLOCK_T sl;
|
||||
spin_mutex(const spin_mutex &);
|
||||
void operator=(const spin_mutex &);
|
||||
|
||||
public:
|
||||
spin_mutex() { BOOST_MOVE_INITIAL_LOCK(&sl); }
|
||||
|
||||
void lock() { BOOST_CONTAINER_ACQUIRE_LOCK(&sl); }
|
||||
void unlock() { BOOST_CONTAINER_RELEASE_LOCK(&sl); }
|
||||
};
|
||||
typedef spin_mutex default_mutex;
|
||||
#elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_WIN32
|
||||
class mutex
|
||||
{
|
||||
private:
|
||||
CRITICAL_SECTION mtx;
|
||||
|
||||
mutex(const mutex &);
|
||||
void operator=(const mutex &);
|
||||
|
||||
public:
|
||||
mutex()
|
||||
{ InitializeCriticalSection(&mtx); }
|
||||
|
||||
~mutex()
|
||||
{ DeleteCriticalSection(&mtx); }
|
||||
|
||||
void lock()
|
||||
{ EnterCriticalSection(&mtx); }
|
||||
|
||||
void unlock()
|
||||
{ LeaveCriticalSection(&mtx); }
|
||||
};
|
||||
|
||||
typedef mutex default_mutex;
|
||||
#elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_PTHREAD
|
||||
class mutex
|
||||
{
|
||||
private:
|
||||
pthread_mutex_t mtx;
|
||||
|
||||
mutex(const mutex &);
|
||||
void operator=(const mutex &);
|
||||
|
||||
public:
|
||||
mutex()
|
||||
{ pthread_mutex_init(&mtx, 0); }
|
||||
|
||||
~mutex()
|
||||
{ pthread_mutex_destroy(&mtx); }
|
||||
|
||||
void lock()
|
||||
{ pthread_mutex_lock(&mtx); }
|
||||
|
||||
void unlock()
|
||||
{ pthread_mutex_unlock(&mtx); }
|
||||
};
|
||||
|
||||
typedef mutex default_mutex;
|
||||
#endif
|
||||
|
||||
template<class Mutex>
|
||||
class scoped_lock
|
||||
{
|
||||
public:
|
||||
scoped_lock(Mutex &m)
|
||||
: m_(m)
|
||||
{ m_.lock(); }
|
||||
~scoped_lock()
|
||||
{ m_.unlock(); }
|
||||
|
||||
private:
|
||||
Mutex &m_;
|
||||
};
|
||||
|
||||
} // namespace container_detail
|
||||
} // namespace container
|
||||
} // namespace boost
|
||||
|
||||
#undef BOOST_MUTEX_HELPER_WIN32
|
||||
#undef BOOST_MUTEX_HELPER_PTHREAD
|
||||
#undef BOOST_MUTEX_HELPER_NONE
|
||||
#undef BOOST_MUTEX_HELPER
|
||||
#undef BOOST_MUTEX_HELPER_SPINLOCKS
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,75 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2014-2015. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#ifndef BOOST_CONTAINER_DETAIL_NEXT_CAPACITY_HPP
|
||||
#define BOOST_CONTAINER_DETAIL_NEXT_CAPACITY_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
// container
|
||||
#include <boost/container/throw_exception.hpp>
|
||||
// container/detail
|
||||
#include <boost/container/detail/min_max.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace container_detail {
|
||||
|
||||
enum NextCapacityOption { NextCapacityDouble, NextCapacity60Percent };
|
||||
|
||||
template<class SizeType, NextCapacityOption Option>
|
||||
struct next_capacity_calculator;
|
||||
|
||||
template<class SizeType>
|
||||
struct next_capacity_calculator<SizeType, NextCapacityDouble>
|
||||
{
|
||||
static SizeType get(const SizeType max_size
|
||||
,const SizeType capacity
|
||||
,const SizeType n)
|
||||
{
|
||||
const SizeType remaining = max_size - capacity;
|
||||
if ( remaining < n )
|
||||
boost::container::throw_length_error("get_next_capacity, allocator's max_size reached");
|
||||
const SizeType additional = max_value(n, capacity);
|
||||
return ( remaining < additional ) ? max_size : ( capacity + additional );
|
||||
}
|
||||
};
|
||||
|
||||
template<class SizeType>
|
||||
struct next_capacity_calculator<SizeType, NextCapacity60Percent>
|
||||
{
|
||||
static SizeType get(const SizeType max_size
|
||||
,const SizeType capacity
|
||||
,const SizeType n)
|
||||
{
|
||||
const SizeType remaining = max_size - capacity;
|
||||
if ( remaining < n )
|
||||
boost::container::throw_length_error("get_next_capacity, allocator's max_size reached");
|
||||
const SizeType m3 = max_size/3;
|
||||
|
||||
if (capacity < m3)
|
||||
return capacity + max_value(3*(capacity+1)/5, n);
|
||||
|
||||
if (capacity < m3*2)
|
||||
return capacity + max_value((capacity+1)/2, n);
|
||||
return max_size;
|
||||
}
|
||||
};
|
||||
|
||||
} //namespace container_detail {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DETAIL_NEXT_CAPACITY_HPP
|
||||
@@ -0,0 +1,419 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2013. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_DETAIL_NODE_ALLOC_HPP_
|
||||
#define BOOST_CONTAINER_DETAIL_NODE_ALLOC_HPP_
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/detail/config_begin.hpp>
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
|
||||
// container
|
||||
#include <boost/container/allocator_traits.hpp>
|
||||
// container/detail
|
||||
#include <boost/container/detail/addressof.hpp>
|
||||
#include <boost/container/detail/alloc_helpers.hpp>
|
||||
#include <boost/container/detail/allocator_version_traits.hpp>
|
||||
#include <boost/container/detail/construct_in_place.hpp>
|
||||
#include <boost/container/detail/destroyers.hpp>
|
||||
#include <boost/container/detail/iterator_to_raw_pointer.hpp>
|
||||
#include <boost/container/detail/mpl.hpp>
|
||||
#include <boost/container/detail/placement_new.hpp>
|
||||
#include <boost/container/detail/to_raw_pointer.hpp>
|
||||
#include <boost/container/detail/type_traits.hpp>
|
||||
#include <boost/container/detail/version_type.hpp>
|
||||
// intrusive
|
||||
#include <boost/intrusive/detail/mpl.hpp>
|
||||
#include <boost/intrusive/options.hpp>
|
||||
// move
|
||||
#include <boost/move/utility_core.hpp>
|
||||
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
#include <boost/move/detail/fwd_macros.hpp>
|
||||
#endif
|
||||
// other
|
||||
#include <boost/core/no_exceptions_support.hpp>
|
||||
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace container_detail {
|
||||
|
||||
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(value_compare)
|
||||
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(predicate_type)
|
||||
|
||||
template<class Allocator, class ICont>
|
||||
struct node_alloc_holder
|
||||
{
|
||||
//If the intrusive container is an associative container, obtain the predicate, which will
|
||||
//be of type node_compare<>. If not an associative container value_compare will be a "nat" type.
|
||||
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT
|
||||
( boost::container::container_detail::
|
||||
, ICont, value_compare, container_detail::nat) intrusive_value_compare;
|
||||
//In that case obtain the value predicate from the node predicate via predicate_type
|
||||
//if intrusive_value_compare is node_compare<>, nat otherwise
|
||||
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT
|
||||
( boost::container::container_detail::
|
||||
, intrusive_value_compare
|
||||
, predicate_type, container_detail::nat) value_compare;
|
||||
|
||||
typedef allocator_traits<Allocator> allocator_traits_type;
|
||||
typedef typename allocator_traits_type::value_type value_type;
|
||||
typedef ICont intrusive_container;
|
||||
typedef typename ICont::value_type Node;
|
||||
typedef typename allocator_traits_type::template
|
||||
portable_rebind_alloc<Node>::type NodeAlloc;
|
||||
typedef allocator_traits<NodeAlloc> node_allocator_traits_type;
|
||||
typedef container_detail::allocator_version_traits<NodeAlloc> node_allocator_version_traits_type;
|
||||
typedef Allocator ValAlloc;
|
||||
typedef typename node_allocator_traits_type::pointer NodePtr;
|
||||
typedef container_detail::scoped_deallocator<NodeAlloc> Deallocator;
|
||||
typedef typename node_allocator_traits_type::size_type size_type;
|
||||
typedef typename node_allocator_traits_type::difference_type difference_type;
|
||||
typedef container_detail::integral_constant<unsigned,
|
||||
boost::container::container_detail::
|
||||
version<NodeAlloc>::value> alloc_version;
|
||||
typedef typename ICont::iterator icont_iterator;
|
||||
typedef typename ICont::const_iterator icont_citerator;
|
||||
typedef allocator_destroyer<NodeAlloc> Destroyer;
|
||||
typedef allocator_traits<NodeAlloc> NodeAllocTraits;
|
||||
typedef allocator_version_traits<NodeAlloc> AllocVersionTraits;
|
||||
|
||||
private:
|
||||
BOOST_COPYABLE_AND_MOVABLE(node_alloc_holder)
|
||||
|
||||
public:
|
||||
|
||||
//Constructors for sequence containers
|
||||
node_alloc_holder()
|
||||
: members_()
|
||||
{}
|
||||
|
||||
explicit node_alloc_holder(const ValAlloc &a)
|
||||
: members_(a)
|
||||
{}
|
||||
|
||||
explicit node_alloc_holder(const node_alloc_holder &x)
|
||||
: members_(NodeAllocTraits::select_on_container_copy_construction(x.node_alloc()))
|
||||
{}
|
||||
|
||||
explicit node_alloc_holder(BOOST_RV_REF(node_alloc_holder) x)
|
||||
: members_(boost::move(x.node_alloc()))
|
||||
{ this->icont().swap(x.icont()); }
|
||||
|
||||
//Constructors for associative containers
|
||||
explicit node_alloc_holder(const value_compare &c, const ValAlloc &a)
|
||||
: members_(a, c)
|
||||
{}
|
||||
|
||||
explicit node_alloc_holder(const value_compare &c, const node_alloc_holder &x)
|
||||
: members_(NodeAllocTraits::select_on_container_copy_construction(x.node_alloc()), c)
|
||||
{}
|
||||
|
||||
explicit node_alloc_holder(const value_compare &c)
|
||||
: members_(c)
|
||||
{}
|
||||
|
||||
//helpers for move assignments
|
||||
explicit node_alloc_holder(BOOST_RV_REF(node_alloc_holder) x, const value_compare &c)
|
||||
: members_(boost::move(x.node_alloc()), c)
|
||||
{ this->icont().swap(x.icont()); }
|
||||
|
||||
void copy_assign_alloc(const node_alloc_holder &x)
|
||||
{
|
||||
container_detail::bool_<allocator_traits_type::propagate_on_container_copy_assignment::value> flag;
|
||||
container_detail::assign_alloc( static_cast<NodeAlloc &>(this->members_)
|
||||
, static_cast<const NodeAlloc &>(x.members_), flag);
|
||||
}
|
||||
|
||||
void move_assign_alloc( node_alloc_holder &x)
|
||||
{
|
||||
container_detail::bool_<allocator_traits_type::propagate_on_container_move_assignment::value> flag;
|
||||
container_detail::move_alloc( static_cast<NodeAlloc &>(this->members_)
|
||||
, static_cast<NodeAlloc &>(x.members_), flag);
|
||||
}
|
||||
|
||||
~node_alloc_holder()
|
||||
{ this->clear(alloc_version()); }
|
||||
|
||||
size_type max_size() const
|
||||
{ return allocator_traits_type::max_size(this->node_alloc()); }
|
||||
|
||||
NodePtr allocate_one()
|
||||
{ return AllocVersionTraits::allocate_one(this->node_alloc()); }
|
||||
|
||||
void deallocate_one(const NodePtr &p)
|
||||
{ AllocVersionTraits::deallocate_one(this->node_alloc(), p); }
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
template<class ...Args>
|
||||
NodePtr create_node(Args &&...args)
|
||||
{
|
||||
NodePtr p = this->allocate_one();
|
||||
Deallocator node_deallocator(p, this->node_alloc());
|
||||
allocator_traits<NodeAlloc>::construct
|
||||
( this->node_alloc()
|
||||
, container_detail::addressof(p->m_data), boost::forward<Args>(args)...);
|
||||
node_deallocator.release();
|
||||
//This does not throw
|
||||
typedef typename Node::hook_type hook_type;
|
||||
::new(static_cast<hook_type*>(container_detail::to_raw_pointer(p)), boost_container_new_t()) hook_type;
|
||||
return (p);
|
||||
}
|
||||
|
||||
#else //defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
#define BOOST_CONTAINER_NODE_ALLOC_HOLDER_CONSTRUCT_IMPL(N) \
|
||||
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
|
||||
NodePtr create_node(BOOST_MOVE_UREF##N)\
|
||||
{\
|
||||
NodePtr p = this->allocate_one();\
|
||||
Deallocator node_deallocator(p, this->node_alloc());\
|
||||
allocator_traits<NodeAlloc>::construct\
|
||||
( this->node_alloc()\
|
||||
, container_detail::addressof(p->m_data)\
|
||||
BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
|
||||
node_deallocator.release();\
|
||||
typedef typename Node::hook_type hook_type;\
|
||||
::new(static_cast<hook_type*>(container_detail::to_raw_pointer(p)), boost_container_new_t()) hook_type;\
|
||||
return (p);\
|
||||
}\
|
||||
//
|
||||
BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_NODE_ALLOC_HOLDER_CONSTRUCT_IMPL)
|
||||
#undef BOOST_CONTAINER_NODE_ALLOC_HOLDER_CONSTRUCT_IMPL
|
||||
|
||||
#endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
template<class It>
|
||||
NodePtr create_node_from_it(const It &it)
|
||||
{
|
||||
NodePtr p = this->allocate_one();
|
||||
Deallocator node_deallocator(p, this->node_alloc());
|
||||
::boost::container::construct_in_place(this->node_alloc(), container_detail::addressof(p->m_data), it);
|
||||
node_deallocator.release();
|
||||
//This does not throw
|
||||
typedef typename Node::hook_type hook_type;
|
||||
::new(static_cast<hook_type*>(container_detail::to_raw_pointer(p)), boost_container_new_t()) hook_type;
|
||||
return (p);
|
||||
}
|
||||
|
||||
template<class KeyConvertible>
|
||||
NodePtr create_node_from_key(BOOST_FWD_REF(KeyConvertible) key)
|
||||
{
|
||||
NodePtr p = this->allocate_one();
|
||||
NodeAlloc &na = this->node_alloc();
|
||||
Deallocator node_deallocator(p, this->node_alloc());
|
||||
node_allocator_traits_type::construct
|
||||
(na, container_detail::addressof(p->m_data.first), boost::forward<KeyConvertible>(key));
|
||||
BOOST_TRY{
|
||||
node_allocator_traits_type::construct(na, container_detail::addressof(p->m_data.second));
|
||||
}
|
||||
BOOST_CATCH(...){
|
||||
node_allocator_traits_type::destroy(na, container_detail::addressof(p->m_data.first));
|
||||
BOOST_RETHROW;
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
node_deallocator.release();
|
||||
//This does not throw
|
||||
typedef typename Node::hook_type hook_type;
|
||||
::new(static_cast<hook_type*>(container_detail::to_raw_pointer(p)), boost_container_new_t()) hook_type;
|
||||
return (p);
|
||||
}
|
||||
|
||||
void destroy_node(const NodePtr &nodep)
|
||||
{
|
||||
allocator_traits<NodeAlloc>::destroy(this->node_alloc(), container_detail::to_raw_pointer(nodep));
|
||||
this->deallocate_one(nodep);
|
||||
}
|
||||
|
||||
void swap(node_alloc_holder &x)
|
||||
{
|
||||
this->icont().swap(x.icont());
|
||||
container_detail::bool_<allocator_traits_type::propagate_on_container_swap::value> flag;
|
||||
container_detail::swap_alloc(this->node_alloc(), x.node_alloc(), flag);
|
||||
}
|
||||
|
||||
template<class FwdIterator, class Inserter>
|
||||
void allocate_many_and_construct
|
||||
(FwdIterator beg, difference_type n, Inserter inserter)
|
||||
{
|
||||
if(n){
|
||||
typedef typename node_allocator_version_traits_type::multiallocation_chain multiallocation_chain;
|
||||
|
||||
//Try to allocate memory in a single block
|
||||
typedef typename multiallocation_chain::iterator multialloc_iterator;
|
||||
multiallocation_chain mem;
|
||||
NodeAlloc &nalloc = this->node_alloc();
|
||||
node_allocator_version_traits_type::allocate_individual(nalloc, n, mem);
|
||||
multialloc_iterator itbeg(mem.begin()), itlast(mem.last());
|
||||
mem.clear();
|
||||
Node *p = 0;
|
||||
BOOST_TRY{
|
||||
Deallocator node_deallocator(NodePtr(), nalloc);
|
||||
container_detail::scoped_destructor<NodeAlloc> sdestructor(nalloc, 0);
|
||||
while(n--){
|
||||
p = container_detail::iterator_to_raw_pointer(itbeg);
|
||||
node_deallocator.set(p);
|
||||
++itbeg;
|
||||
//This can throw
|
||||
boost::container::construct_in_place(nalloc, container_detail::addressof(p->m_data), beg);
|
||||
sdestructor.set(p);
|
||||
++beg;
|
||||
//This does not throw
|
||||
typedef typename Node::hook_type hook_type;
|
||||
::new(static_cast<hook_type*>(p), boost_container_new_t()) hook_type;
|
||||
//This can throw in some containers (predicate might throw).
|
||||
//(sdestructor will destruct the node and node_deallocator will deallocate it in case of exception)
|
||||
inserter(*p);
|
||||
sdestructor.set(0);
|
||||
}
|
||||
sdestructor.release();
|
||||
node_deallocator.release();
|
||||
}
|
||||
BOOST_CATCH(...){
|
||||
mem.incorporate_after(mem.last(), &*itbeg, &*itlast, n);
|
||||
node_allocator_version_traits_type::deallocate_individual(this->node_alloc(), mem);
|
||||
BOOST_RETHROW
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
}
|
||||
}
|
||||
|
||||
void clear(version_1)
|
||||
{ this->icont().clear_and_dispose(Destroyer(this->node_alloc())); }
|
||||
|
||||
void clear(version_2)
|
||||
{
|
||||
typename NodeAlloc::multiallocation_chain chain;
|
||||
allocator_destroyer_and_chain_builder<NodeAlloc> builder(this->node_alloc(), chain);
|
||||
this->icont().clear_and_dispose(builder);
|
||||
//BOOST_STATIC_ASSERT((::boost::has_move_emulation_enabled<typename NodeAlloc::multiallocation_chain>::value == true));
|
||||
if(!chain.empty())
|
||||
this->node_alloc().deallocate_individual(chain);
|
||||
}
|
||||
|
||||
icont_iterator erase_range(const icont_iterator &first, const icont_iterator &last, version_1)
|
||||
{ return this->icont().erase_and_dispose(first, last, Destroyer(this->node_alloc())); }
|
||||
|
||||
icont_iterator erase_range(const icont_iterator &first, const icont_iterator &last, version_2)
|
||||
{
|
||||
typedef typename NodeAlloc::multiallocation_chain multiallocation_chain;
|
||||
NodeAlloc & nalloc = this->node_alloc();
|
||||
multiallocation_chain chain;
|
||||
allocator_destroyer_and_chain_builder<NodeAlloc> chain_builder(nalloc, chain);
|
||||
icont_iterator ret_it = this->icont().erase_and_dispose(first, last, chain_builder);
|
||||
nalloc.deallocate_individual(chain);
|
||||
return ret_it;
|
||||
}
|
||||
|
||||
template<class Key, class Comparator>
|
||||
size_type erase_key(const Key& k, const Comparator &comp, version_1)
|
||||
{ return this->icont().erase_and_dispose(k, comp, Destroyer(this->node_alloc())); }
|
||||
|
||||
template<class Key, class Comparator>
|
||||
size_type erase_key(const Key& k, const Comparator &comp, version_2)
|
||||
{
|
||||
allocator_multialloc_chain_node_deallocator<NodeAlloc> chain_holder(this->node_alloc());
|
||||
return this->icont().erase_and_dispose(k, comp, chain_holder.get_chain_builder());
|
||||
}
|
||||
|
||||
protected:
|
||||
struct cloner
|
||||
{
|
||||
explicit cloner(node_alloc_holder &holder)
|
||||
: m_holder(holder)
|
||||
{}
|
||||
|
||||
NodePtr operator()(const Node &other) const
|
||||
{ return m_holder.create_node(other.m_data); }
|
||||
|
||||
node_alloc_holder &m_holder;
|
||||
};
|
||||
|
||||
struct move_cloner
|
||||
{
|
||||
move_cloner(node_alloc_holder &holder)
|
||||
: m_holder(holder)
|
||||
{}
|
||||
|
||||
NodePtr operator()(Node &other)
|
||||
{ //Use m_data instead of get_data to allow moving const key in [multi]map
|
||||
return m_holder.create_node(::boost::move(other.m_data));
|
||||
}
|
||||
|
||||
node_alloc_holder &m_holder;
|
||||
};
|
||||
|
||||
struct members_holder
|
||||
: public NodeAlloc
|
||||
{
|
||||
private:
|
||||
members_holder(const members_holder&);
|
||||
members_holder & operator=(const members_holder&);
|
||||
|
||||
public:
|
||||
members_holder()
|
||||
: NodeAlloc(), m_icont()
|
||||
{}
|
||||
|
||||
template<class ConvertibleToAlloc>
|
||||
explicit members_holder(BOOST_FWD_REF(ConvertibleToAlloc) c2alloc)
|
||||
: NodeAlloc(boost::forward<ConvertibleToAlloc>(c2alloc))
|
||||
, m_icont()
|
||||
{}
|
||||
|
||||
template<class ConvertibleToAlloc>
|
||||
members_holder(BOOST_FWD_REF(ConvertibleToAlloc) c2alloc, const value_compare &c)
|
||||
: NodeAlloc(boost::forward<ConvertibleToAlloc>(c2alloc))
|
||||
, m_icont(typename ICont::key_compare(c))
|
||||
{}
|
||||
|
||||
explicit members_holder(const value_compare &c)
|
||||
: NodeAlloc()
|
||||
, m_icont(typename ICont::key_compare(c))
|
||||
{}
|
||||
|
||||
//The intrusive container
|
||||
ICont m_icont;
|
||||
};
|
||||
|
||||
ICont &non_const_icont() const
|
||||
{ return const_cast<ICont&>(this->members_.m_icont); }
|
||||
|
||||
NodeAlloc &node_alloc()
|
||||
{ return static_cast<NodeAlloc &>(this->members_); }
|
||||
|
||||
const NodeAlloc &node_alloc() const
|
||||
{ return static_cast<const NodeAlloc &>(this->members_); }
|
||||
|
||||
members_holder members_;
|
||||
|
||||
public:
|
||||
ICont &icont()
|
||||
{ return this->members_.m_icont; }
|
||||
|
||||
const ICont &icont() const
|
||||
{ return this->members_.m_icont; }
|
||||
};
|
||||
|
||||
} //namespace container_detail {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif // BOOST_CONTAINER_DETAIL_NODE_ALLOC_HPP_
|
||||
@@ -0,0 +1,157 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2013. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_DETAIL_NODE_POOL_HPP
|
||||
#define BOOST_CONTAINER_DETAIL_NODE_POOL_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/detail/config_begin.hpp>
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
|
||||
#include <boost/container/detail/mutex.hpp>
|
||||
#include <boost/container/detail/pool_common_alloc.hpp>
|
||||
#include <boost/container/detail/node_pool_impl.hpp>
|
||||
#include <boost/container/detail/mutex.hpp>
|
||||
#include <boost/move/utility_core.hpp>
|
||||
#include <cstddef>
|
||||
#include <cassert>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace container_detail {
|
||||
|
||||
//!Pooled memory allocator using single segregated storage. Includes
|
||||
//!a reference count but the class does not delete itself, this is
|
||||
//!responsibility of user classes. Node size (NodeSize) and the number of
|
||||
//!nodes allocated per block (NodesPerBlock) are known at compile time
|
||||
template< std::size_t NodeSize, std::size_t NodesPerBlock >
|
||||
class private_node_pool
|
||||
//Inherit from the implementation to avoid template bloat
|
||||
: public boost::container::container_detail::
|
||||
private_node_pool_impl<fake_segment_manager>
|
||||
{
|
||||
typedef boost::container::container_detail::
|
||||
private_node_pool_impl<fake_segment_manager> base_t;
|
||||
//Non-copyable
|
||||
private_node_pool(const private_node_pool &);
|
||||
private_node_pool &operator=(const private_node_pool &);
|
||||
|
||||
public:
|
||||
typedef typename base_t::multiallocation_chain multiallocation_chain;
|
||||
static const std::size_t nodes_per_block = NodesPerBlock;
|
||||
|
||||
//!Constructor from a segment manager. Never throws
|
||||
private_node_pool()
|
||||
: base_t(0, NodeSize, NodesPerBlock)
|
||||
{}
|
||||
|
||||
};
|
||||
|
||||
template< std::size_t NodeSize
|
||||
, std::size_t NodesPerBlock
|
||||
>
|
||||
class shared_node_pool
|
||||
: public private_node_pool<NodeSize, NodesPerBlock>
|
||||
{
|
||||
private:
|
||||
typedef private_node_pool<NodeSize, NodesPerBlock> private_node_allocator_t;
|
||||
|
||||
public:
|
||||
typedef typename private_node_allocator_t::free_nodes_t free_nodes_t;
|
||||
typedef typename private_node_allocator_t::multiallocation_chain multiallocation_chain;
|
||||
|
||||
//!Constructor from a segment manager. Never throws
|
||||
shared_node_pool()
|
||||
: private_node_allocator_t(){}
|
||||
|
||||
//!Destructor. Deallocates all allocated blocks. Never throws
|
||||
~shared_node_pool()
|
||||
{}
|
||||
|
||||
//!Allocates array of count elements. Can throw std::bad_alloc
|
||||
void *allocate_node()
|
||||
{
|
||||
//-----------------------
|
||||
scoped_lock<default_mutex> guard(mutex_);
|
||||
//-----------------------
|
||||
return private_node_allocator_t::allocate_node();
|
||||
}
|
||||
|
||||
//!Deallocates an array pointed by ptr. Never throws
|
||||
void deallocate_node(void *ptr)
|
||||
{
|
||||
//-----------------------
|
||||
scoped_lock<default_mutex> guard(mutex_);
|
||||
//-----------------------
|
||||
private_node_allocator_t::deallocate_node(ptr);
|
||||
}
|
||||
|
||||
//!Allocates a singly linked list of n nodes ending in null pointer.
|
||||
//!can throw std::bad_alloc
|
||||
void allocate_nodes(const std::size_t n, multiallocation_chain &chain)
|
||||
{
|
||||
//-----------------------
|
||||
scoped_lock<default_mutex> guard(mutex_);
|
||||
//-----------------------
|
||||
return private_node_allocator_t::allocate_nodes(n, chain);
|
||||
}
|
||||
|
||||
void deallocate_nodes(multiallocation_chain &chain)
|
||||
{
|
||||
//-----------------------
|
||||
scoped_lock<default_mutex> guard(mutex_);
|
||||
//-----------------------
|
||||
private_node_allocator_t::deallocate_nodes(chain);
|
||||
}
|
||||
|
||||
//!Deallocates all the free blocks of memory. Never throws
|
||||
void deallocate_free_blocks()
|
||||
{
|
||||
//-----------------------
|
||||
scoped_lock<default_mutex> guard(mutex_);
|
||||
//-----------------------
|
||||
private_node_allocator_t::deallocate_free_blocks();
|
||||
}
|
||||
|
||||
//!Deallocates all blocks. Never throws
|
||||
void purge_blocks()
|
||||
{
|
||||
//-----------------------
|
||||
scoped_lock<default_mutex> guard(mutex_);
|
||||
//-----------------------
|
||||
private_node_allocator_t::purge_blocks();
|
||||
}
|
||||
|
||||
std::size_t num_free_nodes()
|
||||
{
|
||||
//-----------------------
|
||||
scoped_lock<default_mutex> guard(mutex_);
|
||||
//-----------------------
|
||||
return private_node_allocator_t::num_free_nodes();
|
||||
}
|
||||
|
||||
private:
|
||||
default_mutex mutex_;
|
||||
};
|
||||
|
||||
} //namespace container_detail {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DETAIL_NODE_POOL_HPP
|
||||
@@ -0,0 +1,375 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2013. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#ifndef BOOST_CONTAINER_DETAIL_NODE_POOL_IMPL_HPP
|
||||
#define BOOST_CONTAINER_DETAIL_NODE_POOL_IMPL_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/detail/config_begin.hpp>
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
#include <boost/container/container_fwd.hpp>
|
||||
|
||||
#include <boost/container/detail/math_functions.hpp>
|
||||
#include <boost/container/detail/mpl.hpp>
|
||||
#include <boost/container/detail/pool_common.hpp>
|
||||
#include <boost/container/detail/to_raw_pointer.hpp>
|
||||
#include <boost/container/detail/type_traits.hpp>
|
||||
|
||||
#include <boost/intrusive/pointer_traits.hpp>
|
||||
#include <boost/intrusive/set.hpp>
|
||||
#include <boost/intrusive/slist.hpp>
|
||||
|
||||
#include <boost/core/no_exceptions_support.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <cstddef>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace container_detail {
|
||||
|
||||
template<class SegmentManagerBase>
|
||||
class private_node_pool_impl
|
||||
{
|
||||
//Non-copyable
|
||||
private_node_pool_impl();
|
||||
private_node_pool_impl(const private_node_pool_impl &);
|
||||
private_node_pool_impl &operator=(const private_node_pool_impl &);
|
||||
|
||||
//A node object will hold node_t when it's not allocated
|
||||
public:
|
||||
typedef typename SegmentManagerBase::void_pointer void_pointer;
|
||||
typedef typename node_slist<void_pointer>::slist_hook_t slist_hook_t;
|
||||
typedef typename node_slist<void_pointer>::node_t node_t;
|
||||
typedef typename node_slist<void_pointer>::node_slist_t free_nodes_t;
|
||||
typedef typename SegmentManagerBase::multiallocation_chain multiallocation_chain;
|
||||
typedef typename SegmentManagerBase::size_type size_type;
|
||||
|
||||
private:
|
||||
typedef typename bi::make_slist
|
||||
< node_t, bi::base_hook<slist_hook_t>
|
||||
, bi::linear<true>
|
||||
, bi::constant_time_size<false> >::type blockslist_t;
|
||||
|
||||
static size_type get_rounded_size(size_type orig_size, size_type round_to)
|
||||
{ return ((orig_size-1)/round_to+1)*round_to; }
|
||||
|
||||
public:
|
||||
|
||||
//!Segment manager typedef
|
||||
typedef SegmentManagerBase segment_manager_base_type;
|
||||
|
||||
//!Constructor from a segment manager. Never throws
|
||||
private_node_pool_impl(segment_manager_base_type *segment_mngr_base, size_type node_size, size_type nodes_per_block)
|
||||
: m_nodes_per_block(nodes_per_block)
|
||||
, m_real_node_size(lcm(node_size, size_type(alignment_of<node_t>::value)))
|
||||
//General purpose allocator
|
||||
, mp_segment_mngr_base(segment_mngr_base)
|
||||
, m_blocklist()
|
||||
, m_freelist()
|
||||
//Debug node count
|
||||
, m_allocated(0)
|
||||
{}
|
||||
|
||||
//!Destructor. Deallocates all allocated blocks. Never throws
|
||||
~private_node_pool_impl()
|
||||
{ this->purge_blocks(); }
|
||||
|
||||
size_type get_real_num_node() const
|
||||
{ return m_nodes_per_block; }
|
||||
|
||||
//!Returns the segment manager. Never throws
|
||||
segment_manager_base_type* get_segment_manager_base()const
|
||||
{ return container_detail::to_raw_pointer(mp_segment_mngr_base); }
|
||||
|
||||
void *allocate_node()
|
||||
{ return this->priv_alloc_node(); }
|
||||
|
||||
//!Deallocates an array pointed by ptr. Never throws
|
||||
void deallocate_node(void *ptr)
|
||||
{ this->priv_dealloc_node(ptr); }
|
||||
|
||||
//!Allocates a singly linked list of n nodes ending in null pointer.
|
||||
void allocate_nodes(const size_type n, multiallocation_chain &chain)
|
||||
{
|
||||
//Preallocate all needed blocks to fulfill the request
|
||||
size_type cur_nodes = m_freelist.size();
|
||||
if(cur_nodes < n){
|
||||
this->priv_alloc_block(((n - cur_nodes) - 1)/m_nodes_per_block + 1);
|
||||
}
|
||||
|
||||
//We just iterate the needed nodes to get the last we'll erase
|
||||
typedef typename free_nodes_t::iterator free_iterator;
|
||||
free_iterator before_last_new_it = m_freelist.before_begin();
|
||||
for(size_type j = 0; j != n; ++j){
|
||||
++before_last_new_it;
|
||||
}
|
||||
|
||||
//Cache the first node of the allocated range before erasing
|
||||
free_iterator first_node(m_freelist.begin());
|
||||
free_iterator last_node (before_last_new_it);
|
||||
|
||||
//Erase the range. Since we already have the distance, this is O(1)
|
||||
m_freelist.erase_after( m_freelist.before_begin()
|
||||
, ++free_iterator(before_last_new_it)
|
||||
, n);
|
||||
|
||||
//Now take the last erased node and just splice it in the end
|
||||
//of the intrusive list that will be traversed by the multialloc iterator.
|
||||
chain.incorporate_after(chain.before_begin(), &*first_node, &*last_node, n);
|
||||
m_allocated += n;
|
||||
}
|
||||
|
||||
void deallocate_nodes(multiallocation_chain &chain)
|
||||
{
|
||||
typedef typename multiallocation_chain::iterator iterator;
|
||||
iterator it(chain.begin()), itend(chain.end());
|
||||
while(it != itend){
|
||||
void *pElem = &*it;
|
||||
++it;
|
||||
this->priv_dealloc_node(pElem);
|
||||
}
|
||||
}
|
||||
|
||||
//!Deallocates all the free blocks of memory. Never throws
|
||||
void deallocate_free_blocks()
|
||||
{
|
||||
typedef typename free_nodes_t::iterator nodelist_iterator;
|
||||
typename blockslist_t::iterator bit(m_blocklist.before_begin()),
|
||||
it(m_blocklist.begin()),
|
||||
itend(m_blocklist.end());
|
||||
free_nodes_t backup_list;
|
||||
nodelist_iterator backup_list_last = backup_list.before_begin();
|
||||
|
||||
//Execute the algorithm and get an iterator to the last value
|
||||
size_type blocksize = (get_rounded_size)
|
||||
(m_real_node_size*m_nodes_per_block, (size_type) alignment_of<node_t>::value);
|
||||
|
||||
while(it != itend){
|
||||
//Collect all the nodes from the block pointed by it
|
||||
//and push them in the list
|
||||
free_nodes_t free_nodes;
|
||||
nodelist_iterator last_it = free_nodes.before_begin();
|
||||
const void *addr = get_block_from_hook(&*it, blocksize);
|
||||
|
||||
m_freelist.remove_and_dispose_if
|
||||
(is_between(addr, blocksize), push_in_list(free_nodes, last_it));
|
||||
|
||||
//If the number of nodes is equal to m_nodes_per_block
|
||||
//this means that the block can be deallocated
|
||||
if(free_nodes.size() == m_nodes_per_block){
|
||||
//Unlink the nodes
|
||||
free_nodes.clear();
|
||||
it = m_blocklist.erase_after(bit);
|
||||
mp_segment_mngr_base->deallocate((void*)addr);
|
||||
}
|
||||
//Otherwise, insert them in the backup list, since the
|
||||
//next "remove_if" does not need to check them again.
|
||||
else{
|
||||
//Assign the iterator to the last value if necessary
|
||||
if(backup_list.empty() && !m_freelist.empty()){
|
||||
backup_list_last = last_it;
|
||||
}
|
||||
//Transfer nodes. This is constant time.
|
||||
backup_list.splice_after
|
||||
( backup_list.before_begin()
|
||||
, free_nodes
|
||||
, free_nodes.before_begin()
|
||||
, last_it
|
||||
, free_nodes.size());
|
||||
bit = it;
|
||||
++it;
|
||||
}
|
||||
}
|
||||
//We should have removed all the nodes from the free list
|
||||
BOOST_ASSERT(m_freelist.empty());
|
||||
|
||||
//Now pass all the node to the free list again
|
||||
m_freelist.splice_after
|
||||
( m_freelist.before_begin()
|
||||
, backup_list
|
||||
, backup_list.before_begin()
|
||||
, backup_list_last
|
||||
, backup_list.size());
|
||||
}
|
||||
|
||||
size_type num_free_nodes()
|
||||
{ return m_freelist.size(); }
|
||||
|
||||
//!Deallocates all used memory. Precondition: all nodes allocated from this pool should
|
||||
//!already be deallocated. Otherwise, undefined behaviour. Never throws
|
||||
void purge_blocks()
|
||||
{
|
||||
//check for memory leaks
|
||||
BOOST_ASSERT(m_allocated==0);
|
||||
size_type blocksize = (get_rounded_size)
|
||||
(m_real_node_size*m_nodes_per_block, (size_type)alignment_of<node_t>::value);
|
||||
|
||||
//We iterate though the NodeBlock list to free the memory
|
||||
while(!m_blocklist.empty()){
|
||||
void *addr = get_block_from_hook(&m_blocklist.front(), blocksize);
|
||||
m_blocklist.pop_front();
|
||||
mp_segment_mngr_base->deallocate((void*)addr);
|
||||
}
|
||||
//Just clear free node list
|
||||
m_freelist.clear();
|
||||
}
|
||||
|
||||
void swap(private_node_pool_impl &other)
|
||||
{
|
||||
BOOST_ASSERT(m_nodes_per_block == other.m_nodes_per_block);
|
||||
BOOST_ASSERT(m_real_node_size == other.m_real_node_size);
|
||||
std::swap(mp_segment_mngr_base, other.mp_segment_mngr_base);
|
||||
m_blocklist.swap(other.m_blocklist);
|
||||
m_freelist.swap(other.m_freelist);
|
||||
std::swap(m_allocated, other.m_allocated);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
struct push_in_list
|
||||
{
|
||||
push_in_list(free_nodes_t &l, typename free_nodes_t::iterator &it)
|
||||
: slist_(l), last_it_(it)
|
||||
{}
|
||||
|
||||
void operator()(typename free_nodes_t::pointer p) const
|
||||
{
|
||||
slist_.push_front(*p);
|
||||
if(slist_.size() == 1){ //Cache last element
|
||||
++last_it_ = slist_.begin();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
free_nodes_t &slist_;
|
||||
typename free_nodes_t::iterator &last_it_;
|
||||
};
|
||||
|
||||
struct is_between
|
||||
{
|
||||
typedef typename free_nodes_t::value_type argument_type;
|
||||
typedef bool result_type;
|
||||
|
||||
is_between(const void *addr, std::size_t size)
|
||||
: beg_(static_cast<const char *>(addr)), end_(beg_+size)
|
||||
{}
|
||||
|
||||
bool operator()(typename free_nodes_t::const_reference v) const
|
||||
{
|
||||
return (beg_ <= reinterpret_cast<const char *>(&v) &&
|
||||
end_ > reinterpret_cast<const char *>(&v));
|
||||
}
|
||||
private:
|
||||
const char * beg_;
|
||||
const char * end_;
|
||||
};
|
||||
|
||||
//!Allocates one node, using single segregated storage algorithm.
|
||||
//!Never throws
|
||||
node_t *priv_alloc_node()
|
||||
{
|
||||
//If there are no free nodes we allocate a new block
|
||||
if (m_freelist.empty())
|
||||
this->priv_alloc_block(1);
|
||||
//We take the first free node
|
||||
node_t *n = (node_t*)&m_freelist.front();
|
||||
m_freelist.pop_front();
|
||||
++m_allocated;
|
||||
return n;
|
||||
}
|
||||
|
||||
//!Deallocates one node, using single segregated storage algorithm.
|
||||
//!Never throws
|
||||
void priv_dealloc_node(void *pElem)
|
||||
{
|
||||
//We put the node at the beginning of the free node list
|
||||
node_t * to_deallocate = static_cast<node_t*>(pElem);
|
||||
m_freelist.push_front(*to_deallocate);
|
||||
BOOST_ASSERT(m_allocated>0);
|
||||
--m_allocated;
|
||||
}
|
||||
|
||||
//!Allocates several blocks of nodes. Can throw
|
||||
void priv_alloc_block(size_type num_blocks)
|
||||
{
|
||||
BOOST_ASSERT(num_blocks > 0);
|
||||
size_type blocksize =
|
||||
(get_rounded_size)(m_real_node_size*m_nodes_per_block, (size_type)alignment_of<node_t>::value);
|
||||
|
||||
BOOST_TRY{
|
||||
for(size_type i = 0; i != num_blocks; ++i){
|
||||
//We allocate a new NodeBlock and put it as first
|
||||
//element in the free Node list
|
||||
char *pNode = reinterpret_cast<char*>
|
||||
(mp_segment_mngr_base->allocate(blocksize + sizeof(node_t)));
|
||||
char *pBlock = pNode;
|
||||
m_blocklist.push_front(get_block_hook(pBlock, blocksize));
|
||||
|
||||
//We initialize all Nodes in Node Block to insert
|
||||
//them in the free Node list
|
||||
for(size_type j = 0; j < m_nodes_per_block; ++j, pNode += m_real_node_size){
|
||||
m_freelist.push_front(*new (pNode) node_t);
|
||||
}
|
||||
}
|
||||
}
|
||||
BOOST_CATCH(...){
|
||||
//to-do: if possible, an efficient way to deallocate allocated blocks
|
||||
BOOST_RETHROW
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
}
|
||||
|
||||
//!Deprecated, use deallocate_free_blocks
|
||||
void deallocate_free_chunks()
|
||||
{ this->deallocate_free_blocks(); }
|
||||
|
||||
//!Deprecated, use purge_blocks
|
||||
void purge_chunks()
|
||||
{ this->purge_blocks(); }
|
||||
|
||||
private:
|
||||
//!Returns a reference to the block hook placed in the end of the block
|
||||
static node_t & get_block_hook (void *block, size_type blocksize)
|
||||
{
|
||||
return *reinterpret_cast<node_t*>(reinterpret_cast<char*>(block) + blocksize);
|
||||
}
|
||||
|
||||
//!Returns the starting address of the block reference to the block hook placed in the end of the block
|
||||
void *get_block_from_hook (node_t *hook, size_type blocksize)
|
||||
{
|
||||
return (reinterpret_cast<char*>(hook) - blocksize);
|
||||
}
|
||||
|
||||
private:
|
||||
typedef typename boost::intrusive::pointer_traits
|
||||
<void_pointer>::template rebind_pointer<segment_manager_base_type>::type segment_mngr_base_ptr_t;
|
||||
|
||||
const size_type m_nodes_per_block;
|
||||
const size_type m_real_node_size;
|
||||
segment_mngr_base_ptr_t mp_segment_mngr_base; //Segment manager
|
||||
blockslist_t m_blocklist; //Intrusive container of blocks
|
||||
free_nodes_t m_freelist; //Intrusive container of free nods
|
||||
size_type m_allocated; //Used nodes for debugging
|
||||
};
|
||||
|
||||
|
||||
} //namespace container_detail {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DETAIL_ADAPTIVE_NODE_POOL_IMPL_HPP
|
||||
@@ -0,0 +1,506 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2013.
|
||||
//
|
||||
// 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_CONTAINER_DETAIL_PAIR_HPP
|
||||
#define BOOST_CONTAINER_CONTAINER_DETAIL_PAIR_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/detail/config_begin.hpp>
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
|
||||
#include <boost/container/detail/mpl.hpp>
|
||||
#include <boost/container/detail/type_traits.hpp>
|
||||
#include <boost/container/detail/mpl.hpp>
|
||||
#include <boost/container/detail/std_fwd.hpp>
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
# include <boost/container/detail/variadic_templates_tools.hpp>
|
||||
#endif
|
||||
#include <boost/move/adl_move_swap.hpp> //swap
|
||||
|
||||
#include <boost/intrusive/detail/minimal_pair_header.hpp> //pair
|
||||
#include <boost/move/utility_core.hpp>
|
||||
#include<boost/move/detail/fwd_macros.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace tuples {
|
||||
|
||||
struct null_type;
|
||||
|
||||
} //namespace tuples {
|
||||
} //namespace boost {
|
||||
|
||||
#if defined(BOOST_MSVC) && (_CPPLIB_VER == 520)
|
||||
//MSVC 2010 tuple marker
|
||||
namespace std { namespace tr1 { struct _Nil; }}
|
||||
#elif defined(BOOST_MSVC) && (_CPPLIB_VER == 540)
|
||||
//MSVC 2012 tuple marker
|
||||
namespace std { struct _Nil; }
|
||||
#endif
|
||||
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
template <int Dummy = 0>
|
||||
struct std_piecewise_construct_holder
|
||||
{
|
||||
static ::std::piecewise_construct_t *dummy;
|
||||
};
|
||||
|
||||
template <int Dummy>
|
||||
::std::piecewise_construct_t *std_piecewise_construct_holder<Dummy>::dummy =
|
||||
reinterpret_cast< ::std::piecewise_construct_t *>(0x01234); //Avoid sanitizer errors on references to null pointers
|
||||
|
||||
typedef const std::piecewise_construct_t & piecewise_construct_t;
|
||||
|
||||
struct try_emplace_t{};
|
||||
|
||||
#else
|
||||
|
||||
//! The piecewise_construct_t struct is an empty structure type used as a unique type to
|
||||
//! disambiguate used to disambiguate between different functions that take two tuple arguments.
|
||||
typedef unspecified piecewise_construct_t;
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
//! A instance of type
|
||||
//! piecewise_construct_t
|
||||
static piecewise_construct_t piecewise_construct = BOOST_CONTAINER_DOC1ST(unspecified, *std_piecewise_construct_holder<>::dummy);
|
||||
|
||||
///@cond
|
||||
|
||||
namespace container_detail {
|
||||
|
||||
struct piecewise_construct_use
|
||||
{
|
||||
//Avoid warnings of unused "piecewise_construct"
|
||||
piecewise_construct_use()
|
||||
{ (void)&::boost::container::piecewise_construct; }
|
||||
};
|
||||
|
||||
template <class T1, class T2>
|
||||
struct pair;
|
||||
|
||||
template <class T>
|
||||
struct is_pair
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template <class T1, class T2>
|
||||
struct is_pair< pair<T1, T2> >
|
||||
{
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
template <class T1, class T2>
|
||||
struct is_pair< std::pair<T1, T2> >
|
||||
{
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct is_not_pair
|
||||
{
|
||||
static const bool value = !is_pair<T>::value;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct is_std_pair
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template <class T1, class T2>
|
||||
struct is_std_pair< std::pair<T1, T2> >
|
||||
{
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
struct pair_nat;
|
||||
|
||||
template<typename T, typename U, typename V>
|
||||
void get(T); //to enable ADL
|
||||
|
||||
///@endcond
|
||||
|
||||
template <class T1, class T2>
|
||||
struct pair
|
||||
{
|
||||
private:
|
||||
BOOST_COPYABLE_AND_MOVABLE(pair)
|
||||
|
||||
public:
|
||||
typedef T1 first_type;
|
||||
typedef T2 second_type;
|
||||
|
||||
T1 first;
|
||||
T2 second;
|
||||
|
||||
//Default constructor
|
||||
pair()
|
||||
: first(), second()
|
||||
{}
|
||||
|
||||
//pair copy assignment
|
||||
pair(const pair& x)
|
||||
: first(x.first), second(x.second)
|
||||
{}
|
||||
|
||||
//pair move constructor
|
||||
pair(BOOST_RV_REF(pair) p)
|
||||
: first(::boost::move(p.first)), second(::boost::move(p.second))
|
||||
{}
|
||||
|
||||
template <class D, class S>
|
||||
pair(const pair<D, S> &p)
|
||||
: first(p.first), second(p.second)
|
||||
{}
|
||||
|
||||
template <class D, class S>
|
||||
pair(BOOST_RV_REF_BEG pair<D, S> BOOST_RV_REF_END p)
|
||||
: first(::boost::move(p.first)), second(::boost::move(p.second))
|
||||
{}
|
||||
|
||||
//pair from two values
|
||||
pair(const T1 &t1, const T2 &t2)
|
||||
: first(t1)
|
||||
, second(t2)
|
||||
{}
|
||||
|
||||
template<class U, class V>
|
||||
pair(BOOST_FWD_REF(U) u, BOOST_FWD_REF(V) v)
|
||||
: first(::boost::forward<U>(u))
|
||||
, second(::boost::forward<V>(v))
|
||||
{}
|
||||
|
||||
//And now compatibility with std::pair
|
||||
pair(const std::pair<T1, T2>& x)
|
||||
: first(x.first), second(x.second)
|
||||
{}
|
||||
|
||||
template <class D, class S>
|
||||
pair(const std::pair<D, S>& p)
|
||||
: first(p.first), second(p.second)
|
||||
{}
|
||||
|
||||
pair(BOOST_RV_REF_BEG std::pair<T1, T2> BOOST_RV_REF_END p)
|
||||
: first(::boost::move(p.first)), second(::boost::move(p.second))
|
||||
{}
|
||||
|
||||
template <class D, class S>
|
||||
pair(BOOST_RV_REF_BEG std::pair<D, S> BOOST_RV_REF_END p)
|
||||
: first(::boost::move(p.first)), second(::boost::move(p.second))
|
||||
{}
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
template< class KeyType, class ...Args>
|
||||
pair(try_emplace_t, BOOST_FWD_REF(KeyType) k, Args && ...args)
|
||||
: first(boost::forward<KeyType>(k)), second(::boost::forward<Args>(args)...)\
|
||||
{}
|
||||
#else
|
||||
|
||||
//piecewise construction from boost::tuple
|
||||
#define BOOST_PAIR_TRY_EMPLACE_CONSTRUCT_CODE(N)\
|
||||
template< class KeyType BOOST_MOVE_I##N BOOST_MOVE_CLASS##N > \
|
||||
pair( try_emplace_t, BOOST_FWD_REF(KeyType) k BOOST_MOVE_I##N BOOST_MOVE_UREF##N )\
|
||||
: first(boost::forward<KeyType>(k)), second(BOOST_MOVE_FWD##N)\
|
||||
{}\
|
||||
//
|
||||
BOOST_MOVE_ITERATE_0TO9(BOOST_PAIR_TRY_EMPLACE_CONSTRUCT_CODE)
|
||||
#undef BOOST_PAIR_TRY_EMPLACE_CONSTRUCT_CODE
|
||||
|
||||
#endif //BOOST_NO_CXX11_VARIADIC_TEMPLATES
|
||||
|
||||
//piecewise construction from boost::tuple
|
||||
#define BOOST_PAIR_PIECEWISE_CONSTRUCT_BOOST_TUPLE_CODE(N,M)\
|
||||
template< template<class, class, class, class, class, class, class, class, class, class> class BoostTuple \
|
||||
BOOST_MOVE_I_IF(BOOST_MOVE_OR(N,M)) BOOST_MOVE_CLASS##N BOOST_MOVE_I_IF(BOOST_MOVE_AND(N,M)) BOOST_MOVE_CLASSQ##M > \
|
||||
pair( piecewise_construct_t\
|
||||
, BoostTuple<BOOST_MOVE_TARG##N BOOST_MOVE_I##N BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(10,N),::boost::tuples::null_type)> p\
|
||||
, BoostTuple<BOOST_MOVE_TARGQ##M BOOST_MOVE_I##M BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(10,M),::boost::tuples::null_type)> q)\
|
||||
: first(BOOST_MOVE_TMPL_GET##N), second(BOOST_MOVE_TMPL_GETQ##M)\
|
||||
{ (void)p; (void)q; }\
|
||||
//
|
||||
BOOST_MOVE_ITER2D_0TOMAX(9, BOOST_PAIR_PIECEWISE_CONSTRUCT_BOOST_TUPLE_CODE)
|
||||
#undef BOOST_PAIR_PIECEWISE_CONSTRUCT_BOOST_TUPLE_CODE
|
||||
|
||||
//piecewise construction from variadic tuple (with delegating constructors)
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
# if !defined(BOOST_CONTAINER_NO_CXX11_DELEGATING_CONSTRUCTORS)
|
||||
private:
|
||||
template<template<class ...> class Tuple, class... Args1, class... Args2, size_t... Indexes1, size_t... Indexes2>
|
||||
pair(Tuple<Args1...>& t1, Tuple<Args2...>& t2, index_tuple<Indexes1...>, index_tuple<Indexes2...>)
|
||||
: first (::boost::forward<Args1>(get<Indexes1>(t1))...)
|
||||
, second(::boost::forward<Args2>(get<Indexes2>(t2))...)
|
||||
{ (void) t1; (void)t2; }
|
||||
|
||||
public:
|
||||
template<template<class ...> class Tuple, class... Args1, class... Args2>
|
||||
pair(piecewise_construct_t, Tuple<Args1...> t1, Tuple<Args2...> t2)
|
||||
: pair(t1, t2, typename build_number_seq<sizeof...(Args1)>::type(), typename build_number_seq<sizeof...(Args2)>::type())
|
||||
{}
|
||||
# else
|
||||
//piecewise construction from variadic tuple (suboptimal, without delegating constructors)
|
||||
private:
|
||||
template<typename T, template<class ...> class Tuple, typename... Args>
|
||||
static T build_from_args(Tuple<Args...>&& t)
|
||||
{ return do_build_from_args<T>(::boost::move(t), typename build_number_seq<sizeof...(Args)>::type()); }
|
||||
|
||||
template<typename T, template<class ...> class Tuple, typename... Args, std::size_t... Indexes>
|
||||
static T do_build_from_args(Tuple<Args...> && t, const index_tuple<Indexes...>&)
|
||||
{ (void)t; return T(::boost::forward<Args>(get<Indexes>(t))...); }
|
||||
|
||||
public:
|
||||
template<template<class ...> class Tuple, class... Args1, class... Args2>
|
||||
pair(piecewise_construct_t, Tuple<Args1...> t1, Tuple<Args2...> t2)
|
||||
: first (build_from_args<first_type> (::boost::move(t1)))
|
||||
, second (build_from_args<second_type>(::boost::move(t2)))
|
||||
{}
|
||||
# endif //BOOST_NO_CXX11_VARIADIC_TEMPLATES
|
||||
#elif defined(BOOST_MSVC) && (_CPPLIB_VER == 520)
|
||||
//MSVC 2010 tuple implementation
|
||||
#define BOOST_PAIR_PIECEWISE_CONSTRUCT_MSVC2010_TUPLE_CODE(N,M)\
|
||||
template< template<class, class, class, class, class, class, class, class, class, class> class StdTuple \
|
||||
BOOST_MOVE_I_IF(BOOST_MOVE_OR(N,M)) BOOST_MOVE_CLASS##N BOOST_MOVE_I_IF(BOOST_MOVE_AND(N,M)) BOOST_MOVE_CLASSQ##M > \
|
||||
pair( piecewise_construct_t\
|
||||
, StdTuple<BOOST_MOVE_TARG##N BOOST_MOVE_I##N BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(10,N),::std::tr1::_Nil)> p\
|
||||
, StdTuple<BOOST_MOVE_TARGQ##M BOOST_MOVE_I##M BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(10,M),::std::tr1::_Nil)> q)\
|
||||
: first(BOOST_MOVE_GET_IDX##N), second(BOOST_MOVE_GET_IDXQ##M)\
|
||||
{ (void)p; (void)q; }\
|
||||
//
|
||||
BOOST_MOVE_ITER2D_0TOMAX(9, BOOST_PAIR_PIECEWISE_CONSTRUCT_MSVC2010_TUPLE_CODE)
|
||||
#undef BOOST_PAIR_PIECEWISE_CONSTRUCT_MSVC2010_TUPLE_CODE
|
||||
#elif defined(BOOST_MSVC) && (_CPPLIB_VER == 540)
|
||||
#if _VARIADIC_MAX >= 9
|
||||
#define BOOST_PAIR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_MAX_IT 9
|
||||
#else
|
||||
#define BOOST_PAIR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_MAX_IT BOOST_MOVE_ADD(_VARIADIC_MAX, 1)
|
||||
#endif
|
||||
|
||||
//MSVC 2012 tuple implementation
|
||||
#define BOOST_PAIR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_CODE(N,M)\
|
||||
template< template<BOOST_MOVE_REPEAT(_VARIADIC_MAX, class), class, class, class> class StdTuple \
|
||||
BOOST_MOVE_I_IF(BOOST_MOVE_OR(N,M)) BOOST_MOVE_CLASS##N BOOST_MOVE_I_IF(BOOST_MOVE_AND(N,M)) BOOST_MOVE_CLASSQ##M > \
|
||||
pair( piecewise_construct_t\
|
||||
, StdTuple<BOOST_MOVE_TARG##N BOOST_MOVE_I##N BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(BOOST_MOVE_ADD(_VARIADIC_MAX, 3),N),::std::_Nil) > p\
|
||||
, StdTuple<BOOST_MOVE_TARGQ##M BOOST_MOVE_I##M BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(BOOST_MOVE_ADD(_VARIADIC_MAX, 3),M),::std::_Nil) > q)\
|
||||
: first(BOOST_MOVE_GET_IDX##N), second(BOOST_MOVE_GET_IDXQ##M)\
|
||||
{ (void)p; (void)q; }\
|
||||
//
|
||||
BOOST_MOVE_ITER2D_0TOMAX(BOOST_PAIR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_MAX_IT, BOOST_PAIR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_CODE)
|
||||
#undef BOOST_PAIR_PIECEWISE_CONSTRUCT_MSVC2010_TUPLE_CODE
|
||||
#undef BOOST_PAIR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_MAX_IT
|
||||
#endif
|
||||
|
||||
//pair copy assignment
|
||||
pair& operator=(BOOST_COPY_ASSIGN_REF(pair) p)
|
||||
{
|
||||
first = p.first;
|
||||
second = p.second;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//pair move assignment
|
||||
pair& operator=(BOOST_RV_REF(pair) p)
|
||||
{
|
||||
first = ::boost::move(p.first);
|
||||
second = ::boost::move(p.second);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class D, class S>
|
||||
typename ::boost::container::container_detail::disable_if_or
|
||||
< pair &
|
||||
, ::boost::container::container_detail::is_same<T1, D>
|
||||
, ::boost::container::container_detail::is_same<T2, S>
|
||||
>::type
|
||||
operator=(const pair<D, S>&p)
|
||||
{
|
||||
first = p.first;
|
||||
second = p.second;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class D, class S>
|
||||
typename ::boost::container::container_detail::disable_if_or
|
||||
< pair &
|
||||
, ::boost::container::container_detail::is_same<T1, D>
|
||||
, ::boost::container::container_detail::is_same<T2, S>
|
||||
>::type
|
||||
operator=(BOOST_RV_REF_BEG pair<D, S> BOOST_RV_REF_END p)
|
||||
{
|
||||
first = ::boost::move(p.first);
|
||||
second = ::boost::move(p.second);
|
||||
return *this;
|
||||
}
|
||||
//std::pair copy assignment
|
||||
pair& operator=(const std::pair<T1, T2> &p)
|
||||
{
|
||||
first = p.first;
|
||||
second = p.second;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class D, class S>
|
||||
pair& operator=(const std::pair<D, S> &p)
|
||||
{
|
||||
first = ::boost::move(p.first);
|
||||
second = ::boost::move(p.second);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//std::pair move assignment
|
||||
pair& operator=(BOOST_RV_REF_BEG std::pair<T1, T2> BOOST_RV_REF_END p)
|
||||
{
|
||||
first = ::boost::move(p.first);
|
||||
second = ::boost::move(p.second);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class D, class S>
|
||||
pair& operator=(BOOST_RV_REF_BEG std::pair<D, S> BOOST_RV_REF_END p)
|
||||
{
|
||||
first = ::boost::move(p.first);
|
||||
second = ::boost::move(p.second);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//swap
|
||||
void swap(pair& p)
|
||||
{
|
||||
::boost::adl_move_swap(this->first, p.first);
|
||||
::boost::adl_move_swap(this->second, p.second);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T1, class T2>
|
||||
inline bool operator==(const pair<T1,T2>& x, const pair<T1,T2>& y)
|
||||
{ return static_cast<bool>(x.first == y.first && x.second == y.second); }
|
||||
|
||||
template <class T1, class T2>
|
||||
inline bool operator< (const pair<T1,T2>& x, const pair<T1,T2>& y)
|
||||
{ return static_cast<bool>(x.first < y.first ||
|
||||
(!(y.first < x.first) && x.second < y.second)); }
|
||||
|
||||
template <class T1, class T2>
|
||||
inline bool operator!=(const pair<T1,T2>& x, const pair<T1,T2>& y)
|
||||
{ return static_cast<bool>(!(x == y)); }
|
||||
|
||||
template <class T1, class T2>
|
||||
inline bool operator> (const pair<T1,T2>& x, const pair<T1,T2>& y)
|
||||
{ return y < x; }
|
||||
|
||||
template <class T1, class T2>
|
||||
inline bool operator>=(const pair<T1,T2>& x, const pair<T1,T2>& y)
|
||||
{ return static_cast<bool>(!(x < y)); }
|
||||
|
||||
template <class T1, class T2>
|
||||
inline bool operator<=(const pair<T1,T2>& x, const pair<T1,T2>& y)
|
||||
{ return static_cast<bool>(!(y < x)); }
|
||||
|
||||
template <class T1, class T2>
|
||||
inline pair<T1, T2> make_pair(T1 x, T2 y)
|
||||
{ return pair<T1, T2>(x, y); }
|
||||
|
||||
template <class T1, class T2>
|
||||
inline void swap(pair<T1, T2>& x, pair<T1, T2>& y)
|
||||
{ x.swap(y); }
|
||||
|
||||
} //namespace container_detail {
|
||||
} //namespace container {
|
||||
|
||||
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
|
||||
template<class T1, class T2>
|
||||
struct has_move_emulation_enabled< ::boost::container::container_detail::pair<T1, T2> >
|
||||
{
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
namespace move_detail{
|
||||
|
||||
template<class T>
|
||||
struct is_class_or_union;
|
||||
|
||||
template <class T1, class T2>
|
||||
struct is_class_or_union< ::boost::container::container_detail::pair<T1, T2> >
|
||||
//This specialization is needed to avoid instantiation of pair in
|
||||
//is_class, and allow recursive maps.
|
||||
{
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
template <class T1, class T2>
|
||||
struct is_class_or_union< std::pair<T1, T2> >
|
||||
//This specialization is needed to avoid instantiation of pair in
|
||||
//is_class, and allow recursive maps.
|
||||
{
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct is_union;
|
||||
|
||||
template <class T1, class T2>
|
||||
struct is_union< ::boost::container::container_detail::pair<T1, T2> >
|
||||
//This specialization is needed to avoid instantiation of pair in
|
||||
//is_class, and allow recursive maps.
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template <class T1, class T2>
|
||||
struct is_union< std::pair<T1, T2> >
|
||||
//This specialization is needed to avoid instantiation of pair in
|
||||
//is_class, and allow recursive maps.
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct is_class;
|
||||
|
||||
template <class T1, class T2>
|
||||
struct is_class< ::boost::container::container_detail::pair<T1, T2> >
|
||||
//This specialization is needed to avoid instantiation of pair in
|
||||
//is_class, and allow recursive maps.
|
||||
{
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
template <class T1, class T2>
|
||||
struct is_class< std::pair<T1, T2> >
|
||||
//This specialization is needed to avoid instantiation of pair in
|
||||
//is_class, and allow recursive maps.
|
||||
{
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
} //namespace move_detail{
|
||||
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DETAIL_PAIR_HPP
|
||||
@@ -0,0 +1,30 @@
|
||||
#ifndef BOOST_CONTAINER_DETAIL_PLACEMENT_NEW_HPP
|
||||
#define BOOST_CONTAINER_DETAIL_PLACEMENT_NEW_HPP
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2014-2015. 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/container for documentation.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
struct boost_container_new_t{};
|
||||
|
||||
//avoid including <new>
|
||||
inline void *operator new(std::size_t, void *p, boost_container_new_t)
|
||||
{ return p; }
|
||||
|
||||
inline void operator delete(void *, void *, boost_container_new_t)
|
||||
{}
|
||||
|
||||
#endif //BOOST_CONTAINER_DETAIL_PLACEMENT_NEW_HPP
|
||||
@@ -0,0 +1,57 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2013. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_DETAIL_POOL_COMMON_HPP
|
||||
#define BOOST_CONTAINER_DETAIL_POOL_COMMON_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/detail/config_begin.hpp>
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
|
||||
#include <boost/intrusive/slist.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace container_detail {
|
||||
|
||||
template<class VoidPointer>
|
||||
struct node_slist
|
||||
{
|
||||
//This hook will be used to chain the individual nodes
|
||||
typedef typename bi::make_slist_base_hook
|
||||
<bi::void_pointer<VoidPointer>, bi::link_mode<bi::normal_link> >::type slist_hook_t;
|
||||
|
||||
//A node object will hold node_t when it's not allocated
|
||||
typedef slist_hook_t node_t;
|
||||
|
||||
typedef typename bi::make_slist
|
||||
<node_t, bi::linear<true>, bi::cache_last<true>, bi::base_hook<slist_hook_t> >::type node_slist_t;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct is_stateless_segment_manager
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
} //namespace container_detail {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DETAIL_ADAPTIVE_NODE_POOL_IMPL_HPP
|
||||
@@ -0,0 +1,102 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2013. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_DETAIL_POOL_COMMON_ALLOC_HPP
|
||||
#define BOOST_CONTAINER_DETAIL_POOL_COMMON_ALLOC_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/detail/config_begin.hpp>
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
#include <boost/container/throw_exception.hpp>
|
||||
|
||||
#include <boost/intrusive/slist.hpp>
|
||||
#include <boost/container/detail/pool_common.hpp>
|
||||
#include <boost/container/detail/dlmalloc.hpp>
|
||||
#include <cstddef>
|
||||
|
||||
namespace boost{
|
||||
namespace container{
|
||||
namespace container_detail{
|
||||
|
||||
struct node_slist_helper
|
||||
: public boost::container::container_detail::node_slist<void*>
|
||||
{};
|
||||
|
||||
struct fake_segment_manager
|
||||
{
|
||||
typedef void * void_pointer;
|
||||
static const std::size_t PayloadPerAllocation = BOOST_CONTAINER_ALLOCATION_PAYLOAD;
|
||||
|
||||
typedef boost::container::container_detail::
|
||||
basic_multiallocation_chain<void*> multiallocation_chain;
|
||||
static void deallocate(void_pointer p)
|
||||
{ dlmalloc_free(p); }
|
||||
|
||||
static void deallocate_many(multiallocation_chain &chain)
|
||||
{
|
||||
std::size_t size = chain.size();
|
||||
std::pair<void*, void*> ptrs = chain.extract_data();
|
||||
dlmalloc_memchain dlchain;
|
||||
BOOST_CONTAINER_MEMCHAIN_INIT_FROM(&dlchain, ptrs.first, ptrs.second, size);
|
||||
dlmalloc_multidealloc(&dlchain);
|
||||
}
|
||||
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef std::size_t size_type;
|
||||
|
||||
static void *allocate_aligned(std::size_t nbytes, std::size_t alignment)
|
||||
{
|
||||
void *ret = dlmalloc_memalign(nbytes, alignment);
|
||||
if(!ret)
|
||||
boost::container::throw_bad_alloc();
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void *allocate(std::size_t nbytes)
|
||||
{
|
||||
void *ret = dlmalloc_malloc(nbytes);
|
||||
if(!ret)
|
||||
boost::container::throw_bad_alloc();
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
} //namespace boost{
|
||||
} //namespace container{
|
||||
} //namespace container_detail{
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace container_detail {
|
||||
|
||||
template<class T>
|
||||
struct is_stateless_segment_manager;
|
||||
|
||||
template<>
|
||||
struct is_stateless_segment_manager
|
||||
<boost::container::container_detail::fake_segment_manager>
|
||||
{
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
} //namespace container_detail {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_CONTAINER_DETAIL_POOL_COMMON_ALLOC_HPP
|
||||
@@ -0,0 +1,191 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_POOL_RESOURCE_HPP
|
||||
#define BOOST_CONTAINER_POOL_RESOURCE_HPP
|
||||
|
||||
#if defined (_MSC_VER)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/detail/config_begin.hpp>
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
#include <boost/container/pmr/memory_resource.hpp>
|
||||
#include <boost/container/detail/block_list.hpp>
|
||||
#include <boost/container/pmr/pool_options.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace pmr {
|
||||
|
||||
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
|
||||
class pool_data_t;
|
||||
|
||||
static const std::size_t pool_options_minimum_max_blocks_per_chunk = 1u;
|
||||
static const std::size_t pool_options_default_max_blocks_per_chunk = 32u;
|
||||
static const std::size_t pool_options_minimum_largest_required_pool_block =
|
||||
memory_resource::max_align > 2*sizeof(void*) ? memory_resource::max_align : 2*sizeof(void*);
|
||||
static const std::size_t pool_options_default_largest_required_pool_block =
|
||||
pool_options_minimum_largest_required_pool_block > 4096u
|
||||
? pool_options_minimum_largest_required_pool_block : 4096u;
|
||||
|
||||
#endif //BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
class pool_resource
|
||||
{
|
||||
typedef block_list_base<> block_list_base_t;
|
||||
|
||||
pool_options m_options;
|
||||
memory_resource& m_upstream;
|
||||
block_list_base_t m_oversized_list;
|
||||
pool_data_t *m_pool_data;
|
||||
std::size_t m_pool_count;
|
||||
|
||||
static void priv_limit_option(std::size_t &val, std::size_t min, std::size_t max);
|
||||
static std::size_t priv_pool_index(std::size_t block_size);
|
||||
static std::size_t priv_pool_block(std::size_t index);
|
||||
|
||||
void priv_fix_options();
|
||||
void priv_init_pools();
|
||||
void priv_constructor_body();
|
||||
|
||||
public:
|
||||
|
||||
//! <b>Requires</b>: `upstream` is the address of a valid memory resource.
|
||||
//!
|
||||
//! <b>Effects</b>: Constructs a pool resource object that will obtain memory
|
||||
//! from upstream whenever the pool resource is unable to satisfy a memory
|
||||
//! request from its own internal data structures. The resulting object will hold
|
||||
//! a copy of upstream, but will not own the resource to which upstream points.
|
||||
//! [ Note: The intention is that calls to upstream->allocate() will be
|
||||
//! substantially fewer than calls to this->allocate() in most cases. - end note
|
||||
//! The behavior of the pooling mechanism is tuned according to the value of
|
||||
//! the opts argument.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing unless upstream->allocate() throws. It is unspecified if
|
||||
//! or under what conditions this constructor calls upstream->allocate().
|
||||
pool_resource(const pool_options& opts, memory_resource* upstream) BOOST_NOEXCEPT;
|
||||
|
||||
//! <b>Effects</b>: Same as
|
||||
//! `pool_resource(pool_options(), get_default_resource())`.
|
||||
pool_resource() BOOST_NOEXCEPT;
|
||||
|
||||
//! <b>Effects</b>: Same as
|
||||
//! `pool_resource(pool_options(), upstream)`.
|
||||
explicit pool_resource(memory_resource* upstream) BOOST_NOEXCEPT;
|
||||
|
||||
//! <b>Effects</b>: Same as
|
||||
//! `pool_resource(opts, get_default_resource())`.
|
||||
explicit pool_resource(const pool_options& opts) BOOST_NOEXCEPT;
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
pool_resource(const pool_resource&) = delete;
|
||||
pool_resource operator=(const pool_resource&) = delete;
|
||||
#else
|
||||
private:
|
||||
pool_resource (const pool_resource&);
|
||||
pool_resource operator=(const pool_resource&);
|
||||
public:
|
||||
#endif
|
||||
|
||||
//! <b>Effects</b>: Calls
|
||||
//! `this->release()`.
|
||||
virtual ~pool_resource();
|
||||
|
||||
//! <b>Effects</b>: Calls Calls `upstream_resource()->deallocate()` as necessary
|
||||
//! to release all allocated memory. [ Note: memory is released back to
|
||||
//! `upstream_resource()` even if deallocate has not been called for some
|
||||
//! of the allocated blocks. - end note ]
|
||||
void release();
|
||||
|
||||
//! <b>Returns</b>: The value of the upstream argument provided to the
|
||||
//! constructor of this object.
|
||||
memory_resource* upstream_resource() const;
|
||||
|
||||
//! <b>Returns</b>: The options that control the pooling behavior of this resource.
|
||||
//! The values in the returned struct may differ from those supplied to the pool
|
||||
//! resource constructor in that values of zero will be replaced with
|
||||
//! implementation-defined defaults and sizes may be rounded to unspecified granularity.
|
||||
pool_options options() const;
|
||||
|
||||
public: //public so that [un]synchronized_pool_resource can use them
|
||||
|
||||
//! <b>Returns</b>: A pointer to allocated storage with a size of at least `bytes`.
|
||||
//! The size and alignment of the allocated memory shall meet the requirements for
|
||||
//! a class derived from `memory_resource`.
|
||||
//!
|
||||
//! <b>Effects</b>: If the pool selected for a block of size bytes is unable to
|
||||
//! satisfy the memory request from its own internal data structures, it will call
|
||||
//! `upstream_resource()->allocate()` to obtain more memory. If `bytes` is larger
|
||||
//! than that which the largest pool can handle, then memory will be allocated
|
||||
//! using `upstream_resource()->allocate()`.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing unless `upstream_resource()->allocate()` throws.
|
||||
virtual void* do_allocate(std::size_t bytes, std::size_t alignment);
|
||||
|
||||
//! <b>Effects</b>: Return the memory at p to the pool. It is unspecified if or under
|
||||
//! what circumstances this operation will result in a call to
|
||||
//! `upstream_resource()->deallocate()`.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
virtual void do_deallocate(void* p, std::size_t bytes, std::size_t alignment);
|
||||
|
||||
//! <b>Returns</b>:
|
||||
//! `this == dynamic_cast<const pool_resource*>(&other)`.
|
||||
virtual bool do_is_equal(const memory_resource& other) const BOOST_NOEXCEPT;
|
||||
|
||||
//Non-standard observers
|
||||
public:
|
||||
//! <b>Returns</b>: The number of pools that will be used in the pool resource.
|
||||
//!
|
||||
//! <b>Note</b>: Non-standard extension.
|
||||
std::size_t pool_count() const;
|
||||
|
||||
//! <b>Returns</b>: The index of the pool that will be used to serve the allocation of `bytes`.
|
||||
//! from the pool specified by `pool_index`. Returns `pool_count()` if `bytes` is bigger
|
||||
//! than `options().largest_required_pool_block` (no pool will be used to serve this).
|
||||
//!
|
||||
//! <b>Note</b>: Non-standard extension.
|
||||
std::size_t pool_index(std::size_t bytes) const;
|
||||
|
||||
//! <b>Requires</b>: `pool_idx < pool_index()`
|
||||
//!
|
||||
//! <b>Returns</b>: The number blocks that will be allocated in the next chunk
|
||||
//! from the pool specified by `pool_idx`.
|
||||
//!
|
||||
//! <b>Note</b>: Non-standard extension.
|
||||
std::size_t pool_next_blocks_per_chunk(std::size_t pool_idx) const;
|
||||
|
||||
//! <b>Requires</b>: `pool_idx < pool_index()`
|
||||
//!
|
||||
//! <b>Returns</b>: The number of bytes of the block that the specified `pool_idx` pool manages.
|
||||
//!
|
||||
//! <b>Note</b>: Non-standard extension.
|
||||
std::size_t pool_block(std::size_t pool_idx) const;
|
||||
|
||||
//! <b>Requires</b>: `pool_idx < pool_index()`
|
||||
//!
|
||||
//! <b>Returns</b>: The number of blocks that the specified `pool_idx` pool has cached
|
||||
//! and will be served without calling the upstream_allocator.
|
||||
//!
|
||||
//! <b>Note</b>: Non-standard extension.
|
||||
std::size_t pool_cached_blocks(std::size_t pool_idx) const;
|
||||
};
|
||||
|
||||
} //namespace pmr {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_CONTAINER_POOL_RESOURCE_HPP
|
||||
@@ -0,0 +1,121 @@
|
||||
// Copyright (C) 2000 Stephen Cleary
|
||||
// Copyright (C) 2008 Ion Gaztanaga
|
||||
//
|
||||
// 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 for updates, documentation, and revision history.
|
||||
//
|
||||
// This file is a modified file from Boost.Pool
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2007-2013. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_DETAIL_SINGLETON_DETAIL_HPP
|
||||
#define BOOST_CONTAINER_DETAIL_SINGLETON_DETAIL_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/detail/config_begin.hpp>
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
|
||||
//
|
||||
// The following helper classes are placeholders for a generic "singleton"
|
||||
// class. The classes below support usage of singletons, including use in
|
||||
// program startup/shutdown code, AS LONG AS there is only one thread
|
||||
// running before main() begins, and only one thread running after main()
|
||||
// exits.
|
||||
//
|
||||
// This class is also limited in that it can only provide singleton usage for
|
||||
// classes with default constructors.
|
||||
//
|
||||
|
||||
// The design of this class is somewhat twisted, but can be followed by the
|
||||
// calling inheritance. Let us assume that there is some user code that
|
||||
// calls "singleton_default<T>::instance()". The following (convoluted)
|
||||
// sequence ensures that the same function will be called before main():
|
||||
// instance() contains a call to create_object.do_nothing()
|
||||
// Thus, object_creator is implicitly instantiated, and create_object
|
||||
// must exist.
|
||||
// Since create_object is a static member, its constructor must be
|
||||
// called before main().
|
||||
// The constructor contains a call to instance(), thus ensuring that
|
||||
// instance() will be called before main().
|
||||
// The first time instance() is called (i.e., before main()) is the
|
||||
// latest point in program execution where the object of type T
|
||||
// can be created.
|
||||
// Thus, any call to instance() will auto-magically result in a call to
|
||||
// instance() before main(), unless already present.
|
||||
// Furthermore, since the instance() function contains the object, instead
|
||||
// of the singleton_default class containing a static instance of the
|
||||
// object, that object is guaranteed to be constructed (at the latest) in
|
||||
// the first call to instance(). This permits calls to instance() from
|
||||
// static code, even if that code is called before the file-scope objects
|
||||
// in this file have been initialized.
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace container_detail {
|
||||
|
||||
// T must be: no-throw default constructible and no-throw destructible
|
||||
template <typename T>
|
||||
struct singleton_default
|
||||
{
|
||||
private:
|
||||
struct object_creator
|
||||
{
|
||||
// This constructor does nothing more than ensure that instance()
|
||||
// is called before main() begins, thus creating the static
|
||||
// T object before multithreading race issues can come up.
|
||||
object_creator() { singleton_default<T>::instance(); }
|
||||
inline void do_nothing() const { }
|
||||
};
|
||||
static object_creator create_object;
|
||||
|
||||
singleton_default();
|
||||
|
||||
public:
|
||||
typedef T object_type;
|
||||
|
||||
// If, at any point (in user code), singleton_default<T>::instance()
|
||||
// is called, then the following function is instantiated.
|
||||
static object_type & instance()
|
||||
{
|
||||
// This is the object that we return a reference to.
|
||||
// It is guaranteed to be created before main() begins because of
|
||||
// the next line.
|
||||
static object_type obj;
|
||||
|
||||
// The following line does nothing else than force the instantiation
|
||||
// of singleton_default<T>::create_object, whose constructor is
|
||||
// called before main() begins.
|
||||
create_object.do_nothing();
|
||||
|
||||
return obj;
|
||||
}
|
||||
};
|
||||
template <typename T>
|
||||
typename singleton_default<T>::object_creator
|
||||
singleton_default<T>::create_object;
|
||||
|
||||
} // namespace container_detail
|
||||
} // namespace container
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_CONTAINER_DETAIL_SINGLETON_DETAIL_HPP
|
||||
@@ -0,0 +1,56 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2014-2014. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_DETAIL_STD_FWD_HPP
|
||||
#define BOOST_CONTAINER_DETAIL_STD_FWD_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Standard predeclarations
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/move/detail/std_ns_begin.hpp>
|
||||
BOOST_MOVE_STD_NS_BEG
|
||||
|
||||
template<class T>
|
||||
class allocator;
|
||||
|
||||
template<class T>
|
||||
struct less;
|
||||
|
||||
template<class T1, class T2>
|
||||
struct pair;
|
||||
|
||||
template<class T>
|
||||
struct char_traits;
|
||||
|
||||
struct input_iterator_tag;
|
||||
struct forward_iterator_tag;
|
||||
struct bidirectional_iterator_tag;
|
||||
struct random_access_iterator_tag;
|
||||
|
||||
template<class Container>
|
||||
class insert_iterator;
|
||||
|
||||
struct allocator_arg_t;
|
||||
|
||||
struct piecewise_construct_t;
|
||||
|
||||
BOOST_MOVE_STD_NS_END
|
||||
#include <boost/move/detail/std_ns_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DETAIL_STD_FWD_HPP
|
||||
@@ -0,0 +1,33 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2014-2015. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#ifndef BOOST_CONTAINER_DETAIL_TO_RAW_POINTER_HPP
|
||||
#define BOOST_CONTAINER_DETAIL_TO_RAW_POINTER_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/intrusive/detail/to_raw_pointer.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace container_detail {
|
||||
|
||||
using ::boost::intrusive::detail::to_raw_pointer;
|
||||
|
||||
} //namespace container_detail {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DETAIL_TO_RAW_POINTER_HPP
|
||||
@@ -0,0 +1,180 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2013.
|
||||
// (C) Copyright Gennaro Prota 2003 - 2004.
|
||||
//
|
||||
// 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_DETAIL_TRANSFORM_ITERATORS_HPP
|
||||
#define BOOST_CONTAINER_DETAIL_TRANSFORM_ITERATORS_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/detail/config_begin.hpp>
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
#include <boost/container/detail/type_traits.hpp>
|
||||
#include <boost/container/detail/iterator.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
|
||||
template <class PseudoReference>
|
||||
struct operator_arrow_proxy
|
||||
{
|
||||
operator_arrow_proxy(const PseudoReference &px)
|
||||
: m_value(px)
|
||||
{}
|
||||
|
||||
typedef PseudoReference element_type;
|
||||
|
||||
PseudoReference* operator->() const { return &m_value; }
|
||||
|
||||
mutable PseudoReference m_value;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct operator_arrow_proxy<T&>
|
||||
{
|
||||
operator_arrow_proxy(T &px)
|
||||
: m_value(px)
|
||||
{}
|
||||
|
||||
typedef T element_type;
|
||||
|
||||
T* operator->() const { return const_cast<T*>(&m_value); }
|
||||
|
||||
T &m_value;
|
||||
};
|
||||
|
||||
template <class Iterator, class UnaryFunction>
|
||||
class transform_iterator
|
||||
: public UnaryFunction
|
||||
, public boost::container::iterator
|
||||
< typename Iterator::iterator_category
|
||||
, typename container_detail::remove_reference<typename UnaryFunction::result_type>::type
|
||||
, typename Iterator::difference_type
|
||||
, operator_arrow_proxy<typename UnaryFunction::result_type>
|
||||
, typename UnaryFunction::result_type>
|
||||
{
|
||||
public:
|
||||
explicit transform_iterator(const Iterator &it, const UnaryFunction &f = UnaryFunction())
|
||||
: UnaryFunction(f), m_it(it)
|
||||
{}
|
||||
|
||||
explicit transform_iterator()
|
||||
: UnaryFunction(), m_it()
|
||||
{}
|
||||
|
||||
//Constructors
|
||||
transform_iterator& operator++()
|
||||
{ increment(); return *this; }
|
||||
|
||||
transform_iterator operator++(int)
|
||||
{
|
||||
transform_iterator result (*this);
|
||||
increment();
|
||||
return result;
|
||||
}
|
||||
|
||||
friend bool operator== (const transform_iterator& i, const transform_iterator& i2)
|
||||
{ return i.equal(i2); }
|
||||
|
||||
friend bool operator!= (const transform_iterator& i, const transform_iterator& i2)
|
||||
{ return !(i == i2); }
|
||||
|
||||
/*
|
||||
friend bool operator> (const transform_iterator& i, const transform_iterator& i2)
|
||||
{ return i2 < i; }
|
||||
|
||||
friend bool operator<= (const transform_iterator& i, const transform_iterator& i2)
|
||||
{ return !(i > i2); }
|
||||
|
||||
friend bool operator>= (const transform_iterator& i, const transform_iterator& i2)
|
||||
{ return !(i < i2); }
|
||||
*/
|
||||
friend typename Iterator::difference_type operator- (const transform_iterator& i, const transform_iterator& i2)
|
||||
{ return i2.distance_to(i); }
|
||||
|
||||
//Arithmetic
|
||||
transform_iterator& operator+=(typename Iterator::difference_type off)
|
||||
{ this->advance(off); return *this; }
|
||||
|
||||
transform_iterator operator+(typename Iterator::difference_type off) const
|
||||
{
|
||||
transform_iterator other(*this);
|
||||
other.advance(off);
|
||||
return other;
|
||||
}
|
||||
|
||||
friend transform_iterator operator+(typename Iterator::difference_type off, const transform_iterator& right)
|
||||
{ return right + off; }
|
||||
|
||||
transform_iterator& operator-=(typename Iterator::difference_type off)
|
||||
{ this->advance(-off); return *this; }
|
||||
|
||||
transform_iterator operator-(typename Iterator::difference_type off) const
|
||||
{ return *this + (-off); }
|
||||
|
||||
typename UnaryFunction::result_type operator*() const
|
||||
{ return dereference(); }
|
||||
|
||||
operator_arrow_proxy<typename UnaryFunction::result_type>
|
||||
operator->() const
|
||||
{ return operator_arrow_proxy<typename UnaryFunction::result_type>(dereference()); }
|
||||
|
||||
Iterator & base()
|
||||
{ return m_it; }
|
||||
|
||||
const Iterator & base() const
|
||||
{ return m_it; }
|
||||
|
||||
private:
|
||||
Iterator m_it;
|
||||
|
||||
void increment()
|
||||
{ ++m_it; }
|
||||
|
||||
void decrement()
|
||||
{ --m_it; }
|
||||
|
||||
bool equal(const transform_iterator &other) const
|
||||
{ return m_it == other.m_it; }
|
||||
|
||||
bool less(const transform_iterator &other) const
|
||||
{ return other.m_it < m_it; }
|
||||
|
||||
typename UnaryFunction::result_type dereference() const
|
||||
{ return UnaryFunction::operator()(*m_it); }
|
||||
|
||||
void advance(typename Iterator::difference_type n)
|
||||
{ boost::container::iterator_advance(m_it, n); }
|
||||
|
||||
typename Iterator::difference_type distance_to(const transform_iterator &other)const
|
||||
{ return boost::container::iterator_distance(other.m_it, m_it); }
|
||||
};
|
||||
|
||||
template <class Iterator, class UnaryFunc>
|
||||
transform_iterator<Iterator, UnaryFunc>
|
||||
make_transform_iterator(Iterator it, UnaryFunc fun)
|
||||
{
|
||||
return transform_iterator<Iterator, UnaryFunc>(it, fun);
|
||||
}
|
||||
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DETAIL_TRANSFORM_ITERATORS_HPP
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,70 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// (C) Copyright John Maddock 2000.
|
||||
// (C) Copyright Ion Gaztanaga 2005-2015.
|
||||
//
|
||||
// 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/container for documentation.
|
||||
//
|
||||
// The alignment and Type traits implementation comes from
|
||||
// John Maddock's TypeTraits library.
|
||||
//
|
||||
// Some other tricks come from Howard Hinnant's papers and StackOverflow replies
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#ifndef BOOST_CONTAINER_CONTAINER_DETAIL_TYPE_TRAITS_HPP
|
||||
#define BOOST_CONTAINER_CONTAINER_DETAIL_TYPE_TRAITS_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/move/detail/type_traits.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace container_detail {
|
||||
|
||||
using ::boost::move_detail::enable_if;
|
||||
using ::boost::move_detail::enable_if_and;
|
||||
using ::boost::move_detail::is_same;
|
||||
using ::boost::move_detail::is_different;
|
||||
using ::boost::move_detail::is_pointer;
|
||||
using ::boost::move_detail::add_reference;
|
||||
using ::boost::move_detail::add_const;
|
||||
using ::boost::move_detail::add_const_reference;
|
||||
using ::boost::move_detail::remove_const;
|
||||
using ::boost::move_detail::remove_reference;
|
||||
using ::boost::move_detail::make_unsigned;
|
||||
using ::boost::move_detail::is_floating_point;
|
||||
using ::boost::move_detail::is_integral;
|
||||
using ::boost::move_detail::is_enum;
|
||||
using ::boost::move_detail::is_pod;
|
||||
using ::boost::move_detail::is_empty;
|
||||
using ::boost::move_detail::is_trivially_destructible;
|
||||
using ::boost::move_detail::is_trivially_default_constructible;
|
||||
using ::boost::move_detail::is_trivially_copy_constructible;
|
||||
using ::boost::move_detail::is_trivially_move_constructible;
|
||||
using ::boost::move_detail::is_trivially_copy_assignable;
|
||||
using ::boost::move_detail::is_trivially_move_assignable;
|
||||
using ::boost::move_detail::is_nothrow_default_constructible;
|
||||
using ::boost::move_detail::is_nothrow_copy_constructible;
|
||||
using ::boost::move_detail::is_nothrow_move_constructible;
|
||||
using ::boost::move_detail::is_nothrow_copy_assignable;
|
||||
using ::boost::move_detail::is_nothrow_move_assignable;
|
||||
using ::boost::move_detail::is_nothrow_swappable;
|
||||
using ::boost::move_detail::alignment_of;
|
||||
using ::boost::move_detail::aligned_storage;
|
||||
using ::boost::move_detail::nat;
|
||||
using ::boost::move_detail::max_align_t;
|
||||
|
||||
} //namespace container_detail {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_CONTAINER_DETAIL_TYPE_TRAITS_HPP
|
||||
@@ -0,0 +1,51 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2013.
|
||||
//
|
||||
// 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_DETAIL_VALUE_INIT_HPP
|
||||
#define BOOST_CONTAINER_DETAIL_VALUE_INIT_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/detail/config_begin.hpp>
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace container_detail {
|
||||
|
||||
template<class T>
|
||||
struct value_init
|
||||
{
|
||||
value_init()
|
||||
: m_t()
|
||||
{}
|
||||
|
||||
operator T &() { return m_t; }
|
||||
|
||||
T &get() { return m_t; }
|
||||
|
||||
T m_t;
|
||||
};
|
||||
|
||||
} //namespace container_detail {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DETAIL_VALUE_INIT_HPP
|
||||
+163
@@ -0,0 +1,163 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2008-2013. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP
|
||||
#define BOOST_CONTAINER_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/detail/config_begin.hpp>
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
#include <boost/move/utility_core.hpp>
|
||||
|
||||
#include <boost/container/detail/type_traits.hpp>
|
||||
#include <cstddef> //std::size_t
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace container_detail {
|
||||
|
||||
template<typename... Values>
|
||||
class tuple;
|
||||
|
||||
template<> class tuple<>
|
||||
{};
|
||||
|
||||
template<typename Head, typename... Tail>
|
||||
class tuple<Head, Tail...>
|
||||
: private tuple<Tail...>
|
||||
{
|
||||
typedef tuple<Tail...> inherited;
|
||||
|
||||
public:
|
||||
tuple()
|
||||
: inherited(), m_head()
|
||||
{}
|
||||
|
||||
template<class U, class ...Args>
|
||||
tuple(U &&u, Args && ...args)
|
||||
: inherited(::boost::forward<Args>(args)...), m_head(::boost::forward<U>(u))
|
||||
{}
|
||||
|
||||
// Construct tuple from another tuple.
|
||||
template<typename... VValues>
|
||||
tuple(const tuple<VValues...>& other)
|
||||
: inherited(other.tail()), m_head(other.head())
|
||||
{}
|
||||
|
||||
template<typename... VValues>
|
||||
tuple& operator=(const tuple<VValues...>& other)
|
||||
{
|
||||
m_head = other.head();
|
||||
tail() = other.tail();
|
||||
return this;
|
||||
}
|
||||
|
||||
typename add_reference<Head>::type head() { return m_head; }
|
||||
typename add_reference<const Head>::type head() const { return m_head; }
|
||||
|
||||
inherited& tail() { return *this; }
|
||||
const inherited& tail() const { return *this; }
|
||||
|
||||
protected:
|
||||
Head m_head;
|
||||
};
|
||||
|
||||
|
||||
template<typename... Values>
|
||||
tuple<Values&&...> forward_as_tuple(Values&&... values)
|
||||
{ return tuple<Values&&...>(::boost::forward<Values>(values)...); }
|
||||
|
||||
template<int I, typename Tuple>
|
||||
struct tuple_element;
|
||||
|
||||
template<int I, typename Head, typename... Tail>
|
||||
struct tuple_element<I, tuple<Head, Tail...> >
|
||||
{
|
||||
typedef typename tuple_element<I-1, tuple<Tail...> >::type type;
|
||||
};
|
||||
|
||||
template<typename Head, typename... Tail>
|
||||
struct tuple_element<0, tuple<Head, Tail...> >
|
||||
{
|
||||
typedef Head type;
|
||||
};
|
||||
|
||||
template<int I, typename Tuple>
|
||||
class get_impl;
|
||||
|
||||
template<int I, typename Head, typename... Values>
|
||||
class get_impl<I, tuple<Head, Values...> >
|
||||
{
|
||||
typedef typename tuple_element<I-1, tuple<Values...> >::type Element;
|
||||
typedef get_impl<I-1, tuple<Values...> > Next;
|
||||
|
||||
public:
|
||||
typedef typename add_reference<Element>::type type;
|
||||
typedef typename add_const_reference<Element>::type const_type;
|
||||
static type get(tuple<Head, Values...>& t) { return Next::get(t.tail()); }
|
||||
static const_type get(const tuple<Head, Values...>& t) { return Next::get(t.tail()); }
|
||||
};
|
||||
|
||||
template<typename Head, typename... Values>
|
||||
class get_impl<0, tuple<Head, Values...> >
|
||||
{
|
||||
public:
|
||||
typedef typename add_reference<Head>::type type;
|
||||
typedef typename add_const_reference<Head>::type const_type;
|
||||
static type get(tuple<Head, Values...>& t) { return t.head(); }
|
||||
static const_type get(const tuple<Head, Values...>& t){ return t.head(); }
|
||||
};
|
||||
|
||||
template<int I, typename... Values>
|
||||
typename get_impl<I, tuple<Values...> >::type get(tuple<Values...>& t)
|
||||
{ return get_impl<I, tuple<Values...> >::get(t); }
|
||||
|
||||
template<int I, typename... Values>
|
||||
typename get_impl<I, tuple<Values...> >::const_type get(const tuple<Values...>& t)
|
||||
{ return get_impl<I, tuple<Values...> >::get(t); }
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
// Builds an index_tuple<0, 1, 2, ..., Num-1>, that will
|
||||
// be used to "unpack" into comma-separated values
|
||||
// in a function call.
|
||||
////////////////////////////////////////////////////
|
||||
|
||||
template<std::size_t...> struct index_tuple{ typedef index_tuple type; };
|
||||
|
||||
template<class S1, class S2> struct concat_index_tuple;
|
||||
|
||||
template<std::size_t... I1, std::size_t... I2>
|
||||
struct concat_index_tuple<index_tuple<I1...>, index_tuple<I2...>>
|
||||
: index_tuple<I1..., (sizeof...(I1)+I2)...>{};
|
||||
|
||||
template<std::size_t N> struct build_number_seq;
|
||||
|
||||
template<std::size_t N>
|
||||
struct build_number_seq
|
||||
: concat_index_tuple<typename build_number_seq<N/2>::type
|
||||
,typename build_number_seq<N - N/2 >::type
|
||||
>::type
|
||||
{};
|
||||
|
||||
template<> struct build_number_seq<0> : index_tuple<>{};
|
||||
template<> struct build_number_seq<1> : index_tuple<0>{};
|
||||
|
||||
}}} //namespace boost { namespace container { namespace container_detail {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP
|
||||
@@ -0,0 +1,110 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2013. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// This code comes from N1953 document by Howard E. Hinnant
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef BOOST_CONTAINER_DETAIL_VERSION_TYPE_HPP
|
||||
#define BOOST_CONTAINER_DETAIL_VERSION_TYPE_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/detail/config_begin.hpp>
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
|
||||
#include <boost/container/detail/mpl.hpp>
|
||||
#include <boost/container/detail/type_traits.hpp>
|
||||
|
||||
namespace boost{
|
||||
namespace container {
|
||||
namespace container_detail {
|
||||
|
||||
template <class T, unsigned V>
|
||||
struct version_type
|
||||
: public container_detail::integral_constant<unsigned, V>
|
||||
{
|
||||
typedef T type;
|
||||
|
||||
version_type(const version_type<T, 0>&);
|
||||
};
|
||||
|
||||
namespace impl{
|
||||
|
||||
template <class T,
|
||||
bool = container_detail::is_convertible<version_type<T, 0>, typename T::version>::value>
|
||||
struct extract_version
|
||||
{
|
||||
static const unsigned value = 1;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct extract_version<T, true>
|
||||
{
|
||||
static const unsigned value = T::version::value;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct has_version
|
||||
{
|
||||
private:
|
||||
struct two {char _[2];};
|
||||
template <class U> static two test(...);
|
||||
template <class U> static char test(const typename U::version*);
|
||||
public:
|
||||
static const bool value = sizeof(test<T>(0)) == 1;
|
||||
void dummy(){}
|
||||
};
|
||||
|
||||
template <class T, bool = has_version<T>::value>
|
||||
struct version
|
||||
{
|
||||
static const unsigned value = 1;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct version<T, true>
|
||||
{
|
||||
static const unsigned value = extract_version<T>::value;
|
||||
};
|
||||
|
||||
} //namespace impl
|
||||
|
||||
template <class T>
|
||||
struct version
|
||||
: public container_detail::integral_constant<unsigned, impl::version<T>::value>
|
||||
{};
|
||||
|
||||
template<class T, unsigned N>
|
||||
struct is_version
|
||||
{
|
||||
static const bool value =
|
||||
is_same< typename version<T>::type, integral_constant<unsigned, N> >::value;
|
||||
};
|
||||
|
||||
} //namespace container_detail {
|
||||
|
||||
typedef container_detail::integral_constant<unsigned, 0> version_0;
|
||||
typedef container_detail::integral_constant<unsigned, 1> version_1;
|
||||
typedef container_detail::integral_constant<unsigned, 2> version_2;
|
||||
|
||||
} //namespace container {
|
||||
} //namespace boost{
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //#define BOOST_CONTAINER_DETAIL_VERSION_TYPE_HPP
|
||||
@@ -0,0 +1,117 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2013. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_DETAIL_WORKAROUND_HPP
|
||||
#define BOOST_CONTAINER_DETAIL_WORKAROUND_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)\
|
||||
&& !defined(BOOST_INTERPROCESS_DISABLE_VARIADIC_TMPL)
|
||||
#define BOOST_CONTAINER_PERFECT_FORWARDING
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && defined(__GXX_EXPERIMENTAL_CXX0X__)\
|
||||
&& (__GNUC__*10000 + __GNUC_MINOR__*100 + __GNUC_PATCHLEVEL__ < 40700)
|
||||
#define BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_GCC_VERSION)
|
||||
# if (BOOST_GCC_VERSION < 40700) || !defined(BOOST_GCC_CXX11)
|
||||
# define BOOST_CONTAINER_NO_CXX11_DELEGATING_CONSTRUCTORS
|
||||
# endif
|
||||
#elif defined(BOOST_MSVC)
|
||||
# if _MSC_FULL_VER < 180020827
|
||||
# define BOOST_CONTAINER_NO_CXX11_DELEGATING_CONSTRUCTORS
|
||||
# endif
|
||||
#elif defined(BOOST_CLANG)
|
||||
# if !__has_feature(cxx_delegating_constructors)
|
||||
# define BOOST_CONTAINER_NO_CXX11_DELEGATING_CONSTRUCTORS
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_FALLTHOUGH)
|
||||
#define BOOST_CONTAINER_FALLTHOUGH
|
||||
#else
|
||||
#define BOOST_CONTAINER_FALLTHOUGH BOOST_FALLTHOUGH;
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_MSVC) && (_MSC_VER < 1400)
|
||||
#define BOOST_CONTAINER_TEMPLATED_CONVERSION_OPERATOR_BROKEN
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_TUPLE) || (defined(BOOST_MSVC) && (BOOST_MSVC == 1700 || BOOST_MSVC == 1600))
|
||||
#define BOOST_CONTAINER_PAIR_TEST_HAS_HEADER_TUPLE
|
||||
#endif
|
||||
|
||||
//Macros for documentation purposes. For code, expands to the argument
|
||||
#define BOOST_CONTAINER_IMPDEF(TYPE) TYPE
|
||||
#define BOOST_CONTAINER_SEEDOC(TYPE) TYPE
|
||||
|
||||
//Macros for memset optimization. In most platforms
|
||||
//memsetting pointers and floatings is safe and faster.
|
||||
//
|
||||
//If your platform does not offer these guarantees
|
||||
//define these to value zero.
|
||||
#ifndef BOOST_CONTAINER_MEMZEROED_FLOATING_POINT_IS_NOT_ZERO
|
||||
#define BOOST_CONTAINER_MEMZEROED_FLOATING_POINT_IS_ZERO 1
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_CONTAINER_MEMZEROED_POINTER_IS_NOT_NULL
|
||||
#define BOOST_CONTAINER_MEMZEROED_POINTER_IS_NULL
|
||||
#endif
|
||||
|
||||
#define BOOST_CONTAINER_DOC1ST(TYPE1, TYPE2) TYPE2
|
||||
#define BOOST_CONTAINER_I ,
|
||||
#define BOOST_CONTAINER_DOCIGN(T) T
|
||||
#define BOOST_CONTAINER_DOCONLY(T)
|
||||
|
||||
/*
|
||||
we need to import/export our code only if the user has specifically
|
||||
asked for it by defining either BOOST_ALL_DYN_LINK if they want all boost
|
||||
libraries to be dynamically linked, or BOOST_CONTAINER_DYN_LINK
|
||||
if they want just this one to be dynamically liked:
|
||||
*/
|
||||
#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_CONTAINER_DYN_LINK)
|
||||
|
||||
/* export if this is our own source, otherwise import: */
|
||||
#ifdef BOOST_CONTAINER_SOURCE
|
||||
# define BOOST_CONTAINER_DECL BOOST_SYMBOL_EXPORT
|
||||
#else
|
||||
# define BOOST_CONTAINER_DECL BOOST_SYMBOL_IMPORT
|
||||
|
||||
#endif /* BOOST_CONTAINER_SOURCE */
|
||||
#else
|
||||
#define BOOST_CONTAINER_DECL
|
||||
#endif /* DYN_LINK */
|
||||
|
||||
//#define BOOST_CONTAINER_DISABLE_FORCEINLINE
|
||||
|
||||
#if defined(BOOST_CONTAINER_DISABLE_FORCEINLINE)
|
||||
#define BOOST_CONTAINER_FORCEINLINE inline
|
||||
#elif defined(BOOST_CONTAINER_FORCEINLINE_IS_BOOST_FORCELINE)
|
||||
#define BOOST_CONTAINER_FORCEINLINE BOOST_FORCEINLINE
|
||||
#elif defined(BOOST_MSVC) && defined(_DEBUG)
|
||||
//"__forceinline" and MSVC seems to have some bugs in debug mode
|
||||
#define BOOST_CONTAINER_FORCEINLINE inline
|
||||
#elif defined(__GNUC__) && ((__GNUC__ < 4) || (__GNUC__ == 4 && (__GNUC_MINOR__ < 5)))
|
||||
//Older GCCs have problems with forceinline
|
||||
#define BOOST_CONTAINER_FORCEINLINE inline
|
||||
#else
|
||||
#define BOOST_CONTAINER_FORCEINLINE BOOST_FORCEINLINE
|
||||
#endif
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DETAIL_WORKAROUND_HPP
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,179 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2014-2015. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_NEW_ALLOCATOR_HPP
|
||||
#define BOOST_CONTAINER_NEW_ALLOCATOR_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/detail/config_begin.hpp>
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
#include <boost/container/throw_exception.hpp>
|
||||
#include <cstddef>
|
||||
|
||||
//!\file
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
|
||||
/// @cond
|
||||
|
||||
template<bool Value>
|
||||
struct new_allocator_bool
|
||||
{ static const bool value = Value; };
|
||||
|
||||
template<class T>
|
||||
class new_allocator;
|
||||
|
||||
/// @endcond
|
||||
|
||||
//! Specialization of new_allocator for void types
|
||||
template<>
|
||||
class new_allocator<void>
|
||||
{
|
||||
public:
|
||||
typedef void value_type;
|
||||
typedef void * pointer;
|
||||
typedef const void* const_pointer;
|
||||
//!A integral constant of type bool with value true
|
||||
typedef BOOST_CONTAINER_IMPDEF(new_allocator_bool<true>) propagate_on_container_move_assignment;
|
||||
//!A integral constant of type bool with value true
|
||||
typedef BOOST_CONTAINER_IMPDEF(new_allocator_bool<true>) is_always_equal;
|
||||
// reference-to-void members are impossible
|
||||
|
||||
//!Obtains an new_allocator that allocates
|
||||
//!objects of type T2
|
||||
template<class T2>
|
||||
struct rebind
|
||||
{
|
||||
typedef new_allocator< T2> other;
|
||||
};
|
||||
|
||||
//!Default constructor
|
||||
//!Never throws
|
||||
new_allocator() BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{}
|
||||
|
||||
//!Constructor from other new_allocator.
|
||||
//!Never throws
|
||||
new_allocator(const new_allocator &) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{}
|
||||
|
||||
//!Constructor from related new_allocator.
|
||||
//!Never throws
|
||||
template<class T2>
|
||||
new_allocator(const new_allocator<T2> &) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{}
|
||||
|
||||
//!Swaps two allocators, does nothing
|
||||
//!because this new_allocator is stateless
|
||||
friend void swap(new_allocator &, new_allocator &) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{}
|
||||
|
||||
//!An new_allocator always compares to true, as memory allocated with one
|
||||
//!instance can be deallocated by another instance
|
||||
friend bool operator==(const new_allocator &, const new_allocator &) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return true; }
|
||||
|
||||
//!An new_allocator always compares to false, as memory allocated with one
|
||||
//!instance can be deallocated by another instance
|
||||
friend bool operator!=(const new_allocator &, const new_allocator &) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return false; }
|
||||
};
|
||||
|
||||
|
||||
//! This class is a reduced STL-compatible allocator that allocates memory using operator new
|
||||
template<class T>
|
||||
class new_allocator
|
||||
{
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef T * pointer;
|
||||
typedef const T * const_pointer;
|
||||
typedef T & reference;
|
||||
typedef const T & const_reference;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
//!A integral constant of type bool with value true
|
||||
typedef BOOST_CONTAINER_IMPDEF(new_allocator_bool<true>) propagate_on_container_move_assignment;
|
||||
//!A integral constant of type bool with value true
|
||||
typedef BOOST_CONTAINER_IMPDEF(new_allocator_bool<true>) is_always_equal;
|
||||
|
||||
//!Obtains an new_allocator that allocates
|
||||
//!objects of type T2
|
||||
template<class T2>
|
||||
struct rebind
|
||||
{
|
||||
typedef new_allocator<T2> other;
|
||||
};
|
||||
|
||||
//!Default constructor
|
||||
//!Never throws
|
||||
new_allocator() BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{}
|
||||
|
||||
//!Constructor from other new_allocator.
|
||||
//!Never throws
|
||||
new_allocator(const new_allocator &) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{}
|
||||
|
||||
//!Constructor from related new_allocator.
|
||||
//!Never throws
|
||||
template<class T2>
|
||||
new_allocator(const new_allocator<T2> &) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{}
|
||||
|
||||
//!Allocates memory for an array of count elements.
|
||||
//!Throws std::bad_alloc if there is no enough memory
|
||||
pointer allocate(size_type count)
|
||||
{
|
||||
if(BOOST_UNLIKELY(count > this->max_size()))
|
||||
throw_bad_alloc();
|
||||
return static_cast<T*>(::operator new(count*sizeof(T)));
|
||||
}
|
||||
|
||||
//!Deallocates previously allocated memory.
|
||||
//!Never throws
|
||||
void deallocate(pointer ptr, size_type) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ ::operator delete((void*)ptr); }
|
||||
|
||||
//!Returns the maximum number of elements that could be allocated.
|
||||
//!Never throws
|
||||
size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return size_type(-1)/sizeof(T); }
|
||||
|
||||
//!Swaps two allocators, does nothing
|
||||
//!because this new_allocator is stateless
|
||||
friend void swap(new_allocator &, new_allocator &) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{}
|
||||
|
||||
//!An new_allocator always compares to true, as memory allocated with one
|
||||
//!instance can be deallocated by another instance
|
||||
friend bool operator==(const new_allocator &, const new_allocator &) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return true; }
|
||||
|
||||
//!An new_allocator always compares to false, as memory allocated with one
|
||||
//!instance can be deallocated by another instance
|
||||
friend bool operator!=(const new_allocator &, const new_allocator &) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return false; }
|
||||
};
|
||||
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_CONTAINER_NEW_ALLOCATOR_HPP
|
||||
@@ -0,0 +1,341 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2008-2013. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_POOLED_NODE_ALLOCATOR_HPP
|
||||
#define BOOST_CONTAINER_POOLED_NODE_ALLOCATOR_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/detail/config_begin.hpp>
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
#include <boost/container/container_fwd.hpp>
|
||||
#include <boost/container/throw_exception.hpp>
|
||||
#include <boost/container/detail/node_pool.hpp>
|
||||
#include <boost/container/detail/mpl.hpp>
|
||||
#include <boost/container/detail/multiallocation_chain.hpp>
|
||||
#include <boost/container/detail/dlmalloc.hpp>
|
||||
#include <boost/container/detail/singleton.hpp>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <cstddef>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
|
||||
//!An STL node allocator that uses a modified DlMalloc as memory
|
||||
//!source.
|
||||
//!
|
||||
//!This node allocator shares a segregated storage between all instances
|
||||
//!of node_allocator with equal sizeof(T).
|
||||
//!
|
||||
//!NodesPerBlock is the number of nodes allocated at once when the allocator
|
||||
//!runs out of nodes
|
||||
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
template
|
||||
< class T
|
||||
, std::size_t NodesPerBlock = NodeAlloc_nodes_per_block>
|
||||
#else
|
||||
template
|
||||
< class T
|
||||
, std::size_t NodesPerBlock
|
||||
, std::size_t Version>
|
||||
#endif
|
||||
class node_allocator
|
||||
{
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
//! If Version is 1, the allocator is a STL conforming allocator. If Version is 2,
|
||||
//! the allocator offers advanced expand in place and burst allocation capabilities.
|
||||
public:
|
||||
typedef unsigned int allocation_type;
|
||||
typedef node_allocator<T, NodesPerBlock, Version> self_t;
|
||||
|
||||
static const std::size_t nodes_per_block = NodesPerBlock;
|
||||
|
||||
BOOST_STATIC_ASSERT((Version <=2));
|
||||
#endif
|
||||
|
||||
public:
|
||||
//-------
|
||||
typedef T value_type;
|
||||
typedef T * pointer;
|
||||
typedef const T * const_pointer;
|
||||
typedef typename ::boost::container::
|
||||
container_detail::unvoid_ref<T>::type reference;
|
||||
typedef typename ::boost::container::
|
||||
container_detail::unvoid_ref<const T>::type const_reference;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
|
||||
typedef boost::container::container_detail::
|
||||
version_type<self_t, Version> version;
|
||||
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
typedef boost::container::container_detail::
|
||||
basic_multiallocation_chain<void*> multiallocation_chain_void;
|
||||
typedef boost::container::container_detail::
|
||||
transform_multiallocation_chain
|
||||
<multiallocation_chain_void, T> multiallocation_chain;
|
||||
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
//!Obtains node_allocator from
|
||||
//!node_allocator
|
||||
template<class T2>
|
||||
struct rebind
|
||||
{
|
||||
typedef node_allocator< T2, NodesPerBlock
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
, Version
|
||||
#endif
|
||||
> other;
|
||||
};
|
||||
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
private:
|
||||
//!Not assignable from related node_allocator
|
||||
template<class T2, std::size_t N2>
|
||||
node_allocator& operator=
|
||||
(const node_allocator<T2, N2>&);
|
||||
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
public:
|
||||
|
||||
//!Default constructor
|
||||
node_allocator() BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{}
|
||||
|
||||
//!Copy constructor from other node_allocator.
|
||||
node_allocator(const node_allocator &) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{}
|
||||
|
||||
//!Copy constructor from related node_allocator.
|
||||
template<class T2>
|
||||
node_allocator
|
||||
(const node_allocator<T2, NodesPerBlock
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
, Version
|
||||
#endif
|
||||
> &) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{}
|
||||
|
||||
//!Destructor
|
||||
~node_allocator() BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{}
|
||||
|
||||
//!Returns the number of elements that could be allocated.
|
||||
//!Never throws
|
||||
size_type max_size() const
|
||||
{ return size_type(-1)/sizeof(T); }
|
||||
|
||||
//!Allocate memory for an array of count elements.
|
||||
//!Throws std::bad_alloc if there is no enough memory
|
||||
pointer allocate(size_type count, const void * = 0)
|
||||
{
|
||||
if(BOOST_UNLIKELY(count > this->max_size()))
|
||||
boost::container::throw_bad_alloc();
|
||||
|
||||
if(Version == 1 && count == 1){
|
||||
typedef container_detail::shared_node_pool
|
||||
<sizeof(T), NodesPerBlock> shared_pool_t;
|
||||
typedef container_detail::singleton_default<shared_pool_t> singleton_t;
|
||||
return pointer(static_cast<T*>(singleton_t::instance().allocate_node()));
|
||||
}
|
||||
else{
|
||||
void *ret = dlmalloc_malloc(count*sizeof(T));
|
||||
if(BOOST_UNLIKELY(!ret))
|
||||
boost::container::throw_bad_alloc();
|
||||
return static_cast<pointer>(ret);
|
||||
}
|
||||
}
|
||||
|
||||
//!Deallocate allocated memory.
|
||||
//!Never throws
|
||||
void deallocate(const pointer &ptr, size_type count) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{
|
||||
(void)count;
|
||||
if(Version == 1 && count == 1){
|
||||
typedef container_detail::shared_node_pool
|
||||
<sizeof(T), NodesPerBlock> shared_pool_t;
|
||||
typedef container_detail::singleton_default<shared_pool_t> singleton_t;
|
||||
singleton_t::instance().deallocate_node(ptr);
|
||||
}
|
||||
else{
|
||||
dlmalloc_free(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
//!Deallocates all free blocks of the pool
|
||||
static void deallocate_free_blocks() BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{
|
||||
typedef container_detail::shared_node_pool
|
||||
<sizeof(T), NodesPerBlock> shared_pool_t;
|
||||
typedef container_detail::singleton_default<shared_pool_t> singleton_t;
|
||||
singleton_t::instance().deallocate_free_blocks();
|
||||
}
|
||||
|
||||
pointer allocation_command
|
||||
(allocation_type command, size_type limit_size, size_type &prefer_in_recvd_out_size, pointer &reuse)
|
||||
{
|
||||
BOOST_STATIC_ASSERT(( Version > 1 ));
|
||||
pointer ret = this->priv_allocation_command(command, limit_size, prefer_in_recvd_out_size, reuse);
|
||||
if(BOOST_UNLIKELY(!ret && !(command & BOOST_CONTAINER_NOTHROW_ALLOCATION)))
|
||||
boost::container::throw_bad_alloc();
|
||||
return ret;
|
||||
}
|
||||
|
||||
//!Returns maximum the number of objects the previously allocated memory
|
||||
//!pointed by p can hold.
|
||||
size_type size(pointer p) const BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{
|
||||
BOOST_STATIC_ASSERT(( Version > 1 ));
|
||||
return dlmalloc_size(p);
|
||||
}
|
||||
|
||||
//!Allocates just one object. Memory allocated with this function
|
||||
//!must be deallocated only with deallocate_one().
|
||||
//!Throws bad_alloc if there is no enough memory
|
||||
pointer allocate_one()
|
||||
{
|
||||
BOOST_STATIC_ASSERT(( Version > 1 ));
|
||||
typedef container_detail::shared_node_pool
|
||||
<sizeof(T), NodesPerBlock> shared_pool_t;
|
||||
typedef container_detail::singleton_default<shared_pool_t> singleton_t;
|
||||
return (pointer)singleton_t::instance().allocate_node();
|
||||
}
|
||||
|
||||
//!Allocates many elements of size == 1.
|
||||
//!Elements must be individually deallocated with deallocate_one()
|
||||
void allocate_individual(std::size_t num_elements, multiallocation_chain &chain)
|
||||
{
|
||||
BOOST_STATIC_ASSERT(( Version > 1 ));
|
||||
typedef container_detail::shared_node_pool
|
||||
<sizeof(T), NodesPerBlock> shared_pool_t;
|
||||
typedef container_detail::singleton_default<shared_pool_t> singleton_t;
|
||||
typename shared_pool_t::multiallocation_chain ch;
|
||||
singleton_t::instance().allocate_nodes(num_elements, ch);
|
||||
chain.incorporate_after(chain.before_begin(), (T*)&*ch.begin(), (T*)&*ch.last(), ch.size());
|
||||
}
|
||||
|
||||
//!Deallocates memory previously allocated with allocate_one().
|
||||
//!You should never use deallocate_one to deallocate memory allocated
|
||||
//!with other functions different from allocate_one(). Never throws
|
||||
void deallocate_one(pointer p) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{
|
||||
BOOST_STATIC_ASSERT(( Version > 1 ));
|
||||
typedef container_detail::shared_node_pool
|
||||
<sizeof(T), NodesPerBlock> shared_pool_t;
|
||||
typedef container_detail::singleton_default<shared_pool_t> singleton_t;
|
||||
singleton_t::instance().deallocate_node(p);
|
||||
}
|
||||
|
||||
void deallocate_individual(multiallocation_chain &chain) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{
|
||||
BOOST_STATIC_ASSERT(( Version > 1 ));
|
||||
typedef container_detail::shared_node_pool
|
||||
<sizeof(T), NodesPerBlock> shared_pool_t;
|
||||
typedef container_detail::singleton_default<shared_pool_t> singleton_t;
|
||||
typename shared_pool_t::multiallocation_chain ch(&*chain.begin(), &*chain.last(), chain.size());
|
||||
singleton_t::instance().deallocate_nodes(ch);
|
||||
}
|
||||
|
||||
//!Allocates many elements of size elem_size.
|
||||
//!Elements must be individually deallocated with deallocate()
|
||||
void allocate_many(size_type elem_size, std::size_t n_elements, multiallocation_chain &chain)
|
||||
{
|
||||
BOOST_STATIC_ASSERT(( Version > 1 ));
|
||||
dlmalloc_memchain ch;
|
||||
BOOST_CONTAINER_MEMCHAIN_INIT(&ch);
|
||||
if(BOOST_UNLIKELY(!dlmalloc_multialloc_nodes(n_elements, elem_size*sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &ch))){
|
||||
boost::container::throw_bad_alloc();
|
||||
}
|
||||
chain.incorporate_after( chain.before_begin()
|
||||
, (T*)BOOST_CONTAINER_MEMCHAIN_LASTMEM(&ch)
|
||||
, (T*)BOOST_CONTAINER_MEMCHAIN_LASTMEM(&ch)
|
||||
, BOOST_CONTAINER_MEMCHAIN_SIZE(&ch));
|
||||
}
|
||||
|
||||
//!Allocates n_elements elements, each one of size elem_sizes[i]
|
||||
//!Elements must be individually deallocated with deallocate()
|
||||
void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain)
|
||||
{
|
||||
BOOST_STATIC_ASSERT(( Version > 1 ));
|
||||
dlmalloc_memchain ch;
|
||||
dlmalloc_multialloc_arrays(n_elements, elem_sizes, sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &ch);
|
||||
if(BOOST_UNLIKELY(BOOST_CONTAINER_MEMCHAIN_EMPTY(&ch))){
|
||||
boost::container::throw_bad_alloc();
|
||||
}
|
||||
chain.incorporate_after( chain.before_begin()
|
||||
, (T*)BOOST_CONTAINER_MEMCHAIN_LASTMEM(&ch)
|
||||
, (T*)BOOST_CONTAINER_MEMCHAIN_LASTMEM(&ch)
|
||||
, BOOST_CONTAINER_MEMCHAIN_SIZE(&ch));
|
||||
}
|
||||
|
||||
void deallocate_many(multiallocation_chain &chain) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{
|
||||
BOOST_STATIC_ASSERT(( Version > 1 ));
|
||||
void *first = &*chain.begin();
|
||||
void *last = &*chain.last();
|
||||
size_t num = chain.size();
|
||||
dlmalloc_memchain ch;
|
||||
BOOST_CONTAINER_MEMCHAIN_INIT_FROM(&ch, first, last, num);
|
||||
dlmalloc_multidealloc(&ch);
|
||||
}
|
||||
|
||||
//!Swaps allocators. Does not throw. If each allocator is placed in a
|
||||
//!different memory segment, the result is undefined.
|
||||
friend void swap(self_t &, self_t &) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{}
|
||||
|
||||
//!An allocator always compares to true, as memory allocated with one
|
||||
//!instance can be deallocated by another instance
|
||||
friend bool operator==(const node_allocator &, const node_allocator &) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return true; }
|
||||
|
||||
//!An allocator always compares to false, as memory allocated with one
|
||||
//!instance can be deallocated by another instance
|
||||
friend bool operator!=(const node_allocator &, const node_allocator &) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return false; }
|
||||
|
||||
private:
|
||||
pointer priv_allocation_command
|
||||
(allocation_type command, std::size_t limit_size
|
||||
,size_type &prefer_in_recvd_out_size
|
||||
,pointer &reuse)
|
||||
{
|
||||
std::size_t const preferred_size = prefer_in_recvd_out_size;
|
||||
dlmalloc_command_ret_t ret = {0 , 0};
|
||||
if((limit_size > this->max_size()) | (preferred_size > this->max_size())){
|
||||
return pointer();
|
||||
}
|
||||
std::size_t l_size = limit_size*sizeof(T);
|
||||
std::size_t p_size = preferred_size*sizeof(T);
|
||||
std::size_t r_size;
|
||||
{
|
||||
void* reuse_ptr_void = reuse;
|
||||
ret = dlmalloc_allocation_command(command, sizeof(T), l_size, p_size, &r_size, reuse_ptr_void);
|
||||
reuse = static_cast<T*>(reuse_ptr_void);
|
||||
}
|
||||
prefer_in_recvd_out_size = r_size/sizeof(T);
|
||||
return (pointer)ret.first;
|
||||
}
|
||||
};
|
||||
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_POOLED_NODE_ALLOCATOR_HPP
|
||||
@@ -0,0 +1,399 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2016-2016. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_NODE_HANDLE_HPP
|
||||
#define BOOST_CONTAINER_NODE_HANDLE_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/detail/config_begin.hpp>
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/container/detail/placement_new.hpp>
|
||||
#include <boost/container/detail/to_raw_pointer.hpp>
|
||||
#include <boost/container/allocator_traits.hpp>
|
||||
#include <boost/container/detail/mpl.hpp>
|
||||
|
||||
#include <boost/move/utility_core.hpp>
|
||||
#include <boost/move/adl_move_swap.hpp>
|
||||
|
||||
#include <boost/type_traits/aligned_storage.hpp>
|
||||
|
||||
|
||||
//!\file
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
|
||||
///@cond
|
||||
|
||||
template<class Value, class KeyMapped, bool keymapped_is_void = container_detail::is_same<KeyMapped, void>::value>
|
||||
struct node_handle_keymapped_traits
|
||||
{
|
||||
typedef Value key_type;
|
||||
typedef Value mapped_type;
|
||||
};
|
||||
|
||||
template<class Value, class KeyMapped>
|
||||
struct node_handle_keymapped_traits<Value, KeyMapped, false>
|
||||
{
|
||||
typedef typename KeyMapped::key_type key_type;
|
||||
typedef typename KeyMapped::mapped_type mapped_type;
|
||||
};
|
||||
|
||||
///@endcond
|
||||
|
||||
//! A node_handle is an object that accepts ownership of a single element from an associative container.
|
||||
//! It may be used to transfer that ownership to another container with compatible nodes. Containers
|
||||
//! with compatible nodes have the same node handle type. Elements may be transferred in either direction
|
||||
//! between container types in the same row:.
|
||||
//!
|
||||
//! Container types with compatible nodes
|
||||
//!
|
||||
//! map<K, T, C1, A> <-> map<K, T, C2, A>
|
||||
//!
|
||||
//! map<K, T, C1, A> <-> multimap<K, T, C2, A>
|
||||
//!
|
||||
//! set<K, C1, A> <-> set<K, C2, A>
|
||||
//!
|
||||
//! set<K, C1, A> <-> multiset<K, C2, A>
|
||||
//!
|
||||
//! If a node handle is not empty, then it contains an allocator that is equal to the allocator of the container
|
||||
//! when the element was extracted. If a node handle is empty, it contains no allocator.
|
||||
template <class NodeType, class Value, class Allocator, class KeyMapped = void>
|
||||
class node_handle
|
||||
{
|
||||
typedef node_handle_keymapped_traits<Value, KeyMapped> keymapped_t;
|
||||
|
||||
public:
|
||||
typedef Value value_type;
|
||||
typedef typename keymapped_t::key_type key_type;
|
||||
typedef typename keymapped_t::mapped_type mapped_type;
|
||||
typedef Allocator allocator_type;
|
||||
typedef NodeType container_node_type;
|
||||
|
||||
///@cond
|
||||
private:
|
||||
BOOST_MOVABLE_BUT_NOT_COPYABLE(node_handle)
|
||||
|
||||
typedef allocator_traits<allocator_type> ator_traits;
|
||||
typedef typename ator_traits::template portable_rebind_alloc
|
||||
<container_node_type>::type nallocator_type;
|
||||
typedef allocator_traits<nallocator_type> node_ator_traits;
|
||||
typedef typename node_ator_traits::pointer node_pointer;
|
||||
typedef ::boost::aligned_storage
|
||||
<sizeof(allocator_type), boost::alignment_of<nallocator_type>::value> nalloc_storage_t;
|
||||
|
||||
node_pointer m_ptr;
|
||||
nalloc_storage_t m_nalloc_storage;
|
||||
|
||||
void move_construct_alloc(nallocator_type &al)
|
||||
{ ::new(m_nalloc_storage.address(), boost_container_new_t()) allocator_type(::boost::move(al)); }
|
||||
|
||||
void destroy_node()
|
||||
{
|
||||
node_ator_traits::destroy(this->node_alloc(), container_detail::to_raw_pointer(m_ptr));
|
||||
node_ator_traits::deallocate(this->node_alloc(), m_ptr, 1u);
|
||||
}
|
||||
|
||||
template<class OtherNodeHandle>
|
||||
void move_construct_end(OtherNodeHandle &nh)
|
||||
{
|
||||
if(m_ptr){
|
||||
::new (m_nalloc_storage.address(), boost_container_new_t()) allocator_type(::boost::move(nh.node_alloc()));
|
||||
nh.destroy_alloc();
|
||||
nh.get_node_pointer() = node_pointer();
|
||||
}
|
||||
BOOST_ASSERT(nh.empty());
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
void destroy_alloc()
|
||||
{ static_cast<allocator_type*>(m_nalloc_storage.address())->~allocator_type(); }
|
||||
|
||||
node_pointer &get_node_pointer()
|
||||
{ return m_ptr; }
|
||||
|
||||
nallocator_type &node_alloc()
|
||||
{ return *static_cast<nallocator_type*>(m_nalloc_storage.address()); }
|
||||
|
||||
const nallocator_type &node_alloc() const
|
||||
{ return *static_cast<const nallocator_type*>(m_nalloc_storage.address()); }
|
||||
|
||||
node_pointer release()
|
||||
{
|
||||
node_pointer p(m_ptr);
|
||||
m_ptr = node_pointer();
|
||||
if(p)
|
||||
this->destroy_alloc();
|
||||
return p;
|
||||
}
|
||||
|
||||
///@endcond
|
||||
|
||||
public:
|
||||
//! <b>Effects</b>: Initializes m_ptr to nullptr.
|
||||
//!
|
||||
//! <b>Postcondition</b>: this->empty()
|
||||
BOOST_CXX14_CONSTEXPR node_handle() BOOST_NOEXCEPT
|
||||
: m_ptr(), m_nalloc_storage()
|
||||
{ BOOST_ASSERT(this->empty()); }
|
||||
|
||||
//! <b>Effects</b>: Constructs a node_handle object initializing internal pointer with p.
|
||||
//! If p != nullptr copy constructs internal allocator al.
|
||||
node_handle(node_pointer p, const nallocator_type &al) BOOST_NOEXCEPT
|
||||
: m_ptr(p), m_nalloc_storage()
|
||||
{
|
||||
if(m_ptr){
|
||||
::new (m_nalloc_storage.address(), boost_container_new_t()) nallocator_type(al);
|
||||
}
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Constructs a node_handle object initializing internal pointer with a related nh's internal pointer
|
||||
//! and assigns nullptr to the later. If nh's internal pointer was not nullptr, move constructs internal
|
||||
//! allocator with nh's internal allocator and destroy nh's internal allocator.
|
||||
//!
|
||||
//! <b>Postcondition</b>: nh.empty()
|
||||
//!
|
||||
//! <b>Note</b>: Two node_handle's are related if only one of KeyMapped template parameter
|
||||
//! of a node handle is void.
|
||||
template<class KeyMapped2>
|
||||
node_handle( BOOST_RV_REF_BEG node_handle<NodeType, Value, Allocator, KeyMapped2> BOOST_RV_REF_END nh
|
||||
, typename container_detail::enable_if_c
|
||||
< ((unsigned)container_detail::is_same<KeyMapped, void>::value +
|
||||
(unsigned)container_detail::is_same<KeyMapped2, void>::value) == 1u
|
||||
>::type* = 0)
|
||||
: m_ptr(nh.get_node_pointer()), m_nalloc_storage()
|
||||
{ this->move_construct_end(nh); }
|
||||
|
||||
//! <b>Effects</b>: Constructs a node_handle object initializing internal pointer with nh's internal pointer
|
||||
//! and assigns nullptr to the later. If nh's internal pointer was not nullptr, move constructs internal
|
||||
//! allocator with nh's internal allocator and destroy nh's internal allocator.
|
||||
//!
|
||||
//! <b>Postcondition</b>: nh.empty()
|
||||
node_handle (BOOST_RV_REF(node_handle) nh) BOOST_NOEXCEPT
|
||||
: m_ptr(nh.m_ptr), m_nalloc_storage()
|
||||
{ this->move_construct_end(nh); }
|
||||
|
||||
//! <b>Effects</b>: If !this->empty(), destroys the value_type subobject in the container_node_type object
|
||||
//! pointed to by c by calling allocator_traits<impl_defined>::destroy, then deallocates m_ptr by calling
|
||||
//! ator_traits::rebind_traits<container_node_type>::deallocate.
|
||||
~node_handle () BOOST_NOEXCEPT
|
||||
{
|
||||
if(!this->empty()){
|
||||
this->destroy_node();
|
||||
this->destroy_alloc();
|
||||
}
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: Either this->empty(), or ator_traits::propagate_on_container_move_assignment is true, or
|
||||
//! node_alloc() == nh.node_alloc().
|
||||
//!
|
||||
//! <b>Effects</b>: If m_ptr != nullptr, destroys the value_type subobject in the container_node_type object
|
||||
//! pointed to by m_ptr by calling ator_traits::destroy, then deallocates m_ptr by calling ator_-
|
||||
//! traits::rebind_traits<container_node_type>::deallocate. Assigns nh.m_ptr to m_ptr. If this->empty()
|
||||
//! or ator_traits::propagate_on_container_move_assignment is true, move assigns nh.node_alloc() to
|
||||
//! node_alloc(). Assigns nullptr to nh.m_ptr and assigns nullopt to nh.node_alloc().
|
||||
//! <b>Returns</b>: *this.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
node_handle & operator=(BOOST_RV_REF(node_handle) nh)
|
||||
{
|
||||
BOOST_ASSERT(this->empty() || nh.empty() || ator_traits::propagate_on_container_move_assignment::value
|
||||
|| ator_traits::equal(node_alloc(), nh.node_alloc()));
|
||||
|
||||
bool const was_this_non_null = !this->empty();
|
||||
bool const was_nh_non_null = !nh.empty();
|
||||
|
||||
if(was_nh_non_null){
|
||||
if(was_this_non_null){
|
||||
this->destroy_node();
|
||||
if(ator_traits::propagate_on_container_move_assignment::value){
|
||||
this->node_alloc() = ::boost::move(nh.node_alloc());
|
||||
}
|
||||
}
|
||||
else{
|
||||
this->move_construct_alloc(nh.node_alloc());
|
||||
}
|
||||
m_ptr = nh.m_ptr;
|
||||
nh.m_ptr = node_pointer();
|
||||
nh.destroy_alloc();
|
||||
}
|
||||
else if(was_this_non_null){
|
||||
this->destroy_node();
|
||||
this->destroy_alloc();
|
||||
m_ptr = node_pointer();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: empty() == false.
|
||||
//!
|
||||
//! <b>Returns</b>: A reference to the value_type subobject in the container_node_type object pointed to by m_ptr
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
value_type& value() const BOOST_NOEXCEPT
|
||||
{
|
||||
BOOST_STATIC_ASSERT((container_detail::is_same<KeyMapped, void>::value));
|
||||
BOOST_ASSERT(!empty());
|
||||
return m_ptr->get_data();
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: empty() == false.
|
||||
//!
|
||||
//! <b>Returns</b>: A non-const reference to the key_type member of the value_type subobject in the
|
||||
//! container_node_type object pointed to by m_ptr.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Requires</b>: Modifying the key through the returned reference is permitted.
|
||||
key_type& key() const BOOST_NOEXCEPT
|
||||
{
|
||||
BOOST_STATIC_ASSERT((!container_detail::is_same<KeyMapped, void>::value));
|
||||
BOOST_ASSERT(!empty());
|
||||
return const_cast<key_type &>(KeyMapped().key_of_value(m_ptr->get_data()));
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: empty() == false.
|
||||
//!
|
||||
//! <b>Returns</b>: A reference to the mapped_type member of the value_type subobject
|
||||
//! in the container_node_type object pointed to by m_ptr
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
mapped_type& mapped() const BOOST_NOEXCEPT
|
||||
{
|
||||
BOOST_STATIC_ASSERT((!container_detail::is_same<KeyMapped, void>::value));
|
||||
BOOST_ASSERT(!empty());
|
||||
return KeyMapped().mapped_of_value(m_ptr->get_data());
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: empty() == false.
|
||||
//!
|
||||
//! <b>Returns</b>: A copy of the internally hold allocator.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
allocator_type get_allocator() const
|
||||
{
|
||||
BOOST_ASSERT(!empty());
|
||||
return this->node_alloc();
|
||||
}
|
||||
|
||||
//! <b>Returns</b>: m_ptr != nullptr.
|
||||
//!
|
||||
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
BOOST_CONTAINER_FORCEINLINE explicit operator bool
|
||||
#else
|
||||
private: struct bool_conversion {int for_bool; int for_arg(); }; typedef int bool_conversion::* explicit_bool_arg;
|
||||
public: BOOST_CONTAINER_FORCEINLINE operator explicit_bool_arg
|
||||
#endif
|
||||
()const BOOST_NOEXCEPT
|
||||
{ return m_ptr ? &bool_conversion::for_bool : explicit_bool_arg(0); }
|
||||
|
||||
//! <b>Returns</b>: m_ptr == nullptr.
|
||||
//!
|
||||
bool empty() const BOOST_NOEXCEPT
|
||||
{
|
||||
return !this->m_ptr;
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: this->empty(), or nh.empty(), or ator_traits::propagate_on_container_swap is true, or
|
||||
//! node_alloc() == nh.node_alloc().
|
||||
//!
|
||||
//! <b>Effects</b>: Calls swap(m_ptr, nh.m_ptr). If this->empty(), or nh.empty(), or ator_traits::propagate_on_-
|
||||
//! container_swap is true calls swap(node_alloc(), nh.node_alloc()).
|
||||
void swap(node_handle &nh)
|
||||
BOOST_NOEXCEPT_IF(ator_traits::propagate_on_container_swap::value || ator_traits::is_always_equal::value)
|
||||
{
|
||||
BOOST_ASSERT(this->empty() || nh.empty() || ator_traits::propagate_on_container_swap::value
|
||||
|| ator_traits::equal(node_alloc(), nh.node_alloc()));
|
||||
|
||||
bool const was_this_non_null = !this->empty();
|
||||
bool const was_nh_non_null = !nh.empty();
|
||||
|
||||
if(was_nh_non_null){
|
||||
if(was_this_non_null){
|
||||
if(ator_traits::propagate_on_container_swap::value){
|
||||
::boost::adl_move_swap(this->node_alloc(), nh.node_alloc());
|
||||
}
|
||||
}
|
||||
else{
|
||||
this->move_construct_alloc(nh.node_alloc());
|
||||
nh.destroy_alloc();
|
||||
}
|
||||
}
|
||||
else if(was_this_non_null){
|
||||
nh.move_construct_alloc(this->node_alloc());
|
||||
nh.destroy_alloc();
|
||||
}
|
||||
::boost::adl_move_swap(m_ptr, nh.m_ptr);
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: x.swap(y).
|
||||
//!
|
||||
friend void swap(node_handle & x, node_handle & y) BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT(x.swap(y)))
|
||||
{ x.swap(y); }
|
||||
};
|
||||
|
||||
//! A class template used to describe the results of inserting a
|
||||
//! Container::node_type in a Container with unique keys.
|
||||
//! Includes at least the following non-static public data members:
|
||||
//!
|
||||
//! <ul><li>bool inserted</li>;
|
||||
//! <li>Iterator position</li>;
|
||||
//! <li>NodeType node</li></ul>
|
||||
//!
|
||||
//! This type is MoveConstructible, MoveAssignable, DefaultConstructible,
|
||||
//! Destructible, and lvalues of that type are swappable
|
||||
template<class Iterator, class NodeType>
|
||||
struct insert_return_type_base
|
||||
{
|
||||
private:
|
||||
BOOST_MOVABLE_BUT_NOT_COPYABLE(insert_return_type_base)
|
||||
|
||||
public:
|
||||
insert_return_type_base()
|
||||
: inserted(false), position(), node()
|
||||
{}
|
||||
|
||||
insert_return_type_base(BOOST_RV_REF(insert_return_type_base) other)
|
||||
: inserted(other.inserted), position(other.position), node(boost::move(other.node))
|
||||
{}
|
||||
|
||||
template<class RelatedIt, class RelatedNode>
|
||||
insert_return_type_base(bool insert, RelatedIt it, BOOST_RV_REF(RelatedNode) node)
|
||||
: inserted(insert), position(it), node(boost::move(node))
|
||||
{}
|
||||
|
||||
insert_return_type_base & operator=(BOOST_RV_REF(insert_return_type_base) other)
|
||||
{
|
||||
inserted = other.inserted;
|
||||
position = other.position;
|
||||
node = boost::move(other.node);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool inserted;
|
||||
Iterator position;
|
||||
NodeType node;
|
||||
};
|
||||
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_CONTAINER_NODE_HANDLE_HPP
|
||||
@@ -0,0 +1,80 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2013-2013
|
||||
//
|
||||
// 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/container for documentation.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_OPTIONS_HPP
|
||||
#define BOOST_CONTAINER_OPTIONS_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/detail/config_begin.hpp>
|
||||
#include <boost/container/container_fwd.hpp>
|
||||
#include <boost/intrusive/pack_options.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
|
||||
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
|
||||
template<tree_type_enum TreeType, bool OptimizeSize>
|
||||
struct tree_opt
|
||||
{
|
||||
static const boost::container::tree_type_enum tree_type = TreeType;
|
||||
static const bool optimize_size = OptimizeSize;
|
||||
};
|
||||
|
||||
#endif //!defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
|
||||
//!This option setter specifies the underlying tree type
|
||||
//!(red-black, AVL, Scapegoat or Splay) for ordered associative containers
|
||||
BOOST_INTRUSIVE_OPTION_CONSTANT(tree_type, tree_type_enum, TreeType, tree_type)
|
||||
|
||||
//!This option setter specifies if node size is optimized
|
||||
//!storing rebalancing data masked into pointers for ordered associative containers
|
||||
BOOST_INTRUSIVE_OPTION_CONSTANT(optimize_size, bool, Enabled, optimize_size)
|
||||
|
||||
//! Helper metafunction to combine options into a single type to be used
|
||||
//! by \c boost::container::set, \c boost::container::multiset
|
||||
//! \c boost::container::map and \c boost::container::multimap.
|
||||
//! Supported options are: \c boost::container::optimize_size and \c boost::container::tree_type
|
||||
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) || defined(BOOST_CONTAINER_VARIADIC_TEMPLATES)
|
||||
template<class ...Options>
|
||||
#else
|
||||
template<class O1 = void, class O2 = void, class O3 = void, class O4 = void>
|
||||
#endif
|
||||
struct tree_assoc_options
|
||||
{
|
||||
/// @cond
|
||||
typedef typename ::boost::intrusive::pack_options
|
||||
< tree_assoc_defaults,
|
||||
#if !defined(BOOST_CONTAINER_VARIADIC_TEMPLATES)
|
||||
O1, O2, O3, O4
|
||||
#else
|
||||
Options...
|
||||
#endif
|
||||
>::type packed_options;
|
||||
typedef tree_opt<packed_options::tree_type, packed_options::optimize_size> implementation_defined;
|
||||
/// @endcond
|
||||
typedef implementation_defined type;
|
||||
};
|
||||
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_OPTIONS_HPP
|
||||
@@ -0,0 +1,45 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_PMR_DEQUE_HPP
|
||||
#define BOOST_CONTAINER_PMR_DEQUE_HPP
|
||||
|
||||
#if defined (_MSC_VER)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/deque.hpp>
|
||||
#include <boost/container/pmr/polymorphic_allocator.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace pmr {
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
|
||||
|
||||
template <class T>
|
||||
using deque = boost::container::deque<T, polymorphic_allocator<T>>;
|
||||
|
||||
#endif
|
||||
|
||||
//! A portable metafunction to obtain a deque
|
||||
//! that uses a polymorphic allocator
|
||||
template<class T>
|
||||
struct deque_of
|
||||
{
|
||||
typedef boost::container::deque
|
||||
< T, polymorphic_allocator<T> > type;
|
||||
};
|
||||
|
||||
} //namespace pmr {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //BOOST_CONTAINER_PMR_DEQUE_HPP
|
||||
@@ -0,0 +1,67 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_PMR_FLAT_MAP_HPP
|
||||
#define BOOST_CONTAINER_PMR_FLAT_MAP_HPP
|
||||
|
||||
#if defined (_MSC_VER)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/flat_map.hpp>
|
||||
#include <boost/container/pmr/polymorphic_allocator.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace pmr {
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
|
||||
|
||||
template <class Key
|
||||
,class T
|
||||
,class Compare = std::less<Key>
|
||||
,class Options = tree_assoc_defaults >
|
||||
using flat_map = boost::container::flat_map<Key, T, Compare, polymorphic_allocator<std::pair<Key, T> > >;
|
||||
|
||||
template <class Key
|
||||
,class T
|
||||
,class Compare = std::less<Key>
|
||||
,class Options = tree_assoc_defaults >
|
||||
using flat_multimap = boost::container::flat_multimap<Key, T, Compare, polymorphic_allocator<std::pair<Key, T> > >;
|
||||
|
||||
#endif
|
||||
|
||||
//! A portable metafunction to obtain a flat_map
|
||||
//! that uses a polymorphic allocator
|
||||
template <class Key
|
||||
,class T
|
||||
,class Compare = std::less<Key>
|
||||
,class Options = tree_assoc_defaults >
|
||||
struct flat_map_of
|
||||
{
|
||||
typedef boost::container::flat_map<Key, T, Compare, polymorphic_allocator<std::pair<Key, T> > > type;
|
||||
};
|
||||
|
||||
//! A portable metafunction to obtain a flat_multimap
|
||||
//! that uses a polymorphic allocator
|
||||
template <class Key
|
||||
,class T
|
||||
,class Compare = std::less<Key>
|
||||
,class Options = tree_assoc_defaults >
|
||||
struct flat_multimap_of
|
||||
{
|
||||
typedef boost::container::flat_multimap<Key, T, Compare, polymorphic_allocator<std::pair<Key, T> > > type;
|
||||
};
|
||||
|
||||
} //namespace pmr {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //BOOST_CONTAINER_PMR_FLAT_MAP_HPP
|
||||
@@ -0,0 +1,63 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_PMR_SET_HPP
|
||||
#define BOOST_CONTAINER_PMR_SET_HPP
|
||||
|
||||
#if defined (_MSC_VER)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/flat_set.hpp>
|
||||
#include <boost/container/pmr/polymorphic_allocator.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace pmr {
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
|
||||
|
||||
template <class Key
|
||||
,class Compare = std::less<Key>
|
||||
,class Options = tree_assoc_defaults >
|
||||
using flat_set = boost::container::flat_set<Key, Compare, polymorphic_allocator<Key> >;
|
||||
|
||||
template <class Key
|
||||
,class Compare = std::less<Key>
|
||||
,class Options = tree_assoc_defaults >
|
||||
using flat_multiset = boost::container::flat_multiset<Key, Compare, polymorphic_allocator<Key> >;
|
||||
|
||||
#endif
|
||||
|
||||
//! A portable metafunction to obtain a flat_set
|
||||
//! that uses a polymorphic allocator
|
||||
template <class Key
|
||||
,class Compare = std::less<Key>
|
||||
,class Options = tree_assoc_defaults >
|
||||
struct flat_set_of
|
||||
{
|
||||
typedef boost::container::flat_set<Key, Compare, polymorphic_allocator<Key> > type;
|
||||
};
|
||||
|
||||
//! A portable metafunction to obtain a flat_multiset
|
||||
//! that uses a polymorphic allocator
|
||||
template <class Key
|
||||
,class Compare = std::less<Key>
|
||||
,class Options = tree_assoc_defaults >
|
||||
struct flat_multiset_of
|
||||
{
|
||||
typedef boost::container::flat_multiset<Key, Compare, polymorphic_allocator<Key> > type;
|
||||
};
|
||||
|
||||
} //namespace pmr {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //BOOST_CONTAINER_PMR_SET_HPP
|
||||
@@ -0,0 +1,66 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_PMR_GLOBAL_RESOURCE_HPP
|
||||
#define BOOST_CONTAINER_PMR_GLOBAL_RESOURCE_HPP
|
||||
|
||||
#if defined (_MSC_VER)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/detail/config_begin.hpp>
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
#include <boost/container/detail/auto_link.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace pmr {
|
||||
|
||||
/// @cond
|
||||
class memory_resource;
|
||||
/// @endcond
|
||||
|
||||
//! <b>Returns</b>: A pointer to a static-duration object of a type derived from
|
||||
//! memory_resource that can serve as a resource for allocating memory using
|
||||
//! global `operator new` and global `operator delete`. The same value is returned every time this function
|
||||
//! is called. For return value p and memory resource r, p->is_equal(r) returns &r == p.
|
||||
BOOST_CONTAINER_DECL memory_resource* new_delete_resource() BOOST_NOEXCEPT;
|
||||
|
||||
//! <b>Returns</b>: A pointer to a static-duration object of a type derived from
|
||||
//! memory_resource for which allocate() always throws bad_alloc and for which
|
||||
//! deallocate() has no effect. The same value is returned every time this function
|
||||
//! is called. For return value p and memory resource r, p->is_equal(r) returns &r == p.
|
||||
BOOST_CONTAINER_DECL memory_resource* null_memory_resource() BOOST_NOEXCEPT;
|
||||
|
||||
//! <b>Effects</b>: If r is non-null, sets the value of the default memory resource
|
||||
//! pointer to r, otherwise sets the default memory resource pointer to new_delete_resource().
|
||||
//!
|
||||
//! <b>Postconditions</b>: get_default_resource() == r.
|
||||
//!
|
||||
//! <b>Returns</b>: The previous value of the default memory resource pointer.
|
||||
//!
|
||||
//! <b>Remarks</b>: Calling the set_default_resource and get_default_resource functions shall
|
||||
//! not incur a data race. A call to the set_default_resource function shall synchronize
|
||||
//! with subsequent calls to the set_default_resource and get_default_resource functions.
|
||||
BOOST_CONTAINER_DECL memory_resource* set_default_resource(memory_resource* r) BOOST_NOEXCEPT;
|
||||
|
||||
//! <b>Returns</b>: The current value of the default
|
||||
//! memory resource pointer.
|
||||
BOOST_CONTAINER_DECL memory_resource* get_default_resource() BOOST_NOEXCEPT;
|
||||
|
||||
} //namespace pmr {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_CONTAINER_PMR_GLOBAL_RESOURCE_HPP
|
||||
@@ -0,0 +1,45 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_PMR_LIST_HPP
|
||||
#define BOOST_CONTAINER_PMR_LIST_HPP
|
||||
|
||||
#if defined (_MSC_VER)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/list.hpp>
|
||||
#include <boost/container/pmr/polymorphic_allocator.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace pmr {
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
|
||||
|
||||
template <class T>
|
||||
using list = boost::container::list<T, polymorphic_allocator<T>>;
|
||||
|
||||
#endif
|
||||
|
||||
//! A portable metafunction to obtain a list
|
||||
//! that uses a polymorphic allocator
|
||||
template<class T>
|
||||
struct list_of
|
||||
{
|
||||
typedef boost::container::list
|
||||
< T, polymorphic_allocator<T> > type;
|
||||
};
|
||||
|
||||
} //namespace pmr {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //BOOST_CONTAINER_PMR_VECTOR_HPP
|
||||
@@ -0,0 +1,67 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_PMR_MAP_HPP
|
||||
#define BOOST_CONTAINER_PMR_MAP_HPP
|
||||
|
||||
#if defined (_MSC_VER)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/map.hpp>
|
||||
#include <boost/container/pmr/polymorphic_allocator.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace pmr {
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
|
||||
|
||||
template <class Key
|
||||
,class T
|
||||
,class Compare = std::less<Key>
|
||||
,class Options = tree_assoc_defaults >
|
||||
using map = boost::container::map<Key, T, Compare, polymorphic_allocator<std::pair<const Key, T> >, Options>;
|
||||
|
||||
template <class Key
|
||||
,class T
|
||||
,class Compare = std::less<Key>
|
||||
,class Options = tree_assoc_defaults >
|
||||
using multimap = boost::container::multimap<Key, T, Compare, polymorphic_allocator<std::pair<const Key, T> >, Options>;
|
||||
|
||||
#endif
|
||||
|
||||
//! A portable metafunction to obtain a map
|
||||
//! that uses a polymorphic allocator
|
||||
template <class Key
|
||||
,class T
|
||||
,class Compare = std::less<Key>
|
||||
,class Options = tree_assoc_defaults >
|
||||
struct map_of
|
||||
{
|
||||
typedef boost::container::map<Key, T, Compare, polymorphic_allocator<std::pair<const Key, T> >, Options> type;
|
||||
};
|
||||
|
||||
//! A portable metafunction to obtain a multimap
|
||||
//! that uses a polymorphic allocator
|
||||
template <class Key
|
||||
,class T
|
||||
,class Compare = std::less<Key>
|
||||
,class Options = tree_assoc_defaults >
|
||||
struct multimap_of
|
||||
{
|
||||
typedef boost::container::multimap<Key, T, Compare, polymorphic_allocator<std::pair<const Key, T> >, Options> type;
|
||||
};
|
||||
|
||||
} //namespace pmr {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //BOOST_CONTAINER_PMR_MAP_HPP
|
||||
@@ -0,0 +1,101 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_PMR_MEMORY_RESOURCE_HPP
|
||||
#define BOOST_CONTAINER_PMR_MEMORY_RESOURCE_HPP
|
||||
|
||||
#if defined (_MSC_VER)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/detail/config_begin.hpp>
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
#include <boost/move/detail/type_traits.hpp>
|
||||
#include <cstddef>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace pmr {
|
||||
|
||||
//! The memory_resource class is an abstract interface to an
|
||||
//! unbounded set of classes encapsulating memory resources.
|
||||
class memory_resource
|
||||
{
|
||||
public:
|
||||
// For exposition only
|
||||
static BOOST_CONSTEXPR_OR_CONST std::size_t max_align =
|
||||
boost::move_detail::alignment_of<boost::move_detail::max_align_t>::value;
|
||||
|
||||
//! <b>Effects</b>: Destroys
|
||||
//! this memory_resource.
|
||||
virtual ~memory_resource(){}
|
||||
|
||||
//! <b>Effects</b>: Equivalent to
|
||||
//! `return do_allocate(bytes, alignment);`
|
||||
void* allocate(std::size_t bytes, std::size_t alignment = max_align)
|
||||
{ return this->do_allocate(bytes, alignment); }
|
||||
|
||||
//! <b>Effects</b>: Equivalent to
|
||||
//! `return do_deallocate(bytes, alignment);`
|
||||
void deallocate(void* p, std::size_t bytes, std::size_t alignment = max_align)
|
||||
{ return this->do_deallocate(p, bytes, alignment); }
|
||||
|
||||
//! <b>Effects</b>: Equivalent to
|
||||
//! `return return do_is_equal(other);`
|
||||
bool is_equal(const memory_resource& other) const BOOST_NOEXCEPT
|
||||
{ return this->do_is_equal(other); }
|
||||
|
||||
//! <b>Returns</b>:
|
||||
//! `&a == &b || a.is_equal(b)`.
|
||||
friend bool operator==(const memory_resource& a, const memory_resource& b) BOOST_NOEXCEPT
|
||||
{ return &a == &b || a.is_equal(b); }
|
||||
|
||||
//! <b>Returns</b>:
|
||||
//! !(a == b).
|
||||
friend bool operator!=(const memory_resource& a, const memory_resource& b) BOOST_NOEXCEPT
|
||||
{ return !(a == b); }
|
||||
|
||||
protected:
|
||||
//! <b>Requires</b>: Alignment shall be a power of two.
|
||||
//!
|
||||
//! <b>Returns</b>: A derived class shall implement this function to return a pointer
|
||||
//! to allocated storage with a size of at least bytes. The returned storage is
|
||||
//! aligned to the specified alignment, if such alignment is supported; otherwise
|
||||
//! it is aligned to max_align.
|
||||
//!
|
||||
//! <b>Throws</b>: A derived class implementation shall throw an appropriate exception if
|
||||
//! it is unable to allocate memory with the requested size and alignment.
|
||||
virtual void* do_allocate(std::size_t bytes, std::size_t alignment) = 0;
|
||||
|
||||
//! <b>Requires</b>: p shall have been returned from a prior call to
|
||||
//! `allocate(bytes, alignment)` on a memory resource equal to *this, and the storage
|
||||
//! at p shall not yet have been deallocated.
|
||||
//!
|
||||
//! <b>Effects</b>: A derived class shall implement this function to dispose of allocated storage.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
virtual void do_deallocate(void* p, std::size_t bytes, std::size_t alignment) = 0;
|
||||
|
||||
//! <b>Returns</b>: A derived class shall implement this function to return true if memory
|
||||
//! allocated from this can be deallocated from other and vice-versa; otherwise it shall
|
||||
//! return false. <i>[Note: The most-derived type of other might not match the type of this.
|
||||
//! For a derived class, D, a typical implementation of this function will compute
|
||||
//! `dynamic_cast<const D*>(&other)` and go no further (i.e., return false)
|
||||
//! if it returns nullptr. - end note]</i>.
|
||||
virtual bool do_is_equal(const memory_resource& other) const BOOST_NOEXCEPT = 0;
|
||||
};
|
||||
|
||||
} //namespace pmr {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_CONTAINER_PMR_MEMORY_RESOURCE_HPP
|
||||
+180
@@ -0,0 +1,180 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_PMR_MONOTONIC_BUFFER_RESOURCE_HPP
|
||||
#define BOOST_CONTAINER_PMR_MONOTONIC_BUFFER_RESOURCE_HPP
|
||||
|
||||
#if defined (_MSC_VER)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/detail/config_begin.hpp>
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
#include <boost/container/detail/auto_link.hpp>
|
||||
#include <boost/container/pmr/memory_resource.hpp>
|
||||
#include <boost/container/detail/block_slist.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace pmr {
|
||||
|
||||
//! A monotonic_buffer_resource is a special-purpose memory resource intended for
|
||||
//! very fast memory allocations in situations where memory is used to build up a
|
||||
//! few objects and then is released all at once when the memory resource object
|
||||
//! is destroyed. It has the following qualities:
|
||||
//!
|
||||
//! - A call to deallocate has no effect, thus the amount of memory consumed
|
||||
//! increases monotonically until the resource is destroyed.
|
||||
//!
|
||||
//! - The program can supply an initial buffer, which the allocator uses to satisfy
|
||||
//! memory requests.
|
||||
//!
|
||||
//! - When the initial buffer (if any) is exhausted, it obtains additional buffers
|
||||
//! from an upstream memory resource supplied at construction. Each additional
|
||||
//! buffer is larger than the previous one, following a geometric progression.
|
||||
//!
|
||||
//! - It is intended for access from one thread of control at a time. Specifically,
|
||||
//! calls to allocate and deallocate do not synchronize with one another.
|
||||
//!
|
||||
//! - It owns the allocated memory and frees it on destruction, even if deallocate has
|
||||
//! not been called for some of the allocated blocks.
|
||||
class BOOST_CONTAINER_DECL monotonic_buffer_resource
|
||||
: public memory_resource
|
||||
{
|
||||
block_slist m_memory_blocks;
|
||||
void* m_current_buffer;
|
||||
std::size_t m_current_buffer_size;
|
||||
std::size_t m_next_buffer_size;
|
||||
|
||||
/// @cond
|
||||
void increase_next_buffer();
|
||||
void increase_next_buffer_at_least_to(std::size_t minimum_size);
|
||||
void *allocate_from_current(std::size_t aligner, std::size_t bytes);
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
|
||||
//! The number of bytes that will be requested by the default in the first call
|
||||
//! to the upstream allocator
|
||||
//!
|
||||
//! <b>Note</b>: Non-standard extension.
|
||||
static const std::size_t initial_next_buffer_size = 32u*sizeof(void*);
|
||||
|
||||
//! <b>Requires</b>: `upstream` shall be the address of a valid memory resource or `nullptr`
|
||||
//!
|
||||
//! <b>Effects</b>: If `upstream` is not nullptr, sets the internal resource to `upstream`,
|
||||
//! to get_default_resource() otherwise.
|
||||
//! Sets the internal `current_buffer` to `nullptr` and the internal `next_buffer_size` to an
|
||||
//! implementation-defined size.
|
||||
explicit monotonic_buffer_resource(memory_resource* upstream = 0) BOOST_NOEXCEPT;
|
||||
|
||||
//! <b>Requires</b>: `upstream` shall be the address of a valid memory resource or `nullptr`
|
||||
//! and `initial_size` shall be greater than zero.
|
||||
//!
|
||||
//! <b>Effects</b>: If `upstream` is not nullptr, sets the internal resource to `upstream`,
|
||||
//! to get_default_resource() otherwise. Sets the internal `current_buffer` to `nullptr` and
|
||||
//! `next_buffer_size` to at least `initial_size`.
|
||||
explicit monotonic_buffer_resource(std::size_t initial_size, memory_resource* upstream = 0) BOOST_NOEXCEPT;
|
||||
|
||||
//! <b>Requires</b>: `upstream` shall be the address of a valid memory resource or `nullptr`,
|
||||
//! `buffer_size` shall be no larger than the number of bytes in buffer.
|
||||
//!
|
||||
//! <b>Effects</b>: If `upstream` is not nullptr, sets the internal resource to `upstream`,
|
||||
//! to get_default_resource() otherwise. Sets the internal `current_buffer` to `buffer`,
|
||||
//! and `next_buffer_size` to `buffer_size` (but not less than an implementation-defined size),
|
||||
//! then increases `next_buffer_size` by an implementation-defined growth factor (which need not be integral).
|
||||
monotonic_buffer_resource(void* buffer, std::size_t buffer_size, memory_resource* upstream = 0) BOOST_NOEXCEPT;
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
monotonic_buffer_resource(const monotonic_buffer_resource&) = delete;
|
||||
monotonic_buffer_resource operator=(const monotonic_buffer_resource&) = delete;
|
||||
#else
|
||||
private:
|
||||
monotonic_buffer_resource (const monotonic_buffer_resource&);
|
||||
monotonic_buffer_resource operator=(const monotonic_buffer_resource&);
|
||||
public:
|
||||
#endif
|
||||
|
||||
//! <b>Effects</b>: Calls
|
||||
//! `this->release()`.
|
||||
virtual ~monotonic_buffer_resource();
|
||||
|
||||
//! <b>Effects</b>: `upstream_resource()->deallocate()` as necessary to release all allocated memory.
|
||||
//! [Note: memory is released back to `upstream_resource()` even if some blocks that were allocated
|
||||
//! from this have not been deallocated from this. - end note]
|
||||
void release() BOOST_NOEXCEPT;
|
||||
|
||||
//! <b>Returns</b>: The value of
|
||||
//! the internal resource.
|
||||
memory_resource* upstream_resource() const BOOST_NOEXCEPT;
|
||||
|
||||
//! <b>Returns</b>:
|
||||
//! The number of bytes of storage available for the specified alignment and
|
||||
//! the number of bytes wasted due to the requested alignment.
|
||||
//!
|
||||
//! <b>Note</b>: Non-standard extension.
|
||||
std::size_t remaining_storage(std::size_t alignment, std::size_t &wasted_due_to_alignment) const BOOST_NOEXCEPT;
|
||||
|
||||
//! <b>Returns</b>:
|
||||
//! The number of bytes of storage available for the specified alignment.
|
||||
//!
|
||||
//! <b>Note</b>: Non-standard extension.
|
||||
std::size_t remaining_storage(std::size_t alignment = 1u) const BOOST_NOEXCEPT;
|
||||
|
||||
//! <b>Returns</b>:
|
||||
//! The number of bytes of storage available for the specified alignment.
|
||||
//!
|
||||
//! <b>Note</b>: Non-standard extension.
|
||||
const void *current_buffer() const BOOST_NOEXCEPT;
|
||||
|
||||
//! <b>Returns</b>:
|
||||
//! The number of bytes that will be requested for the next buffer once the
|
||||
//! current one is exhausted.
|
||||
//!
|
||||
//! <b>Note</b>: Non-standard extension.
|
||||
std::size_t next_buffer_size() const BOOST_NOEXCEPT;
|
||||
|
||||
protected:
|
||||
|
||||
//! <b>Returns</b>: A pointer to allocated storage with a size of at least `bytes`. The size
|
||||
//! and alignment of the allocated memory shall meet the requirements for a class derived
|
||||
//! from `memory_resource`.
|
||||
//!
|
||||
//! <b>Effects</b>: If the unused space in the internal `current_buffer` can fit a block with the specified
|
||||
//! bytes and alignment, then allocate the return block from the internal `current_buffer`; otherwise sets
|
||||
//! the internal `current_buffer` to `upstream_resource()->allocate(n, m)`, where `n` is not less than
|
||||
//! `max(bytes, next_buffer_size)` and `m` is not less than alignment, and increase
|
||||
//! `next_buffer_size` by an implementation-defined growth factor (which need not be integral),
|
||||
//! then allocate the return block from the newly-allocated internal `current_buffer`.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing unless `upstream_resource()->allocate()` throws.
|
||||
virtual void* do_allocate(std::size_t bytes, std::size_t alignment);
|
||||
|
||||
//! <b>Effects</b>: None
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing
|
||||
//!
|
||||
//! <b>Remarks</b>: Memory used by this resource increases monotonically until its destruction.
|
||||
virtual void do_deallocate(void* p, std::size_t bytes, std::size_t alignment) BOOST_NOEXCEPT;
|
||||
|
||||
//! <b>Returns</b>:
|
||||
//! `this == dynamic_cast<const monotonic_buffer_resource*>(&other)`.
|
||||
virtual bool do_is_equal(const memory_resource& other) const BOOST_NOEXCEPT;
|
||||
};
|
||||
|
||||
} //namespace pmr {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_CONTAINER_PMR_MONOTONIC_BUFFER_RESOURCE_HPP
|
||||
@@ -0,0 +1,166 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_PMR_POLYMORPHIC_ALLOCATOR_HPP
|
||||
#define BOOST_CONTAINER_PMR_POLYMORPHIC_ALLOCATOR_HPP
|
||||
|
||||
#if defined (_MSC_VER)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/move/detail/type_traits.hpp>
|
||||
#include <boost/move/utility_core.hpp>
|
||||
#include <boost/container/detail/dispatch_uses_allocator.hpp>
|
||||
#include <boost/container/new_allocator.hpp>
|
||||
#include <boost/container/pmr/memory_resource.hpp>
|
||||
#include <boost/container/pmr/global_resource.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace pmr {
|
||||
|
||||
//! A specialization of class template `polymorphic_allocator` conforms to the Allocator requirements.
|
||||
//! Constructed with different memory resources, different instances of the same specialization of
|
||||
//! `polymorphic_allocator` can exhibit entirely different allocation behavior. This runtime
|
||||
//! polymorphism allows objects that use polymorphic_allocator to behave as if they used different
|
||||
//! allocator types at run time even though they use the same static allocator type.
|
||||
template <class T>
|
||||
class polymorphic_allocator
|
||||
{
|
||||
public:
|
||||
typedef T value_type;
|
||||
|
||||
//! <b>Effects</b>: Sets m_resource to
|
||||
//! `get_default_resource()`.
|
||||
polymorphic_allocator() BOOST_NOEXCEPT
|
||||
: m_resource(::boost::container::pmr::get_default_resource())
|
||||
{}
|
||||
|
||||
//! <b>Requires</b>: r is non-null.
|
||||
//!
|
||||
//! <b>Effects</b>: Sets m_resource to r.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing
|
||||
//!
|
||||
//! <b>Notes</b>: This constructor provides an implicit conversion from memory_resource*.
|
||||
//! Non-standard extension: if r is null m_resource is set to get_default_resource().
|
||||
polymorphic_allocator(memory_resource* r)
|
||||
: m_resource(r ? r : ::boost::container::pmr::get_default_resource())
|
||||
{}
|
||||
|
||||
//! <b>Effects</b>: Sets m_resource to
|
||||
//! other.resource().
|
||||
polymorphic_allocator(const polymorphic_allocator& other)
|
||||
: m_resource(other.m_resource)
|
||||
{}
|
||||
|
||||
//! <b>Effects</b>: Sets m_resource to
|
||||
//! other.resource().
|
||||
template <class U>
|
||||
polymorphic_allocator(const polymorphic_allocator<U>& other) BOOST_NOEXCEPT
|
||||
: m_resource(other.resource())
|
||||
{}
|
||||
|
||||
//! <b>Effects</b>: Sets m_resource to
|
||||
//! other.resource().
|
||||
polymorphic_allocator& operator=(const polymorphic_allocator& other)
|
||||
{ m_resource = other.m_resource; return *this; }
|
||||
|
||||
//! <b>Returns</b>: Equivalent to
|
||||
//! `static_cast<T*>(m_resource->allocate(n * sizeof(T), alignof(T)))`.
|
||||
T* allocate(size_t n)
|
||||
{ return static_cast<T*>(m_resource->allocate(n*sizeof(T), ::boost::move_detail::alignment_of<T>::value)); }
|
||||
|
||||
//! <b>Requires</b>: p was allocated from a memory resource, x, equal to *m_resource,
|
||||
//! using `x.allocate(n * sizeof(T), alignof(T))`.
|
||||
//!
|
||||
//! <b>Effects</b>: Equivalent to m_resource->deallocate(p, n * sizeof(T), alignof(T)).
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
void deallocate(T* p, size_t n)
|
||||
{ m_resource->deallocate(p, n*sizeof(T), ::boost::move_detail::alignment_of<T>::value); }
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
//! <b>Requires</b>: Uses-allocator construction of T with allocator
|
||||
//! `this->resource()` and constructor arguments `std::forward<Args>(args)...`
|
||||
//! is well-formed. [Note: uses-allocator construction is always well formed for
|
||||
//! types that do not use allocators. - end note]
|
||||
//!
|
||||
//! <b>Effects</b>: Construct a T object at p by uses-allocator construction with allocator
|
||||
//! `this->resource()` and constructor arguments `std::forward<Args>(args)...`.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing unless the constructor for T throws.
|
||||
template < typename U, class ...Args>
|
||||
void construct(U* p, BOOST_FWD_REF(Args)...args)
|
||||
{
|
||||
new_allocator<U> na;
|
||||
container_detail::dispatch_uses_allocator
|
||||
(na, this->resource(), p, ::boost::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
#else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
|
||||
//Disable this overload if the first argument is pair as some compilers have
|
||||
//overload selection problems when the first parameter is a pair.
|
||||
#define BOOST_CONTAINER_PMR_POLYMORPHIC_ALLOCATOR_CONSTRUCT_CODE(N) \
|
||||
template < typename U BOOST_MOVE_I##N BOOST_MOVE_CLASSQ##N >\
|
||||
void construct(U* p BOOST_MOVE_I##N BOOST_MOVE_UREFQ##N)\
|
||||
{\
|
||||
new_allocator<U> na;\
|
||||
container_detail::dispatch_uses_allocator\
|
||||
(na, this->resource(), p BOOST_MOVE_I##N BOOST_MOVE_FWDQ##N);\
|
||||
}\
|
||||
//
|
||||
BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_PMR_POLYMORPHIC_ALLOCATOR_CONSTRUCT_CODE)
|
||||
#undef BOOST_CONTAINER_PMR_POLYMORPHIC_ALLOCATOR_CONSTRUCT_CODE
|
||||
|
||||
#endif //#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
|
||||
//! <b>Effects</b>:
|
||||
//! p->~U().
|
||||
template <class U>
|
||||
void destroy(U* p)
|
||||
{ (void)p; p->~U(); }
|
||||
|
||||
//! <b>Returns</b>: Equivalent to
|
||||
//! `polymorphic_allocator()`.
|
||||
polymorphic_allocator select_on_container_copy_construction() const
|
||||
{ return polymorphic_allocator(); }
|
||||
|
||||
//! <b>Returns</b>:
|
||||
//! m_resource.
|
||||
memory_resource* resource() const
|
||||
{ return m_resource; }
|
||||
|
||||
private:
|
||||
memory_resource* m_resource;
|
||||
};
|
||||
|
||||
//! <b>Returns</b>:
|
||||
//! `*a.resource() == *b.resource()`.
|
||||
template <class T1, class T2>
|
||||
bool operator==(const polymorphic_allocator<T1>& a, const polymorphic_allocator<T2>& b) BOOST_NOEXCEPT
|
||||
{ return *a.resource() == *b.resource(); }
|
||||
|
||||
|
||||
//! <b>Returns</b>:
|
||||
//! `! (a == b)`.
|
||||
template <class T1, class T2>
|
||||
bool operator!=(const polymorphic_allocator<T1>& a, const polymorphic_allocator<T2>& b) BOOST_NOEXCEPT
|
||||
{ return *a.resource() != *b.resource(); }
|
||||
|
||||
} //namespace pmr {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //BOOST_CONTAINER_PMR_POLYMORPHIC_ALLOCATOR_HPP
|
||||
@@ -0,0 +1,52 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_PMR_POOL_OPTIONS_HPP
|
||||
#define BOOST_CONTAINER_PMR_POOL_OPTIONS_HPP
|
||||
|
||||
#if defined (_MSC_VER)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace pmr {
|
||||
|
||||
//! The members of pool_options comprise a set of constructor options for pool resources.
|
||||
//! The effect of each option on the pool resource behavior is described below:
|
||||
//!
|
||||
//! - `std::size_t max_blocks_per_chunk`: The maximum number of blocks that will be allocated
|
||||
//! at once from the upstream memory resource to replenish a pool. If the value of
|
||||
//! `max_blocks_per_chunk` is zero or is greater than an implementation-defined limit,
|
||||
//! that limit is used instead. The implementation may choose to use a smaller value
|
||||
//! than is specified in this field and may use different values for different pools.
|
||||
//!
|
||||
//! - `std::size_t largest_required_pool_block`: The largest allocation size that is required
|
||||
//! to be fulfilled using the pooling mechanism. Attempts to allocate a single block
|
||||
//! larger than this threshold will be allocated directly from the upstream memory
|
||||
//! resource. If largest_required_pool_block is zero or is greater than an
|
||||
//! implementation-defined limit, that limit is used instead. The implementation may
|
||||
//! choose a pass-through threshold larger than specified in this field.
|
||||
struct pool_options
|
||||
{
|
||||
pool_options()
|
||||
: max_blocks_per_chunk(0u), largest_required_pool_block(0u)
|
||||
{}
|
||||
std::size_t max_blocks_per_chunk;
|
||||
std::size_t largest_required_pool_block;
|
||||
};
|
||||
|
||||
} //namespace pmr {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //BOOST_CONTAINER_PMR_POOL_OPTIONS_HPP
|
||||
@@ -0,0 +1,193 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_PMR_RESOURCE_ADAPTOR_HPP
|
||||
#define BOOST_CONTAINER_PMR_RESOURCE_ADAPTOR_HPP
|
||||
|
||||
#if defined (_MSC_VER)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/container/pmr/memory_resource.hpp>
|
||||
#include <boost/container/allocator_traits.hpp>
|
||||
#include <boost/intrusive/detail/ebo_functor_holder.hpp>
|
||||
#include <boost/move/utility_core.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace pmr {
|
||||
|
||||
//! An instance of resource_adaptor<Allocator> is an adaptor that wraps a memory_resource interface
|
||||
//! around Allocator. In order that resource_adaptor<X<T>> and resource_adaptor<X<U>> are the same
|
||||
//! type for any allocator template X and types T and U, resource_adaptor<Allocator> is rendered as
|
||||
//! an alias to this class template such that Allocator is rebound to a char value type in every
|
||||
//! specialization of the class template. The requirements on this class template are defined below.
|
||||
//! In addition to the Allocator requirements, the parameter to resource_adaptor shall meet
|
||||
//! the following additional requirements:
|
||||
//!
|
||||
//! - `typename allocator_traits<Allocator>:: pointer` shall be identical to
|
||||
//! `typename allocator_traits<Allocator>:: value_type*`.
|
||||
//!
|
||||
//! - `typename allocator_traits<Allocator>:: const_pointer` shall be identical to
|
||||
//! `typename allocator_traits<Allocator>:: value_type const*`.
|
||||
//!
|
||||
//! - `typename allocator_traits<Allocator>:: void_pointer` shall be identical to `void*`.
|
||||
//!
|
||||
//! - `typename allocator_traits<Allocator>:: const_void_pointer` shall be identical to `void const*`.
|
||||
template <class Allocator>
|
||||
class resource_adaptor_imp
|
||||
: public memory_resource
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
, private ::boost::intrusive::detail::ebo_functor_holder<Allocator>
|
||||
#endif
|
||||
{
|
||||
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
Allocator m_alloc;
|
||||
#else
|
||||
BOOST_COPYABLE_AND_MOVABLE(resource_adaptor_imp)
|
||||
typedef ::boost::intrusive::detail::ebo_functor_holder<Allocator> ebo_alloc_t;
|
||||
void static_assert_if_not_char_allocator() const
|
||||
{
|
||||
//This class can only be used with allocators type char
|
||||
BOOST_STATIC_ASSERT((container_detail::is_same<typename Allocator::value_type, char>::value));
|
||||
}
|
||||
#endif
|
||||
|
||||
public:
|
||||
typedef Allocator allocator_type;
|
||||
|
||||
//! <b>Effects</b>: Default constructs
|
||||
//! m_alloc.
|
||||
resource_adaptor_imp()
|
||||
{ this->static_assert_if_not_char_allocator(); }
|
||||
|
||||
//! <b>Effects</b>: Copy constructs
|
||||
//! m_alloc.
|
||||
resource_adaptor_imp(const resource_adaptor_imp &other)
|
||||
: ebo_alloc_t(other.ebo_alloc_t::get())
|
||||
{}
|
||||
|
||||
//! <b>Effects</b>: Move constructs
|
||||
//! m_alloc.
|
||||
resource_adaptor_imp(BOOST_RV_REF(resource_adaptor_imp) other)
|
||||
: ebo_alloc_t(::boost::move(other.get()))
|
||||
{}
|
||||
|
||||
//! <b>Effects</b>: Initializes m_alloc with
|
||||
//! a2.
|
||||
explicit resource_adaptor_imp(const Allocator& a2)
|
||||
: ebo_alloc_t(a2)
|
||||
{ this->static_assert_if_not_char_allocator(); }
|
||||
|
||||
//! <b>Effects</b>: Initializes m_alloc with
|
||||
//! a2.
|
||||
explicit resource_adaptor_imp(BOOST_RV_REF(Allocator) a2)
|
||||
: ebo_alloc_t(::boost::move(a2))
|
||||
{ this->static_assert_if_not_char_allocator(); }
|
||||
|
||||
//! <b>Effects</b>: Copy assigns
|
||||
//! m_alloc.
|
||||
resource_adaptor_imp& operator=(BOOST_COPY_ASSIGN_REF(resource_adaptor_imp) other)
|
||||
{ this->ebo_alloc_t::get() = other.ebo_alloc_t::get(); return *this; }
|
||||
|
||||
//! <b>Effects</b>: Move assigns
|
||||
//! m_alloc.
|
||||
resource_adaptor_imp& operator=(BOOST_RV_REF(resource_adaptor_imp) other)
|
||||
{ this->ebo_alloc_t::get() = ::boost::move(other.ebo_alloc_t::get()); return *this; }
|
||||
|
||||
//! <b>Effects</b>: Returns m_alloc.
|
||||
allocator_type &get_allocator()
|
||||
{ return this->ebo_alloc_t::get(); }
|
||||
|
||||
//! <b>Effects</b>: Returns m_alloc.
|
||||
const allocator_type &get_allocator() const
|
||||
{ return this->ebo_alloc_t::get(); }
|
||||
|
||||
protected:
|
||||
//! <b>Returns</b>: Allocated memory obtained by calling m_alloc.allocate. The size and alignment
|
||||
//! of the allocated memory shall meet the requirements for a class derived from memory_resource.
|
||||
virtual void* do_allocate(size_t bytes, size_t alignment)
|
||||
{ (void)alignment; return this->ebo_alloc_t::get().allocate(bytes); }
|
||||
|
||||
//! <b>Requires</b>: p was previously allocated using A.allocate, where A == m_alloc, and not
|
||||
//! subsequently deallocated.
|
||||
//!
|
||||
//! <b>Effects</b>: Returns memory to the allocator using m_alloc.deallocate().
|
||||
virtual void do_deallocate(void* p, size_t bytes, size_t alignment)
|
||||
{ (void)alignment; this->ebo_alloc_t::get().deallocate((char*)p, bytes); }
|
||||
|
||||
//! Let p be dynamic_cast<const resource_adaptor_imp*>(&other).
|
||||
//!
|
||||
//! <b>Returns</b>: false if p is null, otherwise the value of m_alloc == p->m_alloc.
|
||||
virtual bool do_is_equal(const memory_resource& other) const BOOST_NOEXCEPT
|
||||
{
|
||||
const resource_adaptor_imp* p = dynamic_cast<const resource_adaptor_imp*>(&other);
|
||||
return p && p->ebo_alloc_t::get() == this->ebo_alloc_t::get();
|
||||
}
|
||||
};
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
|
||||
//! `resource_adaptor<Allocator>` is rendered as an alias to resource_adaptor_imp class template
|
||||
//! such that Allocator is rebound to a char value type.
|
||||
template <class Allocator>
|
||||
using resource_adaptor = resource_adaptor_imp
|
||||
<typename allocator_traits<Allocator>::template rebind_alloc<char> >;
|
||||
|
||||
#else
|
||||
|
||||
template <class Allocator>
|
||||
class resource_adaptor
|
||||
: public resource_adaptor_imp
|
||||
<typename allocator_traits<Allocator>::template portable_rebind_alloc<char>::type>
|
||||
{
|
||||
typedef resource_adaptor_imp
|
||||
<typename allocator_traits<Allocator>::template portable_rebind_alloc<char>::type> base_t;
|
||||
|
||||
BOOST_COPYABLE_AND_MOVABLE(resource_adaptor)
|
||||
|
||||
public:
|
||||
resource_adaptor()
|
||||
: base_t()
|
||||
{}
|
||||
|
||||
resource_adaptor(const resource_adaptor &other)
|
||||
: base_t(other)
|
||||
{}
|
||||
|
||||
resource_adaptor(BOOST_RV_REF(resource_adaptor) other)
|
||||
: base_t(BOOST_MOVE_BASE(base_t, other))
|
||||
{}
|
||||
|
||||
explicit resource_adaptor(const Allocator& a2)
|
||||
: base_t(a2)
|
||||
{}
|
||||
|
||||
explicit resource_adaptor(BOOST_RV_REF(Allocator) a2)
|
||||
: base_t(BOOST_MOVE_BASE(base_t, a2))
|
||||
{}
|
||||
|
||||
resource_adaptor& operator=(BOOST_COPY_ASSIGN_REF(resource_adaptor) other)
|
||||
{ return static_cast<resource_adaptor&>(this->base_t::operator=(other)); }
|
||||
|
||||
resource_adaptor& operator=(BOOST_RV_REF(resource_adaptor) other)
|
||||
{ return static_cast<resource_adaptor&>(this->base_t::operator=(BOOST_MOVE_BASE(base_t, other))); }
|
||||
|
||||
//get_allocator and protected functions are properly inherited
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
} //namespace pmr {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //BOOST_CONTAINER_PMR_RESOURCE_ADAPTOR_HPP
|
||||
@@ -0,0 +1,63 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_PMR_SET_HPP
|
||||
#define BOOST_CONTAINER_PMR_SET_HPP
|
||||
|
||||
#if defined (_MSC_VER)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/set.hpp>
|
||||
#include <boost/container/pmr/polymorphic_allocator.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace pmr {
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
|
||||
|
||||
template <class Key
|
||||
,class Compare = std::less<Key>
|
||||
,class Options = tree_assoc_defaults >
|
||||
using set = boost::container::set<Key, Compare, polymorphic_allocator<Key>, Options>;
|
||||
|
||||
template <class Key
|
||||
,class Compare = std::less<Key>
|
||||
,class Options = tree_assoc_defaults >
|
||||
using multiset = boost::container::multiset<Key, Compare, polymorphic_allocator<Key>, Options>;
|
||||
|
||||
#endif
|
||||
|
||||
//! A portable metafunction to obtain a set
|
||||
//! that uses a polymorphic allocator
|
||||
template <class Key
|
||||
,class Compare = std::less<Key>
|
||||
,class Options = tree_assoc_defaults >
|
||||
struct set_of
|
||||
{
|
||||
typedef boost::container::set<Key, Compare, polymorphic_allocator<Key>, Options> type;
|
||||
};
|
||||
|
||||
//! A portable metafunction to obtain a multiset
|
||||
//! that uses a polymorphic allocator
|
||||
template <class Key
|
||||
,class Compare = std::less<Key>
|
||||
,class Options = tree_assoc_defaults >
|
||||
struct multiset_of
|
||||
{
|
||||
typedef boost::container::multiset<Key, Compare, polymorphic_allocator<Key>, Options> type;
|
||||
};
|
||||
|
||||
} //namespace pmr {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //BOOST_CONTAINER_PMR_SET_HPP
|
||||
@@ -0,0 +1,45 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_PMR_SLIST_HPP
|
||||
#define BOOST_CONTAINER_PMR_SLIST_HPP
|
||||
|
||||
#if defined (_MSC_VER)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/slist.hpp>
|
||||
#include <boost/container/pmr/polymorphic_allocator.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace pmr {
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
|
||||
|
||||
template <class T>
|
||||
using slist = boost::container::slist<T, polymorphic_allocator<T>>;
|
||||
|
||||
#endif
|
||||
|
||||
//! A portable metafunction to obtain a slist
|
||||
//! that uses a polymorphic allocator
|
||||
template<class T>
|
||||
struct slist_of
|
||||
{
|
||||
typedef boost::container::slist
|
||||
< T, polymorphic_allocator<T> > type;
|
||||
};
|
||||
|
||||
} //namespace pmr {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //BOOST_CONTAINER_PMR_VECTOR_HPP
|
||||
@@ -0,0 +1,45 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_PMR_SMALL_VECTOR_HPP
|
||||
#define BOOST_CONTAINER_PMR_SMALL_VECTOR_HPP
|
||||
|
||||
#if defined (_MSC_VER)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/small_vector.hpp>
|
||||
#include <boost/container/pmr/polymorphic_allocator.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace pmr {
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
|
||||
|
||||
template <class T, std::size_t N>
|
||||
using small_vector = boost::container::small_vector<T, N, polymorphic_allocator<T>>;
|
||||
|
||||
#endif
|
||||
|
||||
//! A portable metafunction to obtain a small_vector
|
||||
//! that uses a polymorphic allocator
|
||||
template<class T, std::size_t N>
|
||||
struct small_vector_of
|
||||
{
|
||||
typedef boost::container::small_vector
|
||||
< T, N, polymorphic_allocator<T> > type;
|
||||
};
|
||||
|
||||
} //namespace pmr {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //BOOST_CONTAINER_PMR_SMALL_VECTOR_HPP
|
||||
@@ -0,0 +1,45 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_PMR_STABLE_VECTOR_HPP
|
||||
#define BOOST_CONTAINER_PMR_STABLE_VECTOR_HPP
|
||||
|
||||
#if defined (_MSC_VER)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/stable_vector.hpp>
|
||||
#include <boost/container/pmr/polymorphic_allocator.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace pmr {
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
|
||||
|
||||
template <class T>
|
||||
using stable_vector = boost::container::stable_vector<T, polymorphic_allocator<T>>;
|
||||
|
||||
#endif
|
||||
|
||||
//! A portable metafunction to obtain a stable_vector
|
||||
//! that uses a polymorphic allocator
|
||||
template<class T>
|
||||
struct stable_vector_of
|
||||
{
|
||||
typedef boost::container::stable_vector
|
||||
< T, polymorphic_allocator<T> > type;
|
||||
};
|
||||
|
||||
} //namespace pmr {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //BOOST_CONTAINER_PMR_STABLE_VECTOR_HPP
|
||||
@@ -0,0 +1,50 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_PMR_STRING_HPP
|
||||
#define BOOST_CONTAINER_PMR_STRING_HPP
|
||||
|
||||
#if defined (_MSC_VER)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/string.hpp>
|
||||
#include <boost/container/pmr/polymorphic_allocator.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace pmr {
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
|
||||
|
||||
template <class CharT, class Traits = std::char_traits<CharT> >
|
||||
using basic_string =
|
||||
boost::container::basic_string<CharT, Traits, polymorphic_allocator<CharT> >;
|
||||
|
||||
#endif
|
||||
|
||||
//! A portable metafunction to obtain a basic_string
|
||||
//! that uses a polymorphic allocator
|
||||
template <class CharT, class Traits = std::char_traits<CharT> >
|
||||
struct basic_string_of
|
||||
{
|
||||
typedef boost::container::basic_string
|
||||
<CharT, Traits, polymorphic_allocator<CharT> > type;
|
||||
};
|
||||
|
||||
typedef basic_string_of<char>::type string;
|
||||
|
||||
typedef basic_string_of<wchar_t>::type wstring;
|
||||
|
||||
} //namespace pmr {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //BOOST_CONTAINER_PMR_STRING_HPP
|
||||
+138
@@ -0,0 +1,138 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_PMR_SYNCHRONIZED_POOL_RESOURCE_HPP
|
||||
#define BOOST_CONTAINER_PMR_SYNCHRONIZED_POOL_RESOURCE_HPP
|
||||
|
||||
#if defined (_MSC_VER)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/detail/config_begin.hpp>
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
#include <boost/container/detail/auto_link.hpp>
|
||||
#include <boost/container/pmr/memory_resource.hpp>
|
||||
#include <boost/container/detail/pool_resource.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace pmr {
|
||||
|
||||
//! A synchronized_pool_resource is a general-purpose memory resources having
|
||||
//! the following qualities:
|
||||
//!
|
||||
//! - Each resource owns the allocated memory, and frees it on destruction,
|
||||
//! even if deallocate has not been called for some of the allocated blocks.
|
||||
//!
|
||||
//! - A pool resource consists of a collection of pools, serving
|
||||
//! requests for different block sizes. Each individual pool manages a
|
||||
//! collection of chunks that are in turn divided into blocks of uniform size,
|
||||
//! returned via calls to do_allocate. Each call to do_allocate(size, alignment)
|
||||
//! is dispatched to the pool serving the smallest blocks accommodating at
|
||||
//! least size bytes.
|
||||
//!
|
||||
//! - When a particular pool is exhausted, allocating a block from that pool
|
||||
//! results in the allocation of an additional chunk of memory from the upstream
|
||||
//! allocator (supplied at construction), thus replenishing the pool. With
|
||||
//! each successive replenishment, the chunk size obtained increases
|
||||
//! geometrically. [ Note: By allocating memory in chunks, the pooling strategy
|
||||
//! increases the chance that consecutive allocations will be close together
|
||||
//! in memory. - end note ]
|
||||
//!
|
||||
//! - Allocation requests that exceed the largest block size of any pool are
|
||||
//! fulfilled directly from the upstream allocator.
|
||||
//!
|
||||
//! - A pool_options struct may be passed to the pool resource constructors to
|
||||
//! tune the largest block size and the maximum chunk size.
|
||||
//!
|
||||
//! A synchronized_pool_resource may be accessed from multiple threads without
|
||||
//! external synchronization and may have thread-specific pools to reduce
|
||||
//! synchronization costs.
|
||||
class BOOST_CONTAINER_DECL synchronized_pool_resource
|
||||
: public memory_resource
|
||||
{
|
||||
pool_resource m_pool_resource;
|
||||
void *m_opaque_sync;
|
||||
|
||||
public:
|
||||
|
||||
//! @copydoc ::boost::container::pmr::unsynchronized_pool_resource::unsynchronized_pool_resource(const pool_options&,memory_resource*)
|
||||
synchronized_pool_resource(const pool_options& opts, memory_resource* upstream) BOOST_NOEXCEPT;
|
||||
|
||||
//! @copydoc ::boost::container::pmr::unsynchronized_pool_resource::unsynchronized_pool_resource()
|
||||
synchronized_pool_resource() BOOST_NOEXCEPT;
|
||||
|
||||
//! @copydoc ::boost::container::pmr::unsynchronized_pool_resource::unsynchronized_pool_resource(memory_resource*)
|
||||
explicit synchronized_pool_resource(memory_resource* upstream) BOOST_NOEXCEPT;
|
||||
|
||||
//! @copydoc ::boost::container::pmr::unsynchronized_pool_resource::unsynchronized_pool_resource(const pool_options&)
|
||||
explicit synchronized_pool_resource(const pool_options& opts) BOOST_NOEXCEPT;
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
synchronized_pool_resource(const synchronized_pool_resource&) = delete;
|
||||
synchronized_pool_resource operator=(const synchronized_pool_resource&) = delete;
|
||||
#else
|
||||
private:
|
||||
synchronized_pool_resource (const synchronized_pool_resource&);
|
||||
synchronized_pool_resource operator=(const synchronized_pool_resource&);
|
||||
public:
|
||||
#endif
|
||||
|
||||
//! @copydoc ::boost::container::pmr::unsynchronized_pool_resource::~unsynchronized_pool_resource()
|
||||
virtual ~synchronized_pool_resource();
|
||||
|
||||
//! @copydoc ::boost::container::pmr::unsynchronized_pool_resource::release()
|
||||
void release();
|
||||
|
||||
//! @copydoc ::boost::container::pmr::unsynchronized_pool_resource::upstream_resource()const
|
||||
memory_resource* upstream_resource() const;
|
||||
|
||||
//! @copydoc ::boost::container::pmr::unsynchronized_pool_resource::options()const
|
||||
pool_options options() const;
|
||||
|
||||
protected:
|
||||
|
||||
//! @copydoc ::boost::container::pmr::unsynchronized_pool_resource::do_allocate()
|
||||
virtual void* do_allocate(std::size_t bytes, std::size_t alignment);
|
||||
|
||||
//! @copydoc ::boost::container::pmr::unsynchronized_pool_resource::do_deallocate(void*,std::size_t,std::size_t)
|
||||
virtual void do_deallocate(void* p, std::size_t bytes, std::size_t alignment);
|
||||
|
||||
//! @copydoc ::boost::container::pmr::unsynchronized_pool_resource::do_is_equal(const memory_resource&)const
|
||||
virtual bool do_is_equal(const memory_resource& other) const BOOST_NOEXCEPT;
|
||||
|
||||
//Non-standard observers
|
||||
public:
|
||||
|
||||
//! @copydoc ::boost::container::pmr::unsynchronized_pool_resource::pool_count()
|
||||
std::size_t pool_count() const;
|
||||
|
||||
//! @copydoc ::boost::container::pmr::unsynchronized_pool_resource::pool_index(std::size_t)const
|
||||
std::size_t pool_index(std::size_t bytes) const;
|
||||
|
||||
//! @copydoc ::boost::container::pmr::unsynchronized_pool_resource::pool_next_blocks_per_chunk(std::size_t)const
|
||||
std::size_t pool_next_blocks_per_chunk(std::size_t pool_idx) const;
|
||||
|
||||
//! @copydoc ::boost::container::pmr::unsynchronized_pool_resource::pool_block(std::size_t)const
|
||||
std::size_t pool_block(std::size_t pool_idx) const;
|
||||
|
||||
//! @copydoc ::boost::container::pmr::unsynchronized_pool_resource::pool_cached_blocks(std::size_t)const
|
||||
std::size_t pool_cached_blocks(std::size_t pool_idx) const;
|
||||
};
|
||||
|
||||
} //namespace pmr {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_CONTAINER_PMR_SYNCHRONIZED_POOL_RESOURCE_HPP
|
||||
+194
@@ -0,0 +1,194 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_PMR_UNSYNCHRONIZED_POOL_RESOURCE_HPP
|
||||
#define BOOST_CONTAINER_PMR_UNSYNCHRONIZED_POOL_RESOURCE_HPP
|
||||
|
||||
#if defined (_MSC_VER)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/detail/config_begin.hpp>
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
#include <boost/container/detail/auto_link.hpp>
|
||||
#include <boost/container/pmr/memory_resource.hpp>
|
||||
#include <boost/container/detail/pool_resource.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace pmr {
|
||||
|
||||
//! A unsynchronized_pool_resource is a general-purpose memory resources having
|
||||
//! the following qualities:
|
||||
//!
|
||||
//! - Each resource owns the allocated memory, and frees it on destruction,
|
||||
//! even if deallocate has not been called for some of the allocated blocks.
|
||||
//!
|
||||
//! - A pool resource consists of a collection of pools, serving
|
||||
//! requests for different block sizes. Each individual pool manages a
|
||||
//! collection of chunks that are in turn divided into blocks of uniform size,
|
||||
//! returned via calls to do_allocate. Each call to do_allocate(size, alignment)
|
||||
//! is dispatched to the pool serving the smallest blocks accommodating at
|
||||
//! least size bytes.
|
||||
//!
|
||||
//! - When a particular pool is exhausted, allocating a block from that pool
|
||||
//! results in the allocation of an additional chunk of memory from the upstream
|
||||
//! allocator (supplied at construction), thus replenishing the pool. With
|
||||
//! each successive replenishment, the chunk size obtained increases
|
||||
//! geometrically. [ Note: By allocating memory in chunks, the pooling strategy
|
||||
//! increases the chance that consecutive allocations will be close together
|
||||
//! in memory. - end note ]
|
||||
//!
|
||||
//! - Allocation requests that exceed the largest block size of any pool are
|
||||
//! fulfilled directly from the upstream allocator.
|
||||
//!
|
||||
//! - A pool_options struct may be passed to the pool resource constructors to
|
||||
//! tune the largest block size and the maximum chunk size.
|
||||
//!
|
||||
//! An unsynchronized_pool_resource class may not be accessed from multiple threads
|
||||
//! simultaneously and thus avoids the cost of synchronization entirely in
|
||||
//! single-threaded applications.
|
||||
class BOOST_CONTAINER_DECL unsynchronized_pool_resource
|
||||
: public memory_resource
|
||||
{
|
||||
pool_resource m_resource;
|
||||
|
||||
public:
|
||||
|
||||
//! <b>Requires</b>: `upstream` is the address of a valid memory resource.
|
||||
//!
|
||||
//! <b>Effects</b>: Constructs a pool resource object that will obtain memory
|
||||
//! from upstream whenever the pool resource is unable to satisfy a memory
|
||||
//! request from its own internal data structures. The resulting object will hold
|
||||
//! a copy of upstream, but will not own the resource to which upstream points.
|
||||
//! [ Note: The intention is that calls to upstream->allocate() will be
|
||||
//! substantially fewer than calls to this->allocate() in most cases. - end note
|
||||
//! The behavior of the pooling mechanism is tuned according to the value of
|
||||
//! the opts argument.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing unless upstream->allocate() throws. It is unspecified if
|
||||
//! or under what conditions this constructor calls upstream->allocate().
|
||||
unsynchronized_pool_resource(const pool_options& opts, memory_resource* upstream) BOOST_NOEXCEPT;
|
||||
|
||||
//! <b>Effects</b>: Same as
|
||||
//! `unsynchronized_pool_resource(pool_options(), get_default_resource())`.
|
||||
unsynchronized_pool_resource() BOOST_NOEXCEPT;
|
||||
|
||||
//! <b>Effects</b>: Same as
|
||||
//! `unsynchronized_pool_resource(pool_options(), upstream)`.
|
||||
explicit unsynchronized_pool_resource(memory_resource* upstream) BOOST_NOEXCEPT;
|
||||
|
||||
//! <b>Effects</b>: Same as
|
||||
//! `unsynchronized_pool_resource(opts, get_default_resource())`.
|
||||
explicit unsynchronized_pool_resource(const pool_options& opts) BOOST_NOEXCEPT;
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
unsynchronized_pool_resource(const unsynchronized_pool_resource&) = delete;
|
||||
unsynchronized_pool_resource operator=(const unsynchronized_pool_resource&) = delete;
|
||||
#else
|
||||
private:
|
||||
unsynchronized_pool_resource (const unsynchronized_pool_resource&);
|
||||
unsynchronized_pool_resource operator=(const unsynchronized_pool_resource&);
|
||||
public:
|
||||
#endif
|
||||
|
||||
//! <b>Effects</b>: Calls
|
||||
//! `this->release()`.
|
||||
virtual ~unsynchronized_pool_resource();
|
||||
|
||||
//! <b>Effects</b>: Calls Calls `upstream_resource()->deallocate()` as necessary
|
||||
//! to release all allocated memory. [ Note: memory is released back to
|
||||
//! `upstream_resource()` even if deallocate has not been called for some
|
||||
//! of the allocated blocks. - end note ]
|
||||
void release();
|
||||
|
||||
//! <b>Returns</b>: The value of the upstream argument provided to the
|
||||
//! constructor of this object.
|
||||
memory_resource* upstream_resource() const;
|
||||
|
||||
//! <b>Returns</b>: The options that control the pooling behavior of this resource.
|
||||
//! The values in the returned struct may differ from those supplied to the pool
|
||||
//! resource constructor in that values of zero will be replaced with
|
||||
//! implementation-defined defaults and sizes may be rounded to unspecified granularity.
|
||||
pool_options options() const;
|
||||
|
||||
protected:
|
||||
|
||||
//! <b>Returns</b>: A pointer to allocated storage with a size of at least `bytes`.
|
||||
//! The size and alignment of the allocated memory shall meet the requirements for
|
||||
//! a class derived from `memory_resource`.
|
||||
//!
|
||||
//! <b>Effects</b>: If the pool selected for a block of size bytes is unable to
|
||||
//! satisfy the memory request from its own internal data structures, it will call
|
||||
//! `upstream_resource()->allocate()` to obtain more memory. If `bytes` is larger
|
||||
//! than that which the largest pool can handle, then memory will be allocated
|
||||
//! using `upstream_resource()->allocate()`.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing unless `upstream_resource()->allocate()` throws.
|
||||
virtual void* do_allocate(std::size_t bytes, std::size_t alignment);
|
||||
|
||||
//! <b>Effects</b>: Return the memory at p to the pool. It is unspecified if or under
|
||||
//! what circumstances this operation will result in a call to
|
||||
//! `upstream_resource()->deallocate()`.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
virtual void do_deallocate(void* p, std::size_t bytes, std::size_t alignment);
|
||||
|
||||
//! <b>Returns</b>:
|
||||
//! `this == dynamic_cast<const unsynchronized_pool_resource*>(&other)`.
|
||||
virtual bool do_is_equal(const memory_resource& other) const BOOST_NOEXCEPT;
|
||||
|
||||
//Non-standard observers
|
||||
public:
|
||||
//! <b>Returns</b>: The number of pools that will be used in the pool resource.
|
||||
//!
|
||||
//! <b>Note</b>: Non-standard extension.
|
||||
std::size_t pool_count() const;
|
||||
|
||||
//! <b>Returns</b>: The index of the pool that will be used to serve the allocation of `bytes`.
|
||||
//! Returns `pool_count()` if `bytes` is bigger
|
||||
//! than `options().largest_required_pool_block` (no pool will be used to serve this).
|
||||
//!
|
||||
//! <b>Note</b>: Non-standard extension.
|
||||
std::size_t pool_index(std::size_t bytes) const;
|
||||
|
||||
//! <b>Requires</b>: `pool_idx < pool_index()`
|
||||
//!
|
||||
//! <b>Returns</b>: The number blocks that will be allocated in the next chunk
|
||||
//! from the pool specified by `pool_idx`.
|
||||
//!
|
||||
//! <b>Note</b>: Non-standard extension.
|
||||
std::size_t pool_next_blocks_per_chunk(std::size_t pool_idx) const;
|
||||
|
||||
//! <b>Requires</b>: `pool_idx < pool_index()`
|
||||
//!
|
||||
//! <b>Returns</b>: The number of bytes of the block that the specified `pool_idx` pool manages.
|
||||
//!
|
||||
//! <b>Note</b>: Non-standard extension.
|
||||
std::size_t pool_block(std::size_t pool_idx) const;
|
||||
|
||||
//! <b>Requires</b>: `pool_idx < pool_index()`
|
||||
//!
|
||||
//! <b>Returns</b>: The number of blocks that the specified `pool_idx` pool has cached
|
||||
//! and will be served without calling the upstream_allocator.
|
||||
//!
|
||||
//! <b>Note</b>: Non-standard extension.
|
||||
std::size_t pool_cached_blocks(std::size_t pool_idx) const;
|
||||
};
|
||||
|
||||
} //namespace pmr {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_CONTAINER_PMR_UNSYNCHRONIZED_POOL_RESOURCE_HPP
|
||||
@@ -0,0 +1,45 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_PMR_VECTOR_HPP
|
||||
#define BOOST_CONTAINER_PMR_VECTOR_HPP
|
||||
|
||||
#if defined (_MSC_VER)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/vector.hpp>
|
||||
#include <boost/container/pmr/polymorphic_allocator.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace pmr {
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
|
||||
|
||||
template <class T>
|
||||
using vector = boost::container::vector<T, polymorphic_allocator<T>>;
|
||||
|
||||
#endif
|
||||
|
||||
//! A portable metafunction to obtain a vector
|
||||
//! that uses a polymorphic allocator
|
||||
template<class T>
|
||||
struct vector_of
|
||||
{
|
||||
typedef boost::container::vector
|
||||
< T, polymorphic_allocator<T> > type;
|
||||
};
|
||||
|
||||
} //namespace pmr {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //BOOST_CONTAINER_PMR_VECTOR_HPP
|
||||
@@ -0,0 +1,907 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Pablo Halpern 2009. 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)
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2011-2013. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_ALLOCATOR_SCOPED_ALLOCATOR_HPP
|
||||
#define BOOST_CONTAINER_ALLOCATOR_SCOPED_ALLOCATOR_HPP
|
||||
|
||||
#if defined (_MSC_VER)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/detail/config_begin.hpp>
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
|
||||
#include <boost/container/allocator_traits.hpp>
|
||||
#include <boost/container/scoped_allocator_fwd.hpp>
|
||||
#include <boost/container/detail/dispatch_uses_allocator.hpp>
|
||||
|
||||
#include <boost/container/detail/mpl.hpp>
|
||||
#include <boost/container/detail/pair.hpp>
|
||||
#include <boost/container/detail/type_traits.hpp>
|
||||
|
||||
#include <boost/move/adl_move_swap.hpp>
|
||||
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
#include <boost/move/detail/fwd_macros.hpp>
|
||||
#endif
|
||||
#include <boost/move/utility_core.hpp>
|
||||
|
||||
#include <boost/core/no_exceptions_support.hpp>
|
||||
|
||||
namespace boost { namespace container {
|
||||
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
namespace container_detail {
|
||||
|
||||
template <typename Allocator>
|
||||
struct is_scoped_allocator_imp
|
||||
{
|
||||
typedef char yes_type;
|
||||
struct no_type{ char dummy[2]; };
|
||||
|
||||
template <typename T>
|
||||
static yes_type test(typename T::outer_allocator_type*);
|
||||
|
||||
template <typename T>
|
||||
static int test(...);
|
||||
|
||||
static const bool value = (sizeof(yes_type) == sizeof(test<Allocator>(0)));
|
||||
};
|
||||
|
||||
template<class MaybeScopedAlloc, bool = is_scoped_allocator_imp<MaybeScopedAlloc>::value >
|
||||
struct outermost_allocator_type_impl
|
||||
{
|
||||
typedef typename MaybeScopedAlloc::outer_allocator_type outer_type;
|
||||
typedef typename outermost_allocator_type_impl<outer_type>::type type;
|
||||
};
|
||||
|
||||
template<class MaybeScopedAlloc>
|
||||
struct outermost_allocator_type_impl<MaybeScopedAlloc, false>
|
||||
{
|
||||
typedef MaybeScopedAlloc type;
|
||||
};
|
||||
|
||||
template<class MaybeScopedAlloc, bool = is_scoped_allocator_imp<MaybeScopedAlloc>::value >
|
||||
struct outermost_allocator_imp
|
||||
{
|
||||
typedef MaybeScopedAlloc type;
|
||||
|
||||
static type &get(MaybeScopedAlloc &a)
|
||||
{ return a; }
|
||||
|
||||
static const type &get(const MaybeScopedAlloc &a)
|
||||
{ return a; }
|
||||
};
|
||||
|
||||
template<class MaybeScopedAlloc>
|
||||
struct outermost_allocator_imp<MaybeScopedAlloc, true>
|
||||
{
|
||||
typedef typename MaybeScopedAlloc::outer_allocator_type outer_type;
|
||||
typedef typename outermost_allocator_type_impl<outer_type>::type type;
|
||||
|
||||
static type &get(MaybeScopedAlloc &a)
|
||||
{ return outermost_allocator_imp<outer_type>::get(a.outer_allocator()); }
|
||||
|
||||
static const type &get(const MaybeScopedAlloc &a)
|
||||
{ return outermost_allocator_imp<outer_type>::get(a.outer_allocator()); }
|
||||
};
|
||||
|
||||
} //namespace container_detail {
|
||||
|
||||
template <typename Allocator>
|
||||
struct is_scoped_allocator
|
||||
: container_detail::is_scoped_allocator_imp<Allocator>
|
||||
{};
|
||||
|
||||
template <typename Allocator>
|
||||
struct outermost_allocator
|
||||
: container_detail::outermost_allocator_imp<Allocator>
|
||||
{};
|
||||
|
||||
template <typename Allocator>
|
||||
typename outermost_allocator<Allocator>::type &
|
||||
get_outermost_allocator(Allocator &a)
|
||||
{ return outermost_allocator<Allocator>::get(a); }
|
||||
|
||||
template <typename Allocator>
|
||||
const typename outermost_allocator<Allocator>::type &
|
||||
get_outermost_allocator(const Allocator &a)
|
||||
{ return outermost_allocator<Allocator>::get(a); }
|
||||
|
||||
namespace container_detail {
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
template <typename OuterAlloc, class ...InnerAllocs>
|
||||
class scoped_allocator_adaptor_base
|
||||
: public OuterAlloc
|
||||
{
|
||||
typedef allocator_traits<OuterAlloc> outer_traits_type;
|
||||
BOOST_COPYABLE_AND_MOVABLE(scoped_allocator_adaptor_base)
|
||||
|
||||
public:
|
||||
template <class OuterA2>
|
||||
struct rebind_base
|
||||
{
|
||||
typedef scoped_allocator_adaptor_base<OuterA2, InnerAllocs...> other;
|
||||
};
|
||||
|
||||
typedef OuterAlloc outer_allocator_type;
|
||||
typedef scoped_allocator_adaptor<InnerAllocs...> inner_allocator_type;
|
||||
typedef allocator_traits<inner_allocator_type> inner_traits_type;
|
||||
typedef scoped_allocator_adaptor
|
||||
<OuterAlloc, InnerAllocs...> scoped_allocator_type;
|
||||
typedef container_detail::bool_<
|
||||
outer_traits_type::propagate_on_container_copy_assignment::value ||
|
||||
inner_allocator_type::propagate_on_container_copy_assignment::value
|
||||
> propagate_on_container_copy_assignment;
|
||||
typedef container_detail::bool_<
|
||||
outer_traits_type::propagate_on_container_move_assignment::value ||
|
||||
inner_allocator_type::propagate_on_container_move_assignment::value
|
||||
> propagate_on_container_move_assignment;
|
||||
typedef container_detail::bool_<
|
||||
outer_traits_type::propagate_on_container_swap::value ||
|
||||
inner_allocator_type::propagate_on_container_swap::value
|
||||
> propagate_on_container_swap;
|
||||
typedef container_detail::bool_<
|
||||
outer_traits_type::is_always_equal::value &&
|
||||
inner_allocator_type::is_always_equal::value
|
||||
> is_always_equal;
|
||||
|
||||
scoped_allocator_adaptor_base()
|
||||
{}
|
||||
|
||||
template <class OuterA2>
|
||||
scoped_allocator_adaptor_base(BOOST_FWD_REF(OuterA2) outerAlloc, const InnerAllocs &...args)
|
||||
: outer_allocator_type(::boost::forward<OuterA2>(outerAlloc))
|
||||
, m_inner(args...)
|
||||
{}
|
||||
|
||||
scoped_allocator_adaptor_base(const scoped_allocator_adaptor_base& other)
|
||||
: outer_allocator_type(other.outer_allocator())
|
||||
, m_inner(other.inner_allocator())
|
||||
{}
|
||||
|
||||
scoped_allocator_adaptor_base(BOOST_RV_REF(scoped_allocator_adaptor_base) other)
|
||||
: outer_allocator_type(::boost::move(other.outer_allocator()))
|
||||
, m_inner(::boost::move(other.inner_allocator()))
|
||||
{}
|
||||
|
||||
template <class OuterA2>
|
||||
scoped_allocator_adaptor_base
|
||||
(const scoped_allocator_adaptor_base<OuterA2, InnerAllocs...>& other)
|
||||
: outer_allocator_type(other.outer_allocator())
|
||||
, m_inner(other.inner_allocator())
|
||||
{}
|
||||
|
||||
template <class OuterA2>
|
||||
scoped_allocator_adaptor_base
|
||||
(BOOST_RV_REF_BEG scoped_allocator_adaptor_base
|
||||
<OuterA2, InnerAllocs...> BOOST_RV_REF_END other)
|
||||
: outer_allocator_type(other.outer_allocator())
|
||||
, m_inner(other.inner_allocator())
|
||||
{}
|
||||
|
||||
public:
|
||||
struct internal_type_t{};
|
||||
|
||||
template <class OuterA2>
|
||||
scoped_allocator_adaptor_base
|
||||
( internal_type_t
|
||||
, BOOST_FWD_REF(OuterA2) outerAlloc
|
||||
, const inner_allocator_type &inner)
|
||||
: outer_allocator_type(::boost::forward<OuterA2>(outerAlloc))
|
||||
, m_inner(inner)
|
||||
{}
|
||||
|
||||
public:
|
||||
|
||||
scoped_allocator_adaptor_base &operator=
|
||||
(BOOST_COPY_ASSIGN_REF(scoped_allocator_adaptor_base) other)
|
||||
{
|
||||
outer_allocator_type::operator=(other.outer_allocator());
|
||||
m_inner = other.inner_allocator();
|
||||
return *this;
|
||||
}
|
||||
|
||||
scoped_allocator_adaptor_base &operator=(BOOST_RV_REF(scoped_allocator_adaptor_base) other)
|
||||
{
|
||||
outer_allocator_type::operator=(boost::move(other.outer_allocator()));
|
||||
m_inner = ::boost::move(other.inner_allocator());
|
||||
return *this;
|
||||
}
|
||||
|
||||
void swap(scoped_allocator_adaptor_base &r)
|
||||
{
|
||||
boost::adl_move_swap(this->outer_allocator(), r.outer_allocator());
|
||||
boost::adl_move_swap(this->m_inner, r.inner_allocator());
|
||||
}
|
||||
|
||||
friend void swap(scoped_allocator_adaptor_base &l, scoped_allocator_adaptor_base &r)
|
||||
{ l.swap(r); }
|
||||
|
||||
inner_allocator_type& inner_allocator() BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return m_inner; }
|
||||
|
||||
inner_allocator_type const& inner_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return m_inner; }
|
||||
|
||||
outer_allocator_type & outer_allocator() BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return static_cast<outer_allocator_type&>(*this); }
|
||||
|
||||
const outer_allocator_type &outer_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return static_cast<const outer_allocator_type&>(*this); }
|
||||
|
||||
scoped_allocator_type select_on_container_copy_construction() const
|
||||
{
|
||||
return scoped_allocator_type
|
||||
(internal_type_t()
|
||||
,outer_traits_type::select_on_container_copy_construction(this->outer_allocator())
|
||||
,inner_traits_type::select_on_container_copy_construction(this->inner_allocator())
|
||||
);
|
||||
}
|
||||
|
||||
private:
|
||||
inner_allocator_type m_inner;
|
||||
};
|
||||
|
||||
#else //#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
//Let's add a dummy first template parameter to allow creating
|
||||
//specializations up to maximum InnerAlloc count
|
||||
template <typename OuterAlloc, bool Dummy, BOOST_MOVE_CLASSDFLT9>
|
||||
class scoped_allocator_adaptor_base;
|
||||
|
||||
//Specializations for the adaptor with InnerAlloc allocators
|
||||
|
||||
#define BOOST_CONTAINER_SCOPED_ALLOCATOR_ADAPTOR_BASE_CODE(N)\
|
||||
template <typename OuterAlloc BOOST_MOVE_I##N BOOST_MOVE_CLASS##N>\
|
||||
class scoped_allocator_adaptor_base<OuterAlloc, true, BOOST_MOVE_TARG##N>\
|
||||
: public OuterAlloc\
|
||||
{\
|
||||
typedef allocator_traits<OuterAlloc> outer_traits_type;\
|
||||
BOOST_COPYABLE_AND_MOVABLE(scoped_allocator_adaptor_base)\
|
||||
\
|
||||
public:\
|
||||
template <class OuterA2>\
|
||||
struct rebind_base\
|
||||
{\
|
||||
typedef scoped_allocator_adaptor_base<OuterA2, true, BOOST_MOVE_TARG##N> other;\
|
||||
};\
|
||||
\
|
||||
typedef OuterAlloc outer_allocator_type;\
|
||||
typedef scoped_allocator_adaptor<BOOST_MOVE_TARG##N> inner_allocator_type;\
|
||||
typedef scoped_allocator_adaptor<OuterAlloc, BOOST_MOVE_TARG##N> scoped_allocator_type;\
|
||||
typedef allocator_traits<inner_allocator_type> inner_traits_type;\
|
||||
typedef container_detail::bool_<\
|
||||
outer_traits_type::propagate_on_container_copy_assignment::value ||\
|
||||
inner_allocator_type::propagate_on_container_copy_assignment::value\
|
||||
> propagate_on_container_copy_assignment;\
|
||||
typedef container_detail::bool_<\
|
||||
outer_traits_type::propagate_on_container_move_assignment::value ||\
|
||||
inner_allocator_type::propagate_on_container_move_assignment::value\
|
||||
> propagate_on_container_move_assignment;\
|
||||
typedef container_detail::bool_<\
|
||||
outer_traits_type::propagate_on_container_swap::value ||\
|
||||
inner_allocator_type::propagate_on_container_swap::value\
|
||||
> propagate_on_container_swap;\
|
||||
\
|
||||
typedef container_detail::bool_<\
|
||||
outer_traits_type::is_always_equal::value &&\
|
||||
inner_allocator_type::is_always_equal::value\
|
||||
> is_always_equal;\
|
||||
\
|
||||
scoped_allocator_adaptor_base(){}\
|
||||
\
|
||||
template <class OuterA2>\
|
||||
scoped_allocator_adaptor_base(BOOST_FWD_REF(OuterA2) outerAlloc, BOOST_MOVE_CREF##N)\
|
||||
: outer_allocator_type(::boost::forward<OuterA2>(outerAlloc))\
|
||||
, m_inner(BOOST_MOVE_ARG##N)\
|
||||
{}\
|
||||
\
|
||||
scoped_allocator_adaptor_base(const scoped_allocator_adaptor_base& other)\
|
||||
: outer_allocator_type(other.outer_allocator())\
|
||||
, m_inner(other.inner_allocator())\
|
||||
{}\
|
||||
\
|
||||
scoped_allocator_adaptor_base(BOOST_RV_REF(scoped_allocator_adaptor_base) other)\
|
||||
: outer_allocator_type(::boost::move(other.outer_allocator()))\
|
||||
, m_inner(::boost::move(other.inner_allocator()))\
|
||||
{}\
|
||||
\
|
||||
template <class OuterA2>\
|
||||
scoped_allocator_adaptor_base\
|
||||
(const scoped_allocator_adaptor_base<OuterA2, true, BOOST_MOVE_TARG##N>& other)\
|
||||
: outer_allocator_type(other.outer_allocator())\
|
||||
, m_inner(other.inner_allocator())\
|
||||
{}\
|
||||
\
|
||||
template <class OuterA2>\
|
||||
scoped_allocator_adaptor_base\
|
||||
(BOOST_RV_REF_BEG scoped_allocator_adaptor_base<OuterA2, true, BOOST_MOVE_TARG##N> BOOST_RV_REF_END other)\
|
||||
: outer_allocator_type(other.outer_allocator())\
|
||||
, m_inner(other.inner_allocator())\
|
||||
{}\
|
||||
\
|
||||
public:\
|
||||
struct internal_type_t{};\
|
||||
\
|
||||
template <class OuterA2>\
|
||||
scoped_allocator_adaptor_base\
|
||||
( internal_type_t, BOOST_FWD_REF(OuterA2) outerAlloc, const inner_allocator_type &inner)\
|
||||
: outer_allocator_type(::boost::forward<OuterA2>(outerAlloc))\
|
||||
, m_inner(inner)\
|
||||
{}\
|
||||
\
|
||||
public:\
|
||||
scoped_allocator_adaptor_base &operator=\
|
||||
(BOOST_COPY_ASSIGN_REF(scoped_allocator_adaptor_base) other)\
|
||||
{\
|
||||
outer_allocator_type::operator=(other.outer_allocator());\
|
||||
m_inner = other.inner_allocator();\
|
||||
return *this;\
|
||||
}\
|
||||
\
|
||||
scoped_allocator_adaptor_base &operator=(BOOST_RV_REF(scoped_allocator_adaptor_base) other)\
|
||||
{\
|
||||
outer_allocator_type::operator=(boost::move(other.outer_allocator()));\
|
||||
m_inner = ::boost::move(other.inner_allocator());\
|
||||
return *this;\
|
||||
}\
|
||||
\
|
||||
void swap(scoped_allocator_adaptor_base &r)\
|
||||
{\
|
||||
boost::adl_move_swap(this->outer_allocator(), r.outer_allocator());\
|
||||
boost::adl_move_swap(this->m_inner, r.inner_allocator());\
|
||||
}\
|
||||
\
|
||||
friend void swap(scoped_allocator_adaptor_base &l, scoped_allocator_adaptor_base &r)\
|
||||
{ l.swap(r); }\
|
||||
\
|
||||
inner_allocator_type& inner_allocator()\
|
||||
{ return m_inner; }\
|
||||
\
|
||||
inner_allocator_type const& inner_allocator() const\
|
||||
{ return m_inner; }\
|
||||
\
|
||||
outer_allocator_type & outer_allocator()\
|
||||
{ return static_cast<outer_allocator_type&>(*this); }\
|
||||
\
|
||||
const outer_allocator_type &outer_allocator() const\
|
||||
{ return static_cast<const outer_allocator_type&>(*this); }\
|
||||
\
|
||||
scoped_allocator_type select_on_container_copy_construction() const\
|
||||
{\
|
||||
return scoped_allocator_type\
|
||||
(internal_type_t()\
|
||||
,outer_traits_type::select_on_container_copy_construction(this->outer_allocator())\
|
||||
,inner_traits_type::select_on_container_copy_construction(this->inner_allocator())\
|
||||
);\
|
||||
}\
|
||||
private:\
|
||||
inner_allocator_type m_inner;\
|
||||
};\
|
||||
//!
|
||||
BOOST_MOVE_ITERATE_1TO9(BOOST_CONTAINER_SCOPED_ALLOCATOR_ADAPTOR_BASE_CODE)
|
||||
#undef BOOST_CONTAINER_SCOPED_ALLOCATOR_ADAPTOR_BASE_CODE
|
||||
|
||||
#endif //#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
#define BOOST_CONTAINER_SCOPEDALLOC_DUMMYTRUE ,true
|
||||
#define BOOST_CONTAINER_SCOPEDALLOC_ALLINNER BOOST_MOVE_TARG9
|
||||
#define BOOST_CONTAINER_SCOPEDALLOC_ALLINNERCLASS BOOST_MOVE_CLASS9
|
||||
#else
|
||||
#define BOOST_CONTAINER_SCOPEDALLOC_DUMMYTRUE
|
||||
#define BOOST_CONTAINER_SCOPEDALLOC_ALLINNER InnerAllocs...
|
||||
#define BOOST_CONTAINER_SCOPEDALLOC_ALLINNERCLASS typename... InnerAllocs
|
||||
#endif
|
||||
|
||||
//Specialization for adaptor without any InnerAlloc
|
||||
template <typename OuterAlloc>
|
||||
class scoped_allocator_adaptor_base< OuterAlloc BOOST_CONTAINER_SCOPEDALLOC_DUMMYTRUE>
|
||||
: public OuterAlloc
|
||||
{
|
||||
BOOST_COPYABLE_AND_MOVABLE(scoped_allocator_adaptor_base)
|
||||
public:
|
||||
|
||||
template <class U>
|
||||
struct rebind_base
|
||||
{
|
||||
typedef scoped_allocator_adaptor_base
|
||||
<typename allocator_traits<OuterAlloc>::template portable_rebind_alloc<U>::type
|
||||
BOOST_CONTAINER_SCOPEDALLOC_DUMMYTRUE > other;
|
||||
};
|
||||
|
||||
typedef OuterAlloc outer_allocator_type;
|
||||
typedef allocator_traits<OuterAlloc> outer_traits_type;
|
||||
typedef scoped_allocator_adaptor<OuterAlloc> inner_allocator_type;
|
||||
typedef inner_allocator_type scoped_allocator_type;
|
||||
typedef allocator_traits<inner_allocator_type> inner_traits_type;
|
||||
typedef typename outer_traits_type::
|
||||
propagate_on_container_copy_assignment propagate_on_container_copy_assignment;
|
||||
typedef typename outer_traits_type::
|
||||
propagate_on_container_move_assignment propagate_on_container_move_assignment;
|
||||
typedef typename outer_traits_type::
|
||||
propagate_on_container_swap propagate_on_container_swap;
|
||||
typedef typename outer_traits_type::
|
||||
is_always_equal is_always_equal;
|
||||
|
||||
scoped_allocator_adaptor_base()
|
||||
{}
|
||||
|
||||
template <class OuterA2>
|
||||
scoped_allocator_adaptor_base(BOOST_FWD_REF(OuterA2) outerAlloc)
|
||||
: outer_allocator_type(::boost::forward<OuterA2>(outerAlloc))
|
||||
{}
|
||||
|
||||
scoped_allocator_adaptor_base(const scoped_allocator_adaptor_base& other)
|
||||
: outer_allocator_type(other.outer_allocator())
|
||||
{}
|
||||
|
||||
scoped_allocator_adaptor_base(BOOST_RV_REF(scoped_allocator_adaptor_base) other)
|
||||
: outer_allocator_type(::boost::move(other.outer_allocator()))
|
||||
{}
|
||||
|
||||
template <class OuterA2>
|
||||
scoped_allocator_adaptor_base
|
||||
(const scoped_allocator_adaptor_base<OuterA2 BOOST_CONTAINER_SCOPEDALLOC_DUMMYTRUE>& other)
|
||||
: outer_allocator_type(other.outer_allocator())
|
||||
{}
|
||||
|
||||
template <class OuterA2>
|
||||
scoped_allocator_adaptor_base
|
||||
(BOOST_RV_REF_BEG scoped_allocator_adaptor_base<OuterA2 BOOST_CONTAINER_SCOPEDALLOC_DUMMYTRUE> BOOST_RV_REF_END other)
|
||||
: outer_allocator_type(other.outer_allocator())
|
||||
{}
|
||||
|
||||
public:
|
||||
struct internal_type_t{};
|
||||
|
||||
template <class OuterA2>
|
||||
scoped_allocator_adaptor_base(internal_type_t, BOOST_FWD_REF(OuterA2) outerAlloc, const inner_allocator_type &)
|
||||
: outer_allocator_type(::boost::forward<OuterA2>(outerAlloc))
|
||||
{}
|
||||
|
||||
public:
|
||||
scoped_allocator_adaptor_base &operator=(BOOST_COPY_ASSIGN_REF(scoped_allocator_adaptor_base) other)
|
||||
{
|
||||
outer_allocator_type::operator=(other.outer_allocator());
|
||||
return *this;
|
||||
}
|
||||
|
||||
scoped_allocator_adaptor_base &operator=(BOOST_RV_REF(scoped_allocator_adaptor_base) other)
|
||||
{
|
||||
outer_allocator_type::operator=(boost::move(other.outer_allocator()));
|
||||
return *this;
|
||||
}
|
||||
|
||||
void swap(scoped_allocator_adaptor_base &r)
|
||||
{
|
||||
boost::adl_move_swap(this->outer_allocator(), r.outer_allocator());
|
||||
}
|
||||
|
||||
friend void swap(scoped_allocator_adaptor_base &l, scoped_allocator_adaptor_base &r)
|
||||
{ l.swap(r); }
|
||||
|
||||
inner_allocator_type& inner_allocator()
|
||||
{ return static_cast<inner_allocator_type&>(*this); }
|
||||
|
||||
inner_allocator_type const& inner_allocator() const
|
||||
{ return static_cast<const inner_allocator_type&>(*this); }
|
||||
|
||||
outer_allocator_type & outer_allocator()
|
||||
{ return static_cast<outer_allocator_type&>(*this); }
|
||||
|
||||
const outer_allocator_type &outer_allocator() const
|
||||
{ return static_cast<const outer_allocator_type&>(*this); }
|
||||
|
||||
scoped_allocator_type select_on_container_copy_construction() const
|
||||
{
|
||||
return scoped_allocator_type
|
||||
(internal_type_t()
|
||||
,outer_traits_type::select_on_container_copy_construction(this->outer_allocator())
|
||||
//Don't use inner_traits_type::select_on_container_copy_construction(this->inner_allocator())
|
||||
//as inner_allocator() is equal to *this and that would trigger an infinite loop
|
||||
, this->inner_allocator()
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
} //namespace container_detail {
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
//Scoped allocator
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
|
||||
#if !defined(BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST)
|
||||
|
||||
//! This class is a C++03-compatible implementation of std::scoped_allocator_adaptor.
|
||||
//! The class template scoped_allocator_adaptor is an allocator template that specifies
|
||||
//! the memory resource (the outer allocator) to be used by a container (as any other
|
||||
//! allocator does) and also specifies an inner allocator resource to be passed to
|
||||
//! the constructor of every element within the container.
|
||||
//!
|
||||
//! This adaptor is
|
||||
//! instantiated with one outer and zero or more inner allocator types. If
|
||||
//! instantiated with only one allocator type, the inner allocator becomes the
|
||||
//! scoped_allocator_adaptor itself, thus using the same allocator resource for the
|
||||
//! container and every element within the container and, if the elements themselves
|
||||
//! are containers, each of their elements recursively. If instantiated with more than
|
||||
//! one allocator, the first allocator is the outer allocator for use by the container,
|
||||
//! the second allocator is passed to the constructors of the container's elements,
|
||||
//! and, if the elements themselves are containers, the third allocator is passed to
|
||||
//! the elements' elements, and so on. If containers are nested to a depth greater
|
||||
//! than the number of allocators, the last allocator is used repeatedly, as in the
|
||||
//! single-allocator case, for any remaining recursions.
|
||||
//!
|
||||
//! [<b>Note</b>: The
|
||||
//! scoped_allocator_adaptor is derived from the outer allocator type so it can be
|
||||
//! substituted for the outer allocator type in most expressions. -end note]
|
||||
//!
|
||||
//! In the construct member functions, <code>OUTERMOST(x)</code> is x if x does not have
|
||||
//! an <code>outer_allocator()</code> member function and
|
||||
//! <code>OUTERMOST(x.outer_allocator())</code> otherwise; <code>OUTERMOST_ALLOC_TRAITS(x)</code> is
|
||||
//! <code>allocator_traits<decltype(OUTERMOST(x))></code>.
|
||||
//!
|
||||
//! [<b>Note</b>: <code>OUTERMOST(x)</code> and
|
||||
//! <code>OUTERMOST_ALLOC_TRAITS(x)</code> are recursive operations. It is incumbent upon
|
||||
//! the definition of <code>outer_allocator()</code> to ensure that the recursion terminates.
|
||||
//! It will terminate for all instantiations of scoped_allocator_adaptor. -end note]
|
||||
template <typename OuterAlloc, typename ...InnerAllocs>
|
||||
class scoped_allocator_adaptor
|
||||
|
||||
#else // #if !defined(BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST)
|
||||
|
||||
template <typename OuterAlloc, typename ...InnerAllocs>
|
||||
class scoped_allocator_adaptor<OuterAlloc, InnerAllocs...>
|
||||
|
||||
#endif // #if !defined(BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST)
|
||||
|
||||
#else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
|
||||
template <typename OuterAlloc, BOOST_MOVE_CLASS9>
|
||||
class scoped_allocator_adaptor
|
||||
#endif
|
||||
|
||||
: public container_detail::scoped_allocator_adaptor_base
|
||||
<OuterAlloc BOOST_CONTAINER_SCOPEDALLOC_DUMMYTRUE, BOOST_CONTAINER_SCOPEDALLOC_ALLINNER>
|
||||
{
|
||||
BOOST_COPYABLE_AND_MOVABLE(scoped_allocator_adaptor)
|
||||
|
||||
public:
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
typedef container_detail::scoped_allocator_adaptor_base
|
||||
<OuterAlloc BOOST_CONTAINER_SCOPEDALLOC_DUMMYTRUE, BOOST_CONTAINER_SCOPEDALLOC_ALLINNER> base_type;
|
||||
typedef typename base_type::internal_type_t internal_type_t;
|
||||
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
typedef OuterAlloc outer_allocator_type;
|
||||
//! Type: For exposition only
|
||||
//!
|
||||
typedef allocator_traits<OuterAlloc> outer_traits_type;
|
||||
//! Type: <code>scoped_allocator_adaptor<OuterAlloc></code> if <code>sizeof...(InnerAllocs)</code> is zero; otherwise,
|
||||
//! <code>scoped_allocator_adaptor<InnerAllocs...></code>.
|
||||
typedef typename base_type::inner_allocator_type inner_allocator_type;
|
||||
typedef allocator_traits<inner_allocator_type> inner_traits_type;
|
||||
typedef typename outer_traits_type::value_type value_type;
|
||||
typedef typename outer_traits_type::size_type size_type;
|
||||
typedef typename outer_traits_type::difference_type difference_type;
|
||||
typedef typename outer_traits_type::pointer pointer;
|
||||
typedef typename outer_traits_type::const_pointer const_pointer;
|
||||
typedef typename outer_traits_type::void_pointer void_pointer;
|
||||
typedef typename outer_traits_type::const_void_pointer const_void_pointer;
|
||||
//! Type: A type with a constant boolean <code>value</code> == true if
|
||||
//!`allocator_traits<Allocator>:: propagate_on_container_copy_assignment::value` is
|
||||
//! true for any <code>Allocator</code> in the set of <code>OuterAlloc</code> and <code>InnerAllocs...</code>, false otherwise.
|
||||
typedef typename base_type::
|
||||
propagate_on_container_copy_assignment propagate_on_container_copy_assignment;
|
||||
//! Type: A type with a constant boolean <code>value</code> == true if
|
||||
//!`allocator_traits<Allocator>:: propagate_on_container_move_assignment::value` is
|
||||
//! true for any <code>Allocator</code> in the set of <code>OuterAlloc</code> and <code>InnerAllocs...</code>, false otherwise.
|
||||
typedef typename base_type::
|
||||
propagate_on_container_move_assignment propagate_on_container_move_assignment;
|
||||
|
||||
//! Type: A type with a constant boolean <code>value</code> == true if
|
||||
//! `allocator_traits<Allocator>:: propagate_on_container_swap::value` is
|
||||
//! true for any <code>Allocator</code> in the set of <code>OuterAlloc</code> and <code>InnerAllocs...</code>, false otherwise.
|
||||
typedef typename base_type::
|
||||
propagate_on_container_swap propagate_on_container_swap;
|
||||
|
||||
//! Type: A type with a constant boolean <code>value</code> == true if
|
||||
//!`allocator_traits<Allocator>:: is_always_equal::value` is
|
||||
//! true for all <code>Allocator</code> in the set of <code>OuterAlloc</code> and <code>InnerAllocs...</code>, false otherwise.
|
||||
typedef typename base_type::
|
||||
is_always_equal is_always_equal;
|
||||
|
||||
//! Type: Rebinds scoped allocator to
|
||||
//! <code>typedef scoped_allocator_adaptor
|
||||
//! < typename outer_traits_type::template portable_rebind_alloc<U>::type
|
||||
//! , InnerAllocs... ></code>
|
||||
template <class U>
|
||||
struct rebind
|
||||
{
|
||||
typedef scoped_allocator_adaptor
|
||||
< typename outer_traits_type::template portable_rebind_alloc<U>::type
|
||||
, BOOST_CONTAINER_SCOPEDALLOC_ALLINNER> other;
|
||||
};
|
||||
|
||||
//! <b>Effects</b>: value-initializes the OuterAlloc base class
|
||||
//! and the inner allocator object.
|
||||
scoped_allocator_adaptor()
|
||||
{}
|
||||
|
||||
~scoped_allocator_adaptor()
|
||||
{}
|
||||
|
||||
//! <b>Effects</b>: initializes each allocator within the adaptor with
|
||||
//! the corresponding allocator from other.
|
||||
scoped_allocator_adaptor(const scoped_allocator_adaptor& other)
|
||||
: base_type(other.base())
|
||||
{}
|
||||
|
||||
//! <b>Effects</b>: move constructs each allocator within the adaptor with
|
||||
//! the corresponding allocator from other.
|
||||
scoped_allocator_adaptor(BOOST_RV_REF(scoped_allocator_adaptor) other)
|
||||
: base_type(::boost::move(other.base()))
|
||||
{}
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
|
||||
//! <b>Requires</b>: OuterAlloc shall be constructible from OuterA2.
|
||||
//!
|
||||
//! <b>Effects</b>: initializes the OuterAlloc base class with boost::forward<OuterA2>(outerAlloc) and inner
|
||||
//! with innerAllocs...(hence recursively initializing each allocator within the adaptor with the
|
||||
//! corresponding allocator from the argument list).
|
||||
template <class OuterA2>
|
||||
scoped_allocator_adaptor(BOOST_FWD_REF(OuterA2) outerAlloc, const InnerAllocs & ...innerAllocs)
|
||||
: base_type(::boost::forward<OuterA2>(outerAlloc), innerAllocs...)
|
||||
{}
|
||||
#else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
|
||||
#define BOOST_CONTAINER_SCOPED_ALLOCATOR_ADAPTOR_RELATED_ALLOCATOR_CONSTRUCTOR_CODE(N)\
|
||||
template <class OuterA2>\
|
||||
scoped_allocator_adaptor(BOOST_FWD_REF(OuterA2) outerAlloc BOOST_MOVE_I##N BOOST_MOVE_CREF##N)\
|
||||
: base_type(::boost::forward<OuterA2>(outerAlloc) BOOST_MOVE_I##N BOOST_MOVE_ARG##N)\
|
||||
{}\
|
||||
//
|
||||
BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_SCOPED_ALLOCATOR_ADAPTOR_RELATED_ALLOCATOR_CONSTRUCTOR_CODE)
|
||||
#undef BOOST_CONTAINER_SCOPED_ALLOCATOR_ADAPTOR_RELATED_ALLOCATOR_CONSTRUCTOR_CODE
|
||||
|
||||
#endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
|
||||
//! <b>Requires</b>: OuterAlloc shall be constructible from OuterA2.
|
||||
//!
|
||||
//! <b>Effects</b>: initializes each allocator within the adaptor with the corresponding allocator from other.
|
||||
template <class OuterA2>
|
||||
scoped_allocator_adaptor(const scoped_allocator_adaptor<OuterA2, BOOST_CONTAINER_SCOPEDALLOC_ALLINNER> &other)
|
||||
: base_type(other.base())
|
||||
{}
|
||||
|
||||
//! <b>Requires</b>: OuterAlloc shall be constructible from OuterA2.
|
||||
//!
|
||||
//! <b>Effects</b>: initializes each allocator within the adaptor with the corresponding allocator
|
||||
//! rvalue from other.
|
||||
template <class OuterA2>
|
||||
scoped_allocator_adaptor(BOOST_RV_REF_BEG scoped_allocator_adaptor
|
||||
<OuterA2, BOOST_CONTAINER_SCOPEDALLOC_ALLINNER> BOOST_RV_REF_END other)
|
||||
: base_type(::boost::move(other.base()))
|
||||
{}
|
||||
|
||||
scoped_allocator_adaptor &operator=(BOOST_COPY_ASSIGN_REF(scoped_allocator_adaptor) other)
|
||||
{ return static_cast<scoped_allocator_adaptor&>(base_type::operator=(static_cast<const base_type &>(other))); }
|
||||
|
||||
scoped_allocator_adaptor &operator=(BOOST_RV_REF(scoped_allocator_adaptor) other)
|
||||
{ return static_cast<scoped_allocator_adaptor&>(base_type::operator=(boost::move(other.base()))); }
|
||||
|
||||
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
//! <b>Effects</b>: swaps *this with r.
|
||||
//!
|
||||
void swap(scoped_allocator_adaptor &r);
|
||||
|
||||
//! <b>Effects</b>: swaps *this with r.
|
||||
//!
|
||||
friend void swap(scoped_allocator_adaptor &l, scoped_allocator_adaptor &r);
|
||||
|
||||
//! <b>Returns</b>:
|
||||
//! <code>static_cast<OuterAlloc&>(*this)</code>.
|
||||
outer_allocator_type & outer_allocator() BOOST_NOEXCEPT_OR_NOTHROW;
|
||||
|
||||
//! <b>Returns</b>:
|
||||
//! <code>static_cast<const OuterAlloc&>(*this)</code>.
|
||||
const outer_allocator_type &outer_allocator() const BOOST_NOEXCEPT_OR_NOTHROW;
|
||||
|
||||
//! <b>Returns</b>:
|
||||
//! *this if <code>sizeof...(InnerAllocs)</code> is zero; otherwise, inner.
|
||||
inner_allocator_type& inner_allocator() BOOST_NOEXCEPT_OR_NOTHROW;
|
||||
|
||||
//! <b>Returns</b>:
|
||||
//! *this if <code>sizeof...(InnerAllocs)</code> is zero; otherwise, inner.
|
||||
inner_allocator_type const& inner_allocator() const BOOST_NOEXCEPT_OR_NOTHROW;
|
||||
|
||||
#endif //BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
//! <b>Returns</b>:
|
||||
//! <code>allocator_traits<OuterAlloc>:: max_size(outer_allocator())</code>.
|
||||
size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return outer_traits_type::max_size(this->outer_allocator()); }
|
||||
|
||||
//! <b>Effects</b>:
|
||||
//! calls <code>OUTERMOST_ALLOC_TRAITS(*this):: destroy(OUTERMOST(*this), p)</code>.
|
||||
template <class T>
|
||||
void destroy(T* p) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{
|
||||
allocator_traits<typename outermost_allocator<OuterAlloc>::type>
|
||||
::destroy(get_outermost_allocator(this->outer_allocator()), p);
|
||||
}
|
||||
|
||||
//! <b>Returns</b>:
|
||||
//! <code>allocator_traits<OuterAlloc>::allocate(outer_allocator(), n)</code>.
|
||||
pointer allocate(size_type n)
|
||||
{ return outer_traits_type::allocate(this->outer_allocator(), n); }
|
||||
|
||||
//! <b>Returns</b>:
|
||||
//! <code>allocator_traits<OuterAlloc>::allocate(outer_allocator(), n, hint)</code>.
|
||||
pointer allocate(size_type n, const_void_pointer hint)
|
||||
{ return outer_traits_type::allocate(this->outer_allocator(), n, hint); }
|
||||
|
||||
//! <b>Effects</b>:
|
||||
//! <code>allocator_traits<OuterAlloc>::deallocate(outer_allocator(), p, n)</code>.
|
||||
void deallocate(pointer p, size_type n)
|
||||
{ outer_traits_type::deallocate(this->outer_allocator(), p, n); }
|
||||
|
||||
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
//! <b>Returns</b>: A new scoped_allocator_adaptor object where each allocator
|
||||
//! Allocator in the adaptor is initialized from the result of calling
|
||||
//! <code>allocator_traits<Allocator>::select_on_container_copy_construction()</code> on
|
||||
//! the corresponding allocator in *this.
|
||||
scoped_allocator_adaptor select_on_container_copy_construction() const;
|
||||
#endif //BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
base_type &base() { return *this; }
|
||||
|
||||
const base_type &base() const { return *this; }
|
||||
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
|
||||
//! <b>Effects</b>:
|
||||
//! 1) If <code>uses_allocator<T, inner_allocator_type>::value</code> is false calls
|
||||
//! <code>OUTERMOST_ALLOC_TRAITS(*this)::
|
||||
//! construct(OUTERMOST(*this), p, std::forward<Args>(args)...)</code>.
|
||||
//!
|
||||
//! 2) Otherwise, if <code>uses_allocator<T, inner_allocator_type>::value</code> is true and
|
||||
//! <code>is_constructible<T, allocator_arg_t, inner_allocator_type, Args...>:: value</code> is true, calls
|
||||
//! <code>OUTERMOST_ALLOC_TRAITS(*this):: construct(OUTERMOST(*this), p, allocator_arg,
|
||||
//! inner_allocator(), std::forward<Args>(args)...)</code>.
|
||||
//!
|
||||
//! [<b>Note</b>: In compilers without advanced decltype SFINAE support, <code>is_constructible</code> can't
|
||||
//! be implemented so that condition will be replaced by
|
||||
//! constructible_with_allocator_prefix<T>::value. -end note]
|
||||
//!
|
||||
//! 3) Otherwise, if uses_allocator<T, inner_allocator_type>::value is true and
|
||||
//! <code>is_constructible<T, Args..., inner_allocator_type>:: value</code> is true, calls
|
||||
//! <code>OUTERMOST_ALLOC_TRAITS(*this):: construct(OUTERMOST(*this), p,
|
||||
//! std::forward<Args>(args)..., inner_allocator())</code>.
|
||||
//!
|
||||
//! [<b>Note</b>: In compilers without advanced decltype SFINAE support, <code>is_constructible</code> can't be
|
||||
//! implemented so that condition will be replaced by
|
||||
//! <code>constructible_with_allocator_suffix<T>:: value</code>. -end note]
|
||||
//!
|
||||
//! 4) Otherwise, the program is ill-formed.
|
||||
//!
|
||||
//! [<b>Note</b>: An error will result if <code>uses_allocator</code> evaluates
|
||||
//! to true but the specific constructor does not take an allocator. This definition prevents a silent
|
||||
//! failure to pass an inner allocator to a contained element. -end note]
|
||||
template < typename T, class ...Args>
|
||||
void construct(T* p, BOOST_FWD_REF(Args)...args)
|
||||
{
|
||||
container_detail::dispatch_uses_allocator
|
||||
( (get_outermost_allocator)(this->outer_allocator())
|
||||
, this->inner_allocator(), p, ::boost::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
#else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
|
||||
//Disable this overload if the first argument is pair as some compilers have
|
||||
//overload selection problems when the first parameter is a pair.
|
||||
#define BOOST_CONTAINER_SCOPED_ALLOCATOR_CONSTRUCT_CODE(N) \
|
||||
template < typename T BOOST_MOVE_I##N BOOST_MOVE_CLASSQ##N >\
|
||||
void construct(T* p BOOST_MOVE_I##N BOOST_MOVE_UREFQ##N)\
|
||||
{\
|
||||
container_detail::dispatch_uses_allocator\
|
||||
( (get_outermost_allocator)(this->outer_allocator())\
|
||||
, this->inner_allocator(), p BOOST_MOVE_I##N BOOST_MOVE_FWDQ##N);\
|
||||
}\
|
||||
//
|
||||
BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_SCOPED_ALLOCATOR_CONSTRUCT_CODE)
|
||||
#undef BOOST_CONTAINER_SCOPED_ALLOCATOR_CONSTRUCT_CODE
|
||||
|
||||
#endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
public:
|
||||
//Internal function
|
||||
template <class OuterA2>
|
||||
scoped_allocator_adaptor(internal_type_t, BOOST_FWD_REF(OuterA2) outer, const inner_allocator_type& inner)
|
||||
: base_type(internal_type_t(), ::boost::forward<OuterA2>(outer), inner)
|
||||
{}
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
};
|
||||
|
||||
/// @cond
|
||||
|
||||
template<bool ZeroInner>
|
||||
struct scoped_allocator_operator_equal
|
||||
{
|
||||
//Optimize equal outer allocator types with
|
||||
//allocator_traits::equal which uses is_always_equal
|
||||
template<class IA>
|
||||
static bool equal_outer(const IA &l, const IA &r)
|
||||
{ return allocator_traits<IA>::equal(l, r); }
|
||||
|
||||
//Otherwise compare it normally
|
||||
template<class IA1, class IA2>
|
||||
static bool equal_outer(const IA1 &l, const IA2 &r)
|
||||
{ return l == r; }
|
||||
|
||||
//Otherwise compare it normally
|
||||
template<class IA>
|
||||
static bool equal_inner(const IA &l, const IA &r)
|
||||
{ return allocator_traits<IA>::equal(l, r); }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct scoped_allocator_operator_equal<true>
|
||||
: scoped_allocator_operator_equal<false>
|
||||
{
|
||||
//when inner allocator count is zero,
|
||||
//inner_allocator_type is the same as outer_allocator_type
|
||||
//so both types can be different in operator==
|
||||
template<class IA1, class IA2>
|
||||
static bool equal_inner(const IA1 &, const IA2 &)
|
||||
{ return true; }
|
||||
};
|
||||
|
||||
/// @endcond
|
||||
|
||||
template <typename OuterA1, typename OuterA2, BOOST_CONTAINER_SCOPEDALLOC_ALLINNERCLASS>
|
||||
inline bool operator==(const scoped_allocator_adaptor<OuterA1, BOOST_CONTAINER_SCOPEDALLOC_ALLINNER>& a
|
||||
,const scoped_allocator_adaptor<OuterA2, BOOST_CONTAINER_SCOPEDALLOC_ALLINNER>& b)
|
||||
{
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
const bool has_zero_inner = sizeof...(InnerAllocs) == 0u;
|
||||
#else
|
||||
const bool has_zero_inner = boost::container::container_detail::is_same<P0, void>::value;
|
||||
#endif
|
||||
typedef scoped_allocator_operator_equal<has_zero_inner> equal_t;
|
||||
return equal_t::equal_outer(a.outer_allocator(), b.outer_allocator()) &&
|
||||
equal_t::equal_inner(a.inner_allocator(), b.inner_allocator());
|
||||
}
|
||||
|
||||
template <typename OuterA1, typename OuterA2, BOOST_CONTAINER_SCOPEDALLOC_ALLINNERCLASS>
|
||||
inline bool operator!=(const scoped_allocator_adaptor<OuterA1, BOOST_CONTAINER_SCOPEDALLOC_ALLINNER>& a
|
||||
,const scoped_allocator_adaptor<OuterA2, BOOST_CONTAINER_SCOPEDALLOC_ALLINNER>& b)
|
||||
{ return !(a == b); }
|
||||
|
||||
}} // namespace boost { namespace container {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif // BOOST_CONTAINER_ALLOCATOR_SCOPED_ALLOCATOR_HPP
|
||||
@@ -0,0 +1,71 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_ALLOCATOR_SCOPED_ALLOCATOR_FWD_HPP
|
||||
#define BOOST_CONTAINER_ALLOCATOR_SCOPED_ALLOCATOR_FWD_HPP
|
||||
|
||||
//! \file
|
||||
//! This header file forward declares boost::container::scoped_allocator_adaptor
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/detail/config_begin.hpp>
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
#include <boost/container/detail/std_fwd.hpp>
|
||||
#include <boost/container/uses_allocator_fwd.hpp>
|
||||
|
||||
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
#include <boost/move/detail/fwd_macros.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost { namespace container {
|
||||
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
#if !defined(BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST)
|
||||
|
||||
template <typename OuterAlloc, typename ...InnerAllocs>
|
||||
class scoped_allocator_adaptor;
|
||||
|
||||
#else // #if !defined(BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST)
|
||||
|
||||
template <typename ...InnerAllocs>
|
||||
class scoped_allocator_adaptor;
|
||||
|
||||
template <typename OuterAlloc, typename ...InnerAllocs>
|
||||
class scoped_allocator_adaptor<OuterAlloc, InnerAllocs...>;
|
||||
|
||||
#endif // #if !defined(BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST)
|
||||
|
||||
#else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
template <typename OuterAlloc, BOOST_MOVE_CLASSDFLT9>
|
||||
class scoped_allocator_adaptor;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#else //BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
}} // namespace boost { namespace container {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif // BOOST_CONTAINER_ALLOCATOR_SCOPED_ALLOCATOR_FWD_HPP
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,632 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_CONTAINER_SMALL_VECTOR_HPP
|
||||
#define BOOST_CONTAINER_CONTAINER_SMALL_VECTOR_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/detail/config_begin.hpp>
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
|
||||
// container
|
||||
#include <boost/container/container_fwd.hpp>
|
||||
#include <boost/container/vector.hpp>
|
||||
#include <boost/container/allocator_traits.hpp>
|
||||
#include <boost/container/new_allocator.hpp> //new_allocator
|
||||
// container/detail
|
||||
#include <boost/container/detail/type_traits.hpp>
|
||||
#include <boost/container/detail/version_type.hpp>
|
||||
|
||||
//move
|
||||
#include <boost/move/adl_move_swap.hpp>
|
||||
#include <boost/move/iterator.hpp>
|
||||
|
||||
//move/detail
|
||||
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
#include <boost/move/detail/fwd_macros.hpp>
|
||||
#endif
|
||||
|
||||
//std
|
||||
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
||||
#include <initializer_list> //for std::initializer_list
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
template <class T, class Allocator = new_allocator<T> >
|
||||
class small_vector_base;
|
||||
|
||||
#endif
|
||||
|
||||
//! A non-standard allocator used to implement `small_vector`.
|
||||
//! Users should never use it directly. It is described here
|
||||
//! for documentation purposes.
|
||||
//!
|
||||
//! This allocator inherits from a standard-conforming allocator
|
||||
//! and forwards member functions to the standard allocator except
|
||||
//! when internal storage is being used as memory source.
|
||||
//!
|
||||
//! This allocator is a "partially_propagable" allocator and
|
||||
//! defines `is_partially_propagable` as true_type.
|
||||
//!
|
||||
//! A partially propagable allocator means that not all storage
|
||||
//! allocatod by an instance of `small_vector_allocator` can be
|
||||
//! deallocated by another instance of this type, even if both
|
||||
//! instances compare equal or an instance is propagated to another
|
||||
//! one using the copy/move constructor or assignment. The storage that
|
||||
//! can never be propagated is identified by `storage_is_unpropagable(p)`.
|
||||
//!
|
||||
//! `boost::container::vector` supports partially propagable allocators
|
||||
//! fallbacking to deep copy/swap/move operations when internal storage
|
||||
//! is being used to store vector elements.
|
||||
//!
|
||||
//! `small_vector_allocator` assumes that will be instantiated as
|
||||
//! `boost::container::vector< T, small_vector_allocator<Allocator> >`
|
||||
//! and internal storage can be obtained downcasting that vector
|
||||
//! to `small_vector_base<T>`.
|
||||
template<class Allocator>
|
||||
class small_vector_allocator
|
||||
: public Allocator
|
||||
{
|
||||
typedef unsigned int allocation_type;
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
private:
|
||||
|
||||
BOOST_COPYABLE_AND_MOVABLE(small_vector_allocator)
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE const Allocator &as_base() const
|
||||
{ return static_cast<const Allocator&>(*this); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE Allocator &as_base()
|
||||
{ return static_cast<Allocator&>(*this); }
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
public:
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
typedef allocator_traits<Allocator> allocator_traits_type;
|
||||
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
typedef typename allocator_traits<Allocator>::value_type value_type;
|
||||
typedef typename allocator_traits<Allocator>::pointer pointer;
|
||||
typedef typename allocator_traits<Allocator>::const_pointer const_pointer;
|
||||
typedef typename allocator_traits<Allocator>::reference reference;
|
||||
typedef typename allocator_traits<Allocator>::const_reference const_reference;
|
||||
typedef typename allocator_traits<Allocator>::size_type size_type;
|
||||
typedef typename allocator_traits<Allocator>::difference_type difference_type;
|
||||
typedef typename allocator_traits<Allocator>::void_pointer void_pointer;
|
||||
typedef typename allocator_traits<Allocator>::const_void_pointer const_void_pointer;
|
||||
|
||||
typedef typename allocator_traits<Allocator>::propagate_on_container_copy_assignment propagate_on_container_copy_assignment;
|
||||
typedef typename allocator_traits<Allocator>::propagate_on_container_move_assignment propagate_on_container_move_assignment;
|
||||
typedef typename allocator_traits<Allocator>::propagate_on_container_swap propagate_on_container_swap;
|
||||
//! An integral constant with member `value == false`
|
||||
typedef BOOST_CONTAINER_IMPDEF(container_detail::bool_<false>) is_always_equal;
|
||||
//! An integral constant with member `value == true`
|
||||
typedef BOOST_CONTAINER_IMPDEF(container_detail::bool_<true>) is_partially_propagable;
|
||||
|
||||
BOOST_CONTAINER_DOCIGN(typedef container_detail::version_type<small_vector_allocator BOOST_CONTAINER_I 1> version;)
|
||||
|
||||
//!Obtains an small_vector_allocator that allocates
|
||||
//!objects of type T2
|
||||
template<class T2>
|
||||
struct rebind
|
||||
{
|
||||
typedef typename allocator_traits<Allocator>::template rebind_alloc<T2>::type other;
|
||||
};
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
//!Constructor from arbitrary arguments
|
||||
template<class ...Args>
|
||||
BOOST_CONTAINER_FORCEINLINE explicit small_vector_allocator(BOOST_FWD_REF(Args) ...args)
|
||||
: Allocator(::boost::forward<Args>(args)...)
|
||||
{}
|
||||
#else
|
||||
#define BOOST_CONTAINER_SMALL_VECTOR_ALLOCATOR_CTOR_CODE(N) \
|
||||
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
|
||||
BOOST_CONTAINER_FORCEINLINE explicit small_vector_allocator(BOOST_MOVE_UREF##N)\
|
||||
: Allocator(BOOST_MOVE_FWD##N)\
|
||||
{}\
|
||||
//
|
||||
BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_SMALL_VECTOR_ALLOCATOR_CTOR_CODE)
|
||||
#undef BOOST_CONTAINER_SMALL_VECTOR_ALLOCATOR_CTOR_CODE
|
||||
#endif
|
||||
|
||||
//!Constructor from other small_vector_allocator.
|
||||
//!Never throws
|
||||
BOOST_CONTAINER_FORCEINLINE small_vector_allocator
|
||||
(const small_vector_allocator &other) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
: Allocator(other.as_base())
|
||||
{}
|
||||
|
||||
//!Move constructor from small_vector_allocator.
|
||||
//!Never throws
|
||||
BOOST_CONTAINER_FORCEINLINE small_vector_allocator
|
||||
(BOOST_RV_REF(small_vector_allocator) other) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
: Allocator(::boost::move(other.as_base()))
|
||||
{}
|
||||
|
||||
//!Constructor from related small_vector_allocator.
|
||||
//!Never throws
|
||||
template<class OtherAllocator>
|
||||
BOOST_CONTAINER_FORCEINLINE small_vector_allocator
|
||||
(const small_vector_allocator<OtherAllocator> &other) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
: Allocator(other.as_base())
|
||||
{}
|
||||
|
||||
//!Move constructor from related small_vector_allocator.
|
||||
//!Never throws
|
||||
template<class OtherAllocator>
|
||||
BOOST_CONTAINER_FORCEINLINE small_vector_allocator
|
||||
(BOOST_RV_REF(small_vector_allocator<OtherAllocator>) other) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
: Allocator(::boost::move(other.as_base()))
|
||||
{}
|
||||
|
||||
//!Assignment from other small_vector_allocator.
|
||||
//!Never throws
|
||||
BOOST_CONTAINER_FORCEINLINE small_vector_allocator &
|
||||
operator=(BOOST_COPY_ASSIGN_REF(small_vector_allocator) other) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return static_cast<small_vector_allocator&>(this->Allocator::operator=(other.as_base())); }
|
||||
|
||||
//!Move constructor from other small_vector_allocator.
|
||||
//!Never throws
|
||||
BOOST_CONTAINER_FORCEINLINE small_vector_allocator &
|
||||
operator=(BOOST_RV_REF(small_vector_allocator) other) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return static_cast<small_vector_allocator&>(this->Allocator::operator=(::boost::move(other.as_base()))); }
|
||||
|
||||
//!Assignment from related small_vector_allocator.
|
||||
//!Never throws
|
||||
template<class OtherAllocator>
|
||||
BOOST_CONTAINER_FORCEINLINE small_vector_allocator &
|
||||
operator=(BOOST_COPY_ASSIGN_REF(small_vector_allocator<OtherAllocator>) other) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return static_cast<small_vector_allocator&>(this->Allocator::operator=(other.as_base())); }
|
||||
|
||||
//!Move assignment from related small_vector_allocator.
|
||||
//!Never throws
|
||||
template<class OtherAllocator>
|
||||
BOOST_CONTAINER_FORCEINLINE small_vector_allocator &
|
||||
operator=(BOOST_RV_REF(small_vector_allocator<OtherAllocator>) other) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return static_cast<small_vector_allocator&>(this->Allocator::operator=(::boost::move(other.as_base()))); }
|
||||
|
||||
//!Allocates storage from the standard-conforming allocator
|
||||
BOOST_CONTAINER_FORCEINLINE pointer allocate(size_type count, const_void_pointer hint = const_void_pointer())
|
||||
{ return allocator_traits_type::allocate(this->as_base(), count, hint); }
|
||||
|
||||
//!Deallocates previously allocated memory.
|
||||
//!Never throws
|
||||
void deallocate(pointer ptr, size_type n) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{
|
||||
if(!this->is_internal_storage(ptr))
|
||||
allocator_traits_type::deallocate(this->as_base(), ptr, n);
|
||||
}
|
||||
|
||||
//!Returns the maximum number of elements that could be allocated.
|
||||
//!Never throws
|
||||
BOOST_CONTAINER_FORCEINLINE size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return allocator_traits_type::max_size(this->as_base()); }
|
||||
|
||||
small_vector_allocator select_on_container_copy_construction() const
|
||||
{ return small_vector_allocator(allocator_traits_type::select_on_container_copy_construction(this->as_base())); }
|
||||
|
||||
bool storage_is_unpropagable(pointer p) const
|
||||
{ return this->is_internal_storage(p) || allocator_traits_type::storage_is_unpropagable(this->as_base(), p); }
|
||||
|
||||
//!Swaps two allocators, does nothing
|
||||
//!because this small_vector_allocator is stateless
|
||||
BOOST_CONTAINER_FORCEINLINE friend void swap(small_vector_allocator &l, small_vector_allocator &r) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ boost::adl_move_swap(l.as_base(), r.as_base()); }
|
||||
|
||||
//!An small_vector_allocator always compares to true, as memory allocated with one
|
||||
//!instance can be deallocated by another instance (except for unpropagable storage)
|
||||
BOOST_CONTAINER_FORCEINLINE friend bool operator==(const small_vector_allocator &l, const small_vector_allocator &r) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return allocator_traits_type::equal(l.as_base(), r.as_base()); }
|
||||
|
||||
//!An small_vector_allocator always compares to false, as memory allocated with one
|
||||
//!instance can be deallocated by another instance
|
||||
BOOST_CONTAINER_FORCEINLINE friend bool operator!=(const small_vector_allocator &l, const small_vector_allocator &r) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return !(l == r); }
|
||||
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
/*
|
||||
//!An advanced function that offers in-place expansion shrink to fit and new allocation
|
||||
//!capabilities. Memory allocated with this function can only be deallocated with deallocate()
|
||||
//!or deallocate_many().
|
||||
//!This function is available only with Version == 2
|
||||
pointer allocation_command(allocation_type command,
|
||||
size_type limit_size,
|
||||
size_type &prefer_in_recvd_out_size,
|
||||
pointer &reuse)
|
||||
{ return allocator_traits_type::allocation_command(command, limit_size, prefer_in_recvd_out_size, reuse); }
|
||||
|
||||
//!Returns maximum the number of objects the previously allocated memory
|
||||
//!pointed by p can hold.
|
||||
//!Memory must not have been allocated with
|
||||
//!allocate_one or allocate_individual.
|
||||
//!This function is available only with Version == 2
|
||||
size_type size(pointer p) const BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return allocator_traits_type::size(p); }
|
||||
*/
|
||||
private:
|
||||
/*
|
||||
//!Allocates just one object. Memory allocated with this function
|
||||
//!must be deallocated only with deallocate_one().
|
||||
//!Throws bad_alloc if there is no enough memory
|
||||
//!This function is available only with Version == 2
|
||||
using Allocator::allocate_one;
|
||||
using Allocator::allocate_individual;
|
||||
using Allocator::deallocate_one;
|
||||
using Allocator::deallocate_individual;
|
||||
using Allocator::allocate_many;
|
||||
using Allocator::deallocate_many;*/
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE bool is_internal_storage(pointer p) const
|
||||
{ return this->internal_storage() == p; }
|
||||
|
||||
pointer internal_storage() const
|
||||
{
|
||||
typedef typename Allocator::value_type value_type;
|
||||
typedef container_detail::vector_alloc_holder< small_vector_allocator<Allocator> > vector_alloc_holder_t;
|
||||
typedef vector<value_type, small_vector_allocator<Allocator> > vector_base;
|
||||
typedef small_vector_base<value_type, Allocator> derived_type;
|
||||
//
|
||||
const vector_alloc_holder_t &v_holder = static_cast<const vector_alloc_holder_t &>(*this);
|
||||
const vector_base &v_base = reinterpret_cast<const vector_base &>(v_holder);
|
||||
const derived_type &d_base = static_cast<const derived_type &>(v_base);
|
||||
return d_base.internal_storage();
|
||||
}
|
||||
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
};
|
||||
|
||||
//! This class consists of common code from all small_vector<T, N> types that don't depend on the
|
||||
//! "N" template parameter. This class is non-copyable and non-destructible, so this class typically
|
||||
//! used as reference argument to functions that read or write small vectors. Since `small_vector<T, N>`
|
||||
//! derives from `small_vector_base<T>`, the conversion to `small_vector_base` is implicit
|
||||
//! <pre>
|
||||
//!
|
||||
//! //Clients can pass any small_vector<Foo, N>.
|
||||
//! void read_any_small_vector_of_foo(const small_vector_base<Foo> &in_parameter);
|
||||
//!
|
||||
//! void modify_any_small_vector_of_foo(small_vector_base<Foo> &in_out_parameter);
|
||||
//!
|
||||
//! void some_function()
|
||||
//! {
|
||||
//!
|
||||
//! small_vector<Foo, 8> myvector;
|
||||
//!
|
||||
//! read_any_small_vector_of_foo(myvector); // Reads myvector
|
||||
//!
|
||||
//! modify_any_small_vector_of_foo(myvector); // Modifies myvector
|
||||
//!
|
||||
//! }
|
||||
//! </pre>
|
||||
//!
|
||||
//! All `boost::container:vector` member functions are inherited. See `vector` documentation for details.
|
||||
//!
|
||||
template <class T, class SecondaryAllocator>
|
||||
class small_vector_base
|
||||
: public vector<T, small_vector_allocator<SecondaryAllocator> >
|
||||
{
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
public:
|
||||
//Make it public as it will be inherited by small_vector and container
|
||||
//must have this public member
|
||||
typedef typename allocator_traits<SecondaryAllocator>::pointer pointer;
|
||||
|
||||
private:
|
||||
BOOST_COPYABLE_AND_MOVABLE(small_vector_base)
|
||||
|
||||
friend class small_vector_allocator<SecondaryAllocator>;
|
||||
|
||||
pointer internal_storage() const BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{
|
||||
return boost::intrusive::pointer_traits<pointer>::pointer_to
|
||||
(*const_cast<T*>(static_cast<const T*>(static_cast<const void*>(&m_storage_start))));
|
||||
}
|
||||
|
||||
typedef vector<T, small_vector_allocator<SecondaryAllocator> > base_type;
|
||||
base_type &as_base() { return static_cast<base_type&>(*this); }
|
||||
const base_type &as_base() const { return static_cast<const base_type&>(*this); }
|
||||
|
||||
public:
|
||||
typedef typename container_detail::aligned_storage
|
||||
<sizeof(T), container_detail::alignment_of<T>::value>::type storage_type;
|
||||
typedef small_vector_allocator<SecondaryAllocator> allocator_type;
|
||||
|
||||
protected:
|
||||
typedef typename base_type::initial_capacity_t initial_capacity_t;
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE explicit small_vector_base(initial_capacity_t, std::size_t initial_capacity)
|
||||
: base_type(initial_capacity_t(), this->internal_storage(), initial_capacity)
|
||||
{}
|
||||
|
||||
template<class AllocFwd>
|
||||
BOOST_CONTAINER_FORCEINLINE explicit small_vector_base(initial_capacity_t, std::size_t capacity, BOOST_FWD_REF(AllocFwd) a)
|
||||
: base_type(initial_capacity_t(), this->internal_storage(), capacity, ::boost::forward<AllocFwd>(a))
|
||||
{}
|
||||
|
||||
//~small_vector_base(){}
|
||||
|
||||
private:
|
||||
//The only member
|
||||
storage_type m_storage_start;
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
public:
|
||||
BOOST_CONTAINER_FORCEINLINE small_vector_base& operator=(BOOST_COPY_ASSIGN_REF(small_vector_base) other)
|
||||
{ return static_cast<small_vector_base&>(this->base_type::operator=(static_cast<base_type const&>(other))); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE small_vector_base& operator=(BOOST_RV_REF(small_vector_base) other)
|
||||
{ return static_cast<small_vector_base&>(this->base_type::operator=(BOOST_MOVE_BASE(base_type, other))); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE void swap(small_vector_base &other)
|
||||
{ return this->base_type::swap(other); }
|
||||
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
protected:
|
||||
void move_construct_impl(base_type &x, const allocator_type &a)
|
||||
{
|
||||
if(base_type::is_propagable_from(x.get_stored_allocator(), x.data(), a, true)){
|
||||
this->steal_resources(x);
|
||||
}
|
||||
else{
|
||||
this->assign( boost::make_move_iterator(container_detail::iterator_to_raw_pointer(x.begin()))
|
||||
, boost::make_move_iterator(container_detail::iterator_to_raw_pointer(x.end ()))
|
||||
);
|
||||
}
|
||||
}
|
||||
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
};
|
||||
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
//
|
||||
// small_vector_storage_calculator
|
||||
//
|
||||
/////////////////////////////////////////////////////
|
||||
template<std::size_t Needed, std::size_t Hdr, std::size_t SSize, bool NeedsZero = (0u == Needed || Needed <= Hdr)>
|
||||
struct small_vector_storage_calculator_helper
|
||||
{
|
||||
static const std::size_t value = (Needed - Hdr - 1u)/SSize + 1u;
|
||||
};
|
||||
|
||||
template<std::size_t Needed, std::size_t Hdr, std::size_t SSize>
|
||||
struct small_vector_storage_calculator_helper<Needed, Hdr, SSize, true>
|
||||
{
|
||||
static const std::size_t value = 0u;
|
||||
};
|
||||
|
||||
template<class Storage, class Allocator, class T, std::size_t N>
|
||||
struct small_vector_storage_calculator
|
||||
{
|
||||
typedef small_vector_base<T, Allocator> svh_type;
|
||||
typedef vector<T, small_vector_allocator<Allocator> > svhb_type;
|
||||
static const std::size_t s_align = container_detail::alignment_of<Storage>::value;
|
||||
static const std::size_t s_size = sizeof(Storage);
|
||||
static const std::size_t svh_sizeof = sizeof(svh_type);
|
||||
static const std::size_t svhb_sizeof = sizeof(svhb_type);
|
||||
static const std::size_t s_start = ((svhb_sizeof-1)/s_align+1)*s_align;
|
||||
static const std::size_t header_bytes = svh_sizeof-s_start;
|
||||
static const std::size_t needed_bytes = sizeof(T)*N;
|
||||
static const std::size_t needed_extra_storages =
|
||||
small_vector_storage_calculator_helper<needed_bytes, header_bytes, s_size>::value;
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
//
|
||||
// small_vector_storage_definer
|
||||
//
|
||||
/////////////////////////////////////////////////////
|
||||
template<class Storage, std::size_t N>
|
||||
struct small_vector_storage
|
||||
{
|
||||
Storage m_rest_of_storage[N];
|
||||
};
|
||||
|
||||
template<class Storage>
|
||||
struct small_vector_storage<Storage, 0>
|
||||
{};
|
||||
|
||||
template<class Allocator, std::size_t N>
|
||||
struct small_vector_storage_definer
|
||||
{
|
||||
typedef typename Allocator::value_type value_type;
|
||||
typedef typename small_vector_base<value_type, Allocator>::storage_type storage_type;
|
||||
static const std::size_t needed_extra_storages =
|
||||
small_vector_storage_calculator<storage_type, Allocator, value_type, N>::needed_extra_storages;
|
||||
typedef small_vector_storage<storage_type, needed_extra_storages> type;
|
||||
};
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
//! small_vector is a vector-like container optimized for the case when it contains few elements.
|
||||
//! It contains some preallocated elements in-place, which can avoid the use of dynamic storage allocation
|
||||
//! when the actual number of elements is below that preallocated threshold.
|
||||
//!
|
||||
//! `small_vector<T, N, Allocator>` is convertible to `small_vector_base<T, Allocator>` that is independent
|
||||
//! from the preallocated element capacity, so client code does not need to be templated on that N argument.
|
||||
//!
|
||||
//! All `boost::container::vector` member functions are inherited. See `vector` documentation for details.
|
||||
//!
|
||||
//! \tparam T The type of object that is stored in the small_vector
|
||||
//! \tparam N The number of preallocated elements stored inside small_vector. It shall be less than Allocator::max_size();
|
||||
//! \tparam Allocator The allocator used for memory management when the number of elements exceeds N.
|
||||
template <class T, std::size_t N, class Allocator BOOST_CONTAINER_DOCONLY(= new_allocator<T>) >
|
||||
class small_vector : public small_vector_base<T, Allocator>
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
, private small_vector_storage_definer<Allocator, N>::type
|
||||
#endif
|
||||
{
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
typedef small_vector_base<T, Allocator> base_type;
|
||||
typedef typename small_vector_storage_definer<Allocator, N>::type remaining_storage_holder;
|
||||
|
||||
BOOST_COPYABLE_AND_MOVABLE(small_vector)
|
||||
|
||||
typedef typename base_type::initial_capacity_t initial_capacity_t;
|
||||
typedef allocator_traits<typename base_type::allocator_type> allocator_traits_type;
|
||||
|
||||
public:
|
||||
typedef small_vector_storage_calculator< typename small_vector_base<T, Allocator>
|
||||
::storage_type, Allocator, T, N> storage_test;
|
||||
|
||||
static const std::size_t needed_extra_storages = storage_test::needed_extra_storages;
|
||||
static const std::size_t needed_bytes = storage_test::needed_bytes;
|
||||
static const std::size_t header_bytes = storage_test::header_bytes;
|
||||
static const std::size_t s_start = storage_test::s_start;
|
||||
|
||||
typedef typename base_type::allocator_type allocator_type;
|
||||
typedef typename base_type::size_type size_type;
|
||||
typedef typename base_type::value_type value_type;
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE static std::size_t internal_capacity()
|
||||
{ return (sizeof(small_vector) - storage_test::s_start)/sizeof(T); }
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
//! @brief The capacity/max size of the container
|
||||
static const size_type static_capacity = N;
|
||||
|
||||
public:
|
||||
BOOST_CONTAINER_FORCEINLINE small_vector()
|
||||
BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value)
|
||||
: base_type(initial_capacity_t(), internal_capacity())
|
||||
{}
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE explicit small_vector(const allocator_type &a)
|
||||
: base_type(initial_capacity_t(), internal_capacity(), a)
|
||||
{}
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE explicit small_vector(size_type n)
|
||||
: base_type(initial_capacity_t(), internal_capacity())
|
||||
{ this->resize(n); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE small_vector(size_type n, const allocator_type &a)
|
||||
: base_type(initial_capacity_t(), internal_capacity(), a)
|
||||
{ this->resize(n); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE small_vector(size_type n, default_init_t)
|
||||
: base_type(initial_capacity_t(), internal_capacity())
|
||||
{ this->resize(n, default_init_t()); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE small_vector(size_type n, default_init_t, const allocator_type &a)
|
||||
: base_type(initial_capacity_t(), internal_capacity(), a)
|
||||
{ this->resize(n, default_init_t()); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE small_vector(size_type n, const value_type &v)
|
||||
: base_type(initial_capacity_t(), internal_capacity())
|
||||
{ this->resize(n, v); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE small_vector(size_type n, const value_type &v, const allocator_type &a)
|
||||
: base_type(initial_capacity_t(), internal_capacity(), a)
|
||||
{ this->resize(n, v); }
|
||||
|
||||
template <class InIt>
|
||||
BOOST_CONTAINER_FORCEINLINE small_vector(InIt first, InIt last
|
||||
BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename container_detail::disable_if_c
|
||||
< container_detail::is_convertible<InIt BOOST_MOVE_I size_type>::value
|
||||
BOOST_MOVE_I container_detail::nat >::type * = 0)
|
||||
)
|
||||
: base_type(initial_capacity_t(), internal_capacity())
|
||||
{ this->assign(first, last); }
|
||||
|
||||
template <class InIt>
|
||||
BOOST_CONTAINER_FORCEINLINE small_vector(InIt first, InIt last, const allocator_type& a
|
||||
BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename container_detail::disable_if_c
|
||||
< container_detail::is_convertible<InIt BOOST_MOVE_I size_type>::value
|
||||
BOOST_MOVE_I container_detail::nat >::type * = 0)
|
||||
)
|
||||
: base_type(initial_capacity_t(), internal_capacity(), a)
|
||||
{ this->assign(first, last); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE small_vector(const small_vector &other)
|
||||
: base_type( initial_capacity_t(), internal_capacity()
|
||||
, allocator_traits_type::select_on_container_copy_construction(other.get_stored_allocator()))
|
||||
{ this->assign(other.cbegin(), other.cend()); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE small_vector(const small_vector &other, const allocator_type &a)
|
||||
: base_type(initial_capacity_t(), internal_capacity(), a)
|
||||
{ this->assign(other.cbegin(), other.cend()); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE explicit small_vector(const base_type &other)
|
||||
: base_type( initial_capacity_t(), internal_capacity()
|
||||
, allocator_traits_type::select_on_container_copy_construction(other.get_stored_allocator()))
|
||||
{ this->assign(other.cbegin(), other.cend()); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE explicit small_vector(BOOST_RV_REF(base_type) other)
|
||||
: base_type(initial_capacity_t(), internal_capacity(), ::boost::move(other.get_stored_allocator()))
|
||||
{ this->move_construct_impl(other, other.get_stored_allocator()); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE small_vector(BOOST_RV_REF(small_vector) other)
|
||||
: base_type(initial_capacity_t(), internal_capacity(), ::boost::move(other.get_stored_allocator()))
|
||||
{ this->move_construct_impl(other, other.get_stored_allocator()); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE small_vector(BOOST_RV_REF(small_vector) other, const allocator_type &a)
|
||||
: base_type(initial_capacity_t(), internal_capacity(), a)
|
||||
{ this->move_construct_impl(other, a); }
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
||||
BOOST_CONTAINER_FORCEINLINE small_vector(std::initializer_list<value_type> il, const allocator_type& a = allocator_type())
|
||||
: base_type(initial_capacity_t(), internal_capacity(), a)
|
||||
{
|
||||
this->assign(il.begin(), il.end());
|
||||
}
|
||||
#endif
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE small_vector& operator=(BOOST_COPY_ASSIGN_REF(small_vector) other)
|
||||
{ return static_cast<small_vector&>(this->base_type::operator=(static_cast<base_type const&>(other))); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE small_vector& operator=(BOOST_RV_REF(small_vector) other)
|
||||
{ return static_cast<small_vector&>(this->base_type::operator=(BOOST_MOVE_BASE(base_type, other))); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE small_vector& operator=(const base_type &other)
|
||||
{ return static_cast<small_vector&>(this->base_type::operator=(other)); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE small_vector& operator=(BOOST_RV_REF(base_type) other)
|
||||
{ return static_cast<small_vector&>(this->base_type::operator=(boost::move(other))); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE void swap(small_vector &other)
|
||||
{ return this->base_type::swap(other); }
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
/*
|
||||
namespace boost {
|
||||
|
||||
//!has_trivial_destructor_after_move<> == true_type
|
||||
//!specialization for optimizations
|
||||
template <class T, class Allocator>
|
||||
struct has_trivial_destructor_after_move<boost::container::vector<T, Allocator> >
|
||||
{
|
||||
typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer;
|
||||
static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value &&
|
||||
::boost::has_trivial_destructor_after_move<pointer>::value;
|
||||
};
|
||||
|
||||
}
|
||||
*/
|
||||
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif // #ifndef BOOST_CONTAINER_CONTAINER_SMALL_VECTOR_HPP
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,171 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2012-2013. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_THROW_EXCEPTION_HPP
|
||||
#define BOOST_CONTAINER_THROW_EXCEPTION_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/detail/config_begin.hpp>
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
#include <stdexcept> //for std exception types
|
||||
#include <string> //for implicit std::string conversion
|
||||
#include <new> //for std::bad_alloc
|
||||
#else
|
||||
#include <boost/assert.hpp>
|
||||
#include <cstdlib> //for std::abort
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
|
||||
#if defined(BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS)
|
||||
//The user must provide definitions for the following functions
|
||||
|
||||
void throw_bad_alloc();
|
||||
|
||||
void throw_out_of_range(const char* str);
|
||||
|
||||
void throw_length_error(const char* str);
|
||||
|
||||
void throw_logic_error(const char* str);
|
||||
|
||||
void throw_runtime_error(const char* str);
|
||||
|
||||
#elif defined(BOOST_NO_EXCEPTIONS)
|
||||
|
||||
inline void throw_bad_alloc()
|
||||
{
|
||||
BOOST_ASSERT(!"boost::container bad_alloc thrown");
|
||||
std::abort();
|
||||
}
|
||||
|
||||
inline void throw_out_of_range(const char* str)
|
||||
{
|
||||
BOOST_ASSERT_MSG(!"boost::container out_of_range thrown", str);
|
||||
std::abort();
|
||||
}
|
||||
|
||||
inline void throw_length_error(const char* str)
|
||||
{
|
||||
BOOST_ASSERT_MSG(!"boost::container length_error thrown", str);
|
||||
std::abort();
|
||||
}
|
||||
|
||||
inline void throw_logic_error(const char* str)
|
||||
{
|
||||
BOOST_ASSERT_MSG(!"boost::container logic_error thrown", str);
|
||||
std::abort();
|
||||
}
|
||||
|
||||
inline void throw_runtime_error(const char* str)
|
||||
{
|
||||
BOOST_ASSERT_MSG(!"boost::container runtime_error thrown", str);
|
||||
std::abort();
|
||||
}
|
||||
|
||||
#else //defined(BOOST_NO_EXCEPTIONS)
|
||||
|
||||
//! Exception callback called by Boost.Container when fails to allocate the requested storage space.
|
||||
//! <ul>
|
||||
//! <li>If BOOST_NO_EXCEPTIONS is NOT defined <code>std::bad_alloc()</code> is thrown.</li>
|
||||
//!
|
||||
//! <li>If BOOST_NO_EXCEPTIONS is defined and BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS
|
||||
//! is NOT defined <code>BOOST_ASSERT(!"boost::container bad_alloc thrown")</code> is called
|
||||
//! and <code>std::abort()</code> if the former returns.</li>
|
||||
//!
|
||||
//! <li>If BOOST_NO_EXCEPTIONS and BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS are defined
|
||||
//! the user must provide an implementation and the function should not return.</li>
|
||||
//! </ul>
|
||||
inline void throw_bad_alloc()
|
||||
{
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
|
||||
//! Exception callback called by Boost.Container to signal arguments out of range.
|
||||
//! <ul>
|
||||
//! <li>If BOOST_NO_EXCEPTIONS is NOT defined <code>std::out_of_range(str)</code> is thrown.</li>
|
||||
//!
|
||||
//! <li>If BOOST_NO_EXCEPTIONS is defined and BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS
|
||||
//! is NOT defined <code>BOOST_ASSERT_MSG(!"boost::container out_of_range thrown", str)</code> is called
|
||||
//! and <code>std::abort()</code> if the former returns.</li>
|
||||
//!
|
||||
//! <li>If BOOST_NO_EXCEPTIONS and BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS are defined
|
||||
//! the user must provide an implementation and the function should not return.</li>
|
||||
//! </ul>
|
||||
inline void throw_out_of_range(const char* str)
|
||||
{
|
||||
throw std::out_of_range(str);
|
||||
}
|
||||
|
||||
//! Exception callback called by Boost.Container to signal errors resizing.
|
||||
//! <ul>
|
||||
//! <li>If BOOST_NO_EXCEPTIONS is NOT defined <code>std::length_error(str)</code> is thrown.</li>
|
||||
//!
|
||||
//! <li>If BOOST_NO_EXCEPTIONS is defined and BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS
|
||||
//! is NOT defined <code>BOOST_ASSERT_MSG(!"boost::container length_error thrown", str)</code> is called
|
||||
//! and <code>std::abort()</code> if the former returns.</li>
|
||||
//!
|
||||
//! <li>If BOOST_NO_EXCEPTIONS and BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS are defined
|
||||
//! the user must provide an implementation and the function should not return.</li>
|
||||
//! </ul>
|
||||
inline void throw_length_error(const char* str)
|
||||
{
|
||||
throw std::length_error(str);
|
||||
}
|
||||
|
||||
//! Exception callback called by Boost.Container to report errors in the internal logical
|
||||
//! of the program, such as violation of logical preconditions or class invariants.
|
||||
//! <ul>
|
||||
//! <li>If BOOST_NO_EXCEPTIONS is NOT defined <code>std::logic_error(str)</code> is thrown.</li>
|
||||
//!
|
||||
//! <li>If BOOST_NO_EXCEPTIONS is defined and BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS
|
||||
//! is NOT defined <code>BOOST_ASSERT_MSG(!"boost::container logic_error thrown", str)</code> is called
|
||||
//! and <code>std::abort()</code> if the former returns.</li>
|
||||
//!
|
||||
//! <li>If BOOST_NO_EXCEPTIONS and BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS are defined
|
||||
//! the user must provide an implementation and the function should not return.</li>
|
||||
//! </ul>
|
||||
inline void throw_logic_error(const char* str)
|
||||
{
|
||||
throw std::logic_error(str);
|
||||
}
|
||||
|
||||
//! Exception callback called by Boost.Container to report errors that can only be detected during runtime.
|
||||
//! <ul>
|
||||
//! <li>If BOOST_NO_EXCEPTIONS is NOT defined <code>std::runtime_error(str)</code> is thrown.</li>
|
||||
//!
|
||||
//! <li>If BOOST_NO_EXCEPTIONS is defined and BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS
|
||||
//! is NOT defined <code>BOOST_ASSERT_MSG(!"boost::container runtime_error thrown", str)</code> is called
|
||||
//! and <code>std::abort()</code> if the former returns.</li>
|
||||
//!
|
||||
//! <li>If BOOST_NO_EXCEPTIONS and BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS are defined
|
||||
//! the user must provide an implementation and the function should not return.</li>
|
||||
//! </ul>
|
||||
inline void throw_runtime_error(const char* str)
|
||||
{
|
||||
throw std::runtime_error(str);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}} //namespace boost { namespace container {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_THROW_EXCEPTION_HPP
|
||||
@@ -0,0 +1,169 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2011-2013. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_USES_ALLOCATOR_HPP
|
||||
#define BOOST_CONTAINER_USES_ALLOCATOR_HPP
|
||||
|
||||
#include <boost/container/uses_allocator_fwd.hpp>
|
||||
#include <boost/container/detail/type_traits.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
|
||||
//! <b>Remark</b>: if a specialization constructible_with_allocator_suffix<X>::value is true, indicates that T may be constructed
|
||||
//! with an allocator as its last constructor argument. Ideally, all constructors of T (including the
|
||||
//! copy and move constructors) should have a variant that accepts a final argument of
|
||||
//! allocator_type.
|
||||
//!
|
||||
//! <b>Requires</b>: if a specialization constructible_with_allocator_suffix<X>::value is true, T must have a nested type,
|
||||
//! allocator_type and at least one constructor for which allocator_type is the last
|
||||
//! parameter. If not all constructors of T can be called with a final allocator_type argument,
|
||||
//! and if T is used in a context where a container must call such a constructor, then the program is
|
||||
//! ill-formed.
|
||||
//!
|
||||
//! <code>
|
||||
//! template <class T, class Allocator = allocator<T> >
|
||||
//! class Z {
|
||||
//! public:
|
||||
//! typedef Allocator allocator_type;
|
||||
//!
|
||||
//! // Default constructor with optional allocator suffix
|
||||
//! Z(const allocator_type& a = allocator_type());
|
||||
//!
|
||||
//! // Copy constructor and allocator-extended copy constructor
|
||||
//! Z(const Z& zz);
|
||||
//! Z(const Z& zz, const allocator_type& a);
|
||||
//! };
|
||||
//!
|
||||
//! // Specialize trait for class template Z
|
||||
//! template <class T, class Allocator = allocator<T> >
|
||||
//! struct constructible_with_allocator_suffix<Z<T,Allocator> >
|
||||
//! { static const bool value = true; };
|
||||
//! </code>
|
||||
//!
|
||||
//! <b>Note</b>: This trait is a workaround inspired by "N2554: The Scoped A Model (Rev 2)"
|
||||
//! (Pablo Halpern, 2008-02-29) to backport the scoped allocator model to C++03, as
|
||||
//! in C++03 there is no mechanism to detect if a type can be constructed from arbitrary arguments.
|
||||
//! Applications aiming portability with several compilers should always define this trait.
|
||||
//!
|
||||
//! In conforming C++11 compilers or compilers supporting SFINAE expressions
|
||||
//! (when BOOST_NO_SFINAE_EXPR is NOT defined), this trait is ignored and C++11 rules will be used
|
||||
//! to detect if a type should be constructed with suffix or prefix allocator arguments.
|
||||
template <class T>
|
||||
struct constructible_with_allocator_suffix
|
||||
{ static const bool value = false; };
|
||||
|
||||
//! <b>Remark</b>: if a specialization constructible_with_allocator_prefix<X>::value is true, indicates that T may be constructed
|
||||
//! with allocator_arg and T::allocator_type as its first two constructor arguments.
|
||||
//! Ideally, all constructors of T (including the copy and move constructors) should have a variant
|
||||
//! that accepts these two initial arguments.
|
||||
//!
|
||||
//! <b>Requires</b>: specialization constructible_with_allocator_prefix<X>::value is true, T must have a nested type,
|
||||
//! allocator_type and at least one constructor for which allocator_arg_t is the first
|
||||
//! parameter and allocator_type is the second parameter. If not all constructors of T can be
|
||||
//! called with these initial arguments, and if T is used in a context where a container must call such
|
||||
//! a constructor, then the program is ill-formed.
|
||||
//!
|
||||
//! <code>
|
||||
//! template <class T, class Allocator = allocator<T> >
|
||||
//! class Y {
|
||||
//! public:
|
||||
//! typedef Allocator allocator_type;
|
||||
//!
|
||||
//! // Default constructor with and allocator-extended default constructor
|
||||
//! Y();
|
||||
//! Y(allocator_arg_t, const allocator_type& a);
|
||||
//!
|
||||
//! // Copy constructor and allocator-extended copy constructor
|
||||
//! Y(const Y& yy);
|
||||
//! Y(allocator_arg_t, const allocator_type& a, const Y& yy);
|
||||
//!
|
||||
//! // Variadic constructor and allocator-extended variadic constructor
|
||||
//! template<class ...Args> Y(Args&& args...);
|
||||
//! template<class ...Args>
|
||||
//! Y(allocator_arg_t, const allocator_type& a, BOOST_FWD_REF(Args)... args);
|
||||
//! };
|
||||
//!
|
||||
//! // Specialize trait for class template Y
|
||||
//! template <class T, class Allocator = allocator<T> >
|
||||
//! struct constructible_with_allocator_prefix<Y<T,Allocator> >
|
||||
//! { static const bool value = true; };
|
||||
//!
|
||||
//! </code>
|
||||
//!
|
||||
//! <b>Note</b>: This trait is a workaround inspired by "N2554: The Scoped Allocator Model (Rev 2)"
|
||||
//! (Pablo Halpern, 2008-02-29) to backport the scoped allocator model to C++03, as
|
||||
//! in C++03 there is no mechanism to detect if a type can be constructed from arbitrary arguments.
|
||||
//! Applications aiming portability with several compilers should always define this trait.
|
||||
//!
|
||||
//! In conforming C++11 compilers or compilers supporting SFINAE expressions
|
||||
//! (when BOOST_NO_SFINAE_EXPR is NOT defined), this trait is ignored and C++11 rules will be used
|
||||
//! to detect if a type should be constructed with suffix or prefix allocator arguments.
|
||||
template <class T>
|
||||
struct constructible_with_allocator_prefix
|
||||
{ static const bool value = false; };
|
||||
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
namespace container_detail {
|
||||
|
||||
template<typename T, typename Allocator>
|
||||
struct uses_allocator_imp
|
||||
{
|
||||
// Use SFINAE (Substitution Failure Is Not An Error) to detect the
|
||||
// presence of an 'allocator_type' nested type convertilble from Allocator.
|
||||
private:
|
||||
typedef char yes_type;
|
||||
struct no_type{ char dummy[2]; };
|
||||
|
||||
// Match this function if T::allocator_type exists and is
|
||||
// implicitly convertible from Allocator
|
||||
template <class U>
|
||||
static yes_type test(typename U::allocator_type);
|
||||
|
||||
// Match this function if T::allocator_type exists and it's type is `erased_type`.
|
||||
template <class U, class V>
|
||||
static typename container_detail::enable_if
|
||||
< container_detail::is_same<typename U::allocator_type, erased_type>
|
||||
, yes_type
|
||||
>::type test(const V&);
|
||||
|
||||
// Match this function if TypeT::allocator_type does not exist or is
|
||||
// not convertible from Allocator.
|
||||
template <typename U>
|
||||
static no_type test(...);
|
||||
static Allocator alloc; // Declared but not defined
|
||||
|
||||
public:
|
||||
static const bool value = sizeof(test<T>(alloc)) == sizeof(yes_type);
|
||||
};
|
||||
|
||||
} //namespace container_detail {
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
//! <b>Remark</b>: Automatically detects whether T has a nested allocator_type that is convertible from
|
||||
//! Allocator. Meets the BinaryTypeTrait requirements ([meta.rqmts] 20.4.1). A program may
|
||||
//! specialize this type to define uses_allocator<X>::value as true for a T of user-defined type if T does not
|
||||
//! have a nested allocator_type but is nonetheless constructible using the specified Allocator where either:
|
||||
//! the first argument of a constructor has type allocator_arg_t and the second argument has type Alloc or
|
||||
//! the last argument of a constructor has type Alloc.
|
||||
//!
|
||||
//! <b>Result</b>: uses_allocator<T, Allocator>::value== true if a type T::allocator_type
|
||||
//! exists and either is_convertible<Alloc, T::allocator_type>::value != false or T::allocator_type
|
||||
//! is an alias `erased_type`. False otherwise.
|
||||
template <typename T, typename Allocator>
|
||||
struct uses_allocator
|
||||
: container_detail::uses_allocator_imp<T, Allocator>
|
||||
{};
|
||||
|
||||
}} //namespace boost::container
|
||||
|
||||
#endif //BOOST_CONTAINER_USES_ALLOCATOR_HPP
|
||||
@@ -0,0 +1,73 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_USES_ALLOCATOR_FWD_HPP
|
||||
#define BOOST_CONTAINER_USES_ALLOCATOR_FWD_HPP
|
||||
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
#include <boost/container/detail/std_fwd.hpp>
|
||||
|
||||
//! \file
|
||||
//! This header forward declares boost::container::constructible_with_allocator_prefix,
|
||||
//! boost::container::constructible_with_allocator_suffix and
|
||||
//! boost::container::uses_allocator. Also defines the following types:
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
template <int Dummy = 0>
|
||||
struct std_allocator_arg_holder
|
||||
{
|
||||
static ::std::allocator_arg_t *dummy;
|
||||
};
|
||||
|
||||
template <int Dummy> //Silence null-reference compiler warnings
|
||||
::std::allocator_arg_t *std_allocator_arg_holder<Dummy>::dummy = reinterpret_cast< ::std::allocator_arg_t * >(0x1234);
|
||||
|
||||
typedef const std::allocator_arg_t & allocator_arg_t;
|
||||
|
||||
#else
|
||||
|
||||
//! The allocator_arg_t struct is an empty structure type used as a unique type to
|
||||
//! disambiguate constructor and function overloading. Specifically, several types
|
||||
//! have constructors with allocator_arg_t as the first argument, immediately followed
|
||||
//! by an argument of a type that satisfies Allocator requirements
|
||||
typedef unspecified allocator_arg_t;
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
//! The `erased_type` struct is an empty struct that serves as a placeholder for a type
|
||||
//! T in situations where the actual type T is determined at runtime. For example,
|
||||
//! the nested type, `allocator_type`, is an alias for `erased_type` in classes that
|
||||
//! use type-erased allocators.
|
||||
struct erased_type {};
|
||||
|
||||
//! A instance of type
|
||||
//! allocator_arg_t
|
||||
static allocator_arg_t allocator_arg = BOOST_CONTAINER_DOC1ST(unspecified, *std_allocator_arg_holder<>::dummy);
|
||||
|
||||
// @cond
|
||||
|
||||
template <class T>
|
||||
struct constructible_with_allocator_suffix;
|
||||
|
||||
template <class T>
|
||||
struct constructible_with_allocator_prefix;
|
||||
|
||||
template <typename T, typename Allocator>
|
||||
struct uses_allocator;
|
||||
|
||||
// @endcond
|
||||
|
||||
}} // namespace boost { namespace container {
|
||||
|
||||
#endif //BOOST_CONTAINER_USES_ALLOCATOR_HPP
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user