- Modified relational operators to be friend inline definitions. This allows compilation checking when instantiating classes, avoids predeclarations and results in less verbose code.

- First to make associative containers' tree implementation configurable.
This commit is contained in:
Ion Gaztañaga
2013-12-23 23:34:28 +01:00
parent f2947c115e
commit 41c2056ec6
62 changed files with 17386 additions and 834 deletions
+390
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
+368
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
+18 -5
View File
@@ -72,6 +72,16 @@ namespace bi = boost::intrusive;
namespace boost {
namespace container {
//! Enumeration used to configure ordered associative containers
//! with a concrete tree implementation.
enum tree_type
{
red_black_tree,
avl_tree,
scapegoat_tree,
splay_tree
};
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
template <class T
@@ -99,24 +109,28 @@ class slist;
template <class Key
,class Compare = std::less<Key>
,class Allocator = std::allocator<Key> >
,class Allocator = std::allocator<Key>
,tree_type = red_black_tree >
class set;
template <class Key
,class Compare = std::less<Key>
,class Allocator = std::allocator<Key> >
,class Allocator = std::allocator<Key>
,tree_type = red_black_tree >
class multiset;
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> >
,tree_type = red_black_tree >
class map;
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> >
,tree_type = red_black_tree >
class multimap;
template <class Key
@@ -224,7 +238,6 @@ struct value_init_t
//! 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
+21 -33
View File
@@ -1537,6 +1537,27 @@ class deque : protected deque_base<Allocator>
this->members_.m_finish = this->members_.m_start;
}
friend bool operator==(const deque& x, const deque& y)
{ return x.size() == y.size() && std::equal(x.begin(), x.end(), y.begin()); }
friend bool operator!=(const deque& x, const deque& y)
{ return !(x == y); }
friend bool operator<(const deque& x, const deque& y)
{ return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
friend bool operator>(const deque& x, const deque& y)
{ return y < x; }
friend bool operator>=(const deque& x, const deque& y)
{ return !(x < y); }
friend bool operator<=(const deque& x, const deque& y)
{ return !(y < x); }
friend void swap(deque& x, deque& y)
{ x.swap(y); }
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
@@ -1939,39 +1960,6 @@ class deque : protected deque_base<Allocator>
#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); }
}}
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
@@ -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
+326
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
@@ -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
@@ -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
+26 -56
View File
@@ -745,6 +745,32 @@ class flat_tree
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
{
@@ -950,62 +976,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 {
@@ -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);
};
@@ -63,7 +63,6 @@ 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)
@@ -75,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 {
+278
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
@@ -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,31 +51,41 @@ 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 typename ICont::value_type Node;
@@ -121,20 +132,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 +357,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))
{}
@@ -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
@@ -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
@@ -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
+71 -104
View File
@@ -15,11 +15,6 @@
#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,17 @@
#include <boost/container/detail/pair.hpp>
#include <boost/container/detail/type_traits.hpp>
#include <boost/container/allocator_traits.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
@@ -86,7 +91,7 @@ struct tree_value_compare
};
template<class VoidPointer>
struct rbtree_hook
struct intrusive_tree_hook
{
typedef typename container_detail::bi::make_set_base_hook
< container_detail::bi::void_pointer<VoidPointer>
@@ -112,20 +117,20 @@ struct rbtree_internal_data_type< std::pair<T1, T2> >
//The node to be store in the tree
template <class T, class VoidPointer>
struct rbtree_node
: public rbtree_hook<VoidPointer>::type
struct tree_node
: public intrusive_tree_hook<VoidPointer>::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>::type hook_type;
typedef T value_type;
typedef typename rbtree_internal_data_type<T>::type internal_type;
typedef rbtree_node<T, VoidPointer> node_type;
typedef tree_node<T, VoidPointer> node_type;
T &get_data()
{
@@ -210,8 +215,11 @@ class push_back_functor
namespace container_detail {
template<class A, class ValueCompare, boost::container::tree_type tree_type_value>
struct intrusive_tree_type;
template<class A, class ValueCompare>
struct intrusive_rbtree_type
struct intrusive_tree_type<A, ValueCompare, boost::container::red_black_tree>
{
typedef typename boost::container::
allocator_traits<A>::value_type value_type;
@@ -219,13 +227,13 @@ struct intrusive_rbtree_type
allocator_traits<A>::void_pointer void_pointer;
typedef typename boost::container::
allocator_traits<A>::size_type size_type;
typedef typename container_detail::rbtree_node
typedef typename container_detail::tree_node
<value_type, void_pointer> 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::base_hook<typename intrusive_tree_hook<void_pointer>::type>
,container_detail::bi::constant_time_size<true>
,container_detail::bi::size_type<size_type>
>::type container_type;
@@ -237,25 +245,25 @@ struct intrusive_rbtree_type
namespace container_detail {
template <class Key, class Value, class KeyOfValue,
class KeyCompare, class A>
class rbtree
class KeyCompare, class A,
boost::container::tree_type tree_type_value>
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>
, tree_type_value>::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, tree_type_value>::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, tree_type_value> ThisType;
typedef typename AllocHolder::NodeAlloc NodeAlloc;
typedef typename AllocHolder::ValAlloc ValAlloc;
typedef typename AllocHolder::Node Node;
@@ -342,7 +350,7 @@ class rbtree
Icont &m_icont;
};
BOOST_COPYABLE_AND_MOVABLE(rbtree)
BOOST_COPYABLE_AND_MOVABLE(tree)
public:
@@ -409,20 +417,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 +458,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 +487,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 +504,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 +521,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 +551,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();
@@ -577,7 +585,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();
@@ -1001,70 +1009,29 @@ class rbtree
return std::pair<const_iterator,const_iterator>
(const_iterator(ret.first), const_iterator(ret.second));
}
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 +1040,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;
};
+40 -107
View File
@@ -35,17 +35,6 @@ namespace boost {
namespace container {
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
// 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);
namespace container_detail{
@@ -62,7 +51,6 @@ static D force_copy(S s)
} //namespace container_detail{
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//! A flat_map is a kind of associative container that supports unique keys (contains at
@@ -842,14 +830,28 @@ class flat_map
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)); }
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
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>&);
friend bool operator==(const flat_map& x, const flat_map& y)
{ return x.m_flat_tree == y.m_flat_tree; }
friend bool operator<(const flat_map& x, const flat_map& y)
{ return x.m_flat_tree < y.m_flat_tree; }
friend bool operator!=(const flat_map& x, const flat_map& y)
{ return !(x == y); }
friend bool operator>(const flat_map& x, const flat_map& y)
{ return y < x; }
friend bool operator<=(const flat_map& x, const flat_map& y)
{ return !(y < x); }
friend bool operator>=(const flat_map& x, const flat_map& y)
{ return !(x < y); }
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)
{
@@ -875,41 +877,6 @@ class flat_map
#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); }
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
} //namespace container {
@@ -924,17 +891,6 @@ 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);
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//! A flat_multimap is a kind of associative container that supports equivalent keys
@@ -1637,51 +1593,28 @@ 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)); }
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
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);
friend bool operator==(const flat_multimap& x, const flat_multimap& y)
{ return x.m_flat_tree == y.m_flat_tree; }
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);
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
friend bool operator<(const flat_multimap& x, const flat_multimap& y)
{ return x.m_flat_tree < y.m_flat_tree; }
friend bool operator!=(const flat_multimap& x, const flat_multimap& y)
{ return !(x == y); }
friend bool operator>(const flat_multimap& x, const flat_multimap& y)
{ return y < x; }
friend bool operator<=(const flat_multimap& x, const flat_multimap& y)
{ return !(y < x); }
friend bool operator>=(const flat_multimap& x, const flat_multimap& y)
{ return !(x < y); }
friend void swap(flat_multimap& x, flat_multimap& y)
{ x.swap(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; }
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)
{ 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)
{ 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)
{ 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)
{ x.swap(y); }
}}
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+42 -115
View File
@@ -31,25 +31,6 @@
namespace boost {
namespace container {
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
// Forward declarations of operators < and ==, needed for friend declaration.
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
template <class Key, class Compare = std::less<Key>, class Allocator = std::allocator<Key> >
#else
template <class Key, class Compare, class Allocator>
#endif
class flat_set;
template <class Key, class Compare, class Allocator>
inline bool operator==(const flat_set<Key,Compare,Allocator>& x,
const flat_set<Key,Compare,Allocator>& y);
template <class Key, class Compare, class Allocator>
inline bool operator<(const flat_set<Key,Compare,Allocator>& x,
const flat_set<Key,Compare,Allocator>& y);
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//! flat_set is a Sorted Associative Container that stores objects of type Key.
//! It is also a Unique Associative Container, meaning that no two elements are the same.
//!
@@ -678,13 +659,28 @@ class flat_set
std::pair<iterator,iterator> equal_range(const key_type& x)
{ return m_flat_tree.equal_range(x); }
friend bool operator==(const flat_set& x, const flat_set& y)
{ return x.m_flat_tree == y.m_flat_tree; }
friend bool operator<(const flat_set& x, const flat_set& y)
{ return x.m_flat_tree < y.m_flat_tree; }
friend bool operator!=(const flat_set& x, const flat_set& y)
{ return !(x == y); }
friend bool operator>(const flat_set& x, const flat_set& y)
{ return y < x; }
friend bool operator<=(const flat_set& x, const flat_set& y)
{ return !(y < x); }
friend bool operator>=(const flat_set& x, const flat_set& y)
{ return !(x < y); }
friend void swap(flat_set& x, flat_set& y)
{ x.swap(y); }
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
template <class K1, class C1, class A1>
friend bool operator== (const flat_set<K1,C1,A1>&, const flat_set<K1,C1,A1>&);
template <class K1, class C1, class A1>
friend bool operator< (const flat_set<K1,C1,A1>&, const flat_set<K1,C1,A1>&);
private:
template<class KeyType>
std::pair<iterator, bool> priv_insert(BOOST_FWD_REF(KeyType) x)
@@ -696,40 +692,6 @@ class flat_set
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
};
template <class Key, class Compare, class Allocator>
inline bool operator==(const flat_set<Key,Compare,Allocator>& x,
const flat_set<Key,Compare,Allocator>& y)
{ return x.m_flat_tree == y.m_flat_tree; }
template <class Key, class Compare, class Allocator>
inline bool operator<(const flat_set<Key,Compare,Allocator>& x,
const flat_set<Key,Compare,Allocator>& y)
{ return x.m_flat_tree < y.m_flat_tree; }
template <class Key, class Compare, class Allocator>
inline bool operator!=(const flat_set<Key,Compare,Allocator>& x,
const flat_set<Key,Compare,Allocator>& y)
{ return !(x == y); }
template <class Key, class Compare, class Allocator>
inline bool operator>(const flat_set<Key,Compare,Allocator>& x,
const flat_set<Key,Compare,Allocator>& y)
{ return y < x; }
template <class Key, class Compare, class Allocator>
inline bool operator<=(const flat_set<Key,Compare,Allocator>& x,
const flat_set<Key,Compare,Allocator>& y)
{ return !(y < x); }
template <class Key, class Compare, class Allocator>
inline bool operator>=(const flat_set<Key,Compare,Allocator>& x,
const flat_set<Key,Compare,Allocator>& y)
{ return !(x < y); }
template <class Key, class Compare, class Allocator>
inline void swap(flat_set<Key,Compare,Allocator>& x, flat_set<Key,Compare,Allocator>& y)
{ x.swap(y); }
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
} //namespace container {
@@ -744,22 +706,6 @@ struct has_trivial_destructor_after_move<boost::container::flat_set<Key, C, Allo
namespace container {
// Forward declaration of operators < and ==, needed for friend declaration.
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
template <class Key, class Compare = std::less<Key>, class Allocator = std::allocator<Key> >
#else
template <class Key, class Compare, class Allocator>
#endif
class flat_multiset;
template <class Key, class Compare, class Allocator>
inline bool operator==(const flat_multiset<Key,Compare,Allocator>& x,
const flat_multiset<Key,Compare,Allocator>& y);
template <class Key, class Compare, class Allocator>
inline bool operator<(const flat_multiset<Key,Compare,Allocator>& x,
const flat_multiset<Key,Compare,Allocator>& y);
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//! flat_multiset is a Sorted Associative Container that stores objects of type Key.
@@ -1353,13 +1299,28 @@ class flat_multiset
std::pair<iterator,iterator> equal_range(const key_type& x)
{ return m_flat_tree.equal_range(x); }
friend bool operator==(const flat_multiset& x, const flat_multiset& y)
{ return x.m_flat_tree == y.m_flat_tree; }
friend bool operator<(const flat_multiset& x, const flat_multiset& y)
{ return x.m_flat_tree < y.m_flat_tree; }
friend bool operator!=(const flat_multiset& x, const flat_multiset& y)
{ return !(x == y); }
friend bool operator>(const flat_multiset& x, const flat_multiset& y)
{ return y < x; }
friend bool operator<=(const flat_multiset& x, const flat_multiset& y)
{ return !(y < x); }
friend bool operator>=(const flat_multiset& x, const flat_multiset& y)
{ return !(x < y); }
friend void swap(flat_multiset& x, flat_multiset& y)
{ x.swap(y); }
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
template <class K1, class C1, class A1>
friend bool operator== (const flat_multiset<K1,C1,A1>&,
const flat_multiset<K1,C1,A1>&);
template <class K1, class C1, class A1>
friend bool operator< (const flat_multiset<K1,C1,A1>&,
const flat_multiset<K1,C1,A1>&);
private:
template <class KeyType>
iterator priv_insert(BOOST_FWD_REF(KeyType) x)
@@ -1371,40 +1332,6 @@ class flat_multiset
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
};
template <class Key, class Compare, class Allocator>
inline bool operator==(const flat_multiset<Key,Compare,Allocator>& x,
const flat_multiset<Key,Compare,Allocator>& y)
{ return x.m_flat_tree == y.m_flat_tree; }
template <class Key, class Compare, class Allocator>
inline bool operator<(const flat_multiset<Key,Compare,Allocator>& x,
const flat_multiset<Key,Compare,Allocator>& y)
{ return x.m_flat_tree < y.m_flat_tree; }
template <class Key, class Compare, class Allocator>
inline bool operator!=(const flat_multiset<Key,Compare,Allocator>& x,
const flat_multiset<Key,Compare,Allocator>& y)
{ return !(x == y); }
template <class Key, class Compare, class Allocator>
inline bool operator>(const flat_multiset<Key,Compare,Allocator>& x,
const flat_multiset<Key,Compare,Allocator>& y)
{ return y < x; }
template <class Key, class Compare, class Allocator>
inline bool operator<=(const flat_multiset<Key,Compare,Allocator>& x,
const flat_multiset<Key,Compare,Allocator>& y)
{ return !(y < x); }
template <class Key, class Compare, class Allocator>
inline bool operator>=(const flat_multiset<Key,Compare,Allocator>& x,
const flat_multiset<Key,Compare,Allocator>& y)
{ return !(x < y); }
template <class Key, class Compare, class Allocator>
inline void swap(flat_multiset<Key,Compare,Allocator>& x, flat_multiset<Key,Compare,Allocator>& y)
{ x.swap(y); }
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
} //namespace container {
+36 -56
View File
@@ -1214,7 +1214,42 @@ class list
//!
//! <b>Note</b>: Iterators and references are not invalidated
void reverse() BOOST_CONTAINER_NOEXCEPT
{ this->icont().reverse(); }
{ this->icont().reverse(); }
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;
}
friend bool operator<(const list& x, const list& y)
{ return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
friend bool operator!=(const list& x, const list& y)
{ return !(x == y); }
friend bool operator>(const list& x, const list& y)
{ return y < x; }
friend bool operator<=(const list& x, const list& y)
{ return !(y < x); }
friend bool operator>=(const list& x, const list& y)
{ return !(x < y); }
friend void swap(list& x, list& y)
{ x.swap(y); }
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
@@ -1307,61 +1342,6 @@ class list
};
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);
}
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
} //namespace container {
+46 -108
View File
@@ -39,17 +39,6 @@
namespace boost {
namespace container {
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
// Forward declarations of operators == and <, needed for friend declarations.
template <class Key, class T, class Compare, class Allocator>
inline bool operator==(const map<Key,T,Compare,Allocator>& x,
const map<Key,T,Compare,Allocator>& y);
template <class Key, class T, class Compare, class Allocator>
inline bool operator<(const map<Key,T,Compare,Allocator>& x,
const map<Key,T,Compare,Allocator>& y);
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//! A 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
//! type T based on the keys. The map class supports bidirectional iterators.
@@ -65,7 +54,7 @@ inline bool operator<(const map<Key,T,Compare,Allocator>& x,
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
template <class Key, class T, class Compare = std::less<Key>, class Allocator = std::allocator< std::pair< const Key, T> > >
#else
template <class Key, class T, class Compare, class Allocator>
template <class Key, class T, class Compare, class Allocator, tree_type tree_type_value>
#endif
class map
{
@@ -74,8 +63,8 @@ class map
BOOST_COPYABLE_AND_MOVABLE(map)
typedef std::pair<const Key, T> value_type_impl;
typedef container_detail::rbtree
<Key, value_type_impl, container_detail::select1st<value_type_impl>, Compare, Allocator> tree_t;
typedef container_detail::tree
<Key, value_type_impl, container_detail::select1st<value_type_impl>, Compare, Allocator, tree_type_value> tree_t;
typedef container_detail::pair <Key, T> movable_value_type_impl;
typedef container_detail::tree_value_compare
< Key, value_type_impl, Compare, container_detail::select1st<value_type_impl>
@@ -755,13 +744,28 @@ class map
std::pair<const_iterator,const_iterator> equal_range(const key_type& x) const
{ return m_tree.equal_range(x); }
friend bool operator==(const map& x, const map& y)
{ return x.m_tree == y.m_tree; }
friend bool operator<(const map& x, const map& y)
{ return x.m_tree < y.m_tree; }
friend bool operator!=(const map& x, const map& y)
{ return !(x == y); }
friend bool operator>(const map& x, const map& y)
{ return y < x; }
friend bool operator<=(const map& x, const map& y)
{ return !(y < x); }
friend bool operator>=(const map& x, const map& y)
{ return !(x < y); }
friend void swap(map& x, map& y)
{ x.swap(y); }
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
template <class K1, class T1, class C1, class A1>
friend bool operator== (const map<K1, T1, C1, A1>&,
const map<K1, T1, C1, A1>&);
template <class K1, class T1, class C1, class A1>
friend bool operator< (const map<K1, T1, C1, A1>&,
const map<K1, T1, C1, A1>&);
private:
mapped_type& priv_subscript(const key_type &k)
{
@@ -793,52 +797,9 @@ class map
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
};
template <class Key, class T, class Compare, class Allocator>
inline bool operator==(const map<Key,T,Compare,Allocator>& x,
const map<Key,T,Compare,Allocator>& y)
{ return x.m_tree == y.m_tree; }
template <class Key, class T, class Compare, class Allocator>
inline bool operator<(const map<Key,T,Compare,Allocator>& x,
const map<Key,T,Compare,Allocator>& y)
{ return x.m_tree < y.m_tree; }
template <class Key, class T, class Compare, class Allocator>
inline bool operator!=(const map<Key,T,Compare,Allocator>& x,
const map<Key,T,Compare,Allocator>& y)
{ return !(x == y); }
template <class Key, class T, class Compare, class Allocator>
inline bool operator>(const map<Key,T,Compare,Allocator>& x,
const map<Key,T,Compare,Allocator>& y)
{ return y < x; }
template <class Key, class T, class Compare, class Allocator>
inline bool operator<=(const map<Key,T,Compare,Allocator>& x,
const map<Key,T,Compare,Allocator>& y)
{ return !(y < x); }
template <class Key, class T, class Compare, class Allocator>
inline bool operator>=(const map<Key,T,Compare,Allocator>& x,
const map<Key,T,Compare,Allocator>& y)
{ return !(x < y); }
template <class Key, class T, class Compare, class Allocator>
inline void swap(map<Key,T,Compare,Allocator>& x, map<Key,T,Compare,Allocator>& y)
{ x.swap(y); }
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
// Forward declaration of operators < and ==, needed for friend declaration.
template <class Key, class T, class Compare, class Allocator>
inline bool operator==(const multimap<Key,T,Compare,Allocator>& x,
const multimap<Key,T,Compare,Allocator>& y);
template <class Key, class T, class Compare, class Allocator>
inline bool operator<(const multimap<Key,T,Compare,Allocator>& x,
const multimap<Key,T,Compare,Allocator>& y);
} //namespace container {
//!has_trivial_destructor_after_move<> == true_type
@@ -869,7 +830,7 @@ namespace container {
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
template <class Key, class T, class Compare = std::less<Key>, class Allocator = std::allocator< std::pair< const Key, T> > >
#else
template <class Key, class T, class Compare, class Allocator>
template <class Key, class T, class Compare, class Allocator, tree_type tree_type_value>
#endif
class multimap
{
@@ -878,8 +839,8 @@ class multimap
BOOST_COPYABLE_AND_MOVABLE(multimap)
typedef std::pair<const Key, T> value_type_impl;
typedef container_detail::rbtree
<Key, value_type_impl, container_detail::select1st<value_type_impl>, Compare, Allocator> tree_t;
typedef container_detail::tree
<Key, value_type_impl, container_detail::select1st<value_type_impl>, Compare, Allocator, tree_type_value> tree_t;
typedef container_detail::pair <Key, T> movable_value_type_impl;
typedef container_detail::tree_value_compare
< Key, value_type_impl, Compare, container_detail::select1st<value_type_impl>
@@ -1463,51 +1424,28 @@ class multimap
std::pair<const_iterator,const_iterator> equal_range(const key_type& x) const
{ return m_tree.equal_range(x); }
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
template <class K1, class T1, class C1, class A1>
friend bool operator== (const multimap<K1, T1, C1, A1>& x,
const multimap<K1, T1, C1, A1>& y);
friend bool operator==(const multimap& x, const multimap& y)
{ return x.m_tree == y.m_tree; }
friend bool operator<(const multimap& x, const multimap& y)
{ return x.m_tree < y.m_tree; }
template <class K1, class T1, class C1, class A1>
friend bool operator< (const multimap<K1, T1, C1, A1>& x,
const multimap<K1, T1, C1, A1>& y);
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
friend bool operator!=(const multimap& x, const multimap& y)
{ return !(x == y); }
friend bool operator>(const multimap& x, const multimap& y)
{ return y < x; }
friend bool operator<=(const multimap& x, const multimap& y)
{ return !(y < x); }
friend bool operator>=(const multimap& x, const multimap& y)
{ return !(x < y); }
friend void swap(multimap& x, multimap& y)
{ x.swap(y); }
};
template <class Key, class T, class Compare, class Allocator>
inline bool operator==(const multimap<Key,T,Compare,Allocator>& x,
const multimap<Key,T,Compare,Allocator>& y)
{ return x.m_tree == y.m_tree; }
template <class Key, class T, class Compare, class Allocator>
inline bool operator<(const multimap<Key,T,Compare,Allocator>& x,
const multimap<Key,T,Compare,Allocator>& y)
{ return x.m_tree < y.m_tree; }
template <class Key, class T, class Compare, class Allocator>
inline bool operator!=(const multimap<Key,T,Compare,Allocator>& x,
const multimap<Key,T,Compare,Allocator>& y)
{ return !(x == y); }
template <class Key, class T, class Compare, class Allocator>
inline bool operator>(const multimap<Key,T,Compare,Allocator>& x,
const multimap<Key,T,Compare,Allocator>& y)
{ return y < x; }
template <class Key, class T, class Compare, class Allocator>
inline bool operator<=(const multimap<Key,T,Compare,Allocator>& x,
const multimap<Key,T,Compare,Allocator>& y)
{ return !(y < x); }
template <class Key, class T, class Compare, class Allocator>
inline bool operator>=(const multimap<Key,T,Compare,Allocator>& x,
const multimap<Key,T,Compare,Allocator>& y)
{ return !(x < y); }
template <class Key, class T, class Compare, class Allocator>
inline void swap(multimap<Key,T,Compare,Allocator>& x, multimap<Key,T,Compare,Allocator>& y)
{ x.swap(y); }
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
} //namespace container {
+346
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
+48 -106
View File
@@ -35,17 +35,6 @@
namespace boost {
namespace container {
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
// Forward declarations of operators < and ==, needed for friend declaration.
template <class Key, class Compare, class Allocator>
inline bool operator==(const set<Key,Compare,Allocator>& x,
const set<Key,Compare,Allocator>& y);
template <class Key, class Compare, class Allocator>
inline bool operator<(const set<Key,Compare,Allocator>& x,
const set<Key,Compare,Allocator>& y);
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//! A set is a kind of associative container that supports unique keys (contains at
//! most one of each key value) and provides for fast retrieval of the keys themselves.
//! Class set supports bidirectional iterators.
@@ -56,15 +45,15 @@ inline bool operator<(const set<Key,Compare,Allocator>& x,
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
template <class Key, class Compare = std::less<Key>, class Allocator = std::allocator<Key> >
#else
template <class Key, class Compare, class Allocator>
template <class Key, class Compare, class Allocator, tree_type tree_type_value>
#endif
class set
{
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
BOOST_COPYABLE_AND_MOVABLE(set)
typedef container_detail::rbtree<Key, Key,
container_detail::identity<Key>, Compare, Allocator> tree_t;
typedef container_detail::tree
< Key, Key, container_detail::identity<Key>, Compare, Allocator, tree_type_value> tree_t;
tree_t m_tree; // red-black tree representing set
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
@@ -600,13 +589,28 @@ class set
std::pair<const_iterator, const_iterator> equal_range(const key_type& x) const
{ return m_tree.equal_range(x); }
friend bool operator==(const set& x, const set& y)
{ return x.m_tree == y.m_tree; }
friend bool operator<(const set& x, const set& y)
{ return x.m_tree < y.m_tree; }
friend bool operator!=(const set& x, const set& y)
{ return !(x == y); }
friend bool operator>(const set& x, const set& y)
{ return y < x; }
friend bool operator<=(const set& x, const set& y)
{ return !(y < x); }
friend bool operator>=(const set& x, const set& y)
{ return !(x < y); }
friend void swap(set& x, set& y)
{ x.swap(y); }
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
template <class K1, class C1, class A1>
friend bool operator== (const set<K1,C1,A1>&, const set<K1,C1,A1>&);
template <class K1, class C1, class A1>
friend bool operator< (const set<K1,C1,A1>&, const set<K1,C1,A1>&);
private:
template <class KeyType>
std::pair<iterator, bool> priv_insert(BOOST_FWD_REF(KeyType) x)
@@ -618,40 +622,6 @@ class set
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
};
template <class Key, class Compare, class Allocator>
inline bool operator==(const set<Key,Compare,Allocator>& x,
const set<Key,Compare,Allocator>& y)
{ return x.m_tree == y.m_tree; }
template <class Key, class Compare, class Allocator>
inline bool operator<(const set<Key,Compare,Allocator>& x,
const set<Key,Compare,Allocator>& y)
{ return x.m_tree < y.m_tree; }
template <class Key, class Compare, class Allocator>
inline bool operator!=(const set<Key,Compare,Allocator>& x,
const set<Key,Compare,Allocator>& y)
{ return !(x == y); }
template <class Key, class Compare, class Allocator>
inline bool operator>(const set<Key,Compare,Allocator>& x,
const set<Key,Compare,Allocator>& y)
{ return y < x; }
template <class Key, class Compare, class Allocator>
inline bool operator<=(const set<Key,Compare,Allocator>& x,
const set<Key,Compare,Allocator>& y)
{ return !(y < x); }
template <class Key, class Compare, class Allocator>
inline bool operator>=(const set<Key,Compare,Allocator>& x,
const set<Key,Compare,Allocator>& y)
{ return !(x < y); }
template <class Key, class Compare, class Allocator>
inline void swap(set<Key,Compare,Allocator>& x, set<Key,Compare,Allocator>& y)
{ x.swap(y); }
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
} //namespace container {
@@ -666,15 +636,6 @@ struct has_trivial_destructor_after_move<boost::container::set<Key, C, Allocator
namespace container {
// Forward declaration of operators < and ==, needed for friend declaration.
template <class Key, class Compare, class Allocator>
inline bool operator==(const multiset<Key,Compare,Allocator>& x,
const multiset<Key,Compare,Allocator>& y);
template <class Key, class Compare, class Allocator>
inline bool operator<(const multiset<Key,Compare,Allocator>& x,
const multiset<Key,Compare,Allocator>& y);
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//! A multiset is a kind of associative container that supports equivalent keys
@@ -687,15 +648,15 @@ inline bool operator<(const multiset<Key,Compare,Allocator>& x,
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
template <class Key, class Compare = std::less<Key>, class Allocator = std::allocator<Key> >
#else
template <class Key, class Compare, class Allocator>
template <class Key, class Compare, class Allocator, tree_type tree_type_value>
#endif
class multiset
{
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
BOOST_COPYABLE_AND_MOVABLE(multiset)
typedef container_detail::rbtree<Key, Key,
container_detail::identity<Key>, Compare, Allocator> tree_t;
typedef container_detail::tree
<Key, Key,container_detail::identity<Key>, Compare, Allocator, tree_type_value> tree_t;
tree_t m_tree; // red-black tree representing multiset
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
@@ -1221,13 +1182,28 @@ class multiset
std::pair<const_iterator, const_iterator> equal_range(const key_type& x) const
{ return m_tree.equal_range(x); }
friend bool operator==(const multiset& x, const multiset& y)
{ return x.m_tree == y.m_tree; }
friend bool operator<(const multiset& x, const multiset& y)
{ return x.m_tree < y.m_tree; }
friend bool operator!=(const multiset& x, const multiset& y)
{ return !(x == y); }
friend bool operator>(const multiset& x, const multiset& y)
{ return y < x; }
friend bool operator<=(const multiset& x, const multiset& y)
{ return !(y < x); }
friend bool operator>=(const multiset& x, const multiset& y)
{ return !(x < y); }
friend void swap(multiset& x, multiset& y)
{ x.swap(y); }
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
template <class K1, class C1, class A1>
friend bool operator== (const multiset<K1,C1,A1>&,
const multiset<K1,C1,A1>&);
template <class K1, class C1, class A1>
friend bool operator< (const multiset<K1,C1,A1>&,
const multiset<K1,C1,A1>&);
private:
template <class KeyType>
iterator priv_insert(BOOST_FWD_REF(KeyType) x)
@@ -1240,40 +1216,6 @@ class multiset
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
};
template <class Key, class Compare, class Allocator>
inline bool operator==(const multiset<Key,Compare,Allocator>& x,
const multiset<Key,Compare,Allocator>& y)
{ return x.m_tree == y.m_tree; }
template <class Key, class Compare, class Allocator>
inline bool operator<(const multiset<Key,Compare,Allocator>& x,
const multiset<Key,Compare,Allocator>& y)
{ return x.m_tree < y.m_tree; }
template <class Key, class Compare, class Allocator>
inline bool operator!=(const multiset<Key,Compare,Allocator>& x,
const multiset<Key,Compare,Allocator>& y)
{ return !(x == y); }
template <class Key, class Compare, class Allocator>
inline bool operator>(const multiset<Key,Compare,Allocator>& x,
const multiset<Key,Compare,Allocator>& y)
{ return y < x; }
template <class Key, class Compare, class Allocator>
inline bool operator<=(const multiset<Key,Compare,Allocator>& x,
const multiset<Key,Compare,Allocator>& y)
{ return !(y < x); }
template <class Key, class Compare, class Allocator>
inline bool operator>=(const multiset<Key,Compare,Allocator>& x,
const multiset<Key,Compare,Allocator>& y)
{ return !(x < y); }
template <class Key, class Compare, class Allocator>
inline void swap(multiset<Key,Compare,Allocator>& x, multiset<Key,Compare,Allocator>& y)
{ x.swap(y); }
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
} //namespace container {
+38 -51
View File
@@ -1423,6 +1423,44 @@ 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); }
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;
}
friend bool operator<(const slist& x, const slist& y)
{
return std::lexicographical_compare
(x.begin(), x.end(), y.begin(), y.end());
}
friend bool operator!=(const slist& x, const slist& y)
{ return !(x == y); }
friend bool operator>(const slist& x, const slist& y)
{ return y < x; }
friend bool operator<=(const slist& x, const slist& y)
{ return !(y < x); }
friend bool operator>=(const slist& x, const slist& y)
{ return !(x < y); }
friend void swap(slist& x, slist& y)
{ x.swap(y); }
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
@@ -1508,57 +1546,6 @@ class slist
#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); }
}}
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+21 -45
View File
@@ -1510,8 +1510,28 @@ class stable_vector
void clear() BOOST_CONTAINER_NOEXCEPT
{ this->erase(this->cbegin(),this->cend()); }
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
friend bool operator==(const stable_vector& x,const stable_vector& y)
{ return x.size()==y.size()&&std::equal(x.begin(),x.end(),y.begin()); }
friend bool operator< (const stable_vector& x,const stable_vector& y)
{ return std::lexicographical_compare(x.begin(),x.end(),y.begin(),y.end()); }
friend bool operator!=(const stable_vector& x,const stable_vector& y)
{ return !(x==y); }
friend bool operator> (const stable_vector& x,const stable_vector& y)
{ return y<x; }
friend bool operator>=(const stable_vector& x,const stable_vector& y)
{ return !(x<y); }
friend bool operator<=(const stable_vector& x,const stable_vector& y)
{ return !(x>y); }
friend void swap(stable_vector& x,stable_vector& y)
{ x.swap(y); }
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
class insert_rollback
@@ -1839,50 +1859,6 @@ class stable_vector
#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);
}
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
#undef STABLE_VECTOR_CHECK_INVARIANT
+23 -29
View File
@@ -1580,11 +1580,33 @@ class vector
//Absolutely experimental. This function might change, disappear or simply crash!
template<class BiDirPosConstIt, class BiDirSkipConstIt, class BiDirValueIt>
void insert_ordered_at(size_type element_count, BiDirPosConstIt last_position_it, BiDirSkipConstIt last_skip_it, BiDirValueIt last_value_it)
void insert_ordered_at( size_type element_count, BiDirPosConstIt last_position_it
, BiDirSkipConstIt last_skip_it, BiDirValueIt last_value_it)
{
this->priv_insert_ordered_at(element_count, last_position_it, true, last_skip_it, last_value_it);
}
friend bool operator==(const vector& x, const vector& y)
{ return x.size() == y.size() && std::equal(x.begin(), x.end(), y.begin()); }
friend bool operator!=(const vector& x, const vector& y)
{ return !(x == y); }
friend bool operator<(const vector& x, const vector& y)
{ return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
friend bool operator>(const vector& x, const vector& y)
{ return y < x; }
friend bool operator<=(const vector& x, const vector& y)
{ return !(y < x); }
friend bool operator>=(const vector& x, const vector& y)
{ return !(x < y); }
friend void swap(vector& x, vector& y)
{ x.swap(y); }
private:
template<class OtherAllocator, class AllocVersion>
@@ -1907,7 +1929,6 @@ class vector
return iterator(this->m_holder.start() + n_pos);
}
template <class InsertionProxy>
iterator priv_forward_range_insert_no_capacity
(const pointer &pos, const size_type n, const InsertionProxy insert_range_proxy, allocator_v2)
@@ -2635,33 +2656,6 @@ class vector
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
};
template <class T, class Allocator>
inline bool
operator==(const vector<T, Allocator>& x, const vector<T, Allocator>& y)
{
//Check first size and each element if needed
return x.size() == y.size() && std::equal(x.begin(), x.end(), y.begin());
}
template <class T, class Allocator>
inline bool
operator!=(const vector<T, Allocator>& x, const vector<T, Allocator>& y)
{
//Check first size and each element if needed
return x.size() != y.size() || !std::equal(x.begin(), x.end(), y.begin());
}
template <class T, class Allocator>
inline bool
operator<(const vector<T, Allocator>& x, const vector<T, Allocator>& y)
{
return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());
}
template <class T, class Allocator>
inline void swap(vector<T, Allocator>& x, vector<T, Allocator>& y)
{ x.swap(y); }
}}
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED