Merge branch 'develop'

This commit is contained in:
Ion Gaztañaga
2014-02-14 19:58:30 +01:00
166 changed files with 23627 additions and 5227 deletions

View File

@@ -0,0 +1,390 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# 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/alloc_lib_auto_link.hpp>
#include <boost/container/detail/singleton.hpp>
#include <boost/iterator/transform_iterator.hpp>
#include <boost/assert.hpp>
#include <boost/utility/addressof.hpp>
#include <boost/static_assert.hpp>
#include <boost/move/move.hpp>
#include <memory>
#include <algorithm>
#include <cstddef>
#include <new>
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)
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
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
>
#else
template < class T
, std::size_t NodesPerBlock
, std::size_t MaxFreeBlocks
, std::size_t OverheadPercent
, unsigned Version
>
#endif
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
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
, Version
#endif
> self_t;
static const std::size_t nodes_per_block = NodesPerBlock;
static const std::size_t max_free_blocks = MaxFreeBlocks;
static const std::size_t overhead_percent = OverheadPercent;
static const std::size_t real_nodes_per_block = NodesPerBlock;
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
BOOST_STATIC_ASSERT((Version <=2));
#endif
public:
//-------
typedef T value_type;
typedef T * pointer;
typedef const T * const_pointer;
typedef typename ::boost::container::
container_detail::unvoid<T>::type & reference;
typedef const typename ::boost::container::
container_detail::unvoid<T>::type & const_reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef boost::container::container_detail::
version_type<self_t, Version> version;
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
typedef boost::container::container_detail::
basic_multiallocation_chain<void*> multiallocation_chain_void;
typedef boost::container::container_detail::
transform_multiallocation_chain
<multiallocation_chain_void, T> multiallocation_chain;
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//!Obtains adaptive_pool from
//!adaptive_pool
template<class T2>
struct rebind
{
typedef adaptive_pool
< T2
, NodesPerBlock
, MaxFreeBlocks
, OverheadPercent
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
, Version
#endif
> other;
};
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
//!Not assignable from related adaptive_pool
template<class T2, unsigned Version2, std::size_t N2, std::size_t F2>
adaptive_pool& operator=
(const adaptive_pool<T2, Version2, N2, F2>&);
//!Not assignable from other adaptive_pool
adaptive_pool& operator=(const adaptive_pool&);
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
public:
//!Default constructor
adaptive_pool() BOOST_CONTAINER_NOEXCEPT
{}
//!Copy constructor from other adaptive_pool.
adaptive_pool(const adaptive_pool &) BOOST_CONTAINER_NOEXCEPT
{}
//!Copy constructor from related adaptive_pool.
template<class T2>
adaptive_pool
(const adaptive_pool<T2, NodesPerBlock, MaxFreeBlocks, OverheadPercent
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
, Version
#endif
> &) BOOST_CONTAINER_NOEXCEPT
{}
//!Destructor
~adaptive_pool() BOOST_CONTAINER_NOEXCEPT
{}
//!Returns the number of elements that could be allocated.
//!Never throws
size_type max_size() const BOOST_CONTAINER_NOEXCEPT
{ return size_type(-1)/sizeof(T); }
//!Allocate memory for an array of count elements.
//!Throws std::bad_alloc if there is no enough memory
pointer allocate(size_type count, const void * = 0)
{
if(count > this->max_size())
boost::container::throw_bad_alloc();
if(Version == 1 && count == 1){
typedef typename container_detail::shared_adaptive_node_pool
<sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> shared_pool_t;
typedef container_detail::singleton_default<shared_pool_t> singleton_t;
return pointer(static_cast<T*>(singleton_t::instance().allocate_node()));
}
else{
return static_cast<pointer>(boost_cont_malloc(count*sizeof(T)));
}
}
//!Deallocate allocated memory.
//!Never throws
void deallocate(const pointer &ptr, size_type count) BOOST_CONTAINER_NOEXCEPT
{
(void)count;
if(Version == 1 && count == 1){
typedef container_detail::shared_adaptive_node_pool
<sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> shared_pool_t;
typedef container_detail::singleton_default<shared_pool_t> singleton_t;
singleton_t::instance().deallocate_node(ptr);
}
else{
boost_cont_free(ptr);
}
}
std::pair<pointer, bool>
allocation_command(allocation_type command,
size_type limit_size,
size_type preferred_size,
size_type &received_size, pointer reuse = pointer())
{
std::pair<pointer, bool> ret =
this->priv_allocation_command(command, limit_size, preferred_size, received_size, reuse);
if(!ret.first && !(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_CONTAINER_NOEXCEPT
{ return boost_cont_size(p); }
//!Allocates just one object. Memory allocated with this function
//!must be deallocated only with deallocate_one().
//!Throws bad_alloc if there is no enough memory
pointer allocate_one()
{
typedef container_detail::shared_adaptive_node_pool
<sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> shared_pool_t;
typedef container_detail::singleton_default<shared_pool_t> singleton_t;
return (pointer)singleton_t::instance().allocate_node();
}
//!Allocates many elements of size == 1.
//!Elements must be individually deallocated with deallocate_one()
void allocate_individual(std::size_t num_elements, multiallocation_chain &chain)
{
typedef container_detail::shared_adaptive_node_pool
<sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> shared_pool_t;
typedef container_detail::singleton_default<shared_pool_t> singleton_t;
singleton_t::instance().allocate_nodes(num_elements, static_cast<typename shared_pool_t::multiallocation_chain&>(chain));
//typename shared_pool_t::multiallocation_chain ch;
//singleton_t::instance().allocate_nodes(num_elements, ch);
//chain.incorporate_after
//(chain.before_begin(), (T*)&*ch.begin(), (T*)&*ch.last(), ch.size());
}
//!Deallocates memory previously allocated with allocate_one().
//!You should never use deallocate_one to deallocate memory allocated
//!with other functions different from allocate_one(). Never throws
void deallocate_one(pointer p) BOOST_CONTAINER_NOEXCEPT
{
typedef container_detail::shared_adaptive_node_pool
<sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> shared_pool_t;
typedef container_detail::singleton_default<shared_pool_t> singleton_t;
singleton_t::instance().deallocate_node(p);
}
void deallocate_individual(multiallocation_chain &chain) BOOST_CONTAINER_NOEXCEPT
{
typedef container_detail::shared_adaptive_node_pool
<sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> shared_pool_t;
typedef container_detail::singleton_default<shared_pool_t> singleton_t;
//typename shared_pool_t::multiallocation_chain ch(&*chain.begin(), &*chain.last(), chain.size());
//singleton_t::instance().deallocate_nodes(ch);
singleton_t::instance().deallocate_nodes(chain);
}
//!Allocates many elements of size elem_size.
//!Elements must be individually deallocated with deallocate()
void allocate_many(size_type elem_size, std::size_t n_elements, multiallocation_chain &chain)
{
BOOST_STATIC_ASSERT(( Version > 1 ));/*
boost_cont_memchain ch;
BOOST_CONTAINER_MEMCHAIN_INIT(&ch);
if(!boost_cont_multialloc_nodes(n_elements, elem_size*sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &ch)){
boost::container::throw_bad_alloc();
}
chain.incorporate_after(chain.before_begin()
,(T*)BOOST_CONTAINER_MEMCHAIN_FIRSTMEM(&ch)
,(T*)BOOST_CONTAINER_MEMCHAIN_LASTMEM(&ch)
,BOOST_CONTAINER_MEMCHAIN_SIZE(&ch) );*/
if(!boost_cont_multialloc_nodes(n_elements, elem_size*sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, reinterpret_cast<boost_cont_memchain *>(&chain))){
boost::container::throw_bad_alloc();
}
}
//!Allocates n_elements elements, each one of size elem_sizes[i]
//!Elements must be individually deallocated with deallocate()
void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain)
{
BOOST_STATIC_ASSERT(( Version > 1 ));/*
boost_cont_memchain ch;
BOOST_CONTAINER_MEMCHAIN_INIT(&ch);
if(!boost_cont_multialloc_arrays(n_elements, elem_sizes, sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &ch)){
boost::container::throw_bad_alloc();
}
chain.incorporate_after(chain.before_begin()
,(T*)BOOST_CONTAINER_MEMCHAIN_FIRSTMEM(&ch)
,(T*)BOOST_CONTAINER_MEMCHAIN_LASTMEM(&ch)
,BOOST_CONTAINER_MEMCHAIN_SIZE(&ch) );*/
if(!boost_cont_multialloc_arrays(n_elements, elem_sizes, sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, reinterpret_cast<boost_cont_memchain *>(&chain))){
boost::container::throw_bad_alloc();
}
}
void deallocate_many(multiallocation_chain &chain) BOOST_CONTAINER_NOEXCEPT
{/*
boost_cont_memchain ch;
void *beg(&*chain.begin()), *last(&*chain.last());
size_t size(chain.size());
BOOST_CONTAINER_MEMCHAIN_INIT_FROM(&ch, beg, last, size);
boost_cont_multidealloc(&ch);*/
boost_cont_multidealloc(reinterpret_cast<boost_cont_memchain *>(&chain));
}
//!Deallocates all free blocks of the pool
static void deallocate_free_blocks() BOOST_CONTAINER_NOEXCEPT
{
typedef container_detail::shared_adaptive_node_pool
<sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> shared_pool_t;
typedef container_detail::singleton_default<shared_pool_t> singleton_t;
singleton_t::instance().deallocate_free_blocks();
}
//!Swaps allocators. Does not throw. If each allocator is placed in a
//!different memory segment, the result is undefined.
friend void swap(adaptive_pool &, adaptive_pool &) BOOST_CONTAINER_NOEXCEPT
{}
//!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_CONTAINER_NOEXCEPT
{ 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_CONTAINER_NOEXCEPT
{ return false; }
/*
//!Returns address of mutable object.
//!Never throws
pointer address(reference value) const
{ return pointer(boost::addressof(value)); }
//!Returns address of non mutable object.
//!Never throws
const_pointer address(const_reference value) const
{ return const_pointer(boost::addressof(value)); }
//!Default construct an object.
//!Throws if T's default constructor throws
void construct(const pointer &ptr)
{ new(ptr) value_type; }
//!Construct a copy of the passed object.
//!Throws if T's copy constructor throws
void construct(pointer ptr, const_reference t)
{ new(ptr) value_type(t); }
//!Destroys object. Throws if object's
//!destructor throws
void destroy(const pointer &ptr)
{ (void)ptr; BOOST_ASSERT(ptr); (*ptr).~value_type(); }
*/
private:
std::pair<pointer, bool> priv_allocation_command
(allocation_type command, std::size_t limit_size
,std::size_t preferred_size,std::size_t &received_size, void *reuse_ptr)
{
boost_cont_command_ret_t ret = {0 , 0};
if(limit_size > this->max_size() || preferred_size > this->max_size()){
// ret.first = 0;
return std::pair<pointer, bool>(pointer(), false);
}
std::size_t l_size = limit_size*sizeof(T);
std::size_t p_size = preferred_size*sizeof(T);
std::size_t r_size;
{
ret = boost_cont_allocation_command(command, sizeof(T), l_size, p_size, &r_size, reuse_ptr);
}
received_size = r_size/sizeof(T);
return std::pair<pointer, bool>(static_cast<pointer>(ret.first), !!ret.second);
}
};
} //namespace container {
} //namespace boost {
#include <boost/container/detail/config_end.hpp>
#endif //#ifndef BOOST_CONTAINER_ADAPTIVE_POOL_HPP

View File

@@ -0,0 +1,368 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2007-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_ALLOCATOR_HPP
#define BOOST_CONTAINER_ALLOCATOR_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# 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/alloc_lib_auto_link.hpp>
#include <boost/container/detail/multiallocation_chain.hpp>
#include <boost/iterator/transform_iterator.hpp>
#include <boost/static_assert.hpp>
#include <cstddef>
#include <cassert>
#include <new>
namespace boost {
namespace container {
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
template<unsigned Version, unsigned int AllocationDisableMask>
class allocator<void, Version, AllocationDisableMask>
{
typedef allocator<void, Version, AllocationDisableMask> self_t;
public:
typedef void value_type;
typedef void * pointer;
typedef const void* const_pointer;
typedef int & reference;
typedef const int & const_reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef boost::container::container_detail::
version_type<self_t, Version> version;
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
typedef boost::container::container_detail::
basic_multiallocation_chain<void*> multiallocation_chain;
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//!Obtains an allocator that allocates
//!objects of type T2
template<class T2>
struct rebind
{
typedef allocator< T2
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
, Version, AllocationDisableMask
#endif
> other;
};
//!Default constructor
//!Never throws
allocator()
{}
//!Constructor from other allocator.
//!Never throws
allocator(const allocator &)
{}
//!Constructor from related allocator.
//!Never throws
template<class T2>
allocator(const allocator<T2, Version, AllocationDisableMask> &)
{}
};
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//!\file
//! 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.
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
template<class T>
#else
//! 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, unsigned int AllocationDisableMask>
#endif //#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
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>&);
//Not assignable from other allocator
allocator& operator=(const allocator&);
static const unsigned int ForbiddenMask =
BOOST_CONTAINER_ALLOCATE_NEW | BOOST_CONTAINER_EXPAND_BWD | BOOST_CONTAINER_EXPAND_FWD ;
//The mask can't disable all the allocation types
BOOST_STATIC_ASSERT(( (AllocationDisableMask & ForbiddenMask) != ForbiddenMask ));
//The mask is only valid for version 2 allocators
BOOST_STATIC_ASSERT(( Version != 1 || (AllocationDisableMask == 0) ));
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
public:
typedef T value_type;
typedef T * pointer;
typedef const T * const_pointer;
typedef T & reference;
typedef const T & const_reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef boost::container::container_detail::
version_type<self_t, Version> version;
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
typedef boost::container::container_detail::
basic_multiallocation_chain<void*> void_multiallocation_chain;
typedef boost::container::container_detail::
transform_multiallocation_chain
<void_multiallocation_chain, T> multiallocation_chain;
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//!Obtains an allocator that allocates
//!objects of type T2
template<class T2>
struct rebind
{
typedef allocator<T2, Version, AllocationDisableMask> other;
};
//!Default constructor
//!Never throws
allocator() BOOST_CONTAINER_NOEXCEPT
{}
//!Constructor from other allocator.
//!Never throws
allocator(const allocator &) BOOST_CONTAINER_NOEXCEPT
{}
//!Constructor from related allocator.
//!Never throws
template<class T2>
allocator(const allocator<T2
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
, Version, AllocationDisableMask
#endif
> &) BOOST_CONTAINER_NOEXCEPT
{}
//!Allocates memory for an array of count elements.
//!Throws std::bad_alloc if there is no enough memory
//!If Version is 2, this allocated memory can only be deallocated
//!with deallocate() or (for Version == 2) deallocate_many()
pointer allocate(size_type count, const void * hint= 0)
{
(void)hint;
if(count > this->max_size())
boost::container::throw_bad_alloc();
void *ret = boost_cont_malloc(count*sizeof(T));
if(!ret)
boost::container::throw_bad_alloc();
return static_cast<pointer>(ret);
}
//!Deallocates previously allocated memory.
//!Never throws
void deallocate(pointer ptr, size_type) BOOST_CONTAINER_NOEXCEPT
{ boost_cont_free(ptr); }
//!Returns the maximum number of elements that could be allocated.
//!Never throws
size_type max_size() const BOOST_CONTAINER_NOEXCEPT
{ return size_type(-1)/sizeof(T); }
//!Swaps two allocators, does nothing
//!because this allocator is stateless
friend void swap(self_t &, self_t &) BOOST_CONTAINER_NOEXCEPT
{}
//!An allocator always compares to true, as memory allocated with one
//!instance can be deallocated by another instance
friend bool operator==(const allocator &, const allocator &) BOOST_CONTAINER_NOEXCEPT
{ return true; }
//!An allocator always compares to false, as memory allocated with one
//!instance can be deallocated by another instance
friend bool operator!=(const allocator &, const allocator &) BOOST_CONTAINER_NOEXCEPT
{ 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
std::pair<pointer, bool>
allocation_command(allocation_type command,
size_type limit_size,
size_type preferred_size,
size_type &received_size, pointer reuse = pointer())
{
BOOST_STATIC_ASSERT(( Version > 1 ));
const allocation_type mask(AllocationDisableMask);
command &= ~mask;
std::pair<pointer, bool> ret =
priv_allocation_command(command, limit_size, preferred_size, received_size, reuse);
if(!ret.first && !(command & BOOST_CONTAINER_NOTHROW_ALLOCATION))
boost::container::throw_bad_alloc();
return ret;
}
//!Returns maximum the number of objects the previously allocated memory
//!pointed by p can hold.
//!Memory must not have been allocated with
//!allocate_one or allocate_individual.
//!This function is available only with Version == 2
size_type size(pointer p) const BOOST_CONTAINER_NOEXCEPT
{
BOOST_STATIC_ASSERT(( Version > 1 ));
return boost_cont_size(p);
}
//!Allocates just one object. Memory allocated with this function
//!must be deallocated only with deallocate_one().
//!Throws bad_alloc if there is no enough memory
//!This function is available only with Version == 2
pointer allocate_one()
{
BOOST_STATIC_ASSERT(( Version > 1 ));
return this->allocate(1);
}
//!Allocates many elements of size == 1.
//!Elements must be individually deallocated with deallocate_one()
//!This function is available only with Version == 2
void allocate_individual(std::size_t num_elements, multiallocation_chain &chain)
{
BOOST_STATIC_ASSERT(( Version > 1 ));
this->allocate_many(1, num_elements, chain);
}
//!Deallocates memory previously allocated with allocate_one().
//!You should never use deallocate_one to deallocate memory allocated
//!with other functions different from allocate_one() or allocate_individual.
//Never throws
void deallocate_one(pointer p) BOOST_CONTAINER_NOEXCEPT
{
BOOST_STATIC_ASSERT(( Version > 1 ));
return this->deallocate(p, 1);
}
//!Deallocates memory allocated with allocate_one() or allocate_individual().
//!This function is available only with Version == 2
void deallocate_individual(multiallocation_chain &chain) BOOST_CONTAINER_NOEXCEPT
{
BOOST_STATIC_ASSERT(( Version > 1 ));
return this->deallocate_many(chain);
}
//!Allocates many elements of size elem_size.
//!Elements must be individually deallocated with deallocate()
//!This function is available only with Version == 2
void allocate_many(size_type elem_size, std::size_t n_elements, multiallocation_chain &chain)
{
BOOST_STATIC_ASSERT(( Version > 1 ));/*
boost_cont_memchain ch;
BOOST_CONTAINER_MEMCHAIN_INIT(&ch);
if(!boost_cont_multialloc_nodes(n_elements, elem_size*sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &ch)){
boost::container::throw_bad_alloc();
}
chain.incorporate_after(chain.before_begin()
,(T*)BOOST_CONTAINER_MEMCHAIN_FIRSTMEM(&ch)
,(T*)BOOST_CONTAINER_MEMCHAIN_LASTMEM(&ch)
,BOOST_CONTAINER_MEMCHAIN_SIZE(&ch) );*/
if(!boost_cont_multialloc_nodes(n_elements, elem_size*sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, reinterpret_cast<boost_cont_memchain *>(&chain))){
boost::container::throw_bad_alloc();
}
}
//!Allocates n_elements elements, each one of size elem_sizes[i]
//!Elements must be individually deallocated with deallocate()
//!This function is available only with Version == 2
void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain)
{
BOOST_STATIC_ASSERT(( Version > 1 ));
boost_cont_memchain ch;
BOOST_CONTAINER_MEMCHAIN_INIT(&ch);
if(!boost_cont_multialloc_arrays(n_elements, elem_sizes, sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &ch)){
boost::container::throw_bad_alloc();
}
chain.incorporate_after(chain.before_begin()
,(T*)BOOST_CONTAINER_MEMCHAIN_FIRSTMEM(&ch)
,(T*)BOOST_CONTAINER_MEMCHAIN_LASTMEM(&ch)
,BOOST_CONTAINER_MEMCHAIN_SIZE(&ch) );
/*
if(!boost_cont_multialloc_arrays(n_elements, elem_sizes, sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, reinterpret_cast<boost_cont_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_CONTAINER_NOEXCEPT
{
BOOST_STATIC_ASSERT(( Version > 1 ));
boost_cont_memchain ch;
void *beg(&*chain.begin()), *last(&*chain.last());
size_t size(chain.size());
BOOST_CONTAINER_MEMCHAIN_INIT_FROM(&ch, beg, last, size);
boost_cont_multidealloc(&ch);
//boost_cont_multidealloc(reinterpret_cast<boost_cont_memchain *>(&chain));
}
private:
std::pair<pointer, bool> priv_allocation_command
(allocation_type command, std::size_t limit_size
,std::size_t preferred_size,std::size_t &received_size, void *reuse_ptr)
{
boost_cont_command_ret_t ret = {0 , 0};
if((limit_size > this->max_size()) | (preferred_size > this->max_size())){
return std::pair<pointer, bool>(pointer(), false);
}
std::size_t l_size = limit_size*sizeof(T);
std::size_t p_size = preferred_size*sizeof(T);
std::size_t r_size;
{
ret = boost_cont_allocation_command(command, sizeof(T), l_size, p_size, &r_size, reuse_ptr);
}
received_size = r_size/sizeof(T);
return std::pair<pointer, bool>(static_cast<pointer>(ret.first), !!ret.second);
}
};
} //namespace container {
} //namespace boost {
#include <boost/container/detail/config_end.hpp>
#endif //BOOST_CONTAINER_ALLOCATOR_HPP

View File

@@ -6,7 +6,7 @@
//
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2011-2012. Distributed under the Boost
// (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)
//
@@ -38,7 +38,7 @@
#include <boost/container/detail/preprocessor.hpp>
#endif
///@cond
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
namespace boost {
namespace container {
@@ -56,7 +56,7 @@ struct is_std_allocator< std::allocator<T> >
} //namespace container_detail {
///@endcond
#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
@@ -94,29 +94,29 @@ struct allocator_traits
//!
typedef see_documentation size_type;
//! Alloc::propagate_on_container_copy_assignment if such a type exists, otherwise an integral_constant
//! type with internal constant static member `value` == false.
//! type with internal constant static member <code>value</code> == false.
typedef see_documentation propagate_on_container_copy_assignment;
//! Alloc::propagate_on_container_move_assignment if such a type exists, otherwise an integral_constant
//! type with internal constant static member `value` == false.
//! type with internal constant static member <code>value</code> == false.
typedef see_documentation propagate_on_container_move_assignment;
//! Alloc::propagate_on_container_swap if such a type exists, otherwise an integral_constant
//! type with internal constant static member `value` == false.
//! type with internal constant static member <code>value</code> == false.
typedef see_documentation propagate_on_container_swap;
//! Defines an allocator: Alloc::rebind<T>::other if such a type exists; otherwise, Alloc<T, Args>
//! if Alloc is a class template instantiation of the form Alloc<U, Args>, where Args is zero or
//! more type arguments ; otherwise, the instantiation of rebind_alloc is ill-formed.
//!
//! In C++03 compilers `rebind_alloc` is a struct derived from an allocator
//! 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 `rebind_traits` is a struct derived from
//! `allocator_traits<OtherAlloc>`, where `OtherAlloc` is
//! the allocator deduced by rules explained in `rebind_alloc`.
//! 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.
//! `type` is an allocator related to Alloc deduced deduced by rules explained in `rebind_alloc`.
//! <code>type</code> is an allocator related to Alloc deduced deduced by rules explained in <code>rebind_alloc</code>.
template <class T>
struct portable_rebind_alloc
{ typedef see_documentation type; };
@@ -206,19 +206,19 @@ struct allocator_traits
{ typedef typename boost::intrusive::detail::type_rebinder<Alloc, T>::type type; };
#endif //BOOST_CONTAINER_DOXYGEN_INVOKED
//! <b>Returns</b>: `a.allocate(n)`
//! <b>Returns</b>: <code>a.allocate(n)</code>
//!
static pointer allocate(Alloc &a, size_type n)
{ return a.allocate(n); }
//! <b>Returns</b>: `a.deallocate(p, n)`
//! <b>Returns</b>: <code>a.deallocate(p, n)</code>
//!
//! <b>Throws</b>: Nothing
static void deallocate(Alloc &a, pointer p, size_type n)
{ a.deallocate(p, n); }
//! <b>Effects</b>: calls `a.allocate(n, p)` if that call is well-formed;
//! otherwise, invokes `a.allocate(n)`
//! <b>Effects</b>: calls <code>a.allocate(n, p)</code> if that call is well-formed;
//! otherwise, invokes <code>a.allocate(n)</code>
static pointer allocate(Alloc &a, size_type n, const_void_pointer p)
{
const bool value = boost::container::container_detail::
@@ -228,10 +228,10 @@ struct allocator_traits
return allocator_traits::priv_allocate(flag, a, n, p);
}
//! <b>Effects</b>: calls `a.destroy(p)` if that call is well-formed;
//! otherwise, invokes `p->~T()`.
//! <b>Effects</b>: calls <code>a.destroy(p)</code> if that call is well-formed;
//! otherwise, invokes <code>p->~T()</code>.
template<class T>
static void destroy(Alloc &a, T*p)
static void destroy(Alloc &a, T*p) BOOST_CONTAINER_NOEXCEPT
{
typedef T* destroy_pointer;
const bool value = boost::container::container_detail::
@@ -241,9 +241,9 @@ struct allocator_traits
allocator_traits::priv_destroy(flag, a, p);
}
//! <b>Returns</b>: `a.max_size()` if that expression is well-formed; otherwise,
//! `numeric_limits<size_type>::max()`.
static size_type max_size(const Alloc &a)
//! <b>Returns</b>: <code>a.max_size()</code> if that expression is well-formed; otherwise,
//! <code>numeric_limits<size_type>::max()</code>.
static size_type max_size(const Alloc &a) BOOST_CONTAINER_NOEXCEPT
{
const bool value = boost::container::container_detail::
has_member_function_callable_with_max_size
@@ -252,7 +252,7 @@ struct allocator_traits
return allocator_traits::priv_max_size(flag, a);
}
//! <b>Returns</b>: `a.select_on_container_copy_construction()` if that expression is well-formed;
//! <b>Returns</b>: <code>a.select_on_container_copy_construction()</code> if that expression is well-formed;
//! otherwise, a.
static
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
@@ -276,8 +276,8 @@ struct allocator_traits
}
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//! <b>Effects</b>: calls `a.construct(p, std::forward<Args>(args)...)` if that call is well-formed;
//! otherwise, invokes `::new (static_cast<void*>(p)) T(std::forward<Args>(args)...)`
//! <b>Effects</b>: calls <code>a.construct(p, std::forward<Args>(args)...)</code> if that call is well-formed;
//! otherwise, invokes <code>::new (static_cast<void*>(p)) T(std::forward<Args>(args)...)</code>
template <class T, class ...Args>
static void construct(Alloc & a, T* p, BOOST_FWD_REF(Args)... args)
{
@@ -285,7 +285,7 @@ struct allocator_traits
allocator_traits::priv_construct(flag, a, p, ::boost::forward<Args>(args)...);
}
#endif
///@cond
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
private:
static pointer priv_allocate(boost::true_type, Alloc &a, size_type n, const_void_pointer p)
@@ -295,23 +295,23 @@ struct allocator_traits
{ return allocator_traits::allocate(a, n); }
template<class T>
static void priv_destroy(boost::true_type, Alloc &a, T* p)
static void priv_destroy(boost::true_type, Alloc &a, T* p) BOOST_CONTAINER_NOEXCEPT
{ a.destroy(p); }
template<class T>
static void priv_destroy(boost::false_type, Alloc &, T* p)
static void priv_destroy(boost::false_type, Alloc &, T* p) BOOST_CONTAINER_NOEXCEPT
{ p->~T(); (void)p; }
static size_type priv_max_size(boost::true_type, const Alloc &a)
static size_type priv_max_size(boost::true_type, const Alloc &a) BOOST_CONTAINER_NOEXCEPT
{ return a.max_size(); }
static size_type priv_max_size(boost::false_type, const Alloc &)
static size_type priv_max_size(boost::false_type, const Alloc &) BOOST_CONTAINER_NOEXCEPT
{ return (std::numeric_limits<size_type>::max)(); }
static Alloc priv_select_on_container_copy_construction(boost::true_type, const Alloc &a)
{ return a.select_on_container_copy_construction(); }
static const Alloc &priv_select_on_container_copy_construction(boost::false_type, const Alloc &a)
static const Alloc &priv_select_on_container_copy_construction(boost::false_type, const Alloc &a) BOOST_CONTAINER_NOEXCEPT
{ return a; }
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
@@ -394,7 +394,7 @@ struct allocator_traits
{ ::new((void*)p) T; }
#endif //#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
///@endcond
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
};
} //namespace container {

View File

@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// (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)
//
@@ -15,11 +15,37 @@
# 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::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
//!
//! It forward declares the following allocators:
//! - boost::container::allocator
//! - boost::container::node_allocator
//! - boost::container::adaptive_pool
//!
//! And finally it defines the following types
//////////////////////////////////////////////////////////////////////////////
// Standard predeclarations
//////////////////////////////////////////////////////////////////////////////
/// @cond
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
namespace boost{
namespace intrusive{
@@ -32,13 +58,14 @@ namespace bi = boost::intrusive;
}}}
#include <cstddef>
#include <utility>
#include <memory>
#include <functional>
#include <iosfwd>
#include <string>
/// @endcond
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//////////////////////////////////////////////////////////////////////////////
// Containers
@@ -47,89 +74,146 @@ namespace bi = boost::intrusive;
namespace boost {
namespace container {
//vector class
//! Enumeration used to configure ordered associative containers
//! with a concrete tree implementation.
enum tree_type_enum
{
red_black_tree,
avl_tree,
scapegoat_tree,
splay_tree
};
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
template <class T
,class Allocator = std::allocator<T> >
class vector;
//vector class
template <class T
,class Allocator = std::allocator<T> >
class stable_vector;
//vector class
template <class T, std::size_t Capacity>
class static_vector;
template <class T
,class Allocator = std::allocator<T> >
class deque;
//list class
template <class T
,class Allocator = std::allocator<T> >
class list;
//slist class
template <class T
,class Allocator = std::allocator<T> >
class slist;
//set class
template<tree_type_enum TreeType, bool OptimizeSize>
struct tree_opt;
typedef tree_opt<red_black_tree, true> tree_assoc_defaults;
template <class Key
,class Compare = std::less<Key>
,class Allocator = std::allocator<Key> >
,class Allocator = std::allocator<Key>
,class Options = tree_assoc_defaults >
class set;
//multiset class
template <class Key
,class Compare = std::less<Key>
,class Allocator = std::allocator<Key> >
,class Allocator = std::allocator<Key>
,class Options = tree_assoc_defaults >
class multiset;
//map class
template <class Key
,class T
,class Compare = std::less<Key>
,class Allocator = std::allocator<std::pair<const Key, T> > >
,class Allocator = std::allocator<std::pair<const Key, T> >
,class Options = tree_assoc_defaults >
class map;
//multimap class
template <class Key
,class T
,class Compare = std::less<Key>
,class Allocator = std::allocator<std::pair<const Key, T> > >
,class Allocator = std::allocator<std::pair<const Key, T> >
,class Options = tree_assoc_defaults >
class multimap;
//flat_set class
template <class Key
,class Compare = std::less<Key>
,class Allocator = std::allocator<Key> >
class flat_set;
//flat_multiset class
template <class Key
,class Compare = std::less<Key>
,class Allocator = std::allocator<Key> >
class flat_multiset;
//flat_map class
template <class Key
,class T
,class Compare = std::less<Key>
,class Allocator = std::allocator<std::pair<Key, T> > >
class flat_map;
//flat_multimap class
template <class Key
,class T
,class Compare = std::less<Key>
,class Allocator = std::allocator<std::pair<Key, T> > >
class flat_multimap;
//basic_string class
template <class CharT
,class Traits = std::char_traits<CharT>
,class Allocator = std::allocator<CharT> >
class basic_string;
typedef basic_string
<char
,std::char_traits<char>
,std::allocator<char> >
string;
typedef basic_string
<wchar_t
,std::char_traits<wchar_t>
,std::allocator<wchar_t> >
wstring;
static const std::size_t ADP_nodes_per_block = 256u;
static const std::size_t ADP_max_free_blocks = 2u;
static const std::size_t ADP_overhead_percent = 1u;
static const std::size_t ADP_only_alignment = 0u;
template < class T
, std::size_t NodesPerBlock = ADP_nodes_per_block
, std::size_t MaxFreeBlocks = ADP_max_free_blocks
, std::size_t OverheadPercent = ADP_overhead_percent
, unsigned Version = 2
>
class adaptive_pool;
template < class T
, unsigned Version = 2
, unsigned int AllocationDisableMask = 0>
class allocator;
static const std::size_t NodeAlloc_nodes_per_block = 256u;
template
< class T
, std::size_t NodesPerBlock = NodeAlloc_nodes_per_block
, std::size_t Version = 2>
class node_allocator;
#else
//! Default options for tree-based associative containers
//! - tree_type<red_black_tree>
//! - optimize_size<true>
typedef implementation_defined tree_assoc_defaults;
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//! Type used to tag that the input range is
//! guaranteed to be ordered
struct ordered_range_t
@@ -149,17 +233,26 @@ struct ordered_unique_range_t
//! guaranteed to be ordered and unique
static const ordered_unique_range_t ordered_unique_range = ordered_unique_range_t();
//! Type used to tag that the input range is
//! guaranteed to be ordered and unique
//! Type used to tag that the inserted values
//! should be default initialized
struct default_init_t
{};
//! Value used to tag that the input range is
//! guaranteed to be ordered and unique
//! Value used to tag that the inserted values
//! should be default initialized
static const default_init_t default_init = default_init_t();
/// @cond
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
namespace detail_really_deep_namespace {
//! Type used to tag that the inserted values
//! should be value initialized
struct value_init_t
{};
//! Value used to tag that the inserted values
//! should be value initialized
static const value_init_t value_init = value_init_t();
namespace container_detail_really_deep_namespace {
//Otherwise, gcc issues a warning of previously defined
//anonymous_instance and unique_instance
@@ -175,7 +268,7 @@ struct dummy
} //detail_really_deep_namespace {
/// @endcond
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
}} //namespace boost { namespace container {

View File

@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// (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)
//
@@ -45,12 +45,8 @@
namespace boost {
namespace container {
/// @cond
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
template <class T, class Allocator = std::allocator<T> >
#else
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
template <class T, class Allocator>
#endif
class deque;
template <class T>
@@ -465,21 +461,24 @@ class deque_base
const allocator_type &alloc() const BOOST_CONTAINER_NOEXCEPT
{ return members_; }
};
/// @endcond
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//! Deque class
//!
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
//! A double-ended queue is a sequence that supports random access to elements, constant time insertion
//! and removal of elements at the end of the sequence, and linear time insertion and removal of elements in the middle.
//!
//! \tparam T The type of object that is stored in the deque
//! \tparam Allocator The allocator used for all internal memory management
template <class T, class Allocator = std::allocator<T> >
#else
template <class T, class Allocator>
#endif
class deque : protected deque_base<Allocator>
{
/// @cond
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
typedef deque_base<Allocator> Base;
/// @endcond
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
public:
@@ -503,7 +502,7 @@ class deque : protected deque_base<Allocator>
typedef BOOST_CONTAINER_IMPDEF(std::reverse_iterator<iterator>) reverse_iterator;
typedef BOOST_CONTAINER_IMPDEF(std::reverse_iterator<const_iterator>) const_reverse_iterator;
/// @cond
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private: // Internal typedefs
BOOST_COPYABLE_AND_MOVABLE(deque)
@@ -512,7 +511,7 @@ class deque : protected deque_base<Allocator>
{ return Base::s_buffer_size(); }
typedef allocator_traits<Allocator> allocator_traits_type;
/// @endcond
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
public:
//////////////////////////////////////////////
@@ -549,8 +548,8 @@ class deque : protected deque_base<Allocator>
explicit deque(size_type n)
: Base(n, allocator_type())
{
container_detail::insert_value_initialized_n_proxy<Allocator, iterator> proxy(this->alloc());
proxy.uninitialized_copy_n_and_update(this->begin(), n);
container_detail::insert_value_initialized_n_proxy<Allocator, iterator> proxy;
proxy.uninitialized_copy_n_and_update(this->alloc(), this->begin(), n);
//deque_base will deallocate in case of exception...
}
@@ -566,8 +565,8 @@ class deque : protected deque_base<Allocator>
deque(size_type n, default_init_t)
: Base(n, allocator_type())
{
container_detail::insert_default_initialized_n_proxy<Allocator, iterator> proxy(this->alloc());
proxy.uninitialized_copy_n_and_update(this->begin(), n);
container_detail::insert_default_initialized_n_proxy<Allocator, iterator> proxy;
proxy.uninitialized_copy_n_and_update(this->alloc(), this->begin(), n);
//deque_base will deallocate in case of exception...
}
@@ -978,7 +977,7 @@ class deque : protected deque_base<Allocator>
this->priv_erase_last_n(len - new_size);
else{
const size_type n = new_size - this->size();
container_detail::insert_value_initialized_n_proxy<Allocator, iterator> proxy(this->alloc());
container_detail::insert_value_initialized_n_proxy<Allocator, iterator> proxy;
priv_insert_back_aux_impl(n, proxy);
}
}
@@ -998,7 +997,7 @@ class deque : protected deque_base<Allocator>
this->priv_erase_last_n(len - new_size);
else{
const size_type n = new_size - this->size();
container_detail::insert_default_initialized_n_proxy<Allocator, iterator> proxy(this->alloc());
container_detail::insert_default_initialized_n_proxy<Allocator, iterator> proxy;
priv_insert_back_aux_impl(n, proxy);
}
}
@@ -1155,7 +1154,7 @@ class deque : protected deque_base<Allocator>
}
else{
typedef container_detail::insert_non_movable_emplace_proxy<Allocator, iterator, Args...> type;
this->priv_insert_front_aux_impl(1, type(this->alloc(), boost::forward<Args>(args)...));
this->priv_insert_front_aux_impl(1, type(boost::forward<Args>(args)...));
}
}
@@ -1177,7 +1176,7 @@ class deque : protected deque_base<Allocator>
}
else{
typedef container_detail::insert_non_movable_emplace_proxy<Allocator, iterator, Args...> type;
this->priv_insert_back_aux_impl(1, type(this->alloc(), boost::forward<Args>(args)...));
this->priv_insert_back_aux_impl(1, type(boost::forward<Args>(args)...));
}
}
@@ -1203,7 +1202,7 @@ class deque : protected deque_base<Allocator>
}
else{
typedef container_detail::insert_emplace_proxy<Allocator, iterator, Args...> type;
return this->priv_insert_aux_impl(p, 1, type(this->alloc(), boost::forward<Args>(args)...));
return this->priv_insert_aux_impl(p, 1, type(boost::forward<Args>(args)...));
}
}
@@ -1222,10 +1221,10 @@ class deque : protected deque_base<Allocator>
priv_push_front_simple_commit(); \
} \
else{ \
container_detail::BOOST_PP_CAT(insert_non_movable_emplace_proxy_arg, n) \
<Allocator, iterator BOOST_PP_ENUM_TRAILING_PARAMS(n, P)> proxy \
(this->alloc() BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \
priv_insert_front_aux_impl(1, proxy); \
typedef container_detail::BOOST_PP_CAT(insert_non_movable_emplace_proxy_arg, n) \
<Allocator, iterator BOOST_PP_ENUM_TRAILING_PARAMS(n, P)> type; \
priv_insert_front_aux_impl \
(1, type(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); \
} \
} \
\
@@ -1240,10 +1239,10 @@ class deque : protected deque_base<Allocator>
priv_push_back_simple_commit(); \
} \
else{ \
container_detail::BOOST_PP_CAT(insert_non_movable_emplace_proxy_arg, n) \
<Allocator, iterator BOOST_PP_ENUM_TRAILING_PARAMS(n, P)> proxy \
(this->alloc() BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \
priv_insert_back_aux_impl(1, proxy); \
typedef container_detail::BOOST_PP_CAT(insert_non_movable_emplace_proxy_arg, n) \
<Allocator, iterator BOOST_PP_ENUM_TRAILING_PARAMS(n, P)> type; \
priv_insert_back_aux_impl \
(1, type(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); \
} \
} \
\
@@ -1260,10 +1259,10 @@ class deque : protected deque_base<Allocator>
return (this->end()-1); \
} \
else{ \
container_detail::BOOST_PP_CAT(insert_emplace_proxy_arg, n) \
<Allocator, iterator BOOST_PP_ENUM_TRAILING_PARAMS(n, P)> proxy \
(this->alloc() BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \
return this->priv_insert_aux_impl(p, 1, proxy); \
typedef container_detail::BOOST_PP_CAT(insert_emplace_proxy_arg, n) \
<Allocator, iterator BOOST_PP_ENUM_TRAILING_PARAMS(n, P)> type; \
return this->priv_insert_aux_impl \
(p, 1, type(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); \
} \
} \
//!
@@ -1397,7 +1396,7 @@ class deque : protected deque_base<Allocator>
#endif
)
{
container_detail::insert_range_proxy<Allocator, FwdIt, iterator> proxy(this->alloc(), first);
container_detail::insert_range_proxy<Allocator, FwdIt, iterator> proxy(first);
return priv_insert_aux_impl(p, (size_type)std::distance(first, last), proxy);
}
#endif
@@ -1537,7 +1536,49 @@ class deque : protected deque_base<Allocator>
this->members_.m_finish = this->members_.m_start;
}
/// @cond
//! <b>Effects</b>: Returns true if x and y are equal
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator==(const deque& x, const deque& y)
{ return x.size() == y.size() && std::equal(x.begin(), x.end(), y.begin()); }
//! <b>Effects</b>: Returns true if x and y are unequal
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator!=(const deque& x, const deque& y)
{ return !(x == y); }
//! <b>Effects</b>: Returns true if x is less than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator<(const deque& x, const deque& y)
{ return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
//! <b>Effects</b>: Returns true if x is greater than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator>(const deque& x, const deque& y)
{ return y < x; }
//! <b>Effects</b>: Returns true if x is equal or less than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator<=(const deque& x, const deque& y)
{ return !(y < x); }
//! <b>Effects</b>: Returns true if x is equal or greater than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator>=(const deque& x, const deque& y)
{ return !(x < y); }
//! <b>Effects</b>: x.swap(y)
//!
//! <b>Complexity</b>: Constant.
friend void swap(deque& x, deque& y)
{ x.swap(y); }
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
void priv_erase_last_n(size_type n)
@@ -1570,7 +1611,8 @@ class deque : protected deque_base<Allocator>
}
else {
return priv_insert_aux_impl
(position, (size_type)1, container_detail::get_insert_value_proxy<iterator>(this->alloc(), ::boost::forward<U>(x)));
( position, (size_type)1
, container_detail::get_insert_value_proxy<iterator, Allocator>(::boost::forward<U>(x)));
}
}
@@ -1584,7 +1626,8 @@ class deque : protected deque_base<Allocator>
}
else{
priv_insert_aux_impl
(this->cbegin(), (size_type)1, container_detail::get_insert_value_proxy<iterator>(this->alloc(), ::boost::forward<U>(x)));
( this->cbegin(), (size_type)1
, container_detail::get_insert_value_proxy<iterator, Allocator>(::boost::forward<U>(x)));
}
}
@@ -1598,8 +1641,8 @@ class deque : protected deque_base<Allocator>
}
else{
priv_insert_aux_impl
(this->cend(), (size_type)1, container_detail::get_insert_value_proxy<iterator>(this->alloc(), ::boost::forward<U>(x)));
container_detail::insert_copy_proxy<Allocator, iterator> proxy(this->alloc(), x);
( this->cend(), (size_type)1
, container_detail::get_insert_value_proxy<iterator, Allocator>(::boost::forward<U>(x)));
}
}
@@ -1652,7 +1695,7 @@ class deque : protected deque_base<Allocator>
}
template<class InsertProxy>
iterator priv_insert_aux_impl(const_iterator p, size_type n, InsertProxy interf)
iterator priv_insert_aux_impl(const_iterator p, size_type n, InsertProxy proxy)
{
iterator pos(p.unconst());
const size_type pos_n = p - this->cbegin();
@@ -1667,7 +1710,7 @@ class deque : protected deque_base<Allocator>
const iterator new_start = this->priv_reserve_elements_at_front(n);
const iterator old_start = this->members_.m_start;
if(!elemsbefore){
interf.uninitialized_copy_n_and_update(new_start, n);
proxy.uninitialized_copy_n_and_update(this->alloc(), new_start, n);
this->members_.m_start = new_start;
}
else{
@@ -1678,17 +1721,17 @@ class deque : protected deque_base<Allocator>
(this->alloc(), this->members_.m_start, start_n, new_start);
this->members_.m_start = new_start;
boost::move(start_n, pos, old_start);
interf.copy_n_and_update(pos - n, n);
proxy.copy_n_and_update(this->alloc(), pos - n, n);
}
else {
const size_type mid_count = n - elemsbefore;
const iterator mid_start = old_start - mid_count;
interf.uninitialized_copy_n_and_update(mid_start, mid_count);
proxy.uninitialized_copy_n_and_update(this->alloc(), mid_start, mid_count);
this->members_.m_start = mid_start;
::boost::container::uninitialized_move_alloc
(this->alloc(), old_start, pos, new_start);
this->members_.m_start = new_start;
interf.copy_n_and_update(old_start, elemsbefore);
proxy.copy_n_and_update(this->alloc(), old_start, elemsbefore);
}
}
}
@@ -1697,7 +1740,7 @@ class deque : protected deque_base<Allocator>
const iterator old_finish = this->members_.m_finish;
const size_type elemsafter = length - elemsbefore;
if(!elemsafter){
interf.uninitialized_copy_n_and_update(old_finish, n);
proxy.uninitialized_copy_n_and_update(this->alloc(), old_finish, n);
this->members_.m_finish = new_finish;
}
else{
@@ -1708,15 +1751,15 @@ class deque : protected deque_base<Allocator>
(this->alloc(), finish_n, old_finish, old_finish);
this->members_.m_finish = new_finish;
boost::move_backward(pos, finish_n, old_finish);
interf.copy_n_and_update(pos, n);
proxy.copy_n_and_update(this->alloc(), pos, n);
}
else {
const size_type raw_gap = n - elemsafter;
::boost::container::uninitialized_move_alloc
(this->alloc(), pos, old_finish, old_finish + raw_gap);
BOOST_TRY{
interf.copy_n_and_update(pos, elemsafter);
interf.uninitialized_copy_n_and_update(old_finish, raw_gap);
proxy.copy_n_and_update(this->alloc(), pos, elemsafter);
proxy.uninitialized_copy_n_and_update(this->alloc(), old_finish, raw_gap);
}
BOOST_CATCH(...){
this->priv_destroy_range(old_finish, old_finish + elemsafter);
@@ -1731,7 +1774,7 @@ class deque : protected deque_base<Allocator>
}
template <class InsertProxy>
iterator priv_insert_back_aux_impl(size_type n, InsertProxy interf)
iterator priv_insert_back_aux_impl(size_type n, InsertProxy proxy)
{
if(!this->members_.m_map){
this->priv_initialize_map(0);
@@ -1739,20 +1782,20 @@ class deque : protected deque_base<Allocator>
iterator new_finish = this->priv_reserve_elements_at_back(n);
iterator old_finish = this->members_.m_finish;
interf.uninitialized_copy_n_and_update(old_finish, n);
proxy.uninitialized_copy_n_and_update(this->alloc(), old_finish, n);
this->members_.m_finish = new_finish;
return iterator(this->members_.m_finish - n);
}
template <class InsertProxy>
iterator priv_insert_front_aux_impl(size_type n, InsertProxy interf)
iterator priv_insert_front_aux_impl(size_type n, InsertProxy proxy)
{
if(!this->members_.m_map){
this->priv_initialize_map(0);
}
iterator new_start = this->priv_reserve_elements_at_front(n);
interf.uninitialized_copy_n_and_update(new_start, n);
proxy.uninitialized_copy_n_and_update(this->alloc(), new_start, n);
this->members_.m_start = new_start;
return new_start;
}
@@ -1934,45 +1977,12 @@ class deque : protected deque_base<Allocator>
this->members_.m_start.priv_set_node(new_nstart);
this->members_.m_finish.priv_set_node(new_nstart + old_num_nodes - 1);
}
/// @endcond
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
};
// Nonmember functions.
template <class T, class Allocator>
inline bool operator==(const deque<T, Allocator>& x, const deque<T, Allocator>& y) BOOST_CONTAINER_NOEXCEPT
{
return x.size() == y.size() && equal(x.begin(), x.end(), y.begin());
}
template <class T, class Allocator>
inline bool operator<(const deque<T, Allocator>& x, const deque<T, Allocator>& y) BOOST_CONTAINER_NOEXCEPT
{
return lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());
}
template <class T, class Allocator>
inline bool operator!=(const deque<T, Allocator>& x, const deque<T, Allocator>& y) BOOST_CONTAINER_NOEXCEPT
{ return !(x == y); }
template <class T, class Allocator>
inline bool operator>(const deque<T, Allocator>& x, const deque<T, Allocator>& y) BOOST_CONTAINER_NOEXCEPT
{ return y < x; }
template <class T, class Allocator>
inline bool operator>=(const deque<T, Allocator>& x, const deque<T, Allocator>& y) BOOST_CONTAINER_NOEXCEPT
{ return !(x < y); }
template <class T, class Allocator>
inline bool operator<=(const deque<T, Allocator>& x, const deque<T, Allocator>& y) BOOST_CONTAINER_NOEXCEPT
{ return !(y < x); }
template <class T, class Allocator>
inline void swap(deque<T, Allocator>& x, deque<T, Allocator>& y)
{ x.swap(y); }
}}
/// @cond
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
namespace boost {
@@ -1985,7 +1995,7 @@ struct has_trivial_destructor_after_move<boost::container::deque<T, Allocator> >
}
/// @endcond
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
#include <boost/container/detail/config_end.hpp>

View File

@@ -0,0 +1,162 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/intrusive/set.hpp>
#include <boost/aligned_storage.hpp>
#include <boost/container/detail/alloc_lib_auto_link.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 <cstddef>
#include <cmath>
#include <cassert>
#include <new>
namespace boost {
namespace container {
namespace container_detail {
template<bool AlignOnly>
struct select_private_adaptive_node_pool_impl
{
typedef boost::container::container_detail::
private_adaptive_node_pool_impl
< fake_segment_manager
, unsigned(AlignOnly)*::boost::container::adaptive_pool_flag::align_only
| ::boost::container::adaptive_pool_flag::size_ordered | ::boost::container::adaptive_pool_flag::address_ordered
> type;
};
//!Pooled memory allocator using an smart adaptive pool. Includes
//!a reference count but the class does not delete itself, this is
//!responsibility of user classes. Node size (NodeSize) and the number of
//!nodes allocated per block (NodesPerBlock) are known at compile time.
template< std::size_t NodeSize
, std::size_t NodesPerBlock
, std::size_t MaxFreeBlocks
, std::size_t OverheadPercent
>
class private_adaptive_node_pool
: public select_private_adaptive_node_pool_impl<(OverheadPercent == 0)>::type
{
typedef typename select_private_adaptive_node_pool_impl<OverheadPercent == 0>::type base_t;
//Non-copyable
private_adaptive_node_pool(const private_adaptive_node_pool &);
private_adaptive_node_pool &operator=(const private_adaptive_node_pool &);
public:
typedef typename base_t::multiallocation_chain multiallocation_chain;
static const std::size_t nodes_per_block = NodesPerBlock;
//!Constructor. Never throws
private_adaptive_node_pool()
: base_t(0
, NodeSize
, NodesPerBlock
, MaxFreeBlocks
, (unsigned char)OverheadPercent)
{}
};
//!Pooled memory allocator using adaptive pool. Includes
//!a reference count but the class does not delete itself, this is
//!responsibility of user classes. Node size (NodeSize) and the number of
//!nodes allocated per block (NodesPerBlock) are known at compile time
template< std::size_t NodeSize
, std::size_t NodesPerBlock
, std::size_t MaxFreeBlocks
, std::size_t OverheadPercent
>
class shared_adaptive_node_pool
: public private_adaptive_node_pool
<NodeSize, NodesPerBlock, MaxFreeBlocks, OverheadPercent>
{
private:
typedef private_adaptive_node_pool
<NodeSize, NodesPerBlock, MaxFreeBlocks, OverheadPercent> private_node_allocator_t;
public:
typedef typename private_node_allocator_t::multiallocation_chain multiallocation_chain;
//!Constructor. Never throws
shared_adaptive_node_pool()
: private_node_allocator_t(){}
//!Destructor. Deallocates all allocated blocks. Never throws
~shared_adaptive_node_pool()
{}
//!Allocates array of count elements. Can throw std::bad_alloc
void *allocate_node()
{
//-----------------------
scoped_lock<default_mutex> guard(mutex_);
//-----------------------
return private_node_allocator_t::allocate_node();
}
//!Deallocates an array pointed by ptr. Never throws
void deallocate_node(void *ptr)
{
//-----------------------
scoped_lock<default_mutex> guard(mutex_);
//-----------------------
private_node_allocator_t::deallocate_node(ptr);
}
//!Allocates a singly linked list of n nodes ending in null pointer.
//!can throw std::bad_alloc
void allocate_nodes(const std::size_t n, multiallocation_chain &chain)
{
//-----------------------
scoped_lock<default_mutex> guard(mutex_);
//-----------------------
return private_node_allocator_t::allocate_nodes(n, chain);
}
void deallocate_nodes(multiallocation_chain &chain)
{
//-----------------------
scoped_lock<default_mutex> guard(mutex_);
//-----------------------
private_node_allocator_t::deallocate_nodes(chain);
}
//!Deallocates all the free blocks of memory. Never throws
void deallocate_free_blocks()
{
//-----------------------
scoped_lock<default_mutex> guard(mutex_);
//-----------------------
private_node_allocator_t::deallocate_free_blocks();
}
private:
default_mutex mutex_;
};
} //namespace container_detail {
} //namespace container {
} //namespace boost {
#include <boost/container/detail/config_end.hpp>
#endif //#ifndef BOOST_CONTAINER_DETAIL_ADAPTIVE_NODE_POOL_HPP

View File

@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// (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)
//
@@ -15,9 +15,10 @@
# pragma once
#endif
#include "config_begin.hpp"
#include <boost/container/container_fwd.hpp>
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/container_fwd.hpp>
#include <boost/container/detail/utilities.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/intrusive/set.hpp>

View File

@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost
// (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)
//
@@ -15,8 +15,373 @@
# pragma once
#endif
#include "config_begin.hpp"
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/allocator_traits.hpp>
#include <boost/container/detail/destroyers.hpp>
#include <boost/aligned_storage.hpp>
#include <boost/move/utility.hpp>
#include <iterator> //std::iterator_traits
#include <boost/assert.hpp>
#include <boost/detail/no_exceptions_support.hpp>
namespace boost { namespace container { namespace container_detail {
template<class A, class FwdIt, class Iterator>
struct move_insert_range_proxy
{
typedef typename allocator_traits<A>::size_type size_type;
typedef typename allocator_traits<A>::value_type value_type;
explicit move_insert_range_proxy(FwdIt first)
: first_(first)
{}
void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n)
{
this->first_ = ::boost::container::uninitialized_move_alloc_n_source
(a, this->first_, n, p);
}
void copy_n_and_update(A &, Iterator p, size_type n)
{
this->first_ = ::boost::container::move_n_source(this->first_, n, p);
}
FwdIt first_;
};
template<class A, class FwdIt, class Iterator>
struct insert_range_proxy
{
typedef typename allocator_traits<A>::size_type size_type;
typedef typename allocator_traits<A>::value_type value_type;
explicit insert_range_proxy(FwdIt first)
: first_(first)
{}
void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n)
{
this->first_ = ::boost::container::uninitialized_copy_alloc_n_source(a, this->first_, n, p);
}
void copy_n_and_update(A &, Iterator p, size_type n)
{
this->first_ = ::boost::container::copy_n_source(this->first_, n, p);
}
FwdIt first_;
};
template<class A, class Iterator>
struct insert_n_copies_proxy
{
typedef typename allocator_traits<A>::size_type size_type;
typedef typename allocator_traits<A>::value_type value_type;
explicit insert_n_copies_proxy(const value_type &v)
: v_(v)
{}
void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n) const
{ boost::container::uninitialized_fill_alloc_n(a, v_, n, p); }
void copy_n_and_update(A &, Iterator p, size_type n) const
{ std::fill_n(p, n, v_); }
const value_type &v_;
};
template<class A, class Iterator>
struct insert_value_initialized_n_proxy
{
typedef ::boost::container::allocator_traits<A> alloc_traits;
typedef typename allocator_traits<A>::size_type size_type;
typedef typename allocator_traits<A>::value_type value_type;
void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n) const
{ boost::container::uninitialized_value_init_alloc_n(a, n, p); }
void copy_n_and_update(A &, Iterator, size_type) const
{ BOOST_ASSERT(false); }
};
template<class A, class Iterator>
struct insert_default_initialized_n_proxy
{
typedef ::boost::container::allocator_traits<A> alloc_traits;
typedef typename allocator_traits<A>::size_type size_type;
typedef typename allocator_traits<A>::value_type value_type;
void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n) const
{ boost::container::uninitialized_default_init_alloc_n(a, n, p); }
void copy_n_and_update(A &, Iterator, size_type) const
{ BOOST_ASSERT(false); }
};
template<class A, class Iterator>
struct insert_copy_proxy
{
typedef boost::container::allocator_traits<A> alloc_traits;
typedef typename alloc_traits::size_type size_type;
typedef typename alloc_traits::value_type value_type;
explicit insert_copy_proxy(const value_type &v)
: v_(v)
{}
void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n) const
{
BOOST_ASSERT(n == 1); (void)n;
alloc_traits::construct( a, container_detail::to_raw_pointer(&*p), v_);
}
void copy_n_and_update(A &, Iterator p, size_type n) const
{
BOOST_ASSERT(n == 1); (void)n;
*p =v_;
}
const value_type &v_;
};
template<class A, class Iterator>
struct insert_move_proxy
{
typedef boost::container::allocator_traits<A> alloc_traits;
typedef typename alloc_traits::size_type size_type;
typedef typename alloc_traits::value_type value_type;
explicit insert_move_proxy(value_type &v)
: v_(v)
{}
void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n) const
{
BOOST_ASSERT(n == 1); (void)n;
alloc_traits::construct( a
, container_detail::to_raw_pointer(&*p)
, ::boost::move(v_)
);
}
void copy_n_and_update(A &, Iterator p, size_type n) const
{
BOOST_ASSERT(n == 1); (void)n;
*p = ::boost::move(v_);
}
value_type &v_;
};
template<class It, class A>
insert_move_proxy<A, It> get_insert_value_proxy(BOOST_RV_REF(typename std::iterator_traits<It>::value_type) v)
{
return insert_move_proxy<A, It>(v);
}
template<class It, class A>
insert_copy_proxy<A, It> get_insert_value_proxy(const typename std::iterator_traits<It>::value_type &v)
{
return insert_copy_proxy<A, It>(v);
}
}}} //namespace boost { namespace container { namespace container_detail {
#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
#include <boost/container/detail/variadic_templates_tools.hpp>
#include <boost/move/utility.hpp>
#include <typeinfo>
//#include <iostream> //For debugging purposes
namespace boost {
namespace container {
namespace container_detail {
template<class A, class Iterator, class ...Args>
struct insert_non_movable_emplace_proxy
{
typedef boost::container::allocator_traits<A> alloc_traits;
typedef typename alloc_traits::size_type size_type;
typedef typename alloc_traits::value_type value_type;
typedef typename build_number_seq<sizeof...(Args)>::type index_tuple_t;
explicit insert_non_movable_emplace_proxy(Args&&... args)
: args_(args...)
{}
void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n)
{ this->priv_uninitialized_copy_some_and_update(a, index_tuple_t(), p, n); }
private:
template<int ...IdxPack>
void priv_uninitialized_copy_some_and_update(A &a, const index_tuple<IdxPack...>&, Iterator p, size_type n)
{
BOOST_ASSERT(n == 1); (void)n;
alloc_traits::construct( a
, container_detail::to_raw_pointer(&*p)
, ::boost::forward<Args>(get<IdxPack>(this->args_))...
);
}
protected:
tuple<Args&...> args_;
};
template<class A, class Iterator, class ...Args>
struct insert_emplace_proxy
: public insert_non_movable_emplace_proxy<A, Iterator, Args...>
{
typedef insert_non_movable_emplace_proxy<A, Iterator, Args...> base_t;
typedef boost::container::allocator_traits<A> alloc_traits;
typedef typename base_t::value_type value_type;
typedef typename base_t::size_type size_type;
typedef typename base_t::index_tuple_t index_tuple_t;
explicit insert_emplace_proxy(Args&&... args)
: base_t(::boost::forward<Args>(args)...)
{}
void copy_n_and_update(A &a, Iterator p, size_type n)
{ this->priv_copy_some_and_update(a, index_tuple_t(), p, n); }
private:
template<int ...IdxPack>
void priv_copy_some_and_update(A &a, const index_tuple<IdxPack...>&, Iterator p, size_type n)
{
BOOST_ASSERT(n ==1); (void)n;
aligned_storage<sizeof(value_type), alignment_of<value_type>::value> v;
value_type *vp = static_cast<value_type *>(static_cast<void *>(&v));
alloc_traits::construct(a, vp,
::boost::forward<Args>(get<IdxPack>(this->args_))...);
BOOST_TRY{
*p = ::boost::move(*vp);
}
BOOST_CATCH(...){
alloc_traits::destroy(a, vp);
BOOST_RETHROW
}
BOOST_CATCH_END
alloc_traits::destroy(a, vp);
}
};
}}} //namespace boost { namespace container { namespace container_detail {
#else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
#include <boost/container/detail/preprocessor.hpp>
#include <boost/container/detail/value_init.hpp>
namespace boost {
namespace container {
namespace container_detail {
#define BOOST_PP_LOCAL_MACRO(N) \
template<class A, class Iterator BOOST_PP_ENUM_TRAILING_PARAMS(N, class P) > \
struct BOOST_PP_CAT(insert_non_movable_emplace_proxy_arg, N) \
{ \
typedef boost::container::allocator_traits<A> alloc_traits; \
typedef typename alloc_traits::size_type size_type; \
typedef typename alloc_traits::value_type value_type; \
\
explicit BOOST_PP_CAT(insert_non_movable_emplace_proxy_arg, N) \
( BOOST_PP_ENUM(N, BOOST_CONTAINER_PP_PARAM_LIST, _) ) \
BOOST_PP_EXPR_IF(N, :) BOOST_PP_ENUM(N, BOOST_CONTAINER_PP_PARAM_INIT, _) \
{} \
\
void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n) \
{ \
BOOST_ASSERT(n == 1); (void)n; \
alloc_traits::construct \
( a \
, container_detail::to_raw_pointer(&*p) \
BOOST_PP_ENUM_TRAILING(N, BOOST_CONTAINER_PP_MEMBER_FORWARD, _) \
); \
} \
\
void copy_n_and_update(A &, Iterator, size_type) \
{ BOOST_ASSERT(false); } \
\
protected: \
BOOST_PP_REPEAT(N, BOOST_CONTAINER_PP_PARAM_DEFINE, _) \
}; \
\
template<class A, class Iterator BOOST_PP_ENUM_TRAILING_PARAMS(N, class P) > \
struct BOOST_PP_CAT(insert_emplace_proxy_arg, N) \
: BOOST_PP_CAT(insert_non_movable_emplace_proxy_arg, N) \
< A, Iterator BOOST_PP_ENUM_TRAILING_PARAMS(N, P) > \
{ \
typedef BOOST_PP_CAT(insert_non_movable_emplace_proxy_arg, N) \
<A, Iterator BOOST_PP_ENUM_TRAILING_PARAMS(N, P) > base_t; \
typedef typename base_t::value_type value_type; \
typedef typename base_t::size_type size_type; \
typedef boost::container::allocator_traits<A> alloc_traits; \
\
explicit BOOST_PP_CAT(insert_emplace_proxy_arg, N) \
( BOOST_PP_ENUM(N, BOOST_CONTAINER_PP_PARAM_LIST, _) ) \
: base_t(BOOST_PP_ENUM(N, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ) \
{} \
\
void copy_n_and_update(A &a, Iterator p, size_type n) \
{ \
BOOST_ASSERT(n == 1); (void)n; \
aligned_storage<sizeof(value_type), alignment_of<value_type>::value> v; \
value_type *vp = static_cast<value_type *>(static_cast<void *>(&v)); \
alloc_traits::construct(a, vp \
BOOST_PP_ENUM_TRAILING(N, BOOST_CONTAINER_PP_MEMBER_FORWARD, _)); \
BOOST_TRY{ \
*p = ::boost::move(*vp); \
} \
BOOST_CATCH(...){ \
alloc_traits::destroy(a, vp); \
BOOST_RETHROW \
} \
BOOST_CATCH_END \
alloc_traits::destroy(a, vp); \
} \
}; \
//!
#define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
#include BOOST_PP_LOCAL_ITERATE()
}}} //namespace boost { namespace container { namespace container_detail {
#endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
#include <boost/container/detail/config_end.hpp>
#endif //#ifndef BOOST_CONTAINER_ADVANCED_INSERT_INT_HPP
/*
//////////////////////////////////////////////////////////////////////////////
//
// (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
#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/detail/destroyers.hpp>
#include <boost/aligned_storage.hpp>
@@ -391,3 +756,4 @@ struct BOOST_PP_CAT(insert_emplace_proxy_arg, N)
#include <boost/container/detail/config_end.hpp>
#endif //#ifndef BOOST_CONTAINER_ADVANCED_INSERT_INT_HPP
*/

View File

@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2012.
// (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
@@ -17,7 +17,7 @@
# pragma once
#endif
#include "config_begin.hpp"
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/type_traits/has_trivial_copy.hpp>

View File

@@ -0,0 +1,326 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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)
/*
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 __declspec(dllexport)
#else
# define BOOST_CONTAINER_DECL __declspec(dllimport)
#endif /* BOOST_CONTAINER_SOURCE */
#endif /* DYN_LINK */
#endif /* _MSC_VER */
/* if BOOST_CONTAINER_DECL isn't defined yet define it now: */
#ifndef BOOST_CONTAINER_DECL
#define BOOST_CONTAINER_DECL
#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)\
/**/
BOOST_CONTAINER_DECL size_t boost_cont_size(const void *p);
BOOST_CONTAINER_DECL void* boost_cont_malloc(size_t bytes);
BOOST_CONTAINER_DECL void boost_cont_free(void* mem);
BOOST_CONTAINER_DECL void* boost_cont_memalign(size_t bytes, size_t alignment);
/*!Indicates the all elements allocated by boost_cont_multialloc_nodes or boost_cont_multialloc_arrays
must be contiguous.*/
#define DL_MULTIALLOC_ALL_CONTIGUOUS ((size_t)(-1))
/*!Indicates the number of contiguous elements allocated by boost_cont_multialloc_nodes or boost_cont_multialloc_arrays
should be selected by those functions.*/
#define DL_MULTIALLOC_DEFAULT_CONTIGUOUS ((size_t)(0))
BOOST_CONTAINER_DECL int boost_cont_multialloc_nodes
(size_t n_elements, size_t elem_size, size_t contiguous_elements, boost_cont_memchain *pchain);
BOOST_CONTAINER_DECL 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);
BOOST_CONTAINER_DECL void boost_cont_multidealloc(boost_cont_memchain *pchain);
BOOST_CONTAINER_DECL size_t boost_cont_footprint();
BOOST_CONTAINER_DECL size_t boost_cont_allocated_memory();
BOOST_CONTAINER_DECL size_t boost_cont_chunksize(const void *p);
BOOST_CONTAINER_DECL int boost_cont_all_deallocated();
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;
BOOST_CONTAINER_DECL boost_cont_malloc_stats_t boost_cont_malloc_stats();
BOOST_CONTAINER_DECL size_t boost_cont_in_use_memory();
BOOST_CONTAINER_DECL int boost_cont_trim(size_t pad);
BOOST_CONTAINER_DECL int boost_cont_mallopt
(int parameter_number, int parameter_value);
BOOST_CONTAINER_DECL int boost_cont_grow
(void* oldmem, size_t minbytes, size_t maxbytes, size_t *received);
BOOST_CONTAINER_DECL int boost_cont_shrink
(void* oldmem, size_t minbytes, size_t maxbytes, size_t *received, int do_commit);
BOOST_CONTAINER_DECL void* boost_cont_alloc
(size_t minbytes, size_t preferred_bytes, size_t *received_bytes);
BOOST_CONTAINER_DECL int boost_cont_malloc_check();
typedef unsigned int allocation_type;
enum
{
// constants for allocation commands
BOOST_CONTAINER_ALLOCATE_NEW = 0X01,
BOOST_CONTAINER_EXPAND_FWD = 0X02,
BOOST_CONTAINER_EXPAND_BWD = 0X04,
BOOST_CONTAINER_SHRINK_IN_PLACE = 0X08,
BOOST_CONTAINER_NOTHROW_ALLOCATION = 0X10,
// BOOST_CONTAINER_ZERO_MEMORY = 0X20,
BOOST_CONTAINER_TRY_SHRINK_IN_PLACE = 0X40,
BOOST_CONTAINER_EXPAND_BOTH = BOOST_CONTAINER_EXPAND_FWD | BOOST_CONTAINER_EXPAND_BWD,
BOOST_CONTAINER_EXPAND_OR_NEW = BOOST_CONTAINER_ALLOCATE_NEW | BOOST_CONTAINER_EXPAND_BOTH
};
//#define BOOST_CONTAINERDLMALLOC__FOOTERS
#ifndef BOOST_CONTAINERDLMALLOC__FOOTERS
enum { BOOST_CONTAINER_ALLOCATION_PAYLOAD = sizeof(size_t) };
#else
enum { BOOST_CONTAINER_ALLOCATION_PAYLOAD = sizeof(size_t)*2 };
#endif
typedef struct boost_cont_command_ret_impl
{
void *first;
int second;
}boost_cont_command_ret_t;
BOOST_CONTAINER_DECL 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
);
BOOST_CONTAINER_DECL int boost_cont_mallopt(int param_number, int value);
#ifdef __cplusplus
} //extern "C" {
#endif
#ifdef _MSC_VER
#pragma warning (pop)
#endif
#endif //#define BOOST_CONTAINERDLMALLOC__EXT_H

View 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.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_DETAIL_BOOST_CONT_EXT_AUTO_LINK_HPP
#define BOOST_CONTAINER_DETAIL_BOOST_CONT_EXT_AUTO_LINK_HPP
#include <boost/container/detail/auto_link.hpp>
#include <boost/container/detail/alloc_lib.h>
#endif //#ifndef BOOST_CONTAINER_DETAIL_BOOST_CONT_EXT_AUTO_LINK_HPP

View File

@@ -1,6 +1,6 @@
///////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// (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)
//
@@ -15,13 +15,13 @@
# pragma once
#endif
#include "config_begin.hpp"
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
namespace boost {
namespace container {
/// @cond
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
enum allocation_type_v
{
// constants for allocation commands
@@ -37,7 +37,7 @@ enum allocation_type_v
};
typedef int allocation_type;
/// @endcond
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
static const allocation_type allocate_new = (allocation_type)allocate_new_v;
static const allocation_type expand_fwd = (allocation_type)expand_fwd_v;
static const allocation_type expand_bwd = (allocation_type)expand_bwd_v;

View File

@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2012-2012. Distributed under the Boost
// (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)
//
@@ -17,6 +17,7 @@
#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

View File

@@ -0,0 +1,38 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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
#if defined(_MSC_VER)
# pragma once
#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_ALL_DYN_LINK) || defined(BOOST_CONTAINER_DYN_LINK)
# 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

View File

@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// (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)
//
@@ -18,6 +18,10 @@
#define BOOST_CONTAINER_DETAIL_CRT_SECURE_NO_DEPRECATE
#define _CRT_SECURE_NO_DEPRECATE
#endif
#ifndef _SCL_SECURE_NO_WARNINGS
#define BOOST_CONTAINER_DETAIL_SCL_SECURE_NO_WARNINGS
#define _SCL_SECURE_NO_WARNINGS
#endif
#pragma warning (push)
#pragma warning (disable : 4702) // unreachable code
#pragma warning (disable : 4706) // assignment within conditional expression

View File

@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// (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)
//
@@ -13,5 +13,9 @@
#undef BOOST_CONTAINER_DETAIL_CRT_SECURE_NO_DEPRECATE
#undef _CRT_SECURE_NO_DEPRECATE
#endif
#ifdef BOOST_CONTAINER_DETAIL_SCL_SECURE_NO_WARNINGS
#undef BOOST_CONTAINER_DETAIL_SCL_SECURE_NO_WARNINGS
#undef _SCL_SECURE_NO_WARNINGS
#endif
#endif

View File

@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2012.
// (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
@@ -17,8 +17,9 @@
# pragma once
#endif
#include "config_begin.hpp"
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/detail/version_type.hpp>
#include <boost/container/detail/utilities.hpp>
#include <boost/container/allocator_traits.hpp>
@@ -231,6 +232,9 @@ struct null_scoped_destructor_n
void increment_size_backwards(size_type)
{}
void shrink_forward(size_type)
{}
void release()
{}
};

View File

@@ -1,6 +1,6 @@
////////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// (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)
//
@@ -15,7 +15,7 @@
# pragma once
#endif
#include "config_begin.hpp"
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/container_fwd.hpp>
@@ -270,6 +270,9 @@ class flat_tree
Compare key_comp() const
{ return this->m_data.get_comp(); }
value_compare value_comp() const
{ return this->m_data; }
allocator_type get_allocator() const
{ return this->m_data.m_vect.get_allocator(); }
@@ -526,7 +529,7 @@ class flat_tree
this->reserve(this->size()+len);
const const_iterator b(this->cbegin());
const_iterator pos(b);
const value_compare &value_comp = this->m_data;
const value_compare &val_cmp = this->m_data;
skips[0u] = 0u;
//Loop in burst sizes
while(len){
@@ -539,7 +542,7 @@ class flat_tree
--len;
pos = const_cast<const flat_tree&>(*this).priv_lower_bound(pos, ce, KeyOfValue()(val));
//Check if already present
if(pos != ce && !value_comp(val, *pos)){
if(pos != ce && !val_cmp(val, *pos)){
if(unique_burst > 0){
++skips[unique_burst-1];
}
@@ -714,6 +717,7 @@ class flat_tree
return i;
}
// set operations:
size_type count(const key_type& k) const
{
std::pair<const_iterator, const_iterator> p = this->equal_range(k);
@@ -739,12 +743,44 @@ class flat_tree
std::pair<const_iterator, const_iterator> equal_range(const key_type& k) const
{ return this->priv_equal_range(this->cbegin(), this->cend(), k); }
std::pair<iterator, iterator> lower_bound_range(const key_type& k)
{ return this->priv_lower_bound_range(this->begin(), this->end(), k); }
std::pair<const_iterator, const_iterator> lower_bound_range(const key_type& k) const
{ return this->priv_lower_bound_range(this->cbegin(), this->cend(), k); }
size_type capacity() const
{ return this->m_data.m_vect.capacity(); }
void reserve(size_type cnt)
{ this->m_data.m_vect.reserve(cnt); }
friend bool operator==(const flat_tree& x, const flat_tree& y)
{
return x.size() == y.size() && std::equal(x.begin(), x.end(), y.begin());
}
friend bool operator<(const flat_tree& x, const flat_tree& y)
{
return std::lexicographical_compare(x.begin(), x.end(),
y.begin(), y.end());
}
friend bool operator!=(const flat_tree& x, const flat_tree& y)
{ return !(x == y); }
friend bool operator>(const flat_tree& x, const flat_tree& y)
{ return y < x; }
friend bool operator<=(const flat_tree& x, const flat_tree& y)
{ return !(y < x); }
friend bool operator>=(const flat_tree& x, const flat_tree& y)
{ return !(x < y); }
friend void swap(flat_tree& x, flat_tree& y)
{ x.swap(y); }
private:
struct insert_commit_data
{
@@ -764,10 +800,10 @@ class flat_tree
// insert val before upper_bound(val)
// else
// insert val before lower_bound(val)
const value_compare &value_comp = this->m_data;
const value_compare &val_cmp = this->m_data;
if(pos == this->cend() || !value_comp(*pos, val)){
if (pos == this->cbegin() || !value_comp(val, pos[-1])){
if(pos == this->cend() || !val_cmp(*pos, val)){
if (pos == this->cbegin() || !val_cmp(val, pos[-1])){
data.position = pos;
}
else{
@@ -784,9 +820,9 @@ class flat_tree
bool priv_insert_unique_prepare
(const_iterator b, const_iterator e, const value_type& val, insert_commit_data &commit_data)
{
const value_compare &value_comp = this->m_data;
const value_compare &val_cmp = this->m_data;
commit_data.position = this->priv_lower_bound(b, e, KeyOfValue()(val));
return commit_data.position == e || value_comp(val, *commit_data.position);
return commit_data.position == e || val_cmp(val, *commit_data.position);
}
bool priv_insert_unique_prepare
@@ -807,9 +843,9 @@ class flat_tree
// insert val after pos
//else
// insert val before lower_bound(val)
const value_compare &value_comp = this->m_data;
const value_compare &val_cmp = this->m_data;
const const_iterator cend_it = this->cend();
if(pos == cend_it || value_comp(val, *pos)){ //Check if val should go before end
if(pos == cend_it || val_cmp(val, *pos)){ //Check if val should go before end
const const_iterator cbeg = this->cbegin();
commit_data.position = pos;
if(pos == cbeg){ //If container is empty then insert it in the beginning
@@ -817,10 +853,10 @@ class flat_tree
}
const_iterator prev(pos);
--prev;
if(value_comp(*prev, val)){ //If previous element was less, then it should go between prev and pos
if(val_cmp(*prev, val)){ //If previous element was less, then it should go between prev and pos
return true;
}
else if(!value_comp(val, *prev)){ //If previous was equal then insertion should fail
else if(!val_cmp(val, *prev)){ //If previous was equal then insertion should fail
commit_data.position = prev;
return false;
}
@@ -846,7 +882,7 @@ class flat_tree
}
template <class RanIt>
RanIt priv_lower_bound(RanIt first, RanIt last,
RanIt priv_lower_bound(RanIt first, const RanIt last,
const key_type & key) const
{
const Compare &key_cmp = this->m_data.get_comp();
@@ -855,24 +891,23 @@ class flat_tree
RanIt middle;
while (len) {
size_type half = len >> 1;
size_type step = len >> 1;
middle = first;
middle += half;
middle += step;
if (key_cmp(key_extract(*middle), key)) {
++middle;
first = middle;
len = len - half - 1;
first = ++middle;
len -= step + 1;
}
else{
len = step;
}
else
len = half;
}
return first;
}
template <class RanIt>
RanIt priv_upper_bound(RanIt first, RanIt last,
RanIt priv_upper_bound(RanIt first, const RanIt last,
const key_type & key) const
{
const Compare &key_cmp = this->m_data.get_comp();
@@ -881,16 +916,16 @@ class flat_tree
RanIt middle;
while (len) {
size_type half = len >> 1;
size_type step = len >> 1;
middle = first;
middle += half;
middle += step;
if (key_cmp(key, key_extract(*middle))) {
len = half;
len = step;
}
else{
first = ++middle;
len = len - half - 1;
len -= step + 1;
}
}
return first;
@@ -906,29 +941,41 @@ class flat_tree
RanIt middle;
while (len) {
size_type half = len >> 1;
size_type step = len >> 1;
middle = first;
middle += half;
middle += step;
if (key_cmp(key_extract(*middle), key)){
first = middle;
++first;
len = len - half - 1;
first = ++middle;
len -= step + 1;
}
else if (key_cmp(key, key_extract(*middle))){
len = half;
len = step;
}
else {
//Middle is equal to key
last = first;
last += len;
first = this->priv_lower_bound(first, middle, key);
return std::pair<RanIt, RanIt> (first, this->priv_upper_bound(++middle, last, key));
return std::pair<RanIt, RanIt>
( this->priv_lower_bound(first, middle, key)
, this->priv_upper_bound(++middle, last, key));
}
}
return std::pair<RanIt, RanIt>(first, first);
}
template<class RanIt>
std::pair<RanIt, RanIt> priv_lower_bound_range(RanIt first, RanIt last, const key_type& k) const
{
const Compare &key_cmp = this->m_data.get_comp();
KeyOfValue key_extract;
RanIt lb(this->priv_lower_bound(first, last, k)), ub(lb);
if(lb != last && static_cast<difference_type>(!key_cmp(k, key_extract(*lb)))){
++ub;
}
return std::pair<RanIt, RanIt>(lb, ub);
}
template<class InIt>
void priv_insert_equal_loop(InIt first, InIt last)
{
@@ -950,62 +997,6 @@ class flat_tree
}
};
template <class Key, class Value, class KeyOfValue,
class Compare, class A>
inline bool
operator==(const flat_tree<Key,Value,KeyOfValue,Compare,A>& x,
const flat_tree<Key,Value,KeyOfValue,Compare,A>& y)
{
return x.size() == y.size() &&
std::equal(x.begin(), x.end(), y.begin());
}
template <class Key, class Value, class KeyOfValue,
class Compare, class A>
inline bool
operator<(const flat_tree<Key,Value,KeyOfValue,Compare,A>& x,
const flat_tree<Key,Value,KeyOfValue,Compare,A>& y)
{
return std::lexicographical_compare(x.begin(), x.end(),
y.begin(), y.end());
}
template <class Key, class Value, class KeyOfValue,
class Compare, class A>
inline bool
operator!=(const flat_tree<Key,Value,KeyOfValue,Compare,A>& x,
const flat_tree<Key,Value,KeyOfValue,Compare,A>& y)
{ return !(x == y); }
template <class Key, class Value, class KeyOfValue,
class Compare, class A>
inline bool
operator>(const flat_tree<Key,Value,KeyOfValue,Compare,A>& x,
const flat_tree<Key,Value,KeyOfValue,Compare,A>& y)
{ return y < x; }
template <class Key, class Value, class KeyOfValue,
class Compare, class A>
inline bool
operator<=(const flat_tree<Key,Value,KeyOfValue,Compare,A>& x,
const flat_tree<Key,Value,KeyOfValue,Compare,A>& y)
{ return !(y < x); }
template <class Key, class Value, class KeyOfValue,
class Compare, class A>
inline bool
operator>=(const flat_tree<Key,Value,KeyOfValue,Compare,A>& x,
const flat_tree<Key,Value,KeyOfValue,Compare,A>& y)
{ return !(x < y); }
template <class Key, class Value, class KeyOfValue,
class Compare, class A>
inline void
swap(flat_tree<Key,Value,KeyOfValue,Compare,A>& x,
flat_tree<Key,Value,KeyOfValue,Compare,A>& y)
{ x.swap(y); }
} //namespace container_detail {
} //namespace container {

View File

@@ -1,6 +1,6 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2009-2012.
// (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

View File

@@ -0,0 +1,383 @@
/*
template <class Value, unsigned int Options = 0, class Hash = hash<Value>, class Pred = equal_to<Value>,
class Alloc = allocator<Value> >
class hash_set
{
public:
// types
typedef Value key_type;
typedef key_type value_type;
typedef Hash hasher;
typedef Pred key_equal;
typedef Alloc allocator_type;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef typename allocator_traits<allocator_type>::pointer pointer;
typedef typename allocator_traits<allocator_type>::const_pointer const_pointer;
typedef typename allocator_traits<allocator_type>::size_type size_type;
typedef typename allocator_traits<allocator_type>::difference_type difference_type;
typedef /unspecified/ iterator;
typedef /unspecified/ const_iterator;
typedef /unspecified/ local_iterator;
typedef /unspecified/ const_local_iterator;
hash_set()
noexcept(
is_nothrow_default_constructible<hasher>::value &&
is_nothrow_default_constructible<key_equal>::value &&
is_nothrow_default_constructible<allocator_type>::value);
explicit hash_set(size_type n, const hasher& hf = hasher(),
const key_equal& eql = key_equal(),
const allocator_type& a = allocator_type());
template <class InputIterator>
hash_set(InputIterator f, InputIterator l,
size_type n = 0, const hasher& hf = hasher(),
const key_equal& eql = key_equal(),
const allocator_type& a = allocator_type());
explicit hash_set(const allocator_type&);
hash_set(const hash_set&);
hash_set(const hash_set&, const Allocator&);
hash_set(hash_set&&)
noexcept(
is_nothrow_move_constructible<hasher>::value &&
is_nothrow_move_constructible<key_equal>::value &&
is_nothrow_move_constructible<allocator_type>::value);
hash_set(hash_set&&, const Allocator&);
hash_set(initializer_list<value_type>, size_type n = 0,
const hasher& hf = hasher(), const key_equal& eql = key_equal(),
const allocator_type& a = allocator_type());
~hash_set();
hash_set& operator=(const hash_set&);
hash_set& operator=(hash_set&&)
noexcept(
allocator_type::propagate_on_container_move_assignment::value &&
is_nothrow_move_assignable<allocator_type>::value &&
is_nothrow_move_assignable<hasher>::value &&
is_nothrow_move_assignable<key_equal>::value);
hash_set& operator=(initializer_list<value_type>);
allocator_type get_allocator() const noexcept;
bool empty() const noexcept;
size_type size() const noexcept;
size_type max_size() const noexcept;
iterator begin() noexcept;
iterator end() noexcept;
const_iterator begin() const noexcept;
const_iterator end() const noexcept;
const_iterator cbegin() const noexcept;
const_iterator cend() const noexcept;
template <class... Args>
pair<iterator, bool> emplace(Args&&... args);
template <class... Args>
iterator emplace_hint(const_iterator position, Args&&... args);
pair<iterator, bool> insert(const value_type& obj);
pair<iterator, bool> insert(value_type&& obj);
iterator insert(const_iterator hint, const value_type& obj);
iterator insert(const_iterator hint, value_type&& obj);
template <class InputIterator>
void insert(InputIterator first, InputIterator last);
void insert(initializer_list<value_type>);
iterator erase(const_iterator position);
size_type erase(const key_type& k);
iterator erase(const_iterator first, const_iterator last);
void clear() noexcept;
void swap(hash_set&)
noexcept(
(!allocator_type::propagate_on_container_swap::value ||
__is_nothrow_swappable<allocator_type>::value) &&
__is_nothrow_swappable<hasher>::value &&
__is_nothrow_swappable<key_equal>::value);
hasher hash_function() const;
key_equal key_eq() const;
iterator find(const key_type& k);
const_iterator find(const key_type& k) const;
size_type count(const key_type& k) const;
pair<iterator, iterator> equal_range(const key_type& k);
pair<const_iterator, const_iterator> equal_range(const key_type& k) const;
size_type bucket_count() const noexcept;
size_type max_bucket_count() const noexcept;
size_type bucket_size(size_type n) const;
size_type bucket(const key_type& k) const;
local_iterator begin(size_type n);
local_iterator end(size_type n);
const_local_iterator begin(size_type n) const;
const_local_iterator end(size_type n) const;
const_local_iterator cbegin(size_type n) const;
const_local_iterator cend(size_type n) const;
float load_factor() const noexcept;
float max_load_factor() const noexcept;
void max_load_factor(float z);
void rehash(size_type n);
void reserve(size_type n);
};
template <class Key, class T, unsigned int Options = 0, class Hash = hash<Key>, class Pred = equal_to<Key>,
class Alloc = allocator<pair<const Key, T> > >
class hash_map
{
public:
// types
typedef Key key_type;
typedef T mapped_type;
typedef Hash hasher;
typedef Pred key_equal;
typedef Alloc allocator_type;
typedef pair<const key_type, mapped_type> value_type;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef typename allocator_traits<allocator_type>::pointer pointer;
typedef typename allocator_traits<allocator_type>::const_pointer const_pointer;
typedef typename allocator_traits<allocator_type>::size_type size_type;
typedef typename allocator_traits<allocator_type>::difference_type difference_type;
typedef /unspecified/ iterator;
typedef /unspecified/ const_iterator;
typedef /unspecified/ local_iterator;
typedef /unspecified/ const_local_iterator;
hash_map()
noexcept(
is_nothrow_default_constructible<hasher>::value &&
is_nothrow_default_constructible<key_equal>::value &&
is_nothrow_default_constructible<allocator_type>::value);
explicit hash_map(size_type n, const hasher& hf = hasher(),
const key_equal& eql = key_equal(),
const allocator_type& a = allocator_type());
template <class InputIterator>
hash_map(InputIterator f, InputIterator l,
size_type n = 0, const hasher& hf = hasher(),
const key_equal& eql = key_equal(),
const allocator_type& a = allocator_type());
explicit hash_map(const allocator_type&);
hash_map(const hash_map&);
hash_map(const hash_map&, const Allocator&);
hash_map(hash_map&&)
noexcept(
is_nothrow_move_constructible<hasher>::value &&
is_nothrow_move_constructible<key_equal>::value &&
is_nothrow_move_constructible<allocator_type>::value);
hash_map(hash_map&&, const Allocator&);
hash_map(initializer_list<value_type>, size_type n = 0,
const hasher& hf = hasher(), const key_equal& eql = key_equal(),
const allocator_type& a = allocator_type());
~hash_map();
hash_map& operator=(const hash_map&);
hash_map& operator=(hash_map&&)
noexcept(
allocator_type::propagate_on_container_move_assignment::value &&
is_nothrow_move_assignable<allocator_type>::value &&
is_nothrow_move_assignable<hasher>::value &&
is_nothrow_move_assignable<key_equal>::value);
hash_map& operator=(initializer_list<value_type>);
allocator_type get_allocator() const noexcept;
bool empty() const noexcept;
size_type size() const noexcept;
size_type max_size() const noexcept;
iterator begin() noexcept;
iterator end() noexcept;
const_iterator begin() const noexcept;
const_iterator end() const noexcept;
const_iterator cbegin() const noexcept;
const_iterator cend() const noexcept;
template <class... Args>
pair<iterator, bool> emplace(Args&&... args);
template <class... Args>
iterator emplace_hint(const_iterator position, Args&&... args);
pair<iterator, bool> insert(const value_type& obj);
template <class P>
pair<iterator, bool> insert(P&& obj);
iterator insert(const_iterator hint, const value_type& obj);
template <class P>
iterator insert(const_iterator hint, P&& obj);
template <class InputIterator>
void insert(InputIterator first, InputIterator last);
void insert(initializer_list<value_type>);
iterator erase(const_iterator position);
size_type erase(const key_type& k);
iterator erase(const_iterator first, const_iterator last);
void clear() noexcept;
void swap(hash_map&)
noexcept(
(!allocator_type::propagate_on_container_swap::value ||
__is_nothrow_swappable<allocator_type>::value) &&
__is_nothrow_swappable<hasher>::value &&
__is_nothrow_swappable<key_equal>::value);
hasher hash_function() const;
key_equal key_eq() const;
iterator find(const key_type& k);
const_iterator find(const key_type& k) const;
size_type count(const key_type& k) const;
pair<iterator, iterator> equal_range(const key_type& k);
pair<const_iterator, const_iterator> equal_range(const key_type& k) const;
mapped_type& operator[](const key_type& k);
mapped_type& operator[](key_type&& k);
mapped_type& at(const key_type& k);
const mapped_type& at(const key_type& k) const;
size_type bucket_count() const noexcept;
size_type max_bucket_count() const noexcept;
size_type bucket_size(size_type n) const;
size_type bucket(const key_type& k) const;
local_iterator begin(size_type n);
local_iterator end(size_type n);
const_local_iterator begin(size_type n) const;
const_local_iterator end(size_type n) const;
const_local_iterator cbegin(size_type n) const;
const_local_iterator cend(size_type n) const;
float load_factor() const noexcept;
float max_load_factor() const noexcept;
void max_load_factor(float z);
void rehash(size_type n);
void reserve(size_type n);
};
*/
template <class Key, class Value, class KeyOfValue, unsigned int Options = 0, class Hash = hash<Key>, class Pred = equal_to<Key>,
class Alloc = allocator<Value> >
class hash_table
{
public:
// types
typedef Value key_type;
typedef key_type value_type;
typedef Hash hasher;
typedef Pred key_equal;
typedef Alloc allocator_type;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef typename allocator_traits<allocator_type>::pointer pointer;
typedef typename allocator_traits<allocator_type>::const_pointer const_pointer;
typedef typename allocator_traits<allocator_type>::size_type size_type;
typedef typename allocator_traits<allocator_type>::difference_type difference_type;
typedef /unspecified/ iterator;
typedef /unspecified/ const_iterator;
typedef /unspecified/ local_iterator;
typedef /unspecified/ const_local_iterator;
hash_set()
noexcept(
is_nothrow_default_constructible<hasher>::value &&
is_nothrow_default_constructible<key_equal>::value &&
is_nothrow_default_constructible<allocator_type>::value);
explicit hash_set(size_type n, const hasher& hf = hasher(),
const key_equal& eql = key_equal(),
const allocator_type& a = allocator_type());
template <class InputIterator>
hash_set(InputIterator f, InputIterator l,
size_type n = 0, const hasher& hf = hasher(),
const key_equal& eql = key_equal(),
const allocator_type& a = allocator_type());
explicit hash_set(const allocator_type&);
hash_set(const hash_set&);
hash_set(const hash_set&, const Allocator&);
hash_set(hash_set&&)
noexcept(
is_nothrow_move_constructible<hasher>::value &&
is_nothrow_move_constructible<key_equal>::value &&
is_nothrow_move_constructible<allocator_type>::value);
hash_set(hash_set&&, const Allocator&);
hash_set(initializer_list<value_type>, size_type n = 0,
const hasher& hf = hasher(), const key_equal& eql = key_equal(),
const allocator_type& a = allocator_type());
~hash_set();
hash_set& operator=(const hash_set&);
hash_set& operator=(hash_set&&)
noexcept(
allocator_type::propagate_on_container_move_assignment::value &&
is_nothrow_move_assignable<allocator_type>::value &&
is_nothrow_move_assignable<hasher>::value &&
is_nothrow_move_assignable<key_equal>::value);
hash_set& operator=(initializer_list<value_type>);
allocator_type get_allocator() const noexcept;
bool empty() const noexcept;
size_type size() const noexcept;
size_type max_size() const noexcept;
iterator begin() noexcept;
iterator end() noexcept;
const_iterator begin() const noexcept;
const_iterator end() const noexcept;
const_iterator cbegin() const noexcept;
const_iterator cend() const noexcept;
template <class... Args>
pair<iterator, bool> emplace(Args&&... args);
template <class... Args>
iterator emplace_hint(const_iterator position, Args&&... args);
pair<iterator, bool> insert(const value_type& obj);
pair<iterator, bool> insert(value_type&& obj);
iterator insert(const_iterator hint, const value_type& obj);
iterator insert(const_iterator hint, value_type&& obj);
template <class InputIterator>
void insert(InputIterator first, InputIterator last);
void insert(initializer_list<value_type>);
iterator erase(const_iterator position);
size_type erase(const key_type& k);
iterator erase(const_iterator first, const_iterator last);
void clear() noexcept;
void swap(hash_set&)
noexcept(
(!allocator_type::propagate_on_container_swap::value ||
__is_nothrow_swappable<allocator_type>::value) &&
__is_nothrow_swappable<hasher>::value &&
__is_nothrow_swappable<key_equal>::value);
hasher hash_function() const;
key_equal key_eq() const;
iterator find(const key_type& k);
const_iterator find(const key_type& k) const;
size_type count(const key_type& k) const;
pair<iterator, iterator> equal_range(const key_type& k);
pair<const_iterator, const_iterator> equal_range(const key_type& k) const;
size_type bucket_count() const noexcept;
size_type max_bucket_count() const noexcept;
size_type bucket_size(size_type n) const;
size_type bucket(const key_type& k) const;
local_iterator begin(size_type n);
local_iterator end(size_type n);
const_local_iterator begin(size_type n) const;
const_local_iterator end(size_type n) const;
const_local_iterator cbegin(size_type n) const;
const_local_iterator cend(size_type n) const;
float load_factor() const noexcept;
float max_load_factor() const noexcept;
void max_load_factor(float z);
void rehash(size_type n);
void reserve(size_type n);
};

View File

@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2012.
// (C) Copyright Ion Gaztanaga 2005-2013.
// (C) Copyright Gennaro Prota 2003 - 2004.
//
// Distributed under the Boost Software License, Version 1.0.
@@ -18,7 +18,7 @@
# pragma once
#endif
#include "config_begin.hpp"
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/move/utility.hpp>
#include <boost/container/allocator_traits.hpp>

View File

@@ -1,7 +1,7 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Stephen Cleary 2000.
// (C) Copyright Ion Gaztanaga 2007-2012.
// (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
@@ -16,7 +16,9 @@
#ifndef BOOST_CONTAINER_DETAIL_MATH_FUNCTIONS_HPP
#define BOOST_CONTAINER_DETAIL_MATH_FUNCTIONS_HPP
#include "config_begin.hpp"
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <climits>
#include <boost/static_assert.hpp>

View File

@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2011-2012. Distributed under the Boost
// (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)
//
@@ -17,20 +17,22 @@
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/detail/preprocessor.hpp>
#include <boost/intrusive/detail/memory_util.hpp>
#include <boost/intrusive/detail/has_member_function_callable_with.hpp>
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME allocate
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace container { namespace container_detail {
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
#define BOOST_PP_ITERATION_PARAMS_1 (3, (0, 2, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
#define BOOST_PP_ITERATION_PARAMS_1 (3, (2, 2, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
#include BOOST_PP_ITERATE()
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME destroy
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace container { namespace container_detail {
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
#define BOOST_PP_ITERATION_PARAMS_1 (3, (0, 3, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
#define BOOST_PP_ITERATION_PARAMS_1 (3, (1, 1, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
#include BOOST_PP_ITERATE()
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME max_size
@@ -48,20 +50,19 @@
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME construct
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace container { namespace container_detail {
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
#define BOOST_PP_ITERATION_PARAMS_1 (3, (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS+1, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
#define BOOST_PP_ITERATION_PARAMS_1 (3, (1, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS+1, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
#include BOOST_PP_ITERATE()
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME swap
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace container { namespace container_detail {
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
#define BOOST_PP_ITERATION_PARAMS_1 (3, (0, 1, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
#define BOOST_PP_ITERATION_PARAMS_1 (3, (1, 1, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
#include BOOST_PP_ITERATE()
namespace boost {
namespace container {
namespace container_detail {
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(pointer)
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(const_pointer)
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(reference)
@@ -73,6 +74,8 @@ BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(propagate_on_container_copy_assig
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(difference_type)
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(value_compare)
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(wrapped_value_compare)
} //namespace container_detail {
} //namespace container {

View File

@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2012.
// (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
@@ -17,6 +17,9 @@
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <cstddef>
namespace boost {
@@ -110,8 +113,10 @@ struct if_
template <class Pair>
struct select1st
// : public std::unary_function<Pair, typename Pair::first_type>
{
typedef Pair argument_type;
typedef typename Pair::first_type result_type;
template<class OtherPair>
const typename Pair::first_type& operator()(const OtherPair& x) const
{ return x.first; }
@@ -123,8 +128,10 @@ struct select1st
// identity is an extension: it is not part of the standard.
template <class T>
struct identity
// : public std::unary_function<T,T>
{
typedef T argument_type;
typedef T result_type;
typedef T type;
const T& operator()(const T& x) const
{ return x; }
@@ -156,5 +163,7 @@ template <> struct unvoid<const void> { struct type { }; };
} //namespace container {
} //namespace boost {
#include <boost/container/detail/config_end.hpp>
#endif //#ifndef BOOST_CONTAINER_CONTAINER_DETAIL_MPL_HPP

View File

@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// (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)
//
@@ -11,7 +11,9 @@
#ifndef BOOST_CONTAINER_DETAIL_MULTIALLOCATION_CHAIN_HPP
#define BOOST_CONTAINER_DETAIL_MULTIALLOCATION_CHAIN_HPP
#include "config_begin.hpp"
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/container_fwd.hpp>
#include <boost/container/detail/utilities.hpp>
#include <boost/container/detail/type_traits.hpp>

View File

@@ -0,0 +1,278 @@
// Copyright (C) 2000 Stephen Cleary
//
// 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.
//////////////////////////////////////////////////////////////////////////////
//
// (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_MUTEX_HPP
#define BOOST_CONTAINER_MUTEX_HPP
//#define BOOST_CONTAINER_NO_MT
//#define BOOST_CONTAINER_NO_SPINLOCKS
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
// Extremely Light-Weight wrapper classes for OS thread synchronization
#define BOOST_MUTEX_HELPER_NONE 0
#define BOOST_MUTEX_HELPER_WIN32 1
#define BOOST_MUTEX_HELPER_PTHREAD 2
#define BOOST_MUTEX_HELPER_SPINLOCKS 3
#if !defined(BOOST_HAS_THREADS) && !defined(BOOST_NO_MT)
# define BOOST_NO_MT
#endif
#if defined(BOOST_NO_MT) || defined(BOOST_CONTAINER_NO_MT)
// No multithreading -> make locks into no-ops
#define BOOST_MUTEX_HELPER BOOST_MUTEX_HELPER_NONE
#else
//Taken from dlmalloc
#if !defined(BOOST_CONTAINER_NO_SPINLOCKS) && \
((defined(__GNUC__) && \
((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) || \
defined(__i386__) || defined(__x86_64__))) || \
(defined(_MSC_VER) && _MSC_VER>=1310))
#define BOOST_MUTEX_HELPER BOOST_MUTEX_HELPER_SPINLOCKS
#endif
#if defined(BOOST_WINDOWS)
#include <windows.h>
#ifndef BOOST_MUTEX_HELPER
#define BOOST_MUTEX_HELPER BOOST_MUTEX_HELPER_WIN32
#endif
#elif defined(BOOST_HAS_UNISTD_H)
#include <unistd.h>
#if !defined(BOOST_MUTEX_HELPER) && (defined(_POSIX_THREADS) || defined(BOOST_HAS_PTHREADS))
#define BOOST_MUTEX_HELPER BOOST_MUTEX_HELPER_PTHREAD
#endif
#endif
#endif
#ifndef BOOST_MUTEX_HELPER
#error Unable to determine platform mutex type; #define BOOST_NO_MT to assume single-threaded
#endif
#if BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_NONE
//...
#elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_SPINLOCKS
#if defined(_MSC_VER)
#ifndef _M_AMD64
/* These are already defined on AMD64 builds */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
long __cdecl _InterlockedCompareExchange(long volatile *Dest, long Exchange, long Comp);
long __cdecl _InterlockedExchange(long volatile *Target, long Value);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* _M_AMD64 */
#pragma intrinsic (_InterlockedCompareExchange)
#pragma intrinsic (_InterlockedExchange)
#define interlockedcompareexchange _InterlockedCompareExchange
#define interlockedexchange _InterlockedExchange
#elif defined(WIN32) && defined(__GNUC__)
#define interlockedcompareexchange(a, b, c) __sync_val_compare_and_swap(a, c, b)
#define interlockedexchange __sync_lock_test_and_set
#endif /* Win32 */
/* First, define CAS_LOCK and CLEAR_LOCK on ints */
/* Note CAS_LOCK defined to return 0 on success */
#if defined(__GNUC__)&& (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1))
#define BOOST_CONTAINER_CAS_LOCK(sl) __sync_lock_test_and_set(sl, 1)
#define BOOST_CONTAINER_CLEAR_LOCK(sl) __sync_lock_release(sl)
#elif (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)))
/* Custom spin locks for older gcc on x86 */
static FORCEINLINE 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 FORCEINLINE void boost_container_x86_clear_lock(int* sl) {
assert(*sl != 0);
int prev = 0;
int ret;
__asm__ __volatile__ ("lock; xchgl %0, %1"
: "=r" (ret)
: "m" (*(sl)), "0"(prev)
: "memory");
}
#define BOOST_CONTAINER_CAS_LOCK(sl) boost_container_x86_cas_lock(sl)
#define BOOST_CONTAINER_CLEAR_LOCK(sl) boost_container_x86_clear_lock(sl)
#else /* Win32 MSC */
#define BOOST_CONTAINER_CAS_LOCK(sl) interlockedexchange((long volatile*)sl, (long)1)
#define BOOST_CONTAINER_CLEAR_LOCK(sl) interlockedexchange((long volatile*)sl, (long)0)
#endif
/* How to yield for a spin lock */
#define SPINS_PER_YIELD 63
#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
#define SLEEP_EX_DURATION 50 /* delay for yield/sleep */
#define SPIN_LOCK_YIELD SleepEx(SLEEP_EX_DURATION, FALSE)
#elif defined (__SVR4) && defined (__sun) /* solaris */
#define SPIN_LOCK_YIELD thr_yield();
#elif !defined(LACKS_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_CONTAINER_INITIAL_LOCK(sl) (*sl = 0)
#define BOOST_CONTAINER_DESTROY_LOCK(sl) (0)
#elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_WIN32
//
#elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_PTHREAD
#include <pthread.h>
#endif
namespace boost {
namespace container {
namespace container_detail {
#if BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_NONE
class null_mutex
{
private:
null_mutex(const null_mutex &);
void operator=(const null_mutex &);
public:
null_mutex() { }
static void lock() { }
static void unlock() { }
};
typedef null_mutex default_mutex;
#elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_SPINLOCKS
class spin_mutex
{
private:
BOOST_CONTAINER_MLOCK_T sl;
spin_mutex(const spin_mutex &);
void operator=(const spin_mutex &);
public:
spin_mutex() { BOOST_CONTAINER_INITIAL_LOCK(&sl); }
void lock() { BOOST_CONTAINER_ACQUIRE_LOCK(&sl); }
void unlock() { BOOST_CONTAINER_RELEASE_LOCK(&sl); }
};
typedef spin_mutex default_mutex;
#elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_WIN32
class mutex
{
private:
CRITICAL_SECTION mtx;
mutex(const mutex &);
void operator=(const mutex &);
public:
mutex()
{ InitializeCriticalSection(&mtx); }
~mutex()
{ DeleteCriticalSection(&mtx); }
void lock()
{ EnterCriticalSection(&mtx); }
void unlock()
{ LeaveCriticalSection(&mtx); }
};
typedef mutex default_mutex;
#elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_PTHREAD
class mutex
{
private:
pthread_mutex_t mtx;
mutex(const mutex &);
void operator=(const mutex &);
public:
mutex()
{ pthread_mutex_init(&mtx, 0); }
~mutex()
{ pthread_mutex_destroy(&mtx); }
void lock()
{ pthread_mutex_lock(&mtx); }
void unlock()
{ pthread_mutex_unlock(&mtx); }
};
typedef mutex default_mutex;
#endif
template<class Mutex>
class scoped_lock
{
public:
scoped_lock(Mutex &m)
: m_(m)
{ m_.lock(); }
~scoped_lock()
{ m_.unlock(); }
private:
Mutex &m_;
};
} // namespace container_detail
} // namespace container
} // namespace boost
#undef BOOST_MUTEX_HELPER_WIN32
#undef BOOST_MUTEX_HELPER_PTHREAD
#undef BOOST_MUTEX_HELPER_NONE
#undef BOOST_MUTEX_HELPER
#undef BOOST_MUTEX_HELPER_SPINLOCKS
#include <boost/container/detail/config_end.hpp>
#endif

View File

@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// (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)
//
@@ -15,7 +15,7 @@
# pragma once
#endif
#include "config_begin.hpp"
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <utility>
@@ -31,6 +31,7 @@
#include <boost/container/detail/allocator_version_traits.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/destroyers.hpp>
#include <boost/container/detail/memory_util.hpp>
#include <boost/container/detail/allocator_version_traits.hpp>
#include <boost/detail/no_exceptions_support.hpp>
@@ -50,33 +51,44 @@ template<class ValueCompare, class Node>
struct node_compare
: private ValueCompare
{
typedef typename ValueCompare::key_type key_type;
typedef typename ValueCompare::value_type value_type;
typedef typename ValueCompare::key_of_value key_of_value;
typedef ValueCompare wrapped_value_compare;
typedef typename wrapped_value_compare::key_type key_type;
typedef typename wrapped_value_compare::value_type value_type;
typedef typename wrapped_value_compare::key_of_value key_of_value;
explicit node_compare(const ValueCompare &pred)
: ValueCompare(pred)
explicit node_compare(const wrapped_value_compare &pred)
: wrapped_value_compare(pred)
{}
node_compare()
: ValueCompare()
: wrapped_value_compare()
{}
ValueCompare &value_comp()
{ return static_cast<ValueCompare &>(*this); }
wrapped_value_compare &value_comp()
{ return static_cast<wrapped_value_compare &>(*this); }
ValueCompare &value_comp() const
{ return static_cast<const ValueCompare &>(*this); }
wrapped_value_compare &value_comp() const
{ return static_cast<const wrapped_value_compare &>(*this); }
bool operator()(const Node &a, const Node &b) const
{ return ValueCompare::operator()(a.get_data(), b.get_data()); }
{ return wrapped_value_compare::operator()(a.get_data(), b.get_data()); }
};
template<class A, class ICont, class ValPred = container_detail::nat>
template<class A, class ICont>
struct node_alloc_holder
{
//If the intrusive container is an associative container, obtain the predicate, which will
//be of type node_compare<>. If not an associative container value_compare will be a "nat" type.
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, ICont,
value_compare, container_detail::nat) intrusive_value_compare;
//In that case obtain the value predicate from the node predicate via wrapped_value_compare
//if intrusive_value_compare is node_compare<>, nat otherwise
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, ICont,
wrapped_value_compare, container_detail::nat) value_compare;
typedef allocator_traits<A> allocator_traits_type;
typedef typename allocator_traits_type::value_type value_type;
typedef ICont intrusive_container;
typedef typename ICont::value_type Node;
typedef typename allocator_traits_type::template
portable_rebind_alloc<Node>::type NodeAlloc;
@@ -121,20 +133,20 @@ struct node_alloc_holder
{ this->icont().swap(x.icont()); }
//Constructors for associative containers
explicit node_alloc_holder(const ValAlloc &a, const ValPred &c)
explicit node_alloc_holder(const ValAlloc &a, const value_compare &c)
: members_(a, c)
{}
explicit node_alloc_holder(const node_alloc_holder &x, const ValPred &c)
explicit node_alloc_holder(const node_alloc_holder &x, const value_compare &c)
: members_(NodeAllocTraits::select_on_container_copy_construction(x.node_alloc()), c)
{}
explicit node_alloc_holder(const ValPred &c)
explicit node_alloc_holder(const value_compare &c)
: members_(c)
{}
//helpers for move assignments
explicit node_alloc_holder(BOOST_RV_REF(node_alloc_holder) x, const ValPred &c)
explicit node_alloc_holder(BOOST_RV_REF(node_alloc_holder) x, const value_compare &c)
: members_(boost::move(x.node_alloc()), c)
{ this->icont().swap(x.icont()); }
@@ -346,12 +358,12 @@ struct node_alloc_holder
{}
template<class ConvertibleToAlloc>
members_holder(BOOST_FWD_REF(ConvertibleToAlloc) c2alloc, const ValPred &c)
members_holder(BOOST_FWD_REF(ConvertibleToAlloc) c2alloc, const value_compare &c)
: NodeAlloc(boost::forward<ConvertibleToAlloc>(c2alloc))
, m_icont(typename ICont::value_compare(c))
{}
explicit members_holder(const ValPred &c)
explicit members_holder(const value_compare &c)
: NodeAlloc()
, m_icont(typename ICont::value_compare(c))
{}

View 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
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# 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/intrusive/slist.hpp>
#include <boost/move/move.hpp>
#include <cstddef>
#include <new>
#include <functional> //std::unary_function
#include <algorithm> //std::swap
#include <cassert>
namespace boost {
namespace container {
namespace container_detail {
//!Pooled memory allocator using single segregated storage. Includes
//!a reference count but the class does not delete itself, this is
//!responsibility of user classes. Node size (NodeSize) and the number of
//!nodes allocated per block (NodesPerBlock) are known at compile time
template< std::size_t NodeSize, std::size_t NodesPerBlock >
class private_node_pool
//Inherit from the implementation to avoid template bloat
: public boost::container::container_detail::
private_node_pool_impl<fake_segment_manager>
{
typedef boost::container::container_detail::
private_node_pool_impl<fake_segment_manager> base_t;
//Non-copyable
private_node_pool(const private_node_pool &);
private_node_pool &operator=(const private_node_pool &);
public:
typedef typename base_t::multiallocation_chain multiallocation_chain;
static const std::size_t nodes_per_block = NodesPerBlock;
//!Constructor from a segment manager. Never throws
private_node_pool()
: base_t(0, NodeSize, NodesPerBlock)
{}
};
template< std::size_t NodeSize
, std::size_t NodesPerBlock
>
class shared_node_pool
: public private_node_pool<NodeSize, NodesPerBlock>
{
private:
typedef private_node_pool<NodeSize, NodesPerBlock> private_node_allocator_t;
public:
typedef typename private_node_allocator_t::free_nodes_t free_nodes_t;
typedef typename private_node_allocator_t::multiallocation_chain multiallocation_chain;
//!Constructor from a segment manager. Never throws
shared_node_pool()
: private_node_allocator_t(){}
//!Destructor. Deallocates all allocated blocks. Never throws
~shared_node_pool()
{}
//!Allocates array of count elements. Can throw std::bad_alloc
void *allocate_node()
{
//-----------------------
scoped_lock<default_mutex> guard(mutex_);
//-----------------------
return private_node_allocator_t::allocate_node();
}
//!Deallocates an array pointed by ptr. Never throws
void deallocate_node(void *ptr)
{
//-----------------------
scoped_lock<default_mutex> guard(mutex_);
//-----------------------
private_node_allocator_t::deallocate_node(ptr);
}
//!Allocates a singly linked list of n nodes ending in null pointer.
//!can throw std::bad_alloc
void allocate_nodes(const std::size_t n, multiallocation_chain &chain)
{
//-----------------------
scoped_lock<default_mutex> guard(mutex_);
//-----------------------
return private_node_allocator_t::allocate_nodes(n, chain);
}
void deallocate_nodes(multiallocation_chain &chain)
{
//-----------------------
scoped_lock<default_mutex> guard(mutex_);
//-----------------------
private_node_allocator_t::deallocate_nodes(chain);
}
//!Deallocates all the free blocks of memory. Never throws
void deallocate_free_blocks()
{
//-----------------------
scoped_lock<default_mutex> guard(mutex_);
//-----------------------
private_node_allocator_t::deallocate_free_blocks();
}
//!Deallocates all blocks. Never throws
void purge_blocks()
{
//-----------------------
scoped_lock<default_mutex> guard(mutex_);
//-----------------------
private_node_allocator_t::purge_blocks();
}
std::size_t num_free_nodes()
{
//-----------------------
scoped_lock<default_mutex> guard(mutex_);
//-----------------------
return private_node_allocator_t::num_free_nodes();
}
private:
default_mutex mutex_;
};
} //namespace container_detail {
} //namespace container {
} //namespace boost {
#include <boost/container/detail/config_end.hpp>
#endif //#ifndef BOOST_CONTAINER_DETAIL_NODE_POOL_HPP

View File

@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// (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)
//
@@ -15,9 +15,10 @@
# pragma once
#endif
#include "config_begin.hpp"
#include <boost/container/container_fwd.hpp>
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/container_fwd.hpp>
#include <boost/container/detail/utilities.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/intrusive/set.hpp>
@@ -29,8 +30,6 @@
#include <boost/detail/no_exceptions_support.hpp>
#include <boost/assert.hpp>
#include <cstddef>
#include <functional> //std::unary_function
namespace boost {
namespace container {
@@ -251,8 +250,10 @@ class private_node_pool_impl
};
struct is_between
: std::unary_function<typename free_nodes_t::value_type, bool>
{
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)
{}

View File

@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2012.
// (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
@@ -17,7 +17,7 @@
# pragma once
#endif
#include "config_begin.hpp"
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/detail/mpl.hpp>

View File

@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// (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)
//
@@ -8,14 +8,16 @@
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_DETAIL_NODE_POOL_COMMON_HPP
#define BOOST_CONTAINER_DETAIL_NODE_POOL_COMMON_HPP
#ifndef BOOST_CONTAINER_DETAIL_POOL_COMMON_HPP
#define BOOST_CONTAINER_DETAIL_POOL_COMMON_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include "config_begin.hpp"
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/intrusive/slist.hpp>
#include <new>

View File

@@ -0,0 +1,94 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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
#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/alloc_lib.h>
#include <cstddef>
namespace boost{
namespace container{
namespace container_detail{
struct node_slist_helper
: public boost::container::container_detail::node_slist<void*>
{};
struct fake_segment_manager
{
typedef void * void_pointer;
static const std::size_t PayloadPerAllocation = BOOST_CONTAINER_ALLOCATION_PAYLOAD;
typedef boost::container::container_detail::
basic_multiallocation_chain<void*> multiallocation_chain;
static void deallocate(void_pointer p)
{ boost_cont_free(p); }
static void deallocate_many(multiallocation_chain &chain)
{
std::size_t size = chain.size();
std::pair<void*, void*> ptrs = chain.extract_data();
boost_cont_memchain dlchain;
BOOST_CONTAINER_MEMCHAIN_INIT_FROM(&dlchain, ptrs.first, ptrs.second, size);
boost_cont_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 = boost_cont_memalign(nbytes, alignment);
if(!ret)
boost::container::throw_bad_alloc();
return ret;
}
static void *allocate(std::size_t nbytes)
{
void *ret = boost_cont_malloc(nbytes);
if(!ret)
boost::container::throw_bad_alloc();
return ret;
}
};
} //namespace boost{
} //namespace container{
} //namespace container_detail{
namespace boost {
namespace container {
namespace container_detail {
template<class T>
struct is_stateless_segment_manager;
template<>
struct is_stateless_segment_manager
<boost::container::container_detail::fake_segment_manager>
{
static const bool value = true;
};
} //namespace container_detail {
} //namespace container {
} //namespace boost {
#include <boost/container/detail/config_end.hpp>
#endif //BOOST_CONTAINER_DETAIL_POOL_COMMON_ALLOC_HPP

View File

@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost
// (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)
//

View File

@@ -0,0 +1,113 @@
// 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
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
//
// The following helper classes are placeholders for a generic "singleton"
// class. The classes below support usage of singletons, including use in
// program startup/shutdown code, AS LONG AS there is only one thread
// running before main() begins, and only one thread running after main()
// exits.
//
// This class is also limited in that it can only provide singleton usage for
// classes with default constructors.
//
// The design of this class is somewhat twisted, but can be followed by the
// calling inheritance. Let us assume that there is some user code that
// calls "singleton_default<T>::instance()". The following (convoluted)
// sequence ensures that the same function will be called before main():
// instance() contains a call to create_object.do_nothing()
// Thus, object_creator is implicitly instantiated, and create_object
// must exist.
// Since create_object is a static member, its constructor must be
// called before main().
// The constructor contains a call to instance(), thus ensuring that
// instance() will be called before main().
// The first time instance() is called (i.e., before main()) is the
// latest point in program execution where the object of type T
// can be created.
// Thus, any call to instance() will auto-magically result in a call to
// instance() before main(), unless already present.
// Furthermore, since the instance() function contains the object, instead
// of the singleton_default class containing a static instance of the
// object, that object is guaranteed to be constructed (at the latest) in
// the first call to instance(). This permits calls to instance() from
// static code, even if that code is called before the file-scope objects
// in this file have been initialized.
namespace boost {
namespace container {
namespace container_detail {
// T must be: no-throw default constructible and no-throw destructible
template <typename T>
struct singleton_default
{
private:
struct object_creator
{
// This constructor does nothing more than ensure that instance()
// is called before main() begins, thus creating the static
// T object before multithreading race issues can come up.
object_creator() { singleton_default<T>::instance(); }
inline void do_nothing() const { }
};
static object_creator create_object;
singleton_default();
public:
typedef T object_type;
// If, at any point (in user code), singleton_default<T>::instance()
// is called, then the following function is instantiated.
static object_type & instance()
{
// This is the object that we return a reference to.
// It is guaranteed to be created before main() begins because of
// the next line.
static object_type obj;
// The following line does nothing else than force the instantiation
// of singleton_default<T>::create_object, whose constructor is
// called before main() begins.
create_object.do_nothing();
return obj;
}
};
template <typename T>
typename singleton_default<T>::object_creator
singleton_default<T>::create_object;
} // namespace container_detail
} // namespace container
} // namespace boost
#include <boost/container/detail/config_end.hpp>
#endif //BOOST_CONTAINER_DETAIL_SINGLETON_DETAIL_HPP

View File

@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2012.
// (C) Copyright Ion Gaztanaga 2005-2013.
// (C) Copyright Gennaro Prota 2003 - 2004.
//
// Distributed under the Boost Software License, Version 1.0.
@@ -18,8 +18,9 @@
# pragma once
#endif
#include "config_begin.hpp"
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/detail/type_traits.hpp>
#include <iterator>

View File

@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// (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)
//
@@ -11,15 +11,10 @@
#ifndef BOOST_CONTAINER_TREE_HPP
#define BOOST_CONTAINER_TREE_HPP
#include "config_begin.hpp"
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/container_fwd.hpp>
#include <boost/move/utility.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/type_traits/has_trivial_destructor.hpp>
#include <boost/detail/no_exceptions_support.hpp>
#include <boost/intrusive/rbtree.hpp>
#include <boost/container/detail/utilities.hpp>
#include <boost/container/detail/iterators.hpp>
#include <boost/container/detail/algorithms.hpp>
@@ -28,7 +23,19 @@
#include <boost/container/detail/pair.hpp>
#include <boost/container/detail/type_traits.hpp>
#include <boost/container/allocator_traits.hpp>
#include <boost/container/options.hpp>
//
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/intrusive/rbtree.hpp>
#include <boost/intrusive/avltree.hpp>
#include <boost/intrusive/splaytree.hpp>
#include <boost/intrusive/sgtree.hpp>
//
#include <boost/move/utility.hpp>
#include <boost/type_traits/has_trivial_destructor.hpp>
#include <boost/detail/no_exceptions_support.hpp>
//
#ifndef BOOST_CONTAINER_PERFECT_FORWARDING
#include <boost/container/detail/preprocessor.hpp>
#endif
@@ -85,47 +92,78 @@ struct tree_value_compare
{ return key_compare::operator()(this->key_forward(key1), this->key_forward(key2)); }
};
template<class VoidPointer>
struct rbtree_hook
template<class VoidPointer, boost::container::tree_type_enum tree_type_value, bool OptimizeSize>
struct intrusive_tree_hook;
template<class VoidPointer, bool OptimizeSize>
struct intrusive_tree_hook<VoidPointer, boost::container::red_black_tree, OptimizeSize>
{
typedef typename container_detail::bi::make_set_base_hook
< container_detail::bi::void_pointer<VoidPointer>
, container_detail::bi::link_mode<container_detail::bi::normal_link>
, container_detail::bi::optimize_size<true>
, container_detail::bi::optimize_size<OptimizeSize>
>::type type;
};
template<class VoidPointer, bool OptimizeSize>
struct intrusive_tree_hook<VoidPointer, boost::container::avl_tree, OptimizeSize>
{
typedef typename container_detail::bi::make_avl_set_base_hook
< container_detail::bi::void_pointer<VoidPointer>
, container_detail::bi::link_mode<container_detail::bi::normal_link>
, container_detail::bi::optimize_size<OptimizeSize>
>::type type;
};
template<class VoidPointer, bool OptimizeSize>
struct intrusive_tree_hook<VoidPointer, boost::container::scapegoat_tree, OptimizeSize>
{
typedef typename container_detail::bi::make_bs_set_base_hook
< container_detail::bi::void_pointer<VoidPointer>
, container_detail::bi::link_mode<container_detail::bi::normal_link>
>::type type;
};
template<class VoidPointer, bool OptimizeSize>
struct intrusive_tree_hook<VoidPointer, boost::container::splay_tree, OptimizeSize>
{
typedef typename container_detail::bi::make_bs_set_base_hook
< container_detail::bi::void_pointer<VoidPointer>
, container_detail::bi::link_mode<container_detail::bi::normal_link>
>::type type;
};
//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>
struct rbtree_internal_data_type
struct tree_internal_data_type
{
typedef T type;
};
template<class T1, class T2>
struct rbtree_internal_data_type< std::pair<T1, T2> >
struct tree_internal_data_type< std::pair<T1, T2> >
{
typedef pair<T1, T2> type;
};
//The node to be store in the tree
template <class T, class VoidPointer>
struct rbtree_node
: public rbtree_hook<VoidPointer>::type
template <class T, class VoidPointer, boost::container::tree_type_enum tree_type_value, bool OptimizeSize>
struct tree_node
: public intrusive_tree_hook<VoidPointer, tree_type_value, OptimizeSize>::type
{
private:
//BOOST_COPYABLE_AND_MOVABLE(rbtree_node)
rbtree_node();
//BOOST_COPYABLE_AND_MOVABLE(tree_node)
tree_node();
public:
typedef typename rbtree_hook<VoidPointer>::type hook_type;
typedef typename intrusive_tree_hook
<VoidPointer, tree_type_value, OptimizeSize>::type hook_type;
typedef T value_type;
typedef typename rbtree_internal_data_type<T>::type internal_type;
typedef typename tree_internal_data_type<T>::type internal_type;
typedef rbtree_node<T, VoidPointer> node_type;
typedef tree_node< T, VoidPointer
, tree_type_value, OptimizeSize> node_type;
T &get_data()
{
@@ -210,52 +248,224 @@ class push_back_functor
namespace container_detail {
template<class A, class ValueCompare>
struct intrusive_rbtree_type
template< class NodeType, class NodeCompareType
, class SizeType, class HookType
, boost::container::tree_type_enum tree_type_value>
struct intrusive_tree_dispatch;
template<class NodeType, class NodeCompareType, class SizeType, class HookType>
struct intrusive_tree_dispatch
<NodeType, NodeCompareType, SizeType, HookType, boost::container::red_black_tree>
{
typedef typename container_detail::bi::make_rbtree
<NodeType
,container_detail::bi::compare<NodeCompareType>
,container_detail::bi::base_hook<HookType>
,container_detail::bi::constant_time_size<true>
,container_detail::bi::size_type<SizeType>
>::type type;
};
template<class NodeType, class NodeCompareType, class SizeType, class HookType>
struct intrusive_tree_dispatch
<NodeType, NodeCompareType, SizeType, HookType, boost::container::avl_tree>
{
typedef typename container_detail::bi::make_avltree
<NodeType
,container_detail::bi::compare<NodeCompareType>
,container_detail::bi::base_hook<HookType>
,container_detail::bi::constant_time_size<true>
,container_detail::bi::size_type<SizeType>
>::type type;
};
template<class NodeType, class NodeCompareType, class SizeType, class HookType>
struct intrusive_tree_dispatch
<NodeType, NodeCompareType, SizeType, HookType, boost::container::scapegoat_tree>
{
typedef typename container_detail::bi::make_sgtree
<NodeType
,container_detail::bi::compare<NodeCompareType>
,container_detail::bi::base_hook<HookType>
,container_detail::bi::floating_point<true>
,container_detail::bi::size_type<SizeType>
>::type type;
};
template<class NodeType, class NodeCompareType, class SizeType, class HookType>
struct intrusive_tree_dispatch
<NodeType, NodeCompareType, SizeType, HookType, boost::container::splay_tree>
{
typedef typename container_detail::bi::make_splaytree
<NodeType
,container_detail::bi::compare<NodeCompareType>
,container_detail::bi::base_hook<HookType>
,container_detail::bi::constant_time_size<true>
,container_detail::bi::size_type<SizeType>
>::type type;
};
template<class A, class ValueCompare, boost::container::tree_type_enum tree_type_value, bool OptimizeSize>
struct intrusive_tree_type
{
private:
typedef typename boost::container::
allocator_traits<A>::value_type value_type;
typedef typename boost::container::
allocator_traits<A>::void_pointer void_pointer;
typedef typename boost::container::
allocator_traits<A>::size_type size_type;
typedef typename container_detail::rbtree_node
<value_type, void_pointer> node_type;
typedef typename container_detail::tree_node
< value_type, void_pointer
, tree_type_value, OptimizeSize> node_type;
typedef node_compare<ValueCompare, node_type> node_compare_type;
typedef typename container_detail::bi::make_rbtree
<node_type
,container_detail::bi::compare<node_compare_type>
,container_detail::bi::base_hook<typename rbtree_hook<void_pointer>::type>
,container_detail::bi::constant_time_size<true>
,container_detail::bi::size_type<size_type>
>::type container_type;
typedef container_type type ;
//Deducing the hook type from node_type (e.g. node_type::hook_type) would
//provoke an early instantiation of node_type that could ruin recursive
//tree definitions, so retype the complete type to avoid any problem.
typedef typename intrusive_tree_hook
<void_pointer, tree_type_value
, OptimizeSize>::type hook_type;
public:
typedef typename intrusive_tree_dispatch
< node_type, node_compare_type
, size_type, hook_type
, tree_type_value>::type type;
};
//Trait to detect manually rebalanceable tree types
template<boost::container::tree_type_enum tree_type_value>
struct is_manually_balanceable
{ static const bool value = true; };
template<> struct is_manually_balanceable<red_black_tree>
{ static const bool value = false; };
template<> struct is_manually_balanceable<avl_tree>
{ static const bool value = false; };
//Proxy traits to implement different operations depending on the
//is_manually_balanceable<>::value
template< boost::container::tree_type_enum tree_type_value
, bool IsManuallyRebalanceable = is_manually_balanceable<tree_type_value>::value>
struct intrusive_tree_proxy
{
template<class Icont>
static void rebalance(Icont &) {}
};
template<boost::container::tree_type_enum tree_type_value>
struct intrusive_tree_proxy<tree_type_value, true>
{
template<class Icont>
static void rebalance(Icont &c)
{ c.rebalance(); }
};
} //namespace container_detail {
namespace container_detail {
//This functor will be used with Intrusive clone functions to obtain
//already allocated nodes from a intrusive container instead of
//allocating new ones. When the intrusive container runs out of nodes
//the node holder is used instead.
template<class AllocHolder, bool DoMove>
class RecyclingCloner
{
typedef typename AllocHolder::intrusive_container intrusive_container;
typedef typename AllocHolder::Node node_type;
typedef typename AllocHolder::NodePtr node_ptr_type;
public:
RecyclingCloner(AllocHolder &holder, intrusive_container &itree)
: m_holder(holder), m_icont(itree)
{}
static void do_assign(node_ptr_type &p, const node_type &other, bool_<true>)
{ p->do_assign(other.m_data); }
static void do_assign(node_ptr_type &p, const node_type &other, bool_<false>)
{ p->do_move_assign(const_cast<node_type &>(other).m_data); }
node_ptr_type operator()(const node_type &other) const
{
if(node_ptr_type p = m_icont.unlink_leftmost_without_rebalance()){
//First recycle a node (this can't throw)
BOOST_TRY{
//This can throw
this->do_assign(p, other, bool_<DoMove>());
return p;
}
BOOST_CATCH(...){
//If there is an exception destroy the whole source
m_holder.destroy_node(p);
while((p = m_icont.unlink_leftmost_without_rebalance())){
m_holder.destroy_node(p);
}
BOOST_RETHROW
}
BOOST_CATCH_END
}
else{
return m_holder.create_node(other.m_data);
}
}
AllocHolder &m_holder;
intrusive_container &m_icont;
};
template<class KeyValueCompare, class Node>
//where KeyValueCompare is tree_value_compare<Key, Value, KeyCompare, KeyOfValue>
struct key_node_compare
: private KeyValueCompare
{
explicit key_node_compare(const KeyValueCompare &comp)
: KeyValueCompare(comp)
{}
template<class T>
struct is_node
{
static const bool value = is_same<T, Node>::value;
};
template<class T>
typename enable_if_c<is_node<T>::value, const typename KeyValueCompare::value_type &>::type
key_forward(const T &node) const
{ return node.get_data(); }
template<class T>
typename enable_if_c<!is_node<T>::value, const T &>::type
key_forward(const T &key) const
{ return key; }
template<class KeyType, class KeyType2>
bool operator()(const KeyType &key1, const KeyType2 &key2) const
{ return KeyValueCompare::operator()(this->key_forward(key1), this->key_forward(key2)); }
};
template <class Key, class Value, class KeyOfValue,
class KeyCompare, class A>
class rbtree
class KeyCompare, class A,
class Options = tree_assoc_defaults>
class tree
: protected container_detail::node_alloc_holder
< A
, typename container_detail::intrusive_rbtree_type
<A, tree_value_compare<Key, Value, KeyCompare, KeyOfValue>
>::type
, tree_value_compare<Key, Value, KeyCompare, KeyOfValue>
, typename container_detail::intrusive_tree_type
< A, tree_value_compare<Key, Value, KeyCompare, KeyOfValue> //ValComp
, Options::tree_type, Options::optimize_size>::type
>
{
typedef tree_value_compare
<Key, Value, KeyCompare, KeyOfValue> ValComp;
typedef typename container_detail::intrusive_rbtree_type
< A, ValComp>::type Icont;
typedef typename container_detail::intrusive_tree_type
< A, ValComp, Options::tree_type
, Options::optimize_size>::type Icont;
typedef container_detail::node_alloc_holder
<A, Icont, ValComp> AllocHolder;
<A, Icont> AllocHolder;
typedef typename AllocHolder::NodePtr NodePtr;
typedef rbtree < Key, Value, KeyOfValue
, KeyCompare, A> ThisType;
typedef tree < Key, Value, KeyOfValue
, KeyCompare, A, Options> ThisType;
typedef typename AllocHolder::NodeAlloc NodeAlloc;
typedef typename AllocHolder::ValAlloc ValAlloc;
typedef typename AllocHolder::Node Node;
@@ -265,84 +475,9 @@ class rbtree
typedef typename AllocHolder::allocator_v1 allocator_v1;
typedef typename AllocHolder::allocator_v2 allocator_v2;
typedef typename AllocHolder::alloc_version alloc_version;
typedef intrusive_tree_proxy<Options::tree_type> intrusive_tree_proxy_t;
class RecyclingCloner;
friend class RecyclingCloner;
class RecyclingCloner
{
public:
RecyclingCloner(AllocHolder &holder, Icont &irbtree)
: m_holder(holder), m_icont(irbtree)
{}
NodePtr operator()(const Node &other) const
{
if(NodePtr p = m_icont.unlink_leftmost_without_rebalance()){
//First recycle a node (this can't throw)
BOOST_TRY{
//This can throw
p->do_assign(other.m_data);
return p;
}
BOOST_CATCH(...){
//If there is an exception destroy the whole source
m_holder.destroy_node(p);
while((p = m_icont.unlink_leftmost_without_rebalance())){
m_holder.destroy_node(p);
}
BOOST_RETHROW
}
BOOST_CATCH_END
}
else{
return m_holder.create_node(other.m_data);
}
}
AllocHolder &m_holder;
Icont &m_icont;
};
class RecyclingMoveCloner;
friend class RecyclingMoveCloner;
class RecyclingMoveCloner
{
public:
RecyclingMoveCloner(AllocHolder &holder, Icont &irbtree)
: m_holder(holder), m_icont(irbtree)
{}
NodePtr operator()(const Node &other) const
{
if(NodePtr p = m_icont.unlink_leftmost_without_rebalance()){
//First recycle a node (this can't throw)
BOOST_TRY{
//This can throw
p->do_move_assign(const_cast<Node &>(other).m_data);
return p;
}
BOOST_CATCH(...){
//If there is an exception destroy the whole source
m_holder.destroy_node(p);
while((p = m_icont.unlink_leftmost_without_rebalance())){
m_holder.destroy_node(p);
}
BOOST_RETHROW
}
BOOST_CATCH_END
}
else{
return m_holder.create_node(other.m_data);
}
}
AllocHolder &m_holder;
Icont &m_icont;
};
BOOST_COPYABLE_AND_MOVABLE(rbtree)
BOOST_COPYABLE_AND_MOVABLE(tree)
public:
@@ -363,45 +498,16 @@ class rbtree
allocator_traits<A>::size_type size_type;
typedef typename boost::container::
allocator_traits<A>::difference_type difference_type;
typedef difference_type rbtree_difference_type;
typedef pointer rbtree_pointer;
typedef const_pointer rbtree_const_pointer;
typedef reference rbtree_reference;
typedef const_reference rbtree_const_reference;
typedef difference_type tree_difference_type;
typedef pointer tree_pointer;
typedef const_pointer tree_const_pointer;
typedef reference tree_reference;
typedef const_reference tree_const_reference;
typedef NodeAlloc stored_allocator_type;
private:
template<class KeyValueCompare>
struct key_node_compare
: private KeyValueCompare
{
key_node_compare(const KeyValueCompare &comp)
: KeyValueCompare(comp)
{}
template<class T>
struct is_node
{
static const bool value = is_same<T, Node>::value;
};
template<class T>
typename enable_if_c<is_node<T>::value, const value_type &>::type
key_forward(const T &node) const
{ return node.get_data(); }
template<class T>
typename enable_if_c<!is_node<T>::value, const T &>::type
key_forward(const T &key) const
{ return key; }
template<class KeyType, class KeyType2>
bool operator()(const KeyType &key1, const KeyType2 &key2) const
{ return KeyValueCompare::operator()(this->key_forward(key1), this->key_forward(key2)); }
};
typedef key_node_compare<value_compare> KeyNodeCompare;
typedef key_node_compare<value_compare, Node> KeyNodeCompare;
public:
typedef container_detail::iterator<iiterator, false> iterator;
@@ -409,20 +515,20 @@ class rbtree
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
rbtree()
tree()
: AllocHolder(ValComp(key_compare()))
{}
explicit rbtree(const key_compare& comp, const allocator_type& a = allocator_type())
explicit tree(const key_compare& comp, const allocator_type& a = allocator_type())
: AllocHolder(a, ValComp(comp))
{}
explicit rbtree(const allocator_type& a)
explicit tree(const allocator_type& a)
: AllocHolder(a)
{}
template <class InputIterator>
rbtree(bool unique_insertion, InputIterator first, InputIterator last, const key_compare& comp,
tree(bool unique_insertion, InputIterator first, InputIterator last, const key_compare& comp,
const allocator_type& a
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
, typename container_detail::enable_if_c
@@ -450,7 +556,7 @@ class rbtree
}
template <class InputIterator>
rbtree(bool unique_insertion, InputIterator first, InputIterator last, const key_compare& comp,
tree(bool unique_insertion, InputIterator first, InputIterator last, const key_compare& comp,
const allocator_type& a
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
, typename container_detail::enable_if_c
@@ -479,7 +585,7 @@ class rbtree
}
template <class InputIterator>
rbtree( ordered_range_t, InputIterator first, InputIterator last
tree( ordered_range_t, InputIterator first, InputIterator last
, const key_compare& comp = key_compare(), const allocator_type& a = allocator_type()
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
, typename container_detail::enable_if_c
@@ -496,7 +602,7 @@ class rbtree
}
template <class InputIterator>
rbtree( ordered_range_t, InputIterator first, InputIterator last
tree( ordered_range_t, InputIterator first, InputIterator last
, const key_compare& comp = key_compare(), const allocator_type& a = allocator_type()
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
, typename container_detail::enable_if_c
@@ -513,25 +619,25 @@ class rbtree
, container_detail::push_back_functor<Node, Icont>(this->icont()));
}
rbtree(const rbtree& x)
tree(const tree& x)
: AllocHolder(x, x.value_comp())
{
this->icont().clone_from
(x.icont(), typename AllocHolder::cloner(*this), Destroyer(this->node_alloc()));
}
rbtree(BOOST_RV_REF(rbtree) x)
tree(BOOST_RV_REF(tree) x)
: AllocHolder(::boost::move(static_cast<AllocHolder&>(x)), x.value_comp())
{}
rbtree(const rbtree& x, const allocator_type &a)
tree(const tree& x, const allocator_type &a)
: AllocHolder(a, x.value_comp())
{
this->icont().clone_from
(x.icont(), typename AllocHolder::cloner(*this), Destroyer(this->node_alloc()));
}
rbtree(BOOST_RV_REF(rbtree) x, const allocator_type &a)
tree(BOOST_RV_REF(tree) x, const allocator_type &a)
: AllocHolder(a, x.value_comp())
{
if(this->node_alloc() == x.node_alloc()){
@@ -543,10 +649,10 @@ class rbtree
}
}
~rbtree()
~tree()
{} //AllocHolder clears the tree
rbtree& operator=(BOOST_COPY_ASSIGN_REF(rbtree) x)
tree& operator=(BOOST_COPY_ASSIGN_REF(tree) x)
{
if (&x != this){
NodeAlloc &this_alloc = this->get_stored_allocator();
@@ -565,7 +671,7 @@ class rbtree
//Now recreate the source tree reusing nodes stored by other_tree
this->icont().clone_from
(x.icont()
, RecyclingCloner(*this, other_tree)
, RecyclingCloner<AllocHolder, false>(*this, other_tree)
, Destroyer(this->node_alloc()));
//If there are remaining nodes, destroy them
@@ -577,7 +683,7 @@ class rbtree
return *this;
}
rbtree& operator=(BOOST_RV_REF(rbtree) x)
tree& operator=(BOOST_RV_REF(tree) x)
{
if (&x != this){
NodeAlloc &this_alloc = this->get_stored_allocator();
@@ -600,7 +706,7 @@ class rbtree
//Now recreate the source tree reusing nodes stored by other_tree
this->icont().clone_from
(x.icont()
, RecyclingMoveCloner(*this, other_tree)
, RecyclingCloner<AllocHolder, true>(*this, other_tree)
, Destroyer(this->node_alloc()));
//If there are remaining nodes, destroy them
@@ -965,7 +1071,8 @@ class rbtree
void clear()
{ AllocHolder::clear(alloc_version()); }
// set operations:
// search operations. Const and non-const overloads even if no iterator is returned
// so splay implementations can to their rebalancing when searching in non-const versions
iterator find(const key_type& k)
{ return iterator(this->icont().find(k, KeyNodeCompare(value_comp()))); }
@@ -1001,70 +1108,47 @@ class rbtree
return std::pair<const_iterator,const_iterator>
(const_iterator(ret.first), const_iterator(ret.second));
}
std::pair<iterator,iterator> lower_bound_range(const key_type& k)
{
std::pair<iiterator, iiterator> ret =
this->icont().lower_bound_range(k, KeyNodeCompare(value_comp()));
return std::pair<iterator,iterator>(iterator(ret.first), iterator(ret.second));
}
std::pair<const_iterator, const_iterator> lower_bound_range(const key_type& k) const
{
std::pair<iiterator, iiterator> ret =
this->non_const_icont().lower_bound_range(k, KeyNodeCompare(value_comp()));
return std::pair<const_iterator,const_iterator>
(const_iterator(ret.first), const_iterator(ret.second));
}
void rebalance()
{ intrusive_tree_proxy_t::rebalance(this->icont()); }
friend bool operator==(const tree& x, const tree& y)
{ return x.size() == y.size() && std::equal(x.begin(), x.end(), y.begin()); }
friend bool operator<(const tree& x, const tree& y)
{ return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
friend bool operator!=(const tree& x, const tree& y)
{ return !(x == y); }
friend bool operator>(const tree& x, const tree& y)
{ return y < x; }
friend bool operator<=(const tree& x, const tree& y)
{ return !(y < x); }
friend bool operator>=(const tree& x, const tree& y)
{ return !(x < y); }
friend void swap(tree& x, tree& y)
{ x.swap(y); }
};
template <class Key, class Value, class KeyOfValue,
class KeyCompare, class A>
inline bool
operator==(const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& x,
const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& y)
{
return x.size() == y.size() &&
std::equal(x.begin(), x.end(), y.begin());
}
template <class Key, class Value, class KeyOfValue,
class KeyCompare, class A>
inline bool
operator<(const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& x,
const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& y)
{
return std::lexicographical_compare(x.begin(), x.end(),
y.begin(), y.end());
}
template <class Key, class Value, class KeyOfValue,
class KeyCompare, class A>
inline bool
operator!=(const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& x,
const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& y) {
return !(x == y);
}
template <class Key, class Value, class KeyOfValue,
class KeyCompare, class A>
inline bool
operator>(const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& x,
const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& y) {
return y < x;
}
template <class Key, class Value, class KeyOfValue,
class KeyCompare, class A>
inline bool
operator<=(const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& x,
const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& y) {
return !(y < x);
}
template <class Key, class Value, class KeyOfValue,
class KeyCompare, class A>
inline bool
operator>=(const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& x,
const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& y) {
return !(x < y);
}
template <class Key, class Value, class KeyOfValue,
class KeyCompare, class A>
inline void
swap(rbtree<Key,Value,KeyOfValue,KeyCompare,A>& x,
rbtree<Key,Value,KeyOfValue,KeyCompare,A>& y)
{
x.swap(y);
}
} //namespace container_detail {
} //namespace container {
/*
@@ -1073,7 +1157,7 @@ swap(rbtree<Key,Value,KeyOfValue,KeyCompare,A>& x,
template <class K, class V, class KOV,
class C, class A>
struct has_trivial_destructor_after_move
<boost::container::container_detail::rbtree<K, V, KOV, C, A> >
<boost::container::container_detail::tree<K, V, KOV, C, A> >
{
static const bool value = has_trivial_destructor_after_move<A>::value && has_trivial_destructor_after_move<C>::value;
};

View File

@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
// (C) Copyright John Maddock 2000.
// (C) Copyright Ion Gaztanaga 2005-2012.
// (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
@@ -19,7 +19,8 @@
# pragma once
#endif
#include "config_begin.hpp"
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/move/utility.hpp>

View File

@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// (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)
//
@@ -11,8 +11,9 @@
#ifndef BOOST_CONTAINER_DETAIL_UTILITIES_HPP
#define BOOST_CONTAINER_DETAIL_UTILITIES_HPP
#include "config_begin.hpp"
#include "workaround.hpp"
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <cstdio>
#include <cstring> //for ::memcpy
#include <boost/type_traits/is_fundamental.hpp>
@@ -24,6 +25,7 @@
#include <boost/move/core.hpp>
#include <boost/move/utility.hpp>
#include <boost/move/iterator.hpp>
#include <boost/container/throw_exception.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/type_traits.hpp>
#include <boost/container/allocator_traits.hpp>
@@ -109,25 +111,47 @@ template<class T>
const T &min_value(const T &a, const T &b)
{ return a < b ? a : b; }
template <class SizeType>
SizeType
get_next_capacity(const SizeType max_size
,const SizeType capacity
,const SizeType n)
enum NextCapacityOption { NextCapacityDouble, NextCapacity60Percent };
template<class SizeType, NextCapacityOption Option>
struct next_capacity_calculator;
template<class SizeType>
struct next_capacity_calculator<SizeType, NextCapacityDouble>
{
// if (n > max_size - capacity)
// throw std::length_error("get_next_capacity");
static SizeType get(const SizeType max_size
,const SizeType capacity
,const SizeType n)
{
const SizeType remaining = max_size - capacity;
if ( remaining < n )
boost::container::throw_length_error("get_next_capacity, allocator's max_size reached");
const SizeType additional = max_value(n, capacity);
return ( remaining < additional ) ? max_size : ( capacity + additional );
}
};
const SizeType m3 = max_size/3;
if (capacity < m3)
return capacity + max_value(3*(capacity+1)/5, n);
template<class SizeType>
struct next_capacity_calculator<SizeType, NextCapacity60Percent>
{
static SizeType get(const SizeType max_size
,const SizeType capacity
,const SizeType n)
{
const SizeType remaining = max_size - capacity;
if ( remaining < n )
boost::container::throw_length_error("get_next_capacity, allocator's max_size reached");
const SizeType m3 = max_size/3;
if (capacity < m3*2)
return capacity + max_value((capacity+1)/2, n);
if (capacity < m3)
return capacity + max_value(3*(capacity+1)/5, n);
return max_size;
}
if (capacity < m3*2)
return capacity + max_value((capacity+1)/2, n);
return max_size;
}
};
template <class T>
inline T* to_raw_pointer(T* p)

View File

@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2012.
// (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
@@ -17,7 +17,7 @@
# pragma once
#endif
#include "config_begin.hpp"
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
namespace boost {

View File

@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost
// (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)
//
@@ -15,8 +15,9 @@
# pragma once
#endif
#include "config_begin.hpp"
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/detail/type_traits.hpp>
#include <cstddef> //std::size_t

View File

@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// (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)
//
@@ -16,7 +16,8 @@
#ifndef BOOST_CONTAINER_DETAIL_VERSION_TYPE_HPP
#define BOOST_CONTAINER_DETAIL_VERSION_TYPE_HPP
#include "config_begin.hpp"
#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>
@@ -87,6 +88,6 @@ struct version
} //namespace container {
} //namespace boost{
#include "config_end.hpp"
#include <boost/container/detail/config_end.hpp>
#endif //#define BOOST_CONTAINER_DETAIL_VERSION_TYPE_HPP

View File

@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// (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)
//

View File

@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// (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)
//
@@ -34,18 +34,7 @@
namespace boost {
namespace container {
/// @cond
// Forward declarations of operators == and <, needed for friend declarations.
template <class Key, class T, class Compare, class Allocator>
class flat_map;
template <class Key, class T, class Compare, class Allocator>
inline bool operator==(const flat_map<Key,T,Compare,Allocator>& x,
const flat_map<Key,T,Compare,Allocator>& y);
template <class Key, class T, class Compare, class Allocator>
inline bool operator<(const flat_map<Key,T,Compare,Allocator>& x,
const flat_map<Key,T,Compare,Allocator>& y);
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
namespace container_detail{
@@ -62,8 +51,7 @@ static D force_copy(S s)
} //namespace container_detail{
/// @endcond
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//! A flat_map is a kind of associative container that supports unique keys (contains at
//! most one of each key value) and provides for fast retrieval of values of another
@@ -88,6 +76,12 @@ static D force_copy(S s)
//! pointing to elements that come after (their keys are bigger) the erased element.
//!
//! This container provides random-access iterators.
//!
//! \tparam Key is the key_type of the map
//! \tparam Value is the <code>mapped_type</code>
//! \tparam Compare is the ordering function for Keys (e.g. <i>std::less<Key></i>).
//! \tparam Allocator is the allocator to allocate the <code>value_type</code>s
//! (e.g. <i>allocator< std::pair<Key, T> > </i>).
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
template <class Key, class T, class Compare = std::less<Key>, class Allocator = std::allocator< std::pair< Key, T> > >
#else
@@ -95,7 +89,7 @@ template <class Key, class T, class Compare, class Allocator>
#endif
class flat_map
{
/// @cond
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
BOOST_COPYABLE_AND_MOVABLE(flat_map)
//This is the tree that we should store if pair was movable
@@ -129,7 +123,7 @@ class flat_map
<typename allocator_traits<Allocator>::pointer>::reverse_iterator reverse_iterator_impl;
typedef typename container_detail::get_flat_tree_iterators
<typename allocator_traits<Allocator>::pointer>::const_reverse_iterator const_reverse_iterator_impl;
/// @endcond
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
public:
@@ -168,7 +162,11 @@ class flat_map
//!
//! <b>Complexity</b>: Constant.
flat_map()
: m_flat_tree() {}
: m_flat_tree()
{
//Allocator type must be std::pair<CONST Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
}
//! <b>Effects</b>: Constructs an empty flat_map using the specified
//! comparison object and allocator.
@@ -176,14 +174,20 @@ class flat_map
//! <b>Complexity</b>: Constant.
explicit flat_map(const Compare& comp, const allocator_type& a = allocator_type())
: m_flat_tree(comp, container_detail::force<impl_allocator_type>(a))
{}
{
//Allocator type must be std::pair<CONST Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
}
//! <b>Effects</b>: Constructs an empty flat_map using the specified allocator.
//!
//! <b>Complexity</b>: Constant.
explicit flat_map(const allocator_type& a)
: m_flat_tree(container_detail::force<impl_allocator_type>(a))
{}
{
//Allocator type must be std::pair<CONST Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
}
//! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
//! allocator, and inserts elements from the range [first ,last ).
@@ -194,7 +198,10 @@ class flat_map
flat_map(InputIterator first, InputIterator last, const Compare& comp = Compare(),
const allocator_type& a = allocator_type())
: m_flat_tree(true, first, last, comp, container_detail::force<impl_allocator_type>(a))
{}
{
//Allocator type must be std::pair<CONST Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
}
//! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
//! allocator, and inserts elements from the ordered unique range [first ,last). This function
@@ -210,13 +217,20 @@ class flat_map
flat_map( ordered_unique_range_t, InputIterator first, InputIterator last
, const Compare& comp = Compare(), const allocator_type& a = allocator_type())
: m_flat_tree(ordered_range, first, last, comp, a)
{}
{
//Allocator type must be std::pair<CONST Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
}
//! <b>Effects</b>: Copy constructs a flat_map.
//!
//! <b>Complexity</b>: Linear in x.size().
flat_map(const flat_map& x)
: m_flat_tree(x.m_flat_tree) {}
: m_flat_tree(x.m_flat_tree)
{
//Allocator type must be std::pair<CONST Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
}
//! <b>Effects</b>: Move constructs a flat_map.
//! Constructs *this using x's resources.
@@ -226,14 +240,20 @@ class flat_map
//! <b>Postcondition</b>: x is emptied.
flat_map(BOOST_RV_REF(flat_map) x)
: m_flat_tree(boost::move(x.m_flat_tree))
{}
{
//Allocator type must be std::pair<CONST Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
}
//! <b>Effects</b>: Copy constructs a flat_map using the specified allocator.
//!
//! <b>Complexity</b>: Linear in x.size().
flat_map(const flat_map& x, const allocator_type &a)
: m_flat_tree(x.m_flat_tree, a)
{}
{
//Allocator type must be std::pair<CONST Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
}
//! <b>Effects</b>: Move constructs a flat_map using the specified allocator.
//! Constructs *this using x's resources.
@@ -241,7 +261,10 @@ class flat_map
//! <b>Complexity</b>: Constant if x.get_allocator() == a, linear otherwise.
flat_map(BOOST_RV_REF(flat_map) x, const allocator_type &a)
: m_flat_tree(boost::move(x.m_flat_tree), a)
{}
{
//Allocator type must be std::pair<CONST Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
}
//! <b>Effects</b>: Makes *this a copy of x.
//!
@@ -834,22 +857,57 @@ class flat_map
//!
//! <b>Complexity</b>: Logarithmic
std::pair<iterator,iterator> equal_range(const key_type& x)
{ return container_detail::force_copy<std::pair<iterator,iterator> >(m_flat_tree.equal_range(x)); }
{ return container_detail::force_copy<std::pair<iterator,iterator> >(m_flat_tree.lower_bound_range(x)); }
//! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
//!
//! <b>Complexity</b>: Logarithmic
std::pair<const_iterator,const_iterator> equal_range(const key_type& x) const
{ return container_detail::force_copy<std::pair<const_iterator,const_iterator> >(m_flat_tree.equal_range(x)); }
{ return container_detail::force_copy<std::pair<const_iterator,const_iterator> >(m_flat_tree.lower_bound_range(x)); }
/// @cond
template <class K1, class T1, class C1, class A1>
friend bool operator== (const flat_map<K1, T1, C1, A1>&,
const flat_map<K1, T1, C1, A1>&);
template <class K1, class T1, class C1, class A1>
friend bool operator< (const flat_map<K1, T1, C1, A1>&,
const flat_map<K1, T1, C1, A1>&);
//! <b>Effects</b>: Returns true if x and y are equal
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator==(const flat_map& x, const flat_map& y)
{ return x.size() == y.size() && std::equal(x.begin(), x.end(), y.begin()); }
//! <b>Effects</b>: Returns true if x and y are unequal
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator!=(const flat_map& x, const flat_map& y)
{ return !(x == y); }
//! <b>Effects</b>: Returns true if x is less than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator<(const flat_map& x, const flat_map& y)
{ return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
//! <b>Effects</b>: Returns true if x is greater than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator>(const flat_map& x, const flat_map& y)
{ return y < x; }
//! <b>Effects</b>: Returns true if x is equal or less than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator<=(const flat_map& x, const flat_map& y)
{ return !(y < x); }
//! <b>Effects</b>: Returns true if x is equal or greater than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator>=(const flat_map& x, const flat_map& y)
{ return !(x < y); }
//! <b>Effects</b>: x.swap(y)
//!
//! <b>Complexity</b>: Constant.
friend void swap(flat_map& x, flat_map& y)
{ x.swap(y); }
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
mapped_type &priv_subscript(const key_type& k)
{
@@ -872,45 +930,10 @@ class flat_map
}
return (*i).second;
}
/// @endcond
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
};
template <class Key, class T, class Compare, class Allocator>
inline bool operator==(const flat_map<Key,T,Compare,Allocator>& x,
const flat_map<Key,T,Compare,Allocator>& y)
{ return x.m_flat_tree == y.m_flat_tree; }
template <class Key, class T, class Compare, class Allocator>
inline bool operator<(const flat_map<Key,T,Compare,Allocator>& x,
const flat_map<Key,T,Compare,Allocator>& y)
{ return x.m_flat_tree < y.m_flat_tree; }
template <class Key, class T, class Compare, class Allocator>
inline bool operator!=(const flat_map<Key,T,Compare,Allocator>& x,
const flat_map<Key,T,Compare,Allocator>& y)
{ return !(x == y); }
template <class Key, class T, class Compare, class Allocator>
inline bool operator>(const flat_map<Key,T,Compare,Allocator>& x,
const flat_map<Key,T,Compare,Allocator>& y)
{ return y < x; }
template <class Key, class T, class Compare, class Allocator>
inline bool operator<=(const flat_map<Key,T,Compare,Allocator>& x,
const flat_map<Key,T,Compare,Allocator>& y)
{ return !(y < x); }
template <class Key, class T, class Compare, class Allocator>
inline bool operator>=(const flat_map<Key,T,Compare,Allocator>& x,
const flat_map<Key,T,Compare,Allocator>& y)
{ return !(x < y); }
template <class Key, class T, class Compare, class Allocator>
inline void swap(flat_map<Key,T,Compare,Allocator>& x,
flat_map<Key,T,Compare,Allocator>& y)
{ x.swap(y); }
/// @cond
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
} //namespace container {
@@ -924,18 +947,7 @@ struct has_trivial_destructor_after_move<boost::container::flat_map<K, T, C, All
namespace container {
// Forward declaration of operators < and ==, needed for friend declaration.
template <class Key, class T, class Compare, class Allocator>
class flat_multimap;
template <class Key, class T, class Compare, class Allocator>
inline bool operator==(const flat_multimap<Key,T,Compare,Allocator>& x,
const flat_multimap<Key,T,Compare,Allocator>& y);
template <class Key, class T, class Compare, class Allocator>
inline bool operator<(const flat_multimap<Key,T,Compare,Allocator>& x,
const flat_multimap<Key,T,Compare,Allocator>& y);
/// @endcond
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//! A flat_multimap is a kind of associative container that supports equivalent keys
//! (possibly containing multiple copies of the same key value) and provides for
@@ -960,6 +972,12 @@ inline bool operator<(const flat_multimap<Key,T,Compare,Allocator>& x,
//! pointing to elements that come after (their keys are bigger) the erased element.
//!
//! This container provides random-access iterators.
//!
//! \tparam Key is the key_type of the map
//! \tparam Value is the <code>mapped_type</code>
//! \tparam Compare is the ordering function for Keys (e.g. <i>std::less<Key></i>).
//! \tparam Allocator is the allocator to allocate the <code>value_type</code>s
//! (e.g. <i>allocator< std::pair<Key, T> > </i>).
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
template <class Key, class T, class Compare = std::less<Key>, class Allocator = std::allocator< std::pair< Key, T> > >
#else
@@ -967,7 +985,7 @@ template <class Key, class T, class Compare, class Allocator>
#endif
class flat_multimap
{
/// @cond
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
BOOST_COPYABLE_AND_MOVABLE(flat_multimap)
typedef container_detail::flat_tree<Key,
@@ -999,7 +1017,7 @@ class flat_multimap
<typename allocator_traits<Allocator>::pointer>::reverse_iterator reverse_iterator_impl;
typedef typename container_detail::get_flat_tree_iterators
<typename allocator_traits<Allocator>::pointer>::const_reverse_iterator const_reverse_iterator_impl;
/// @endcond
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
public:
@@ -1037,7 +1055,11 @@ class flat_multimap
//!
//! <b>Complexity</b>: Constant.
flat_multimap()
: m_flat_tree() {}
: m_flat_tree()
{
//Allocator type must be std::pair<CONST Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
}
//! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison
//! object and allocator.
@@ -1046,14 +1068,20 @@ class flat_multimap
explicit flat_multimap(const Compare& comp,
const allocator_type& a = allocator_type())
: m_flat_tree(comp, container_detail::force<impl_allocator_type>(a))
{}
{
//Allocator type must be std::pair<CONST Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
}
//! <b>Effects</b>: Constructs an empty flat_multimap using the specified allocator.
//!
//! <b>Complexity</b>: Constant.
explicit flat_multimap(const allocator_type& a)
: m_flat_tree(container_detail::force<impl_allocator_type>(a))
{}
{
//Allocator type must be std::pair<CONST Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
}
//! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison object
//! and allocator, and inserts elements from the range [first ,last ).
@@ -1065,7 +1093,10 @@ class flat_multimap
const Compare& comp = Compare(),
const allocator_type& a = allocator_type())
: m_flat_tree(false, first, last, comp, container_detail::force<impl_allocator_type>(a))
{}
{
//Allocator type must be std::pair<CONST Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
}
//! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison object and
//! allocator, and inserts elements from the ordered range [first ,last). This function
@@ -1081,13 +1112,20 @@ class flat_multimap
const Compare& comp = Compare(),
const allocator_type& a = allocator_type())
: m_flat_tree(ordered_range, first, last, comp, a)
{}
{
//Allocator type must be std::pair<CONST Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
}
//! <b>Effects</b>: Copy constructs a flat_multimap.
//!
//! <b>Complexity</b>: Linear in x.size().
flat_multimap(const flat_multimap& x)
: m_flat_tree(x.m_flat_tree) { }
: m_flat_tree(x.m_flat_tree)
{
//Allocator type must be std::pair<CONST Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
}
//! <b>Effects</b>: Move constructs a flat_multimap. Constructs *this using x's resources.
//!
@@ -1096,14 +1134,20 @@ class flat_multimap
//! <b>Postcondition</b>: x is emptied.
flat_multimap(BOOST_RV_REF(flat_multimap) x)
: m_flat_tree(boost::move(x.m_flat_tree))
{}
{
//Allocator type must be std::pair<CONST Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
}
//! <b>Effects</b>: Copy constructs a flat_multimap using the specified allocator.
//!
//! <b>Complexity</b>: Linear in x.size().
flat_multimap(const flat_multimap& x, const allocator_type &a)
: m_flat_tree(x.m_flat_tree, a)
{}
{
//Allocator type must be std::pair<CONST Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
}
//! <b>Effects</b>: Move constructs a flat_multimap using the specified allocator.
//! Constructs *this using x's resources.
@@ -1111,7 +1155,10 @@ class flat_multimap
//! <b>Complexity</b>: Constant if a == x.get_allocator(), linear otherwise.
flat_multimap(BOOST_RV_REF(flat_multimap) x, const allocator_type &a)
: m_flat_tree(boost::move(x.m_flat_tree), a)
{ }
{
//Allocator type must be std::pair<CONST Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
}
//! <b>Effects</b>: Makes *this a copy of x.
//!
@@ -1637,54 +1684,52 @@ class flat_multimap
std::pair<const_iterator,const_iterator> equal_range(const key_type& x) const
{ return container_detail::force_copy<std::pair<const_iterator,const_iterator> >(m_flat_tree.equal_range(x)); }
/// @cond
template <class K1, class T1, class C1, class A1>
friend bool operator== (const flat_multimap<K1, T1, C1, A1>& x,
const flat_multimap<K1, T1, C1, A1>& y);
//! <b>Effects</b>: Returns true if x and y are equal
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator==(const flat_multimap& x, const flat_multimap& y)
{ return x.size() == y.size() && std::equal(x.begin(), x.end(), y.begin()); }
template <class K1, class T1, class C1, class A1>
friend bool operator< (const flat_multimap<K1, T1, C1, A1>& x,
const flat_multimap<K1, T1, C1, A1>& y);
/// @endcond
};
//! <b>Effects</b>: Returns true if x and y are unequal
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator!=(const flat_multimap& x, const flat_multimap& y)
{ return !(x == y); }
template <class Key, class T, class Compare, class Allocator>
inline bool operator==(const flat_multimap<Key,T,Compare,Allocator>& x,
const flat_multimap<Key,T,Compare,Allocator>& y)
{ return x.m_flat_tree == y.m_flat_tree; }
//! <b>Effects</b>: Returns true if x is less than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator<(const flat_multimap& x, const flat_multimap& y)
{ return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
template <class Key, class T, class Compare, class Allocator>
inline bool operator<(const flat_multimap<Key,T,Compare,Allocator>& x,
const flat_multimap<Key,T,Compare,Allocator>& y)
{ return x.m_flat_tree < y.m_flat_tree; }
template <class Key, class T, class Compare, class Allocator>
inline bool operator!=(const flat_multimap<Key,T,Compare,Allocator>& x,
const flat_multimap<Key,T,Compare,Allocator>& y)
{ return !(x == y); }
template <class Key, class T, class Compare, class Allocator>
inline bool operator>(const flat_multimap<Key,T,Compare,Allocator>& x,
const flat_multimap<Key,T,Compare,Allocator>& y)
//! <b>Effects</b>: Returns true if x is greater than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator>(const flat_multimap& x, const flat_multimap& y)
{ return y < x; }
template <class Key, class T, class Compare, class Allocator>
inline bool operator<=(const flat_multimap<Key,T,Compare,Allocator>& x,
const flat_multimap<Key,T,Compare,Allocator>& y)
//! <b>Effects</b>: Returns true if x is equal or less than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator<=(const flat_multimap& x, const flat_multimap& y)
{ return !(y < x); }
template <class Key, class T, class Compare, class Allocator>
inline bool operator>=(const flat_multimap<Key,T,Compare,Allocator>& x,
const flat_multimap<Key,T,Compare,Allocator>& y)
//! <b>Effects</b>: Returns true if x is equal or greater than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator>=(const flat_multimap& x, const flat_multimap& y)
{ return !(x < y); }
template <class Key, class T, class Compare, class Allocator>
inline void swap(flat_multimap<Key,T,Compare,Allocator>& x, flat_multimap<Key,T,Compare,Allocator>& y)
//! <b>Effects</b>: x.swap(y)
//!
//! <b>Complexity</b>: Constant.
friend void swap(flat_multimap& x, flat_multimap& y)
{ x.swap(y); }
};
}}
/// @cond
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
namespace boost {
@@ -1698,7 +1743,7 @@ struct has_trivial_destructor_after_move< boost::container::flat_multimap<K, T,
} //namespace boost {
/// @endcond
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
#include <boost/container/detail/config_end.hpp>

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// (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)
//
@@ -47,7 +47,7 @@
namespace boost {
namespace container {
/// @cond
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
namespace container_detail {
template<class VoidPointer>
@@ -99,7 +99,7 @@ struct intrusive_list_type
};
} //namespace container_detail {
/// @endcond
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//! A list is a doubly linked list. That is, it is a Sequence that supports both
//! forward and backward traversal, and (amortized) constant time insertion and
@@ -111,6 +111,9 @@ struct intrusive_list_type
//! after a list operation than it did before), but the iterators themselves will
//! not be invalidated or made to point to different elements unless that invalidation
//! or mutation is explicit.
//!
//! \tparam T The type of object that is stored in the list
//! \tparam Allocator The allocator used for all internal memory management
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
template <class T, class Allocator = std::allocator<T> >
#else
@@ -120,7 +123,7 @@ class list
: protected container_detail::node_alloc_holder
<Allocator, typename container_detail::intrusive_list_type<Allocator>::type>
{
/// @cond
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
typedef typename
container_detail::intrusive_list_type<Allocator>::type Icont;
typedef container_detail::node_alloc_holder<Allocator, Icont> AllocHolder;
@@ -167,7 +170,7 @@ class list
typedef container_detail::iterator<typename Icont::iterator, false> iterator_impl;
typedef container_detail::iterator<typename Icont::iterator, true> const_iterator_impl;
/// @endcond
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
public:
//////////////////////////////////////////////
@@ -1214,9 +1217,65 @@ class list
//!
//! <b>Note</b>: Iterators and references are not invalidated
void reverse() BOOST_CONTAINER_NOEXCEPT
{ this->icont().reverse(); }
{ this->icont().reverse(); }
/// @cond
//! <b>Effects</b>: Returns true if x and y are equal
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator==(const list& x, const list& y)
{
if(x.size() != y.size()){
return false;
}
typedef typename list::const_iterator const_iterator;
const_iterator end1 = x.end();
const_iterator i1 = x.begin();
const_iterator i2 = y.begin();
while (i1 != end1 && *i1 == *i2) {
++i1;
++i2;
}
return i1 == end1;
}
//! <b>Effects</b>: Returns true if x and y are unequal
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator!=(const list& x, const list& y)
{ return !(x == y); }
//! <b>Effects</b>: Returns true if x is less than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator<(const list& x, const list& y)
{ return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
//! <b>Effects</b>: Returns true if x is greater than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator>(const list& x, const list& y)
{ return y < x; }
//! <b>Effects</b>: Returns true if x is equal or less than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator<=(const list& x, const list& y)
{ return !(y < x); }
//! <b>Effects</b>: Returns true if x is equal or greater than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator>=(const list& x, const list& y)
{ return !(x < y); }
//! <b>Effects</b>: x.swap(y)
//!
//! <b>Complexity</b>: Constant.
friend void swap(list& x, list& y)
{ x.swap(y); }
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
bool priv_try_shrink(size_type new_size)
@@ -1303,66 +1362,11 @@ class list
bool operator()(const value_type &a, const value_type &b) const
{ return a == b; }
};
/// @endcond
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
};
template <class T, class Allocator>
inline bool operator==(const list<T,Allocator>& x, const list<T,Allocator>& y)
{
if(x.size() != y.size()){
return false;
}
typedef typename list<T,Allocator>::const_iterator const_iterator;
const_iterator end1 = x.end();
const_iterator i1 = x.begin();
const_iterator i2 = y.begin();
while (i1 != end1 && *i1 == *i2) {
++i1;
++i2;
}
return i1 == end1;
}
template <class T, class Allocator>
inline bool operator<(const list<T,Allocator>& x,
const list<T,Allocator>& y)
{
return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());
}
template <class T, class Allocator>
inline bool operator!=(const list<T,Allocator>& x, const list<T,Allocator>& y)
{
return !(x == y);
}
template <class T, class Allocator>
inline bool operator>(const list<T,Allocator>& x, const list<T,Allocator>& y)
{
return y < x;
}
template <class T, class Allocator>
inline bool operator<=(const list<T,Allocator>& x, const list<T,Allocator>& y)
{
return !(y < x);
}
template <class T, class Allocator>
inline bool operator>=(const list<T,Allocator>& x, const list<T,Allocator>& y)
{
return !(x < y);
}
template <class T, class Allocator>
inline void swap(list<T, Allocator>& x, list<T, Allocator>& y)
{
x.swap(y);
}
/// @cond
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
} //namespace container {
@@ -1375,7 +1379,7 @@ struct has_trivial_destructor_after_move<boost::container::list<T, Allocator> >
namespace container {
/// @endcond
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
}}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,346 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2008-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_POOLED_NODE_ALLOCATOR_HPP
#define BOOST_CONTAINER_POOLED_NODE_ALLOCATOR_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/container_fwd.hpp>
#include <boost/container/throw_exception.hpp>
#include <boost/container/detail/node_pool.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/multiallocation_chain.hpp>
#include <boost/container/detail/alloc_lib_auto_link.hpp>
#include <boost/container/detail/singleton.hpp>
#include <boost/iterator/transform_iterator.hpp>
#include <boost/assert.hpp>
#include <boost/utility/addressof.hpp>
#include <boost/static_assert.hpp>
#include <memory>
#include <algorithm>
#include <cstddef>
#include <new>
namespace boost {
namespace container {
//!An STL node allocator that uses a modified DlMalloc as memory
//!source.
//!
//!This node allocator shares a segregated storage between all instances
//!of node_allocator with equal sizeof(T).
//!
//!NodesPerBlock is the number of nodes allocated at once when the allocator
//!runs out of nodes
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
template
< class T
, std::size_t NodesPerBlock = NodeAlloc_nodes_per_block>
#else
template
< class T
, std::size_t NodesPerBlock
, std::size_t Version>
#endif
class node_allocator
{
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//! If Version is 1, the allocator is a STL conforming allocator. If Version is 2,
//! the allocator offers advanced expand in place and burst allocation capabilities.
public:
typedef unsigned int allocation_type;
typedef node_allocator<T, NodesPerBlock, Version> self_t;
static const std::size_t nodes_per_block = NodesPerBlock;
BOOST_STATIC_ASSERT((Version <=2));
#endif
public:
//-------
typedef T value_type;
typedef T * pointer;
typedef const T * const_pointer;
typedef typename ::boost::container::
container_detail::unvoid<T>::type & reference;
typedef const typename ::boost::container::
container_detail::unvoid<T>::type & const_reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef boost::container::container_detail::
version_type<self_t, Version> version;
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
typedef boost::container::container_detail::
basic_multiallocation_chain<void*> multiallocation_chain_void;
typedef boost::container::container_detail::
transform_multiallocation_chain
<multiallocation_chain_void, T> multiallocation_chain;
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//!Obtains node_allocator from
//!node_allocator
template<class T2>
struct rebind
{
typedef node_allocator< T2, NodesPerBlock
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
, Version
#endif
> other;
};
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
//!Not assignable from related node_allocator
template<class T2, std::size_t N2>
node_allocator& operator=
(const node_allocator<T2, N2>&);
//!Not assignable from other node_allocator
node_allocator& operator=(const node_allocator&);
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
public:
//!Default constructor
node_allocator() BOOST_CONTAINER_NOEXCEPT
{}
//!Copy constructor from other node_allocator.
node_allocator(const node_allocator &) BOOST_CONTAINER_NOEXCEPT
{}
//!Copy constructor from related node_allocator.
template<class T2>
node_allocator
(const node_allocator<T2, NodesPerBlock
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
, Version
#endif
> &) BOOST_CONTAINER_NOEXCEPT
{}
//!Destructor
~node_allocator() BOOST_CONTAINER_NOEXCEPT
{}
//!Returns the number of elements that could be allocated.
//!Never throws
size_type max_size() const
{ return size_type(-1)/sizeof(T); }
//!Allocate memory for an array of count elements.
//!Throws std::bad_alloc if there is no enough memory
pointer allocate(size_type count, const void * = 0)
{
if(count > this->max_size())
boost::container::throw_bad_alloc();
if(Version == 1 && count == 1){
typedef container_detail::shared_node_pool
<sizeof(T), NodesPerBlock> shared_pool_t;
typedef container_detail::singleton_default<shared_pool_t> singleton_t;
return pointer(static_cast<T*>(singleton_t::instance().allocate_node()));
}
else{
void *ret = boost_cont_malloc(count*sizeof(T));
if(!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_CONTAINER_NOEXCEPT
{
(void)count;
if(Version == 1 && count == 1){
typedef container_detail::shared_node_pool
<sizeof(T), NodesPerBlock> shared_pool_t;
typedef container_detail::singleton_default<shared_pool_t> singleton_t;
singleton_t::instance().deallocate_node(ptr);
}
else{
boost_cont_free(ptr);
}
}
//!Deallocates all free blocks of the pool
static void deallocate_free_blocks() BOOST_CONTAINER_NOEXCEPT
{
typedef container_detail::shared_node_pool
<sizeof(T), NodesPerBlock> shared_pool_t;
typedef container_detail::singleton_default<shared_pool_t> singleton_t;
singleton_t::instance().deallocate_free_blocks();
}
std::pair<pointer, bool>
allocation_command(allocation_type command,
size_type limit_size,
size_type preferred_size,
size_type &received_size, pointer reuse = pointer())
{
BOOST_STATIC_ASSERT(( Version > 1 ));
std::pair<pointer, bool> ret =
priv_allocation_command(command, limit_size, preferred_size, received_size, reuse);
if(!ret.first && !(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_CONTAINER_NOEXCEPT
{
BOOST_STATIC_ASSERT(( Version > 1 ));
return boost_cont_size(p);
}
//!Allocates just one object. Memory allocated with this function
//!must be deallocated only with deallocate_one().
//!Throws bad_alloc if there is no enough memory
pointer allocate_one()
{
BOOST_STATIC_ASSERT(( Version > 1 ));
typedef container_detail::shared_node_pool
<sizeof(T), NodesPerBlock> shared_pool_t;
typedef container_detail::singleton_default<shared_pool_t> singleton_t;
return (pointer)singleton_t::instance().allocate_node();
}
//!Allocates many elements of size == 1.
//!Elements must be individually deallocated with deallocate_one()
void allocate_individual(std::size_t num_elements, multiallocation_chain &chain)
{
BOOST_STATIC_ASSERT(( Version > 1 ));
typedef container_detail::shared_node_pool
<sizeof(T), NodesPerBlock> shared_pool_t;
typedef container_detail::singleton_default<shared_pool_t> singleton_t;
typename shared_pool_t::multiallocation_chain ch;
singleton_t::instance().allocate_nodes(num_elements, ch);
chain.incorporate_after(chain.before_begin(), (T*)&*ch.begin(), (T*)&*ch.last(), ch.size());
}
//!Deallocates memory previously allocated with allocate_one().
//!You should never use deallocate_one to deallocate memory allocated
//!with other functions different from allocate_one(). Never throws
void deallocate_one(pointer p) BOOST_CONTAINER_NOEXCEPT
{
BOOST_STATIC_ASSERT(( Version > 1 ));
typedef container_detail::shared_node_pool
<sizeof(T), NodesPerBlock> shared_pool_t;
typedef container_detail::singleton_default<shared_pool_t> singleton_t;
singleton_t::instance().deallocate_node(p);
}
void deallocate_individual(multiallocation_chain &chain) BOOST_CONTAINER_NOEXCEPT
{
BOOST_STATIC_ASSERT(( Version > 1 ));
typedef container_detail::shared_node_pool
<sizeof(T), NodesPerBlock> shared_pool_t;
typedef container_detail::singleton_default<shared_pool_t> singleton_t;
typename shared_pool_t::multiallocation_chain ch(&*chain.begin(), &*chain.last(), chain.size());
singleton_t::instance().deallocate_nodes(ch);
}
//!Allocates many elements of size elem_size.
//!Elements must be individually deallocated with deallocate()
void allocate_many(size_type elem_size, std::size_t n_elements, multiallocation_chain &chain)
{
BOOST_STATIC_ASSERT(( Version > 1 ));
boost_cont_memchain ch;
BOOST_CONTAINER_MEMCHAIN_INIT(&ch);
if(!boost_cont_multialloc_nodes(n_elements, elem_size*sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &ch)){
boost::container::throw_bad_alloc();
}
chain.incorporate_after( chain.before_begin()
, (T*)BOOST_CONTAINER_MEMCHAIN_LASTMEM(&ch)
, (T*)BOOST_CONTAINER_MEMCHAIN_LASTMEM(&ch)
, BOOST_CONTAINER_MEMCHAIN_SIZE(&ch));
}
//!Allocates n_elements elements, each one of size elem_sizes[i]
//!Elements must be individually deallocated with deallocate()
void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain)
{
BOOST_STATIC_ASSERT(( Version > 1 ));
boost_cont_memchain ch;
boost_cont_multialloc_arrays(n_elements, elem_sizes, sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &ch);
if(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_CONTAINER_NOEXCEPT
{
BOOST_STATIC_ASSERT(( Version > 1 ));
void *first = &*chain.begin();
void *last = &*chain.last();
size_t num = chain.size();
boost_cont_memchain ch;
BOOST_CONTAINER_MEMCHAIN_INIT_FROM(&ch, first, last, num);
boost_cont_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_CONTAINER_NOEXCEPT
{}
//!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_CONTAINER_NOEXCEPT
{ 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_CONTAINER_NOEXCEPT
{ return false; }
private:
std::pair<pointer, bool> priv_allocation_command
(allocation_type command, std::size_t limit_size
,std::size_t preferred_size,std::size_t &received_size, void *reuse_ptr)
{
boost_cont_command_ret_t ret = {0 , 0};
if(limit_size > this->max_size() || preferred_size > this->max_size()){
//ret.first = 0;
return std::pair<pointer, bool>(pointer(), false);
}
std::size_t l_size = limit_size*sizeof(T);
std::size_t p_size = preferred_size*sizeof(T);
std::size_t r_size;
{
ret = boost_cont_allocation_command(command, sizeof(T), l_size, p_size, &r_size, reuse_ptr);
}
received_size = r_size/sizeof(T);
return std::pair<pointer, bool>(static_cast<pointer>(ret.first), !!ret.second);
}
};
} //namespace container {
} //namespace boost {
#include <boost/container/detail/config_end.hpp>
#endif //#ifndef BOOST_CONTAINER_POOLED_NODE_ALLOCATOR_HPP

View File

@@ -0,0 +1,72 @@
/////////////////////////////////////////////////////////////////////////////
//
// (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
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/container_fwd.hpp>
#include <boost/intrusive/pack_options.hpp>
namespace boost {
namespace container {
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
template<tree_type_enum TreeType, bool OptimizeSize>
struct tree_opt
{
static const boost::container::tree_type_enum tree_type = TreeType;
static const bool optimize_size = OptimizeSize;
};
#endif //!defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//!This option setter specifies the underlying tree type
//!(red-black, AVL, Scapegoat or Splay) for ordered associative containers
BOOST_INTRUSIVE_OPTION_CONSTANT(tree_type, tree_type_enum, TreeType, tree_type)
//!This option setter specifies if node size is optimized
//!storing rebalancing data masked into pointers for ordered associative containers
BOOST_INTRUSIVE_OPTION_CONSTANT(optimize_size, bool, Enabled, optimize_size)
//! Helper metafunction to combine options into a single type to be used
//! by \c boost::container::set, \c boost::container::multiset
//! \c boost::container::map and \c boost::container::multimap.
//! Supported options are: \c boost::container::optimize_size and \c boost::container::tree_type
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) || defined(BOOST_CONTAINER_VARIADIC_TEMPLATES)
template<class ...Options>
#else
template<class O1 = void, class O2 = void, class O3 = void, class O4 = void>
#endif
struct tree_assoc_options
{
/// @cond
typedef typename ::boost::intrusive::pack_options
< tree_assoc_defaults,
#if !defined(BOOST_CONTAINER_VARIADIC_TEMPLATES)
O1, O2, O3, O4
#else
Options...
#endif
>::type packed_options;
typedef tree_opt<packed_options::tree_type, packed_options::optimize_size> implementation_defined;
/// @endcond
typedef implementation_defined type;
};
} //namespace container {
} //namespace boost {
#include <boost/container/detail/config_end.hpp>
#endif //#ifndef BOOST_CONTAINER_OPTIONS_HPP

View File

@@ -6,7 +6,7 @@
//
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2011-2012. Distributed under the Boost
// (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)
//
@@ -46,7 +46,7 @@ namespace boost { namespace container {
//! and if T is used in a context where a container must call such a constructor, then the program is
//! ill-formed.
//!
//! [Example:
//! <code>
//! template <class T, class Allocator = allocator<T> >
//! class Z {
//! public:
@@ -64,7 +64,7 @@ namespace boost { namespace container {
//! template <class T, class Allocator = allocator<T> >
//! struct constructible_with_allocator_suffix<Z<T,Allocator> >
//! : ::boost::true_type { };
//! -- end example]
//! </code>
//!
//! <b>Note</b>: This trait is a workaround inspired by "N2554: The Scoped Allocator Model (Rev 2)"
//! (Pablo Halpern, 2008-02-29) to backport the scoped allocator model to C++03, as
@@ -90,7 +90,7 @@ struct constructible_with_allocator_suffix
//! called with these initial arguments, and if T is used in a context where a container must call such
//! a constructor, then the program is ill-formed.
//!
//! [Example:
//! <code>
//! template <class T, class Allocator = allocator<T> >
//! class Y {
//! public:
@@ -115,7 +115,7 @@ struct constructible_with_allocator_suffix
//! struct constructible_with_allocator_prefix<Y<T,Allocator> >
//! : ::boost::true_type { };
//!
//! -- end example]
//! </code>
//!
//! <b>Note</b>: This trait is a workaround inspired by "N2554: The Scoped Allocator Model (Rev 2)"
//! (Pablo Halpern, 2008-02-29) to backport the scoped allocator model to C++03, as
@@ -130,7 +130,7 @@ struct constructible_with_allocator_prefix
: ::boost::false_type
{};
///@cond
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
namespace container_detail {
@@ -159,7 +159,7 @@ struct uses_allocator_imp
} //namespace container_detail {
///@endcond
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//! <b>Remark</b>: Automatically detects if T has a nested allocator_type that is convertible from
//! Alloc. Meets the BinaryTypeTrait requirements ([meta.rqmts] 20.4.1). A program may
@@ -173,7 +173,7 @@ struct uses_allocator
: boost::integral_constant<bool, container_detail::uses_allocator_imp<T, Alloc>::value>
{};
///@cond
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
namespace container_detail {
@@ -675,16 +675,16 @@ class scoped_allocator_adaptor_base
friend void swap(scoped_allocator_adaptor_base &l, scoped_allocator_adaptor_base &r)
{ l.swap(r); }
inner_allocator_type& inner_allocator()
inner_allocator_type& inner_allocator() BOOST_CONTAINER_NOEXCEPT
{ return m_inner; }
inner_allocator_type const& inner_allocator() const
inner_allocator_type const& inner_allocator() const BOOST_CONTAINER_NOEXCEPT
{ return m_inner; }
outer_allocator_type & outer_allocator()
outer_allocator_type & outer_allocator() BOOST_CONTAINER_NOEXCEPT
{ return static_cast<outer_allocator_type&>(*this); }
const outer_allocator_type &outer_allocator() const
const outer_allocator_type &outer_allocator() const BOOST_CONTAINER_NOEXCEPT
{ return static_cast<const outer_allocator_type&>(*this); }
scoped_allocator_type select_on_container_copy_construction() const
@@ -1008,7 +1008,7 @@ class scoped_allocator_adaptor_base
} //namespace container_detail {
///@endcond
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//Scoped allocator
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
@@ -1038,14 +1038,14 @@ class scoped_allocator_adaptor_base
//! 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, `OUTERMOST(x)` is x if x does not have
//! an `outer_allocator()` member function and
//! `OUTERMOST(x.outer_allocator())` otherwise; `OUTERMOST_ALLOC_TRAITS(x)` is
//! `allocator_traits<decltype(OUTERMOST(x))>`.
//! 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>: `OUTERMOST(x)` and
//! `OUTERMOST_ALLOC_TRAITS(x)` are recursive operations. It is incumbent upon
//! the definition of `outer_allocator()` to ensure that the recursion terminates.
//! [<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
@@ -1076,7 +1076,7 @@ class scoped_allocator_adaptor
BOOST_COPYABLE_AND_MOVABLE(scoped_allocator_adaptor)
public:
/// @cond
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
typedef container_detail::scoped_allocator_adaptor_base
<OuterAlloc
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
@@ -1086,13 +1086,13 @@ class scoped_allocator_adaptor
#endif
> base_type;
typedef typename base_type::internal_type_t internal_type_t;
/// @endcond
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
typedef OuterAlloc outer_allocator_type;
//! Type: For exposition only
//!
typedef allocator_traits<OuterAlloc> outer_traits_type;
//! Type: `scoped_allocator_adaptor<OuterAlloc>` if `sizeof...(InnerAllocs)` is zero; otherwise,
//! `scoped_allocator_adaptor<InnerAllocs...>`.
//! 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;
@@ -1102,23 +1102,23 @@ class scoped_allocator_adaptor
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: `true_type` if `allocator_traits<Allocator>::propagate_on_container_copy_assignment::value` is
//! true for any `Allocator` in the set of `OuterAlloc` and `InnerAllocs...`; otherwise, false_type.
//! Type: <code>true_type</code> if <code>allocator_traits<Allocator>::propagate_on_container_copy_assignment::value</code> is
//! true for any <code>Allocator</code> in the set of <code>OuterAlloc</code> and <code>InnerAllocs...</code>; otherwise, false_type.
typedef typename base_type::
propagate_on_container_copy_assignment propagate_on_container_copy_assignment;
//! Type: `true_type` if `allocator_traits<Allocator>::propagate_on_container_move_assignment::value` is
//! true for any `Allocator` in the set of `OuterAlloc` and `InnerAllocs...`; otherwise, false_type.
//! Type: <code>true_type</code> if <code>allocator_traits<Allocator>::propagate_on_container_move_assignment::value</code> is
//! true for any <code>Allocator</code> in the set of <code>OuterAlloc</code> and <code>InnerAllocs...</code>; otherwise, false_type.
typedef typename base_type::
propagate_on_container_move_assignment propagate_on_container_move_assignment;
//! Type: `true_type` if `allocator_traits<Allocator>::propagate_on_container_swap::value` is true for any
//! `Allocator` in the set of `OuterAlloc` and `InnerAllocs...`; otherwise, false_type.
//! Type: <code>true_type</code> if <code>allocator_traits<Allocator>::propagate_on_container_swap::value</code> is true for any
//! <code>Allocator</code> in the set of <code>OuterAlloc</code> and <code>InnerAllocs...</code>; otherwise, false_type.
typedef typename base_type::
propagate_on_container_swap propagate_on_container_swap;
//! Type: Rebinds scoped allocator to
//! `typedef scoped_allocator_adaptor
//! <code>typedef scoped_allocator_adaptor
//! < typename outer_traits_type::template portable_rebind_alloc<U>::type
//! , InnerAllocs... >`
//! , InnerAllocs... ></code>
template <class U>
struct rebind
{
@@ -1224,55 +1224,55 @@ class scoped_allocator_adaptor
friend void swap(scoped_allocator_adaptor &l, scoped_allocator_adaptor &r);
//! <b>Returns</b>:
//! `static_cast<OuterAlloc&>(*this)`.
outer_allocator_type & outer_allocator();
//! <code>static_cast<OuterAlloc&>(*this)</code>.
outer_allocator_type & outer_allocator() BOOST_CONTAINER_NOEXCEPT;
//! <b>Returns</b>:
//! `static_cast<const OuterAlloc&>(*this)`.
const outer_allocator_type &outer_allocator() const;
//! <code>static_cast<const OuterAlloc&>(*this)</code>.
const outer_allocator_type &outer_allocator() const BOOST_CONTAINER_NOEXCEPT;
//! <b>Returns</b>:
//! *this if `sizeof...(InnerAllocs)` is zero; otherwise, inner.
inner_allocator_type& inner_allocator();
//! *this if <code>sizeof...(InnerAllocs)</code> is zero; otherwise, inner.
inner_allocator_type& inner_allocator() BOOST_CONTAINER_NOEXCEPT;
//! <b>Returns</b>:
//! *this if `sizeof...(InnerAllocs)` is zero; otherwise, inner.
inner_allocator_type const& inner_allocator() const;
//! *this if <code>sizeof...(InnerAllocs)</code> is zero; otherwise, inner.
inner_allocator_type const& inner_allocator() const BOOST_CONTAINER_NOEXCEPT;
#endif //BOOST_CONTAINER_DOXYGEN_INVOKED
//! <b>Returns</b>:
//! `allocator_traits<OuterAlloc>::max_size(outer_allocator())`.
size_type max_size() const
//! <code>allocator_traits<OuterAlloc>::max_size(outer_allocator())</code>.
size_type max_size() const BOOST_CONTAINER_NOEXCEPT
{
return outer_traits_type::max_size(this->outer_allocator());
}
//! <b>Effects</b>:
//! calls `OUTERMOST_ALLOC_TRAITS(*this)::destroy(OUTERMOST(*this), p)`.
//! calls <code>OUTERMOST_ALLOC_TRAITS(*this)::destroy(OUTERMOST(*this), p)</code>.
template <class T>
void destroy(T* p)
void destroy(T* p) BOOST_CONTAINER_NOEXCEPT
{
allocator_traits<typename outermost_allocator<OuterAlloc>::type>
::destroy(get_outermost_allocator(this->outer_allocator()), p);
}
//! <b>Returns</b>:
//! `allocator_traits<OuterAlloc>::allocate(outer_allocator(), n)`.
//! <code>allocator_traits<OuterAlloc>::allocate(outer_allocator(), n)</code>.
pointer allocate(size_type n)
{
return outer_traits_type::allocate(this->outer_allocator(), n);
}
//! <b>Returns</b>:
//! `allocator_traits<OuterAlloc>::allocate(outer_allocator(), n, hint)`.
//! <code>allocator_traits<OuterAlloc>::allocate(outer_allocator(), n, hint)</code>.
pointer allocate(size_type n, const_void_pointer hint)
{
return outer_traits_type::allocate(this->outer_allocator(), n, hint);
}
//! <b>Effects</b>:
//! `allocator_traits<OuterAlloc>::deallocate(outer_allocator(), p, n)`.
//! <code>allocator_traits<OuterAlloc>::deallocate(outer_allocator(), p, n)</code>.
void deallocate(pointer p, size_type n)
{
outer_traits_type::deallocate(this->outer_allocator(), p, n);
@@ -1281,45 +1281,45 @@ class scoped_allocator_adaptor
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
//! <b>Returns</b>: Allocator new scoped_allocator_adaptor object where each allocator
//! A in the adaptor is initialized from the result of calling
//! `allocator_traits<Allocator>::select_on_container_copy_construction()` on
//! <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
/// @cond
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
base_type &base() { return *this; }
const base_type &base() const { return *this; }
/// @endcond
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//! <b>Effects</b>:
//! 1) If `uses_allocator<T, inner_allocator_type>::value` is false calls
//! `OUTERMOST_ALLOC_TRAITS(*this)::construct
//! (OUTERMOST(*this), p, std::forward<Args>(args)...)`.
//! 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 `uses_allocator<T, inner_allocator_type>::value` is true and
//! `is_constructible<T, allocator_arg_t, inner_allocator_type, Args...>::value` is true, calls
//! `OUTERMOST_ALLOC_TRAITS(*this)::construct(OUTERMOST(*this), p, allocator_arg,
//! inner_allocator(), std::forward<Args>(args)...)`.
//! 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, `is_constructible` can't
//! [<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
//! `is_constructible<T, Args..., inner_allocator_type>::value` is true, calls
//! `OUTERMOST_ALLOC_TRAITS(*this)::construct(OUTERMOST(*this), p,
//! std::forward<Args>(args)..., inner_allocator())`.
//! <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, `is_constructible` can't be
//! [<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_suffix<T>::value`. -end note]
//! <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 `uses_allocator` evaluates
//! [<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>
@@ -1395,7 +1395,7 @@ class scoped_allocator_adaptor
, BOOST_RV_REF_BEG container_detail::pair<U, V> BOOST_RV_REF_END x)
{ this->construct_pair(p, x); }
/// @cond
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
template <class Pair>
void construct_pair(Pair* p)
@@ -1463,7 +1463,7 @@ class scoped_allocator_adaptor
: base_type(internal_type_t(), ::boost::forward<OuterA2>(outer), inner)
{}
/// @endcond
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
};
template <typename OuterA1, typename OuterA2

View File

@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2011-2012. Distributed under the Boost
// (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)
//
@@ -11,6 +11,10 @@
#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
//! and defines the following types:
#if defined(_MSC_VER)
# pragma once
#endif
@@ -25,7 +29,7 @@
namespace boost { namespace container {
///@cond
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
@@ -55,7 +59,7 @@ class scoped_allocator_adaptor;
#endif
///@endcond
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//! The allocator_arg_t struct is an empty structure type used as a unique type to
//! disambiguate constructor and function overloading. Specifically, several types

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2004-2012. Distributed under the Boost
// (C) Copyright Ion Gaztanaga 2004-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)
//
@@ -48,7 +48,7 @@
namespace boost {
namespace container {
/// @cond
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
template <class T, class Allocator>
class slist;
@@ -106,7 +106,7 @@ struct intrusive_slist_type
} //namespace container_detail {
/// @endcond
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//! An slist is a singly linked list: a list where each element is linked to the next
//! element, but not to the previous element. That is, it is a Sequence that
@@ -140,6 +140,9 @@ struct intrusive_slist_type
//! possible. If you find that insert_after and erase_after aren't adequate for your
//! needs, and that you often need to use insert and erase in the middle of the list,
//! then you should probably use list instead of slist.
//!
//! \tparam T The type of object that is stored in the list
//! \tparam Allocator The allocator used for all internal memory management
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
template <class T, class Allocator = std::allocator<T> >
#else
@@ -149,7 +152,7 @@ class slist
: protected container_detail::node_alloc_holder
<Allocator, typename container_detail::intrusive_slist_type<Allocator>::type>
{
/// @cond
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
typedef typename
container_detail::intrusive_slist_type<Allocator>::type Icont;
typedef container_detail::node_alloc_holder<Allocator, Icont> AllocHolder;
@@ -195,7 +198,7 @@ class slist
BOOST_COPYABLE_AND_MOVABLE(slist)
typedef container_detail::iterator<typename Icont::iterator, false> iterator_impl;
typedef container_detail::iterator<typename Icont::iterator, true > const_iterator_impl;
/// @endcond
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
public:
//////////////////////////////////////////////
@@ -313,7 +316,7 @@ class slist
this->icont().swap(x.icont());
}
else{
this->insert(this->cbegin(), x.begin(), x.end());
this->insert_after(this->cbefore_begin(), x.begin(), x.end());
}
}
@@ -1423,14 +1426,70 @@ class slist
void splice(const_iterator p, BOOST_RV_REF(slist) x, const_iterator first, const_iterator last) BOOST_CONTAINER_NOEXCEPT
{ this->splice(p, static_cast<slist&>(x), first, last); }
/// @cond
//! <b>Effects</b>: Returns true if x and y are equal
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator==(const slist& x, const slist& y)
{
if(x.size() != y.size()){
return false;
}
typedef typename slist<T,Allocator>::const_iterator const_iterator;
const_iterator end1 = x.end();
const_iterator i1 = x.begin();
const_iterator i2 = y.begin();
while (i1 != end1 && *i1 == *i2){
++i1;
++i2;
}
return i1 == end1;
}
//! <b>Effects</b>: Returns true if x and y are unequal
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator!=(const slist& x, const slist& y)
{ return !(x == y); }
//! <b>Effects</b>: Returns true if x is less than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator<(const slist& x, const slist& y)
{ return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
//! <b>Effects</b>: Returns true if x is greater than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator>(const slist& x, const slist& y)
{ return y < x; }
//! <b>Effects</b>: Returns true if x is equal or less than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator<=(const slist& x, const slist& y)
{ return !(y < x); }
//! <b>Effects</b>: Returns true if x is equal or greater than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator>=(const slist& x, const slist& y)
{ return !(x < y); }
//! <b>Effects</b>: x.swap(y)
//!
//! <b>Complexity</b>: Constant.
friend void swap(slist& x, slist& y)
{ x.swap(y); }
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
void priv_push_front (const T &x)
{ this->insert(this->cbegin(), x); }
{ this->insert_after(this->cbefore_begin(), x); }
void priv_push_front (BOOST_RV_REF(T) x)
{ this->insert(this->cbegin(), ::boost::move(x)); }
{ this->insert_after(this->cbefore_begin(), ::boost::move(x)); }
bool priv_try_shrink(size_type new_size, const_iterator &last_pos)
{
@@ -1505,63 +1564,12 @@ class slist
const value_type &m_ref;
};
/// @endcond
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
};
template <class T, class Allocator>
inline bool
operator==(const slist<T,Allocator>& x, const slist<T,Allocator>& y)
{
if(x.size() != y.size()){
return false;
}
typedef typename slist<T,Allocator>::const_iterator const_iterator;
const_iterator end1 = x.end();
const_iterator i1 = x.begin();
const_iterator i2 = y.begin();
while (i1 != end1 && *i1 == *i2){
++i1;
++i2;
}
return i1 == end1;
}
template <class T, class Allocator>
inline bool
operator<(const slist<T,Allocator>& sL1, const slist<T,Allocator>& sL2)
{
return std::lexicographical_compare
(sL1.begin(), sL1.end(), sL2.begin(), sL2.end());
}
template <class T, class Allocator>
inline bool
operator!=(const slist<T,Allocator>& sL1, const slist<T,Allocator>& sL2)
{ return !(sL1 == sL2); }
template <class T, class Allocator>
inline bool
operator>(const slist<T,Allocator>& sL1, const slist<T,Allocator>& sL2)
{ return sL2 < sL1; }
template <class T, class Allocator>
inline bool
operator<=(const slist<T,Allocator>& sL1, const slist<T,Allocator>& sL2)
{ return !(sL2 < sL1); }
template <class T, class Allocator>
inline bool
operator>=(const slist<T,Allocator>& sL1, const slist<T,Allocator>& sL2)
{ return !(sL1 < sL2); }
template <class T, class Allocator>
inline void swap(slist<T,Allocator>& x, slist<T,Allocator>& y)
{ x.swap(y); }
}}
/// @cond
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
namespace boost {
@@ -1574,14 +1582,14 @@ struct has_trivial_destructor_after_move<boost::container::slist<T, Allocator> >
namespace container {
/// @endcond
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
}} //namespace boost{ namespace container {
// Specialization of insert_iterator so that insertions will be constant
// time rather than linear time.
///@cond
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//Ummm, I don't like to define things in namespace std, but
//there is no other way
@@ -1620,7 +1628,7 @@ class insert_iterator<boost::container::slist<T, Allocator> >
} //namespace std;
///@endcond
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
#include <boost/container/detail/config_end.hpp>

View File

@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost
// (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)
//
@@ -47,18 +47,18 @@
#include <memory>
#include <new> //placement new
///@cond
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
#include <boost/container/vector.hpp>
//#define STABLE_VECTOR_ENABLE_INVARIANT_CHECKING
///@endcond
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
namespace boost {
namespace container {
///@cond
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
namespace stable_vector_detail{
@@ -393,7 +393,7 @@ struct index_traits
#endif //#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
/// @endcond
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//! Originally developed by Joaquin M. Lopez Munoz, stable_vector is a std::vector
//! drop-in replacement implemented as a node container, offering iterator and reference
@@ -426,6 +426,9 @@ struct index_traits
//!
//! Exception safety: As stable_vector does not internally copy elements around, some
//! operations provide stronger exception safety guarantees than in std::vector.
//!
//! \tparam T The type of object that is stored in the stable_vector
//! \tparam Allocator The allocator used for all internal memory management
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
template <class T, class Allocator = std::allocator<T> >
#else
@@ -433,7 +436,7 @@ template <class T, class Allocator>
#endif
class stable_vector
{
///@cond
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
typedef allocator_traits<Allocator> allocator_traits_type;
typedef boost::intrusive::
pointer_traits
@@ -504,7 +507,7 @@ class stable_vector
typedef stable_vector_detail::iterator
< typename allocator_traits<Allocator>::pointer
, false> const_iterator_impl;
///@endcond
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
public:
//////////////////////////////////////////////
@@ -526,7 +529,7 @@ class stable_vector
typedef BOOST_CONTAINER_IMPDEF(std::reverse_iterator<iterator>) reverse_iterator;
typedef BOOST_CONTAINER_IMPDEF(std::reverse_iterator<const_iterator>) const_reverse_iterator;
///@cond
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
BOOST_COPYABLE_AND_MOVABLE(stable_vector)
static const size_type ExtraPointers = index_traits_type::ExtraPointers;
@@ -536,7 +539,7 @@ class stable_vector
class push_back_rollback;
friend class push_back_rollback;
///@endcond
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
public:
//////////////////////////////////////////////
@@ -1510,8 +1513,49 @@ class stable_vector
void clear() BOOST_CONTAINER_NOEXCEPT
{ this->erase(this->cbegin(),this->cend()); }
/// @cond
//! <b>Effects</b>: Returns true if x and y are equal
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator==(const stable_vector& x, const stable_vector& y)
{ return x.size() == y.size() && std::equal(x.begin(), x.end(), y.begin()); }
//! <b>Effects</b>: Returns true if x and y are unequal
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator!=(const stable_vector& x, const stable_vector& y)
{ return !(x == y); }
//! <b>Effects</b>: Returns true if x is less than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator<(const stable_vector& x, const stable_vector& y)
{ return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
//! <b>Effects</b>: Returns true if x is greater than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator>(const stable_vector& x, const stable_vector& y)
{ return y < x; }
//! <b>Effects</b>: Returns true if x is equal or less than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator<=(const stable_vector& x, const stable_vector& y)
{ return !(y < x); }
//! <b>Effects</b>: Returns true if x is equal or greater than y
//!
//! <b>Complexity</b>: Linear to the number of elements in the container.
friend bool operator>=(const stable_vector& x, const stable_vector& y)
{ return !(x < y); }
//! <b>Effects</b>: x.swap(y)
//!
//! <b>Complexity</b>: Constant.
friend void swap(stable_vector& x, stable_vector& y)
{ x.swap(y); }
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
class insert_rollback
@@ -1836,58 +1880,14 @@ class stable_vector
const node_allocator_type &priv_node_alloc() const { return internal_data; }
index_type index;
/// @endcond
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
};
template <typename T,typename Allocator>
bool operator==(const stable_vector<T,Allocator>& x,const stable_vector<T,Allocator>& y)
{
return x.size()==y.size()&&std::equal(x.begin(),x.end(),y.begin());
}
template <typename T,typename Allocator>
bool operator< (const stable_vector<T,Allocator>& x,const stable_vector<T,Allocator>& y)
{
return std::lexicographical_compare(x.begin(),x.end(),y.begin(),y.end());
}
template <typename T,typename Allocator>
bool operator!=(const stable_vector<T,Allocator>& x,const stable_vector<T,Allocator>& y)
{
return !(x==y);
}
template <typename T,typename Allocator>
bool operator> (const stable_vector<T,Allocator>& x,const stable_vector<T,Allocator>& y)
{
return y<x;
}
template <typename T,typename Allocator>
bool operator>=(const stable_vector<T,Allocator>& x,const stable_vector<T,Allocator>& y)
{
return !(x<y);
}
template <typename T,typename Allocator>
bool operator<=(const stable_vector<T,Allocator>& x,const stable_vector<T,Allocator>& y)
{
return !(x>y);
}
// specialized algorithms:
template <typename T, typename Allocator>
void swap(stable_vector<T,Allocator>& x,stable_vector<T,Allocator>& y)
{
x.swap(y);
}
/// @cond
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
#undef STABLE_VECTOR_CHECK_INVARIANT
/// @endcond
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
/*

View File

@@ -21,6 +21,8 @@
namespace boost { namespace container {
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
namespace container_detail {
template<class T, std::size_t N>
@@ -61,46 +63,46 @@ class static_storage_allocator
} //namespace container_detail {
/**
* @defgroup static_vector_non_member static_vector non-member functions
*/
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
/**
* @brief A variable-size array container with fixed capacity.
*
* static_vector is a sequence container like boost::container::vector with contiguous storage that can
* change in size, along with the static allocation, low overhead, and fixed capacity of boost::array.
*
* A static_vector is a sequence that supports random access to elements, constant time insertion and
* removal of elements at the end, and linear time insertion and removal of elements at the beginning or
* in the middle. The number of elements in a static_vector may vary dynamically up to a fixed capacity
* because elements are stored within the object itself similarly to an array. However, objects are
* initialized as they are inserted into static_vector unlike C arrays or std::array which must construct
* all elements on instantiation. The behavior of static_vector enables the use of statically allocated
* elements in cases with complex object lifetime requirements that would otherwise not be trivially
* possible.
*
* @par Error Handling
* Insertion beyond the capacity result in throwing std::bad_alloc() if exceptions are enabled or
* calling throw_bad_alloc() if not enabled.
*
* std::out_of_range is thrown if out of bound access is performed in `at()` if exceptions are
* enabled, throw_out_of_range() if not enabled.
*
* @tparam Value The type of element that will be stored.
* @tparam Capacity The maximum number of elements static_vector can store, fixed at compile time.
*/
//!
//!@brief A variable-size array container with fixed capacity.
//!
//!static_vector is a sequence container like boost::container::vector with contiguous storage that can
//!change in size, along with the static allocation, low overhead, and fixed capacity of boost::array.
//!
//!A static_vector is a sequence that supports random access to elements, constant time insertion and
//!removal of elements at the end, and linear time insertion and removal of elements at the beginning or
//!in the middle. The number of elements in a static_vector may vary dynamically up to a fixed capacity
//!because elements are stored within the object itself similarly to an array. However, objects are
//!initialized as they are inserted into static_vector unlike C arrays or std::array which must construct
//!all elements on instantiation. The behavior of static_vector enables the use of statically allocated
//!elements in cases with complex object lifetime requirements that would otherwise not be trivially
//!possible.
//!
//!@par Error Handling
//! Insertion beyond the capacity result in throwing std::bad_alloc() if exceptions are enabled or
//! calling throw_bad_alloc() if not enabled.
//!
//! std::out_of_range is thrown if out of bound access is performed in <code>at()</code> if exceptions are
//! enabled, throw_out_of_range() if not enabled.
//!
//!@tparam Value The type of element that will be stored.
//!@tparam Capacity The maximum number of elements static_vector can store, fixed at compile time.
template <typename Value, std::size_t Capacity>
class static_vector
: public vector<Value, container_detail::static_storage_allocator<Value, Capacity> >
{
typedef vector<Value, container_detail::static_storage_allocator<Value, Capacity> > base_t;
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
typedef vector<Value, container_detail::static_storage_allocator<Value, Capacity> > base_t;
BOOST_COPYABLE_AND_MOVABLE(static_vector)
BOOST_COPYABLE_AND_MOVABLE(static_vector)
template<class U, std::size_t OtherCapacity>
friend class static_vector;
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
public:
//! @brief The type of elements stored in the container.
typedef typename base_t::value_type value_type;

View File

@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// (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)
//
@@ -52,7 +52,7 @@
namespace boost {
namespace container {
/// @cond
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
namespace container_detail {
// ------------------------------------------------------------
// Class basic_string_base.
@@ -268,7 +268,12 @@ class basic_string_base
}
size_type next_capacity(size_type additional_objects) const
{ return get_next_capacity(allocator_traits_type::max_size(this->alloc()), this->priv_storage(), additional_objects); }
{
return next_capacity_calculator
<size_type, NextCapacityDouble /*NextCapacity60Percent*/>::
get( allocator_traits_type::max_size(this->alloc())
, this->priv_storage(), additional_objects );
}
void deallocate(pointer p, size_type n)
{
@@ -433,7 +438,7 @@ class basic_string_base
} //namespace container_detail {
/// @endcond
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//! The basic_string class represents a Sequence of characters. It contains all the
//! usual operations of a Sequence, and, additionally, it contains standard string
@@ -463,6 +468,10 @@ class basic_string_base
//! end(), rbegin(), rend(), operator[], c_str(), and data() do not invalidate iterators.
//! In this implementation, iterators are only invalidated by member functions that
//! explicitly change the string's contents.
//!
//! \tparam CharT The type of character it contains.
//! \tparam Traits The Character Traits type, which encapsulates basic character operations
//! \tparam Allocator The allocator, used for internal memory management.
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
template <class CharT, class Traits = std::char_traits<CharT>, class Allocator = std::allocator<CharT> >
#else
@@ -471,7 +480,7 @@ template <class CharT, class Traits, class Allocator>
class basic_string
: private container_detail::basic_string_base<Allocator>
{
/// @cond
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
typedef allocator_traits<Allocator> allocator_traits_type;
BOOST_COPYABLE_AND_MOVABLE(basic_string)
@@ -483,19 +492,22 @@ class basic_string
template <class Tr>
struct Eq_traits
: public std::binary_function<typename Tr::char_type,
typename Tr::char_type,
bool>
{
bool operator()(const typename Tr::char_type& x,
const typename Tr::char_type& y) const
//Compatibility with std::binary_function
typedef typename Tr::char_type first_argument_type;
typedef typename Tr::char_type second_argument_type;
typedef bool result_type;
bool operator()(const first_argument_type& x, const second_argument_type& y) const
{ return Tr::eq(x, y); }
};
template <class Tr>
struct Not_within_traits
: public std::unary_function<typename Tr::char_type, bool>
{
typedef typename Tr::char_type argument_type;
typedef bool result_type;
typedef const typename Tr::char_type* Pointer;
const Pointer m_first;
const Pointer m_last;
@@ -509,7 +521,7 @@ class basic_string
std::bind1st(Eq_traits<Tr>(), x)) == m_last;
}
};
/// @endcond
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
public:
//////////////////////////////////////////////
@@ -533,14 +545,14 @@ class basic_string
typedef BOOST_CONTAINER_IMPDEF(std::reverse_iterator<const_iterator>) const_reverse_iterator;
static const size_type npos = size_type(-1);
/// @cond
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
typedef constant_iterator<CharT, difference_type> cvalue_iterator;
typedef typename base_t::allocator_v1 allocator_v1;
typedef typename base_t::allocator_v2 allocator_v2;
typedef typename base_t::alloc_version alloc_version;
typedef ::boost::intrusive::pointer_traits<pointer> pointer_traits;
/// @endcond
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
public: // Constructor, destructor, assignment.
//////////////////////////////////////////////
@@ -548,7 +560,7 @@ class basic_string
// construct/copy/destroy
//
//////////////////////////////////////////////
/// @cond
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
struct reserve_t {};
basic_string(reserve_t, size_type n,
@@ -559,7 +571,7 @@ class basic_string
, n + 1)
{ this->priv_terminate_string(); }
/// @endcond
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//! <b>Effects</b>: Default constructs a basic_string.
//!
@@ -668,6 +680,15 @@ class basic_string
this->assign(n, c);
}
//! <b>Effects</b>: Constructs a basic_string taking the allocator as parameter,
//! and is initialized by n default-initialized characters.
basic_string(size_type n, default_init_t, const allocator_type& a = allocator_type())
: base_t(a, n + 1)
{
this->priv_size(n);
this->priv_terminate_string();
}
//! <b>Effects</b>: Constructs a basic_string taking the allocator as parameter,
//! and a range of iterators.
template <class InputIterator>
@@ -945,6 +966,26 @@ class basic_string
void resize(size_type n)
{ resize(n, CharT()); }
//! <b>Effects</b>: Inserts or erases elements at the end such that
//! the size becomes n. New elements are uninitialized.
//!
//! <b>Throws</b>: If memory allocation throws
//!
//! <b>Complexity</b>: Linear to the difference between size() and new_size.
//!
//! <b>Note</b>: Non-standard extension
void resize(size_type n, default_init_t)
{
if (n <= this->size())
this->erase(this->begin() + n, this->end());
else{
this->priv_reserve(n, false);
this->priv_size(n);
this->priv_terminate_string();
}
}
//! <b>Effects</b>: Number of elements for which memory has been allocated.
//! capacity() is always greater than or equal to size().
//!
@@ -961,29 +1002,7 @@ class basic_string
//!
//! <b>Throws</b>: If memory allocation allocation throws
void reserve(size_type res_arg)
{
if (res_arg > this->max_size()){
throw_length_error("basic_string::reserve max_size() exceeded");
}
if (this->capacity() < res_arg){
size_type n = container_detail::max_value(res_arg, this->size()) + 1;
size_type new_cap = this->next_capacity(n);
pointer new_start = this->allocation_command
(allocate_new, n, new_cap, new_cap).first;
size_type new_length = 0;
const pointer addr = this->priv_addr();
new_length += priv_uninitialized_copy
(addr, addr + this->priv_size(), new_start);
this->priv_construct_null(new_start + new_length);
this->deallocate_block();
this->is_short(false);
this->priv_long_addr(new_start);
this->priv_long_size(new_length);
this->priv_storage(new_cap);
}
}
{ this->priv_reserve(res_arg); }
//! <b>Effects</b>: Tries to deallocate the excess of memory created
//! with previous allocations. The size of the string is unchanged
@@ -1228,6 +1247,20 @@ class basic_string
basic_string& assign(size_type n, CharT c)
{ return this->assign(cvalue_iterator(c, n), cvalue_iterator()); }
//! <b>Effects</b>: Equivalent to assign(basic_string(first, last)).
//!
//! <b>Returns</b>: *this
basic_string& assign(const CharT* first, const CharT* last)
{
size_type n = static_cast<size_type>(last - first);
this->reserve(n);
CharT* ptr = container_detail::to_raw_pointer(this->priv_addr());
Traits::copy(ptr, first, n);
this->priv_construct_null(ptr + n);
this->priv_size(n);
return *this;
}
//! <b>Effects</b>: Equivalent to assign(basic_string(first, last)).
//!
//! <b>Returns</b>: *this
@@ -2296,8 +2329,35 @@ class basic_string
int compare(size_type pos1, size_type n1, const CharT* s) const
{ return this->compare(pos1, n1, s, Traits::length(s)); }
/// @cond
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
void priv_reserve(size_type res_arg, const bool null_terminate = true)
{
if (res_arg > this->max_size()){
throw_length_error("basic_string::reserve max_size() exceeded");
}
if (this->capacity() < res_arg){
size_type n = container_detail::max_value(res_arg, this->size()) + 1;
size_type new_cap = this->next_capacity(n);
pointer new_start = this->allocation_command
(allocate_new, n, new_cap, new_cap).first;
size_type new_length = 0;
const pointer addr = this->priv_addr();
new_length += priv_uninitialized_copy
(addr, addr + this->priv_size(), new_start);
if(null_terminate){
this->priv_construct_null(new_start + new_length);
}
this->deallocate_block();
this->is_short(false);
this->priv_long_addr(new_start);
this->priv_long_size(new_length);
this->priv_storage(new_cap);
}
}
static int s_compare(const_pointer f1, const_pointer l1,
const_pointer f2, const_pointer l2)
{
@@ -2431,9 +2491,11 @@ class basic_string
return this->priv_replace(first, last, f, l, Category());
}
/// @endcond
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
};
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
//!Typedef for a basic_string of
//!narrow characters
typedef basic_string
@@ -2450,6 +2512,8 @@ typedef basic_string
,std::allocator<wchar_t> >
wstring;
#endif
// ------------------------------------------------------------
// Non-member functions.
@@ -2663,7 +2727,7 @@ template <class CharT, class Traits, class Allocator>
inline void swap(basic_string<CharT,Traits,Allocator>& x, basic_string<CharT,Traits,Allocator>& y)
{ x.swap(y); }
/// @cond
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
// I/O.
namespace container_detail {
@@ -2683,7 +2747,7 @@ string_fill(std::basic_ostream<CharT, Traits>& os,
}
} //namespace container_detail {
/// @endcond
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
template <class CharT, class Traits, class Allocator>
std::basic_ostream<CharT, Traits>&
@@ -2814,7 +2878,7 @@ inline std::size_t hash_value(basic_string<Ch, std::char_traits<Ch>, Allocator>
}}
/// @cond
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
namespace boost {
@@ -2827,7 +2891,7 @@ struct has_trivial_destructor_after_move<boost::container::basic_string<C, T, Al
}
/// @endcond
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
#include <boost/container/detail/config_end.hpp>

View File

@@ -76,26 +76,82 @@ namespace container {
#else //defined(BOOST_NO_EXCEPTIONS)
//! Exception callback called by Boost.Container when fails to allocate the requested storage space.
//! <ul>
//! <li>If BOOST_NO_EXCEPTIONS is NOT defined <code>std::bad_alloc()</code> is thrown.</li>
//!
//! <li>If BOOST_NO_EXCEPTIONS is defined and BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS
//! is NOT defined <code>BOOST_ASSERT(!"boost::container bad_alloc thrown")</code> is called
//! and <code>std::abort()</code> if the former returns.</li>
//!
//! <li>If BOOST_NO_EXCEPTIONS and BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS are defined
//! the user must provide an implementation and the function should not return.</li>
//! </ul>
inline void throw_bad_alloc()
{
throw std::bad_alloc();
}
//! Exception callback called by Boost.Container to signal arguments out of range.
//! <ul>
//! <li>If BOOST_NO_EXCEPTIONS is NOT defined <code>std::out_of_range(str)</code> is thrown.</li>
//!
//! <li>If BOOST_NO_EXCEPTIONS is defined and BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS
//! is NOT defined <code>BOOST_ASSERT_MSG(!"boost::container out_of_range thrown", str)</code> is called
//! and <code>std::abort()</code> if the former returns.</li>
//!
//! <li>If BOOST_NO_EXCEPTIONS and BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS are defined
//! the user must provide an implementation and the function should not return.</li>
//! </ul>
inline void throw_out_of_range(const char* str)
{
throw std::out_of_range(str);
}
//! Exception callback called by Boost.Container to signal errors resizing.
//! <ul>
//! <li>If BOOST_NO_EXCEPTIONS is NOT defined <code>std::length_error(str)</code> is thrown.</li>
//!
//! <li>If BOOST_NO_EXCEPTIONS is defined and BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS
//! is NOT defined <code>BOOST_ASSERT_MSG(!"boost::container length_error thrown", str)</code> is called
//! and <code>std::abort()</code> if the former returns.</li>
//!
//! <li>If BOOST_NO_EXCEPTIONS and BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS are defined
//! the user must provide an implementation and the function should not return.</li>
//! </ul>
inline void throw_length_error(const char* str)
{
throw std::length_error(str);
}
//! Exception callback called by Boost.Container to report errors in the internal logical
//! of the program, such as violation of logical preconditions or class invariants.
//! <ul>
//! <li>If BOOST_NO_EXCEPTIONS is NOT defined <code>std::logic_error(str)</code> is thrown.</li>
//!
//! <li>If BOOST_NO_EXCEPTIONS is defined and BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS
//! is NOT defined <code>BOOST_ASSERT_MSG(!"boost::container logic_error thrown", str)</code> is called
//! and <code>std::abort()</code> if the former returns.</li>
//!
//! <li>If BOOST_NO_EXCEPTIONS and BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS are defined
//! the user must provide an implementation and the function should not return.</li>
//! </ul>
inline void throw_logic_error(const char* str)
{
throw std::logic_error(str);
}
//! Exception callback called by Boost.Container to report errors that can only be detected during runtime.
//! <ul>
//! <li>If BOOST_NO_EXCEPTIONS is NOT defined <code>std::runtime_error(str)</code> is thrown.</li>
//!
//! <li>If BOOST_NO_EXCEPTIONS is defined and BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS
//! is NOT defined <code>BOOST_ASSERT_MSG(!"boost::container runtime_error thrown", str)</code> is called
//! and <code>std::abort()</code> if the former returns.</li>
//!
//! <li>If BOOST_NO_EXCEPTIONS and BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS are defined
//! the user must provide an implementation and the function should not return.</li>
//! </ul>
inline void throw_runtime_error(const char* str)
{
throw std::runtime_error(str);

File diff suppressed because it is too large Load Diff