整理
This commit is contained in:
622
include/boost/container/adaptive_pool.hpp
Normal file
622
include/boost/container/adaptive_pool.hpp
Normal file
@@ -0,0 +1,622 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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/move/detail/force_ptr.hpp>
|
||||
|
||||
#include <boost/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;
|
||||
|
||||
BOOST_STATIC_CONSTEXPR std::size_t nodes_per_block = NodesPerBlock;
|
||||
BOOST_STATIC_CONSTEXPR std::size_t max_free_blocks = MaxFreeBlocks;
|
||||
BOOST_STATIC_CONSTEXPR std::size_t overhead_percent = OverheadPercent;
|
||||
BOOST_STATIC_CONSTEXPR std::size_t real_nodes_per_block = NodesPerBlock;
|
||||
|
||||
BOOST_CONTAINER_DOCIGN(BOOST_CONTAINER_STATIC_ASSERT((Version <=2)));
|
||||
|
||||
public:
|
||||
//-------
|
||||
typedef T value_type;
|
||||
typedef T * pointer;
|
||||
typedef const T * const_pointer;
|
||||
typedef typename ::boost::container::
|
||||
dtl::unvoid_ref<T>::type reference;
|
||||
typedef typename ::boost::container::
|
||||
dtl::unvoid_ref<const T>::type const_reference;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
|
||||
typedef boost::container::dtl::
|
||||
version_type<self_t, Version> version;
|
||||
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
typedef boost::container::dtl::
|
||||
basic_multiallocation_chain<void*> multiallocation_chain_void;
|
||||
typedef boost::container::dtl::
|
||||
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, std::size_t N2, std::size_t F2, std::size_t O2, unsigned Version2>
|
||||
adaptive_pool& operator=
|
||||
(const adaptive_pool<T2, N2, F2, O2, Version2>&);
|
||||
|
||||
#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 assignment from other adaptive_pool.
|
||||
adaptive_pool & operator=(const adaptive_pool &) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return *this; }
|
||||
|
||||
//!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)/(2u*sizeof(T)); }
|
||||
|
||||
//!Allocate memory for an array of count elements.
|
||||
//!Throws bad_alloc if there is no enough memory
|
||||
pointer allocate(size_type count, const void * = 0)
|
||||
{
|
||||
if(BOOST_UNLIKELY(count > size_type(-1)/(2u*sizeof(T))))
|
||||
boost::container::throw_bad_alloc();
|
||||
|
||||
if(Version == 1 && count == 1){
|
||||
typedef typename dtl::shared_adaptive_node_pool
|
||||
<sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> shared_pool_t;
|
||||
typedef dtl::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 dtl::shared_adaptive_node_pool
|
||||
<sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> shared_pool_t;
|
||||
typedef dtl::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 dtl::shared_adaptive_node_pool
|
||||
<sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> shared_pool_t;
|
||||
typedef dtl::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 dtl::shared_adaptive_node_pool
|
||||
<sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> shared_pool_t;
|
||||
typedef dtl::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 dtl::shared_adaptive_node_pool
|
||||
<sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> shared_pool_t;
|
||||
typedef dtl::singleton_default<shared_pool_t> singleton_t;
|
||||
singleton_t::instance().deallocate_node(p);
|
||||
}
|
||||
|
||||
void deallocate_individual(multiallocation_chain &chain) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{
|
||||
typedef dtl::shared_adaptive_node_pool
|
||||
<sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> shared_pool_t;
|
||||
typedef dtl::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_CONTAINER_STATIC_ASSERT(( Version > 1 ));/*
|
||||
dlmalloc_memchain ch;
|
||||
BOOST_CONTAINER_MEMCHAIN_INIT(&ch);
|
||||
if(BOOST_UNLIKELY(!dlmalloc_multialloc_nodes(n_elements, elem_size*sizeof(T), BOOST_CONTAINER_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), BOOST_CONTAINER_DL_MULTIALLOC_DEFAULT_CONTIGUOUS
|
||||
, move_detail::force_ptr<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_CONTAINER_STATIC_ASSERT(( Version > 1 ));/*
|
||||
dlmalloc_memchain ch;
|
||||
BOOST_CONTAINER_MEMCHAIN_INIT(&ch);
|
||||
if(BOOST_UNLIKELY(!dlmalloc_multialloc_arrays(n_elements, elem_sizes, sizeof(T), BOOST_CONTAINER_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), BOOST_CONTAINER_DL_MULTIALLOC_DEFAULT_CONTIGUOUS
|
||||
, move_detail::force_ptr<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(move_detail::force_ptr<dlmalloc_memchain *>(&chain));
|
||||
}
|
||||
|
||||
//!Deallocates all free blocks of the pool
|
||||
static void deallocate_free_blocks() BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{
|
||||
typedef dtl::shared_adaptive_node_pool
|
||||
<sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> shared_pool_t;
|
||||
typedef dtl::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;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
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 private_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 private_adaptive_pool
|
||||
<T, NodesPerBlock, MaxFreeBlocks, OverheadPercent
|
||||
BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I Version)
|
||||
> self_t;
|
||||
|
||||
BOOST_STATIC_CONSTEXPR std::size_t nodes_per_block = NodesPerBlock;
|
||||
BOOST_STATIC_CONSTEXPR std::size_t max_free_blocks = MaxFreeBlocks;
|
||||
BOOST_STATIC_CONSTEXPR std::size_t overhead_percent = OverheadPercent;
|
||||
BOOST_STATIC_CONSTEXPR std::size_t real_nodes_per_block = NodesPerBlock;
|
||||
|
||||
BOOST_CONTAINER_DOCIGN(BOOST_CONTAINER_STATIC_ASSERT((Version <=2)));
|
||||
|
||||
typedef dtl::private_adaptive_node_pool
|
||||
<sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> pool_t;
|
||||
pool_t m_pool;
|
||||
|
||||
public:
|
||||
//-------
|
||||
typedef T value_type;
|
||||
typedef T * pointer;
|
||||
typedef const T * const_pointer;
|
||||
typedef typename ::boost::container::
|
||||
dtl::unvoid_ref<T>::type reference;
|
||||
typedef typename ::boost::container::
|
||||
dtl::unvoid_ref<const T>::type const_reference;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
|
||||
typedef boost::container::dtl::
|
||||
version_type<self_t, Version> version;
|
||||
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
typedef boost::container::dtl::
|
||||
basic_multiallocation_chain<void*> multiallocation_chain_void;
|
||||
typedef boost::container::dtl::
|
||||
transform_multiallocation_chain
|
||||
<multiallocation_chain_void, T> multiallocation_chain;
|
||||
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
//!Obtains private_adaptive_pool from
|
||||
//!private_adaptive_pool
|
||||
template<class T2>
|
||||
struct rebind
|
||||
{
|
||||
typedef private_adaptive_pool
|
||||
< T2
|
||||
, NodesPerBlock
|
||||
, MaxFreeBlocks
|
||||
, OverheadPercent
|
||||
BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I Version)
|
||||
> other;
|
||||
};
|
||||
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
private:
|
||||
//!Not assignable from related private_adaptive_pool
|
||||
template<class T2, std::size_t N2, std::size_t F2, std::size_t O2, unsigned Version2>
|
||||
private_adaptive_pool& operator=
|
||||
(const private_adaptive_pool<T2, N2, F2, O2, Version2>&);
|
||||
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
public:
|
||||
//!Default constructor
|
||||
private_adaptive_pool() BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{}
|
||||
|
||||
//!Copy constructor from other private_adaptive_pool.
|
||||
private_adaptive_pool(const private_adaptive_pool &) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{}
|
||||
|
||||
//!Copy assignment from other adaptive_pool.
|
||||
private_adaptive_pool & operator=(const private_adaptive_pool &) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return *this; }
|
||||
|
||||
//!Copy constructor from related private_adaptive_pool.
|
||||
template<class T2>
|
||||
private_adaptive_pool
|
||||
(const private_adaptive_pool<T2, NodesPerBlock, MaxFreeBlocks, OverheadPercent
|
||||
BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I Version)> &) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{}
|
||||
|
||||
//!Destructor
|
||||
~private_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)/(2u*sizeof(T)); }
|
||||
|
||||
//!Allocate memory for an array of count elements.
|
||||
//!Throws bad_alloc if there is no enough memory
|
||||
pointer allocate(size_type count, const void * = 0)
|
||||
{
|
||||
if(BOOST_UNLIKELY(count > size_type(-1)/(2u*sizeof(T))))
|
||||
boost::container::throw_bad_alloc();
|
||||
|
||||
if(Version == 1 && count == 1){
|
||||
return pointer(static_cast<T*>(m_pool.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){
|
||||
m_pool.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()
|
||||
{
|
||||
return (pointer)m_pool.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)
|
||||
{
|
||||
m_pool.allocate_nodes(num_elements, static_cast<typename pool_t::multiallocation_chain&>(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(). Never throws
|
||||
void deallocate_one(pointer p) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{
|
||||
m_pool.deallocate_node(p);
|
||||
}
|
||||
|
||||
void deallocate_individual(multiallocation_chain &chain) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{
|
||||
m_pool.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_CONTAINER_STATIC_ASSERT(( Version > 1 ));
|
||||
if(BOOST_UNLIKELY(!dlmalloc_multialloc_nodes
|
||||
( n_elements, elem_size*sizeof(T), BOOST_CONTAINER_DL_MULTIALLOC_DEFAULT_CONTIGUOUS
|
||||
, move_detail::force_ptr<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_CONTAINER_STATIC_ASSERT(( Version > 1 ));
|
||||
if(BOOST_UNLIKELY(!dlmalloc_multialloc_arrays
|
||||
(n_elements, elem_sizes, sizeof(T), BOOST_CONTAINER_DL_MULTIALLOC_DEFAULT_CONTIGUOUS
|
||||
, move_detail::force_ptr<dlmalloc_memchain *>(&chain)))){
|
||||
boost::container::throw_bad_alloc();
|
||||
}
|
||||
}
|
||||
|
||||
void deallocate_many(multiallocation_chain &chain) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{
|
||||
dlmalloc_multidealloc(move_detail::force_ptr<dlmalloc_memchain *>(&chain));
|
||||
}
|
||||
|
||||
//!Deallocates all free blocks of the pool
|
||||
void deallocate_free_blocks() BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{
|
||||
m_pool.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(private_adaptive_pool &, private_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 private_adaptive_pool &, const private_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 private_adaptive_pool &, const private_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
|
||||
376
include/boost/container/allocator.hpp
Normal file
376
include/boost/container/allocator.hpp
Normal file
@@ -0,0 +1,376 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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/move/detail/force_ptr.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::dtl::
|
||||
version_type<self_t, Version> version;
|
||||
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
typedef boost::container::dtl::
|
||||
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>&);
|
||||
|
||||
BOOST_STATIC_CONSTEXPR 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_CONTAINER_STATIC_ASSERT(( (AllocationDisableMask & ForbiddenMask) != ForbiddenMask ));
|
||||
|
||||
//The mask is only valid for version 2 allocators
|
||||
BOOST_CONTAINER_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::dtl::
|
||||
version_type<self_t, Version> version;
|
||||
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
typedef boost::container::dtl::
|
||||
basic_multiallocation_chain<void*> void_multiallocation_chain;
|
||||
|
||||
typedef boost::container::dtl::
|
||||
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 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()
|
||||
BOOST_CONTAINER_ATTRIBUTE_NODISCARD pointer allocate(size_type count, const void * hint= 0)
|
||||
{
|
||||
(void)hint;
|
||||
if(count > size_type(-1)/(2u*sizeof(T)))
|
||||
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
|
||||
inline 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
|
||||
inline size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return size_type(-1)/(2u*sizeof(T)); }
|
||||
|
||||
//!Swaps two allocators, does nothing
|
||||
//!because this allocator is stateless
|
||||
inline 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
|
||||
BOOST_CONTAINER_ATTRIBUTE_NODISCARD
|
||||
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
|
||||
BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
|
||||
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
|
||||
BOOST_CONTAINER_ATTRIBUTE_NODISCARD pointer allocation_command(allocation_type command,
|
||||
size_type limit_size,
|
||||
size_type &prefer_in_recvd_out_size,
|
||||
pointer &reuse)
|
||||
{
|
||||
BOOST_CONTAINER_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
|
||||
BOOST_CONTAINER_ATTRIBUTE_NODISCARD size_type size(pointer p) const BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{
|
||||
BOOST_CONTAINER_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
|
||||
BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline pointer allocate_one()
|
||||
{
|
||||
BOOST_CONTAINER_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
|
||||
inline void allocate_individual(std::size_t num_elements, multiallocation_chain &chain)
|
||||
{
|
||||
BOOST_CONTAINER_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_CONTAINER_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
|
||||
inline
|
||||
void deallocate_individual(multiallocation_chain &chain) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{
|
||||
BOOST_CONTAINER_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_CONTAINER_STATIC_ASSERT(( Version > 1 ));
|
||||
dlmalloc_memchain ch;
|
||||
BOOST_CONTAINER_MEMCHAIN_INIT(&ch);
|
||||
if(!dlmalloc_multialloc_nodes(n_elements, elem_size*sizeof(T), BOOST_CONTAINER_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), BOOST_CONTAINER_DL_MULTIALLOC_DEFAULT_CONTIGUOUS
|
||||
, move_detail::force_ptr<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_CONTAINER_STATIC_ASSERT(( Version > 1 ));
|
||||
dlmalloc_memchain ch;
|
||||
BOOST_CONTAINER_MEMCHAIN_INIT(&ch);
|
||||
if(!dlmalloc_multialloc_arrays(n_elements, elem_sizes, sizeof(T), BOOST_CONTAINER_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), BOOST_CONTAINER_DL_MULTIALLOC_DEFAULT_CONTIGUOUS
|
||||
, move_detail::force_ptr<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_CONTAINER_STATIC_ASSERT(( Version > 1 ));
|
||||
dlmalloc_memchain ch;
|
||||
void *beg(&*chain.begin()), *last(&*chain.last());
|
||||
size_t sz(chain.size());
|
||||
BOOST_CONTAINER_MEMCHAIN_INIT_FROM(&ch, beg, last, sz);
|
||||
dlmalloc_multidealloc(&ch);
|
||||
//dlmalloc_multidealloc(move_detail::force_ptr<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
|
||||
|
||||
708
include/boost/container/allocator_traits.hpp
Normal file
708
include/boost/container/allocator_traits.hpp
Normal file
@@ -0,0 +1,708 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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>
|
||||
#include <boost/container/detail/is_pair.hpp>
|
||||
#include <boost/container/detail/addressof.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
|
||||
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
#if defined(BOOST_CONTAINER_GCC_COMPATIBLE_HAS_DIAGNOSTIC_IGNORED)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-result"
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#endif
|
||||
|
||||
#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 dtl {
|
||||
#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 dtl {
|
||||
#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 dtl {
|
||||
#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>
|
||||
|
||||
#if defined(BOOST_CONTAINER_GCC_COMPATIBLE_HAS_DIAGNOSTIC_IGNORED)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace dtl {
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
template<class T, class ...Args>
|
||||
BOOST_CONTAINER_FORCEINLINE void construct_type(T *p, BOOST_FWD_REF(Args) ...args)
|
||||
{
|
||||
::new(const_cast<void*>(static_cast<const volatile void*>(p)), boost_container_new_t()) T(::boost::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define BOOST_CONTAINER_ALLOCATOR_TRAITS_CONSTRUCT_TYPEJ(N) \
|
||||
template<class T BOOST_MOVE_I##N BOOST_MOVE_CLASS##N>\
|
||||
BOOST_CONTAINER_FORCEINLINE \
|
||||
typename dtl::disable_if_c<dtl::is_pair<T>::value, void >::type \
|
||||
construct_type(T *p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
|
||||
{\
|
||||
::new(const_cast<void*>(static_cast<const volatile void*>(p)), boost_container_new_t()) T( BOOST_MOVE_FWD##N );\
|
||||
}\
|
||||
//
|
||||
BOOST_MOVE_ITERATE_0TO8(BOOST_CONTAINER_ALLOCATOR_TRAITS_CONSTRUCT_TYPEJ)
|
||||
#undef BOOST_CONTAINER_ALLOCATOR_TRAITS_CONSTRUCT_TYPEJ
|
||||
|
||||
#endif
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
typename dtl::enable_if<dtl::is_pair<T>, void >::type
|
||||
construct_type(T* p)
|
||||
{
|
||||
dtl::construct_type(dtl::addressof(p->first));
|
||||
BOOST_CONTAINER_TRY{
|
||||
dtl::construct_type(dtl::addressof(p->second));
|
||||
}
|
||||
BOOST_CONTAINER_CATCH(...) {
|
||||
typedef typename T::first_type first_type;
|
||||
dtl::addressof(p->first)->~first_type();
|
||||
BOOST_CONTAINER_RETHROW
|
||||
}
|
||||
BOOST_CONTAINER_CATCH_END
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
inline
|
||||
typename dtl::enable_if_c
|
||||
< dtl::is_pair<T>::value
|
||||
, void >::type
|
||||
construct_type(T* p, U &u)
|
||||
{
|
||||
dtl::construct_type(dtl::addressof(p->first), u.first);
|
||||
BOOST_CONTAINER_TRY{
|
||||
dtl::construct_type(dtl::addressof(p->second), u.second);
|
||||
}
|
||||
BOOST_CONTAINER_CATCH(...) {
|
||||
typedef typename T::first_type first_type;
|
||||
dtl::addressof(p->first)->~first_type();
|
||||
BOOST_CONTAINER_RETHROW
|
||||
}
|
||||
BOOST_CONTAINER_CATCH_END
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
inline
|
||||
typename dtl::enable_if_c
|
||||
< dtl::is_pair<typename dtl::remove_reference<T>::type>::value &&
|
||||
!boost::move_detail::is_reference<U>::value //This is needed for MSVC10 and ambiguous overloads
|
||||
, void >::type
|
||||
construct_type(T* p, BOOST_RV_REF(U) u)
|
||||
{
|
||||
dtl::construct_type(dtl::addressof(p->first), ::boost::move(u.first));
|
||||
BOOST_CONTAINER_TRY{
|
||||
dtl::construct_type(dtl::addressof(p->second), ::boost::move(u.second));
|
||||
}
|
||||
BOOST_CONTAINER_CATCH(...) {
|
||||
typedef typename T::first_type first_type;
|
||||
dtl::addressof(p->first)->~first_type();
|
||||
BOOST_CONTAINER_RETHROW
|
||||
}
|
||||
BOOST_CONTAINER_CATCH_END
|
||||
}
|
||||
|
||||
template<class T, class U, class V>
|
||||
inline
|
||||
typename dtl::enable_if<dtl::is_pair<T>, void >::type
|
||||
construct_type(T* p, BOOST_FWD_REF(U) x, BOOST_FWD_REF(V) y)
|
||||
{
|
||||
dtl::construct_type(dtl::addressof(p->first), ::boost::forward<U>(x));
|
||||
BOOST_CONTAINER_TRY{
|
||||
dtl::construct_type(dtl::addressof(p->second), ::boost::forward<V>(y));
|
||||
}
|
||||
BOOST_CONTAINER_CATCH(...) {
|
||||
typedef typename T::first_type first_type;
|
||||
dtl::addressof(p->first)->~first_type();
|
||||
BOOST_CONTAINER_RETHROW
|
||||
}
|
||||
BOOST_CONTAINER_CATCH_END
|
||||
}
|
||||
|
||||
} //namespace dtl
|
||||
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
template<class T, class VoidAllocator, class Options>
|
||||
class small_vector_allocator;
|
||||
|
||||
namespace allocator_traits_detail {
|
||||
|
||||
#if defined(BOOST_CONTAINER_GCC_COMPATIBLE_HAS_DIAGNOSTIC_IGNORED)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#endif
|
||||
|
||||
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)
|
||||
|
||||
|
||||
#if defined(BOOST_CONTAINER_GCC_COMPATIBLE_HAS_DIAGNOSTIC_IGNORED)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
} //namespace allocator_traits_detail {
|
||||
|
||||
namespace dtl {
|
||||
|
||||
//workaround needed for C++03 compilers with no construct()
|
||||
//supporting rvalue references
|
||||
template<class Allocator>
|
||||
struct is_std_allocator
|
||||
{ BOOST_STATIC_CONSTEXPR bool value = false; };
|
||||
|
||||
template<class T>
|
||||
struct is_std_allocator< std::allocator<T> >
|
||||
{ BOOST_STATIC_CONSTEXPR bool value = true; };
|
||||
|
||||
template<class T, class Options>
|
||||
struct is_std_allocator< small_vector_allocator<T, std::allocator<T>, Options > >
|
||||
{ BOOST_STATIC_CONSTEXPR bool value = true; };
|
||||
|
||||
template<class Allocator>
|
||||
struct is_not_std_allocator
|
||||
{ BOOST_STATIC_CONSTEXPR bool value = !is_std_allocator<Allocator>::value; };
|
||||
|
||||
#if defined(BOOST_CONTAINER_GCC_COMPATIBLE_HAS_DIAGNOSTIC_IGNORED)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#endif
|
||||
|
||||
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)
|
||||
|
||||
#if defined(BOOST_CONTAINER_GCC_COMPATIBLE_HAS_DIAGNOSTIC_IGNORED)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
} //namespace dtl {
|
||||
|
||||
#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 ; otherwise, 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::dtl::, Allocator,
|
||||
pointer, value_type*)
|
||||
pointer;
|
||||
//const_pointer
|
||||
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_EVAL_DEFAULT(boost::container::dtl::, 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::dtl::, Allocator,
|
||||
reference, typename dtl::unvoid_ref<value_type>::type)
|
||||
reference;
|
||||
//const_reference
|
||||
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::dtl::, Allocator,
|
||||
const_reference, typename dtl::unvoid_ref<const value_type>::type)
|
||||
const_reference;
|
||||
//void_pointer
|
||||
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_EVAL_DEFAULT(boost::container::dtl::, 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::dtl::, 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::dtl::, Allocator,
|
||||
difference_type, std::ptrdiff_t)
|
||||
difference_type;
|
||||
//size_type
|
||||
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::dtl::, Allocator,
|
||||
size_type, std::size_t)
|
||||
size_type;
|
||||
//propagate_on_container_copy_assignment
|
||||
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::dtl::, Allocator,
|
||||
propagate_on_container_copy_assignment, dtl::false_type)
|
||||
propagate_on_container_copy_assignment;
|
||||
//propagate_on_container_move_assignment
|
||||
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::dtl::, Allocator,
|
||||
propagate_on_container_move_assignment, dtl::false_type)
|
||||
propagate_on_container_move_assignment;
|
||||
//propagate_on_container_swap
|
||||
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::dtl::, Allocator,
|
||||
propagate_on_container_swap, dtl::false_type)
|
||||
propagate_on_container_swap;
|
||||
//is_always_equal
|
||||
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::dtl::, Allocator,
|
||||
is_always_equal, dtl::is_empty<Allocator>)
|
||||
is_always_equal;
|
||||
//is_partially_propagable
|
||||
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::dtl::, Allocator,
|
||||
is_partially_propagable, dtl::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>
|
||||
//!
|
||||
inline 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
|
||||
inline 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>
|
||||
inline static pointer allocate(Allocator &a, size_type n, const_void_pointer p)
|
||||
{
|
||||
const bool value = boost::container::dtl::
|
||||
has_member_function_callable_with_allocate
|
||||
<Allocator, const size_type, const const_void_pointer>::value;
|
||||
dtl::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>
|
||||
inline static void destroy(Allocator &a, T*p) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{
|
||||
typedef T* destroy_pointer;
|
||||
const bool value = boost::container::dtl::
|
||||
has_member_function_callable_with_destroy
|
||||
<Allocator, const destroy_pointer>::value;
|
||||
dtl::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>.
|
||||
inline 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;
|
||||
dtl::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.
|
||||
inline static BOOST_CONTAINER_DOC1ST(Allocator,
|
||||
typename dtl::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;
|
||||
dtl::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>`placement new` (static_cast<void*>(p)) T(std::forward<Args>(args)...)</code>
|
||||
template <class T, class ...Args>
|
||||
inline static void construct(Allocator & a, T* p, BOOST_FWD_REF(Args)... args)
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR bool value = ::boost::move_detail::and_
|
||||
< dtl::is_not_std_allocator<Allocator>
|
||||
, boost::container::dtl::has_member_function_callable_with_construct
|
||||
< Allocator, T*, Args... >
|
||||
>::value;
|
||||
dtl::bool_<value> flag;
|
||||
allocator_traits::priv_construct(flag, a, p, ::boost::forward<Args>(args)...);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
|
||||
template < class Pair, class KeyType, class ... Args>
|
||||
static typename dtl::enable_if< dtl::is_pair<Pair>, void >::type construct
|
||||
(Allocator & a, Pair* p, try_emplace_t, BOOST_FWD_REF(KeyType) k, BOOST_FWD_REF(Args) ...args)
|
||||
{
|
||||
allocator_traits::construct(a, dtl::addressof(p->first), ::boost::forward<KeyType>(k));
|
||||
BOOST_CONTAINER_TRY{
|
||||
allocator_traits::construct(a, dtl::addressof(p->second), ::boost::forward<Args>(args)...);
|
||||
}
|
||||
BOOST_CONTAINER_CATCH(...) {
|
||||
typedef typename Pair::first_type first_type;
|
||||
dtl::addressof(p->first)->~first_type();
|
||||
BOOST_CONTAINER_RETHROW
|
||||
}
|
||||
BOOST_CONTAINER_CATCH_END
|
||||
}
|
||||
#endif
|
||||
|
||||
//! <b>Returns</b>: <code>a.storage_is_unpropagable(p)</code> if is_partially_propagable::value is true; otherwise,
|
||||
//! <code>false</code>.
|
||||
inline static bool storage_is_unpropagable(const Allocator &a, pointer p) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{
|
||||
dtl::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>.
|
||||
inline static bool equal(const Allocator &a, const Allocator &b) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{
|
||||
dtl::bool_<is_always_equal::value> flag;
|
||||
return allocator_traits::priv_equal(flag, a, b);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
private:
|
||||
inline static pointer priv_allocate(dtl::true_type, Allocator &a, size_type n, const_void_pointer p)
|
||||
{ return a.allocate(n, p); }
|
||||
|
||||
inline static pointer priv_allocate(dtl::false_type, Allocator &a, size_type n, const_void_pointer)
|
||||
{ return a.allocate(n); }
|
||||
|
||||
#if defined(BOOST_CONTAINER_GCC_COMPATIBLE_HAS_DIAGNOSTIC_IGNORED)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#endif
|
||||
|
||||
template<class T>
|
||||
inline static void priv_destroy(dtl::true_type, Allocator &a, T* p) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ a.destroy(p); }
|
||||
|
||||
#if defined(BOOST_CONTAINER_GCC_COMPATIBLE_HAS_DIAGNOSTIC_IGNORED)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
template<class T>
|
||||
inline static void priv_destroy(dtl::false_type, Allocator &, T* p) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ p->~T(); (void)p; }
|
||||
|
||||
#if defined(BOOST_CONTAINER_GCC_COMPATIBLE_HAS_DIAGNOSTIC_IGNORED)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#endif
|
||||
|
||||
inline static size_type priv_max_size(dtl::true_type, const Allocator &a) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return a.max_size(); }
|
||||
|
||||
#if defined(BOOST_CONTAINER_GCC_COMPATIBLE_HAS_DIAGNOSTIC_IGNORED)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
inline static size_type priv_max_size(dtl::false_type, const Allocator &) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return size_type(-1)/sizeof(value_type); }
|
||||
|
||||
inline static Allocator priv_select_on_container_copy_construction(dtl::true_type, const Allocator &a)
|
||||
{ return a.select_on_container_copy_construction(); }
|
||||
|
||||
inline static const Allocator &priv_select_on_container_copy_construction(dtl::false_type, const Allocator &a) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return a; }
|
||||
|
||||
|
||||
#if defined(BOOST_CONTAINER_GCC_COMPATIBLE_HAS_DIAGNOSTIC_IGNORED)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
template<class T, class ...Args>
|
||||
inline static void priv_construct(dtl::true_type, Allocator &a, T *p, BOOST_FWD_REF(Args) ...args)
|
||||
{ a.construct( p, ::boost::forward<Args>(args)...); }
|
||||
|
||||
template<class T, class KeyType, class ...Args>
|
||||
inline static typename dtl::enable_if< dtl::is_pair<T>, void >::type
|
||||
priv_construct(dtl::true_type, Allocator &a, T *p, try_emplace_t, BOOST_FWD_REF(KeyType) k, BOOST_FWD_REF(Args) ...args)
|
||||
{
|
||||
a.construct(dtl::addressof(p->first), ::boost::forward<KeyType>(k));
|
||||
BOOST_CONTAINER_TRY{
|
||||
a.construct(dtl::addressof(p->second), ::boost::forward<Args>(args)...);
|
||||
}
|
||||
BOOST_CONTAINER_CATCH(...) {
|
||||
typedef typename T::first_type first_type;
|
||||
dtl::addressof(p->first)->~first_type();
|
||||
BOOST_CONTAINER_RETHROW
|
||||
}
|
||||
BOOST_CONTAINER_CATCH_END
|
||||
}
|
||||
|
||||
template<class T, class ...Args>
|
||||
inline static void priv_construct(dtl::false_type, Allocator &, T *p, BOOST_FWD_REF(Args) ...args)
|
||||
{ dtl::construct_type(p, ::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 >\
|
||||
inline static void construct(Allocator &a, T *p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
|
||||
{\
|
||||
BOOST_STATIC_CONSTEXPR bool value = ::boost::move_detail::and_ \
|
||||
< dtl::is_not_std_allocator<Allocator> \
|
||||
, boost::container::dtl::has_member_function_callable_with_construct \
|
||||
< Allocator, T* BOOST_MOVE_I##N BOOST_MOVE_FWD_T##N > \
|
||||
>::value; \
|
||||
dtl::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
|
||||
|
||||
#define BOOST_CONTAINER_ALLOCATOR_TRAITS_CONSTRUCT_IMPL(N) \
|
||||
template<class T, class KeyType BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
|
||||
inline static typename dtl::enable_if< dtl::is_pair<T>, void >::type\
|
||||
construct(Allocator &a, T *p, try_emplace_t, BOOST_FWD_REF(KeyType) k BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
|
||||
{\
|
||||
allocator_traits::construct(a, dtl::addressof(p->first), ::boost::forward<KeyType>(k));\
|
||||
BOOST_CONTAINER_TRY{\
|
||||
allocator_traits::construct(a, dtl::addressof(p->second) BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
|
||||
}\
|
||||
BOOST_CONTAINER_CATCH(...) {\
|
||||
typedef typename T::first_type first_type;\
|
||||
dtl::addressof(p->first)->~first_type();\
|
||||
BOOST_CONTAINER_RETHROW\
|
||||
}\
|
||||
BOOST_CONTAINER_CATCH_END\
|
||||
}\
|
||||
\
|
||||
//
|
||||
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 >\
|
||||
inline static void priv_construct(dtl::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 >\
|
||||
inline static void priv_construct(dtl::false_type, Allocator &, T *p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
|
||||
{ dtl::construct_type(p BOOST_MOVE_I##N 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)
|
||||
|
||||
#if defined(BOOST_CONTAINER_GCC_COMPATIBLE_HAS_DIAGNOSTIC_IGNORED)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
|
||||
template<class T>
|
||||
inline static void priv_construct(dtl::false_type, Allocator &, T *p, const ::boost::container::default_init_t&)
|
||||
{ ::new((void*)p, boost_container_new_t()) T; }
|
||||
|
||||
inline static bool priv_storage_is_unpropagable(dtl::true_type, const Allocator &a, pointer p)
|
||||
{ return a.storage_is_unpropagable(p); }
|
||||
|
||||
inline static bool priv_storage_is_unpropagable(dtl::false_type, const Allocator &, pointer)
|
||||
{ return false; }
|
||||
|
||||
inline static bool priv_equal(dtl::true_type, const Allocator &, const Allocator &)
|
||||
{ return true; }
|
||||
|
||||
inline static bool priv_equal(dtl::false_type, const Allocator &a, const Allocator &b)
|
||||
{ return a == b; }
|
||||
|
||||
#endif //#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
};
|
||||
|
||||
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
|
||||
template<class T, class AllocatorOrVoid>
|
||||
struct real_allocator
|
||||
{
|
||||
typedef AllocatorOrVoid type;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct real_allocator<T, void>
|
||||
{
|
||||
typedef new_allocator<T> type;
|
||||
};
|
||||
|
||||
#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)
|
||||
390
include/boost/container/container_fwd.hpp
Normal file
390
include/boost/container/container_fwd.hpp
Normal file
@@ -0,0 +1,390 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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
|
||||
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
|
||||
#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_base
|
||||
//! - boost::container::small_vector
|
||||
//! - boost::container::devector
|
||||
//! - 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 dtl{
|
||||
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 {
|
||||
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
template<class T>
|
||||
class new_allocator;
|
||||
|
||||
template <class T
|
||||
,class Allocator = void
|
||||
,class Options = void>
|
||||
class vector;
|
||||
|
||||
template <class T
|
||||
,class Allocator = void >
|
||||
class stable_vector;
|
||||
|
||||
template < class T
|
||||
, std::size_t Capacity
|
||||
, class Options = void>
|
||||
class static_vector;
|
||||
|
||||
template < class T
|
||||
, class Allocator = void
|
||||
, class Options = void >
|
||||
class small_vector_base;
|
||||
|
||||
template < class T
|
||||
, std::size_t N
|
||||
, class Allocator = void
|
||||
, class Options = void >
|
||||
class small_vector;
|
||||
|
||||
template <class T
|
||||
,class Allocator = void
|
||||
,class Options = void>
|
||||
class devector;
|
||||
|
||||
template <class T
|
||||
,class Allocator = void
|
||||
,class Options = void>
|
||||
class deque;
|
||||
|
||||
template <class T
|
||||
,class Allocator = void >
|
||||
class list;
|
||||
|
||||
template <class T
|
||||
,class Allocator = void >
|
||||
class slist;
|
||||
|
||||
template <class Key
|
||||
,class Compare = std::less<Key>
|
||||
,class Allocator = void
|
||||
,class Options = void>
|
||||
class set;
|
||||
|
||||
template <class Key
|
||||
,class Compare = std::less<Key>
|
||||
,class Allocator = void
|
||||
,class Options = void >
|
||||
class multiset;
|
||||
|
||||
template <class Key
|
||||
,class T
|
||||
,class Compare = std::less<Key>
|
||||
,class Allocator = void
|
||||
,class Options = void >
|
||||
class map;
|
||||
|
||||
template <class Key
|
||||
,class T
|
||||
,class Compare = std::less<Key>
|
||||
,class Allocator = void
|
||||
,class Options = void >
|
||||
class multimap;
|
||||
|
||||
template <class Key
|
||||
,class Compare = std::less<Key>
|
||||
,class Allocator = void >
|
||||
class flat_set;
|
||||
|
||||
template <class Key
|
||||
,class Compare = std::less<Key>
|
||||
,class Allocator = void >
|
||||
class flat_multiset;
|
||||
|
||||
template <class Key
|
||||
,class T
|
||||
,class Compare = std::less<Key>
|
||||
,class Allocator = void >
|
||||
class flat_map;
|
||||
|
||||
template <class Key
|
||||
,class T
|
||||
,class Compare = std::less<Key>
|
||||
,class Allocator = void >
|
||||
class flat_multimap;
|
||||
|
||||
#ifndef BOOST_NO_CXX11_TEMPLATE_ALIASES
|
||||
|
||||
//! Alias templates for small_flat_[multi]{set|map} using small_vector as container
|
||||
|
||||
template < class Key
|
||||
, std::size_t N
|
||||
, class Compare = std::less<Key>
|
||||
, class SmallVectorAllocator = void
|
||||
, class SmallVectorOptions = void >
|
||||
using small_flat_set = flat_set<Key, Compare, small_vector<Key, N, SmallVectorAllocator, SmallVectorOptions>>;
|
||||
|
||||
template < class Key
|
||||
, std::size_t N
|
||||
, class Compare = std::less<Key>
|
||||
, class SmallVectorAllocator = void
|
||||
, class SmallVectorOptions = void >
|
||||
using small_flat_multiset = flat_multiset<Key, Compare, small_vector<Key, N, SmallVectorAllocator, SmallVectorOptions>>;
|
||||
|
||||
template < class Key
|
||||
, class T
|
||||
, std::size_t N
|
||||
, class Compare = std::less<Key>
|
||||
, class SmallVectorAllocator = void
|
||||
, class SmallVectorOptions = void >
|
||||
using small_flat_map = flat_map<Key, T, Compare, small_vector<std::pair<Key, T>, N, SmallVectorAllocator, SmallVectorOptions>>;
|
||||
|
||||
template < class Key
|
||||
, class T
|
||||
, std::size_t N
|
||||
, class Compare = std::less<Key>
|
||||
, class SmallVectorAllocator = void
|
||||
, class SmallVectorOptions = void >
|
||||
using small_flat_multimap = flat_multimap<Key, T, Compare, small_vector<std::pair<Key, T>, N, SmallVectorAllocator, SmallVectorOptions>>;
|
||||
|
||||
#endif // #ifndef BOOST_NO_CXX11_TEMPLATE_ALIASES
|
||||
|
||||
|
||||
//! A portable metafunction to obtain a small_flat_set
|
||||
template < class Key
|
||||
, std::size_t N
|
||||
, class Compare = std::less<Key>
|
||||
, class SmallVectorAllocator = void
|
||||
, class SmallVectorOptions = void >
|
||||
struct small_flat_set_of
|
||||
{
|
||||
typedef flat_set<Key, Compare, small_vector<Key, N, SmallVectorAllocator, SmallVectorOptions> > type;
|
||||
};
|
||||
|
||||
//! A portable metafunction to obtain a small_flat_multiset
|
||||
template < class Key
|
||||
, std::size_t N
|
||||
, class Compare = std::less<Key>
|
||||
, class SmallVectorAllocator = void
|
||||
, class SmallVectorOptions = void >
|
||||
struct small_flat_multiset_of
|
||||
{
|
||||
typedef flat_multiset<Key, Compare, small_vector<Key, N, SmallVectorAllocator, SmallVectorOptions> > type;
|
||||
};
|
||||
|
||||
//! A portable metafunction to obtain a small_flat_map
|
||||
template < class Key
|
||||
, class T
|
||||
, std::size_t N
|
||||
, class Compare = std::less<Key>
|
||||
, class SmallVectorAllocator = void
|
||||
, class SmallVectorOptions = void >
|
||||
struct small_flat_map_of
|
||||
{
|
||||
typedef flat_map<Key, T, Compare, small_vector<std::pair<Key, T>, N, SmallVectorAllocator, SmallVectorOptions> > type;
|
||||
};
|
||||
|
||||
//! A portable metafunction to obtain a small_flat_multimap
|
||||
template < class Key
|
||||
, class T
|
||||
, std::size_t N
|
||||
, class Compare = std::less<Key>
|
||||
, class SmallVectorAllocator = void
|
||||
, class SmallVectorOptions = void >
|
||||
struct small_flat_multimap_of
|
||||
{
|
||||
typedef flat_multimap<Key, T, Compare, small_vector<std::pair<Key, T>, N, SmallVectorAllocator, SmallVectorOptions> > type;
|
||||
};
|
||||
|
||||
template <class CharT
|
||||
,class Traits = std::char_traits<CharT>
|
||||
,class Allocator = void >
|
||||
class basic_string;
|
||||
|
||||
typedef basic_string <char> string;
|
||||
typedef basic_string<wchar_t> wstring;
|
||||
|
||||
BOOST_STATIC_CONSTEXPR std::size_t ADP_nodes_per_block = 256u;
|
||||
BOOST_STATIC_CONSTEXPR std::size_t ADP_max_free_blocks = 2u;
|
||||
BOOST_STATIC_CONSTEXPR std::size_t ADP_overhead_percent = 1u;
|
||||
BOOST_STATIC_CONSTEXPR 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;
|
||||
|
||||
BOOST_STATIC_CONSTEXPR 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 {
|
||||
|
||||
#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
|
||||
BOOST_CONTAINER_CONSTANT_VAR 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
|
||||
BOOST_CONTAINER_CONSTANT_VAR 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
|
||||
BOOST_CONTAINER_CONSTANT_VAR 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
|
||||
BOOST_CONTAINER_CONSTANT_VAR 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 {
|
||||
|
||||
typedef const std::piecewise_construct_t & piecewise_construct_t;
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
}} //namespace boost { namespace container {
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_CONTAINER_FWD_HPP
|
||||
3114
include/boost/container/deque.hpp
Normal file
3114
include/boost/container/deque.hpp
Normal file
File diff suppressed because it is too large
Load Diff
169
include/boost/container/detail/adaptive_node_pool.hpp
Normal file
169
include/boost/container/detail/adaptive_node_pool.hpp
Normal file
@@ -0,0 +1,169 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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 dtl {
|
||||
|
||||
//!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 private_adaptive_node_pool_impl_ct
|
||||
< fake_segment_manager
|
||||
, MaxFreeBlocks
|
||||
, NodeSize
|
||||
, NodesPerBlock
|
||||
, OverheadPercent
|
||||
, unsigned(OverheadPercent == 0)*::boost::container::adaptive_pool_flag::align_only
|
||||
| ::boost::container::adaptive_pool_flag::size_ordered
|
||||
| ::boost::container::adaptive_pool_flag::address_ordered
|
||||
>
|
||||
{
|
||||
typedef private_adaptive_node_pool_impl_ct
|
||||
< fake_segment_manager
|
||||
, MaxFreeBlocks
|
||||
, NodeSize
|
||||
, NodesPerBlock
|
||||
, OverheadPercent
|
||||
, unsigned(OverheadPercent == 0)*::boost::container::adaptive_pool_flag::align_only
|
||||
| ::boost::container::adaptive_pool_flag::size_ordered
|
||||
| ::boost::container::adaptive_pool_flag::address_ordered
|
||||
> base_t;
|
||||
|
||||
//Non-copyable
|
||||
private_adaptive_node_pool(const private_adaptive_node_pool &);
|
||||
private_adaptive_node_pool &operator=(const private_adaptive_node_pool &);
|
||||
|
||||
public:
|
||||
BOOST_STATIC_CONSTEXPR std::size_t nodes_per_block = NodesPerBlock;
|
||||
|
||||
//!Constructor. Never throws
|
||||
private_adaptive_node_pool()
|
||||
: base_t(0)
|
||||
{}
|
||||
};
|
||||
|
||||
//!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 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 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 dtl {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DETAIL_ADAPTIVE_NODE_POOL_HPP
|
||||
1260
include/boost/container/detail/adaptive_node_pool_impl.hpp
Normal file
1260
include/boost/container/detail/adaptive_node_pool_impl.hpp
Normal file
File diff suppressed because it is too large
Load Diff
33
include/boost/container/detail/addressof.hpp
Normal file
33
include/boost/container/detail/addressof.hpp
Normal file
@@ -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_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 <boost/move/detail/addressof.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace dtl {
|
||||
|
||||
using boost::move_detail::addressof;
|
||||
|
||||
} //namespace dtl {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DETAIL_ADDRESSOF_HPP
|
||||
544
include/boost/container/detail/advanced_insert_int.hpp
Normal file
544
include/boost/container/detail/advanced_insert_int.hpp
Normal file
@@ -0,0 +1,544 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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/move/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>
|
||||
#include <boost/move/detail/force_ptr.hpp>
|
||||
#include <boost/move/detail/launder.hpp>
|
||||
// other
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
namespace boost { namespace container { namespace dtl {
|
||||
|
||||
template<class Allocator, class FwdIt>
|
||||
struct move_insert_range_proxy
|
||||
{
|
||||
typedef typename allocator_traits<Allocator>::value_type value_type;
|
||||
|
||||
inline explicit move_insert_range_proxy(FwdIt first)
|
||||
: first_(first)
|
||||
{}
|
||||
|
||||
template<class Iterator>
|
||||
inline void uninitialized_copy_n_and_update(Allocator &a, Iterator p, std::size_t n)
|
||||
{
|
||||
this->first_ = ::boost::container::uninitialized_move_alloc_n_source
|
||||
(a, this->first_, n, p);
|
||||
}
|
||||
|
||||
template<class Iterator>
|
||||
inline void copy_n_and_update(Allocator &, Iterator p, std::size_t n)
|
||||
{
|
||||
this->first_ = ::boost::container::move_n_source(this->first_, n, p);
|
||||
}
|
||||
|
||||
FwdIt first_;
|
||||
};
|
||||
|
||||
|
||||
template<class Allocator, class FwdIt>
|
||||
struct insert_range_proxy
|
||||
{
|
||||
typedef typename allocator_traits<Allocator>::value_type value_type;
|
||||
|
||||
inline explicit insert_range_proxy(FwdIt first)
|
||||
: first_(first)
|
||||
{}
|
||||
|
||||
template<class Iterator>
|
||||
inline void uninitialized_copy_n_and_update(Allocator &a, Iterator p, std::size_t n)
|
||||
{
|
||||
this->first_ = ::boost::container::uninitialized_copy_alloc_n_source(a, this->first_, n, p);
|
||||
}
|
||||
|
||||
template<class Iterator>
|
||||
inline void copy_n_and_update(Allocator &, Iterator p, std::size_t n)
|
||||
{
|
||||
this->first_ = ::boost::container::copy_n_source(this->first_, n, p);
|
||||
}
|
||||
|
||||
FwdIt first_;
|
||||
};
|
||||
|
||||
|
||||
template<class Allocator>
|
||||
struct insert_n_copies_proxy
|
||||
{
|
||||
typedef typename allocator_traits<Allocator>::value_type value_type;
|
||||
|
||||
inline explicit insert_n_copies_proxy(const value_type &v)
|
||||
: v_(v)
|
||||
{}
|
||||
|
||||
template<class Iterator>
|
||||
inline void uninitialized_copy_n_and_update(Allocator &a, Iterator p, std::size_t n) const
|
||||
{ boost::container::uninitialized_fill_alloc_n(a, v_, n, p); }
|
||||
|
||||
template<class Iterator>
|
||||
inline void copy_n_and_update(Allocator &, Iterator p, std::size_t n) const
|
||||
{
|
||||
while (n){
|
||||
--n;
|
||||
*p = v_;
|
||||
++p;
|
||||
}
|
||||
}
|
||||
|
||||
const value_type &v_;
|
||||
};
|
||||
|
||||
template<class Allocator>
|
||||
struct insert_value_initialized_n_proxy
|
||||
{
|
||||
typedef ::boost::container::allocator_traits<Allocator> alloc_traits;
|
||||
typedef typename allocator_traits<Allocator>::value_type value_type;
|
||||
typedef typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type storage_t;
|
||||
|
||||
template<class Iterator>
|
||||
inline void uninitialized_copy_n_and_update(Allocator &a, Iterator p, std::size_t n) const
|
||||
{ boost::container::uninitialized_value_init_alloc_n(a, n, p); }
|
||||
|
||||
template<class Iterator>
|
||||
void copy_n_and_update(Allocator &a, Iterator p, std::size_t n) const
|
||||
{
|
||||
while (n){
|
||||
--n;
|
||||
storage_t v;
|
||||
alloc_traits::construct(a, (value_type*)&v);
|
||||
value_type *vp = move_detail::launder_cast<value_type *>(&v);
|
||||
value_destructor<Allocator> on_exit(a, *vp); (void)on_exit;
|
||||
*p = ::boost::move(*vp);
|
||||
++p;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<class Allocator>
|
||||
struct insert_default_initialized_n_proxy
|
||||
{
|
||||
typedef ::boost::container::allocator_traits<Allocator> alloc_traits;
|
||||
typedef typename allocator_traits<Allocator>::value_type value_type;
|
||||
typedef typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type storage_t;
|
||||
|
||||
template<class Iterator>
|
||||
inline void uninitialized_copy_n_and_update(Allocator &a, Iterator p, std::size_t n) const
|
||||
{ boost::container::uninitialized_default_init_alloc_n(a, n, p); }
|
||||
|
||||
template<class Iterator>
|
||||
void copy_n_and_update(Allocator &a, Iterator p, std::size_t n) const
|
||||
{
|
||||
if(!is_pod<value_type>::value){
|
||||
while (n){
|
||||
--n;
|
||||
typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;
|
||||
alloc_traits::construct(a, (value_type*)&v, default_init);
|
||||
value_type *vp = move_detail::launder_cast<value_type *>(&v);
|
||||
value_destructor<Allocator> on_exit(a, *vp); (void)on_exit;
|
||||
*p = ::boost::move(*vp);
|
||||
++p;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<class Allocator>
|
||||
struct insert_copy_proxy
|
||||
{
|
||||
typedef boost::container::allocator_traits<Allocator> alloc_traits;
|
||||
typedef typename alloc_traits::value_type value_type;
|
||||
|
||||
BOOST_STATIC_CONSTEXPR bool single_value = true;
|
||||
|
||||
inline explicit insert_copy_proxy(const value_type &v)
|
||||
: v_(v)
|
||||
{}
|
||||
|
||||
template<class Iterator>
|
||||
inline void uninitialized_copy_n_and_update(Allocator &a, Iterator p, std::size_t n) const
|
||||
{
|
||||
BOOST_ASSERT(n == 1); (void)n;
|
||||
alloc_traits::construct( a, boost::movelib::iterator_to_raw_pointer(p), v_);
|
||||
}
|
||||
|
||||
template<class Iterator>
|
||||
inline void copy_n_and_update(Allocator &, Iterator p, std::size_t n) const
|
||||
{
|
||||
BOOST_ASSERT(n == 1); (void)n;
|
||||
*p = v_;
|
||||
}
|
||||
|
||||
const value_type &v_;
|
||||
};
|
||||
|
||||
|
||||
template<class Allocator>
|
||||
struct insert_move_proxy
|
||||
{
|
||||
typedef boost::container::allocator_traits<Allocator> alloc_traits;
|
||||
typedef typename alloc_traits::value_type value_type;
|
||||
|
||||
BOOST_STATIC_CONSTEXPR bool single_value = true;
|
||||
|
||||
inline explicit insert_move_proxy(value_type &v)
|
||||
: v_(v)
|
||||
{}
|
||||
|
||||
template<class Iterator>
|
||||
inline void uninitialized_copy_n_and_update(Allocator &a, Iterator p, std::size_t n) const
|
||||
{
|
||||
BOOST_ASSERT(n == 1); (void)n;
|
||||
alloc_traits::construct( a, boost::movelib::iterator_to_raw_pointer(p), ::boost::move(v_) );
|
||||
}
|
||||
|
||||
template<class Iterator>
|
||||
inline void copy_n_and_update(Allocator &, Iterator p, std::size_t n) const
|
||||
{
|
||||
BOOST_ASSERT(n == 1); (void)n;
|
||||
*p = ::boost::move(v_);
|
||||
}
|
||||
|
||||
value_type &v_;
|
||||
};
|
||||
|
||||
template<class It, class Allocator>
|
||||
inline insert_move_proxy<Allocator> get_insert_value_proxy(BOOST_RV_REF(typename boost::container::iterator_traits<It>::value_type) v)
|
||||
{
|
||||
return insert_move_proxy<Allocator>(v);
|
||||
}
|
||||
|
||||
template<class It, class Allocator>
|
||||
inline insert_copy_proxy<Allocator> get_insert_value_proxy(const typename boost::container::iterator_traits<It>::value_type &v)
|
||||
{
|
||||
return insert_copy_proxy<Allocator>(v);
|
||||
}
|
||||
|
||||
}}} //namespace boost { namespace container { namespace dtl {
|
||||
|
||||
#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 dtl {
|
||||
|
||||
template<class Allocator, class ...Args>
|
||||
struct insert_nonmovable_emplace_proxy
|
||||
{
|
||||
typedef boost::container::allocator_traits<Allocator> alloc_traits;
|
||||
typedef typename alloc_traits::value_type value_type;
|
||||
typedef typename build_number_seq<sizeof...(Args)>::type index_tuple_t;
|
||||
|
||||
BOOST_STATIC_CONSTEXPR bool single_value = true;
|
||||
|
||||
inline explicit insert_nonmovable_emplace_proxy(BOOST_FWD_REF(Args)... args)
|
||||
: args_(args...)
|
||||
{}
|
||||
|
||||
template<class Iterator>
|
||||
BOOST_CONTAINER_FORCEINLINE void uninitialized_copy_n_and_update(Allocator &a, Iterator p, std::size_t n)
|
||||
{ this->priv_uninitialized_copy_some_and_update(a, index_tuple_t(), p, n); }
|
||||
|
||||
private:
|
||||
template<std::size_t ...IdxPack, class Iterator>
|
||||
inline void priv_uninitialized_copy_some_and_update(Allocator &a, const index_tuple<IdxPack...>&, Iterator p, std::size_t n)
|
||||
{
|
||||
BOOST_ASSERT(n == 1); (void)n;
|
||||
alloc_traits::construct( a, boost::movelib::iterator_to_raw_pointer(p), ::boost::forward<Args>(get<IdxPack>(this->args_))... );
|
||||
}
|
||||
|
||||
protected:
|
||||
tuple<Args&...> args_;
|
||||
};
|
||||
|
||||
template<class Allocator, class ...Args>
|
||||
struct insert_emplace_proxy
|
||||
: public insert_nonmovable_emplace_proxy<Allocator, Args...>
|
||||
{
|
||||
typedef insert_nonmovable_emplace_proxy<Allocator, Args...> base_t;
|
||||
typedef boost::container::allocator_traits<Allocator> alloc_traits;
|
||||
typedef typename base_t::value_type value_type;
|
||||
typedef typename base_t::index_tuple_t index_tuple_t;
|
||||
|
||||
BOOST_STATIC_CONSTEXPR bool single_value = true;
|
||||
|
||||
inline explicit insert_emplace_proxy(BOOST_FWD_REF(Args)... args)
|
||||
: base_t(::boost::forward<Args>(args)...)
|
||||
{}
|
||||
|
||||
template<class Iterator>
|
||||
BOOST_CONTAINER_FORCEINLINE void copy_n_and_update(Allocator &a, Iterator p, std::size_t n)
|
||||
{ this->priv_copy_some_and_update(a, index_tuple_t(), p, n); }
|
||||
|
||||
private:
|
||||
|
||||
template<std::size_t ...IdxPack, class Iterator>
|
||||
inline void priv_copy_some_and_update(Allocator &a, const index_tuple<IdxPack...>&, Iterator p, std::size_t n)
|
||||
{
|
||||
BOOST_ASSERT(n ==1); (void)n;
|
||||
typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;
|
||||
alloc_traits::construct(a, (value_type*)&v, ::boost::forward<Args>(get<IdxPack>(this->args_))...);
|
||||
value_type *vp = move_detail::launder_cast<value_type *>(&v);
|
||||
BOOST_CONTAINER_TRY{
|
||||
*p = ::boost::move(*vp);
|
||||
}
|
||||
BOOST_CONTAINER_CATCH(...){
|
||||
alloc_traits::destroy(a, vp);
|
||||
BOOST_CONTAINER_RETHROW
|
||||
}
|
||||
BOOST_CONTAINER_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>
|
||||
struct insert_emplace_proxy<Allocator, typename boost::container::allocator_traits<Allocator>::value_type>
|
||||
: public insert_move_proxy<Allocator>
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR bool single_value = true;
|
||||
|
||||
inline explicit insert_emplace_proxy(typename boost::container::allocator_traits<Allocator>::value_type &&v)
|
||||
: insert_move_proxy<Allocator>(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>
|
||||
struct insert_emplace_proxy<Allocator
|
||||
, typename boost::container::dtl::add_const<typename boost::container::allocator_traits<Allocator>::value_type>::type
|
||||
>
|
||||
: public insert_copy_proxy<Allocator>
|
||||
{
|
||||
|
||||
BOOST_STATIC_CONSTEXPR bool single_value = true;
|
||||
|
||||
inline explicit insert_emplace_proxy(const typename boost::container::allocator_traits<Allocator>::value_type &v)
|
||||
: insert_copy_proxy<Allocator>(v)
|
||||
{}
|
||||
};
|
||||
|
||||
template<class Allocator>
|
||||
struct insert_emplace_proxy<Allocator, typename boost::container::allocator_traits<Allocator>::value_type &>
|
||||
: public insert_copy_proxy<Allocator>
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR bool single_value = true;
|
||||
|
||||
inline explicit insert_emplace_proxy(const typename boost::container::allocator_traits<Allocator>::value_type &v)
|
||||
: insert_copy_proxy<Allocator>(v)
|
||||
{}
|
||||
};
|
||||
|
||||
template<class Allocator>
|
||||
struct insert_emplace_proxy<Allocator
|
||||
, typename boost::container::dtl::add_const<typename boost::container::allocator_traits<Allocator>::value_type>::type &
|
||||
>
|
||||
: public insert_copy_proxy<Allocator>
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR bool single_value = true;
|
||||
|
||||
inline explicit insert_emplace_proxy(const typename boost::container::allocator_traits<Allocator>::value_type &v)
|
||||
: insert_copy_proxy<Allocator>(v)
|
||||
{}
|
||||
};
|
||||
|
||||
}}} //namespace boost { namespace container { namespace dtl {
|
||||
|
||||
#else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
#include <boost/container/detail/value_init.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace dtl {
|
||||
|
||||
#define BOOST_CONTAINER_ADVANCED_INSERT_INT_CODE(N) \
|
||||
template< class Allocator 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::value_type value_type;\
|
||||
\
|
||||
BOOST_STATIC_CONSTEXPR bool single_value = true;\
|
||||
\
|
||||
inline explicit insert_nonmovable_emplace_proxy##N(BOOST_MOVE_UREF##N)\
|
||||
BOOST_MOVE_COLON##N BOOST_MOVE_FWD_INIT##N {}\
|
||||
\
|
||||
template<class Iterator>\
|
||||
inline void uninitialized_copy_n_and_update(Allocator &a, Iterator p, std::size_t n)\
|
||||
{\
|
||||
BOOST_ASSERT(n == 1); (void)n;\
|
||||
alloc_traits::construct(a, boost::movelib::iterator_to_raw_pointer(p) BOOST_MOVE_I##N BOOST_MOVE_MFWD##N);\
|
||||
}\
|
||||
\
|
||||
template<class Iterator>\
|
||||
inline void copy_n_and_update(Allocator &, Iterator, std::size_t)\
|
||||
{ BOOST_ASSERT(false); }\
|
||||
\
|
||||
protected:\
|
||||
BOOST_MOVE_MREF##N\
|
||||
};\
|
||||
\
|
||||
template< class Allocator BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
|
||||
struct insert_emplace_proxy_arg##N\
|
||||
: insert_nonmovable_emplace_proxy##N< Allocator BOOST_MOVE_I##N BOOST_MOVE_TARG##N >\
|
||||
{\
|
||||
typedef insert_nonmovable_emplace_proxy##N\
|
||||
< Allocator BOOST_MOVE_I##N BOOST_MOVE_TARG##N > base_t;\
|
||||
typedef typename base_t::value_type value_type;\
|
||||
typedef boost::container::allocator_traits<Allocator> alloc_traits;\
|
||||
\
|
||||
BOOST_STATIC_CONSTEXPR bool single_value = true;\
|
||||
\
|
||||
inline explicit insert_emplace_proxy_arg##N(BOOST_MOVE_UREF##N)\
|
||||
: base_t(BOOST_MOVE_FWD##N){}\
|
||||
\
|
||||
template<class Iterator>\
|
||||
inline void copy_n_and_update(Allocator &a, Iterator p, std::size_t n)\
|
||||
{\
|
||||
BOOST_ASSERT(n == 1); (void)n;\
|
||||
typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;\
|
||||
alloc_traits::construct(a, (value_type*)&v BOOST_MOVE_I##N BOOST_MOVE_MFWD##N);\
|
||||
value_type *vp = move_detail::launder_cast<value_type *>(&v);\
|
||||
BOOST_CONTAINER_TRY{\
|
||||
*p = ::boost::move(*vp);\
|
||||
}\
|
||||
BOOST_CONTAINER_CATCH(...){\
|
||||
alloc_traits::destroy(a, vp);\
|
||||
BOOST_CONTAINER_RETHROW\
|
||||
}\
|
||||
BOOST_CONTAINER_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>
|
||||
struct insert_emplace_proxy_arg1<Allocator, ::boost::rv<typename boost::container::allocator_traits<Allocator>::value_type> >
|
||||
: public insert_move_proxy<Allocator>
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR bool single_value = true;
|
||||
|
||||
inline explicit insert_emplace_proxy_arg1(typename boost::container::allocator_traits<Allocator>::value_type &v)
|
||||
: insert_move_proxy<Allocator>(v)
|
||||
{}
|
||||
};
|
||||
|
||||
template<class Allocator>
|
||||
struct insert_emplace_proxy_arg1<Allocator, typename boost::container::allocator_traits<Allocator>::value_type>
|
||||
: public insert_copy_proxy<Allocator>
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR bool single_value = true;
|
||||
|
||||
inline explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<Allocator>::value_type &v)
|
||||
: insert_copy_proxy<Allocator>(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>
|
||||
struct insert_emplace_proxy_arg1<Allocator, typename boost::container::allocator_traits<Allocator>::value_type>
|
||||
: public insert_move_proxy<Allocator>
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR bool single_value = true;
|
||||
|
||||
inline explicit insert_emplace_proxy_arg1(typename boost::container::allocator_traits<Allocator>::value_type &&v)
|
||||
: insert_move_proxy<Allocator>(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>
|
||||
struct insert_emplace_proxy_arg1<Allocator
|
||||
, typename boost::container::dtl::add_const<typename boost::container::allocator_traits<Allocator>::value_type>::type
|
||||
>
|
||||
: public insert_copy_proxy<Allocator>
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR bool single_value = true;
|
||||
|
||||
inline explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<Allocator>::value_type &v)
|
||||
: insert_copy_proxy<Allocator>(v)
|
||||
{}
|
||||
};
|
||||
|
||||
template<class Allocator>
|
||||
struct insert_emplace_proxy_arg1<Allocator, typename boost::container::allocator_traits<Allocator>::value_type &>
|
||||
: public insert_copy_proxy<Allocator>
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR bool single_value = true;
|
||||
|
||||
inline explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<Allocator>::value_type &v)
|
||||
: insert_copy_proxy<Allocator>(v)
|
||||
{}
|
||||
};
|
||||
|
||||
template<class Allocator>
|
||||
struct insert_emplace_proxy_arg1<Allocator
|
||||
, typename boost::container::dtl::add_const<typename boost::container::allocator_traits<Allocator>::value_type>::type &
|
||||
>
|
||||
: public insert_copy_proxy<Allocator>
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR bool single_value = true;
|
||||
|
||||
inline explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<Allocator>::value_type &v)
|
||||
: insert_copy_proxy<Allocator>(v)
|
||||
{}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
}}} //namespace boost { namespace container { namespace dtl {
|
||||
|
||||
#endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_ADVANCED_INSERT_INT_HPP
|
||||
241
include/boost/container/detail/algorithm.hpp
Normal file
241
include/boost/container/detail/algorithm.hpp
Normal file
@@ -0,0 +1,241 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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>
|
||||
#include <boost/move/utility_core.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
|
||||
using boost::intrusive::algo_equal;
|
||||
using boost::intrusive::algo_lexicographical_compare;
|
||||
|
||||
template<class Func>
|
||||
class binder1st
|
||||
{
|
||||
public:
|
||||
typedef typename Func::second_argument_type argument_type;
|
||||
typedef typename Func::result_type result_type;
|
||||
|
||||
binder1st(const Func& func, const typename Func::first_argument_type& arg)
|
||||
: op(func), value(arg)
|
||||
{}
|
||||
|
||||
result_type operator()(const argument_type& arg) const
|
||||
{ return op(value, arg); }
|
||||
|
||||
result_type operator()(argument_type& arg) const
|
||||
{ return op(value, arg); }
|
||||
|
||||
private:
|
||||
Func op;
|
||||
typename Func::first_argument_type value;
|
||||
};
|
||||
|
||||
template<class Func, class T>
|
||||
inline binder1st<Func> bind1st(const Func& func, const T& arg)
|
||||
{ return boost::container::binder1st<Func>(func, arg); }
|
||||
|
||||
template<class Func>
|
||||
class binder2nd
|
||||
{
|
||||
public:
|
||||
typedef typename Func::first_argument_type argument_type;
|
||||
typedef typename Func::result_type result_type;
|
||||
|
||||
binder2nd(const Func& func, const typename Func::second_argument_type& arg)
|
||||
: op(func), value(arg)
|
||||
{}
|
||||
|
||||
result_type operator()(const argument_type& arg) const
|
||||
{ return op(arg, value); }
|
||||
|
||||
result_type operator()(argument_type& arg) const
|
||||
{ return op(arg, value); }
|
||||
|
||||
private:
|
||||
Func op;
|
||||
typename Func::second_argument_type value;
|
||||
};
|
||||
|
||||
template<class Func, class T>
|
||||
inline binder2nd<Func> bind2nd(const Func& func, const T& arg)
|
||||
{
|
||||
return (boost::container::binder2nd<Func>(func, arg));
|
||||
}
|
||||
|
||||
template<class Func>
|
||||
class unary_negate
|
||||
{
|
||||
public:
|
||||
typedef typename Func::argument_type argument_type;
|
||||
typedef typename Func::result_type result_type;
|
||||
|
||||
explicit unary_negate(const Func& func)
|
||||
: m_func(func)
|
||||
{}
|
||||
|
||||
bool operator()(const typename Func::argument_type& arg) const
|
||||
{ return !m_func(arg); }
|
||||
|
||||
private:
|
||||
Func m_func;
|
||||
};
|
||||
|
||||
template<class Func> inline
|
||||
unary_negate<Func> not1(const Func& func)
|
||||
{
|
||||
return boost::container::unary_negate<Func>(func);
|
||||
}
|
||||
|
||||
template<class InputIt, class UnaryPredicate>
|
||||
InputIt find_if(InputIt first, InputIt last, UnaryPredicate p)
|
||||
{
|
||||
for (; first != last; ++first) {
|
||||
if (p(*first)) {
|
||||
return first;
|
||||
}
|
||||
}
|
||||
return last;
|
||||
}
|
||||
|
||||
template<class ForwardIt1, class ForwardIt2, class BinaryPredicate>
|
||||
ForwardIt1 find_end (ForwardIt1 first1, ForwardIt1 last1
|
||||
,ForwardIt2 first2, ForwardIt2 last2
|
||||
,BinaryPredicate p)
|
||||
{
|
||||
if (first2==last2)
|
||||
return last1; // specified in C++11
|
||||
|
||||
ForwardIt1 ret = last1;
|
||||
|
||||
while (first1!=last1)
|
||||
{
|
||||
ForwardIt1 it1 = first1;
|
||||
ForwardIt2 it2 = first2;
|
||||
while ( p(*it1, *it2) ) {
|
||||
++it1; ++it2;
|
||||
if (it2==last2) {
|
||||
ret=first1;
|
||||
break;
|
||||
}
|
||||
if (it1==last1)
|
||||
return ret;
|
||||
}
|
||||
++first1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<class InputIt, class ForwardIt, class BinaryPredicate>
|
||||
InputIt find_first_of(InputIt first1, InputIt last1, ForwardIt first2, ForwardIt last2, BinaryPredicate p)
|
||||
{
|
||||
for (; first1 != last1; ++first1) {
|
||||
for (ForwardIt it = first2; it != last2; ++it) {
|
||||
if (p(*first1, *it)) {
|
||||
return first1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return last1;
|
||||
}
|
||||
|
||||
template<class ForwardIt1, class ForwardIt2, class BinaryPredicate>
|
||||
ForwardIt1 search(ForwardIt1 first1, ForwardIt1 last1,
|
||||
ForwardIt2 first2, ForwardIt2 last2, BinaryPredicate p)
|
||||
{
|
||||
for (; ; ++first1) {
|
||||
ForwardIt1 it = first1;
|
||||
for (ForwardIt2 it2 = first2; ; ++it, ++it2) {
|
||||
if (it2 == last2) {
|
||||
return first1;
|
||||
}
|
||||
if (it == last1) {
|
||||
return last1;
|
||||
}
|
||||
if (!p(*it, *it2)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<class InpIt, class U>
|
||||
InpIt find(InpIt first, InpIt last, const U& value)
|
||||
{
|
||||
for (; first != last; ++first)
|
||||
if (*first == value)
|
||||
return first;
|
||||
|
||||
return last;
|
||||
}
|
||||
|
||||
|
||||
template<class FwdIt, class U>
|
||||
FwdIt remove(FwdIt first, FwdIt last, const U& value)
|
||||
{
|
||||
first = find(first, last, value);
|
||||
if (first != last)
|
||||
for (FwdIt i = first; ++i != last;)
|
||||
if (!(*i == value))
|
||||
*first++ = boost::move(*i);
|
||||
return first;
|
||||
}
|
||||
|
||||
template<class FwdIt, class Pred>
|
||||
FwdIt remove_if(FwdIt first, FwdIt last, Pred p)
|
||||
{
|
||||
first = find_if(first, last, p);
|
||||
if (first != last)
|
||||
for (FwdIt i = first; ++i != last;)
|
||||
if (!p(*i))
|
||||
*first++ = boost::move(*i);
|
||||
return first;
|
||||
}
|
||||
|
||||
template <class Cont, class Pred>
|
||||
typename Cont::size_type container_erase_if(Cont& c, Pred p)
|
||||
{
|
||||
typedef typename Cont::size_type size_type;
|
||||
typedef typename Cont::iterator it_t;
|
||||
|
||||
size_type prev_size = c.size();
|
||||
it_t it = c.begin();
|
||||
|
||||
//end() must be called each loop for non-node containers
|
||||
while ( it != c.end() ) {
|
||||
if (p(*it)) {
|
||||
it = c.erase(it);
|
||||
}
|
||||
else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
return prev_size - c.size();
|
||||
}
|
||||
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DETAIL_ALGORITHM_HPP
|
||||
61
include/boost/container/detail/alloc_helpers.hpp
Normal file
61
include/boost/container/detail/alloc_helpers.hpp
Normal file
@@ -0,0 +1,61 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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>
|
||||
#include <boost/container/detail/mpl.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace dtl {
|
||||
|
||||
template<class AllocatorType>
|
||||
inline void swap_alloc(AllocatorType &, AllocatorType &, dtl::false_type)
|
||||
BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{}
|
||||
|
||||
template<class AllocatorType>
|
||||
inline void swap_alloc(AllocatorType &l, AllocatorType &r, dtl::true_type)
|
||||
{ boost::adl_move_swap(l, r); }
|
||||
|
||||
template<class AllocatorType>
|
||||
inline void assign_alloc(AllocatorType &, const AllocatorType &, dtl::false_type)
|
||||
BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{}
|
||||
|
||||
template<class AllocatorType>
|
||||
inline void assign_alloc(AllocatorType &l, const AllocatorType &r, dtl::true_type)
|
||||
{ l = r; }
|
||||
|
||||
template<class AllocatorType>
|
||||
inline void move_alloc(AllocatorType &, AllocatorType &, dtl::false_type)
|
||||
BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{}
|
||||
|
||||
template<class AllocatorType>
|
||||
inline void move_alloc(AllocatorType &l, AllocatorType &r, dtl::true_type)
|
||||
{ l = ::boost::move(r); }
|
||||
|
||||
} //namespace dtl {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DETAIL_ALLOC_TRAITS_HPP
|
||||
314
include/boost/container/detail/alloc_lib.h
Normal file
314
include/boost/container/detail/alloc_lib.h
Normal file
@@ -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 BOOST_CONTAINER_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 BOOST_CONTAINER_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_CONTAINER_DLMALLOC_FOOTERS
|
||||
#ifndef BOOST_CONTAINER_DLMALLOC_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(void);
|
||||
|
||||
size_t boost_cont_allocated_memory(void);
|
||||
|
||||
size_t boost_cont_chunksize(const void *p);
|
||||
|
||||
int boost_cont_all_deallocated(void);
|
||||
|
||||
boost_cont_malloc_stats_t boost_cont_malloc_stats(void);
|
||||
|
||||
size_t boost_cont_in_use_memory(void);
|
||||
|
||||
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(void);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
void boost_cont_global_sync_unlock(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} //extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (pop)
|
||||
#endif
|
||||
|
||||
|
||||
#endif //#define BOOST_CONTAINERDLMALLOC__EXT_H
|
||||
58
include/boost/container/detail/allocation_type.hpp
Normal file
58
include/boost/container/detail/allocation_type.hpp
Normal file
@@ -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
|
||||
BOOST_CONTAINER_CONSTANT_VAR allocation_type allocate_new = (allocation_type)allocate_new_v;
|
||||
BOOST_CONTAINER_CONSTANT_VAR allocation_type expand_fwd = (allocation_type)expand_fwd_v;
|
||||
BOOST_CONTAINER_CONSTANT_VAR allocation_type expand_bwd = (allocation_type)expand_bwd_v;
|
||||
BOOST_CONTAINER_CONSTANT_VAR allocation_type shrink_in_place = (allocation_type)shrink_in_place_v;
|
||||
BOOST_CONTAINER_CONSTANT_VAR allocation_type try_shrink_in_place= (allocation_type)try_shrink_in_place_v;
|
||||
BOOST_CONTAINER_CONSTANT_VAR allocation_type nothrow_allocation = (allocation_type)nothrow_allocation_v;
|
||||
BOOST_CONTAINER_CONSTANT_VAR 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
include/boost/container/detail/allocator_version_traits.hpp
Normal file
162
include/boost/container/detail/allocator_version_traits.hpp
Normal file
@@ -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
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace dtl {
|
||||
|
||||
template<class Allocator, unsigned Version = boost::container::dtl::version<Allocator>::value>
|
||||
struct allocator_version_traits
|
||||
{
|
||||
typedef ::boost::container::dtl::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
|
||||
inline static pointer allocate_one(Allocator &a)
|
||||
{ return a.allocate_one(); }
|
||||
|
||||
inline static void deallocate_one(Allocator &a, const pointer &p)
|
||||
{ a.deallocate_one(p); }
|
||||
|
||||
inline static void allocate_individual(Allocator &a, size_type n, multiallocation_chain &m)
|
||||
{ return a.allocate_individual(n, m); }
|
||||
|
||||
inline static void deallocate_individual(Allocator &a, multiallocation_chain &holder)
|
||||
{ a.deallocate_individual(holder); }
|
||||
|
||||
inline 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::dtl::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 dtl::basic_multiallocation_chain
|
||||
<void_ptr> multialloc_cached_counted;
|
||||
typedef boost::container::dtl::
|
||||
transform_multiallocation_chain
|
||||
< multialloc_cached_counted, value_type> multiallocation_chain;
|
||||
|
||||
//Node allocation interface
|
||||
inline static pointer allocate_one(Allocator &a)
|
||||
{ return a.allocate(1); }
|
||||
|
||||
inline 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){
|
||||
--n;
|
||||
pointer p = boost::intrusive::pointer_traits<pointer>::pointer_to(*it);
|
||||
++it;
|
||||
a.deallocate(p, 1);
|
||||
}
|
||||
}
|
||||
|
||||
struct allocate_individual_rollback
|
||||
{
|
||||
inline allocate_individual_rollback(Allocator &a, multiallocation_chain &chain)
|
||||
: mr_a(a), mp_chain(&chain)
|
||||
{}
|
||||
|
||||
inline ~allocate_individual_rollback()
|
||||
{
|
||||
if(mp_chain)
|
||||
allocator_version_traits::deallocate_individual(mr_a, *mp_chain);
|
||||
}
|
||||
|
||||
inline 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_CONTAINER_TRY{
|
||||
ret = a.allocate(prefer_in_recvd_out_size);
|
||||
}
|
||||
BOOST_CONTAINER_CATCH(...){
|
||||
if(!(command & nothrow_allocation)){
|
||||
BOOST_CONTAINER_RETHROW
|
||||
}
|
||||
}
|
||||
BOOST_CONTAINER_CATCH_END
|
||||
reuse = pointer();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
} //namespace dtl {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif // ! defined(BOOST_CONTAINER_DETAIL_ALLOCATOR_VERSION_TRAITS_HPP)
|
||||
51
include/boost/container/detail/auto_link.hpp
Normal file
51
include/boost/container/detail/auto_link.hpp
Normal file
@@ -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
|
||||
140
include/boost/container/detail/block_list.hpp
Normal file
140
include/boost/container/detail/block_list.hpp
Normal file
@@ -0,0 +1,140 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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 <boost/container/detail/placement_new.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;
|
||||
|
||||
BOOST_STATIC_CONSTEXPR std::size_t MaxAlignMinus1 = memory_resource::max_align-1u;
|
||||
|
||||
public:
|
||||
|
||||
BOOST_STATIC_CONSTEXPR 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, boost_container_new_t()) 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
|
||||
158
include/boost/container/detail/block_slist.hpp
Normal file
158
include/boost/container/detail/block_slist.hpp
Normal file
@@ -0,0 +1,158 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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/container/detail/placement_new.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;
|
||||
|
||||
BOOST_STATIC_CONSTEXPR std::size_t MaxAlignMinus1 = memory_resource::max_align-1u;
|
||||
|
||||
public:
|
||||
|
||||
BOOST_STATIC_CONSTEXPR 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, boost_container_new_t()) 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
|
||||
155
include/boost/container/detail/compare_functors.hpp
Normal file
155
include/boost/container/detail/compare_functors.hpp
Normal file
@@ -0,0 +1,155 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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
|
||||
|
||||
#include <boost/intrusive/detail/ebo_functor_holder.hpp>
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
|
||||
template<class ValueType>
|
||||
class equal_to_value
|
||||
{
|
||||
typedef ValueType value_type;
|
||||
const value_type &t_;
|
||||
|
||||
public:
|
||||
inline explicit equal_to_value(const value_type &t)
|
||||
: t_(t)
|
||||
{}
|
||||
|
||||
template <class U>
|
||||
inline bool operator()(const U &t)const
|
||||
{
|
||||
return t_ == t;
|
||||
}
|
||||
};
|
||||
|
||||
template<class ValueType>
|
||||
class equal_to_value_first
|
||||
{
|
||||
typedef ValueType value_type;
|
||||
const value_type &t_;
|
||||
|
||||
public:
|
||||
inline explicit equal_to_value_first(const value_type &t)
|
||||
: t_(t)
|
||||
{}
|
||||
|
||||
template <class U>
|
||||
inline bool operator()(const U &t)const
|
||||
{
|
||||
return t_ == t.first;
|
||||
}
|
||||
};
|
||||
|
||||
template<class Node, class Pred, class Ret = bool>
|
||||
struct value_to_node_compare
|
||||
: Pred
|
||||
{
|
||||
typedef Pred predicate_type;
|
||||
typedef Node node_type;
|
||||
|
||||
inline value_to_node_compare()
|
||||
: Pred()
|
||||
{}
|
||||
|
||||
inline explicit value_to_node_compare(Pred pred)
|
||||
: Pred(pred)
|
||||
{}
|
||||
|
||||
inline Ret operator()(const Node &a, const Node &b) const
|
||||
{ return static_cast<const Pred&>(*this)(a.get_data(), b.get_data()); }
|
||||
|
||||
inline Ret operator()(const Node &a) const
|
||||
{ return static_cast<const Pred&>(*this)(a.get_data()); }
|
||||
|
||||
inline Ret operator()(const Node &a, const Node &b)
|
||||
{ return static_cast<Pred&>(*this)(a.get_data(), b.get_data()); }
|
||||
|
||||
inline Ret operator()(const Node &a)
|
||||
{ return static_cast<Pred&>(*this)(a.get_data()); }
|
||||
|
||||
inline predicate_type & predicate() { return static_cast<predicate_type&>(*this); }
|
||||
inline const predicate_type & predicate() const { return static_cast<predicate_type&>(*this); }
|
||||
};
|
||||
|
||||
template<class KeyPred, class KeyOfValue, class Node, class Ret = bool>
|
||||
struct key_node_pred
|
||||
: public boost::intrusive::detail::ebo_functor_holder<KeyPred>
|
||||
{
|
||||
inline explicit key_node_pred(const KeyPred &comp)
|
||||
: base_t(comp)
|
||||
{}
|
||||
|
||||
inline explicit key_node_pred()
|
||||
{}
|
||||
|
||||
typedef boost::intrusive::detail::ebo_functor_holder<KeyPred> base_t;
|
||||
typedef KeyPred key_predicate;
|
||||
typedef KeyOfValue key_of_value;
|
||||
typedef typename KeyOfValue::type key_type;
|
||||
|
||||
|
||||
inline static const key_type &key_from(const Node &n)
|
||||
{
|
||||
return key_of_value()(n.get_data());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline static const T &
|
||||
key_from(const T &t)
|
||||
{ return t; }
|
||||
|
||||
inline const key_predicate &key_pred() const
|
||||
{ return static_cast<const key_predicate &>(*this); }
|
||||
|
||||
inline key_predicate &key_pred()
|
||||
{ return static_cast<key_predicate &>(*this); }
|
||||
|
||||
inline Ret operator()(const key_type &key) const
|
||||
{ return this->key_pred()(key); }
|
||||
|
||||
template<class U>
|
||||
inline Ret operator()(const U &nonkey) const
|
||||
{ return this->key_pred()(this->key_from(nonkey)); }
|
||||
|
||||
inline bool operator()(const key_type &key1, const key_type &key2) const
|
||||
{ return this->key_pred()(key1, key2); }
|
||||
|
||||
template<class U>
|
||||
inline bool operator()(const key_type &key1, const U &nonkey2) const
|
||||
{ return this->key_pred()(key1, this->key_from(nonkey2)); }
|
||||
|
||||
template<class U>
|
||||
inline bool operator()(const U &nonkey1, const key_type &key2) const
|
||||
{ return this->key_pred()(this->key_from(nonkey1), key2); }
|
||||
|
||||
template<class U, class V>
|
||||
inline bool operator()(const U &nonkey1, const V &nonkey2) const
|
||||
{ return this->key_pred()(this->key_from(nonkey1), this->key_from(nonkey2)); }
|
||||
};
|
||||
|
||||
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //BOOST_CONTAINER_DETAIL_COMPARE_FUNCTORS_HPP
|
||||
61
include/boost/container/detail/config_begin.hpp
Normal file
61
include/boost/container/detail/config_begin.hpp
Normal file
@@ -0,0 +1,61 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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 : 4619) // there is no warning number 'XXXX'
|
||||
#pragma warning (disable : 4127) // conditional expression is constant
|
||||
#pragma warning (disable : 4197) // top-level volatile in cast is ignored
|
||||
#pragma warning (disable : 4251) // "identifier" : class "type" needs to have dll-interface to be used by clients of class "type2"
|
||||
#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
|
||||
|
||||
|
||||
#if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
|
||||
#pragma GCC diagnostic push
|
||||
//Sign conversion warnings broken before GCC 9.3
|
||||
//(https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87519)
|
||||
#if BOOST_GCC < 90300
|
||||
#pragma GCC diagnostic ignored "-Wsign-conversion"
|
||||
#endif
|
||||
#endif
|
||||
16
include/boost/container/detail/config_end.hpp
Normal file
16
include/boost/container/detail/config_end.hpp
Normal file
@@ -0,0 +1,16 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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
|
||||
|
||||
#if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
132
include/boost/container/detail/construct_in_place.hpp
Normal file
132
include/boost/container/detail/construct_in_place.hpp
Normal file
@@ -0,0 +1,132 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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>
|
||||
#include <boost/container/detail/is_pair.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
|
||||
//In place construction
|
||||
|
||||
struct iterator_arg_t{};
|
||||
|
||||
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>
|
||||
BOOST_CONTAINER_FORCEINLINE void construct_in_place(Allocator &a, T *dest, value_init_construct_iterator<U>)
|
||||
{
|
||||
boost::container::allocator_traits<Allocator>::construct(a, dest);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
class default_init_construct_iterator;
|
||||
|
||||
template<class Allocator, class T, class U>
|
||||
BOOST_CONTAINER_FORCEINLINE void construct_in_place(Allocator &a, T *dest, default_init_construct_iterator<U>)
|
||||
{
|
||||
boost::container::allocator_traits<Allocator>::construct(a, dest, default_init);
|
||||
}
|
||||
|
||||
template <class T, class EmplaceFunctor>
|
||||
class emplace_iterator;
|
||||
|
||||
template<class Allocator, class T, class U, class EF>
|
||||
BOOST_CONTAINER_FORCEINLINE void construct_in_place(Allocator &a, T *dest, emplace_iterator<U, EF> ei)
|
||||
{
|
||||
ei.construct_in_place(a, dest);
|
||||
}
|
||||
|
||||
//Assignment
|
||||
|
||||
template<class T, class U>
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
typename dtl::disable_if_c
|
||||
< dtl::is_pair<typename dtl::remove_reference<T>::type>::value
|
||||
&& dtl::is_pair<typename dtl::remove_reference<U>::type>::value
|
||||
, void>::type
|
||||
assign_in_place_ref(T &t, BOOST_FWD_REF(U) u)
|
||||
{ t = ::boost::forward<U>(u); }
|
||||
|
||||
template<class T, class U>
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
typename dtl::enable_if_c
|
||||
< dtl::is_pair<typename dtl::remove_reference<T>::type>::value
|
||||
&& dtl::is_pair<typename dtl::remove_reference<U>::type>::value
|
||||
, void>::type
|
||||
assign_in_place_ref(T &t, const U &u)
|
||||
{
|
||||
assign_in_place_ref(t.first, u.first);
|
||||
assign_in_place_ref(t.second, u.second);
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
typename dtl::enable_if_c
|
||||
< dtl::is_pair<typename dtl::remove_reference<T>::type>::value
|
||||
&& dtl::is_pair<typename dtl::remove_reference<U>::type>::value
|
||||
, void>::type
|
||||
assign_in_place_ref(T &t, BOOST_RV_REF(U) u)
|
||||
{
|
||||
assign_in_place_ref(t.first, ::boost::move(u.first));
|
||||
assign_in_place_ref(t.second, ::boost::move(u.second));
|
||||
}
|
||||
|
||||
template<class DstIt, class InpIt>
|
||||
BOOST_CONTAINER_FORCEINLINE void assign_in_place(DstIt dest, InpIt source)
|
||||
{ assign_in_place_ref(*dest, *source); }
|
||||
|
||||
template<class DstIt, class U>
|
||||
BOOST_CONTAINER_FORCEINLINE void assign_in_place(DstIt dest, value_init_construct_iterator<U>)
|
||||
{
|
||||
dtl::value_init<U> val;
|
||||
*dest = boost::move(val.get());
|
||||
}
|
||||
|
||||
template <class DstIt>
|
||||
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>)
|
||||
{
|
||||
U u;
|
||||
*dest = boost::move(u);
|
||||
}
|
||||
|
||||
template <class T, class EmplaceFunctor>
|
||||
class emplace_iterator;
|
||||
|
||||
template<class DstIt, class U, class EF>
|
||||
BOOST_CONTAINER_FORCEINLINE void assign_in_place(DstIt dest, emplace_iterator<U, EF> ei)
|
||||
{
|
||||
ei.assign_in_place(dest);
|
||||
}
|
||||
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DETAIL_CONSTRUCT_IN_PLACE_HPP
|
||||
@@ -0,0 +1,52 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2017-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_DETAIL_CONTAINER_OR_ALLOCATOR_REBIND_HPP
|
||||
#define BOOST_CONTAINER_DETAIL_CONTAINER_OR_ALLOCATOR_REBIND_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/container_rebind.hpp>
|
||||
#include <boost/container/detail/is_container.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace dtl {
|
||||
|
||||
template<class AllocatorOrContainer, class ToType, bool = is_container<AllocatorOrContainer>::value>
|
||||
struct container_or_allocator_rebind_impl
|
||||
: container_rebind<AllocatorOrContainer, ToType>
|
||||
{};
|
||||
|
||||
template<class AllocatorOrContainer, class ToType>
|
||||
struct container_or_allocator_rebind_impl<AllocatorOrContainer, ToType, false>
|
||||
: allocator_traits<AllocatorOrContainer>::template portable_rebind_alloc<ToType>
|
||||
{};
|
||||
|
||||
template<class ToType>
|
||||
struct container_or_allocator_rebind_impl<void, ToType, false>
|
||||
{ typedef void type; };
|
||||
|
||||
template<class AllocatorOrContainer, class ToType>
|
||||
struct container_or_allocator_rebind
|
||||
: container_or_allocator_rebind_impl<AllocatorOrContainer, ToType>
|
||||
{};
|
||||
|
||||
} //namespace dtl {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DETAIL_CONTAINER_OR_ALLOCATOR_REBIND_HPP
|
||||
173
include/boost/container/detail/container_rebind.hpp
Normal file
173
include/boost/container/detail/container_rebind.hpp
Normal file
@@ -0,0 +1,173 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2017-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_DETAIL_CONTAINER_REBIND_HPP
|
||||
#define BOOST_CONTAINER_DETAIL_CONTAINER_REBIND_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/container_fwd.hpp>
|
||||
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace dtl {
|
||||
|
||||
template<class V, class A, class U>
|
||||
struct void_or_portable_rebind_alloc
|
||||
{
|
||||
typedef typename allocator_traits<typename real_allocator<V, A>::type>::template portable_rebind_alloc<U>::type type;
|
||||
};
|
||||
|
||||
template<class V, class U>
|
||||
struct void_or_portable_rebind_alloc<V, void, U>
|
||||
{ typedef void type; };
|
||||
|
||||
template <class Cont, class U>
|
||||
struct container_rebind;
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
template <template <class, class, class...> class Cont, typename V, typename A, class... An, class U>
|
||||
struct container_rebind<Cont<V, A, An...>, U>
|
||||
{
|
||||
typedef Cont<U, typename void_or_portable_rebind_alloc<V, A, U>::type, An...> type;
|
||||
};
|
||||
|
||||
//Needed for non-conforming compilers like GCC 4.3
|
||||
template <template <class, class> class Cont, typename V, typename A, class U>
|
||||
struct container_rebind<Cont<V, A>, U>
|
||||
{
|
||||
typedef Cont<U, typename void_or_portable_rebind_alloc<V, A, U>::type> type;
|
||||
};
|
||||
|
||||
template <template <class> class Cont, typename V, class U>
|
||||
struct container_rebind<Cont<V>, U>
|
||||
{
|
||||
typedef Cont<U> type;
|
||||
};
|
||||
|
||||
#else //C++03 compilers
|
||||
|
||||
template <template <class> class Cont //0arg
|
||||
, typename V
|
||||
, class U>
|
||||
struct container_rebind<Cont<V>, U>
|
||||
{
|
||||
typedef Cont<U> type;
|
||||
};
|
||||
|
||||
template <template <class, class> class Cont //0arg
|
||||
, typename V, typename A
|
||||
, class U>
|
||||
struct container_rebind<Cont<V, A>, U>
|
||||
{
|
||||
typedef Cont<U, typename void_or_portable_rebind_alloc<V, A, U>::type> type;
|
||||
};
|
||||
|
||||
template <template <class, class, class> class Cont //1arg
|
||||
, typename V, typename A, class P0
|
||||
, class U>
|
||||
struct container_rebind<Cont<V, A, P0>, U>
|
||||
{
|
||||
typedef Cont<U, typename void_or_portable_rebind_alloc<V, A, U>::type, P0> type;
|
||||
};
|
||||
|
||||
template <template <class, class, class, class> class Cont //2arg
|
||||
, typename V, typename A, class P0, class P1
|
||||
, class U>
|
||||
struct container_rebind<Cont<V, A, P0, P1>, U>
|
||||
{
|
||||
typedef Cont<U, typename void_or_portable_rebind_alloc<V, A, U>::type, P0, P1> type;
|
||||
};
|
||||
|
||||
template <template <class, class, class, class, class> class Cont //3arg
|
||||
, typename V, typename A, class P0, class P1, class P2
|
||||
, class U>
|
||||
struct container_rebind<Cont<V, A, P0, P1, P2>, U>
|
||||
{
|
||||
typedef Cont<U, typename void_or_portable_rebind_alloc<V, A, U>::type, P0, P1, P2> type;
|
||||
};
|
||||
|
||||
template <template <class, class, class, class, class, class> class Cont //4arg
|
||||
, typename V, typename A, class P0, class P1, class P2, class P3
|
||||
, class U>
|
||||
struct container_rebind<Cont<V, A, P0, P1, P2, P3>, U>
|
||||
{
|
||||
typedef Cont<U, typename void_or_portable_rebind_alloc<V, A, U>::type, P0, P1, P2, P3> type;
|
||||
};
|
||||
|
||||
template <template <class, class, class, class, class, class, class> class Cont //5arg
|
||||
, typename V, typename A, class P0, class P1, class P2, class P3, class P4
|
||||
, class U>
|
||||
struct container_rebind<Cont<V, A, P0, P1, P2, P3, P4>, U>
|
||||
{
|
||||
typedef Cont<U, typename void_or_portable_rebind_alloc<V, A, U>::type, P0, P1, P2, P3, P4> type;
|
||||
};
|
||||
|
||||
template <template <class, class, class, class, class, class, class, class> class Cont //6arg
|
||||
, typename V, typename A, class P0, class P1, class P2, class P3, class P4, class P5
|
||||
, class U>
|
||||
struct container_rebind<Cont<V, A, P0, P1, P2, P3, P4, P5>, U>
|
||||
{
|
||||
typedef Cont<U, typename void_or_portable_rebind_alloc<V, A, U>::type, P0, P1, P2, P3, P4, P5> type;
|
||||
};
|
||||
|
||||
template <template <class, class, class, class, class, class, class, class, class> class Cont //7arg
|
||||
, typename V, typename A, class P0, class P1, class P2, class P3, class P4, class P5, class P6
|
||||
, class U>
|
||||
struct container_rebind<Cont<V, A, P0, P1, P2, P3, P4, P5, P6>, U>
|
||||
{
|
||||
typedef Cont<U, typename void_or_portable_rebind_alloc<V, A, U>::type, P0, P1, P2, P3, P4, P5, P6> type;
|
||||
};
|
||||
|
||||
template <template <class, class, class, class, class, class, class, class, class, class> class Cont //8arg
|
||||
, typename V, typename A, class P0, class P1, class P2, class P3, class P4, class P5, class P6, class P7
|
||||
, class U>
|
||||
struct container_rebind<Cont<V, A, P0, P1, P2, P3, P4, P5, P6, P7>, U>
|
||||
{
|
||||
typedef Cont<U, typename void_or_portable_rebind_alloc<V, A, U>::type, P0, P1, P2, P3, P4, P5, P6, P7> type;
|
||||
};
|
||||
|
||||
template <template <class, class, class, class, class, class, class, class, class, class, class> class Cont //9arg
|
||||
, typename V, typename A, class P0, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8
|
||||
, class U>
|
||||
struct container_rebind<Cont<V, A, P0, P1, P2, P3, P4, P5, P6, P7, P8>, U>
|
||||
{
|
||||
typedef Cont<U, typename void_or_portable_rebind_alloc<V, A, U>::type, P0, P1, P2, P3, P4, P5, P6, P7, P8> type;
|
||||
};
|
||||
|
||||
#endif //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
//for small_vector,static_vector
|
||||
|
||||
template <typename V, std::size_t N, typename A, typename O, class U>
|
||||
struct container_rebind<small_vector<V, N, A, O>, U>
|
||||
{
|
||||
typedef small_vector<U, N, typename void_or_portable_rebind_alloc<V, A, U>::type, O> type;
|
||||
};
|
||||
|
||||
template <typename V, std::size_t N, typename O, class U>
|
||||
struct container_rebind<static_vector<V, N, O>, U>
|
||||
{
|
||||
typedef static_vector<U, N, O> type;
|
||||
};
|
||||
|
||||
} //namespace dtl {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DETAIL_CONTAINER_REBIND_HPP
|
||||
2052
include/boost/container/detail/copy_move_algo.hpp
Normal file
2052
include/boost/container/detail/copy_move_algo.hpp
Normal file
File diff suppressed because it is too large
Load Diff
502
include/boost/container/detail/destroyers.hpp
Normal file
502
include/boost/container/detail/destroyers.hpp
Normal file
@@ -0,0 +1,502 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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/move/detail/to_raw_pointer.hpp>
|
||||
#include <boost/container/detail/version_type.hpp>
|
||||
#include <boost/move/detail/iterator_to_raw_pointer.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace dtl {
|
||||
|
||||
//!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 dtl::integral_constant<unsigned,
|
||||
boost::container::dtl::
|
||||
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;
|
||||
|
||||
null_scoped_deallocator(pointer, Allocator&, std::size_t)
|
||||
{}
|
||||
|
||||
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, std::size_t length)
|
||||
: m_ptr(p), m_alloc(a), m_length(length) {}
|
||||
|
||||
~scoped_array_deallocator()
|
||||
{ if (m_ptr) m_alloc.deallocate(m_ptr, size_type(m_length)); }
|
||||
|
||||
void release()
|
||||
{ m_ptr = 0; }
|
||||
|
||||
private:
|
||||
pointer m_ptr;
|
||||
Allocator& m_alloc;
|
||||
std::size_t m_length;
|
||||
};
|
||||
|
||||
template <class Allocator>
|
||||
struct null_scoped_array_deallocator
|
||||
{
|
||||
typedef boost::container::allocator_traits<Allocator> AllocTraits;
|
||||
typedef typename AllocTraits::pointer pointer;
|
||||
|
||||
null_scoped_array_deallocator(pointer, Allocator&, std::size_t)
|
||||
{}
|
||||
|
||||
void release()
|
||||
{}
|
||||
};
|
||||
|
||||
template <class Allocator>
|
||||
struct scoped_node_destroy_deallocator
|
||||
{
|
||||
typedef boost::container::allocator_traits<Allocator> AllocTraits;
|
||||
typedef typename AllocTraits::pointer pointer;
|
||||
typedef dtl::integral_constant<unsigned,
|
||||
boost::container::dtl::
|
||||
version<Allocator>::value> alloc_version;
|
||||
|
||||
scoped_node_destroy_deallocator(pointer p, Allocator& a)
|
||||
: m_ptr(p), m_alloc(a) {}
|
||||
|
||||
~scoped_node_destroy_deallocator()
|
||||
{
|
||||
if(m_ptr){
|
||||
boost::movelib::to_raw_pointer(m_ptr)->destructor(m_alloc);
|
||||
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, class Ptr = typename allocator_traits<Allocator>::pointer>
|
||||
struct scoped_destructor_n
|
||||
{
|
||||
typedef boost::container::allocator_traits<Allocator> AllocTraits;
|
||||
typedef Ptr pointer;
|
||||
typedef typename AllocTraits::value_type value_type;
|
||||
|
||||
inline scoped_destructor_n(Ptr p, Allocator& a, std::size_t n)
|
||||
: m_p(p), m_n(n), m_a(a)
|
||||
{}
|
||||
|
||||
inline void release()
|
||||
{ m_p = Ptr(); m_n = 0; }
|
||||
|
||||
inline void increment_size(std::size_t inc)
|
||||
{ m_n += inc; }
|
||||
|
||||
inline void increment_size_backwards(std::size_t inc)
|
||||
{ m_n += inc; m_p -= std::ptrdiff_t(inc); }
|
||||
|
||||
inline void shrink_forward(std::size_t inc)
|
||||
{ m_n -= inc; m_p += std::ptrdiff_t(inc); }
|
||||
|
||||
inline void set_size(std::size_t sz)
|
||||
{ m_n = sz; }
|
||||
|
||||
~scoped_destructor_n()
|
||||
{
|
||||
if(m_n){
|
||||
value_type *raw_ptr = boost::movelib::iterator_to_raw_pointer(m_p);
|
||||
do {
|
||||
--m_n;
|
||||
AllocTraits::destroy(m_a, raw_ptr);
|
||||
++raw_ptr;
|
||||
} while(m_n);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
pointer m_p;
|
||||
std::size_t m_n;
|
||||
Allocator& m_a;
|
||||
};
|
||||
|
||||
//!A deleter for scoped_ptr that destroys
|
||||
//!an object using a STL allocator.
|
||||
template <class Allocator, class Ptr = typename allocator_traits<Allocator>::pointer>
|
||||
struct null_scoped_destructor_n
|
||||
{
|
||||
typedef boost::container::allocator_traits<Allocator> AllocTraits;
|
||||
typedef Ptr pointer;
|
||||
|
||||
inline null_scoped_destructor_n(Ptr, Allocator&, std::size_t)
|
||||
{}
|
||||
|
||||
inline void increment_size(std::size_t)
|
||||
{}
|
||||
|
||||
inline void increment_size_backwards(std::size_t)
|
||||
{}
|
||||
|
||||
inline void set_size(std::size_t )
|
||||
{}
|
||||
|
||||
inline void shrink_forward(std::size_t)
|
||||
{}
|
||||
|
||||
inline void release()
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
//!A deleter for scoped_ptr that destroys
|
||||
//!an object using a STL allocator.
|
||||
template <class Allocator>
|
||||
struct scoped_destructor_range
|
||||
{
|
||||
typedef boost::container::allocator_traits<Allocator> AllocTraits;
|
||||
typedef typename AllocTraits::pointer pointer;
|
||||
typedef typename AllocTraits::value_type value_type;
|
||||
|
||||
inline scoped_destructor_range(pointer p, pointer e, Allocator& a)
|
||||
: m_p(p), m_e(e), m_a(a)
|
||||
{}
|
||||
|
||||
inline void release()
|
||||
{ m_p = pointer(); m_e = pointer(); }
|
||||
|
||||
inline void set_end(pointer e)
|
||||
{ m_e = e; }
|
||||
|
||||
inline void set_begin(pointer b)
|
||||
{ m_p = b; }
|
||||
|
||||
inline void set_range(pointer b, pointer e)
|
||||
{ m_p = b; m_e = e; }
|
||||
|
||||
~scoped_destructor_range()
|
||||
{
|
||||
while(m_p != m_e){
|
||||
value_type *raw_ptr = boost::movelib::to_raw_pointer(m_p);
|
||||
AllocTraits::destroy(m_a, raw_ptr);
|
||||
++m_p;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
pointer m_p;
|
||||
pointer m_e;
|
||||
Allocator & m_a;
|
||||
};
|
||||
|
||||
//!A deleter for scoped_ptr that destroys
|
||||
//!an object using a STL allocator.
|
||||
template <class Allocator>
|
||||
struct null_scoped_destructor_range
|
||||
{
|
||||
typedef boost::container::allocator_traits<Allocator> AllocTraits;
|
||||
typedef typename AllocTraits::pointer pointer;
|
||||
|
||||
inline null_scoped_destructor_range(pointer, pointer, Allocator&)
|
||||
{}
|
||||
|
||||
inline void release()
|
||||
{}
|
||||
|
||||
inline void set_end(pointer)
|
||||
{}
|
||||
|
||||
inline void set_begin(pointer)
|
||||
{}
|
||||
|
||||
inline void set_range(pointer, pointer)
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
template<class Allocator>
|
||||
class scoped_destructor
|
||||
{
|
||||
typedef boost::container::allocator_traits<Allocator> AllocTraits;
|
||||
public:
|
||||
typedef typename Allocator::value_type value_type;
|
||||
inline scoped_destructor(Allocator &a, value_type *pv)
|
||||
: pv_(pv), a_(a)
|
||||
{}
|
||||
|
||||
inline ~scoped_destructor()
|
||||
{
|
||||
if(pv_){
|
||||
AllocTraits::destroy(a_, pv_);
|
||||
}
|
||||
}
|
||||
|
||||
inline void release()
|
||||
{ pv_ = 0; }
|
||||
|
||||
|
||||
inline void set(value_type *ptr) { pv_ = ptr; }
|
||||
|
||||
inline value_type *get() const { return pv_; }
|
||||
|
||||
private:
|
||||
value_type *pv_;
|
||||
Allocator &a_;
|
||||
};
|
||||
|
||||
template<class Allocator>
|
||||
class null_scoped_destructor
|
||||
{
|
||||
typedef boost::container::allocator_traits<Allocator> AllocTraits;
|
||||
public:
|
||||
typedef typename Allocator::value_type value_type;
|
||||
inline null_scoped_destructor(Allocator &, value_type *)
|
||||
{}
|
||||
|
||||
inline ~null_scoped_destructor()
|
||||
{}
|
||||
|
||||
inline void release()
|
||||
{}
|
||||
|
||||
inline void set(value_type *) { }
|
||||
|
||||
inline value_type *get() const { return 0; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
template<class Allocator, class Value = typename Allocator::value_type>
|
||||
class value_destructor
|
||||
{
|
||||
typedef boost::container::allocator_traits<Allocator> AllocTraits;
|
||||
public:
|
||||
typedef Value value_type;
|
||||
inline value_destructor(Allocator &a, value_type &rv)
|
||||
: rv_(rv), a_(a)
|
||||
{}
|
||||
|
||||
inline ~value_destructor()
|
||||
{
|
||||
AllocTraits::destroy(a_, &rv_);
|
||||
}
|
||||
|
||||
private:
|
||||
value_type &rv_;
|
||||
Allocator &a_;
|
||||
};
|
||||
|
||||
template <class Allocator>
|
||||
class allocator_node_destroyer
|
||||
{
|
||||
typedef boost::container::allocator_traits<Allocator> AllocTraits;
|
||||
typedef typename AllocTraits::value_type value_type;
|
||||
typedef typename AllocTraits::pointer pointer;
|
||||
typedef dtl::integral_constant<unsigned,
|
||||
boost::container::dtl::
|
||||
version<Allocator>::value> alloc_version;
|
||||
|
||||
private:
|
||||
Allocator & a_;
|
||||
|
||||
private:
|
||||
inline void priv_deallocate(const pointer &p, version_1)
|
||||
{ AllocTraits::deallocate(a_,p, 1); }
|
||||
|
||||
inline void priv_deallocate(const pointer &p, version_2)
|
||||
{ a_.deallocate_one(p); }
|
||||
|
||||
public:
|
||||
inline explicit allocator_node_destroyer(Allocator &a)
|
||||
: a_(a)
|
||||
{}
|
||||
|
||||
inline void operator()(const pointer &p)
|
||||
{
|
||||
boost::movelib::to_raw_pointer(p)->destructor(a_);
|
||||
this->priv_deallocate(p, alloc_version());
|
||||
}
|
||||
};
|
||||
|
||||
template<class Allocator>
|
||||
class scoped_node_destructor
|
||||
{
|
||||
typedef boost::container::allocator_traits<Allocator> AllocTraits;
|
||||
public:
|
||||
typedef typename Allocator::value_type value_type;
|
||||
inline scoped_node_destructor(Allocator &a, value_type *pv)
|
||||
: pv_(pv), a_(a)
|
||||
{}
|
||||
|
||||
inline ~scoped_node_destructor()
|
||||
{
|
||||
if(pv_){
|
||||
pv_->destructor(a_);
|
||||
}
|
||||
}
|
||||
|
||||
inline void release()
|
||||
{ pv_ = 0; }
|
||||
|
||||
|
||||
inline void set(value_type *ptr) { pv_ = ptr; }
|
||||
|
||||
inline value_type *get() const { return pv_; }
|
||||
|
||||
private:
|
||||
value_type *pv_;
|
||||
Allocator &a_;
|
||||
};
|
||||
|
||||
|
||||
|
||||
template <class Allocator>
|
||||
class allocator_node_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:
|
||||
inline allocator_node_destroyer_and_chain_builder(Allocator &a, multiallocation_chain &c)
|
||||
: a_(a), c_(c)
|
||||
{}
|
||||
|
||||
inline void operator()(const typename Allocator::pointer &p)
|
||||
{
|
||||
boost::movelib::to_raw_pointer(p)->destructor(a_);
|
||||
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_node_destroyer_and_chain_builder<Allocator> chain_builder;
|
||||
|
||||
Allocator & a_;
|
||||
multiallocation_chain c_;
|
||||
|
||||
public:
|
||||
inline allocator_multialloc_chain_node_deallocator(Allocator &a)
|
||||
: a_(a), c_()
|
||||
{}
|
||||
|
||||
inline chain_builder get_chain_builder()
|
||||
{ return chain_builder(a_, c_); }
|
||||
|
||||
inline ~allocator_multialloc_chain_node_deallocator()
|
||||
{
|
||||
a_.deallocate_individual(c_);
|
||||
}
|
||||
};
|
||||
|
||||
} //namespace dtl {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DESTROYERS_HPP
|
||||
461
include/boost/container/detail/dispatch_uses_allocator.hpp
Normal file
461
include/boost/container/detail/dispatch_uses_allocator.hpp
Normal file
@@ -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/is_pair.hpp>
|
||||
#include <boost/container/detail/type_traits.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/move/utility_core.hpp>
|
||||
|
||||
namespace boost { namespace container {
|
||||
|
||||
namespace dtl {
|
||||
|
||||
|
||||
// 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(...);
|
||||
|
||||
BOOST_STATIC_CONSTEXPR 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 dtl::enable_if_and
|
||||
< void
|
||||
, dtl::is_not_pair<T>
|
||||
, dtl::not_< uses_allocator<T, typename remove_cvref<ArgAlloc>::type > >
|
||||
>::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 dtl::enable_if_and
|
||||
< void
|
||||
, dtl::is_not_pair<T>
|
||||
, uses_allocator<T, typename remove_cvref<ArgAlloc>::type>
|
||||
, 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 dtl::enable_if_and
|
||||
< void
|
||||
, dtl::is_not_pair<T>
|
||||
, uses_allocator<T, typename remove_cvref<ArgAlloc>::type>
|
||||
, dtl::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 dtl::enable_if_and\
|
||||
< void\
|
||||
, dtl::is_not_pair<T>\
|
||||
, dtl::not_<uses_allocator<T, typename remove_cvref<ArgAlloc>::type> >\
|
||||
>::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 dtl::enable_if_and\
|
||||
< void\
|
||||
, dtl::is_not_pair<T>\
|
||||
, uses_allocator<T, typename remove_cvref<ArgAlloc>::type>\
|
||||
, 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 dtl::enable_if_and\
|
||||
< void\
|
||||
, dtl::is_not_pair<T>\
|
||||
, uses_allocator<T, typename remove_cvref<ArgAlloc>::type>\
|
||||
, dtl::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 dtl::enable_if<dtl::is_pair<Pair> BOOST_MOVE_I void >::type)
|
||||
dispatch_uses_allocator
|
||||
( ConstructAlloc & construct_alloc
|
||||
, BOOST_FWD_REF(ArgAlloc) arg_alloc
|
||||
, Pair* p)
|
||||
{
|
||||
dispatch_uses_allocator(construct_alloc, arg_alloc, dtl::addressof(p->first));
|
||||
BOOST_CONTAINER_TRY{
|
||||
dispatch_uses_allocator(construct_alloc, arg_alloc, dtl::addressof(p->second));
|
||||
}
|
||||
BOOST_CONTAINER_CATCH(...) {
|
||||
allocator_traits<ConstructAlloc>::destroy(construct_alloc, dtl::addressof(p->first));
|
||||
BOOST_CONTAINER_RETHROW
|
||||
}
|
||||
BOOST_CONTAINER_CATCH_END
|
||||
}
|
||||
|
||||
|
||||
template < typename ConstructAlloc
|
||||
, typename ArgAlloc
|
||||
, class Pair, class U, class V>
|
||||
BOOST_CONTAINER_DOC1ST(void, typename dtl::enable_if<dtl::is_pair<Pair> BOOST_MOVE_I void>::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, dtl::addressof(p->first), ::boost::forward<U>(x));
|
||||
BOOST_CONTAINER_TRY{
|
||||
dispatch_uses_allocator(construct_alloc, arg_alloc, dtl::addressof(p->second), ::boost::forward<V>(y));
|
||||
}
|
||||
BOOST_CONTAINER_CATCH(...){
|
||||
allocator_traits<ConstructAlloc>::destroy(construct_alloc, dtl::addressof(p->first));
|
||||
BOOST_CONTAINER_RETHROW
|
||||
}
|
||||
BOOST_CONTAINER_CATCH_END
|
||||
}
|
||||
|
||||
template < typename ConstructAlloc
|
||||
, typename ArgAlloc
|
||||
, class Pair, class Pair2>
|
||||
BOOST_CONTAINER_DOC1ST(void, typename dtl::enable_if< dtl::is_pair<Pair> BOOST_MOVE_I void >::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 dtl::enable_if_and
|
||||
< void
|
||||
, dtl::is_pair<Pair>
|
||||
, dtl::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 dtl::enable_if< dtl::is_pair<Pair> BOOST_MOVE_I void>::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, dtl::addressof(pair->first) BOOST_MOVE_I_IF(N) BOOST_MOVE_TMPL_GET##N);\
|
||||
BOOST_CONTAINER_TRY{\
|
||||
dispatch_uses_allocator\
|
||||
(construct_alloc, arg_alloc, dtl::addressof(pair->second) BOOST_MOVE_I_IF(M) BOOST_MOVE_TMPL_GETQ##M);\
|
||||
}\
|
||||
BOOST_CONTAINER_CATCH(...) {\
|
||||
allocator_traits<ConstructAlloc>::destroy(construct_alloc, dtl::addressof(pair->first));\
|
||||
BOOST_CONTAINER_RETHROW\
|
||||
}\
|
||||
BOOST_CONTAINER_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, dtl::addressof(pair->first), ::boost::forward<Args1>(get<Indexes1>(t1))...);
|
||||
BOOST_CONTAINER_TRY{
|
||||
dispatch_uses_allocator(construct_alloc, arg_alloc, dtl::addressof(pair->second), ::boost::forward<Args2>(get<Indexes2>(t2))...);
|
||||
}
|
||||
BOOST_CONTAINER_CATCH(...){
|
||||
allocator_traits<ConstructAlloc>::destroy(construct_alloc, dtl::addressof(pair->first));
|
||||
BOOST_CONTAINER_RETHROW
|
||||
}
|
||||
BOOST_CONTAINER_CATCH_END
|
||||
}
|
||||
|
||||
template< typename ConstructAlloc, typename ArgAlloc, class Pair
|
||||
, template<class ...> class Tuple, class... Args1, class... Args2>
|
||||
typename dtl::enable_if< dtl::is_pair<Pair>, void >::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 dtl::enable_if< dtl::is_pair<Pair> BOOST_MOVE_I void>::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, dtl::addressof(pair->first) BOOST_MOVE_I_IF(N) BOOST_MOVE_GET_IDX##N);\
|
||||
BOOST_CONTAINER_TRY{\
|
||||
dispatch_uses_allocator\
|
||||
(construct_alloc, arg_alloc, dtl::addressof(pair->second) BOOST_MOVE_I_IF(M) BOOST_MOVE_GET_IDXQ##M);\
|
||||
}\
|
||||
BOOST_CONTAINER_CATCH(...) {\
|
||||
allocator_traits<ConstructAlloc>::destroy(construct_alloc, dtl::addressof(pair->first));\
|
||||
BOOST_CONTAINER_RETHROW\
|
||||
}\
|
||||
BOOST_CONTAINER_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 dtl::enable_if< dtl::is_pair<Pair> BOOST_MOVE_I void>::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, dtl::addressof(pair->first) BOOST_MOVE_I_IF(N) BOOST_MOVE_GET_IDX##N);\
|
||||
BOOST_CONTAINER_TRY{\
|
||||
dispatch_uses_allocator\
|
||||
(construct_alloc, arg_alloc, dtl::addressof(pair->second) BOOST_MOVE_I_IF(M) BOOST_MOVE_GET_IDXQ##M);\
|
||||
}\
|
||||
BOOST_CONTAINER_CATCH(...) {\
|
||||
allocator_traits<ConstructAlloc>::destroy(construct_alloc, dtl::addressof(pair->first));\
|
||||
BOOST_CONTAINER_RETHROW\
|
||||
}\
|
||||
BOOST_CONTAINER_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 dtl::enable_if< dtl::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, dtl::addressof(p->first), ::boost::forward<KeyType>(k));
|
||||
BOOST_CONTAINER_TRY{
|
||||
dispatch_uses_allocator(construct_alloc, arg_alloc, dtl::addressof(p->second), ::boost::forward<Args>(args)...);
|
||||
}
|
||||
BOOST_CONTAINER_CATCH(...) {
|
||||
allocator_traits<ConstructAlloc>::destroy(construct_alloc, dtl::addressof(p->first));
|
||||
BOOST_CONTAINER_RETHROW
|
||||
}
|
||||
BOOST_CONTAINER_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 dtl::enable_if\
|
||||
< dtl::is_pair<Pair> BOOST_MOVE_I 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, dtl::addressof(p->first), ::boost::forward<KeyType>(k));\
|
||||
BOOST_CONTAINER_TRY{\
|
||||
dispatch_uses_allocator(construct_alloc, arg_alloc, dtl::addressof(p->second) BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
|
||||
}\
|
||||
BOOST_CONTAINER_CATCH(...) {\
|
||||
allocator_traits<ConstructAlloc>::destroy(construct_alloc, dtl::addressof(p->first));\
|
||||
BOOST_CONTAINER_RETHROW\
|
||||
}\
|
||||
BOOST_CONTAINER_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 dtl
|
||||
|
||||
}} // namespace boost { namespace container {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif // BOOST_CONTAINER_DISPATCH_USES_ALLOCATOR_HPP
|
||||
103
include/boost/container/detail/dlmalloc.hpp
Normal file
103
include/boost/container/detail/dlmalloc.hpp
Normal file
@@ -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
|
||||
1767
include/boost/container/detail/flat_tree.hpp
Normal file
1767
include/boost/container/detail/flat_tree.hpp
Normal file
File diff suppressed because it is too large
Load Diff
96
include/boost/container/detail/function_detector.hpp
Normal file
96
include/boost/container/detail/function_detector.hpp
Normal file
@@ -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 : \
|
||||
BOOST_STATIC_CONSTEXPR int check = NotFound + int(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
|
||||
198
include/boost/container/detail/guards_dended.hpp
Normal file
198
include/boost/container/detail/guards_dended.hpp
Normal file
@@ -0,0 +1,198 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Benedek Thaler 2015-2016
|
||||
// (C) Copyright Ion Gaztanaga 2019-2020. 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://erenon.hu/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_DETAIL_GUARDS_HPP
|
||||
#define BOOST_CONTAINER_DETAIL_GUARDS_HPP
|
||||
|
||||
#include <boost/container/detail/config_begin.hpp>
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
|
||||
#include <boost/move/core.hpp> // BOOST_MOVABLE_BUT_NOT_COPYABLE
|
||||
|
||||
// move/detail
|
||||
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
#include <boost/move/detail/fwd_macros.hpp>
|
||||
#endif
|
||||
|
||||
#include <boost/container/allocator_traits.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace detail {
|
||||
|
||||
class null_construction_guard
|
||||
{
|
||||
public:
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
|
||||
template <typename... Args>
|
||||
null_construction_guard(Args&&...) {}
|
||||
|
||||
#else
|
||||
|
||||
#define NULL_CONSTRUCTION_GUARD_CODE(N) \
|
||||
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
|
||||
BOOST_CONTAINER_FORCEINLINE null_construction_guard(BOOST_MOVE_UREFANON##N)\
|
||||
{}\
|
||||
//
|
||||
BOOST_MOVE_ITERATE_0TO9(NULL_CONSTRUCTION_GUARD_CODE)
|
||||
#undef NULL_CONSTRUCTION_GUARD_CODE
|
||||
#endif
|
||||
|
||||
void release() {}
|
||||
void extend() {}
|
||||
};
|
||||
|
||||
template <typename Allocator>
|
||||
class construction_guard
|
||||
{
|
||||
typedef typename boost::container::allocator_traits<Allocator>::pointer pointer;
|
||||
typedef typename boost::container::allocator_traits<Allocator>::size_type size_type;
|
||||
|
||||
BOOST_MOVABLE_BUT_NOT_COPYABLE(construction_guard)
|
||||
|
||||
public:
|
||||
construction_guard()
|
||||
: _alloc_ptr()
|
||||
, _elem_count()
|
||||
, _allocator()
|
||||
{}
|
||||
|
||||
construction_guard(pointer alloc_ptr, Allocator& allocator)
|
||||
:_alloc_ptr(alloc_ptr)
|
||||
, _elem_count(0)
|
||||
, _allocator(&allocator)
|
||||
{}
|
||||
|
||||
construction_guard(BOOST_RV_REF(construction_guard) rhs)
|
||||
:_alloc_ptr(rhs._alloc_ptr)
|
||||
, _elem_count(rhs._elem_count)
|
||||
, _allocator(rhs._allocator)
|
||||
{
|
||||
rhs._elem_count = 0;
|
||||
}
|
||||
|
||||
~construction_guard()
|
||||
{
|
||||
while (_elem_count) {
|
||||
--_elem_count;
|
||||
boost::container::allocator_traits<Allocator>::destroy(*_allocator, _alloc_ptr++);
|
||||
}
|
||||
}
|
||||
|
||||
void release()
|
||||
{
|
||||
_elem_count = 0;
|
||||
}
|
||||
|
||||
void extend()
|
||||
{
|
||||
++_elem_count;
|
||||
}
|
||||
|
||||
private:
|
||||
pointer _alloc_ptr;
|
||||
size_type _elem_count;
|
||||
Allocator* _allocator;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Has two ranges
|
||||
*
|
||||
* On success, destroys the first range (src),
|
||||
* on failure, destroys the second range (dst).
|
||||
*
|
||||
* Can be used when copying/moving a range
|
||||
*/
|
||||
template <class Allocator>
|
||||
class nand_construction_guard
|
||||
{
|
||||
typedef typename boost::container::allocator_traits<Allocator>::pointer pointer;
|
||||
typedef typename boost::container::allocator_traits<Allocator>::size_type size_type;
|
||||
|
||||
construction_guard<Allocator> _src;
|
||||
construction_guard<Allocator> _dst;
|
||||
bool _dst_released;
|
||||
|
||||
public:
|
||||
nand_construction_guard()
|
||||
: _src()
|
||||
, _dst()
|
||||
, _dst_released(false)
|
||||
{}
|
||||
|
||||
nand_construction_guard( pointer src, Allocator& src_alloc
|
||||
, pointer dst, Allocator& dst_alloc)
|
||||
:_src(src, src_alloc),
|
||||
_dst(dst, dst_alloc),
|
||||
_dst_released(false)
|
||||
{}
|
||||
|
||||
void extend()
|
||||
{
|
||||
_src.extend();
|
||||
_dst.extend();
|
||||
}
|
||||
|
||||
void release() // on success
|
||||
{
|
||||
_dst.release();
|
||||
_dst_released = true;
|
||||
}
|
||||
|
||||
~nand_construction_guard()
|
||||
{
|
||||
if (! _dst_released) { _src.release(); }
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Allocator>
|
||||
class allocation_guard
|
||||
{
|
||||
typedef typename boost::container::allocator_traits<Allocator>::pointer pointer;
|
||||
typedef typename boost::container::allocator_traits<Allocator>::size_type size_type;
|
||||
|
||||
BOOST_MOVABLE_BUT_NOT_COPYABLE(allocation_guard)
|
||||
|
||||
public:
|
||||
allocation_guard(pointer alloc_ptr, size_type alloc_size, Allocator& allocator)
|
||||
:_alloc_ptr(alloc_ptr),
|
||||
_alloc_size(alloc_size),
|
||||
_allocator(allocator)
|
||||
{}
|
||||
|
||||
~allocation_guard()
|
||||
{
|
||||
if (_alloc_ptr)
|
||||
{
|
||||
boost::container::allocator_traits<Allocator>::deallocate(_allocator, _alloc_ptr, _alloc_size);
|
||||
}
|
||||
}
|
||||
|
||||
void release()
|
||||
{
|
||||
_alloc_ptr = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
pointer _alloc_ptr;
|
||||
size_type _alloc_size;
|
||||
Allocator& _allocator;
|
||||
};
|
||||
|
||||
}}} // namespace boost::container::detail
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif // BOOST_CONTAINER_DETAIL_GUARDS_HPP
|
||||
72
include/boost/container/detail/is_container.hpp
Normal file
72
include/boost/container/detail/is_container.hpp
Normal file
@@ -0,0 +1,72 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2017-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_DETAIL_IS_CONTAINER_HPP
|
||||
#define BOOST_CONTAINER_DETAIL_IS_CONTAINER_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-result"
|
||||
#endif
|
||||
|
||||
//empty
|
||||
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME empty
|
||||
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace is_container_detail {
|
||||
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
|
||||
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 0
|
||||
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 0
|
||||
#include <boost/intrusive/detail/has_member_function_callable_with.hpp>
|
||||
|
||||
//size
|
||||
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME size
|
||||
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace is_container_detail {
|
||||
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
|
||||
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 0
|
||||
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 0
|
||||
#include <boost/intrusive/detail/has_member_function_callable_with.hpp>
|
||||
|
||||
//#pragma GCC diagnostic ignored "-Wunused-result"
|
||||
#if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace dtl {
|
||||
|
||||
template <class Container>
|
||||
struct is_container
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR bool value =
|
||||
boost::container::is_container_detail::
|
||||
has_member_function_callable_with_size <const Container>::value &&
|
||||
boost::container::is_container_detail::
|
||||
has_member_function_callable_with_empty<const Container>::value;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct is_container<void>
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR bool value = false;
|
||||
};
|
||||
|
||||
|
||||
} //namespace dtl {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DETAIL_IS_CONTAINER_HPP
|
||||
86
include/boost/container/detail/is_contiguous_container.hpp
Normal file
86
include/boost/container/detail/is_contiguous_container.hpp
Normal file
@@ -0,0 +1,86 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2017-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_DETAIL_IS_CONTIGUOUS_CONTAINER_HPP
|
||||
#define BOOST_CONTAINER_DETAIL_IS_CONTIGUOUS_CONTAINER_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-result"
|
||||
#endif
|
||||
|
||||
//data
|
||||
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME data
|
||||
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace is_contiguous_container_detail {
|
||||
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
|
||||
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 0
|
||||
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 0
|
||||
#include <boost/intrusive/detail/has_member_function_callable_with.hpp>
|
||||
|
||||
//free_storage
|
||||
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME unused_storage
|
||||
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace unused_storage_detail {
|
||||
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
|
||||
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 0
|
||||
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 0
|
||||
#include <boost/intrusive/detail/has_member_function_callable_with.hpp>
|
||||
|
||||
//#pragma GCC diagnostic ignored "-Wunused-result"
|
||||
#if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace dtl {
|
||||
|
||||
template <class Container>
|
||||
struct is_contiguous_container
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR bool value =
|
||||
boost::container::is_contiguous_container_detail::
|
||||
has_member_function_callable_with_data<Container>::value &&
|
||||
boost::container::is_contiguous_container_detail::
|
||||
has_member_function_callable_with_data<const Container>::value;
|
||||
};
|
||||
|
||||
|
||||
template < class Container
|
||||
, bool = boost::container::unused_storage_detail::
|
||||
has_member_function_callable_with_unused_storage<const Container>::value>
|
||||
struct unused_storage
|
||||
{
|
||||
static typename Container::value_type* get(Container &c, typename Container::size_type &s)
|
||||
{ return c.unused_storage(s); }
|
||||
};
|
||||
|
||||
|
||||
template < class Container>
|
||||
struct unused_storage<Container, false>
|
||||
{
|
||||
static typename Container::value_type* get(Container&, typename Container::size_type &s)
|
||||
{
|
||||
s = 0;
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
} //namespace dtl {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DETAIL_IS_CONTIGUOUS_CONTAINER_HPP
|
||||
91
include/boost/container/detail/is_pair.hpp
Normal file
91
include/boost/container/detail/is_pair.hpp
Normal file
@@ -0,0 +1,91 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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_IS_PAIR_HPP
|
||||
#define BOOST_CONTAINER_CONTAINER_DETAIL_IS_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/std_fwd.hpp>
|
||||
|
||||
#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 tuples {
|
||||
|
||||
struct null_type;
|
||||
|
||||
template <
|
||||
class T0, class T1, class T2,
|
||||
class T3, class T4, class T5,
|
||||
class T6, class T7, class T8,
|
||||
class T9>
|
||||
class tuple;
|
||||
|
||||
} //namespace tuples {
|
||||
} //namespace boost {
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
|
||||
struct try_emplace_t{};
|
||||
|
||||
namespace dtl {
|
||||
|
||||
template <class T1, class T2>
|
||||
struct pair;
|
||||
|
||||
template <class T>
|
||||
struct is_pair
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR bool value = false;
|
||||
};
|
||||
|
||||
template <class T1, class T2>
|
||||
struct is_pair< pair<T1, T2> >
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR bool value = true;
|
||||
};
|
||||
|
||||
template <class T1, class T2>
|
||||
struct is_pair< std::pair<T1, T2> >
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR bool value = true;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct is_not_pair
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR bool value = !is_pair<T>::value;
|
||||
};
|
||||
|
||||
} //namespace dtl {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_CONTAINER_DETAIL_IS_PAIR_HPP
|
||||
57
include/boost/container/detail/is_sorted.hpp
Normal file
57
include/boost/container/detail/is_sorted.hpp
Normal file
@@ -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 dtl {
|
||||
|
||||
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 dtl {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DETAIL_IS_SORTED_HPP
|
||||
94
include/boost/container/detail/iterator.hpp
Normal file
94
include/boost/container/detail/iterator.hpp
Normal file
@@ -0,0 +1,94 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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>
|
||||
#include <boost/move/utility_core.hpp>
|
||||
#include <boost/container/detail/mpl.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
|
||||
using ::boost::intrusive::iterator_traits;
|
||||
using ::boost::intrusive::iter_difference;
|
||||
using ::boost::intrusive::iter_category;
|
||||
using ::boost::intrusive::iter_value;
|
||||
using ::boost::intrusive::iter_size;
|
||||
using ::boost::intrusive::iterator_distance;
|
||||
using ::boost::intrusive::iterator_udistance;
|
||||
using ::boost::intrusive::iterator_advance;
|
||||
using ::boost::intrusive::iterator_uadvance;
|
||||
using ::boost::intrusive::make_iterator_advance;
|
||||
using ::boost::intrusive::make_iterator_uadvance;
|
||||
using ::boost::intrusive::iterator;
|
||||
using ::boost::intrusive::iterator_enable_if_tag;
|
||||
using ::boost::intrusive::iterator_disable_if_tag;
|
||||
using ::boost::intrusive::iterator_arrow_result;
|
||||
|
||||
template <class Container>
|
||||
class back_emplacer
|
||||
{
|
||||
private:
|
||||
Container& container;
|
||||
|
||||
public:
|
||||
typedef std::output_iterator_tag iterator_category;
|
||||
typedef void value_type;
|
||||
typedef void difference_type;
|
||||
typedef void pointer;
|
||||
typedef void reference;
|
||||
|
||||
back_emplacer(Container& x)
|
||||
: container(x)
|
||||
{}
|
||||
|
||||
template<class U>
|
||||
back_emplacer& operator=(BOOST_FWD_REF(U) value)
|
||||
{
|
||||
container.emplace_back(boost::forward<U>(value));
|
||||
return *this;
|
||||
}
|
||||
back_emplacer& operator*() { return *this; }
|
||||
back_emplacer& operator++() { return *this; }
|
||||
back_emplacer& operator++(int){ return *this; }
|
||||
};
|
||||
|
||||
#ifndef BOOST_CONTAINER_NO_CXX17_CTAD
|
||||
|
||||
template<class InputIterator>
|
||||
using it_based_non_const_first_type_t = typename dtl::remove_const<typename iterator_traits<InputIterator>::value_type::first_type>::type;
|
||||
|
||||
template<class InputIterator>
|
||||
using it_based_const_first_type_t = const typename dtl::remove_const<typename iterator_traits<InputIterator>::value_type::first_type>::type;
|
||||
|
||||
template<class InputIterator>
|
||||
using it_based_second_type_t = typename iterator_traits<InputIterator>::value_type::second_type;
|
||||
|
||||
template<class InputIterator>
|
||||
using it_based_value_type_t = typename iterator_traits<InputIterator>::value_type;
|
||||
|
||||
#endif
|
||||
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DETAIL_ITERATORS_HPP
|
||||
33
include/boost/container/detail/iterator_to_raw_pointer.hpp
Normal file
33
include/boost/container/detail/iterator_to_raw_pointer.hpp
Normal file
@@ -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_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/move/detail/iterator_to_raw_pointer.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace dtl {
|
||||
|
||||
using ::boost::movelib::iterator_to_raw_pointer;
|
||||
|
||||
} //namespace dtl {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DETAIL_ITERATOR_TO_RAW_POINTER_HPP
|
||||
909
include/boost/container/detail/iterators.hpp
Normal file
909
include/boost/container/detail/iterators.hpp
Normal file
@@ -0,0 +1,909 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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/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 constant_iterator
|
||||
: public ::boost::container::iterator
|
||||
<std::random_access_iterator_tag, T, std::ptrdiff_t, const T*, const T &>
|
||||
{
|
||||
typedef constant_iterator<T> this_type;
|
||||
|
||||
public:
|
||||
inline explicit constant_iterator(const T &ref, std::size_t range_size)
|
||||
: m_ptr(&ref), m_num(range_size){}
|
||||
|
||||
//Constructors
|
||||
inline constant_iterator()
|
||||
: m_ptr(0), m_num(0){}
|
||||
|
||||
inline constant_iterator& operator++()
|
||||
{ increment(); return *this; }
|
||||
|
||||
inline constant_iterator operator++(int)
|
||||
{
|
||||
constant_iterator result (*this);
|
||||
increment();
|
||||
return result;
|
||||
}
|
||||
|
||||
inline constant_iterator& operator--()
|
||||
{ decrement(); return *this; }
|
||||
|
||||
inline constant_iterator operator--(int)
|
||||
{
|
||||
constant_iterator result (*this);
|
||||
decrement();
|
||||
return result;
|
||||
}
|
||||
|
||||
inline friend bool operator== (const constant_iterator& i, const constant_iterator& i2)
|
||||
{ return i.equal(i2); }
|
||||
|
||||
inline friend bool operator!= (const constant_iterator& i, const constant_iterator& i2)
|
||||
{ return !(i == i2); }
|
||||
|
||||
inline friend bool operator< (const constant_iterator& i, const constant_iterator& i2)
|
||||
{ return i.less(i2); }
|
||||
|
||||
inline friend bool operator> (const constant_iterator& i, const constant_iterator& i2)
|
||||
{ return i2 < i; }
|
||||
|
||||
inline friend bool operator<= (const constant_iterator& i, const constant_iterator& i2)
|
||||
{ return !(i > i2); }
|
||||
|
||||
inline friend bool operator>= (const constant_iterator& i, const constant_iterator& i2)
|
||||
{ return !(i < i2); }
|
||||
|
||||
inline friend std::ptrdiff_t operator- (const constant_iterator& i, const constant_iterator& i2)
|
||||
{ return i2.distance_to(i); }
|
||||
|
||||
//Arithmetic signed
|
||||
inline constant_iterator& operator+=(std::ptrdiff_t off)
|
||||
{ this->advance(off); return *this; }
|
||||
|
||||
inline constant_iterator operator+(std::ptrdiff_t off) const
|
||||
{
|
||||
constant_iterator other(*this);
|
||||
other.advance(off);
|
||||
return other;
|
||||
}
|
||||
|
||||
inline friend constant_iterator operator+(std::ptrdiff_t off, const constant_iterator& right)
|
||||
{ return right + off; }
|
||||
|
||||
inline constant_iterator& operator-=(std::ptrdiff_t off)
|
||||
{ this->advance(-off); return *this; }
|
||||
|
||||
inline constant_iterator operator-(std::ptrdiff_t off) const
|
||||
{ return *this + (-off); }
|
||||
|
||||
inline const T& operator[] (std::ptrdiff_t ) const
|
||||
{ return dereference(); }
|
||||
|
||||
inline const T& operator*() const
|
||||
{ return dereference(); }
|
||||
|
||||
inline const T* operator->() const
|
||||
{ return &(dereference()); }
|
||||
|
||||
//Arithmetic unsigned
|
||||
inline constant_iterator& operator+=(std::size_t off)
|
||||
{ return *this += std::ptrdiff_t(off); }
|
||||
|
||||
inline constant_iterator operator+(std::size_t off) const
|
||||
{ return *this + std::ptrdiff_t(off); }
|
||||
|
||||
inline friend constant_iterator operator+(std::size_t off, const constant_iterator& right)
|
||||
{ return std::ptrdiff_t(off) + right; }
|
||||
|
||||
inline constant_iterator& operator-=(std::size_t off)
|
||||
{ return *this -= std::ptrdiff_t(off); }
|
||||
|
||||
inline constant_iterator operator-(std::size_t off) const
|
||||
{ return *this - std::ptrdiff_t(off); }
|
||||
|
||||
inline const T& operator[] (std::size_t off) const
|
||||
{ return (*this)[std::ptrdiff_t(off)]; }
|
||||
|
||||
private:
|
||||
const T * m_ptr;
|
||||
std::size_t m_num;
|
||||
|
||||
inline void increment()
|
||||
{ --m_num; }
|
||||
|
||||
inline void decrement()
|
||||
{ ++m_num; }
|
||||
|
||||
inline bool equal(const this_type &other) const
|
||||
{ return m_num == other.m_num; }
|
||||
|
||||
inline bool less(const this_type &other) const
|
||||
{ return other.m_num < m_num; }
|
||||
|
||||
inline const T & dereference() const
|
||||
{ return *m_ptr; }
|
||||
|
||||
inline void advance(std::ptrdiff_t n)
|
||||
{ m_num = std::size_t(std::ptrdiff_t(m_num) - n); }
|
||||
|
||||
inline std::ptrdiff_t distance_to(const this_type &other)const
|
||||
{ return std::ptrdiff_t(m_num - other.m_num); }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class value_init_construct_iterator
|
||||
: public ::boost::container::iterator
|
||||
<std::random_access_iterator_tag, T, std::ptrdiff_t, const T*, const T &>
|
||||
{
|
||||
typedef value_init_construct_iterator<T> this_type;
|
||||
|
||||
public:
|
||||
inline explicit value_init_construct_iterator(std::size_t range_size)
|
||||
: m_num(range_size){}
|
||||
|
||||
//Constructors
|
||||
inline value_init_construct_iterator()
|
||||
: m_num(0){}
|
||||
|
||||
inline value_init_construct_iterator& operator++()
|
||||
{ increment(); return *this; }
|
||||
|
||||
inline value_init_construct_iterator operator++(int)
|
||||
{
|
||||
value_init_construct_iterator result (*this);
|
||||
increment();
|
||||
return result;
|
||||
}
|
||||
|
||||
inline value_init_construct_iterator& operator--()
|
||||
{ decrement(); return *this; }
|
||||
|
||||
inline value_init_construct_iterator operator--(int)
|
||||
{
|
||||
value_init_construct_iterator result (*this);
|
||||
decrement();
|
||||
return result;
|
||||
}
|
||||
|
||||
inline friend bool operator== (const value_init_construct_iterator& i, const value_init_construct_iterator& i2)
|
||||
{ return i.equal(i2); }
|
||||
|
||||
inline friend bool operator!= (const value_init_construct_iterator& i, const value_init_construct_iterator& i2)
|
||||
{ return !(i == i2); }
|
||||
|
||||
inline friend bool operator< (const value_init_construct_iterator& i, const value_init_construct_iterator& i2)
|
||||
{ return i.less(i2); }
|
||||
|
||||
inline friend bool operator> (const value_init_construct_iterator& i, const value_init_construct_iterator& i2)
|
||||
{ return i2 < i; }
|
||||
|
||||
inline friend bool operator<= (const value_init_construct_iterator& i, const value_init_construct_iterator& i2)
|
||||
{ return !(i > i2); }
|
||||
|
||||
inline friend bool operator>= (const value_init_construct_iterator& i, const value_init_construct_iterator& i2)
|
||||
{ return !(i < i2); }
|
||||
|
||||
inline friend std::ptrdiff_t operator- (const value_init_construct_iterator& i, const value_init_construct_iterator& i2)
|
||||
{ return i2.distance_to(i); }
|
||||
|
||||
//Arithmetic
|
||||
inline value_init_construct_iterator& operator+=(std::ptrdiff_t off)
|
||||
{ this->advance(off); return *this; }
|
||||
|
||||
inline value_init_construct_iterator operator+(std::ptrdiff_t off) const
|
||||
{
|
||||
value_init_construct_iterator other(*this);
|
||||
other.advance(off);
|
||||
return other;
|
||||
}
|
||||
|
||||
inline friend value_init_construct_iterator operator+(std::ptrdiff_t off, const value_init_construct_iterator& right)
|
||||
{ return right + off; }
|
||||
|
||||
inline value_init_construct_iterator& operator-=(std::ptrdiff_t off)
|
||||
{ this->advance(-off); return *this; }
|
||||
|
||||
inline value_init_construct_iterator operator-(std::ptrdiff_t 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:
|
||||
std::size_t m_num;
|
||||
|
||||
inline void increment()
|
||||
{ --m_num; }
|
||||
|
||||
inline void decrement()
|
||||
{ ++m_num; }
|
||||
|
||||
inline bool equal(const this_type &other) const
|
||||
{ return m_num == other.m_num; }
|
||||
|
||||
inline bool less(const this_type &other) const
|
||||
{ return other.m_num < m_num; }
|
||||
|
||||
inline const T & dereference() const
|
||||
{
|
||||
static T dummy;
|
||||
return dummy;
|
||||
}
|
||||
|
||||
inline void advance(std::ptrdiff_t n)
|
||||
{ m_num = std::size_t(std::ptrdiff_t(m_num) - n); }
|
||||
|
||||
inline std::ptrdiff_t distance_to(const this_type &other)const
|
||||
{ return std::ptrdiff_t(m_num - other.m_num); }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class default_init_construct_iterator
|
||||
: public ::boost::container::iterator
|
||||
<std::random_access_iterator_tag, T, std::ptrdiff_t, const T*, const T &>
|
||||
{
|
||||
typedef default_init_construct_iterator<T> this_type;
|
||||
|
||||
public:
|
||||
inline explicit default_init_construct_iterator(std::size_t range_size)
|
||||
: m_num(range_size){}
|
||||
|
||||
//Constructors
|
||||
inline default_init_construct_iterator()
|
||||
: m_num(0){}
|
||||
|
||||
inline default_init_construct_iterator& operator++()
|
||||
{ increment(); return *this; }
|
||||
|
||||
inline default_init_construct_iterator operator++(int)
|
||||
{
|
||||
default_init_construct_iterator result (*this);
|
||||
increment();
|
||||
return result;
|
||||
}
|
||||
|
||||
inline default_init_construct_iterator& operator--()
|
||||
{ decrement(); return *this; }
|
||||
|
||||
inline default_init_construct_iterator operator--(int)
|
||||
{
|
||||
default_init_construct_iterator result (*this);
|
||||
decrement();
|
||||
return result;
|
||||
}
|
||||
|
||||
inline friend bool operator== (const default_init_construct_iterator& i, const default_init_construct_iterator& i2)
|
||||
{ return i.equal(i2); }
|
||||
|
||||
inline friend bool operator!= (const default_init_construct_iterator& i, const default_init_construct_iterator& i2)
|
||||
{ return !(i == i2); }
|
||||
|
||||
inline friend bool operator< (const default_init_construct_iterator& i, const default_init_construct_iterator& i2)
|
||||
{ return i.less(i2); }
|
||||
|
||||
inline friend bool operator> (const default_init_construct_iterator& i, const default_init_construct_iterator& i2)
|
||||
{ return i2 < i; }
|
||||
|
||||
inline friend bool operator<= (const default_init_construct_iterator& i, const default_init_construct_iterator& i2)
|
||||
{ return !(i > i2); }
|
||||
|
||||
inline friend bool operator>= (const default_init_construct_iterator& i, const default_init_construct_iterator& i2)
|
||||
{ return !(i < i2); }
|
||||
|
||||
inline friend std::ptrdiff_t operator- (const default_init_construct_iterator& i, const default_init_construct_iterator& i2)
|
||||
{ return i2.distance_to(i); }
|
||||
|
||||
//Arithmetic
|
||||
inline default_init_construct_iterator& operator+=(std::ptrdiff_t off)
|
||||
{ this->advance(off); return *this; }
|
||||
|
||||
inline default_init_construct_iterator operator+(std::ptrdiff_t off) const
|
||||
{
|
||||
default_init_construct_iterator other(*this);
|
||||
other.advance(off);
|
||||
return other;
|
||||
}
|
||||
|
||||
inline friend default_init_construct_iterator operator+(std::ptrdiff_t off, const default_init_construct_iterator& right)
|
||||
{ return right + off; }
|
||||
|
||||
inline default_init_construct_iterator& operator-=(std::ptrdiff_t off)
|
||||
{ this->advance(-off); return *this; }
|
||||
|
||||
inline default_init_construct_iterator operator-(std::ptrdiff_t 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:
|
||||
std::size_t m_num;
|
||||
|
||||
inline void increment()
|
||||
{ --m_num; }
|
||||
|
||||
inline void decrement()
|
||||
{ ++m_num; }
|
||||
|
||||
inline bool equal(const this_type &other) const
|
||||
{ return m_num == other.m_num; }
|
||||
|
||||
inline bool less(const this_type &other) const
|
||||
{ return other.m_num < m_num; }
|
||||
|
||||
inline const T & dereference() const
|
||||
{
|
||||
static T dummy;
|
||||
return dummy;
|
||||
}
|
||||
|
||||
inline void advance(std::ptrdiff_t n)
|
||||
{ m_num = std::size_t(std::ptrdiff_t(m_num) - n); }
|
||||
|
||||
inline std::ptrdiff_t distance_to(const this_type &other) const
|
||||
{ return std::ptrdiff_t(m_num - other.m_num); }
|
||||
};
|
||||
|
||||
|
||||
template <class T>
|
||||
class repeat_iterator
|
||||
: public ::boost::container::iterator
|
||||
<std::random_access_iterator_tag, T, std::ptrdiff_t, T*, T&>
|
||||
{
|
||||
typedef repeat_iterator<T> this_type;
|
||||
public:
|
||||
inline explicit repeat_iterator(T &ref, std::size_t range_size)
|
||||
: m_ptr(&ref), m_num(range_size){}
|
||||
|
||||
//Constructors
|
||||
inline repeat_iterator()
|
||||
: m_ptr(0), m_num(0){}
|
||||
|
||||
inline this_type& operator++()
|
||||
{ increment(); return *this; }
|
||||
|
||||
inline this_type operator++(int)
|
||||
{
|
||||
this_type result (*this);
|
||||
increment();
|
||||
return result;
|
||||
}
|
||||
|
||||
inline this_type& operator--()
|
||||
{ increment(); return *this; }
|
||||
|
||||
inline this_type operator--(int)
|
||||
{
|
||||
this_type result (*this);
|
||||
increment();
|
||||
return result;
|
||||
}
|
||||
|
||||
inline friend bool operator== (const this_type& i, const this_type& i2)
|
||||
{ return i.equal(i2); }
|
||||
|
||||
inline friend bool operator!= (const this_type& i, const this_type& i2)
|
||||
{ return !(i == i2); }
|
||||
|
||||
inline friend bool operator< (const this_type& i, const this_type& i2)
|
||||
{ return i.less(i2); }
|
||||
|
||||
inline friend bool operator> (const this_type& i, const this_type& i2)
|
||||
{ return i2 < i; }
|
||||
|
||||
inline friend bool operator<= (const this_type& i, const this_type& i2)
|
||||
{ return !(i > i2); }
|
||||
|
||||
inline friend bool operator>= (const this_type& i, const this_type& i2)
|
||||
{ return !(i < i2); }
|
||||
|
||||
inline friend std::ptrdiff_t operator- (const this_type& i, const this_type& i2)
|
||||
{ return i2.distance_to(i); }
|
||||
|
||||
//Arithmetic
|
||||
inline this_type& operator+=(std::ptrdiff_t off)
|
||||
{ this->advance(off); return *this; }
|
||||
|
||||
inline this_type operator+(std::ptrdiff_t off) const
|
||||
{
|
||||
this_type other(*this);
|
||||
other.advance(off);
|
||||
return other;
|
||||
}
|
||||
|
||||
inline friend this_type operator+(std::ptrdiff_t off, const this_type& right)
|
||||
{ return right + off; }
|
||||
|
||||
inline this_type& operator-=(std::ptrdiff_t off)
|
||||
{ this->advance(-off); return *this; }
|
||||
|
||||
inline this_type operator-(std::ptrdiff_t off) const
|
||||
{ return *this + (-off); }
|
||||
|
||||
inline T& operator*() const
|
||||
{ return dereference(); }
|
||||
|
||||
inline T& operator[] (std::ptrdiff_t ) const
|
||||
{ return dereference(); }
|
||||
|
||||
inline T *operator->() const
|
||||
{ return &(dereference()); }
|
||||
|
||||
private:
|
||||
T * m_ptr;
|
||||
std::size_t m_num;
|
||||
|
||||
inline void increment()
|
||||
{ --m_num; }
|
||||
|
||||
inline void decrement()
|
||||
{ ++m_num; }
|
||||
|
||||
inline bool equal(const this_type &other) const
|
||||
{ return m_num == other.m_num; }
|
||||
|
||||
inline bool less(const this_type &other) const
|
||||
{ return other.m_num < m_num; }
|
||||
|
||||
inline T & dereference() const
|
||||
{ return *m_ptr; }
|
||||
|
||||
inline void advance(std::ptrdiff_t n)
|
||||
{ m_num = std::size_t(std::ptrdiff_t(m_num - n)); }
|
||||
|
||||
inline std::ptrdiff_t distance_to(const this_type &other)const
|
||||
{ return std::ptrdiff_t(m_num - other.m_num); }
|
||||
};
|
||||
|
||||
template <class T, class EmplaceFunctor>
|
||||
class emplace_iterator
|
||||
: public ::boost::container::iterator
|
||||
<std::random_access_iterator_tag, T, std::ptrdiff_t, const T*, const T &>
|
||||
{
|
||||
typedef emplace_iterator this_type;
|
||||
|
||||
public:
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
inline explicit emplace_iterator(EmplaceFunctor&e)
|
||||
: m_num(1), m_pe(&e){}
|
||||
|
||||
inline emplace_iterator()
|
||||
: m_num(0), m_pe(0){}
|
||||
|
||||
inline this_type& operator++()
|
||||
{ increment(); return *this; }
|
||||
|
||||
inline this_type operator++(int)
|
||||
{
|
||||
this_type result (*this);
|
||||
increment();
|
||||
return result;
|
||||
}
|
||||
|
||||
inline this_type& operator--()
|
||||
{ decrement(); return *this; }
|
||||
|
||||
inline this_type operator--(int)
|
||||
{
|
||||
this_type result (*this);
|
||||
decrement();
|
||||
return result;
|
||||
}
|
||||
|
||||
inline friend bool operator== (const this_type& i, const this_type& i2)
|
||||
{ return i.equal(i2); }
|
||||
|
||||
inline friend bool operator!= (const this_type& i, const this_type& i2)
|
||||
{ return !(i == i2); }
|
||||
|
||||
inline friend bool operator< (const this_type& i, const this_type& i2)
|
||||
{ return i.less(i2); }
|
||||
|
||||
inline friend bool operator> (const this_type& i, const this_type& i2)
|
||||
{ return i2 < i; }
|
||||
|
||||
inline friend bool operator<= (const this_type& i, const this_type& i2)
|
||||
{ return !(i > i2); }
|
||||
|
||||
inline friend bool operator>= (const this_type& i, const this_type& i2)
|
||||
{ return !(i < i2); }
|
||||
|
||||
inline friend difference_type operator- (const this_type& i, const this_type& i2)
|
||||
{ return i2.distance_to(i); }
|
||||
|
||||
//Arithmetic
|
||||
inline this_type& operator+=(difference_type off)
|
||||
{ this->advance(off); return *this; }
|
||||
|
||||
inline this_type operator+(difference_type off) const
|
||||
{
|
||||
this_type other(*this);
|
||||
other.advance(off);
|
||||
return other;
|
||||
}
|
||||
|
||||
inline friend this_type operator+(difference_type off, const this_type& right)
|
||||
{ return right + off; }
|
||||
|
||||
inline this_type& operator-=(difference_type off)
|
||||
{ this->advance(-off); return *this; }
|
||||
|
||||
inline 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>
|
||||
inline void construct_in_place(Allocator &a, T* ptr)
|
||||
{ (*m_pe)(a, ptr); }
|
||||
|
||||
template<class DestIt>
|
||||
inline void assign_in_place(DestIt dest)
|
||||
{ (*m_pe)(dest); }
|
||||
|
||||
private:
|
||||
std::size_t m_num;
|
||||
EmplaceFunctor * m_pe;
|
||||
|
||||
inline void increment()
|
||||
{ --m_num; }
|
||||
|
||||
inline void decrement()
|
||||
{ ++m_num; }
|
||||
|
||||
inline bool equal(const this_type &other) const
|
||||
{ return m_num == other.m_num; }
|
||||
|
||||
inline bool less(const this_type &other) const
|
||||
{ return other.m_num < m_num; }
|
||||
|
||||
inline const T & dereference() const
|
||||
{
|
||||
static T dummy;
|
||||
return dummy;
|
||||
}
|
||||
|
||||
inline void advance(difference_type n)
|
||||
{ m_num -= n; }
|
||||
|
||||
inline 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 dtl::build_number_seq<sizeof...(Args)>::type index_tuple_t;
|
||||
|
||||
inline emplace_functor(BOOST_FWD_REF(Args)... args)
|
||||
: args_(args...)
|
||||
{}
|
||||
|
||||
template<class Allocator, class T>
|
||||
inline void operator()(Allocator &a, T *ptr)
|
||||
{ emplace_functor::inplace_impl(a, ptr, index_tuple_t()); }
|
||||
|
||||
template<class DestIt>
|
||||
inline void operator()(DestIt dest)
|
||||
{ emplace_functor::inplace_impl(dest, index_tuple_t()); }
|
||||
|
||||
private:
|
||||
template<class Allocator, class T, std::size_t ...IdxPack>
|
||||
inline void inplace_impl(Allocator &a, T* ptr, const dtl::index_tuple<IdxPack...>&)
|
||||
{
|
||||
allocator_traits<Allocator>::construct
|
||||
(a, ptr, ::boost::forward<Args>(dtl::get<IdxPack>(args_))...);
|
||||
}
|
||||
|
||||
template<class DestIt, std::size_t ...IdxPack>
|
||||
inline void inplace_impl(DestIt dest, const dtl::index_tuple<IdxPack...>&)
|
||||
{
|
||||
typedef typename boost::container::iterator_traits<DestIt>::value_type value_type;
|
||||
value_type && tmp= value_type(::boost::forward<Args>(dtl::get<IdxPack>(args_))...);
|
||||
*dest = ::boost::move(tmp);
|
||||
}
|
||||
|
||||
dtl::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\
|
||||
{\
|
||||
inline explicit emplace_functor##N( BOOST_MOVE_UREF##N )\
|
||||
BOOST_MOVE_COLON##N BOOST_MOVE_FWD_INIT##N{}\
|
||||
\
|
||||
template<class Allocator, class T>\
|
||||
inline void operator()(Allocator &a, T *ptr)\
|
||||
{ allocator_traits<Allocator>::construct(a, ptr BOOST_MOVE_I##N BOOST_MOVE_MFWD##N); }\
|
||||
\
|
||||
template<class DestIt>\
|
||||
inline 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), dtl::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 dtl {
|
||||
|
||||
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, ...);
|
||||
|
||||
BOOST_STATIC_CONSTEXPR bool value = (1 == sizeof(test<T>(0, 0)));
|
||||
};
|
||||
|
||||
|
||||
template<class T, bool = has_iterator_category<T>::value >
|
||||
struct is_input_iterator
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR bool value = is_same<typename T::iterator_category, std::input_iterator_tag>::value;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct is_input_iterator<T, false>
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR bool value = false;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct is_not_input_iterator
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR bool value = !is_input_iterator<T>::value;
|
||||
};
|
||||
|
||||
template<class T, bool = has_iterator_category<T>::value >
|
||||
struct is_forward_iterator
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR bool value = is_same<typename T::iterator_category, std::forward_iterator_tag>::value;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct is_forward_iterator<T, false>
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR bool value = false;
|
||||
};
|
||||
|
||||
template<class T, bool = has_iterator_category<T>::value >
|
||||
struct is_bidirectional_iterator
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR bool value = is_same<typename T::iterator_category, std::bidirectional_iterator_tag>::value;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct is_bidirectional_iterator<T, false>
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR 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;
|
||||
class nat
|
||||
{
|
||||
public:
|
||||
IIterator get() const
|
||||
{ return IIterator(); }
|
||||
};
|
||||
typedef typename dtl::if_c< IsConst
|
||||
, iterator_from_iiterator<IIterator, false>
|
||||
, nat>::type nonconst_iterator;
|
||||
|
||||
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;
|
||||
|
||||
inline iterator_from_iiterator()
|
||||
: m_iit()
|
||||
{}
|
||||
|
||||
inline explicit iterator_from_iiterator(IIterator iit) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
: m_iit(iit)
|
||||
{}
|
||||
|
||||
inline iterator_from_iiterator(const iterator_from_iiterator& other) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
: m_iit(other.get())
|
||||
{}
|
||||
|
||||
inline iterator_from_iiterator(const nonconst_iterator& other) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
: m_iit(other.get())
|
||||
{}
|
||||
|
||||
inline iterator_from_iiterator& operator=(const iterator_from_iiterator& other) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ m_iit = other.get(); return *this; }
|
||||
|
||||
inline iterator_from_iiterator& operator++() BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ ++this->m_iit; return *this; }
|
||||
|
||||
inline iterator_from_iiterator operator++(int) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{
|
||||
iterator_from_iiterator result (*this);
|
||||
++this->m_iit;
|
||||
return result;
|
||||
}
|
||||
|
||||
inline iterator_from_iiterator& operator--() BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{
|
||||
//If the iterator_from_iiterator is not a bidirectional iterator, operator-- should not exist
|
||||
BOOST_CONTAINER_STATIC_ASSERT((is_bidirectional_iterator<iterator_from_iiterator>::value));
|
||||
--this->m_iit; return *this;
|
||||
}
|
||||
|
||||
inline iterator_from_iiterator operator--(int) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{
|
||||
iterator_from_iiterator result (*this);
|
||||
--this->m_iit;
|
||||
return result;
|
||||
}
|
||||
|
||||
inline friend bool operator== (const iterator_from_iiterator& l, const iterator_from_iiterator& r) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return l.m_iit == r.m_iit; }
|
||||
|
||||
inline friend bool operator!= (const iterator_from_iiterator& l, const iterator_from_iiterator& r) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return l.m_iit != r.m_iit; }
|
||||
|
||||
inline reference operator*() const BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return this->m_iit->get_data(); }
|
||||
|
||||
inline pointer operator->() const BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return ::boost::intrusive::pointer_traits<pointer>::pointer_to(this->operator*()); }
|
||||
|
||||
inline const IIterator &get() const BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return this->m_iit; }
|
||||
|
||||
private:
|
||||
IIterator m_iit;
|
||||
};
|
||||
|
||||
} //namespace dtl {
|
||||
|
||||
using ::boost::intrusive::reverse_iterator;
|
||||
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DETAIL_ITERATORS_HPP
|
||||
176
include/boost/container/detail/math_functions.hpp
Normal file
176
include/boost/container/detail/math_functions.hpp
Normal file
@@ -0,0 +1,176 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace dtl {
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
template <typename Integer, bool Loop = true>
|
||||
struct upper_power_of_2_loop_ct
|
||||
{
|
||||
|
||||
template <Integer I, Integer P>
|
||||
struct apply
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR Integer value =
|
||||
upper_power_of_2_loop_ct<Integer, (I > P*2)>::template apply<I, P*2>::value;
|
||||
};
|
||||
};
|
||||
|
||||
template <typename Integer>
|
||||
struct upper_power_of_2_loop_ct<Integer, false>
|
||||
{
|
||||
template <Integer I, Integer P>
|
||||
struct apply
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR Integer value = P;
|
||||
};
|
||||
};
|
||||
|
||||
template <typename Integer, Integer I>
|
||||
struct upper_power_of_2_ct
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR Integer value = upper_power_of_2_loop_ct<Integer, (I > 1)>::template apply<I, 2>::value;
|
||||
};
|
||||
|
||||
//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_CONTAINER_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;
|
||||
}
|
||||
|
||||
template<std::size_t I1, std::size_t I2>
|
||||
struct gcd_ct
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR std::size_t Max = I1 > I2 ? I1 : I2;
|
||||
BOOST_STATIC_CONSTEXPR std::size_t Min = I1 < I2 ? I1 : I2;
|
||||
BOOST_STATIC_CONSTEXPR std::size_t value = gcd_ct<Min, Max % Min>::value;
|
||||
};
|
||||
|
||||
template<std::size_t I1>
|
||||
struct gcd_ct<I1, 0>
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR std::size_t value = I1;
|
||||
};
|
||||
|
||||
template<std::size_t I1>
|
||||
struct gcd_ct<0, I1>
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR std::size_t value = I1;
|
||||
};
|
||||
|
||||
template<std::size_t I1, std::size_t I2>
|
||||
struct lcm_ct
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR std::size_t value = I1 * I2 / gcd_ct<I1, I2>::value;
|
||||
};
|
||||
|
||||
} // namespace dtl
|
||||
} // namespace container
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif
|
||||
37
include/boost/container/detail/min_max.hpp
Normal file
37
include/boost/container/detail/min_max.hpp
Normal file
@@ -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 dtl {
|
||||
|
||||
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 dtl {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DETAIL_MIN_MAX_HPP
|
||||
@@ -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
|
||||
144
include/boost/container/detail/mpl.hpp
Normal file
144
include/boost/container/detail/mpl.hpp
Normal file
@@ -0,0 +1,144 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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 dtl {
|
||||
|
||||
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;
|
||||
using boost::move_detail::remove_const;
|
||||
|
||||
template <class FirstType>
|
||||
struct select1st
|
||||
{
|
||||
typedef FirstType type;
|
||||
|
||||
template<class T>
|
||||
BOOST_CONTAINER_FORCEINLINE const type& operator()(const T& x) const
|
||||
{ return x.first; }
|
||||
|
||||
template<class T>
|
||||
BOOST_CONTAINER_FORCEINLINE type& operator()(T& x)
|
||||
{ return const_cast<type&>(x.first); }
|
||||
};
|
||||
|
||||
|
||||
template<typename T>
|
||||
struct void_t { typedef void type; };
|
||||
|
||||
template <class T, class=void>
|
||||
struct is_transparent_base
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR bool value = false;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct is_transparent_base<T, typename void_t<typename T::is_transparent>::type>
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR bool value = true;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct is_transparent
|
||||
: is_transparent_base<T>
|
||||
{};
|
||||
|
||||
template <typename C, class /*Dummy*/, typename R>
|
||||
struct enable_if_transparent
|
||||
: boost::move_detail::enable_if_c<dtl::is_transparent<C>::value, R>
|
||||
{};
|
||||
|
||||
#ifndef BOOST_CONTAINER_NO_CXX17_CTAD
|
||||
|
||||
// void_t (void_t for C++11)
|
||||
template<typename...> using variadic_void_t = void;
|
||||
|
||||
// Trait to detect Allocator-like types.
|
||||
template<typename Allocator, typename = void>
|
||||
struct is_allocator
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR bool value = false;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
T&& ctad_declval();
|
||||
|
||||
template<typename Allocator>
|
||||
struct is_allocator < Allocator,
|
||||
variadic_void_t< typename Allocator::value_type
|
||||
, decltype(ctad_declval<Allocator&>().allocate(size_t{})) >>
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR bool value = true;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
using require_allocator_t = typename enable_if_c<is_allocator<T>::value, T>::type;
|
||||
|
||||
template<class T>
|
||||
using require_nonallocator_t = typename enable_if_c<!is_allocator<T>::value, T>::type;
|
||||
|
||||
#endif
|
||||
|
||||
} //namespace dtl {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_CONTAINER_DETAIL_MPL_HPP
|
||||
|
||||
393
include/boost/container/detail/multiallocation_chain.hpp
Normal file
393
include/boost/container/detail/multiallocation_chain.hpp
Normal file
@@ -0,0 +1,393 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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/move/detail/to_raw_pointer.hpp>
|
||||
#include <boost/container/detail/type_traits.hpp>
|
||||
#include <boost/container/detail/placement_new.hpp>
|
||||
#include <boost/container/detail/iterator.hpp>
|
||||
// intrusive
|
||||
#include <boost/intrusive/slist.hpp>
|
||||
#include <boost/intrusive/pointer_traits.hpp>
|
||||
#include <boost/intrusive/detail/twin.hpp>
|
||||
// move
|
||||
#include <boost/move/utility_core.hpp>
|
||||
#include <boost/move/detail/iterator_to_raw_pointer.hpp>
|
||||
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace dtl {
|
||||
|
||||
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::dtl::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*>(boost::movelib::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;
|
||||
typedef boost::intrusive::twin<void_pointer> pointer_pair;
|
||||
|
||||
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 += difference_type(unit_bytes);
|
||||
for(size_type i = 0; i != num_units-1u; ++i, elem += difference_type(unit_bytes)){
|
||||
::new (boost::movelib::to_raw_pointer(prev_elem), boost_container_new_t()) 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)); }
|
||||
|
||||
pointer_pair extract_data()
|
||||
{
|
||||
if(BOOST_LIKELY(!slist_impl_.empty())){
|
||||
pointer_pair ret
|
||||
(slist_impl_.begin().operator->()
|
||||
,slist_impl_.last().operator->());
|
||||
slist_impl_.clear();
|
||||
return ret;
|
||||
}
|
||||
else {
|
||||
return pointer_pair();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <class Iterator, class T>
|
||||
class multialloc_iterator
|
||||
: public boost::container::iterator
|
||||
< typename Iterator::iterator_category
|
||||
, T
|
||||
, typename Iterator::difference_type
|
||||
, T*
|
||||
, T&
|
||||
>
|
||||
{
|
||||
public:
|
||||
inline explicit multialloc_iterator(const Iterator &it)
|
||||
: m_it(it)
|
||||
{}
|
||||
|
||||
inline explicit multialloc_iterator()
|
||||
: m_it()
|
||||
{}
|
||||
|
||||
//Constructors
|
||||
inline multialloc_iterator& operator++()
|
||||
{ increment(); return *this; }
|
||||
|
||||
inline multialloc_iterator operator++(int)
|
||||
{
|
||||
multialloc_iterator result (*this);
|
||||
increment();
|
||||
return result;
|
||||
}
|
||||
|
||||
inline friend bool operator== (const multialloc_iterator& i, const multialloc_iterator& i2)
|
||||
{ return i.equal(i2); }
|
||||
|
||||
inline friend bool operator!= (const multialloc_iterator& i, const multialloc_iterator& i2)
|
||||
{ return !(i == i2); }
|
||||
|
||||
inline friend typename Iterator::difference_type operator- (const multialloc_iterator& i, const multialloc_iterator& i2)
|
||||
{ return i2.distance_to(i); }
|
||||
|
||||
//Arithmetic
|
||||
inline multialloc_iterator& operator+=(typename Iterator::difference_type off)
|
||||
{ this->advance(off); return *this; }
|
||||
|
||||
inline multialloc_iterator operator+(typename Iterator::difference_type off) const
|
||||
{
|
||||
multialloc_iterator other(*this);
|
||||
other.advance(off);
|
||||
return other;
|
||||
}
|
||||
|
||||
inline friend multialloc_iterator operator+(typename Iterator::difference_type off, const multialloc_iterator& right)
|
||||
{ return right + off; }
|
||||
|
||||
inline multialloc_iterator& operator-=(typename Iterator::difference_type off)
|
||||
{ this->advance(-off); return *this; }
|
||||
|
||||
inline multialloc_iterator operator-(typename Iterator::difference_type off) const
|
||||
{ return *this + (-off); }
|
||||
|
||||
inline T& operator*() const
|
||||
{ return *this->operator->(); }
|
||||
|
||||
inline T* operator->() const
|
||||
{ return static_cast<T*>(static_cast<void*>(boost::movelib::iterator_to_raw_pointer(m_it))); }
|
||||
|
||||
inline Iterator & base()
|
||||
{ return m_it; }
|
||||
|
||||
inline const Iterator & base() const
|
||||
{ return m_it; }
|
||||
|
||||
private:
|
||||
Iterator m_it;
|
||||
|
||||
inline void increment()
|
||||
{ ++m_it; }
|
||||
|
||||
inline void decrement()
|
||||
{ --m_it; }
|
||||
|
||||
inline bool equal(const multialloc_iterator &other) const
|
||||
{ return m_it == other.m_it; }
|
||||
|
||||
inline bool less(const multialloc_iterator &other) const
|
||||
{ return other.m_it < m_it; }
|
||||
|
||||
inline void advance(typename Iterator::difference_type n)
|
||||
{ boost::container::iterator_advance(m_it, n); }
|
||||
|
||||
inline typename Iterator::difference_type distance_to(const multialloc_iterator &other)const
|
||||
{ return boost::container::iterator_distance(other.m_it, m_it); }
|
||||
};
|
||||
|
||||
|
||||
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 multialloc_iterator
|
||||
<typename MultiallocationChain::iterator, T> iterator;
|
||||
typedef typename MultiallocationChain::size_type size_type;
|
||||
typedef boost::intrusive::twin<pointer> pointer_pair;
|
||||
|
||||
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)
|
||||
{ this->MultiallocationChain::push_front(mem); }
|
||||
|
||||
void push_back(const pointer &mem)
|
||||
{ return this->MultiallocationChain::push_back(mem); }
|
||||
|
||||
void swap(transform_multiallocation_chain &other_chain)
|
||||
{ this->MultiallocationChain::swap(other_chain); }
|
||||
|
||||
void splice_after(iterator after_this, transform_multiallocation_chain &x, iterator before_b, iterator before_e, size_type n)
|
||||
{ this->MultiallocationChain::splice_after(after_this.base(), x, before_b.base(), before_e.base(), n); }
|
||||
|
||||
void incorporate_after(iterator after_this, pointer b, pointer before_e, size_type n)
|
||||
{ this->MultiallocationChain::incorporate_after(after_this.base(), b, before_e, n); }
|
||||
|
||||
pointer pop_front()
|
||||
{ return cast(this->MultiallocationChain::pop_front()); }
|
||||
|
||||
bool empty() const
|
||||
{ return this->MultiallocationChain::empty(); }
|
||||
|
||||
iterator before_begin()
|
||||
{ return iterator(this->MultiallocationChain::before_begin()); }
|
||||
|
||||
iterator begin()
|
||||
{ return iterator(this->MultiallocationChain::begin()); }
|
||||
|
||||
iterator last()
|
||||
{ return iterator(this->MultiallocationChain::last()); }
|
||||
|
||||
iterator end()
|
||||
{ return iterator(this->MultiallocationChain::end()); }
|
||||
|
||||
size_type size() const
|
||||
{ return this->MultiallocationChain::size(); }
|
||||
|
||||
void clear()
|
||||
{ this->MultiallocationChain::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)); }
|
||||
|
||||
pointer_pair extract_data()
|
||||
{
|
||||
typename MultiallocationChain::pointer_pair data(this->MultiallocationChain::extract_data());
|
||||
return pointer_pair(cast(data.first), cast(data.second));
|
||||
}
|
||||
/*
|
||||
MultiallocationChain &extract_multiallocation_chain()
|
||||
{ return holder_; }*/
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
// namespace dtl {
|
||||
// namespace container {
|
||||
// namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_CONTAINER_DETAIL_MULTIALLOCATION_CHAIN_HPP
|
||||
308
include/boost/container/detail/mutex.hpp
Normal file
308
include/boost/container/detail/mutex.hpp
Normal file
@@ -0,0 +1,308 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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
|
||||
#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)
|
||||
#include <intrin.h>
|
||||
#define interlockedexchange _InterlockedExchange
|
||||
#elif defined(WIN32) && defined(__GNUC__)
|
||||
#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)
|
||||
#if !defined( BOOST_USE_WINDOWS_H )
|
||||
#if defined (WIN32_PLATFORM_PSPC)
|
||||
#define BOOST_CONTAINERWINAPI_IMPORT BOOST_SYMBOL_IMPORT
|
||||
#elif defined (_WIN32_WCE)
|
||||
#define BOOST_CONTAINERWINAPI_IMPORT
|
||||
#else
|
||||
#define BOOST_CONTAINERWINAPI_IMPORT BOOST_SYMBOL_IMPORT
|
||||
#endif
|
||||
|
||||
#if defined(WINAPI)
|
||||
#define BOOST_CONTAINERWINAPI_WINAPI_CC WINAPI
|
||||
#else
|
||||
#if defined(_M_IX86) || defined(__i386__)
|
||||
#define BOOST_CONTAINERWINAPI_DETAIL_STDCALL __stdcall
|
||||
#else
|
||||
#define BOOST_CONTAINERWINAPI_DETAIL_STDCALL
|
||||
#endif
|
||||
#define BOOST_CONTAINERWINAPI_WINAPI_CC BOOST_CONTAINERWINAPI_DETAIL_STDCALL
|
||||
#endif
|
||||
|
||||
#if !defined(__LP64__)
|
||||
namespace boost {
|
||||
namespace container_winapi {
|
||||
typedef unsigned long DWORD_;
|
||||
#else
|
||||
typedef unsigned int DWORD_;
|
||||
#endif
|
||||
typedef int BOOL_;
|
||||
}}
|
||||
|
||||
extern "C" {
|
||||
BOOST_CONTAINERWINAPI_IMPORT boost::container_winapi::DWORD_ BOOST_CONTAINERWINAPI_WINAPI_CC
|
||||
SleepEx(
|
||||
boost::container_winapi::DWORD_ dwMilliseconds,
|
||||
boost::container_winapi::BOOL_ bAlertable);
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace container_winapi {
|
||||
using ::SleepEx;
|
||||
}
|
||||
}
|
||||
|
||||
#define SLEEP_EX_DURATION 50 /* delay for yield/sleep */
|
||||
#define SPIN_LOCK_YIELD boost::container_winapi::SleepEx(SLEEP_EX_DURATION, 0)
|
||||
#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 dtl {
|
||||
|
||||
#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 dtl
|
||||
} // 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
|
||||
96
include/boost/container/detail/next_capacity.hpp
Normal file
96
include/boost/container/detail/next_capacity.hpp
Normal file
@@ -0,0 +1,96 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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
|
||||
|
||||
#include <boost/container/detail/config_begin.hpp>
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
|
||||
// container
|
||||
#include <boost/container/throw_exception.hpp>
|
||||
// container/detail
|
||||
#include <boost/container/detail/min_max.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace dtl {
|
||||
|
||||
template<unsigned Minimum, unsigned Numerator, unsigned Denominator>
|
||||
struct grow_factor_ratio
|
||||
{
|
||||
BOOST_CONTAINER_STATIC_ASSERT(Numerator > Denominator);
|
||||
BOOST_CONTAINER_STATIC_ASSERT(Numerator < 100);
|
||||
BOOST_CONTAINER_STATIC_ASSERT(Denominator < 100);
|
||||
BOOST_CONTAINER_STATIC_ASSERT(Denominator == 1 || (0 != Numerator % Denominator));
|
||||
|
||||
template<class SizeType>
|
||||
SizeType operator()(const SizeType cur_cap, const SizeType add_min_cap, const SizeType max_cap) const
|
||||
{
|
||||
const SizeType overflow_limit = ((SizeType)-1) / Numerator;
|
||||
|
||||
SizeType new_cap = 0;
|
||||
|
||||
if(cur_cap <= overflow_limit){
|
||||
new_cap = SizeType(cur_cap * Numerator / Denominator);
|
||||
}
|
||||
else if(Denominator == 1 || (SizeType(new_cap = cur_cap) / Denominator) > overflow_limit){
|
||||
new_cap = (SizeType)-1;
|
||||
}
|
||||
else{
|
||||
new_cap = SizeType(new_cap*Numerator);
|
||||
}
|
||||
return max_value<SizeType>
|
||||
( SizeType(Minimum)
|
||||
, max_value<SizeType>
|
||||
( SizeType(cur_cap+add_min_cap)
|
||||
, min_value<SizeType>(max_cap, new_cap))
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
} //namespace dtl {
|
||||
|
||||
struct growth_factor_50
|
||||
: dtl::grow_factor_ratio<0, 3, 2>
|
||||
{};
|
||||
|
||||
struct growth_factor_60
|
||||
: dtl::grow_factor_ratio<0, 8, 5>
|
||||
{};
|
||||
|
||||
struct growth_factor_100
|
||||
: dtl::grow_factor_ratio<0, 2, 1>
|
||||
{};
|
||||
|
||||
template<class SizeType>
|
||||
inline void clamp_by_stored_size_type(SizeType &, SizeType)
|
||||
{}
|
||||
|
||||
template<class SizeType, class SomeStoredSizeType>
|
||||
inline void clamp_by_stored_size_type(SizeType &s, SomeStoredSizeType)
|
||||
{
|
||||
if (s >= SomeStoredSizeType(-1) )
|
||||
s = SomeStoredSizeType(-1);
|
||||
}
|
||||
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DETAIL_NEXT_CAPACITY_HPP
|
||||
619
include/boost/container/detail/node_alloc_holder.hpp
Normal file
619
include/boost/container/detail/node_alloc_holder.hpp
Normal file
@@ -0,0 +1,619 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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/move/detail/iterator_to_raw_pointer.hpp>
|
||||
#include <boost/move/detail/launder.hpp>
|
||||
#include <boost/container/detail/mpl.hpp>
|
||||
#include <boost/container/detail/placement_new.hpp>
|
||||
#include <boost/move/detail/to_raw_pointer.hpp>
|
||||
#include <boost/container/detail/type_traits.hpp>
|
||||
#include <boost/container/detail/version_type.hpp>
|
||||
#include <boost/container/detail/is_pair.hpp>
|
||||
#include <boost/container/detail/pair.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
|
||||
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
|
||||
//This trait is used to type-pun std::pair because in C++03
|
||||
//compilers std::pair is useless for C++11 features
|
||||
template<class T, bool>
|
||||
struct node_internal_data_type
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct node_internal_data_type< T, true>
|
||||
{
|
||||
typedef dtl::pair< typename dtl::remove_const<typename T::first_type>::type
|
||||
, typename T::second_type>
|
||||
type;
|
||||
};
|
||||
|
||||
template <class T, class HookDefiner, bool PairBased = false>
|
||||
struct base_node
|
||||
: public HookDefiner::type
|
||||
{
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef typename node_internal_data_type<T, PairBased && dtl::is_pair<T>::value>::type internal_type;
|
||||
typedef typename HookDefiner::type hook_type;
|
||||
|
||||
typedef typename dtl::aligned_storage<sizeof(T), dtl::alignment_of<T>::value>::type storage_t;
|
||||
storage_t m_storage;
|
||||
|
||||
#if defined(BOOST_GCC) && (BOOST_GCC >= 40600) && (BOOST_GCC < 80000)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
||||
#define BOOST_CONTAINER_DISABLE_ALIASING_WARNING
|
||||
# endif
|
||||
public:
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
template<class Alloc, class ...Args>
|
||||
explicit base_node(Alloc &a, Args &&...args)
|
||||
: hook_type()
|
||||
{
|
||||
::boost::container::allocator_traits<Alloc>::construct
|
||||
(a, &this->get_real_data(), ::boost::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
#else //defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
#define BOOST_CONTAINER_BASE_NODE_CONSTRUCT_IMPL(N) \
|
||||
template< class Alloc BOOST_MOVE_I##N BOOST_MOVE_CLASS##N > \
|
||||
explicit base_node(Alloc &a BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
|
||||
: hook_type()\
|
||||
{\
|
||||
::boost::container::allocator_traits<Alloc>::construct\
|
||||
(a, &this->get_real_data() BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
|
||||
}\
|
||||
//
|
||||
BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_BASE_NODE_CONSTRUCT_IMPL)
|
||||
#undef BOOST_CONTAINER_BASE_NODE_CONSTRUCT_IMPL
|
||||
|
||||
#endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
template<class Alloc, class It>
|
||||
explicit base_node(iterator_arg_t, Alloc &a, It it)
|
||||
: hook_type()
|
||||
{
|
||||
::boost::container::construct_in_place(a, &this->get_real_data(), it);
|
||||
}
|
||||
|
||||
inline T &get_data()
|
||||
{ return *move_detail::force_ptr<T*>(&this->m_storage); }
|
||||
|
||||
inline const T &get_data() const
|
||||
{ return *move_detail::launder_cast<const T*>(&this->m_storage); }
|
||||
|
||||
inline internal_type &get_real_data()
|
||||
{ return *move_detail::launder_cast<internal_type*>(&this->m_storage); }
|
||||
|
||||
inline const internal_type &get_real_data() const
|
||||
{ return *move_detail::launder_cast<const internal_type*>(&this->m_storage); }
|
||||
|
||||
#if defined(BOOST_CONTAINER_DISABLE_ALIASING_WARNING)
|
||||
#pragma GCC diagnostic pop
|
||||
#undef BOOST_CONTAINER_DISABLE_ALIASING_WARNING
|
||||
# endif
|
||||
|
||||
template<class Alloc>
|
||||
inline void destructor(Alloc &a) BOOST_NOEXCEPT
|
||||
{
|
||||
allocator_traits<Alloc>::destroy
|
||||
(a, &this->get_real_data());
|
||||
this->~base_node();
|
||||
}
|
||||
|
||||
template<class Pair>
|
||||
inline
|
||||
typename dtl::enable_if< dtl::is_pair<Pair>, void >::type
|
||||
do_assign(const Pair &p)
|
||||
{
|
||||
typedef typename Pair::first_type first_type;
|
||||
const_cast<typename dtl::remove_const<first_type>::type &>(this->get_real_data().first) = p.first;
|
||||
this->get_real_data().second = p.second;
|
||||
}
|
||||
|
||||
template<class V>
|
||||
inline
|
||||
typename dtl::disable_if< dtl::is_pair<V>, void >::type
|
||||
do_assign(const V &v)
|
||||
{ this->get_real_data() = v; }
|
||||
|
||||
template<class Pair>
|
||||
inline
|
||||
typename dtl::enable_if< dtl::is_pair<Pair>, void >::type
|
||||
do_move_assign(Pair &p)
|
||||
{
|
||||
typedef typename Pair::first_type first_type;
|
||||
const_cast<first_type&>(this->get_real_data().first) = ::boost::move(p.first);
|
||||
this->get_real_data().second = ::boost::move(p.second);
|
||||
}
|
||||
|
||||
template<class V>
|
||||
inline
|
||||
typename dtl::disable_if< dtl::is_pair<V>, void >::type
|
||||
do_move_assign(V &v)
|
||||
{ this->get_real_data() = ::boost::move(v); }
|
||||
|
||||
private:
|
||||
base_node();
|
||||
|
||||
inline ~base_node()
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
namespace dtl {
|
||||
|
||||
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(key_compare)
|
||||
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(key_equal)
|
||||
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(hasher)
|
||||
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(predicate_type)
|
||||
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(bucket_traits)
|
||||
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(bucket_type)
|
||||
|
||||
template<class Allocator, class ICont>
|
||||
struct node_alloc_holder
|
||||
: public allocator_traits<Allocator>::template
|
||||
portable_rebind_alloc<typename ICont::value_type>::type //NodeAlloc
|
||||
{
|
||||
//If the intrusive container is an associative container, obtain the predicate, which will
|
||||
//be of type node_compare<>. If not an associative container val_compare will be a "nat" type.
|
||||
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT
|
||||
( boost::container::dtl::
|
||||
, ICont, key_compare, dtl::nat) intrusive_key_compare;
|
||||
|
||||
//If the intrusive container is a hash container, obtain the predicate, which will
|
||||
//be of type node_compare<>. If not an associative container val_equal will be a "nat" type.
|
||||
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT
|
||||
(boost::container::dtl::
|
||||
, ICont, key_equal, dtl::nat2) intrusive_val_equal;
|
||||
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT
|
||||
(boost::container::dtl::
|
||||
, ICont, hasher, dtl::nat3) intrusive_val_hasher;
|
||||
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT
|
||||
(boost::container::dtl::
|
||||
, ICont, bucket_traits, dtl::natN<0>) intrusive_bucket_traits;
|
||||
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT
|
||||
(boost::container::dtl::
|
||||
, ICont, bucket_type, dtl::natN<1>) intrusive_bucket_type;
|
||||
//In that case obtain the value predicate from the node predicate via predicate_type
|
||||
//if intrusive_key_compare is node_compare<>, nat otherwise
|
||||
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT
|
||||
(boost::container::dtl::
|
||||
, intrusive_val_equal
|
||||
, predicate_type, dtl::nat2) val_equal;
|
||||
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT
|
||||
(boost::container::dtl::
|
||||
, intrusive_val_hasher
|
||||
, predicate_type, dtl::nat3) val_hasher;
|
||||
|
||||
typedef allocator_traits<Allocator> allocator_traits_type;
|
||||
typedef typename allocator_traits_type::value_type val_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 dtl::allocator_version_traits<NodeAlloc> node_allocator_version_traits_type;
|
||||
typedef Allocator ValAlloc;
|
||||
typedef typename node_allocator_traits_type::pointer NodePtr;
|
||||
typedef dtl::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 dtl::integral_constant<unsigned,
|
||||
boost::container::dtl::
|
||||
version<NodeAlloc>::value> alloc_version;
|
||||
typedef typename ICont::iterator icont_iterator;
|
||||
typedef typename ICont::const_iterator icont_citerator;
|
||||
typedef allocator_node_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
|
||||
inline node_alloc_holder()
|
||||
{}
|
||||
|
||||
explicit node_alloc_holder(const intrusive_bucket_traits& bt)
|
||||
: m_icont(bt)
|
||||
{}
|
||||
|
||||
explicit node_alloc_holder(const ValAlloc &a)
|
||||
: NodeAlloc(a)
|
||||
{}
|
||||
|
||||
node_alloc_holder(const intrusive_bucket_traits& bt, const ValAlloc& a)
|
||||
: NodeAlloc(a)
|
||||
, m_icont(bt)
|
||||
{}
|
||||
|
||||
//Constructors for associative containers
|
||||
node_alloc_holder(const intrusive_key_compare &c, const ValAlloc &a)
|
||||
: NodeAlloc(a), m_icont(c)
|
||||
{}
|
||||
|
||||
node_alloc_holder(const intrusive_bucket_traits & bt, const val_hasher &hf, const val_equal &eql, const ValAlloc &a)
|
||||
: NodeAlloc(a)
|
||||
, m_icont(bt
|
||||
, typename ICont::hasher(hf)
|
||||
, typename ICont::key_equal(eql))
|
||||
{}
|
||||
|
||||
node_alloc_holder(const intrusive_bucket_traits& bt, const val_hasher &hf, const ValAlloc &a)
|
||||
: NodeAlloc(a)
|
||||
, m_icont(bt
|
||||
, typename ICont::hasher(hf)
|
||||
, typename ICont::key_equal())
|
||||
{}
|
||||
|
||||
node_alloc_holder(const intrusive_bucket_traits& bt, const val_hasher &hf)
|
||||
: m_icont(bt
|
||||
, typename ICont::hasher(hf)
|
||||
, typename ICont::key_equal())
|
||||
{}
|
||||
|
||||
explicit node_alloc_holder(const node_alloc_holder &x)
|
||||
: NodeAlloc(NodeAllocTraits::select_on_container_copy_construction(x.node_alloc()))
|
||||
{}
|
||||
|
||||
node_alloc_holder(const node_alloc_holder &x, const intrusive_key_compare &c)
|
||||
: NodeAlloc(NodeAllocTraits::select_on_container_copy_construction(x.node_alloc()))
|
||||
, m_icont(c)
|
||||
{}
|
||||
|
||||
node_alloc_holder(const node_alloc_holder &x, const intrusive_bucket_traits& bt, const val_hasher &hf, const val_equal &eql)
|
||||
: NodeAlloc(NodeAllocTraits::select_on_container_copy_construction(x.node_alloc()))
|
||||
, m_icont( bt
|
||||
, typename ICont::hasher(hf)
|
||||
, typename ICont::key_equal(eql))
|
||||
{}
|
||||
|
||||
node_alloc_holder(const val_hasher &hf, const intrusive_bucket_traits& bt, const val_equal &eql)
|
||||
: m_icont(bt
|
||||
, typename ICont::hasher(hf)
|
||||
, typename ICont::key_equal(eql))
|
||||
{}
|
||||
|
||||
explicit node_alloc_holder(BOOST_RV_REF(node_alloc_holder) x)
|
||||
: NodeAlloc(boost::move(BOOST_MOVE_TO_LV(x).node_alloc()))
|
||||
{ this->icont().swap(x.icont()); }
|
||||
|
||||
explicit node_alloc_holder(const intrusive_key_compare &c)
|
||||
: m_icont(c)
|
||||
{}
|
||||
|
||||
//helpers for move assignments
|
||||
explicit node_alloc_holder(BOOST_RV_REF(node_alloc_holder) x, const intrusive_key_compare &c)
|
||||
: NodeAlloc(boost::move(BOOST_MOVE_TO_LV(x).node_alloc())), m_icont(c)
|
||||
{ this->icont().swap(x.icont()); }
|
||||
|
||||
explicit node_alloc_holder(BOOST_RV_REF(node_alloc_holder) x, const intrusive_bucket_traits& bt, const val_hasher &hf, const val_equal &eql)
|
||||
: NodeAlloc(boost::move(BOOST_MOVE_TO_LV(x).node_alloc()))
|
||||
, m_icont( bt
|
||||
, typename ICont::hasher(hf)
|
||||
, typename ICont::key_equal(eql))
|
||||
{ this->icont().swap(BOOST_MOVE_TO_LV(x).icont()); }
|
||||
|
||||
inline void copy_assign_alloc(const node_alloc_holder &x)
|
||||
{
|
||||
dtl::bool_<allocator_traits_type::propagate_on_container_copy_assignment::value> flag;
|
||||
dtl::assign_alloc( static_cast<NodeAlloc &>(*this)
|
||||
, static_cast<const NodeAlloc &>(x), flag);
|
||||
}
|
||||
|
||||
inline void move_assign_alloc( node_alloc_holder &x)
|
||||
{
|
||||
dtl::bool_<allocator_traits_type::propagate_on_container_move_assignment::value> flag;
|
||||
dtl::move_alloc( static_cast<NodeAlloc &>(*this)
|
||||
, static_cast<NodeAlloc &>(x), flag);
|
||||
}
|
||||
|
||||
inline ~node_alloc_holder()
|
||||
{ this->clear(alloc_version()); }
|
||||
|
||||
inline size_type max_size() const
|
||||
{ return allocator_traits_type::max_size(this->node_alloc()); }
|
||||
|
||||
inline NodePtr allocate_one()
|
||||
{ return AllocVersionTraits::allocate_one(this->node_alloc()); }
|
||||
|
||||
inline 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();
|
||||
NodeAlloc &nalloc = this->node_alloc();
|
||||
Deallocator node_deallocator(p, nalloc);
|
||||
::new(boost::movelib::iterator_to_raw_pointer(p), boost_container_new_t())
|
||||
Node(nalloc, boost::forward<Args>(args)...);
|
||||
node_deallocator.release();
|
||||
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();\
|
||||
NodeAlloc &nalloc = this->node_alloc();\
|
||||
Deallocator node_deallocator(p, nalloc);\
|
||||
::new(boost::movelib::iterator_to_raw_pointer(p), boost_container_new_t())\
|
||||
Node(nalloc BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
|
||||
node_deallocator.release();\
|
||||
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();
|
||||
NodeAlloc &nalloc = this->node_alloc();
|
||||
Deallocator node_deallocator(p, nalloc);
|
||||
::new(boost::movelib::iterator_to_raw_pointer(p), boost_container_new_t())
|
||||
Node(iterator_arg_t(), nalloc, it);
|
||||
node_deallocator.release();
|
||||
return (p);
|
||||
}
|
||||
|
||||
template<class KeyConvertible>
|
||||
NodePtr create_node_from_key(BOOST_FWD_REF(KeyConvertible) key)
|
||||
{
|
||||
NodePtr p = this->allocate_one();
|
||||
BOOST_CONTAINER_TRY{
|
||||
::new(boost::movelib::iterator_to_raw_pointer(p), boost_container_new_t()) Node;
|
||||
NodeAlloc &na = this->node_alloc();
|
||||
node_allocator_traits_type::construct
|
||||
(na, dtl::addressof(p->get_real_data().first), boost::forward<KeyConvertible>(key));
|
||||
BOOST_CONTAINER_TRY{
|
||||
node_allocator_traits_type::construct(na, dtl::addressof(p->get_real_data().second));
|
||||
}
|
||||
BOOST_CONTAINER_CATCH(...){
|
||||
node_allocator_traits_type::destroy(na, dtl::addressof(p->get_real_data().first));
|
||||
BOOST_CONTAINER_RETHROW;
|
||||
}
|
||||
BOOST_CONTAINER_CATCH_END
|
||||
}
|
||||
BOOST_CONTAINER_CATCH(...) {
|
||||
p->destroy_header();
|
||||
this->node_alloc().deallocate(p, 1);
|
||||
BOOST_CONTAINER_RETHROW
|
||||
}
|
||||
BOOST_CONTAINER_CATCH_END
|
||||
return (p);
|
||||
}
|
||||
|
||||
void destroy_node(const NodePtr &nodep)
|
||||
{
|
||||
boost::movelib::to_raw_pointer(nodep)->destructor(this->node_alloc());
|
||||
this->deallocate_one(nodep);
|
||||
}
|
||||
|
||||
void swap(node_alloc_holder &x)
|
||||
{
|
||||
this->icont().swap(x.icont());
|
||||
dtl::bool_<allocator_traits_type::propagate_on_container_swap::value> flag;
|
||||
dtl::swap_alloc(this->node_alloc(), x.node_alloc(), flag);
|
||||
}
|
||||
|
||||
template<class FwdIterator, class Inserter>
|
||||
void allocate_many_and_construct
|
||||
(FwdIterator beg, size_type n, Inserter inserter)
|
||||
{
|
||||
if(n){
|
||||
typedef typename node_allocator_version_traits_type::multiallocation_chain multiallocation_chain_t;
|
||||
|
||||
//Try to allocate memory in a single block
|
||||
typedef typename multiallocation_chain_t::iterator multialloc_iterator_t;
|
||||
multiallocation_chain_t chain;
|
||||
NodeAlloc &nalloc = this->node_alloc();
|
||||
node_allocator_version_traits_type::allocate_individual(nalloc, n, chain);
|
||||
multialloc_iterator_t itbeg = chain.begin();
|
||||
multialloc_iterator_t itlast = chain.last();
|
||||
chain.clear();
|
||||
|
||||
Node *p = 0;
|
||||
BOOST_CONTAINER_TRY{
|
||||
Deallocator node_deallocator(NodePtr(), nalloc);
|
||||
dtl::scoped_node_destructor<NodeAlloc> sdestructor(nalloc, 0);
|
||||
while(n){
|
||||
--n;
|
||||
p = boost::movelib::iterator_to_raw_pointer(itbeg);
|
||||
++itbeg; //Increment iterator before overwriting pointed memory
|
||||
//This does not throw
|
||||
::new(boost::movelib::iterator_to_raw_pointer(p), boost_container_new_t())
|
||||
Node(iterator_arg_t(), nalloc, beg);
|
||||
sdestructor.set(p);
|
||||
++beg;
|
||||
//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.release();
|
||||
}
|
||||
sdestructor.release();
|
||||
node_deallocator.release();
|
||||
}
|
||||
BOOST_CONTAINER_CATCH(...){
|
||||
chain.incorporate_after(chain.last(), &*itbeg, &*itlast, n);
|
||||
node_allocator_version_traits_type::deallocate_individual(this->node_alloc(), chain);
|
||||
BOOST_CONTAINER_RETHROW
|
||||
}
|
||||
BOOST_CONTAINER_CATCH_END
|
||||
}
|
||||
}
|
||||
|
||||
inline void clear(version_1)
|
||||
{ this->icont().clear_and_dispose(Destroyer(this->node_alloc())); }
|
||||
|
||||
void clear(version_2)
|
||||
{
|
||||
typename NodeAlloc::multiallocation_chain chain;
|
||||
allocator_node_destroyer_and_chain_builder<NodeAlloc> builder(this->node_alloc(), chain);
|
||||
this->icont().clear_and_dispose(builder);
|
||||
//BOOST_CONTAINER_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)
|
||||
{
|
||||
NodeAlloc & nalloc = this->node_alloc();
|
||||
typename NodeAlloc::multiallocation_chain chain;
|
||||
allocator_node_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>
|
||||
inline size_type erase_key(const Key& k, version_1)
|
||||
{ return this->icont().erase_and_dispose(k, Destroyer(this->node_alloc())); }
|
||||
|
||||
template<class Key>
|
||||
inline size_type erase_key(const Key& k, version_2)
|
||||
{
|
||||
allocator_multialloc_chain_node_deallocator<NodeAlloc> chain_holder(this->node_alloc());
|
||||
return this->icont().erase_and_dispose(k, chain_holder.get_chain_builder());
|
||||
}
|
||||
|
||||
template<class Key, class KeyCompare>
|
||||
inline size_type erase_key(const Key& k, KeyCompare cmp, version_1)
|
||||
{
|
||||
return this->icont().erase_and_dispose(k, cmp, Destroyer(this->node_alloc()));
|
||||
}
|
||||
|
||||
template<class Key, class KeyCompare>
|
||||
inline size_type erase_key(const Key& k, KeyCompare cmp, version_2)
|
||||
{
|
||||
allocator_multialloc_chain_node_deallocator<NodeAlloc> chain_holder(this->node_alloc());
|
||||
return this->icont().erase_and_dispose(k, cmp, chain_holder.get_chain_builder());
|
||||
}
|
||||
|
||||
protected:
|
||||
struct cloner
|
||||
{
|
||||
inline explicit cloner(node_alloc_holder &holder)
|
||||
: m_holder(holder)
|
||||
{}
|
||||
|
||||
inline NodePtr operator()(const Node &other) const
|
||||
{ return m_holder.create_node(other.get_real_data()); }
|
||||
|
||||
node_alloc_holder &m_holder;
|
||||
};
|
||||
|
||||
struct move_cloner
|
||||
{
|
||||
inline move_cloner(node_alloc_holder &holder)
|
||||
: m_holder(holder)
|
||||
{}
|
||||
|
||||
inline NodePtr operator()(Node &other)
|
||||
{ //Use get_real_data() instead of get_real_data to allow moving const key in [multi]map
|
||||
return m_holder.create_node(::boost::move(other.get_real_data()));
|
||||
}
|
||||
|
||||
node_alloc_holder &m_holder;
|
||||
};
|
||||
|
||||
inline ICont &non_const_icont() const
|
||||
{ return const_cast<ICont&>(this->m_icont); }
|
||||
|
||||
inline NodeAlloc &node_alloc()
|
||||
{ return static_cast<NodeAlloc &>(*this); }
|
||||
|
||||
inline const NodeAlloc &node_alloc() const
|
||||
{ return static_cast<const NodeAlloc &>(*this); }
|
||||
|
||||
public:
|
||||
inline ICont &icont()
|
||||
{ return this->m_icont; }
|
||||
|
||||
inline const ICont &icont() const
|
||||
{ return this->m_icont; }
|
||||
|
||||
protected:
|
||||
//The intrusive container
|
||||
ICont m_icont;
|
||||
};
|
||||
|
||||
template<class Node, class KeyOfValue>
|
||||
struct key_of_node : KeyOfValue
|
||||
{
|
||||
typedef typename KeyOfValue::type type;
|
||||
|
||||
inline key_of_node()
|
||||
{}
|
||||
|
||||
inline const type& operator()(const Node& x) const
|
||||
{ return this->KeyOfValue::operator()(x.get_data()); }
|
||||
};
|
||||
|
||||
|
||||
} //namespace dtl {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif // BOOST_CONTAINER_DETAIL_NODE_ALLOC_HPP_
|
||||
157
include/boost/container/detail/node_pool.hpp
Normal file
157
include/boost/container/detail/node_pool.hpp
Normal file
@@ -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 dtl {
|
||||
|
||||
//!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::dtl::
|
||||
private_node_pool_impl<fake_segment_manager>
|
||||
{
|
||||
typedef boost::container::dtl::
|
||||
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;
|
||||
BOOST_STATIC_CONSTEXPR 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 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 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 dtl {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DETAIL_NODE_POOL_HPP
|
||||
375
include/boost/container/detail/node_pool_impl.hpp
Normal file
375
include/boost/container/detail/node_pool_impl.hpp
Normal file
@@ -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/move/detail/to_raw_pointer.hpp>
|
||||
#include <boost/move/detail/force_ptr.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/assert.hpp>
|
||||
#include <cstddef>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace dtl {
|
||||
|
||||
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
|
||||
inline ~private_node_pool_impl()
|
||||
{ this->purge_blocks(); }
|
||||
|
||||
inline size_type get_real_num_node() const
|
||||
{ return m_nodes_per_block; }
|
||||
|
||||
//!Returns the segment manager. Never throws
|
||||
inline segment_manager_base_type* get_segment_manager_base()const
|
||||
{ return boost::movelib::to_raw_pointer(mp_segment_mngr_base); }
|
||||
|
||||
inline void *allocate_node()
|
||||
{ return this->priv_alloc_node(); }
|
||||
|
||||
//!Deallocates an array pointed by ptr. Never throws
|
||||
inline 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(const_cast<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());
|
||||
}
|
||||
|
||||
inline 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(const_cast<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_CONTAINER_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_CONTAINER_CATCH(...){
|
||||
//to-do: if possible, an efficient way to deallocate allocated blocks
|
||||
BOOST_CONTAINER_RETHROW
|
||||
}
|
||||
BOOST_CONTAINER_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 *move_detail::force_ptr<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 dtl {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DETAIL_ADAPTIVE_NODE_POOL_IMPL_HPP
|
||||
68
include/boost/container/detail/operator_new_helpers.hpp
Normal file
68
include/boost/container/detail/operator_new_helpers.hpp
Normal file
@@ -0,0 +1,68 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2025-2025. 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_OPERATOR_NEW_HELPERS_HPP
|
||||
#define BOOST_CONTAINER_DETAIL_OPERATOR_NEW_HELPERS_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/detail/std_fwd.hpp>
|
||||
#include <boost/container/throw_exception.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace dtl {
|
||||
|
||||
template <class T>
|
||||
T* operator_new_allocate(std::size_t count)
|
||||
{
|
||||
const std::size_t max_count = std::size_t(-1)/(2*sizeof(T));
|
||||
if(BOOST_UNLIKELY(count > max_count))
|
||||
throw_bad_alloc();
|
||||
#if defined(__cpp_aligned_new)
|
||||
BOOST_IF_CONSTEXPR(__STDCPP_DEFAULT_NEW_ALIGNMENT__ < alignof(T)) {
|
||||
return static_cast<T*>(::operator new(count*sizeof(T), std::align_val_t(alignof(T))));
|
||||
}
|
||||
#endif
|
||||
return static_cast<T*>(::operator new(count*sizeof(T)));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void operator_delete_deallocate(T* ptr, std::size_t n) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{
|
||||
(void)n;
|
||||
#ifdef __cpp_aligned_new
|
||||
BOOST_IF_CONSTEXPR(__STDCPP_DEFAULT_NEW_ALIGNMENT__ < alignof(T)) {
|
||||
# if defined(__cpp_sized_deallocation)
|
||||
::operator delete((void*)ptr, n * sizeof(T), std::align_val_t(alignof(T)));
|
||||
#else
|
||||
::operator delete((void*)ptr, std::align_val_t(alignof(T)));
|
||||
# endif
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
# if defined(__cpp_sized_deallocation)
|
||||
::operator delete((void*)ptr, n * sizeof(T));
|
||||
#else
|
||||
::operator delete((void*)ptr);
|
||||
# endif
|
||||
}
|
||||
|
||||
} //namespace dtl {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DETAIL_OPERATOR_NEW_HELPERS_HPP
|
||||
665
include/boost/container/detail/pair.hpp
Normal file
665
include/boost/container/detail/pair.hpp
Normal file
@@ -0,0 +1,665 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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/container_fwd.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>
|
||||
#include <boost/container/detail/is_pair.hpp> //Forward declares boost::tuples::tuple
|
||||
#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 container {
|
||||
namespace pair_impl {
|
||||
|
||||
template <class TupleClass>
|
||||
struct is_boost_tuple
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR bool value = false;
|
||||
};
|
||||
|
||||
template <
|
||||
class T0, class T1, class T2,
|
||||
class T3, class T4, class T5,
|
||||
class T6, class T7, class T8,
|
||||
class T9>
|
||||
struct is_boost_tuple< boost::tuples::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR bool value = true;
|
||||
};
|
||||
|
||||
template<class Tuple>
|
||||
struct disable_if_boost_tuple
|
||||
: boost::container::dtl::disable_if< is_boost_tuple<Tuple> >
|
||||
{};
|
||||
|
||||
template<class T>
|
||||
struct is_tuple_null
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR bool value = false;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct is_tuple_null<boost::tuples::null_type>
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR bool value = true;
|
||||
};
|
||||
|
||||
} //namespace detail {
|
||||
|
||||
#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
|
||||
|
||||
#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 dtl {
|
||||
|
||||
struct piecewise_construct_use
|
||||
{
|
||||
//Avoid warnings of unused "piecewise_construct"
|
||||
piecewise_construct_use()
|
||||
{ (void)&::boost::container::piecewise_construct; }
|
||||
};
|
||||
|
||||
struct pair_nat;
|
||||
|
||||
template<typename T, typename U, typename V>
|
||||
void get(T); //to enable ADL
|
||||
|
||||
///@endcond
|
||||
|
||||
#ifdef _LIBCPP_DEPRECATED_ABI_DISABLE_PAIR_TRIVIAL_COPY_CTOR
|
||||
//Libc++, in some versions, has an ABI breakage that needs some
|
||||
//padding in dtl::pair, as "std::pair::first" is not at offset zero.
|
||||
//See: https://reviews.llvm.org/D56357 for more information.
|
||||
//
|
||||
template <class T1, class T2, std::size_t N>
|
||||
struct pair_padding
|
||||
{
|
||||
char padding[N];
|
||||
};
|
||||
|
||||
template <class T1, class T2>
|
||||
struct pair_padding<T1, T2, 0>
|
||||
{
|
||||
};
|
||||
|
||||
template <class T1, class T2>
|
||||
struct simple_pair
|
||||
{
|
||||
T1 first;
|
||||
T2 second;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
template <class T1, class T2>
|
||||
struct pair
|
||||
#ifdef _LIBCPP_DEPRECATED_ABI_DISABLE_PAIR_TRIVIAL_COPY_CTOR
|
||||
: pair_padding<T1, T2, sizeof(std::pair<T1, T2>) - sizeof(simple_pair<T1, T2>)>
|
||||
#endif
|
||||
{
|
||||
private:
|
||||
BOOST_COPYABLE_AND_MOVABLE(pair)
|
||||
|
||||
public:
|
||||
typedef T1 first_type;
|
||||
typedef T2 second_type;
|
||||
|
||||
T1 first;
|
||||
T2 second;
|
||||
|
||||
//Default constructor
|
||||
pair()
|
||||
: first(), second()
|
||||
{
|
||||
BOOST_CONTAINER_STATIC_ASSERT((sizeof(std::pair<T1, T2>) == sizeof(pair<T1, T2>)));
|
||||
}
|
||||
|
||||
//pair copy assignment
|
||||
pair(const pair& x)
|
||||
: first(x.first), second(x.second)
|
||||
{
|
||||
BOOST_CONTAINER_STATIC_ASSERT((sizeof(std::pair<T1, T2>) == sizeof(pair<T1, T2>)));
|
||||
}
|
||||
|
||||
//pair move constructor
|
||||
pair(BOOST_RV_REF(pair) p)
|
||||
: first(::boost::move(BOOST_MOVE_TO_LV(p).first)), second(::boost::move(BOOST_MOVE_TO_LV(p).second))
|
||||
{
|
||||
BOOST_CONTAINER_STATIC_ASSERT((sizeof(std::pair<T1, T2>) == sizeof(pair<T1, T2>)));
|
||||
}
|
||||
|
||||
template <class D, class S>
|
||||
pair(const pair<D, S> &p)
|
||||
: first(p.first), second(p.second)
|
||||
{
|
||||
BOOST_CONTAINER_STATIC_ASSERT((sizeof(std::pair<T1, T2>) == sizeof(pair<T1, T2>)));
|
||||
}
|
||||
|
||||
template <class D, class S>
|
||||
pair(BOOST_RV_REF_BEG pair<D, S> BOOST_RV_REF_END p)
|
||||
: first(::boost::move(BOOST_MOVE_TO_LV(p).first)), second(::boost::move(BOOST_MOVE_TO_LV(p).second))
|
||||
{
|
||||
BOOST_CONTAINER_STATIC_ASSERT((sizeof(std::pair<T1, T2>) == sizeof(pair<T1, T2>)));
|
||||
}
|
||||
|
||||
//pair from two values
|
||||
pair(const T1 &t1, const T2 &t2)
|
||||
: first(t1)
|
||||
, second(t2)
|
||||
{
|
||||
BOOST_CONTAINER_STATIC_ASSERT((sizeof(std::pair<T1, T2>) == sizeof(pair<T1, 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))
|
||||
{
|
||||
BOOST_CONTAINER_STATIC_ASSERT((sizeof(std::pair<T1, T2>) == sizeof(pair<T1, T2>)));
|
||||
}
|
||||
|
||||
//And now compatibility with std::pair
|
||||
pair(const std::pair<T1, T2>& x)
|
||||
: first(x.first), second(x.second)
|
||||
{
|
||||
BOOST_CONTAINER_STATIC_ASSERT((sizeof(std::pair<T1, T2>) == sizeof(pair<T1, T2>)));
|
||||
}
|
||||
|
||||
template <class D, class S>
|
||||
pair(const std::pair<D, S>& p)
|
||||
: first(p.first), second(p.second)
|
||||
{
|
||||
BOOST_CONTAINER_STATIC_ASSERT((sizeof(std::pair<T1, T2>) == sizeof(pair<T1, T2>)));
|
||||
}
|
||||
|
||||
pair(BOOST_RV_REF_BEG std::pair<T1, T2> BOOST_RV_REF_END p)
|
||||
: first(::boost::move(BOOST_MOVE_TO_LV(p).first)), second(::boost::move(BOOST_MOVE_TO_LV(p).second))
|
||||
{
|
||||
BOOST_CONTAINER_STATIC_ASSERT((sizeof(std::pair<T1, T2>) == sizeof(pair<T1, T2>)));
|
||||
}
|
||||
|
||||
template <class D, class S>
|
||||
pair(BOOST_RV_REF_BEG std::pair<D, S> BOOST_RV_REF_END p)
|
||||
: first(::boost::move(BOOST_MOVE_TO_LV(p).first)), second(::boost::move(BOOST_MOVE_TO_LV(p).second))
|
||||
{
|
||||
BOOST_CONTAINER_STATIC_ASSERT((sizeof(std::pair<T1, T2>) == sizeof(pair<T1, T2>)));
|
||||
}
|
||||
|
||||
#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)...)\
|
||||
{
|
||||
BOOST_CONTAINER_STATIC_ASSERT((sizeof(std::pair<T1, T2>) == sizeof(pair<T1, T2>)));
|
||||
}
|
||||
#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_CONTAINER_STATIC_ASSERT((sizeof(std::pair<T1, T2>) == sizeof(pair<T1, T2>)));\
|
||||
}\
|
||||
//
|
||||
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\
|
||||
, typename dtl::enable_if_c\
|
||||
< pair_impl::is_boost_tuple< BoostTuple<BOOST_MOVE_TARG##N BOOST_MOVE_I##N BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(10,N),::boost::tuples::null_type)> >::value &&\
|
||||
!(pair_impl::is_tuple_null<BOOST_MOVE_LAST_TARG##N>::value || pair_impl::is_tuple_null<BOOST_MOVE_LAST_TARGQ##M>::value) \
|
||||
>::type* = 0\
|
||||
)\
|
||||
: first(BOOST_MOVE_TMPL_GET##N), second(BOOST_MOVE_TMPL_GETQ##M)\
|
||||
{ (void)p; (void)q;\
|
||||
BOOST_CONTAINER_STATIC_ASSERT((sizeof(std::pair<T1, T2>) == sizeof(pair<T1, T2>)));\
|
||||
}\
|
||||
//
|
||||
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
|
||||
, class = typename pair_impl::disable_if_boost_tuple< Tuple<Args1...> >::type>
|
||||
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())
|
||||
{
|
||||
BOOST_CONTAINER_STATIC_ASSERT((sizeof(std::pair<T1, T2>) == sizeof(pair<T1, T2>)));
|
||||
}
|
||||
# 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
|
||||
, class = typename pair_impl::disable_if_boost_tuple< Tuple<Args1...> >::type>
|
||||
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)))
|
||||
{
|
||||
BOOST_CONTAINER_STATIC_ASSERT((sizeof(std::pair<T1, T2>) == sizeof(pair<T1, 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_CONTAINER_STATIC_ASSERT((sizeof(std::pair<T1, T2>) == sizeof(pair<T1, T2>)));\
|
||||
}\
|
||||
//
|
||||
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_CONTAINER_STATIC_ASSERT((sizeof(std::pair<T1, T2>) == sizeof(pair<T1, T2>)));\
|
||||
}\
|
||||
//
|
||||
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(BOOST_MOVE_TO_LV(p).first);
|
||||
second = ::boost::move(BOOST_MOVE_TO_LV(p).second);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class D, class S>
|
||||
typename ::boost::container::dtl::disable_if_or
|
||||
< pair &
|
||||
, ::boost::container::dtl::is_same<T1, D>
|
||||
, ::boost::container::dtl::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::dtl::disable_if_or
|
||||
< pair &
|
||||
, ::boost::container::dtl::is_same<T1, D>
|
||||
, ::boost::container::dtl::is_same<T2, S>
|
||||
>::type
|
||||
operator=(BOOST_RV_REF_BEG pair<D, S> BOOST_RV_REF_END p)
|
||||
{
|
||||
first = ::boost::move(BOOST_MOVE_TO_LV(p).first);
|
||||
second = ::boost::move(BOOST_MOVE_TO_LV(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(BOOST_MOVE_TO_LV(p).first);
|
||||
second = ::boost::move(BOOST_MOVE_TO_LV(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(BOOST_MOVE_TO_LV(p).first);
|
||||
second = ::boost::move(BOOST_MOVE_TO_LV(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 dtl {
|
||||
} //namespace container {
|
||||
|
||||
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
|
||||
template<class T1, class T2>
|
||||
struct has_move_emulation_enabled< ::boost::container::dtl::pair<T1, T2> >
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR 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::dtl::pair<T1, T2> >
|
||||
//This specialization is needed to avoid instantiation of pair in
|
||||
//is_class, and allow recursive maps.
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR 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.
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR bool value = true;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct is_union;
|
||||
|
||||
template <class T1, class T2>
|
||||
struct is_union< ::boost::container::dtl::pair<T1, T2> >
|
||||
//This specialization is needed to avoid instantiation of pair in
|
||||
//is_class, and allow recursive maps.
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR 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.
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR bool value = false;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct is_class;
|
||||
|
||||
template <class T1, class T2>
|
||||
struct is_class< ::boost::container::dtl::pair<T1, T2> >
|
||||
//This specialization is needed to avoid instantiation of pair in
|
||||
//is_class, and allow recursive maps.
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR 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.
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR bool value = true;
|
||||
};
|
||||
|
||||
|
||||
//Triviality of pair
|
||||
|
||||
//
|
||||
// is_trivially_copy_assignable
|
||||
//
|
||||
|
||||
template<class T>
|
||||
struct is_trivially_copy_assignable;
|
||||
|
||||
template<class A, class B>
|
||||
struct is_trivially_copy_assignable<boost::container::dtl::pair<A,B> >
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR bool value = boost::move_detail::is_trivially_copy_assignable<A>::value &&
|
||||
boost::move_detail::is_trivially_copy_assignable<B>::value;
|
||||
};
|
||||
|
||||
template<class A, class B>
|
||||
struct is_trivially_copy_assignable<std::pair<A,B> >
|
||||
: is_trivially_copy_assignable<boost::container::dtl::pair<A,B> >
|
||||
{};
|
||||
|
||||
//
|
||||
// is_trivially_move_assignable
|
||||
//
|
||||
|
||||
template<class T>
|
||||
struct is_trivially_move_assignable;
|
||||
|
||||
template<class A, class B>
|
||||
struct is_trivially_move_assignable<boost::container::dtl::pair<A,B> >
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR bool value = boost::move_detail::is_trivially_move_assignable<A>::value &&
|
||||
boost::move_detail::is_trivially_move_assignable<B>::value;
|
||||
};
|
||||
|
||||
template<class A, class B>
|
||||
struct is_trivially_move_assignable<std::pair<A,B> >
|
||||
: is_trivially_move_assignable<boost::container::dtl::pair<A,B> >
|
||||
{};
|
||||
|
||||
|
||||
//
|
||||
// is_trivially_copy_constructible
|
||||
//
|
||||
|
||||
template<class T>
|
||||
struct is_trivially_copy_constructible;
|
||||
|
||||
template<class A, class B>
|
||||
struct is_trivially_copy_constructible<boost::container::dtl::pair<A,B> >
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR bool value = boost::move_detail::is_trivially_copy_constructible<A>::value &&
|
||||
boost::move_detail::is_trivially_copy_constructible<B>::value;
|
||||
};
|
||||
|
||||
template<class A, class B>
|
||||
struct is_trivially_copy_constructible<std::pair<A,B> >
|
||||
: is_trivially_copy_constructible<boost::container::dtl::pair<A,B> >
|
||||
{};
|
||||
|
||||
//
|
||||
// is_trivially_move_constructible
|
||||
//
|
||||
|
||||
template<class T>
|
||||
struct is_trivially_move_constructible;
|
||||
|
||||
template<class A, class B>
|
||||
struct is_trivially_move_constructible<boost::container::dtl::pair<A,B> >
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR bool value = boost::move_detail::is_trivially_move_constructible<A>::value &&
|
||||
boost::move_detail::is_trivially_move_constructible<B>::value;
|
||||
};
|
||||
|
||||
template<class A, class B>
|
||||
struct is_trivially_move_constructible<std::pair<A,B> >
|
||||
: is_trivially_move_constructible<boost::container::dtl::pair<A,B> >
|
||||
{};
|
||||
|
||||
template<class T>
|
||||
struct is_trivially_destructible;
|
||||
|
||||
template<class A, class B>
|
||||
struct is_trivially_destructible<boost::container::dtl::pair<A,B> >
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR bool value = boost::move_detail::is_trivially_destructible<A>::value &&
|
||||
boost::move_detail::is_trivially_destructible<B>::value;
|
||||
};
|
||||
|
||||
template<class A, class B>
|
||||
struct is_trivially_destructible<std::pair<A,B> >
|
||||
: is_trivially_destructible<boost::container::dtl::pair<A,B> >
|
||||
{};
|
||||
|
||||
} //namespace move_detail{
|
||||
|
||||
template<class T>
|
||||
struct has_trivial_destructor_after_move;
|
||||
|
||||
template<class A, class B>
|
||||
struct has_trivial_destructor_after_move<boost::container::dtl::pair<A,B> >
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR bool value = boost::has_trivial_destructor_after_move<A>::value &&
|
||||
boost::has_trivial_destructor_after_move<B>::value;
|
||||
};
|
||||
|
||||
template<class A, class B>
|
||||
struct has_trivial_destructor_after_move<std::pair<A,B> >
|
||||
: has_trivial_destructor_after_move<boost::container::dtl::pair<A,B> >
|
||||
{};
|
||||
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DETAIL_PAIR_HPP
|
||||
55
include/boost/container/detail/pair_key_mapped_of_value.hpp
Normal file
55
include/boost/container/detail/pair_key_mapped_of_value.hpp
Normal file
@@ -0,0 +1,55 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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_PAIR_KEY_MAPPED_OF_VALUE_HPP
|
||||
#define BOOST_CONTAINER_PAIR_KEY_MAPPED_OF_VALUE_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 {
|
||||
|
||||
template<class Key, class Mapped>
|
||||
struct pair_key_mapped_of_value
|
||||
{
|
||||
typedef Key key_type;
|
||||
typedef Mapped mapped_type;
|
||||
|
||||
template<class Pair>
|
||||
const key_type & key_of_value(const Pair &p) const
|
||||
{ return p.first; }
|
||||
|
||||
template<class Pair>
|
||||
const mapped_type & mapped_of_value(const Pair &p) const
|
||||
{ return p.second; }
|
||||
|
||||
template<class Pair>
|
||||
key_type & key_of_value(Pair &p) const
|
||||
{ return const_cast<key_type&>(p.first); }
|
||||
|
||||
template<class Pair>
|
||||
mapped_type & mapped_of_value(Pair &p) const
|
||||
{ return p.second; }
|
||||
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif // BOOST_CONTAINER_PAIR_KEY_MAPPED_OF_VALUE_HPP
|
||||
24
include/boost/container/detail/placement_new.hpp
Normal file
24
include/boost/container/detail/placement_new.hpp
Normal file
@@ -0,0 +1,24 @@
|
||||
#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.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
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
|
||||
57
include/boost/container/detail/pool_common.hpp
Normal file
57
include/boost/container/detail/pool_common.hpp
Normal file
@@ -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 dtl {
|
||||
|
||||
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
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR bool value = false;
|
||||
};
|
||||
|
||||
} //namespace dtl {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DETAIL_ADAPTIVE_NODE_POOL_IMPL_HPP
|
||||
102
include/boost/container/detail/pool_common_alloc.hpp
Normal file
102
include/boost/container/detail/pool_common_alloc.hpp
Normal file
@@ -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 dtl{
|
||||
|
||||
struct node_slist_helper
|
||||
: public boost::container::dtl::node_slist<void*>
|
||||
{};
|
||||
|
||||
struct fake_segment_manager
|
||||
{
|
||||
typedef void * void_pointer;
|
||||
BOOST_STATIC_CONSTEXPR std::size_t PayloadPerAllocation = BOOST_CONTAINER_ALLOCATION_PAYLOAD;
|
||||
|
||||
typedef boost::container::dtl::
|
||||
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();
|
||||
multiallocation_chain::pointer_pair 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 dtl{
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace dtl {
|
||||
|
||||
template<class T>
|
||||
struct is_stateless_segment_manager;
|
||||
|
||||
template<>
|
||||
struct is_stateless_segment_manager
|
||||
<boost::container::dtl::fake_segment_manager>
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR bool value = true;
|
||||
};
|
||||
|
||||
} //namespace dtl {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_CONTAINER_DETAIL_POOL_COMMON_ALLOC_HPP
|
||||
187
include/boost/container/detail/pool_resource.hpp
Normal file
187
include/boost/container/detail/pool_resource.hpp
Normal file
@@ -0,0 +1,187 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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;
|
||||
|
||||
BOOST_CONTAINER_CONSTANT_VAR std::size_t pool_options_minimum_max_blocks_per_chunk = 1u;
|
||||
BOOST_CONTAINER_CONSTANT_VAR std::size_t pool_options_default_max_blocks_per_chunk = 32u;
|
||||
BOOST_CONTAINER_CONSTANT_VAR std::size_t pool_options_minimum_largest_required_pool_block =
|
||||
memory_resource::max_align > 2*sizeof(void*) ? memory_resource::max_align : 2*sizeof(void*);
|
||||
BOOST_CONTAINER_CONSTANT_VAR 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()`.
|
||||
~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.
|
||||
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.
|
||||
void do_deallocate(void* p, std::size_t bytes, std::size_t alignment);
|
||||
|
||||
//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
|
||||
121
include/boost/container/detail/singleton.hpp
Normal file
121
include/boost/container/detail/singleton.hpp
Normal file
@@ -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 dtl {
|
||||
|
||||
// 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 dtl
|
||||
} // namespace container
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_CONTAINER_DETAIL_SINGLETON_DETAIL_HPP
|
||||
75
include/boost/container/detail/std_fwd.hpp
Normal file
75
include/boost/container/detail/std_fwd.hpp
Normal file
@@ -0,0 +1,75 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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 <cstddef>
|
||||
|
||||
#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 T>
|
||||
struct equal_to;
|
||||
|
||||
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;
|
||||
|
||||
template <class Ptr>
|
||||
struct pointer_traits;
|
||||
|
||||
BOOST_MOVE_STD_NS_END
|
||||
#include <boost/move/detail/std_ns_end.hpp>
|
||||
|
||||
#if defined(__cpp_aligned_new)
|
||||
|
||||
//align_val_t is not usually in an inline namespace
|
||||
namespace std {
|
||||
|
||||
enum class align_val_t : std::size_t;
|
||||
|
||||
} //namespace std
|
||||
|
||||
#endif
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DETAIL_STD_FWD_HPP
|
||||
181
include/boost/container/detail/thread_mutex.hpp
Normal file
181
include/boost/container/detail/thread_mutex.hpp
Normal file
@@ -0,0 +1,181 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2018-2018. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/interprocess for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// This code is partially based on the lightweight mutex implemented
|
||||
// by Boost.SmartPtr:
|
||||
//
|
||||
// Copyright (c) 2002, 2003 Peter Dimov
|
||||
// Copyright (c) Microsoft Corporation 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)
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_CONTAINER_DETAIL_THREAD_MUTEX_HPP
|
||||
#define BOOST_CONTAINER_DETAIL_THREAD_MUTEX_HPP
|
||||
|
||||
#include <boost/container/detail/config_begin.hpp>
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
|
||||
#if defined(BOOST_HAS_PTHREADS)
|
||||
|
||||
#include <pthread.h>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
namespace boost{
|
||||
namespace container {
|
||||
namespace dtl {
|
||||
|
||||
class thread_mutex
|
||||
{
|
||||
public:
|
||||
thread_mutex()
|
||||
{
|
||||
BOOST_VERIFY(pthread_mutex_init(&m_mut, 0) == 0);
|
||||
}
|
||||
|
||||
~thread_mutex()
|
||||
{
|
||||
BOOST_VERIFY(pthread_mutex_destroy(&m_mut) == 0);
|
||||
}
|
||||
|
||||
void lock()
|
||||
{
|
||||
BOOST_VERIFY(pthread_mutex_lock( &m_mut) == 0);
|
||||
}
|
||||
|
||||
void unlock()
|
||||
{
|
||||
BOOST_VERIFY(pthread_mutex_unlock(&m_mut) == 0);
|
||||
}
|
||||
|
||||
private:
|
||||
thread_mutex(thread_mutex const &);
|
||||
thread_mutex & operator=(thread_mutex const &);
|
||||
|
||||
pthread_mutex_t m_mut;
|
||||
};
|
||||
|
||||
} // namespace dtl {
|
||||
} // namespace container {
|
||||
} // namespace boost {
|
||||
|
||||
#else //!BOOST_HAS_PTHREADS (Windows implementation)
|
||||
|
||||
#ifdef BOOST_USE_WINDOWS_H
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
namespace boost{
|
||||
namespace container {
|
||||
namespace dtl {
|
||||
|
||||
typedef ::CRITICAL_SECTION win_critical_section;
|
||||
|
||||
} // namespace dtl {
|
||||
} // namespace container {
|
||||
} // namespace boost {
|
||||
|
||||
#else //! BOOST_USE_WINDOWS_H
|
||||
|
||||
struct _RTL_CRITICAL_SECTION_DEBUG;
|
||||
struct _RTL_CRITICAL_SECTION;
|
||||
|
||||
namespace boost{
|
||||
namespace container {
|
||||
namespace dtl {
|
||||
|
||||
#ifdef BOOST_PLAT_WINDOWS_UWP
|
||||
extern "C" __declspec(dllimport) int __stdcall InitializeCriticalSectionEx(::_RTL_CRITICAL_SECTION *, unsigned long, unsigned long);
|
||||
#else
|
||||
extern "C" __declspec(dllimport) void __stdcall InitializeCriticalSection(::_RTL_CRITICAL_SECTION *);
|
||||
#endif
|
||||
extern "C" __declspec(dllimport) void __stdcall EnterCriticalSection(::_RTL_CRITICAL_SECTION *);
|
||||
extern "C" __declspec(dllimport) void __stdcall LeaveCriticalSection(::_RTL_CRITICAL_SECTION *);
|
||||
extern "C" __declspec(dllimport) void __stdcall DeleteCriticalSection(::_RTL_CRITICAL_SECTION *);
|
||||
|
||||
struct win_critical_section
|
||||
{
|
||||
struct _RTL_CRITICAL_SECTION_DEBUG * DebugInfo;
|
||||
long LockCount;
|
||||
long RecursionCount;
|
||||
void * OwningThread;
|
||||
void * LockSemaphore;
|
||||
#if defined(_WIN64)
|
||||
unsigned __int64 SpinCount;
|
||||
#else
|
||||
unsigned long SpinCount;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace dtl {
|
||||
} // namespace container {
|
||||
} // namespace boost {
|
||||
|
||||
#endif //BOOST_USE_WINDOWS_H
|
||||
|
||||
namespace boost{
|
||||
namespace container {
|
||||
namespace dtl {
|
||||
|
||||
class thread_mutex
|
||||
{
|
||||
public:
|
||||
thread_mutex()
|
||||
{
|
||||
#ifdef BOOST_PLAT_WINDOWS_UWP
|
||||
(InitializeCriticalSectionEx)(reinterpret_cast< ::_RTL_CRITICAL_SECTION* >(&m_crit_sect), 4000, 0);
|
||||
#else
|
||||
(InitializeCriticalSection)(reinterpret_cast< ::_RTL_CRITICAL_SECTION* >(&m_crit_sect));
|
||||
#endif
|
||||
}
|
||||
|
||||
void lock()
|
||||
{
|
||||
(EnterCriticalSection)(reinterpret_cast< ::_RTL_CRITICAL_SECTION* >(&m_crit_sect));
|
||||
}
|
||||
|
||||
void unlock()
|
||||
{
|
||||
(LeaveCriticalSection)(reinterpret_cast< ::_RTL_CRITICAL_SECTION* >(&m_crit_sect));
|
||||
}
|
||||
|
||||
~thread_mutex()
|
||||
{
|
||||
(DeleteCriticalSection)(reinterpret_cast< ::_RTL_CRITICAL_SECTION* >(&m_crit_sect));
|
||||
}
|
||||
|
||||
private:
|
||||
thread_mutex(thread_mutex const &);
|
||||
thread_mutex & operator=(thread_mutex const &);
|
||||
|
||||
win_critical_section m_crit_sect;
|
||||
};
|
||||
|
||||
} // namespace dtl {
|
||||
} // namespace container {
|
||||
} // namespace boost {
|
||||
|
||||
#endif //BOOST_HAS_PTHREADS
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif // #ifndef BOOST_CONTAINER_DETAIL_THREAD_MUTEX_HPP
|
||||
180
include/boost/container/detail/transform_iterator.hpp
Normal file
180
include/boost/container/detail/transform_iterator.hpp
Normal file
@@ -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
|
||||
{
|
||||
inline operator_arrow_proxy(const PseudoReference &px)
|
||||
: m_value(px)
|
||||
{}
|
||||
|
||||
typedef PseudoReference element_type;
|
||||
|
||||
inline PseudoReference* operator->() const { return &m_value; }
|
||||
|
||||
mutable PseudoReference m_value;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct operator_arrow_proxy<T&>
|
||||
{
|
||||
inline operator_arrow_proxy(T &px)
|
||||
: m_value(px)
|
||||
{}
|
||||
|
||||
typedef T element_type;
|
||||
|
||||
inline 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 dtl::remove_reference<typename UnaryFunction::result_type>::type
|
||||
, typename Iterator::difference_type
|
||||
, operator_arrow_proxy<typename UnaryFunction::result_type>
|
||||
, typename UnaryFunction::result_type>
|
||||
{
|
||||
public:
|
||||
inline explicit transform_iterator(const Iterator &it, const UnaryFunction &f = UnaryFunction())
|
||||
: UnaryFunction(f), m_it(it)
|
||||
{}
|
||||
|
||||
inline explicit transform_iterator()
|
||||
: UnaryFunction(), m_it()
|
||||
{}
|
||||
|
||||
//Constructors
|
||||
inline transform_iterator& operator++()
|
||||
{ increment(); return *this; }
|
||||
|
||||
inline transform_iterator operator++(int)
|
||||
{
|
||||
transform_iterator result (*this);
|
||||
increment();
|
||||
return result;
|
||||
}
|
||||
|
||||
inline friend bool operator== (const transform_iterator& i, const transform_iterator& i2)
|
||||
{ return i.equal(i2); }
|
||||
|
||||
inline 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); }
|
||||
*/
|
||||
inline friend typename Iterator::difference_type operator- (const transform_iterator& i, const transform_iterator& i2)
|
||||
{ return i2.distance_to(i); }
|
||||
|
||||
//Arithmetic
|
||||
inline transform_iterator& operator+=(typename Iterator::difference_type off)
|
||||
{ this->advance(off); return *this; }
|
||||
|
||||
inline transform_iterator operator+(typename Iterator::difference_type off) const
|
||||
{
|
||||
transform_iterator other(*this);
|
||||
other.advance(off);
|
||||
return other;
|
||||
}
|
||||
|
||||
inline friend transform_iterator operator+(typename Iterator::difference_type off, const transform_iterator& right)
|
||||
{ return right + off; }
|
||||
|
||||
inline transform_iterator& operator-=(typename Iterator::difference_type off)
|
||||
{ this->advance(-off); return *this; }
|
||||
|
||||
inline transform_iterator operator-(typename Iterator::difference_type off) const
|
||||
{ return *this + (-off); }
|
||||
|
||||
inline typename UnaryFunction::result_type operator*() const
|
||||
{ return dereference(); }
|
||||
|
||||
inline operator_arrow_proxy<typename UnaryFunction::result_type>
|
||||
operator->() const
|
||||
{ return operator_arrow_proxy<typename UnaryFunction::result_type>(dereference()); }
|
||||
|
||||
inline Iterator & base()
|
||||
{ return m_it; }
|
||||
|
||||
inline const Iterator & base() const
|
||||
{ return m_it; }
|
||||
|
||||
private:
|
||||
Iterator m_it;
|
||||
|
||||
inline void increment()
|
||||
{ ++m_it; }
|
||||
|
||||
inline void decrement()
|
||||
{ --m_it; }
|
||||
|
||||
inline bool equal(const transform_iterator &other) const
|
||||
{ return m_it == other.m_it; }
|
||||
|
||||
inline bool less(const transform_iterator &other) const
|
||||
{ return other.m_it < m_it; }
|
||||
|
||||
inline typename UnaryFunction::result_type dereference() const
|
||||
{ return UnaryFunction::operator()(*m_it); }
|
||||
|
||||
inline void advance(typename Iterator::difference_type n)
|
||||
{ boost::container::iterator_advance(m_it, n); }
|
||||
|
||||
inline 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>
|
||||
inline 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
|
||||
1478
include/boost/container/detail/tree.hpp
Normal file
1478
include/boost/container/detail/tree.hpp
Normal file
File diff suppressed because it is too large
Load Diff
75
include/boost/container/detail/type_traits.hpp
Normal file
75
include/boost/container/detail/type_traits.hpp
Normal file
@@ -0,0 +1,75 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// (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 dtl {
|
||||
|
||||
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::remove_cvref;
|
||||
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::nat2;
|
||||
using ::boost::move_detail::nat3;
|
||||
using ::boost::move_detail::natN;
|
||||
using ::boost::move_detail::max_align_t;
|
||||
using ::boost::move_detail::is_convertible;
|
||||
|
||||
} //namespace dtl {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_CONTAINER_DETAIL_TYPE_TRAITS_HPP
|
||||
32
include/boost/container/detail/value_functors.hpp
Normal file
32
include/boost/container/detail/value_functors.hpp
Normal file
@@ -0,0 +1,32 @@
|
||||
#ifndef BOOST_CONTAINER_DETAIL_VALUE_FUNCTORS_HPP
|
||||
#define BOOST_CONTAINER_DETAIL_VALUE_FUNCTORS_HPP
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2017-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_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/intrusive/detail/value_functors.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
|
||||
using ::boost::intrusive::value_less;
|
||||
using ::boost::intrusive::value_equal;
|
||||
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //BOOST_CONTAINER_DETAIL_VALUE_FUNCTORS_HPP
|
||||
51
include/boost/container/detail/value_init.hpp
Normal file
51
include/boost/container/detail/value_init.hpp
Normal file
@@ -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 dtl {
|
||||
|
||||
template<class T>
|
||||
struct value_init
|
||||
{
|
||||
BOOST_CONTAINER_FORCEINLINE value_init()
|
||||
: m_t()
|
||||
{}
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE operator T &() { return m_t; }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE T &get() { return m_t; }
|
||||
|
||||
T m_t;
|
||||
};
|
||||
|
||||
} //namespace dtl {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DETAIL_VALUE_INIT_HPP
|
||||
163
include/boost/container/detail/variadic_templates_tools.hpp
Normal file
163
include/boost/container/detail/variadic_templates_tools.hpp
Normal file
@@ -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 dtl {
|
||||
|
||||
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_impl(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 dtl {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP
|
||||
101
include/boost/container/detail/version_type.hpp
Normal file
101
include/boost/container/detail/version_type.hpp
Normal file
@@ -0,0 +1,101 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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 dtl {
|
||||
|
||||
template <class T, unsigned V>
|
||||
struct version_type
|
||||
: public dtl::integral_constant<unsigned, V>
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
namespace impl{
|
||||
|
||||
template <class T>
|
||||
struct extract_version
|
||||
{
|
||||
typedef typename T::version type;
|
||||
};
|
||||
|
||||
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:
|
||||
BOOST_STATIC_CONSTEXPR bool value = sizeof(test<T>(0)) == 1;
|
||||
void dummy(){}
|
||||
};
|
||||
|
||||
template <class T, bool = has_version<T>::value>
|
||||
struct version
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR unsigned value = 1;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct version<T, true>
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR unsigned value = extract_version<T>::type::value;
|
||||
};
|
||||
|
||||
} //namespace impl
|
||||
|
||||
template <class T>
|
||||
struct version
|
||||
: public dtl::integral_constant<unsigned, impl::version<T>::value>
|
||||
{};
|
||||
|
||||
template<class T, unsigned N>
|
||||
struct is_version
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR bool value =
|
||||
is_same< typename version<T>::type, integral_constant<unsigned, N> >::value;
|
||||
};
|
||||
|
||||
} //namespace dtl {
|
||||
|
||||
typedef dtl::integral_constant<unsigned, 0> version_0;
|
||||
typedef dtl::integral_constant<unsigned, 1> version_1;
|
||||
typedef dtl::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
|
||||
245
include/boost/container/detail/workaround.hpp
Normal file
245
include/boost/container/detail/workaround.hpp
Normal file
@@ -0,0 +1,245 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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_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) && (_MSC_VER <= 1900 || defined(_DEBUG))
|
||||
//"__forceinline" and MSVC seems to have some bugs in old versions and in debug mode
|
||||
#define BOOST_CONTAINER_FORCEINLINE inline
|
||||
#elif defined(BOOST_CLANG) || (defined(BOOST_GCC) && ((__GNUC__ <= 5) || defined(__MINGW32__)))
|
||||
//Older GCCs and MinGw have problems with forceinline
|
||||
//Clang can have code bloat issues with forceinline, see
|
||||
//https://lists.boost.org/boost-users/2023/04/91445.php and
|
||||
//https://github.com/llvm/llvm-project/issues/62202
|
||||
#define BOOST_CONTAINER_FORCEINLINE inline
|
||||
#else
|
||||
#define BOOST_CONTAINER_FORCEINLINE BOOST_FORCEINLINE
|
||||
#endif
|
||||
|
||||
//#define BOOST_CONTAINER_DISABLE_NOINLINE
|
||||
|
||||
#if defined(BOOST_CONTAINER_DISABLE_NOINLINE)
|
||||
#define BOOST_CONTAINER_NOINLINE
|
||||
#else
|
||||
#define BOOST_CONTAINER_NOINLINE BOOST_NOINLINE
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined(__has_feature)
|
||||
#define BOOST_CONTAINER_HAS_FEATURE(feature) 0
|
||||
#else
|
||||
#define BOOST_CONTAINER_HAS_FEATURE(feature) __has_feature(feature)
|
||||
#endif
|
||||
|
||||
//Detect address sanitizer
|
||||
#if defined(__SANITIZE_ADDRESS__) || BOOST_CONTAINER_HAS_FEATURE(address_sanitizer)
|
||||
#define BOOST_CONTAINER_ASAN
|
||||
#endif
|
||||
|
||||
|
||||
#if (BOOST_CXX_VERSION < 201703L) || !defined(__cpp_deduction_guides)
|
||||
#define BOOST_CONTAINER_NO_CXX17_CTAD
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_CONTAINER_DISABLE_ATTRIBUTE_NODISCARD)
|
||||
#define BOOST_CONTAINER_ATTRIBUTE_NODISCARD
|
||||
#else
|
||||
#if defined(BOOST_GCC) && ((BOOST_GCC < 100000) || (__cplusplus < 201703L))
|
||||
//Avoid using it in C++ < 17 and GCC < 10 because it warns in SFINAE contexts
|
||||
//(see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89070)
|
||||
#define BOOST_CONTAINER_ATTRIBUTE_NODISCARD
|
||||
#else
|
||||
#define BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_ATTRIBUTE_NODISCARD
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
//Configuration options:
|
||||
|
||||
//Define this to use std exception types instead of boost::container's own exception types
|
||||
//#define BOOST_CONTAINER_USE_STD_EXCEPTIONS
|
||||
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
|
||||
template <typename T1>
|
||||
BOOST_FORCEINLINE BOOST_CXX14_CONSTEXPR void ignore(T1 const&)
|
||||
{}
|
||||
|
||||
}} //namespace boost::container {
|
||||
|
||||
#if !(defined BOOST_NO_EXCEPTIONS)
|
||||
# define BOOST_CONTAINER_TRY { try
|
||||
# define BOOST_CONTAINER_CATCH(x) catch(x)
|
||||
# define BOOST_CONTAINER_RETHROW throw;
|
||||
# define BOOST_CONTAINER_CATCH_END }
|
||||
#else
|
||||
# if !defined(BOOST_MSVC) || BOOST_MSVC >= 1900
|
||||
# define BOOST_CONTAINER_TRY { if (true)
|
||||
# define BOOST_CONTAINER_CATCH(x) else if (false)
|
||||
# else
|
||||
// warning C4127: conditional expression is constant
|
||||
# define BOOST_CONTAINER_TRY { \
|
||||
__pragma(warning(push)) \
|
||||
__pragma(warning(disable: 4127)) \
|
||||
if (true) \
|
||||
__pragma(warning(pop))
|
||||
# define BOOST_CONTAINER_CATCH(x) else \
|
||||
__pragma(warning(push)) \
|
||||
__pragma(warning(disable: 4127)) \
|
||||
if (false) \
|
||||
__pragma(warning(pop))
|
||||
# endif
|
||||
# define BOOST_CONTAINER_RETHROW
|
||||
# define BOOST_CONTAINER_CATCH_END }
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_NO_CXX11_STATIC_ASSERT
|
||||
# ifndef BOOST_NO_CXX11_VARIADIC_MACROS
|
||||
# define BOOST_CONTAINER_STATIC_ASSERT( ... ) static_assert(__VA_ARGS__, #__VA_ARGS__)
|
||||
# else
|
||||
# define BOOST_CONTAINER_STATIC_ASSERT( B ) static_assert(B, #B)
|
||||
# endif
|
||||
#else
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace dtl {
|
||||
|
||||
template<bool B>
|
||||
struct STATIC_ASSERTION_FAILURE;
|
||||
|
||||
template<>
|
||||
struct STATIC_ASSERTION_FAILURE<true> {};
|
||||
|
||||
template<unsigned> struct static_assert_test {};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define BOOST_CONTAINER_STATIC_ASSERT(B) \
|
||||
typedef ::boost::container::dtl::static_assert_test<\
|
||||
(unsigned)sizeof(::boost::container::dtl::STATIC_ASSERTION_FAILURE<bool(B)>)>\
|
||||
BOOST_JOIN(boost_container_static_assert_typedef_, __LINE__) BOOST_ATTRIBUTE_UNUSED
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_NO_CXX11_STATIC_ASSERT
|
||||
# ifndef BOOST_NO_CXX11_VARIADIC_MACROS
|
||||
# define BOOST_CONTAINER_STATIC_ASSERT_MSG( ... ) static_assert(__VA_ARGS__)
|
||||
# else
|
||||
# define BOOST_CONTAINER_STATIC_ASSERT_MSG( B, Msg ) static_assert( B, Msg )
|
||||
# endif
|
||||
#else
|
||||
# define BOOST_CONTAINER_STATIC_ASSERT_MSG( B, Msg ) BOOST_CONTAINER_STATIC_ASSERT( B )
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX17_INLINE_VARIABLES)
|
||||
# define BOOST_CONTAINER_CONSTANT_VAR BOOST_INLINE_CONSTEXPR
|
||||
#else
|
||||
# define BOOST_CONTAINER_CONSTANT_VAR static BOOST_CONSTEXPR_OR_CONST
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && ((__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) >= 40600)
|
||||
#define BOOST_CONTAINER_GCC_COMPATIBLE_HAS_DIAGNOSTIC_IGNORED
|
||||
#elif defined(__clang__)
|
||||
#define BOOST_CONTAINER_GCC_COMPATIBLE_HAS_DIAGNOSTIC_IGNORED
|
||||
#endif
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DETAIL_WORKAROUND_HPP
|
||||
3089
include/boost/container/devector.hpp
Normal file
3089
include/boost/container/devector.hpp
Normal file
File diff suppressed because it is too large
Load Diff
3184
include/boost/container/flat_map.hpp
Normal file
3184
include/boost/container/flat_map.hpp
Normal file
File diff suppressed because it is too large
Load Diff
1965
include/boost/container/flat_set.hpp
Normal file
1965
include/boost/container/flat_set.hpp
Normal file
File diff suppressed because it is too large
Load Diff
1545
include/boost/container/list.hpp
Normal file
1545
include/boost/container/list.hpp
Normal file
File diff suppressed because it is too large
Load Diff
2397
include/boost/container/map.hpp
Normal file
2397
include/boost/container/map.hpp
Normal file
File diff suppressed because it is too large
Load Diff
192
include/boost/container/new_allocator.hpp
Normal file
192
include/boost/container/new_allocator.hpp
Normal file
@@ -0,0 +1,192 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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 <boost/container/detail/operator_new_helpers.hpp>
|
||||
#include <cstddef>
|
||||
|
||||
//!\file
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
|
||||
/// @cond
|
||||
|
||||
template<bool Value>
|
||||
struct new_allocator_bool
|
||||
{ BOOST_STATIC_CONSTEXPR 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
|
||||
{}
|
||||
|
||||
//!Copy assignment operator from other new_allocator.
|
||||
//!Never throws
|
||||
new_allocator& operator=(const new_allocator &) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
//!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
|
||||
inline new_allocator() BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{}
|
||||
|
||||
//!Constructor from other new_allocator.
|
||||
//!Never throws
|
||||
inline new_allocator(const new_allocator &) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{}
|
||||
|
||||
//!Copy assignment operator from other new_allocator.
|
||||
//!Never throws
|
||||
inline new_allocator& operator=(const new_allocator &) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return *this; }
|
||||
|
||||
//!Constructor from related new_allocator.
|
||||
//!Never throws
|
||||
template<class T2>
|
||||
inline new_allocator(const new_allocator<T2> &) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{}
|
||||
|
||||
//!Allocates memory for an array of count elements.
|
||||
//!Throws bad_alloc if there is no enough memory
|
||||
pointer allocate(size_type count)
|
||||
{
|
||||
return dtl::operator_new_allocate<T>(count);
|
||||
}
|
||||
|
||||
//!Deallocates previously allocated memory.
|
||||
//!Never throws
|
||||
void deallocate(pointer ptr, size_type n) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{
|
||||
return dtl::operator_delete_deallocate<T>(ptr, n);
|
||||
}
|
||||
|
||||
//!Returns the maximum number of elements that could be allocated.
|
||||
//!Never throws
|
||||
inline size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return std::size_t(-1)/(2*sizeof(T)); }
|
||||
|
||||
//!Swaps two allocators, does nothing
|
||||
//!because this new_allocator is stateless
|
||||
inline 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
|
||||
inline 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
|
||||
inline 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
|
||||
347
include/boost/container/node_allocator.hpp
Normal file
347
include/boost/container/node_allocator.hpp
Normal file
@@ -0,0 +1,347 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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_NODE_ALLOCATOR_HPP
|
||||
#define BOOST_CONTAINER_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/move/detail/iterator_to_raw_pointer.hpp>
|
||||
#include <boost/container/detail/dlmalloc.hpp>
|
||||
#include <boost/container/detail/singleton.hpp>
|
||||
|
||||
#include <boost/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;
|
||||
|
||||
BOOST_STATIC_CONSTEXPR std::size_t nodes_per_block = NodesPerBlock;
|
||||
|
||||
BOOST_CONTAINER_STATIC_ASSERT((Version <=2));
|
||||
#endif
|
||||
|
||||
public:
|
||||
//-------
|
||||
typedef T value_type;
|
||||
typedef T * pointer;
|
||||
typedef const T * const_pointer;
|
||||
typedef typename ::boost::container::
|
||||
dtl::unvoid_ref<T>::type reference;
|
||||
typedef typename ::boost::container::
|
||||
dtl::unvoid_ref<const T>::type const_reference;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
|
||||
typedef boost::container::dtl::
|
||||
version_type<self_t, (unsigned int) Version> version;
|
||||
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
typedef boost::container::dtl::
|
||||
basic_multiallocation_chain<void*> multiallocation_chain_void;
|
||||
typedef boost::container::dtl::
|
||||
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 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 dtl::shared_node_pool
|
||||
<sizeof(T), NodesPerBlock> shared_pool_t;
|
||||
typedef dtl::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 dtl::shared_node_pool
|
||||
<sizeof(T), NodesPerBlock> shared_pool_t;
|
||||
typedef dtl::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 dtl::shared_node_pool
|
||||
<sizeof(T), NodesPerBlock> shared_pool_t;
|
||||
typedef dtl::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_CONTAINER_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_CONTAINER_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_CONTAINER_STATIC_ASSERT(( Version > 1 ));
|
||||
typedef dtl::shared_node_pool
|
||||
<sizeof(T), NodesPerBlock> shared_pool_t;
|
||||
typedef dtl::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_CONTAINER_STATIC_ASSERT(( Version > 1 ));
|
||||
typedef dtl::shared_node_pool
|
||||
<sizeof(T), NodesPerBlock> shared_pool_t;
|
||||
typedef dtl::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*)boost::movelib::iterator_to_raw_pointer(ch.begin())
|
||||
, (T*)boost::movelib::iterator_to_raw_pointer(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_CONTAINER_STATIC_ASSERT(( Version > 1 ));
|
||||
typedef dtl::shared_node_pool
|
||||
<sizeof(T), NodesPerBlock> shared_pool_t;
|
||||
typedef dtl::singleton_default<shared_pool_t> singleton_t;
|
||||
singleton_t::instance().deallocate_node(p);
|
||||
}
|
||||
|
||||
void deallocate_individual(multiallocation_chain &chain) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{
|
||||
BOOST_CONTAINER_STATIC_ASSERT(( Version > 1 ));
|
||||
typedef dtl::shared_node_pool
|
||||
<sizeof(T), NodesPerBlock> shared_pool_t;
|
||||
typedef dtl::singleton_default<shared_pool_t> singleton_t;
|
||||
typename shared_pool_t::multiallocation_chain ch
|
||||
( boost::movelib::iterator_to_raw_pointer(chain.begin())
|
||||
, boost::movelib::iterator_to_raw_pointer(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_CONTAINER_STATIC_ASSERT(( Version > 1 ));
|
||||
dlmalloc_memchain ch;
|
||||
BOOST_CONTAINER_MEMCHAIN_INIT(&ch);
|
||||
if(BOOST_UNLIKELY(!dlmalloc_multialloc_nodes(n_elements, elem_size*sizeof(T), BOOST_CONTAINER_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_CONTAINER_STATIC_ASSERT(( Version > 1 ));
|
||||
dlmalloc_memchain ch;
|
||||
dlmalloc_multialloc_arrays(n_elements, elem_sizes, sizeof(T), BOOST_CONTAINER_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_CONTAINER_STATIC_ASSERT(( Version > 1 ));
|
||||
void *first = boost::movelib::iterator_to_raw_pointer(chain.begin());
|
||||
void *last = boost::movelib::iterator_to_raw_pointer(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_NODE_ALLOCATOR_HPP
|
||||
456
include/boost/container/node_handle.hpp
Normal file
456
include/boost/container/node_handle.hpp
Normal file
@@ -0,0 +1,456 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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/container/detail/placement_new.hpp>
|
||||
#include <boost/move/detail/to_raw_pointer.hpp>
|
||||
#include <boost/move/detail/launder.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/container/detail/mpl.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
//GCC 12 is confused about maybe uninitialized allocators
|
||||
#if defined(BOOST_GCC) && (BOOST_GCC >= 120000) && (BOOST_GCC < 130000)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
|
||||
#endif
|
||||
|
||||
|
||||
//!\file
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
|
||||
///@cond
|
||||
|
||||
template<class Value, class KeyMapped>
|
||||
struct node_handle_keymapped_traits
|
||||
{
|
||||
typedef typename KeyMapped::key_type key_type;
|
||||
typedef typename KeyMapped::mapped_type mapped_type;
|
||||
};
|
||||
|
||||
template<class Value>
|
||||
struct node_handle_keymapped_traits<Value, void>
|
||||
{
|
||||
typedef Value key_type;
|
||||
typedef Value mapped_type;
|
||||
};
|
||||
|
||||
class node_handle_friend
|
||||
{
|
||||
public:
|
||||
|
||||
template<class NH>
|
||||
inline static void destroy_alloc(NH &nh) BOOST_NOEXCEPT
|
||||
{ nh.destroy_alloc(); }
|
||||
|
||||
template<class NH>
|
||||
inline static typename NH::node_pointer &get_node_pointer(NH &nh) BOOST_NOEXCEPT
|
||||
{ return nh.get_node_pointer(); }
|
||||
};
|
||||
|
||||
|
||||
///@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 NodeAllocator, class KeyMapped = void>
|
||||
class node_handle
|
||||
{
|
||||
typedef NodeAllocator nallocator_type;
|
||||
typedef allocator_traits<NodeAllocator> nator_traits;
|
||||
typedef typename nator_traits::value_type priv_node_t;
|
||||
typedef typename priv_node_t::value_type priv_value_t;
|
||||
typedef node_handle_keymapped_traits<priv_value_t, KeyMapped> keymapped_t;
|
||||
|
||||
public:
|
||||
typedef priv_value_t value_type;
|
||||
typedef typename keymapped_t::key_type key_type;
|
||||
typedef typename keymapped_t::mapped_type mapped_type;
|
||||
typedef typename nator_traits::template portable_rebind_alloc
|
||||
<value_type>::type allocator_type;
|
||||
|
||||
typedef priv_node_t container_node_type;
|
||||
friend class node_handle_friend;
|
||||
|
||||
///@cond
|
||||
private:
|
||||
BOOST_MOVABLE_BUT_NOT_COPYABLE(node_handle)
|
||||
|
||||
typedef typename nator_traits::pointer node_pointer;
|
||||
typedef typename dtl::aligned_storage
|
||||
< sizeof(nallocator_type)
|
||||
, dtl::alignment_of<nallocator_type>::value
|
||||
>::type nalloc_storage_t;
|
||||
|
||||
node_pointer m_ptr;
|
||||
nalloc_storage_t m_nalloc_storage;
|
||||
|
||||
void move_construct_alloc(nallocator_type &al)
|
||||
{ ::new((void*)m_nalloc_storage.data, boost_container_new_t()) nallocator_type(::boost::move(al)); }
|
||||
|
||||
void destroy_deallocate_node()
|
||||
{
|
||||
boost::movelib::to_raw_pointer(m_ptr)->destructor(this->node_alloc());
|
||||
nator_traits::deallocate(this->node_alloc(), m_ptr, 1u);
|
||||
}
|
||||
|
||||
template<class OtherNodeHandle>
|
||||
void move_construct_end(OtherNodeHandle &nh)
|
||||
{
|
||||
if(m_ptr){
|
||||
::new ((void*)m_nalloc_storage.data, boost_container_new_t()) nallocator_type(::boost::move(nh.node_alloc()));
|
||||
node_handle_friend::destroy_alloc(nh);
|
||||
node_handle_friend::get_node_pointer(nh) = node_pointer();
|
||||
}
|
||||
BOOST_ASSERT(nh.empty());
|
||||
}
|
||||
|
||||
void destroy_alloc() BOOST_NOEXCEPT
|
||||
{ move_detail::launder_cast<nallocator_type*>(&m_nalloc_storage)->~nallocator_type(); }
|
||||
|
||||
node_pointer &get_node_pointer() BOOST_NOEXCEPT
|
||||
{ return m_ptr; }
|
||||
|
||||
///@endcond
|
||||
|
||||
public:
|
||||
//! <b>Effects</b>: Initializes m_ptr to nullptr.
|
||||
//!
|
||||
//! <b>Postcondition</b>: this->empty()
|
||||
BOOST_CXX14_CONSTEXPR node_handle() BOOST_NOEXCEPT
|
||||
: m_ptr()
|
||||
{ }
|
||||
|
||||
//! <b>Effects</b>: Constructs a node_handle object initializing internal pointer with p.
|
||||
//! If p != nullptr copy constructs internal allocator from al.
|
||||
node_handle(node_pointer p, const nallocator_type &al) BOOST_NOEXCEPT
|
||||
: m_ptr(p)
|
||||
{
|
||||
if(m_ptr){
|
||||
::new ((void*)m_nalloc_storage.data, 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<NodeAllocator, KeyMapped2> BOOST_RV_REF_END nh
|
||||
, typename dtl::enable_if_c
|
||||
< ((unsigned)dtl::is_same<KeyMapped, void>::value +
|
||||
(unsigned)dtl::is_same<KeyMapped2, void>::value) == 1u
|
||||
>::type* = 0) BOOST_NOEXCEPT
|
||||
: m_ptr(nh.get())
|
||||
{ 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)
|
||||
{ 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
|
||||
//! nator_traits::rebind_traits<container_node_type>::deallocate.
|
||||
~node_handle() BOOST_NOEXCEPT
|
||||
{
|
||||
if(!this->empty()){
|
||||
this->destroy_deallocate_node();
|
||||
this->destroy_alloc();
|
||||
}
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: Either this->empty(), or nator_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 nator_traits::destroy, then deallocates m_ptr by calling
|
||||
//! nator_traits::deallocate. Assigns nh.m_ptr to m_ptr. If this->empty()
|
||||
//! or nator_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_NOEXCEPT
|
||||
{
|
||||
BOOST_ASSERT(this->empty() || nator_traits::propagate_on_container_move_assignment::value
|
||||
|| nator_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_deallocate_node();
|
||||
BOOST_IF_CONSTEXPR(nator_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_deallocate_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_CONTAINER_STATIC_ASSERT((dtl::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_CONTAINER_STATIC_ASSERT((!dtl::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_CONTAINER_STATIC_ASSERT((!dtl::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
|
||||
inline explicit operator bool
|
||||
#else
|
||||
private: struct bool_conversion {int for_bool; int for_arg(); }; typedef int bool_conversion::* explicit_bool_arg;
|
||||
public: inline 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 nator_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 nator_traits::propagate_on_-
|
||||
//! container_swap is true calls swap(node_alloc(), nh.node_alloc()).
|
||||
void swap(node_handle &nh)
|
||||
BOOST_NOEXCEPT_IF(nator_traits::propagate_on_container_swap::value || nator_traits::is_always_equal::value)
|
||||
{
|
||||
BOOST_ASSERT(this->empty() || nh.empty() || nator_traits::propagate_on_container_swap::value
|
||||
|| nator_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){
|
||||
BOOST_IF_CONSTEXPR(nator_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());
|
||||
this->destroy_alloc();
|
||||
}
|
||||
|
||||
::boost::adl_move_swap(m_ptr, nh.m_ptr);
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: If this->empty() returns nullptr, otherwise returns m_ptr
|
||||
//! resets m_ptr to nullptr and destroys the internal allocator.
|
||||
//!
|
||||
//! <b>Postcondition</b>: this->empty()
|
||||
//!
|
||||
//! <b>Note</b>: Non-standard extensions
|
||||
node_pointer release() BOOST_NOEXCEPT
|
||||
{
|
||||
node_pointer p(m_ptr);
|
||||
m_ptr = node_pointer();
|
||||
if(p)
|
||||
this->destroy_alloc();
|
||||
return p;
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Returns m_ptr.
|
||||
//!
|
||||
//! <b>Note</b>: Non-standard extensions
|
||||
node_pointer get() const BOOST_NOEXCEPT
|
||||
{
|
||||
return m_ptr;
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Returns a reference to the internal node allocator.
|
||||
//!
|
||||
//! <b>Note</b>: Non-standard extensions
|
||||
nallocator_type &node_alloc() BOOST_NOEXCEPT
|
||||
{
|
||||
BOOST_ASSERT(!empty());
|
||||
return *move_detail::launder_cast<nallocator_type*>(&m_nalloc_storage);
|
||||
}
|
||||
|
||||
|
||||
//! <b>Effects</b>: Returns a reference to the internal node allocator.
|
||||
//!
|
||||
//! <b>Note</b>: Non-standard extensions
|
||||
const nallocator_type &node_alloc() const BOOST_NOEXCEPT
|
||||
{
|
||||
BOOST_ASSERT(!empty());
|
||||
return *move_detail::launder_cast<const nallocator_type*>(&m_nalloc_storage);
|
||||
}
|
||||
|
||||
//! <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) n)
|
||||
: inserted(insert), position(it), node(boost::move(n))
|
||||
{}
|
||||
|
||||
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 {
|
||||
|
||||
#if defined(BOOST_GCC) && (BOOST_GCC >= 120000) && (BOOST_GCC < 130000)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_CONTAINER_NODE_HANDLE_HPP
|
||||
706
include/boost/container/options.hpp
Normal file
706
include/boost/container/options.hpp
Normal file
@@ -0,0 +1,706 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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/container/detail/workaround.hpp>
|
||||
#include <boost/intrusive/pack_options.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//
|
||||
// OPTIONS FOR ASSOCIATIVE TREE-BASED CONTAINERS
|
||||
//
|
||||
//
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
//! 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
|
||||
};
|
||||
|
||||
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
|
||||
template<tree_type_enum TreeType, bool OptimizeSize>
|
||||
struct tree_opt
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR boost::container::tree_type_enum tree_type = TreeType;
|
||||
BOOST_STATIC_CONSTEXPR bool optimize_size = OptimizeSize;
|
||||
};
|
||||
|
||||
typedef tree_opt<red_black_tree, true> tree_assoc_defaults;
|
||||
|
||||
#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;
|
||||
};
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
|
||||
|
||||
//! Helper alias metafunction to combine options into a single type to be used
|
||||
//! by tree-based associative containers
|
||||
template<class ...Options>
|
||||
using tree_assoc_options_t = typename boost::container::tree_assoc_options<Options...>::type;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//
|
||||
// OPTIONS FOR ASSOCIATIVE HASH-BASED CONTAINERS
|
||||
//
|
||||
//
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
|
||||
template<bool StoreHash, bool CacheBegin, bool LinearBuckets, bool FastmodBuckets>
|
||||
struct hash_opt
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR bool store_hash = StoreHash;
|
||||
BOOST_STATIC_CONSTEXPR bool cache_begin = CacheBegin;
|
||||
BOOST_STATIC_CONSTEXPR bool linear_buckets = LinearBuckets;
|
||||
BOOST_STATIC_CONSTEXPR bool fastmod_buckets = FastmodBuckets;
|
||||
};
|
||||
|
||||
typedef hash_opt<false, false, false, false> hash_assoc_defaults;
|
||||
|
||||
//!This option setter specifies if nodes also store the hash value
|
||||
//!so that search and rehashing for hash-expensive types is improved.
|
||||
//!This option might degrade performance for easy to hash types (like integers)
|
||||
BOOST_INTRUSIVE_OPTION_CONSTANT(store_hash, bool, Enabled, store_hash)
|
||||
|
||||
//!This option setter specifies if the container will cache the first
|
||||
//!non-empty bucket so that begin() is O(1) instead of searching for the
|
||||
//!first non-empty bucket (which can be O(bucket_size()))
|
||||
BOOST_INTRUSIVE_OPTION_CONSTANT(cache_begin, bool, Enabled, cache_begin)
|
||||
|
||||
BOOST_INTRUSIVE_OPTION_CONSTANT(linear_buckets, bool, Enabled, linear_buckets)
|
||||
|
||||
BOOST_INTRUSIVE_OPTION_CONSTANT(fastmod_buckets, bool, Enabled, fastmod_buckets)
|
||||
|
||||
//! Helper metafunction to combine options into a single type to be used
|
||||
//! by \c boost::container::hash_set, \c boost::container::hash_multiset
|
||||
//! \c boost::container::hash_map and \c boost::container::hash_multimap.
|
||||
//! Supported options are: \c boost::container::store_hash
|
||||
#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 hash_assoc_options
|
||||
{
|
||||
/// @cond
|
||||
typedef typename ::boost::intrusive::pack_options
|
||||
< hash_assoc_defaults,
|
||||
#if !defined(BOOST_CONTAINER_VARIADIC_TEMPLATES)
|
||||
O1, O2, O3, O4
|
||||
#else
|
||||
Options...
|
||||
#endif
|
||||
>::type packed_options;
|
||||
typedef hash_opt<packed_options::store_hash
|
||||
,packed_options::cache_begin
|
||||
,packed_options::linear_buckets
|
||||
,packed_options::fastmod_buckets
|
||||
> implementation_defined;
|
||||
/// @endcond
|
||||
typedef implementation_defined type;
|
||||
};
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
|
||||
|
||||
//! Helper alias metafunction to combine options into a single type to be used
|
||||
//! by hash-based associative containers
|
||||
template<class ...Options>
|
||||
using hash_assoc_options_t = typename boost::container::hash_assoc_options<Options...>::type;
|
||||
|
||||
#endif
|
||||
|
||||
#endif //!defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//
|
||||
// OPTIONS FOR VECTOR-BASED CONTAINERS
|
||||
//
|
||||
//
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
|
||||
template<class T, class Default>
|
||||
struct default_if_void
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<class Default>
|
||||
struct default_if_void<void, Default>
|
||||
{
|
||||
typedef Default type;
|
||||
};
|
||||
|
||||
template<std::size_t N, std::size_t DefaultN>
|
||||
struct default_if_zero
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR std::size_t value = N;
|
||||
};
|
||||
|
||||
template<std::size_t DefaultN>
|
||||
struct default_if_zero<0u, DefaultN>
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR std::size_t value = DefaultN;
|
||||
};
|
||||
|
||||
#endif //!defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
|
||||
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
|
||||
template<class AllocTraits, class StoredSizeType>
|
||||
struct get_stored_size_type_with_alloctraits
|
||||
{
|
||||
typedef StoredSizeType type;
|
||||
};
|
||||
|
||||
template<class AllocTraits>
|
||||
struct get_stored_size_type_with_alloctraits<AllocTraits, void>
|
||||
{
|
||||
typedef typename AllocTraits::size_type type;
|
||||
};
|
||||
|
||||
template<class GrowthType, class StoredSizeType>
|
||||
struct vector_opt
|
||||
{
|
||||
typedef GrowthType growth_factor_type;
|
||||
typedef StoredSizeType stored_size_type;
|
||||
|
||||
template<class AllocTraits>
|
||||
struct get_stored_size_type
|
||||
: get_stored_size_type_with_alloctraits<AllocTraits, StoredSizeType>
|
||||
{};
|
||||
};
|
||||
|
||||
class default_next_capacity;
|
||||
|
||||
typedef vector_opt<void, void> vector_null_opt;
|
||||
|
||||
#else
|
||||
|
||||
//!This growth factor argument specifies that the container should increase its
|
||||
//!capacity a 50% when existing capacity is exhausted.
|
||||
struct growth_factor_50{};
|
||||
|
||||
//!This growth factor argument specifies that the container should increase its
|
||||
//!capacity a 60% when existing capacity is exhausted.
|
||||
struct growth_factor_60{};
|
||||
|
||||
//!This growth factor argument specifies that the container should increase its
|
||||
//!capacity a 100% (doubling its capacity) when existing capacity is exhausted.
|
||||
struct growth_factor_100{};
|
||||
|
||||
#endif //!defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
|
||||
//!This option setter specifies the growth factor strategy of the
|
||||
//!underlying vector.
|
||||
//!
|
||||
//!\tparam GrowthFactor The function object that implements the growth factor
|
||||
//!
|
||||
//! The GrowthFactor function object must offer the following interface:
|
||||
//!
|
||||
//!\code
|
||||
//!template<class SizeType>
|
||||
//!SizeType operator()(SizeType cur_cap, SizeType add_min_cap, SizeType max_cap) const;
|
||||
//!\endcode
|
||||
//!
|
||||
//!Where:
|
||||
//! * `cur_cap` is the current capacity
|
||||
//! * `add_min_cap` is the minimum additional capacity we want to achieve
|
||||
//! * `max_cap` is the maximum capacity that the allocator or other factors allow.
|
||||
//!
|
||||
//!The implementation should return a value between `cur_cap + add_min_cap`
|
||||
//!and `max_cap`. The implementation should handle the potential wraparound produced
|
||||
//!by the growth factor and always succeed with a correct value.
|
||||
//!
|
||||
//!Predefined growth factors that can be passed as arguments to this option are:
|
||||
//!\c boost::container::growth_factor_50,
|
||||
//!\c boost::container::growth_factor_60 and
|
||||
//!\c boost::container::growth_factor_100
|
||||
//!
|
||||
//!If this option is not specified, a default will be used by the container.
|
||||
BOOST_INTRUSIVE_OPTION_TYPE(growth_factor, GrowthFactor, GrowthFactor, growth_factor_type)
|
||||
|
||||
//!This option specifies the unsigned integer type that a user wants the container
|
||||
//!to use to hold size-related information inside a container (e.g. current size, current capacity).
|
||||
//!
|
||||
//!\tparam StoredSizeType An unsigned integer type. It shall be smaller than than the size
|
||||
//! of the size_type deduced from `allocator_traits<A>::size_type` or the same type.
|
||||
//!
|
||||
//!If the maximum capacity() to be used is limited, a user can try to use 8-bit, 16-bit
|
||||
//!(e.g. in 32-bit machines), or 32-bit size types (e.g. in a 64 bit machine) to see if some
|
||||
//!memory can be saved, specially for empty containers. This could potentially improve performance
|
||||
//!due to better cache usage.
|
||||
//!
|
||||
//!Note that alignment requirements can disallow theoretical space savings. Example:
|
||||
//!\c vector holds a pointer and two size types (for size and capacity), in a 32 bit machine
|
||||
//!a 8 bit size type (total size: 4 byte pointer + 2 x 1 byte sizes = 6 bytes)
|
||||
//!will not save space when comparing two 16-bit size types because usually
|
||||
//!a 32 bit alignment is required for vector and the size will be rounded to 8 bytes. In a 64-bit
|
||||
//!machine a 16 bit size type does not usually save memory when comparing to a 32-bit size type.
|
||||
//!Measure the size of the resulting container and do not assume a smaller \c stored_size
|
||||
//!will always lead to a smaller sizeof(container).
|
||||
//!
|
||||
//!If a user tries to insert more elements than representable by \c stored_size, the container
|
||||
//!will throw a length_error.
|
||||
//!
|
||||
//!If this option is not specified, `allocator_traits<A>::size_type` (usually std::size_t) will
|
||||
//!be used to store size-related information inside the container.
|
||||
BOOST_INTRUSIVE_OPTION_TYPE(stored_size, StoredSizeType, StoredSizeType, stored_size_type)
|
||||
|
||||
//! Helper metafunction to combine options into a single type to be used
|
||||
//! by \c boost::container::vector.
|
||||
//! Supported options are: \c boost::container::growth_factor and \c boost::container::stored_size
|
||||
#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 vector_options
|
||||
{
|
||||
/// @cond
|
||||
typedef typename ::boost::intrusive::pack_options
|
||||
< vector_null_opt,
|
||||
#if !defined(BOOST_CONTAINER_VARIADIC_TEMPLATES)
|
||||
O1, O2, O3, O4
|
||||
#else
|
||||
Options...
|
||||
#endif
|
||||
>::type packed_options;
|
||||
typedef vector_opt< typename packed_options::growth_factor_type
|
||||
, typename packed_options::stored_size_type> implementation_defined;
|
||||
/// @endcond
|
||||
typedef implementation_defined type;
|
||||
};
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
|
||||
|
||||
//! Helper alias metafunction to combine options into a single type to be used
|
||||
//! by \c boost::container::vector.
|
||||
template<class ...Options>
|
||||
using vector_options_t = typename boost::container::vector_options<Options...>::type;
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//
|
||||
// OPTIONS FOR SMALL-VECTOR CONTAINER
|
||||
//
|
||||
//
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
//! This option specifies the desired alignment for the value_type stored
|
||||
//! in the container.
|
||||
//! A value zero represents the natural alignment.
|
||||
//!
|
||||
//!\tparam Alignment An unsigned integer value. Must be power of two.
|
||||
BOOST_INTRUSIVE_OPTION_CONSTANT(inplace_alignment, std::size_t, Alignment, inplace_alignment)
|
||||
|
||||
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
|
||||
template<class GrowthType, std::size_t InplaceAlignment, class StoredSizeType>
|
||||
struct small_vector_opt
|
||||
{
|
||||
typedef GrowthType growth_factor_type;
|
||||
BOOST_STATIC_CONSTEXPR std::size_t inplace_alignment = InplaceAlignment;
|
||||
typedef StoredSizeType stored_size_type;
|
||||
};
|
||||
|
||||
typedef small_vector_opt<void, 0u, void> small_vector_null_opt;
|
||||
|
||||
#endif //!defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
|
||||
//! Helper metafunction to combine options into a single type to be used
|
||||
//! by \c boost::container::small_vector.
|
||||
//! Supported options are: \c boost::container::growth_factor,
|
||||
//! \c boost::container::inplace_alignment and
|
||||
//! \c boost::container::stored_size.
|
||||
#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 small_vector_options
|
||||
{
|
||||
/// @cond
|
||||
typedef typename ::boost::intrusive::pack_options
|
||||
< small_vector_null_opt,
|
||||
#if !defined(BOOST_CONTAINER_VARIADIC_TEMPLATES)
|
||||
O1, O2, O3, O4
|
||||
#else
|
||||
Options...
|
||||
#endif
|
||||
>::type packed_options;
|
||||
typedef small_vector_opt< typename packed_options::growth_factor_type
|
||||
, packed_options::inplace_alignment
|
||||
, typename packed_options::stored_size_type
|
||||
> implementation_defined;
|
||||
/// @endcond
|
||||
typedef implementation_defined type;
|
||||
};
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
|
||||
|
||||
//! Helper alias metafunction to combine options into a single type to be used
|
||||
//! by \c boost::container::small_vector.
|
||||
template<class ...Options>
|
||||
using small_vector_options_t = typename boost::container::small_vector_options<Options...>::type;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//
|
||||
// OPTIONS FOR STATIC-VECTOR CONTAINER
|
||||
//
|
||||
//
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
//!This option specifies if the container will throw if in
|
||||
//!the static capacity is not sufficient to hold the required
|
||||
//!values. If false is specified, insufficient capacity will
|
||||
//!lead to BOOST_ASSERT, and if this assertion returns, to undefined behaviour,
|
||||
//!which potentially can lead to better static_vector performance.
|
||||
//!The default value is true.
|
||||
//!
|
||||
//!\tparam ThrowOnExhaustion A boolean value. True if throw is required.
|
||||
BOOST_INTRUSIVE_OPTION_CONSTANT(throw_on_overflow, bool, ThrowOnOverflow, throw_on_overflow)
|
||||
|
||||
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
|
||||
template<bool ThrowOnOverflow, std::size_t InplaceAlignment, class StoredSizeType>
|
||||
struct static_vector_opt
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR bool throw_on_overflow = ThrowOnOverflow;
|
||||
BOOST_STATIC_CONSTEXPR std::size_t inplace_alignment = InplaceAlignment;
|
||||
typedef StoredSizeType stored_size_type;
|
||||
};
|
||||
|
||||
typedef static_vector_opt<true, 0u, void> static_vector_null_opt;
|
||||
|
||||
#endif //!defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
|
||||
//! Helper metafunction to combine options into a single type to be used
|
||||
//! by \c boost::container::static_vector.
|
||||
//! Supported options are: \c boost::container::throw_on_overflow, \c boost::container::inplace_alignment
|
||||
//! and \c boost::container::stored_size.
|
||||
#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 static_vector_options
|
||||
{
|
||||
/// @cond
|
||||
typedef typename ::boost::intrusive::pack_options
|
||||
< static_vector_null_opt,
|
||||
#if !defined(BOOST_CONTAINER_VARIADIC_TEMPLATES)
|
||||
O1, O2, O3, O4
|
||||
#else
|
||||
Options...
|
||||
#endif
|
||||
>::type packed_options;
|
||||
typedef static_vector_opt< packed_options::throw_on_overflow
|
||||
, packed_options::inplace_alignment
|
||||
, typename packed_options::stored_size_type
|
||||
> implementation_defined;
|
||||
/// @endcond
|
||||
typedef implementation_defined type;
|
||||
};
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
|
||||
|
||||
//! Helper alias metafunction to combine options into a single type to be used
|
||||
//! by \c boost::container::static_vector.
|
||||
template<class ...Options>
|
||||
using static_vector_options_t = typename boost::container::static_vector_options<Options...>::type;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//
|
||||
// OPTIONS FOR DEVECTOR CONTAINER
|
||||
//
|
||||
//
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
//!Thse options specify the relocation strategy of devector.
|
||||
//!
|
||||
//!Predefined relocation limits that can be passed as arguments to this option are:
|
||||
//!\c boost::container::relocate_on_66
|
||||
//!\c boost::container::relocate_on_75
|
||||
//!\c boost::container::relocate_on_80
|
||||
//!\c boost::container::relocate_on_85
|
||||
//!\c boost::container::relocate_on_90
|
||||
//!
|
||||
//!If this option is not specified, a default will be used by the container.
|
||||
//!
|
||||
//!Note: Repeated insertions at only one end (only back insertions or only front insertions) usually will
|
||||
//!lead to a single relocation when `relocate_on_66` is used and two relocations when `relocate_on_90`
|
||||
//!is used.
|
||||
|
||||
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
|
||||
BOOST_INTRUSIVE_OPTION_CONSTANT(relocate_on, std::size_t, Fraction, free_fraction)
|
||||
|
||||
struct relocate_on_66 : public relocate_on<3U>{};
|
||||
|
||||
struct relocate_on_75 : public relocate_on<4U> {};
|
||||
|
||||
struct relocate_on_80 : public relocate_on<5U> {};
|
||||
|
||||
struct relocate_on_85 : public relocate_on<7U> {};
|
||||
|
||||
struct relocate_on_90 : public relocate_on<10U> {};
|
||||
|
||||
template<class GrowthType, class StoredSizeType, std::size_t FreeFraction>
|
||||
struct devector_opt
|
||||
: vector_opt<GrowthType, StoredSizeType>
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR std::size_t free_fraction = FreeFraction;
|
||||
};
|
||||
|
||||
typedef devector_opt<void, void, 0u> devector_null_opt;
|
||||
|
||||
#else
|
||||
|
||||
//!This relocation condition option specifies that the container will never relocate
|
||||
//!elements when there is no space at the side the insertion should
|
||||
//!take place
|
||||
struct relocate_never;
|
||||
|
||||
//!This relocation condition option specifies that the container will relocate
|
||||
//!all elements when there is no space at the side the insertion should
|
||||
//!take place and memory usage is below 66% (2/3)
|
||||
struct relocate_on_66;
|
||||
|
||||
//!This relocation condition option specifies that the container will relocate
|
||||
//!all elements when there is no space at the side the insertion should
|
||||
//!take place and memory usage is below 75% (3/4)
|
||||
struct relocate_on_75;
|
||||
|
||||
//!This relocation condition option specifies that the container will relocate
|
||||
//!all elements when there is no space at the side the insertion should
|
||||
//!take place and memory usage is below 80% (4/5)
|
||||
struct relocate_on_80;
|
||||
|
||||
//!This relocation condition option specifies that the container will relocate
|
||||
//!all elements when there is no space at the side the insertion should
|
||||
//!take place and memory usage is below 85% (6/7)
|
||||
struct relocate_on_85;
|
||||
|
||||
//!This relocation condition option specifies that the container will relocate
|
||||
//!all elements when there is no space at the side the insertion should
|
||||
//!take place and memory usage is below 90% (9/10)
|
||||
struct relocate_on_90;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
//! Helper metafunction to combine options into a single type to be used
|
||||
//! by \c boost::container::devector.
|
||||
//! Supported options are: \c boost::container::growth_factor, \c boost::container::stored_size
|
||||
//! and \c boost::container::relocate_on
|
||||
#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 devector_options
|
||||
{
|
||||
/// @cond
|
||||
typedef typename ::boost::intrusive::pack_options
|
||||
< devector_null_opt,
|
||||
#if !defined(BOOST_CONTAINER_VARIADIC_TEMPLATES)
|
||||
O1, O2, O3, O4
|
||||
#else
|
||||
Options...
|
||||
#endif
|
||||
>::type packed_options;
|
||||
typedef devector_opt< typename packed_options::growth_factor_type
|
||||
, typename packed_options::stored_size_type
|
||||
, packed_options::free_fraction
|
||||
> implementation_defined;
|
||||
/// @endcond
|
||||
typedef implementation_defined type;
|
||||
};
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
|
||||
|
||||
//! Helper alias metafunction to combine options into a single type to be used
|
||||
//! by \c boost::container::devector.
|
||||
template<class ...Options>
|
||||
using devector_options_t = typename boost::container::devector_options<Options...>::type;
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//
|
||||
// OPTIONS FOR DEQUE-BASED CONTAINERS
|
||||
//
|
||||
//
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
|
||||
template<std::size_t BlockBytes, std::size_t BlockSize, class StoredSizeType, bool Reservable>
|
||||
struct deque_opt
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR std::size_t block_bytes = BlockBytes;
|
||||
BOOST_STATIC_CONSTEXPR std::size_t block_size = BlockSize;
|
||||
BOOST_CONTAINER_STATIC_ASSERT_MSG(!(block_bytes && block_size), "block_bytes and block_size can't be specified at the same time");
|
||||
BOOST_STATIC_CONSTEXPR bool reservable = Reservable;
|
||||
|
||||
typedef StoredSizeType stored_size_type;
|
||||
|
||||
template<class AllocTraits>
|
||||
struct get_stored_size_type
|
||||
: get_stored_size_type_with_alloctraits<AllocTraits, StoredSizeType>
|
||||
{};
|
||||
};
|
||||
|
||||
typedef deque_opt<0u, 0u, void, false> deque_null_opt;
|
||||
|
||||
#endif
|
||||
|
||||
//! Helper metafunction to combine options into a single type to be used
|
||||
//! by \c boost::container::deque.
|
||||
//! Supported options are: \c boost::container::block_bytes, \c boost::container::block_size,
|
||||
//! \c boost::container::stored_size and \c boost::container::reservable
|
||||
#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 deque_options
|
||||
{
|
||||
/// @cond
|
||||
typedef typename ::boost::intrusive::pack_options
|
||||
< deque_null_opt,
|
||||
#if !defined(BOOST_CONTAINER_VARIADIC_TEMPLATES)
|
||||
O1, O2, O3, O4
|
||||
#else
|
||||
Options...
|
||||
#endif
|
||||
>::type packed_options;
|
||||
typedef deque_opt< packed_options::block_bytes
|
||||
, packed_options::block_size
|
||||
, typename packed_options::stored_size_type
|
||||
, packed_options::reservable
|
||||
> implementation_defined;
|
||||
/// @endcond
|
||||
typedef implementation_defined type;
|
||||
};
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
|
||||
|
||||
//! Helper alias metafunction to combine options into a single type to be used
|
||||
//! by \c boost::container::deque.
|
||||
template<class ...Options>
|
||||
using deque_options_t = typename boost::container::deque_options<Options...>::type;
|
||||
|
||||
#endif
|
||||
|
||||
//!This option specifies the maximum size of a block in bytes: this delimites the number of contiguous elements
|
||||
//!that will be allocated by some containers as min(1u, BlockBytes/sizeof(value_type))
|
||||
//!A value zero represents the default value.
|
||||
//!
|
||||
//!\tparam BlockBytes An unsigned integer value.
|
||||
BOOST_INTRUSIVE_OPTION_CONSTANT(block_bytes, std::size_t, BlockBytes, block_bytes)
|
||||
|
||||
//!This option specifies the size of a block, delimites the number of contiguous elements
|
||||
//!that will be allocated by some containersas BlockSize.
|
||||
//!For some containers (like deque), a power of two value can improve performance.
|
||||
//!A value zero represents the default value.
|
||||
//!
|
||||
//!\tparam BlockBytes An unsigned integer value.
|
||||
BOOST_INTRUSIVE_OPTION_CONSTANT(block_size, std::size_t, BlockSize, block_size)
|
||||
|
||||
//!This option specifies if the container has reserve/capacity-like features
|
||||
//!
|
||||
//!For some containers (like deque) this option might change the internal representation or
|
||||
//!behavior so that memory for elements can be allocated in advance in
|
||||
//!order to improve performance.
|
||||
//!
|
||||
//!\tparam Reservable An boolean value.
|
||||
BOOST_INTRUSIVE_OPTION_CONSTANT(reservable, bool, Reservable, reservable)
|
||||
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_OPTIONS_HPP
|
||||
45
include/boost/container/pmr/deque.hpp
Normal file
45
include/boost/container/pmr/deque.hpp
Normal file
@@ -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
|
||||
53
include/boost/container/pmr/devector.hpp
Normal file
53
include/boost/container/pmr/devector.hpp
Normal file
@@ -0,0 +1,53 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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/devector.hpp>
|
||||
#include <boost/container/pmr/polymorphic_allocator.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace pmr {
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename Options = void
|
||||
>
|
||||
using devector = boost::container::devector<T, polymorphic_allocator<T>, Options >;
|
||||
|
||||
#endif
|
||||
|
||||
//! A portable metafunction to obtain a vector
|
||||
//! that uses a polymorphic allocator
|
||||
template <
|
||||
typename T,
|
||||
typename Options = void
|
||||
>
|
||||
struct devector_of
|
||||
{
|
||||
typedef boost::container::devector
|
||||
< T
|
||||
, polymorphic_allocator<T>
|
||||
, Options > type;
|
||||
};
|
||||
|
||||
} //namespace pmr {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //BOOST_CONTAINER_PMR_VECTOR_HPP
|
||||
63
include/boost/container/pmr/flat_map.hpp
Normal file
63
include/boost/container/pmr/flat_map.hpp
Normal file
@@ -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_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 > >
|
||||
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> >
|
||||
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> >
|
||||
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> >
|
||||
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
|
||||
59
include/boost/container/pmr/flat_set.hpp
Normal file
59
include/boost/container/pmr/flat_set.hpp
Normal file
@@ -0,0 +1,59 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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_SET_HPP
|
||||
#define BOOST_CONTAINER_PMR_FLAT_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> >
|
||||
using flat_set = boost::container::flat_set<Key, Compare, polymorphic_allocator<Key> >;
|
||||
|
||||
template <class Key
|
||||
,class Compare = std::less<Key> >
|
||||
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> >
|
||||
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> >
|
||||
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_FLAT_SET_HPP
|
||||
63
include/boost/container/pmr/global_resource.hpp
Normal file
63
include/boost/container/pmr/global_resource.hpp
Normal file
@@ -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_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 <boost/container/container_fwd.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace pmr {
|
||||
|
||||
//! <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
|
||||
45
include/boost/container/pmr/list.hpp
Normal file
45
include/boost/container/pmr/list.hpp
Normal file
@@ -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
|
||||
67
include/boost/container/pmr/map.hpp
Normal file
67
include/boost/container/pmr/map.hpp
Normal file
@@ -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 = void >
|
||||
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 = void >
|
||||
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 = void >
|
||||
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 = void >
|
||||
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
|
||||
135
include/boost/container/pmr/memory_resource.hpp
Normal file
135
include/boost/container/pmr/memory_resource.hpp
Normal file
@@ -0,0 +1,135 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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/container/container_fwd.hpp>
|
||||
#include <boost/move/detail/type_traits.hpp>
|
||||
#include <boost/container/detail/placement_new.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
|
||||
BOOST_STATIC_CONSTEXPR 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)
|
||||
{
|
||||
//Obtain a pointer to enough storage and initialize the lifetime
|
||||
//of an array object of the given size in the address
|
||||
return ::operator new(bytes, this->do_allocate(bytes, alignment), boost_container_new_t());
|
||||
}
|
||||
|
||||
//! <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 do_is_equal(other);`
|
||||
bool is_equal(const memory_resource& other) const BOOST_NOEXCEPT
|
||||
{ return this->do_is_equal(other); }
|
||||
|
||||
#if !defined(BOOST_EMBTC)
|
||||
|
||||
//! <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); }
|
||||
|
||||
#else
|
||||
|
||||
//! <b>Returns</b>:
|
||||
//! `&a == &b || a.is_equal(b)`.
|
||||
friend bool operator==(const memory_resource& a, const memory_resource& b) BOOST_NOEXCEPT;
|
||||
|
||||
//! <b>Returns</b>:
|
||||
//! !(a == b).
|
||||
friend bool operator!=(const memory_resource& a, const memory_resource& b) BOOST_NOEXCEPT;
|
||||
|
||||
#endif
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
#if defined(BOOST_EMBTC)
|
||||
|
||||
//! <b>Returns</b>:
|
||||
//! `&a == &b || a.is_equal(b)`.
|
||||
inline bool operator==(const memory_resource& a, const memory_resource& b) BOOST_NOEXCEPT
|
||||
{ return &a == &b || a.is_equal(b); }
|
||||
|
||||
//! <b>Returns</b>:
|
||||
//! !(a == b).
|
||||
inline bool operator!=(const memory_resource& a, const memory_resource& b) BOOST_NOEXCEPT
|
||||
{ return !(a == b); }
|
||||
|
||||
#endif
|
||||
|
||||
} //namespace pmr {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_CONTAINER_PMR_MEMORY_RESOURCE_HPP
|
||||
183
include/boost/container/pmr/monotonic_buffer_resource.hpp
Normal file
183
include/boost/container/pmr/monotonic_buffer_resource.hpp
Normal file
@@ -0,0 +1,183 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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/container_fwd.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;
|
||||
void * const m_initial_buffer;
|
||||
std::size_t const m_initial_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.
|
||||
BOOST_STATIC_CONSTEXPR 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()`.
|
||||
~monotonic_buffer_resource() BOOST_OVERRIDE;
|
||||
|
||||
//! <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 address pointing to the start of the current free storage.
|
||||
//!
|
||||
//! <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) BOOST_OVERRIDE;
|
||||
|
||||
//! <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 BOOST_OVERRIDE;
|
||||
|
||||
//! <b>Returns</b>:
|
||||
//! `this == dynamic_cast<const monotonic_buffer_resource*>(&other)`.
|
||||
virtual bool do_is_equal(const memory_resource& other) const BOOST_NOEXCEPT BOOST_OVERRIDE;
|
||||
};
|
||||
|
||||
} //namespace pmr {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_CONTAINER_PMR_MONOTONIC_BUFFER_RESOURCE_HPP
|
||||
166
include/boost/container/pmr/polymorphic_allocator.hpp
Normal file
166
include/boost/container/pmr/polymorphic_allocator.hpp
Normal file
@@ -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 <boost/assert.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*.
|
||||
polymorphic_allocator(memory_resource* r) BOOST_NOEXCEPT
|
||||
: m_resource(r)
|
||||
{ BOOST_ASSERT(r != 0); }
|
||||
|
||||
//! <b>Effects</b>: Sets m_resource to
|
||||
//! other.resource().
|
||||
polymorphic_allocator(const polymorphic_allocator& other) BOOST_NOEXCEPT
|
||||
: 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) BOOST_NOEXCEPT
|
||||
{ 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) BOOST_NOEXCEPT
|
||||
{ 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` 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` 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;
|
||||
dtl::dispatch_uses_allocator
|
||||
(na, *this, 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;\
|
||||
dtl::dispatch_uses_allocator\
|
||||
(na, *this, 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 BOOST_NOEXCEPT
|
||||
{ return polymorphic_allocator(); }
|
||||
|
||||
//! <b>Returns</b>:
|
||||
//! m_resource.
|
||||
memory_resource* resource() const BOOST_NOEXCEPT
|
||||
{ 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
|
||||
52
include/boost/container/pmr/pool_options.hpp
Normal file
52
include/boost/container/pmr/pool_options.hpp
Normal file
@@ -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
|
||||
277
include/boost/container/pmr/resource_adaptor.hpp
Normal file
277
include/boost/container/pmr/resource_adaptor.hpp
Normal file
@@ -0,0 +1,277 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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/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/allocator_traits.hpp>
|
||||
#include <boost/intrusive/detail/ebo_functor_holder.hpp>
|
||||
#include <boost/move/utility_core.hpp>
|
||||
#include <boost/move/detail/type_traits.hpp>
|
||||
#include <boost/container/detail/std_fwd.hpp>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
|
||||
namespace pmr_dtl {
|
||||
|
||||
template<class T>
|
||||
struct max_allocator_alignment
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR std::size_t value = 1;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct max_allocator_alignment< ::boost::container::new_allocator<T> >
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR std::size_t value = boost::move_detail::alignment_of<boost::move_detail::max_align_t>::value;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct max_allocator_alignment< std::allocator<T> >
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR std::size_t value = boost::move_detail::alignment_of<boost::move_detail::max_align_t>::value;
|
||||
};
|
||||
|
||||
} //namespace pmr_dtl
|
||||
|
||||
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_CONTAINER_STATIC_ASSERT((boost::container::dtl::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(std::size_t bytes, std::size_t alignment) BOOST_OVERRIDE
|
||||
{
|
||||
if (alignment <= priv_guaranteed_allocator_alignment())
|
||||
return this->ebo_alloc_t::get().allocate(bytes);
|
||||
else
|
||||
return this->priv_aligned_alloc(bytes, alignment);
|
||||
}
|
||||
|
||||
//! <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, std::size_t bytes, std::size_t alignment) BOOST_OVERRIDE
|
||||
{
|
||||
if (alignment <= priv_guaranteed_allocator_alignment())
|
||||
this->ebo_alloc_t::get().deallocate((char*)p, bytes);
|
||||
else
|
||||
this->priv_aligned_dealloc(p, bytes, alignment);
|
||||
}
|
||||
|
||||
//! 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 BOOST_OVERRIDE
|
||||
{
|
||||
const resource_adaptor_imp* p = dynamic_cast<const resource_adaptor_imp*>(&other);
|
||||
return p && p->ebo_alloc_t::get() == this->ebo_alloc_t::get();
|
||||
}
|
||||
|
||||
private:
|
||||
void * priv_aligned_alloc(std::size_t bytes, std::size_t alignment)
|
||||
{
|
||||
//Allocate space for requested bytes, plus alignment, plus bookeeping data
|
||||
void *const p = this->ebo_alloc_t::get().allocate(bytes + priv_extra_bytes_for_overalignment(alignment));
|
||||
|
||||
if (0 != p) {
|
||||
//Obtain the aligned address after the bookeeping data
|
||||
void *const aligned_ptr = (void*)(((std::size_t)p + priv_extra_bytes_for_overalignment(alignment)) & ~(alignment - 1));
|
||||
|
||||
//Store bookeeping data. Use memcpy as the underlying memory might be unaligned for
|
||||
//a pointer (e.g. 2 byte alignment in 32 bit, 4 byte alignment in 64 bit)
|
||||
std::memcpy(priv_bookeeping_addr_from_aligned_ptr(aligned_ptr), &p, sizeof(p));
|
||||
return aligned_ptr;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void priv_aligned_dealloc(void *aligned_ptr, std::size_t bytes, std::size_t alignment)
|
||||
{
|
||||
//Obtain bookeeping data
|
||||
void *p;
|
||||
std::memcpy(&p, priv_bookeeping_addr_from_aligned_ptr(aligned_ptr), sizeof(p));
|
||||
std::size_t s = bytes + priv_extra_bytes_for_overalignment(alignment);
|
||||
this->ebo_alloc_t::get().deallocate((char*)p, s);
|
||||
}
|
||||
|
||||
static BOOST_CONTAINER_FORCEINLINE void *priv_bookeeping_addr_from_aligned_ptr(void *aligned_ptr)
|
||||
{
|
||||
return reinterpret_cast<void*>(reinterpret_cast<std::size_t>(aligned_ptr) - sizeof(void*));
|
||||
}
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE static std::size_t priv_extra_bytes_for_overalignment(std::size_t alignment)
|
||||
{
|
||||
return alignment - 1 + sizeof(void*);
|
||||
}
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE static std::size_t priv_guaranteed_allocator_alignment()
|
||||
{
|
||||
return pmr_dtl::max_allocator_alignment<Allocator>::value;
|
||||
}
|
||||
};
|
||||
|
||||
#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(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 {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_CONTAINER_PMR_RESOURCE_ADAPTOR_HPP
|
||||
63
include/boost/container/pmr/set.hpp
Normal file
63
include/boost/container/pmr/set.hpp
Normal file
@@ -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 = void >
|
||||
using set = boost::container::set<Key, Compare, polymorphic_allocator<Key>, Options>;
|
||||
|
||||
template <class Key
|
||||
,class Compare = std::less<Key>
|
||||
,class Options = void >
|
||||
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 = void >
|
||||
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 = void >
|
||||
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
|
||||
45
include/boost/container/pmr/slist.hpp
Normal file
45
include/boost/container/pmr/slist.hpp
Normal file
@@ -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
|
||||
45
include/boost/container/pmr/small_vector.hpp
Normal file
45
include/boost/container/pmr/small_vector.hpp
Normal file
@@ -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
|
||||
45
include/boost/container/pmr/stable_vector.hpp
Normal file
45
include/boost/container/pmr/stable_vector.hpp
Normal file
@@ -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
|
||||
50
include/boost/container/pmr/string.hpp
Normal file
50
include/boost/container/pmr/string.hpp
Normal file
@@ -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
|
||||
139
include/boost/container/pmr/synchronized_pool_resource.hpp
Normal file
139
include/boost/container/pmr/synchronized_pool_resource.hpp
Normal file
@@ -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_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 <boost/container/detail/thread_mutex.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
|
||||
{
|
||||
dtl::thread_mutex m_mut;
|
||||
pool_resource m_pool_resource;
|
||||
|
||||
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()
|
||||
~synchronized_pool_resource() BOOST_OVERRIDE;
|
||||
|
||||
//! @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) BOOST_OVERRIDE;
|
||||
|
||||
//! @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) BOOST_OVERRIDE;
|
||||
|
||||
//! @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 BOOST_OVERRIDE;
|
||||
|
||||
//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
include/boost/container/pmr/unsynchronized_pool_resource.hpp
Normal file
194
include/boost/container/pmr/unsynchronized_pool_resource.hpp
Normal file
@@ -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()`.
|
||||
~unsynchronized_pool_resource() BOOST_OVERRIDE;
|
||||
|
||||
//! <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) BOOST_OVERRIDE;
|
||||
|
||||
//! <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) BOOST_OVERRIDE;
|
||||
|
||||
//! <b>Returns</b>:
|
||||
//! `this == dynamic_cast<const unsynchronized_pool_resource*>(&other)`.
|
||||
virtual bool do_is_equal(const memory_resource& other) const BOOST_NOEXCEPT BOOST_OVERRIDE;
|
||||
|
||||
//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
|
||||
45
include/boost/container/pmr/vector.hpp
Normal file
45
include/boost/container/pmr/vector.hpp
Normal file
@@ -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
|
||||
905
include/boost/container/scoped_allocator.hpp
Normal file
905
include/boost/container/scoped_allocator.hpp
Normal file
@@ -0,0 +1,905 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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>
|
||||
|
||||
namespace boost { namespace container {
|
||||
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
namespace dtl {
|
||||
|
||||
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(...);
|
||||
|
||||
BOOST_STATIC_CONSTEXPR 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;
|
||||
|
||||
inline static type &get(MaybeScopedAlloc &a)
|
||||
{ return a; }
|
||||
|
||||
inline 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;
|
||||
|
||||
inline static type &get(MaybeScopedAlloc &a)
|
||||
{ return outermost_allocator_imp<outer_type>::get(a.outer_allocator()); }
|
||||
|
||||
inline static const type &get(const MaybeScopedAlloc &a)
|
||||
{ return outermost_allocator_imp<outer_type>::get(a.outer_allocator()); }
|
||||
};
|
||||
|
||||
} //namespace dtl {
|
||||
|
||||
template <typename Allocator>
|
||||
struct is_scoped_allocator
|
||||
: dtl::is_scoped_allocator_imp<Allocator>
|
||||
{};
|
||||
|
||||
template <typename Allocator>
|
||||
struct outermost_allocator
|
||||
: dtl::outermost_allocator_imp<Allocator>
|
||||
{};
|
||||
|
||||
template <typename Allocator>
|
||||
inline typename outermost_allocator<Allocator>::type &
|
||||
get_outermost_allocator(Allocator &a)
|
||||
{ return outermost_allocator<Allocator>::get(a); }
|
||||
|
||||
template <typename Allocator>
|
||||
inline const typename outermost_allocator<Allocator>::type &
|
||||
get_outermost_allocator(const Allocator &a)
|
||||
{ return outermost_allocator<Allocator>::get(a); }
|
||||
|
||||
namespace dtl {
|
||||
|
||||
#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 dtl::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 dtl::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 dtl::bool_<
|
||||
outer_traits_type::propagate_on_container_swap::value ||
|
||||
inner_allocator_type::propagate_on_container_swap::value
|
||||
> propagate_on_container_swap;
|
||||
typedef dtl::bool_<
|
||||
outer_traits_type::is_always_equal::value &&
|
||||
inner_allocator_type::is_always_equal::value
|
||||
> is_always_equal;
|
||||
|
||||
inline scoped_allocator_adaptor_base()
|
||||
{}
|
||||
|
||||
template <class OuterA2>
|
||||
inline scoped_allocator_adaptor_base(BOOST_FWD_REF(OuterA2) outerAlloc, const InnerAllocs &...args)
|
||||
: outer_allocator_type(::boost::forward<OuterA2>(outerAlloc))
|
||||
, m_inner(args...)
|
||||
{}
|
||||
|
||||
inline scoped_allocator_adaptor_base(const scoped_allocator_adaptor_base& other)
|
||||
: outer_allocator_type(other.outer_allocator())
|
||||
, m_inner(other.inner_allocator())
|
||||
{}
|
||||
|
||||
inline 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>
|
||||
inline 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>
|
||||
inline 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>
|
||||
inline 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:
|
||||
|
||||
inline 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;
|
||||
}
|
||||
|
||||
inline 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;
|
||||
}
|
||||
|
||||
inline 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());
|
||||
}
|
||||
|
||||
inline friend void swap(scoped_allocator_adaptor_base &l, scoped_allocator_adaptor_base &r)
|
||||
{ l.swap(r); }
|
||||
|
||||
inline inner_allocator_type& inner_allocator() BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return m_inner; }
|
||||
|
||||
inline inner_allocator_type const& inner_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return m_inner; }
|
||||
|
||||
inline outer_allocator_type & outer_allocator() BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return static_cast<outer_allocator_type&>(*this); }
|
||||
|
||||
inline const outer_allocator_type &outer_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return static_cast<const outer_allocator_type&>(*this); }
|
||||
|
||||
inline 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 dtl::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 dtl::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 dtl::bool_<\
|
||||
outer_traits_type::propagate_on_container_swap::value ||\
|
||||
inner_allocator_type::propagate_on_container_swap::value\
|
||||
> propagate_on_container_swap;\
|
||||
\
|
||||
typedef dtl::bool_<\
|
||||
outer_traits_type::is_always_equal::value &&\
|
||||
inner_allocator_type::is_always_equal::value\
|
||||
> is_always_equal;\
|
||||
\
|
||||
inline scoped_allocator_adaptor_base(){}\
|
||||
\
|
||||
template <class OuterA2>\
|
||||
inline 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)\
|
||||
{}\
|
||||
\
|
||||
inline scoped_allocator_adaptor_base(const scoped_allocator_adaptor_base& other)\
|
||||
: outer_allocator_type(other.outer_allocator())\
|
||||
, m_inner(other.inner_allocator())\
|
||||
{}\
|
||||
\
|
||||
inline 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>\
|
||||
inline 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>\
|
||||
inline 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>\
|
||||
inline 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:\
|
||||
inline 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;\
|
||||
}\
|
||||
\
|
||||
inline 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;\
|
||||
}\
|
||||
\
|
||||
inline 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());\
|
||||
}\
|
||||
\
|
||||
inline friend void swap(scoped_allocator_adaptor_base &l, scoped_allocator_adaptor_base &r)\
|
||||
{ l.swap(r); }\
|
||||
\
|
||||
inline inner_allocator_type& inner_allocator()\
|
||||
{ return m_inner; }\
|
||||
\
|
||||
inline inner_allocator_type const& inner_allocator() const\
|
||||
{ return m_inner; }\
|
||||
\
|
||||
inline outer_allocator_type & outer_allocator()\
|
||||
{ return static_cast<outer_allocator_type&>(*this); }\
|
||||
\
|
||||
inline const outer_allocator_type &outer_allocator() const\
|
||||
{ return static_cast<const outer_allocator_type&>(*this); }\
|
||||
\
|
||||
inline 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;
|
||||
|
||||
inline scoped_allocator_adaptor_base()
|
||||
{}
|
||||
|
||||
template <class OuterA2>
|
||||
inline scoped_allocator_adaptor_base(BOOST_FWD_REF(OuterA2) outerAlloc)
|
||||
: outer_allocator_type(::boost::forward<OuterA2>(outerAlloc))
|
||||
{}
|
||||
|
||||
inline scoped_allocator_adaptor_base(const scoped_allocator_adaptor_base& other)
|
||||
: outer_allocator_type(other.outer_allocator())
|
||||
{}
|
||||
|
||||
inline scoped_allocator_adaptor_base(BOOST_RV_REF(scoped_allocator_adaptor_base) other)
|
||||
: outer_allocator_type(::boost::move(other.outer_allocator()))
|
||||
{}
|
||||
|
||||
template <class OuterA2>
|
||||
inline scoped_allocator_adaptor_base
|
||||
(const scoped_allocator_adaptor_base<OuterA2 BOOST_CONTAINER_SCOPEDALLOC_DUMMYTRUE>& other)
|
||||
: outer_allocator_type(other.outer_allocator())
|
||||
{}
|
||||
|
||||
template <class OuterA2>
|
||||
inline 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>
|
||||
inline scoped_allocator_adaptor_base(internal_type_t, BOOST_FWD_REF(OuterA2) outerAlloc, const inner_allocator_type &)
|
||||
: outer_allocator_type(::boost::forward<OuterA2>(outerAlloc))
|
||||
{}
|
||||
|
||||
public:
|
||||
inline scoped_allocator_adaptor_base &operator=(BOOST_COPY_ASSIGN_REF(scoped_allocator_adaptor_base) other)
|
||||
{
|
||||
outer_allocator_type::operator=(other.outer_allocator());
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline scoped_allocator_adaptor_base &operator=(BOOST_RV_REF(scoped_allocator_adaptor_base) other)
|
||||
{
|
||||
outer_allocator_type::operator=(boost::move(other.outer_allocator()));
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline void swap(scoped_allocator_adaptor_base &r)
|
||||
{
|
||||
boost::adl_move_swap(this->outer_allocator(), r.outer_allocator());
|
||||
}
|
||||
|
||||
inline friend void swap(scoped_allocator_adaptor_base &l, scoped_allocator_adaptor_base &r)
|
||||
{ l.swap(r); }
|
||||
|
||||
inline inner_allocator_type& inner_allocator()
|
||||
{ return static_cast<inner_allocator_type&>(*this); }
|
||||
|
||||
inline inner_allocator_type const& inner_allocator() const
|
||||
{ return static_cast<const inner_allocator_type&>(*this); }
|
||||
|
||||
inline outer_allocator_type & outer_allocator()
|
||||
{ return static_cast<outer_allocator_type&>(*this); }
|
||||
|
||||
inline const outer_allocator_type &outer_allocator() const
|
||||
{ return static_cast<const outer_allocator_type&>(*this); }
|
||||
|
||||
inline 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 dtl {
|
||||
|
||||
#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 dtl::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 dtl::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.
|
||||
inline scoped_allocator_adaptor()
|
||||
{}
|
||||
|
||||
inline ~scoped_allocator_adaptor()
|
||||
{}
|
||||
|
||||
//! <b>Effects</b>: initializes each allocator within the adaptor with
|
||||
//! the corresponding allocator from other.
|
||||
inline 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.
|
||||
inline 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>
|
||||
inline 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>\
|
||||
inline 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>
|
||||
inline 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>
|
||||
inline 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()))
|
||||
{}
|
||||
|
||||
inline 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))); }
|
||||
|
||||
inline 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>.
|
||||
inline 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>
|
||||
inline 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>.
|
||||
inline 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>.
|
||||
inline 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>.
|
||||
inline 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
|
||||
inline base_type &base() { return *this; }
|
||||
|
||||
inline 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>
|
||||
inline void construct(T* p, BOOST_FWD_REF(Args)...args)
|
||||
{
|
||||
dtl::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 >\
|
||||
inline void construct(T* p BOOST_MOVE_I##N BOOST_MOVE_UREFQ##N)\
|
||||
{\
|
||||
dtl::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>
|
||||
inline 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>
|
||||
inline 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>
|
||||
inline static bool equal_outer(const IA1 &l, const IA2 &r)
|
||||
{ return l == r; }
|
||||
|
||||
//Otherwise compare it normally
|
||||
template<class IA>
|
||||
inline 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>
|
||||
inline 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::dtl::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
|
||||
71
include/boost/container/scoped_allocator_fwd.hpp
Normal file
71
include/boost/container/scoped_allocator_fwd.hpp
Normal file
@@ -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
|
||||
1714
include/boost/container/set.hpp
Normal file
1714
include/boost/container/set.hpp
Normal file
File diff suppressed because it is too large
Load Diff
1763
include/boost/container/slist.hpp
Normal file
1763
include/boost/container/slist.hpp
Normal file
File diff suppressed because it is too large
Load Diff
722
include/boost/container/small_vector.hpp
Normal file
722
include/boost/container/small_vector.hpp
Normal file
@@ -0,0 +1,722 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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
|
||||
|
||||
#include <cstddef> //offsetof
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
|
||||
namespace dtl{
|
||||
|
||||
template<class Options>
|
||||
struct get_small_vector_opt
|
||||
{
|
||||
typedef Options type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct get_small_vector_opt<void>
|
||||
{
|
||||
typedef small_vector_null_opt type;
|
||||
};
|
||||
|
||||
template<class Options>
|
||||
struct get_vopt_from_svopt
|
||||
: get_small_vector_opt<Options>::type
|
||||
{
|
||||
typedef typename get_small_vector_opt<Options>::type options_t;
|
||||
typedef vector_opt< typename options_t::growth_factor_type
|
||||
, typename options_t::stored_size_type
|
||||
> type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct get_vopt_from_svopt<void>
|
||||
{
|
||||
typedef void type;
|
||||
};
|
||||
|
||||
template <class T, class SecAlloc, class Options>
|
||||
struct vector_for_small_vector
|
||||
{
|
||||
typedef vector
|
||||
< T
|
||||
, small_vector_allocator
|
||||
< T
|
||||
, typename allocator_traits<typename real_allocator<T, SecAlloc>::type>::template portable_rebind_alloc<void>::type
|
||||
, Options>
|
||||
, typename dtl::get_vopt_from_svopt<Options>::type
|
||||
> type;
|
||||
};
|
||||
|
||||
} //namespace dtl
|
||||
|
||||
//! 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<T, Allocator> >`
|
||||
//! and internal storage can be obtained downcasting that vector
|
||||
//! to `small_vector_base<T>`.
|
||||
template<class T, class VoidAlloc BOOST_CONTAINER_DOCONLY(= void), class Options BOOST_CONTAINER_DOCONLY(= void)>
|
||||
class small_vector_allocator
|
||||
: public allocator_traits<VoidAlloc>::template portable_rebind_alloc<T>::type
|
||||
{
|
||||
typedef unsigned int allocation_type;
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
public:
|
||||
typedef typename allocator_traits<VoidAlloc>::template portable_rebind_alloc<T>::type allocator_type;
|
||||
|
||||
private:
|
||||
BOOST_COPYABLE_AND_MOVABLE(small_vector_allocator)
|
||||
|
||||
inline const allocator_type &as_base() const BOOST_NOEXCEPT
|
||||
{ return static_cast<const allocator_type&>(*this); }
|
||||
|
||||
inline allocator_type &as_base() BOOST_NOEXCEPT
|
||||
{ return static_cast<allocator_type&>(*this); }
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
public:
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
typedef allocator_traits<allocator_type> allocator_traits_type;
|
||||
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
typedef typename allocator_traits<allocator_type>::value_type value_type;
|
||||
typedef typename allocator_traits<allocator_type>::pointer pointer;
|
||||
typedef typename allocator_traits<allocator_type>::const_pointer const_pointer;
|
||||
typedef typename allocator_traits<allocator_type>::reference reference;
|
||||
typedef typename allocator_traits<allocator_type>::const_reference const_reference;
|
||||
typedef typename allocator_traits<allocator_type>::size_type size_type;
|
||||
typedef typename allocator_traits<allocator_type>::difference_type difference_type;
|
||||
typedef typename allocator_traits<allocator_type>::void_pointer void_pointer;
|
||||
typedef typename allocator_traits<allocator_type>::const_void_pointer const_void_pointer;
|
||||
|
||||
typedef typename allocator_traits<allocator_type>::propagate_on_container_copy_assignment propagate_on_container_copy_assignment;
|
||||
typedef typename allocator_traits<allocator_type>::propagate_on_container_move_assignment propagate_on_container_move_assignment;
|
||||
typedef typename allocator_traits<allocator_type>::propagate_on_container_swap propagate_on_container_swap;
|
||||
//! An integral constant with member `value == false`
|
||||
typedef BOOST_CONTAINER_IMPDEF(dtl::bool_<false>) is_always_equal;
|
||||
//! An integral constant with member `value == true`
|
||||
typedef BOOST_CONTAINER_IMPDEF(dtl::bool_<true>) is_partially_propagable;
|
||||
|
||||
BOOST_CONTAINER_DOCIGN(typedef dtl::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_type>::template portable_rebind_alloc<T2>::type other;
|
||||
};
|
||||
|
||||
inline small_vector_allocator() BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<allocator_type>::value)
|
||||
{}
|
||||
|
||||
//!Constructor from other small_vector_allocator.
|
||||
//!Never throws
|
||||
inline small_vector_allocator
|
||||
(const small_vector_allocator &other) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
: allocator_type(other.as_base())
|
||||
{}
|
||||
|
||||
//!Move constructor from small_vector_allocator.
|
||||
//!Never throws
|
||||
inline small_vector_allocator
|
||||
(BOOST_RV_REF(small_vector_allocator) other) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
: allocator_type(::boost::move(other.as_base()))
|
||||
{}
|
||||
|
||||
//!Constructor from related small_vector_allocator.
|
||||
//!Never throws
|
||||
template<class U, class OtherVoidAllocator, class OtherOptions>
|
||||
inline small_vector_allocator
|
||||
(const small_vector_allocator<U, OtherVoidAllocator, OtherOptions> &other) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
: allocator_type(other.as_base())
|
||||
{}
|
||||
|
||||
//!Move constructor from related small_vector_allocator.
|
||||
//!Never throws
|
||||
template<class U, class OtherVoidAllocator, class OtherOptions>
|
||||
inline small_vector_allocator
|
||||
(BOOST_RV_REF(small_vector_allocator<U BOOST_MOVE_I OtherVoidAllocator BOOST_MOVE_I OtherOptions>) other) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
: allocator_type(::boost::move(other.as_base()))
|
||||
{}
|
||||
|
||||
//!Constructor from allocator_type.
|
||||
//!Never throws
|
||||
inline explicit small_vector_allocator
|
||||
(const allocator_type &other) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
: allocator_type(other)
|
||||
{}
|
||||
|
||||
//!Assignment from other small_vector_allocator.
|
||||
//!Never throws
|
||||
inline small_vector_allocator &
|
||||
operator=(BOOST_COPY_ASSIGN_REF(small_vector_allocator) other) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return static_cast<small_vector_allocator&>(this->allocator_type::operator=(other.as_base())); }
|
||||
|
||||
//!Move assignment from other small_vector_allocator.
|
||||
//!Never throws
|
||||
inline small_vector_allocator &
|
||||
operator=(BOOST_RV_REF(small_vector_allocator) other) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return static_cast<small_vector_allocator&>(this->allocator_type::operator=(::boost::move(other.as_base()))); }
|
||||
|
||||
//!Assignment from related small_vector_allocator.
|
||||
//!Never throws
|
||||
template<class U, class OtherVoidAllocator>
|
||||
inline small_vector_allocator &
|
||||
operator=(BOOST_COPY_ASSIGN_REF(small_vector_allocator<U BOOST_MOVE_I OtherVoidAllocator BOOST_MOVE_I Options>) other) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return static_cast<small_vector_allocator&>(this->allocator_type::operator=(other.as_base())); }
|
||||
|
||||
//!Move assignment from related small_vector_allocator.
|
||||
//!Never throws
|
||||
template<class U, class OtherVoidAllocator>
|
||||
inline small_vector_allocator &
|
||||
operator=(BOOST_RV_REF(small_vector_allocator<U BOOST_MOVE_I OtherVoidAllocator BOOST_MOVE_I Options>) other) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return static_cast<small_vector_allocator&>(this->allocator_type::operator=(::boost::move(other.as_base()))); }
|
||||
|
||||
//!Move assignment from allocator_type.
|
||||
//!Never throws
|
||||
inline small_vector_allocator &
|
||||
operator=(const allocator_type &other) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return static_cast<small_vector_allocator&>(this->allocator_type::operator=(other)); }
|
||||
|
||||
//!Allocates storage from the standard-conforming allocator
|
||||
inline 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
|
||||
inline 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
|
||||
inline 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)
|
||||
inline 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
|
||||
inline 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
|
||||
public:
|
||||
|
||||
typedef small_vector_base<value_type, allocator_type, Options> derived_type;
|
||||
typedef typename dtl::vector_for_small_vector
|
||||
<value_type, allocator_type, Options>::type vector_type;
|
||||
|
||||
inline bool is_internal_storage(const_pointer p) const
|
||||
{ return this->internal_storage() == p; }
|
||||
|
||||
public:
|
||||
inline const_pointer internal_storage() const BOOST_NOEXCEPT_OR_NOTHROW;
|
||||
inline pointer internal_storage() BOOST_NOEXCEPT_OR_NOTHROW;
|
||||
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
};
|
||||
|
||||
template<class T, std::size_t N, std::size_t Alignment>
|
||||
struct small_vector_storage
|
||||
{
|
||||
typedef typename dtl::aligned_storage
|
||||
<sizeof(T)*N, Alignment>::type storage_type;
|
||||
storage_type m_storage;
|
||||
BOOST_STATIC_CONSTEXPR std::size_t sms_size = sizeof(storage_type)/sizeof(T);
|
||||
};
|
||||
|
||||
template<class T, std::size_t Alignment>
|
||||
struct small_vector_storage<T, 0u, Alignment>
|
||||
{
|
||||
BOOST_STATIC_CONSTEXPR std::size_t sms_size = 0u;
|
||||
};
|
||||
|
||||
//! 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 SecAlloc, class Options>
|
||||
class small_vector_base
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
: public dtl::vector_for_small_vector<T, SecAlloc, Options>::type
|
||||
#endif
|
||||
{
|
||||
#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 real_allocator<T, SecAlloc>::type underlying_allocator_t;
|
||||
typedef typename allocator_traits<underlying_allocator_t>::
|
||||
template portable_rebind_alloc<void>::type void_underlying_allocator_t;
|
||||
typedef typename small_vector_allocator
|
||||
<T, void_underlying_allocator_t, Options>::allocator_type allocator_type;
|
||||
typedef typename dtl::get_small_vector_opt<Options>::type options_t;
|
||||
typedef typename dtl::vector_for_small_vector
|
||||
<T, SecAlloc, Options>::type base_type;
|
||||
typedef typename allocator_traits<allocator_type>::pointer pointer;
|
||||
typedef typename allocator_traits<allocator_type>::const_pointer const_pointer;
|
||||
typedef typename allocator_traits<allocator_type>::void_pointer void_pointer;
|
||||
typedef typename allocator_traits<allocator_type>::const_void_pointer const_void_pointer;
|
||||
typedef typename base_type::size_type size_type;
|
||||
|
||||
|
||||
private:
|
||||
BOOST_COPYABLE_AND_MOVABLE(small_vector_base)
|
||||
|
||||
friend class small_vector_allocator<T, void_underlying_allocator_t, Options>;
|
||||
|
||||
inline
|
||||
const_pointer internal_storage() const BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return this->base_type::get_stored_allocator().internal_storage(); }
|
||||
|
||||
inline
|
||||
pointer internal_storage() BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return this->base_type::get_stored_allocator().internal_storage(); }
|
||||
|
||||
private:
|
||||
base_type &as_base() { return static_cast<base_type&>(*this); }
|
||||
const base_type &as_base() const { return static_cast<const base_type&>(*this); }
|
||||
|
||||
public:
|
||||
|
||||
BOOST_CONTAINER_ATTRIBUTE_NODISCARD bool is_small() const
|
||||
{ return this->internal_storage() == this->data(); }
|
||||
|
||||
protected:
|
||||
|
||||
inline explicit small_vector_base(initial_capacity_t, size_type initial_capacity)
|
||||
: base_type(initial_capacity_t(), this->internal_storage(), initial_capacity)
|
||||
{}
|
||||
|
||||
template<class AllocFwd>
|
||||
inline explicit small_vector_base(initial_capacity_t, size_type initial_capacity, BOOST_FWD_REF(AllocFwd) a)
|
||||
: base_type(initial_capacity_t(), this->internal_storage(), initial_capacity, ::boost::forward<AllocFwd>(a))
|
||||
{}
|
||||
|
||||
template<class AllocFwd>
|
||||
inline explicit small_vector_base(initial_capacity_t, size_type initial_capacity, BOOST_FWD_REF(AllocFwd) a, small_vector_base &x)
|
||||
: base_type(initial_capacity_t(), this->internal_storage(), initial_capacity, ::boost::forward<AllocFwd>(a), x)
|
||||
{}
|
||||
|
||||
inline explicit small_vector_base(maybe_initial_capacity_t, size_type initial_capacity, size_type initial_size)
|
||||
: base_type( maybe_initial_capacity_t()
|
||||
, (initial_capacity >= initial_size) ? this->internal_storage() : pointer()
|
||||
, (initial_capacity >= initial_size) ? initial_capacity : initial_size
|
||||
)
|
||||
{}
|
||||
|
||||
template<class AllocFwd>
|
||||
inline explicit small_vector_base(maybe_initial_capacity_t, size_type initial_capacity, size_type initial_size, BOOST_FWD_REF(AllocFwd) a)
|
||||
: base_type(maybe_initial_capacity_t()
|
||||
, (initial_capacity >= initial_size) ? this->internal_storage() : pointer()
|
||||
, (initial_capacity >= initial_size) ? initial_capacity : initial_size
|
||||
, ::boost::forward<AllocFwd>(a)
|
||||
)
|
||||
{}
|
||||
|
||||
void prot_shrink_to_fit_small(const size_type small_capacity)
|
||||
{ this->base_type::prot_shrink_to_fit_small(this->internal_storage(), small_capacity); }
|
||||
|
||||
using base_type::protected_set_size;
|
||||
|
||||
//~small_vector_base(){}
|
||||
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
inline void prot_swap(small_vector_base& other, size_type internal_capacity_value)
|
||||
{ this->base_type::prot_swap_small(other, internal_capacity_value); }
|
||||
|
||||
public:
|
||||
inline 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))); }
|
||||
|
||||
inline 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))); }
|
||||
|
||||
inline void swap(small_vector_base &other)
|
||||
{ return this->base_type::prot_swap_small(other, 0u); }
|
||||
|
||||
};
|
||||
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
//
|
||||
// small_vector_storage_definer
|
||||
//
|
||||
/////////////////////////////////////////////////////
|
||||
template<class T, std::size_t N, class Options>
|
||||
struct small_vector_storage_definer
|
||||
{
|
||||
typedef typename dtl::get_small_vector_opt<Options>::type options_t;
|
||||
BOOST_STATIC_CONSTEXPR std::size_t final_alignment =
|
||||
options_t::inplace_alignment ? options_t::inplace_alignment : dtl::alignment_of<T>::value;
|
||||
typedef small_vector_storage<T, N, final_alignment> type;
|
||||
};
|
||||
|
||||
|
||||
/// Figure out the offset of the first element. Idea taken from LLVM's SmallVector
|
||||
template <class T, class SecAlloc, class Options>
|
||||
struct small_vector_storage_offset
|
||||
{
|
||||
typedef small_vector_base<T, SecAlloc, Options> base_type;
|
||||
typedef typename small_vector_storage_definer<T, 1, Options>::type storage_type;
|
||||
typename dtl::aligned_storage
|
||||
< sizeof(base_type), dtl::alignment_of<base_type>::value
|
||||
>::type base;
|
||||
|
||||
typename dtl::aligned_storage
|
||||
< sizeof(storage_type), dtl::alignment_of<storage_type>::value
|
||||
> ::type storage;
|
||||
};
|
||||
|
||||
template <class T, class SecAlloc, class Options>
|
||||
inline std::size_t get_small_vector_storage_offset()
|
||||
{
|
||||
typedef small_vector_storage_offset<T, SecAlloc, Options> struct_type;
|
||||
return offsetof(struct_type, storage);
|
||||
}
|
||||
|
||||
#if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wcast-align"
|
||||
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
||||
#endif
|
||||
|
||||
//Internal storage hack
|
||||
template<class T, class VoidAlloc, class Options>
|
||||
inline typename small_vector_allocator<T, VoidAlloc, Options>::const_pointer
|
||||
small_vector_allocator<T, VoidAlloc, Options>::internal_storage() const BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{
|
||||
const vector_type& v = *static_cast<const vector_type*>(static_cast<const void *>(this));
|
||||
BOOST_ASSERT((std::size_t(this) % dtl::alignment_of< small_vector_storage_offset<T, allocator_type, Options> >::value) == 0);
|
||||
const char *addr = reinterpret_cast<const char*>(&v);
|
||||
typedef typename boost::intrusive::pointer_traits<pointer>::template rebind_pointer<const char>::type const_char_pointer;
|
||||
const_void_pointer vptr = boost::intrusive::pointer_traits<const_char_pointer>::pointer_to(*addr)
|
||||
+ get_small_vector_storage_offset<T, allocator_type, Options>();
|
||||
return boost::intrusive::pointer_traits<const_pointer>::static_cast_from(vptr);
|
||||
}
|
||||
|
||||
template <class T, class VoidAlloc, class Options>
|
||||
inline typename small_vector_allocator<T, VoidAlloc, Options>::pointer
|
||||
small_vector_allocator<T, VoidAlloc, Options>::internal_storage() BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{
|
||||
vector_type& v = *static_cast<vector_type*>(static_cast<void*>(this));
|
||||
BOOST_ASSERT((std::size_t(this) % dtl::alignment_of< small_vector_storage_offset<T, allocator_type, Options> >::value) == 0);
|
||||
char* addr = reinterpret_cast<char*>(&v);
|
||||
typedef typename boost::intrusive::pointer_traits<pointer>::template rebind_pointer<char>::type char_pointer;
|
||||
void_pointer vptr = boost::intrusive::pointer_traits<char_pointer>::pointer_to(*addr)
|
||||
+ get_small_vector_storage_offset<T, allocator_type, Options>();
|
||||
return boost::intrusive::pointer_traits<pointer>::static_cast_from(vptr);
|
||||
}
|
||||
|
||||
#if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#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, Options>` is convertible to `small_vector_base<T, Allocator, Options>` 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.
|
||||
//!
|
||||
//! Any change to the capacity of the vector, including decreasing its size such as with the shrink_to_fit method, will
|
||||
//! cause the vector to permanently switch to dynamically allocated storage.
|
||||
//!
|
||||
//! \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. Use void
|
||||
//! for the default allocator
|
||||
//! \tparam Options A type produced from \c boost::container::small_vector_options.
|
||||
template <class T, std::size_t N, class Allocator BOOST_CONTAINER_DOCONLY(= void), class Options BOOST_CONTAINER_DOCONLY(= void) >
|
||||
class small_vector
|
||||
: public small_vector_base<T, Allocator, Options>
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
, private small_vector_storage_definer<T, N, Options>::type
|
||||
#endif
|
||||
{
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
BOOST_COPYABLE_AND_MOVABLE(small_vector)
|
||||
|
||||
public:
|
||||
typedef dtl::true_type is_partially_propagable;
|
||||
typedef small_vector_base<T, Allocator, Options> base_type;
|
||||
typedef typename base_type::allocator_type allocator_type;
|
||||
typedef typename base_type::size_type size_type;
|
||||
typedef typename base_type::value_type value_type;
|
||||
|
||||
inline static size_type internal_capacity()
|
||||
{ return static_capacity; }
|
||||
|
||||
typedef allocator_traits<typename base_type::allocator_type> allocator_traits_type;
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
//! @brief The capacity/max size of the container
|
||||
BOOST_STATIC_CONSTEXPR size_type static_capacity = small_vector_storage_definer<T, N, Options>::type::sms_size;
|
||||
|
||||
public:
|
||||
inline small_vector()
|
||||
BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<allocator_type>::value)
|
||||
: base_type(initial_capacity_t(), internal_capacity())
|
||||
{}
|
||||
|
||||
inline explicit small_vector(const allocator_type &a)
|
||||
: base_type(initial_capacity_t(), internal_capacity(), a)
|
||||
{}
|
||||
|
||||
inline explicit small_vector(size_type n)
|
||||
: base_type(maybe_initial_capacity_t(), internal_capacity(), n)
|
||||
{ this->protected_init_n(n, value_init); }
|
||||
|
||||
inline small_vector(size_type n, const allocator_type &a)
|
||||
: base_type(maybe_initial_capacity_t(), internal_capacity(), n, a)
|
||||
{ this->protected_init_n(n, value_init); }
|
||||
|
||||
inline small_vector(size_type n, default_init_t)
|
||||
: base_type(maybe_initial_capacity_t(), internal_capacity(), n)
|
||||
{ this->protected_init_n(n, default_init_t()); }
|
||||
|
||||
inline small_vector(size_type n, default_init_t, const allocator_type &a)
|
||||
: base_type(maybe_initial_capacity_t(), internal_capacity(), n, a)
|
||||
{ this->protected_init_n(n, default_init_t()); }
|
||||
|
||||
inline small_vector(size_type n, const value_type &v)
|
||||
: base_type(maybe_initial_capacity_t(), internal_capacity(), n)
|
||||
{ this->protected_init_n(n, v); }
|
||||
|
||||
inline small_vector(size_type n, const value_type &v, const allocator_type &a)
|
||||
: base_type(maybe_initial_capacity_t(), internal_capacity(), n, a)
|
||||
{ this->protected_init_n(n, v); }
|
||||
|
||||
template <class InIt>
|
||||
inline small_vector(InIt first, InIt last
|
||||
BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_c
|
||||
< dtl::is_convertible<InIt BOOST_MOVE_I size_type>::value
|
||||
BOOST_MOVE_I dtl::nat >::type * = 0)
|
||||
)
|
||||
: base_type(initial_capacity_t(), internal_capacity())
|
||||
{ this->assign(first, last); }
|
||||
|
||||
template <class InIt>
|
||||
inline small_vector(InIt first, InIt last, const allocator_type& a
|
||||
BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_c
|
||||
< dtl::is_convertible<InIt BOOST_MOVE_I size_type>::value
|
||||
BOOST_MOVE_I dtl::nat >::type * = 0)
|
||||
)
|
||||
: base_type(initial_capacity_t(), internal_capacity(), a)
|
||||
{ this->assign(first, last); }
|
||||
|
||||
inline 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()); }
|
||||
|
||||
inline small_vector(const small_vector &other, const allocator_type &a)
|
||||
: base_type(initial_capacity_t(), internal_capacity(), a)
|
||||
{ this->assign(other.cbegin(), other.cend()); }
|
||||
|
||||
inline 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()); }
|
||||
|
||||
inline explicit small_vector(BOOST_RV_REF(base_type) other)
|
||||
: base_type(initial_capacity_t(), internal_capacity(), ::boost::move(other.get_stored_allocator()), other)
|
||||
{}
|
||||
|
||||
inline small_vector(BOOST_RV_REF(small_vector) other)
|
||||
BOOST_NOEXCEPT_IF(boost::container::dtl::is_nothrow_move_constructible<value_type>::value)
|
||||
: base_type(initial_capacity_t(), internal_capacity(), ::boost::move(other.get_stored_allocator()), other)
|
||||
{}
|
||||
|
||||
inline small_vector(BOOST_RV_REF(small_vector) other, const allocator_type &a)
|
||||
: base_type(initial_capacity_t(), internal_capacity(), a, other)
|
||||
{}
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
||||
inline 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
|
||||
|
||||
inline 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))); }
|
||||
|
||||
inline small_vector& operator=(BOOST_RV_REF(small_vector) other)
|
||||
BOOST_NOEXCEPT_IF(boost::container::dtl::is_nothrow_move_assignable<value_type>::value
|
||||
&& (allocator_traits_type::propagate_on_container_move_assignment::value
|
||||
|| allocator_traits_type::is_always_equal::value))
|
||||
{ return static_cast<small_vector&>(this->base_type::operator=(BOOST_MOVE_BASE(base_type, other))); }
|
||||
|
||||
inline small_vector& operator=(const base_type &other)
|
||||
{ return static_cast<small_vector&>(this->base_type::operator=(other)); }
|
||||
|
||||
inline small_vector& operator=(BOOST_RV_REF(base_type) other)
|
||||
{ return static_cast<small_vector&>(this->base_type::operator=(boost::move(other))); }
|
||||
|
||||
inline void swap(small_vector &other)
|
||||
{ return this->base_type::prot_swap(other, static_capacity); }
|
||||
|
||||
inline void shrink_to_fit()
|
||||
{ this->base_type::prot_shrink_to_fit_small(this->internal_capacity()); }
|
||||
};
|
||||
|
||||
//! <b>Effects</b>: Erases all elements that compare equal to v from the container c.
|
||||
//!
|
||||
//! <b>Complexity</b>: Linear.
|
||||
template <class T, std::size_t N, class A, class O, class U>
|
||||
inline typename small_vector<T, N, A, O>::size_type erase(small_vector<T, N, A, O>& c, const U& v)
|
||||
{
|
||||
typename small_vector<T, N, A, O>::size_type old_size = c.size();
|
||||
c.erase(boost::container::remove(c.begin(), c.end(), v), c.end());
|
||||
return old_size - c.size();
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Erases all elements that satisfy the predicate pred from the container c.
|
||||
//!
|
||||
//! <b>Complexity</b>: Linear.
|
||||
template <class T, std::size_t N, class A, class O, class Pred>
|
||||
inline typename small_vector<T, N, A, O>::size_type erase_if(small_vector<T, N, A, O>& c, Pred pred)
|
||||
{
|
||||
typename small_vector<T, N, A, O>::size_type old_size = c.size();
|
||||
c.erase(boost::container::remove_if(c.begin(), c.end(), pred), c.end());
|
||||
return old_size - c.size();
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
#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;
|
||||
BOOST_STATIC_CONSTEXPR 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
|
||||
2297
include/boost/container/stable_vector.hpp
Normal file
2297
include/boost/container/stable_vector.hpp
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user