Merge pull request #1 from yuriks/add-container

Add container library (for static_vector)
This commit is contained in:
bunnei 2014-12-27 22:24:36 -05:00
commit 97052c28ac
166 changed files with 77078 additions and 0 deletions

View file

@ -1,12 +1,17 @@
Boost libraries - trimmed down for Citra Boost libraries - trimmed down for Citra
======================================== ========================================
This is a subset of Boost v1.57.0.
Currently imported libraries: Currently imported libraries:
----------------------------- -----------------------------
* concept * concept
* config * config
* container
* core * core
* intrusive
* iterator * iterator
* move
* mpl * mpl
* preprocessor * preprocessor
* range * range

View file

@ -0,0 +1,349 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_ADAPTIVE_POOL_HPP
#define BOOST_CONTAINER_ADAPTIVE_POOL_HPP
#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/container/detail/placement_new.hpp>
#include <boost/assert.hpp>
#include <boost/utility/addressof.hpp>
#include <boost/static_assert.hpp>
#include <boost/move/utility_core.hpp>
#include <memory>
#include <algorithm>
#include <cstddef>
namespace boost {
namespace container {
//!An STL node allocator that uses a modified DLMalloc as memory
//!source.
//!
//!This node allocator shares a segregated storage between all instances
//!of adaptive_pool with equal sizeof(T).
//!
//!NodesPerBlock is the number of nodes allocated at once when the allocator
//!needs runs out of nodes. MaxFreeBlocks is the maximum number of totally free blocks
//!that the adaptive node pool will hold. The rest of the totally free blocks will be
//!deallocated to the memory manager.
//!
//!OverheadPercent is the (approximated) maximum size overhead (1-20%) of the allocator:
//!(memory usable for nodes / total memory allocated from the memory allocator)
template < class T
, std::size_t NodesPerBlock BOOST_CONTAINER_DOCONLY(= ADP_nodes_per_block)
, std::size_t MaxFreeBlocks BOOST_CONTAINER_DOCONLY(= ADP_max_free_blocks)
, std::size_t OverheadPercent BOOST_CONTAINER_DOCONLY(= ADP_overhead_percent)
BOOST_CONTAINER_DOCIGN(BOOST_CONTAINER_I unsigned Version)
>
class adaptive_pool
{
//!If Version is 1, the allocator is a STL conforming allocator. If Version is 2,
//!the allocator offers advanced expand in place and burst allocation capabilities.
public:
typedef unsigned int allocation_type;
typedef adaptive_pool
<T, NodesPerBlock, MaxFreeBlocks, OverheadPercent
BOOST_CONTAINER_DOCIGN(BOOST_CONTAINER_I Version)
> self_t;
static const std::size_t nodes_per_block = NodesPerBlock;
static const std::size_t max_free_blocks = MaxFreeBlocks;
static const std::size_t overhead_percent = OverheadPercent;
static const std::size_t real_nodes_per_block = NodesPerBlock;
BOOST_CONTAINER_DOCIGN(BOOST_STATIC_ASSERT((Version <=2)));
public:
//-------
typedef T value_type;
typedef T * pointer;
typedef const T * const_pointer;
typedef typename ::boost::container::
container_detail::unvoid<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
BOOST_CONTAINER_DOCIGN(BOOST_CONTAINER_I Version)
> other;
};
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
//!Not assignable from related adaptive_pool
template<class T2, unsigned Version2, std::size_t N2, std::size_t F2>
adaptive_pool& operator=
(const adaptive_pool<T2, Version2, N2, F2>&);
//!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
BOOST_CONTAINER_DOCIGN(BOOST_CONTAINER_I Version)> &) 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; }
private:
std::pair<pointer, bool> priv_allocation_command
(allocation_type command, std::size_t limit_size
,std::size_t preferred_size,std::size_t &received_size, void *reuse_ptr)
{
boost_cont_command_ret_t ret = {0 , 0};
if(limit_size > this->max_size() || preferred_size > this->max_size()){
// ret.first = 0;
return std::pair<pointer, bool>(pointer(), false);
}
std::size_t l_size = limit_size*sizeof(T);
std::size_t p_size = preferred_size*sizeof(T);
std::size_t r_size;
{
ret = boost_cont_allocation_command(command, sizeof(T), l_size, p_size, &r_size, reuse_ptr);
}
received_size = r_size/sizeof(T);
return std::pair<pointer, bool>(static_cast<pointer>(ret.first), !!ret.second);
}
};
} //namespace container {
} //namespace boost {
#include <boost/container/detail/config_end.hpp>
#endif //#ifndef BOOST_CONTAINER_ADAPTIVE_POOL_HPP

View file

@ -0,0 +1,367 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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/static_assert.hpp>
#include <cstddef>
#include <cassert>
#include <new>
namespace boost {
namespace container {
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
template<unsigned Version, unsigned int AllocationDisableMask>
class allocator<void, Version, AllocationDisableMask>
{
typedef allocator<void, Version, AllocationDisableMask> self_t;
public:
typedef void value_type;
typedef void * pointer;
typedef const void* const_pointer;
typedef int & reference;
typedef const int & const_reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef boost::container::container_detail::
version_type<self_t, Version> version;
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
typedef boost::container::container_detail::
basic_multiallocation_chain<void*> multiallocation_chain;
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//!Obtains an allocator that allocates
//!objects of type T2
template<class T2>
struct rebind
{
typedef allocator< T2
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
, Version, AllocationDisableMask
#endif
> other;
};
//!Default constructor
//!Never throws
allocator()
{}
//!Constructor from other allocator.
//!Never throws
allocator(const allocator &)
{}
//!Constructor from related allocator.
//!Never throws
template<class T2>
allocator(const allocator<T2, Version, AllocationDisableMask> &)
{}
};
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//!\file
//! This class is an extended STL-compatible that offers advanced allocation mechanism
//!(in-place expansion, shrinking, burst-allocation...)
//!
//! This allocator is a wrapper around a modified DLmalloc.
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
template<class T>
#else
//! If Version is 1, the allocator is a STL conforming allocator. If Version is 2,
//! the allocator offers advanced expand in place and burst allocation capabilities.
//
//! AllocationDisableMask works only if Version is 2 and it can be an inclusive OR
//! of allocation types the user wants to disable.
template<class T, unsigned Version, unsigned int AllocationDisableMask>
#endif //#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
class allocator
{
typedef unsigned int allocation_type;
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
//Self type
typedef allocator<T, Version, AllocationDisableMask> self_t;
//Not assignable from related allocator
template<class T2, unsigned int Version2, unsigned int AllocationDisableMask2>
allocator& operator=(const allocator<T2, Version2, AllocationDisableMask2>&);
//Not assignable from other allocator
allocator& operator=(const allocator&);
static const unsigned int ForbiddenMask =
BOOST_CONTAINER_ALLOCATE_NEW | BOOST_CONTAINER_EXPAND_BWD | BOOST_CONTAINER_EXPAND_FWD ;
//The mask can't disable all the allocation types
BOOST_STATIC_ASSERT(( (AllocationDisableMask & ForbiddenMask) != ForbiddenMask ));
//The mask is only valid for version 2 allocators
BOOST_STATIC_ASSERT(( Version != 1 || (AllocationDisableMask == 0) ));
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
public:
typedef T value_type;
typedef T * pointer;
typedef const T * const_pointer;
typedef T & reference;
typedef const T & const_reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef boost::container::container_detail::
version_type<self_t, Version> version;
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
typedef boost::container::container_detail::
basic_multiallocation_chain<void*> void_multiallocation_chain;
typedef boost::container::container_detail::
transform_multiallocation_chain
<void_multiallocation_chain, T> multiallocation_chain;
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//!Obtains an allocator that allocates
//!objects of type T2
template<class T2>
struct rebind
{
typedef allocator<T2, Version, AllocationDisableMask> other;
};
//!Default constructor
//!Never throws
allocator() BOOST_CONTAINER_NOEXCEPT
{}
//!Constructor from other allocator.
//!Never throws
allocator(const allocator &) BOOST_CONTAINER_NOEXCEPT
{}
//!Constructor from related allocator.
//!Never throws
template<class T2>
allocator(const allocator<T2
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
, Version, AllocationDisableMask
#endif
> &) BOOST_CONTAINER_NOEXCEPT
{}
//!Allocates memory for an array of count elements.
//!Throws std::bad_alloc if there is no enough memory
//!If Version is 2, this allocated memory can only be deallocated
//!with deallocate() or (for Version == 2) deallocate_many()
pointer allocate(size_type count, const void * hint= 0)
{
(void)hint;
if(count > this->max_size())
boost::container::throw_bad_alloc();
void *ret = boost_cont_malloc(count*sizeof(T));
if(!ret)
boost::container::throw_bad_alloc();
return static_cast<pointer>(ret);
}
//!Deallocates previously allocated memory.
//!Never throws
void deallocate(pointer ptr, size_type) BOOST_CONTAINER_NOEXCEPT
{ boost_cont_free(ptr); }
//!Returns the maximum number of elements that could be allocated.
//!Never throws
size_type max_size() const BOOST_CONTAINER_NOEXCEPT
{ return size_type(-1)/sizeof(T); }
//!Swaps two allocators, does nothing
//!because this allocator is stateless
friend void swap(self_t &, self_t &) BOOST_CONTAINER_NOEXCEPT
{}
//!An allocator always compares to true, as memory allocated with one
//!instance can be deallocated by another instance
friend bool operator==(const allocator &, const allocator &) BOOST_CONTAINER_NOEXCEPT
{ return true; }
//!An allocator always compares to false, as memory allocated with one
//!instance can be deallocated by another instance
friend bool operator!=(const allocator &, const allocator &) BOOST_CONTAINER_NOEXCEPT
{ return false; }
//!An advanced function that offers in-place expansion shrink to fit and new allocation
//!capabilities. Memory allocated with this function can only be deallocated with deallocate()
//!or deallocate_many().
//!This function is available only with Version == 2
std::pair<pointer, bool>
allocation_command(allocation_type command,
size_type limit_size,
size_type preferred_size,
size_type &received_size, pointer reuse = pointer())
{
BOOST_STATIC_ASSERT(( Version > 1 ));
const allocation_type mask(AllocationDisableMask);
command &= ~mask;
std::pair<pointer, bool> ret =
priv_allocation_command(command, limit_size, preferred_size, received_size, reuse);
if(!ret.first && !(command & BOOST_CONTAINER_NOTHROW_ALLOCATION))
boost::container::throw_bad_alloc();
return ret;
}
//!Returns maximum the number of objects the previously allocated memory
//!pointed by p can hold.
//!Memory must not have been allocated with
//!allocate_one or allocate_individual.
//!This function is available only with Version == 2
size_type size(pointer p) const BOOST_CONTAINER_NOEXCEPT
{
BOOST_STATIC_ASSERT(( Version > 1 ));
return boost_cont_size(p);
}
//!Allocates just one object. Memory allocated with this function
//!must be deallocated only with deallocate_one().
//!Throws bad_alloc if there is no enough memory
//!This function is available only with Version == 2
pointer allocate_one()
{
BOOST_STATIC_ASSERT(( Version > 1 ));
return this->allocate(1);
}
//!Allocates many elements of size == 1.
//!Elements must be individually deallocated with deallocate_one()
//!This function is available only with Version == 2
void allocate_individual(std::size_t num_elements, multiallocation_chain &chain)
{
BOOST_STATIC_ASSERT(( Version > 1 ));
this->allocate_many(1, num_elements, chain);
}
//!Deallocates memory previously allocated with allocate_one().
//!You should never use deallocate_one to deallocate memory allocated
//!with other functions different from allocate_one() or allocate_individual.
//Never throws
void deallocate_one(pointer p) BOOST_CONTAINER_NOEXCEPT
{
BOOST_STATIC_ASSERT(( Version > 1 ));
return this->deallocate(p, 1);
}
//!Deallocates memory allocated with allocate_one() or allocate_individual().
//!This function is available only with Version == 2
void deallocate_individual(multiallocation_chain &chain) BOOST_CONTAINER_NOEXCEPT
{
BOOST_STATIC_ASSERT(( Version > 1 ));
return this->deallocate_many(chain);
}
//!Allocates many elements of size elem_size.
//!Elements must be individually deallocated with deallocate()
//!This function is available only with Version == 2
void allocate_many(size_type elem_size, std::size_t n_elements, multiallocation_chain &chain)
{
BOOST_STATIC_ASSERT(( Version > 1 ));/*
boost_cont_memchain ch;
BOOST_CONTAINER_MEMCHAIN_INIT(&ch);
if(!boost_cont_multialloc_nodes(n_elements, elem_size*sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &ch)){
boost::container::throw_bad_alloc();
}
chain.incorporate_after(chain.before_begin()
,(T*)BOOST_CONTAINER_MEMCHAIN_FIRSTMEM(&ch)
,(T*)BOOST_CONTAINER_MEMCHAIN_LASTMEM(&ch)
,BOOST_CONTAINER_MEMCHAIN_SIZE(&ch) );*/
if(!boost_cont_multialloc_nodes(n_elements, elem_size*sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, reinterpret_cast<boost_cont_memchain *>(&chain))){
boost::container::throw_bad_alloc();
}
}
//!Allocates n_elements elements, each one of size elem_sizes[i]
//!Elements must be individually deallocated with deallocate()
//!This function is available only with Version == 2
void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain)
{
BOOST_STATIC_ASSERT(( Version > 1 ));
boost_cont_memchain ch;
BOOST_CONTAINER_MEMCHAIN_INIT(&ch);
if(!boost_cont_multialloc_arrays(n_elements, elem_sizes, sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &ch)){
boost::container::throw_bad_alloc();
}
chain.incorporate_after(chain.before_begin()
,(T*)BOOST_CONTAINER_MEMCHAIN_FIRSTMEM(&ch)
,(T*)BOOST_CONTAINER_MEMCHAIN_LASTMEM(&ch)
,BOOST_CONTAINER_MEMCHAIN_SIZE(&ch) );
/*
if(!boost_cont_multialloc_arrays(n_elements, elem_sizes, sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, reinterpret_cast<boost_cont_memchain *>(&chain))){
boost::container::throw_bad_alloc();
}*/
}
//!Deallocates several elements allocated by
//!allocate_many(), allocate(), or allocation_command().
//!This function is available only with Version == 2
void deallocate_many(multiallocation_chain &chain) BOOST_CONTAINER_NOEXCEPT
{
BOOST_STATIC_ASSERT(( Version > 1 ));
boost_cont_memchain ch;
void *beg(&*chain.begin()), *last(&*chain.last());
size_t size(chain.size());
BOOST_CONTAINER_MEMCHAIN_INIT_FROM(&ch, beg, last, size);
boost_cont_multidealloc(&ch);
//boost_cont_multidealloc(reinterpret_cast<boost_cont_memchain *>(&chain));
}
private:
std::pair<pointer, bool> priv_allocation_command
(allocation_type command, std::size_t limit_size
,std::size_t preferred_size,std::size_t &received_size, void *reuse_ptr)
{
boost_cont_command_ret_t ret = {0 , 0};
if((limit_size > this->max_size()) | (preferred_size > this->max_size())){
return std::pair<pointer, bool>(pointer(), false);
}
std::size_t l_size = limit_size*sizeof(T);
std::size_t p_size = preferred_size*sizeof(T);
std::size_t r_size;
{
ret = boost_cont_allocation_command(command, sizeof(T), l_size, p_size, &r_size, reuse_ptr);
}
received_size = r_size/sizeof(T);
return std::pair<pointer, bool>(static_cast<pointer>(ret.first), !!ret.second);
}
};
} //namespace container {
} //namespace boost {
#include <boost/container/detail/config_end.hpp>
#endif //BOOST_CONTAINER_ALLOCATOR_HPP

View file

@ -0,0 +1,409 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Pablo Halpern 2009. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2011-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_ALLOCATOR_ALLOCATOR_TRAITS_HPP
#define BOOST_CONTAINER_ALLOCATOR_ALLOCATOR_TRAITS_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/container_fwd.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/intrusive/detail/memory_util.hpp>
#include <boost/container/detail/memory_util.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/placement_new.hpp>
#include <boost/move/utility_core.hpp>
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#include <boost/container/detail/preprocessor.hpp>
#endif
namespace boost {
namespace container {
namespace allocator_traits_detail {
}
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
namespace container_detail {
//workaround needed for C++03 compilers with no construct()
//supporting rvalue references
template<class A>
struct is_std_allocator
{ static const bool value = false; };
template<class T>
struct is_std_allocator< std::allocator<T> >
{ static const bool value = true; };
} //namespace container_detail {
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//! The class template allocator_traits supplies a uniform interface to all allocator types.
//! This class is a C++03-compatible implementation of std::allocator_traits
template <typename Alloc>
struct allocator_traits
{
//allocator_type
typedef Alloc allocator_type;
//value_type
typedef typename Alloc::value_type value_type;
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//! Alloc::pointer if such a type exists; otherwise, value_type*
//!
typedef unspecified pointer;
//! Alloc::const_pointer if such a type exists ; otherwise, pointer_traits<pointer>::rebind<const
//!
typedef see_documentation const_pointer;
//! Non-standard extension
//! Alloc::reference if such a type exists; otherwise, value_type&
typedef see_documentation reference;
//! Non-standard extension
//! Alloc::const_reference if such a type exists ; otherwise, const value_type&
typedef see_documentation const_reference;
//! Alloc::void_pointer if such a type exists ; otherwise, pointer_traits<pointer>::rebind<void>.
//!
typedef see_documentation void_pointer;
//! Alloc::const_void_pointer if such a type exists ; otherwis e, pointer_traits<pointer>::rebind<const
//!
typedef see_documentation const_void_pointer;
//! Alloc::difference_type if such a type exists ; otherwise, pointer_traits<pointer>::difference_type.
//!
typedef see_documentation difference_type;
//! Alloc::size_type if such a type exists ; otherwise, make_unsigned<difference_type>::type
//!
typedef see_documentation size_type;
//! Alloc::propagate_on_container_copy_assignment if such a type exists, otherwise an integral_constant
//! type with internal constant static member <code>value</code> == false.
typedef see_documentation propagate_on_container_copy_assignment;
//! Alloc::propagate_on_container_move_assignment if such a type exists, otherwise an integral_constant
//! type with internal constant static member <code>value</code> == false.
typedef see_documentation propagate_on_container_move_assignment;
//! Alloc::propagate_on_container_swap if such a type exists, otherwise an integral_constant
//! type with internal constant static member <code>value</code> == false.
typedef see_documentation propagate_on_container_swap;
//! Defines an allocator: Alloc::rebind<T>::other if such a type exists; otherwise, Alloc<T, Args>
//! if Alloc is a class template instantiation of the form Alloc<U, Args>, where Args is zero or
//! more type arguments ; otherwise, the instantiation of rebind_alloc is ill-formed.
//!
//! In C++03 compilers <code>rebind_alloc</code> is a struct derived from an allocator
//! deduced by previously detailed rules.
template <class T> using rebind_alloc = see_documentation;
//! In C++03 compilers <code>rebind_traits</code> is a struct derived from
//! <code>allocator_traits<OtherAlloc></code>, where <code>OtherAlloc</code> is
//! the allocator deduced by rules explained in <code>rebind_alloc</code>.
template <class T> using rebind_traits = allocator_traits<rebind_alloc<T> >;
//! Non-standard extension: Portable allocator rebind for C++03 and C++11 compilers.
//! <code>type</code> is an allocator related to Alloc deduced deduced by rules explained in <code>rebind_alloc</code>.
template <class T>
struct portable_rebind_alloc
{ typedef see_documentation type; };
#else
//pointer
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc,
pointer, value_type*)
pointer;
//const_pointer
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_EVAL_DEFAULT(boost::container::container_detail::, Alloc,
const_pointer, typename boost::intrusive::pointer_traits<pointer>::template
rebind_pointer<const value_type>)
const_pointer;
//reference
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc,
reference, typename container_detail::unvoid<value_type>::type&)
reference;
//const_reference
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc,
const_reference, const typename container_detail::unvoid<value_type>::type&)
const_reference;
//void_pointer
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_EVAL_DEFAULT(boost::container::container_detail::, Alloc,
void_pointer, typename boost::intrusive::pointer_traits<pointer>::template
rebind_pointer<void>)
void_pointer;
//const_void_pointer
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_EVAL_DEFAULT(boost::container::container_detail::, Alloc,
const_void_pointer, typename boost::intrusive::pointer_traits<pointer>::template
rebind_pointer<const void>)
const_void_pointer;
//difference_type
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc,
difference_type, std::ptrdiff_t)
difference_type;
//size_type
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc,
size_type, std::size_t)
size_type;
//propagate_on_container_copy_assignment
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc,
propagate_on_container_copy_assignment, container_detail::false_type)
propagate_on_container_copy_assignment;
//propagate_on_container_move_assignment
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc,
propagate_on_container_move_assignment, container_detail::false_type)
propagate_on_container_move_assignment;
//propagate_on_container_swap
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc,
propagate_on_container_swap, container_detail::false_type)
propagate_on_container_swap;
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
//C++11
template <typename T> using rebind_alloc = typename boost::intrusive::pointer_rebind<Alloc, T>::type;
template <typename T> using rebind_traits = allocator_traits< rebind_alloc<T> >;
#else // #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
//Some workaround for C++03 or C++11 compilers with no template aliases
template <typename T>
struct rebind_alloc : boost::intrusive::pointer_rebind<Alloc,T>::type
{
typedef typename boost::intrusive::pointer_rebind<Alloc,T>::type Base;
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <typename... Args>
rebind_alloc(BOOST_FWD_REF(Args)... args)
: Base(boost::forward<Args>(args)...)
{}
#else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#define BOOST_PP_LOCAL_MACRO(n) \
BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
rebind_alloc(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
: Base(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)) \
{} \
//
#define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
#include BOOST_PP_LOCAL_ITERATE()
#endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
};
template <typename T>
struct rebind_traits
: allocator_traits<typename boost::intrusive::pointer_rebind<Alloc, T>::type>
{};
#endif // #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
template <class T>
struct portable_rebind_alloc
{ typedef typename boost::intrusive::pointer_rebind<Alloc, T>::type type; };
#endif //BOOST_CONTAINER_DOXYGEN_INVOKED
//! <b>Returns</b>: <code>a.allocate(n)</code>
//!
static pointer allocate(Alloc &a, size_type n)
{ return a.allocate(n); }
//! <b>Returns</b>: <code>a.deallocate(p, n)</code>
//!
//! <b>Throws</b>: Nothing
static void deallocate(Alloc &a, pointer p, size_type n)
{ a.deallocate(p, n); }
//! <b>Effects</b>: calls <code>a.allocate(n, p)</code> if that call is well-formed;
//! otherwise, invokes <code>a.allocate(n)</code>
static pointer allocate(Alloc &a, size_type n, const_void_pointer p)
{
const bool value = boost::container::container_detail::
has_member_function_callable_with_allocate
<Alloc, const size_type, const const_void_pointer>::value;
container_detail::bool_<value> flag;
return allocator_traits::priv_allocate(flag, a, n, p);
}
//! <b>Effects</b>: calls <code>a.destroy(p)</code> if that call is well-formed;
//! otherwise, invokes <code>p->~T()</code>.
template<class T>
static void destroy(Alloc &a, T*p) BOOST_CONTAINER_NOEXCEPT
{
typedef T* destroy_pointer;
const bool value = boost::container::container_detail::
has_member_function_callable_with_destroy
<Alloc, const destroy_pointer>::value;
container_detail::bool_<value> flag;
allocator_traits::priv_destroy(flag, a, p);
}
//! <b>Returns</b>: <code>a.max_size()</code> if that expression is well-formed; otherwise,
//! <code>numeric_limits<size_type>::max()</code>.
static size_type max_size(const Alloc &a) BOOST_CONTAINER_NOEXCEPT
{
const bool value = boost::container::container_detail::
has_member_function_callable_with_max_size
<const Alloc>::value;
container_detail::bool_<value> flag;
return allocator_traits::priv_max_size(flag, a);
}
//! <b>Returns</b>: <code>a.select_on_container_copy_construction()</code> if that expression is well-formed;
//! otherwise, a.
static
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
typename container_detail::if_c
< boost::container::container_detail::
has_member_function_callable_with_select_on_container_copy_construction
<const Alloc>::value
, Alloc
, const Alloc &
>::type
#else
Alloc
#endif
select_on_container_copy_construction(const Alloc &a)
{
const bool value = boost::container::container_detail::
has_member_function_callable_with_select_on_container_copy_construction
<const Alloc>::value;
container_detail::bool_<value> flag;
return allocator_traits::priv_select_on_container_copy_construction(flag, a);
}
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//! <b>Effects</b>: calls <code>a.construct(p, std::forward<Args>(args)...)</code> if that call is well-formed;
//! otherwise, invokes <code>::new (static_cast<void*>(p)) T(std::forward<Args>(args)...)</code>
template <class T, class ...Args>
static void construct(Alloc & a, T* p, BOOST_FWD_REF(Args)... args)
{
container_detail::bool_<container_detail::is_std_allocator<Alloc>::value> flag;
allocator_traits::priv_construct(flag, a, p, ::boost::forward<Args>(args)...);
}
#endif
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
private:
static pointer priv_allocate(container_detail::true_type, Alloc &a, size_type n, const_void_pointer p)
{ return a.allocate(n, p); }
static pointer priv_allocate(container_detail::false_type, Alloc &a, size_type n, const_void_pointer)
{ return allocator_traits::allocate(a, n); }
template<class T>
static void priv_destroy(container_detail::true_type, Alloc &a, T* p) BOOST_CONTAINER_NOEXCEPT
{ a.destroy(p); }
template<class T>
static void priv_destroy(container_detail::false_type, Alloc &, T* p) BOOST_CONTAINER_NOEXCEPT
{ p->~T(); (void)p; }
static size_type priv_max_size(container_detail::true_type, const Alloc &a) BOOST_CONTAINER_NOEXCEPT
{ return a.max_size(); }
static size_type priv_max_size(container_detail::false_type, const Alloc &) BOOST_CONTAINER_NOEXCEPT
{ return size_type(-1); }
static Alloc priv_select_on_container_copy_construction(container_detail::true_type, const Alloc &a)
{ return a.select_on_container_copy_construction(); }
static const Alloc &priv_select_on_container_copy_construction(container_detail::false_type, const Alloc &a) BOOST_CONTAINER_NOEXCEPT
{ return a; }
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template<class T, class ...Args>
static void priv_construct(container_detail::false_type, Alloc &a, T *p, BOOST_FWD_REF(Args) ...args)
{
const bool value = boost::container::container_detail::
has_member_function_callable_with_construct
< Alloc, T*, Args... >::value;
container_detail::bool_<value> flag;
priv_construct_dispatch2(flag, a, p, ::boost::forward<Args>(args)...);
}
template<class T, class ...Args>
static void priv_construct(container_detail::true_type, Alloc &a, T *p, BOOST_FWD_REF(Args) ...args)
{
priv_construct_dispatch2(container_detail::false_type(), a, p, ::boost::forward<Args>(args)...);
}
template<class T, class ...Args>
static void priv_construct_dispatch2(container_detail::true_type, Alloc &a, T *p, BOOST_FWD_REF(Args) ...args)
{ a.construct( p, ::boost::forward<Args>(args)...); }
template<class T, class ...Args>
static void priv_construct_dispatch2(container_detail::false_type, Alloc &, T *p, BOOST_FWD_REF(Args) ...args)
{ ::new((void*)p, boost_container_new_t()) T(::boost::forward<Args>(args)...); }
#else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
public:
#define BOOST_PP_LOCAL_MACRO(n) \
template<class T BOOST_PP_ENUM_TRAILING_PARAMS(n, class P) > \
static void construct(Alloc &a, T *p \
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
{ \
container_detail::bool_ \
<container_detail::is_std_allocator<Alloc>::value> flag; \
allocator_traits::priv_construct(flag, a, p \
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \
} \
//
#define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
#include BOOST_PP_LOCAL_ITERATE()
private:
#define BOOST_PP_LOCAL_MACRO(n) \
template<class T BOOST_PP_ENUM_TRAILING_PARAMS(n, class P) > \
static void priv_construct(container_detail::false_type, Alloc &a, T *p \
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST,_)) \
{ \
const bool value = \
boost::container::container_detail::has_member_function_callable_with_construct \
< Alloc, T* BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_FWD_TYPE, _) >::value; \
container_detail::bool_<value> flag; \
priv_construct_dispatch2(flag, a, p \
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \
} \
\
template<class T BOOST_PP_ENUM_TRAILING_PARAMS(n, class P) > \
static void priv_construct(container_detail::true_type, Alloc &a, T *p \
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST,_)) \
{ \
priv_construct_dispatch2(container_detail::false_type(), a, p \
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \
} \
\
template<class T BOOST_PP_ENUM_TRAILING_PARAMS(n, class P) > \
static void priv_construct_dispatch2(container_detail::true_type, Alloc &a, T *p \
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST,_)) \
{ a.construct( p BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); } \
\
template<class T BOOST_PP_ENUM_TRAILING_PARAMS(n, class P) > \
static void priv_construct_dispatch2(container_detail::false_type, Alloc &, T *p \
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _) ) \
{ ::new((void*)p, boost_container_new_t()) T(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); }\
//
#define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
#include BOOST_PP_LOCAL_ITERATE()
#endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template<class T>
static void priv_construct_dispatch2(container_detail::false_type, Alloc &, T *p, ::boost::container::default_init_t)
{ ::new((void*)p) T; }
#endif //#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
};
} //namespace container {
} //namespace boost {
#include <boost/container/detail/config_end.hpp>
#endif // ! defined(BOOST_CONTAINER_ALLOCATOR_ALLOCATOR_TRAITS_HPP)

View file

@ -0,0 +1,270 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2014. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_CONTAINER_FWD_HPP
#define BOOST_CONTAINER_CONTAINER_FWD_HPP
#if defined(_MSC_VER)
# pragma once
#endif
//! \file
//! This header file forward declares the following containers:
//! - boost::container::vector
//! - boost::container::stable_vector
//! - boost::container::static_vector
//! - boost::container::slist
//! - boost::container::list
//! - boost::container::set
//! - boost::container::multiset
//! - boost::container::map
//! - boost::container::multimap
//! - boost::container::flat_set
//! - boost::container::flat_multiset
//! - boost::container::flat_map
//! - boost::container::flat_multimap
//! - boost::container::basic_string
//! - boost::container::string
//! - boost::container::wstring
//!
//! It forward declares the following allocators:
//! - boost::container::allocator
//! - boost::container::node_allocator
//! - boost::container::adaptive_pool
//!
//! And finally it defines the following types
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//Std forward declarations
#ifndef BOOST_CONTAINER_DETAIL_STD_FWD_HPP
#include <boost/container/detail/std_fwd.hpp>
#endif
namespace boost{
namespace intrusive{
//Create namespace to avoid compilation errors
}}
namespace boost{ namespace container{ namespace container_detail{
namespace bi = boost::intrusive;
}}}
#include <cstddef>
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//////////////////////////////////////////////////////////////////////////////
// Containers
//////////////////////////////////////////////////////////////////////////////
namespace boost {
namespace container {
//! Enumeration used to configure ordered associative containers
//! with a concrete tree implementation.
enum tree_type_enum
{
red_black_tree,
avl_tree,
scapegoat_tree,
splay_tree
};
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
template <class T
,class Allocator = std::allocator<T> >
class vector;
template <class T
,class Allocator = std::allocator<T> >
class stable_vector;
template <class T, std::size_t Capacity>
class static_vector;
template <class T
,class Allocator = std::allocator<T> >
class deque;
template <class T
,class Allocator = std::allocator<T> >
class list;
template <class T
,class Allocator = std::allocator<T> >
class slist;
template<tree_type_enum TreeType, bool OptimizeSize>
struct tree_opt;
typedef tree_opt<red_black_tree, true> tree_assoc_defaults;
template <class Key
,class Compare = std::less<Key>
,class Allocator = std::allocator<Key>
,class Options = tree_assoc_defaults >
class set;
template <class Key
,class Compare = std::less<Key>
,class Allocator = std::allocator<Key>
,class Options = tree_assoc_defaults >
class multiset;
template <class Key
,class T
,class Compare = std::less<Key>
,class Allocator = std::allocator<std::pair<const Key, T> >
,class Options = tree_assoc_defaults >
class map;
template <class Key
,class T
,class Compare = std::less<Key>
,class Allocator = std::allocator<std::pair<const Key, T> >
,class Options = tree_assoc_defaults >
class multimap;
template <class Key
,class Compare = std::less<Key>
,class Allocator = std::allocator<Key> >
class flat_set;
template <class Key
,class Compare = std::less<Key>
,class Allocator = std::allocator<Key> >
class flat_multiset;
template <class Key
,class T
,class Compare = std::less<Key>
,class Allocator = std::allocator<std::pair<Key, T> > >
class flat_map;
template <class Key
,class T
,class Compare = std::less<Key>
,class Allocator = std::allocator<std::pair<Key, T> > >
class flat_multimap;
template <class CharT
,class Traits = std::char_traits<CharT>
,class Allocator = std::allocator<CharT> >
class basic_string;
typedef basic_string
<char
,std::char_traits<char>
,std::allocator<char> >
string;
typedef basic_string
<wchar_t
,std::char_traits<wchar_t>
,std::allocator<wchar_t> >
wstring;
static const std::size_t ADP_nodes_per_block = 256u;
static const std::size_t ADP_max_free_blocks = 2u;
static const std::size_t ADP_overhead_percent = 1u;
static const std::size_t ADP_only_alignment = 0u;
template < class T
, std::size_t NodesPerBlock = ADP_nodes_per_block
, std::size_t MaxFreeBlocks = ADP_max_free_blocks
, std::size_t OverheadPercent = ADP_overhead_percent
, unsigned Version = 2
>
class adaptive_pool;
template < class T
, unsigned Version = 2
, unsigned int AllocationDisableMask = 0>
class allocator;
static const std::size_t NodeAlloc_nodes_per_block = 256u;
template
< class T
, std::size_t NodesPerBlock = NodeAlloc_nodes_per_block
, std::size_t Version = 2>
class node_allocator;
#else
//! Default options for tree-based associative containers
//! - tree_type<red_black_tree>
//! - optimize_size<true>
typedef implementation_defined tree_assoc_defaults;
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//! Type used to tag that the input range is
//! guaranteed to be ordered
struct ordered_range_t
{};
//! Value used to tag that the input range is
//! guaranteed to be ordered
static const ordered_range_t ordered_range = ordered_range_t();
//! Type used to tag that the input range is
//! guaranteed to be ordered and unique
struct ordered_unique_range_t
: public ordered_range_t
{};
//! Value used to tag that the input range is
//! guaranteed to be ordered and unique
static const ordered_unique_range_t ordered_unique_range = ordered_unique_range_t();
//! Type used to tag that the inserted values
//! should be default initialized
struct default_init_t
{};
//! Value used to tag that the inserted values
//! should be default initialized
static const default_init_t default_init = default_init_t();
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//! Type used to tag that the inserted values
//! should be value initialized
struct value_init_t
{};
//! Value used to tag that the inserted values
//! should be value initialized
static const value_init_t value_init = value_init_t();
namespace container_detail_really_deep_namespace {
//Otherwise, gcc issues a warning of previously defined
//anonymous_instance and unique_instance
struct dummy
{
dummy()
{
(void)ordered_range;
(void)ordered_unique_range;
(void)default_init;
}
};
} //detail_really_deep_namespace {
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
}} //namespace boost { namespace container {
#endif //#ifndef BOOST_CONTAINER_CONTAINER_FWD_HPP

2069
boost/container/deque.hpp Normal file

File diff suppressed because it is too large Load diff

View file

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

View file

@ -0,0 +1,875 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_DETAIL_ADAPTIVE_NODE_POOL_IMPL_HPP
#define BOOST_CONTAINER_DETAIL_ADAPTIVE_NODE_POOL_IMPL_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/container_fwd.hpp>
#include <boost/container/detail/utilities.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/intrusive/set.hpp>
#include <boost/intrusive/list.hpp>
#include <boost/intrusive/slist.hpp>
#include <boost/container/detail/type_traits.hpp>
#include <boost/container/detail/math_functions.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/pool_common.hpp>
#include <boost/container/throw_exception.hpp>
#include <boost/assert.hpp>
#include <boost/core/no_exceptions_support.hpp>
#include <cstddef>
namespace boost {
namespace container {
namespace adaptive_pool_flag {
static const unsigned int none = 0u;
static const unsigned int align_only = 1u << 0u;
static const unsigned int size_ordered = 1u << 1u;
static const unsigned int address_ordered = 1u << 2u;
} //namespace adaptive_pool_flag{
namespace container_detail {
template<class size_type>
struct hdr_offset_holder_t
{
hdr_offset_holder_t(size_type offset = 0)
: hdr_offset(offset)
{}
size_type hdr_offset;
};
template<class SizeType, unsigned int Flags>
struct less_func;
template<class SizeType>
struct less_func<SizeType, adaptive_pool_flag::none>
{
static bool less(SizeType, SizeType, const void *, const void *)
{ return true; }
};
template<class SizeType>
struct less_func<SizeType, adaptive_pool_flag::size_ordered>
{
static bool less(SizeType ls, SizeType rs, const void *, const void *)
{ return ls < rs; }
};
template<class SizeType>
struct less_func<SizeType, adaptive_pool_flag::address_ordered>
{
static bool less(SizeType, SizeType, const void *la, const void *ra)
{ return &la < &ra; }
};
template<class SizeType>
struct less_func<SizeType, adaptive_pool_flag::size_ordered | adaptive_pool_flag::address_ordered>
{
static bool less(SizeType ls, SizeType rs, const void *la, const void *ra)
{ return (ls < rs) || ((ls == rs) && (la < ra)); }
};
template<class VoidPointer, class SizeType, bool ordered>
struct block_container_traits
{
typedef typename bi::make_set_base_hook
< bi::void_pointer<VoidPointer>
, bi::optimize_size<true>
, bi::link_mode<bi::normal_link> >::type hook_t;
template<class T>
struct container
{
typedef typename bi::make_multiset
<T, bi::base_hook<hook_t>, bi::size_type<SizeType> >::type type;
};
template<class Container>
static void reinsert_was_used(Container &container, typename Container::reference v, bool)
{
typedef typename Container::const_iterator const_block_iterator;
const const_block_iterator this_block
(Container::s_iterator_to(const_cast<typename Container::const_reference>(v)));
const_block_iterator next_block(this_block);
if(++next_block != container.cend()){
if(this_block->free_nodes.size() > next_block->free_nodes.size()){
container.erase(this_block);
container.insert(v);
}
}
}
template<class Container>
static void insert_was_empty(Container &container, typename Container::value_type &v, bool)
{
container.insert(v);
}
template<class Container>
static void erase_first(Container &container)
{
container.erase(container.cbegin());
}
template<class Container>
static void erase_last(Container &container)
{
container.erase(--container.cend());
}
};
template<class VoidPointer, class SizeType>
struct block_container_traits<VoidPointer, SizeType, false>
{
typedef typename bi::make_list_base_hook
< bi::void_pointer<VoidPointer>
, bi::link_mode<bi::normal_link> >::type hook_t;
template<class T>
struct container
{
typedef typename bi::make_list
<T, bi::base_hook<hook_t>, bi::size_type<SizeType>, bi::constant_time_size<false> >::type type;
};
template<class Container>
static void reinsert_was_used(Container &container, typename Container::value_type &v, bool is_full)
{
if(is_full){
container.erase(Container::s_iterator_to(v));
container.push_back(v);
}
}
template<class Container>
static void insert_was_empty(Container &container, typename Container::value_type &v, bool is_full)
{
if(is_full){
container.push_back(v);
}
else{
container.push_front(v);
}
}
template<class Container>
static void erase_first(Container &container)
{
container.pop_front();
}
template<class Container>
static void erase_last(Container &container)
{
container.pop_back();
}
};
template<class MultiallocationChain, class VoidPointer, class SizeType, unsigned int Flags>
struct adaptive_pool_types
{
typedef VoidPointer void_pointer;
static const bool ordered = (Flags & (adaptive_pool_flag::size_ordered | adaptive_pool_flag::address_ordered)) != 0;
typedef block_container_traits<VoidPointer, SizeType, ordered> block_container_traits_t;
typedef typename block_container_traits_t::hook_t hook_t;
typedef hdr_offset_holder_t<SizeType> hdr_offset_holder;
static const unsigned int order_flags = Flags & (adaptive_pool_flag::size_ordered | adaptive_pool_flag::address_ordered);
typedef MultiallocationChain free_nodes_t;
struct block_info_t
: public hdr_offset_holder,
public hook_t
{
//An intrusive list of free node from this block
free_nodes_t free_nodes;
friend bool operator <(const block_info_t &l, const block_info_t &r)
{
return less_func<SizeType, order_flags>::
less(l.free_nodes.size(), r.free_nodes.size(), &l , &r);
}
friend bool operator ==(const block_info_t &l, const block_info_t &r)
{ return &l == &r; }
};
typedef typename block_container_traits_t:: template container<block_info_t>::type block_container_t;
};
template<class size_type>
inline size_type calculate_alignment
( size_type overhead_percent, size_type real_node_size
, size_type hdr_size, size_type hdr_offset_size, size_type payload_per_allocation)
{
//to-do: handle real_node_size != node_size
const size_type divisor = overhead_percent*real_node_size;
const size_type dividend = hdr_offset_size*100;
size_type elements_per_subblock = (dividend - 1)/divisor + 1;
size_type candidate_power_of_2 =
upper_power_of_2(elements_per_subblock*real_node_size + hdr_offset_size);
bool overhead_satisfied = false;
//Now calculate the wors-case overhead for a subblock
const size_type max_subblock_overhead = hdr_size + payload_per_allocation;
while(!overhead_satisfied){
elements_per_subblock = (candidate_power_of_2 - max_subblock_overhead)/real_node_size;
const size_type overhead_size = candidate_power_of_2 - elements_per_subblock*real_node_size;
if(overhead_size*100/candidate_power_of_2 < overhead_percent){
overhead_satisfied = true;
}
else{
candidate_power_of_2 <<= 1;
}
}
return candidate_power_of_2;
}
template<class size_type>
inline void calculate_num_subblocks
(size_type alignment, size_type real_node_size, size_type elements_per_block
, size_type &num_subblocks, size_type &real_num_node, size_type overhead_percent
, size_type hdr_size, size_type hdr_offset_size, size_type payload_per_allocation)
{
const size_type hdr_subblock_elements = (alignment - hdr_size - payload_per_allocation)/real_node_size;
size_type elements_per_subblock = (alignment - hdr_offset_size)/real_node_size;
size_type possible_num_subblock = (elements_per_block - 1)/elements_per_subblock + 1;
while(((possible_num_subblock-1)*elements_per_subblock + hdr_subblock_elements) < elements_per_block){
++possible_num_subblock;
}
elements_per_subblock = (alignment - hdr_offset_size)/real_node_size;
bool overhead_satisfied = false;
while(!overhead_satisfied){
const size_type total_data = (elements_per_subblock*(possible_num_subblock-1) + hdr_subblock_elements)*real_node_size;
const size_type total_size = alignment*possible_num_subblock;
if((total_size - total_data)*100/total_size < overhead_percent){
overhead_satisfied = true;
}
else{
++possible_num_subblock;
}
}
num_subblocks = possible_num_subblock;
real_num_node = (possible_num_subblock-1)*elements_per_subblock + hdr_subblock_elements;
}
template<class SegmentManagerBase, unsigned int Flags>
class private_adaptive_node_pool_impl
{
//Non-copyable
private_adaptive_node_pool_impl();
private_adaptive_node_pool_impl(const private_adaptive_node_pool_impl &);
private_adaptive_node_pool_impl &operator=(const private_adaptive_node_pool_impl &);
typedef private_adaptive_node_pool_impl this_type;
typedef typename SegmentManagerBase::void_pointer void_pointer;
static const typename SegmentManagerBase::
size_type PayloadPerAllocation = SegmentManagerBase::PayloadPerAllocation;
//Flags
//align_only
static const bool AlignOnly = (Flags & adaptive_pool_flag::align_only) != 0;
typedef bool_<AlignOnly> IsAlignOnly;
typedef true_ AlignOnlyTrue;
typedef false_ AlignOnlyFalse;
//size_ordered
static const bool SizeOrdered = (Flags & adaptive_pool_flag::size_ordered) != 0;
typedef bool_<SizeOrdered> IsSizeOrdered;
typedef true_ SizeOrderedTrue;
typedef false_ SizeOrderedFalse;
//address_ordered
static const bool AddressOrdered = (Flags & adaptive_pool_flag::address_ordered) != 0;
typedef bool_<AddressOrdered> IsAddressOrdered;
typedef true_ AddressOrderedTrue;
typedef false_ AddressOrderedFalse;
public:
typedef typename SegmentManagerBase::multiallocation_chain multiallocation_chain;
typedef typename SegmentManagerBase::size_type size_type;
private:
typedef adaptive_pool_types
<multiallocation_chain, void_pointer, size_type, Flags> adaptive_pool_types_t;
typedef typename adaptive_pool_types_t::free_nodes_t free_nodes_t;
typedef typename adaptive_pool_types_t::block_info_t block_info_t;
typedef typename adaptive_pool_types_t::block_container_t block_container_t;
typedef typename adaptive_pool_types_t::block_container_traits_t block_container_traits_t;
typedef typename block_container_t::iterator block_iterator;
typedef typename block_container_t::const_iterator const_block_iterator;
typedef typename adaptive_pool_types_t::hdr_offset_holder hdr_offset_holder;
static const size_type MaxAlign = alignment_of<void_pointer>::value;
static const size_type HdrSize = ((sizeof(block_info_t)-1)/MaxAlign+1)*MaxAlign;
static const size_type HdrOffsetSize = ((sizeof(hdr_offset_holder)-1)/MaxAlign+1)*MaxAlign;
public:
//!Segment manager typedef
typedef SegmentManagerBase segment_manager_base_type;
//!Constructor from a segment manager. Never throws
private_adaptive_node_pool_impl
( segment_manager_base_type *segment_mngr_base
, size_type node_size
, size_type nodes_per_block
, size_type max_free_blocks
, unsigned char overhead_percent
)
: m_max_free_blocks(max_free_blocks)
, m_real_node_size(lcm(node_size, size_type(alignment_of<void_pointer>::value)))
//Round the size to a power of two value.
//This is the total memory size (including payload) that we want to
//allocate from the general-purpose allocator
, m_real_block_alignment
(AlignOnly ?
upper_power_of_2(HdrSize + m_real_node_size*nodes_per_block) :
calculate_alignment( (size_type)overhead_percent, m_real_node_size
, HdrSize, HdrOffsetSize, PayloadPerAllocation))
//This is the real number of nodes per block
, m_num_subblocks(0)
, m_real_num_node(AlignOnly ? (m_real_block_alignment - PayloadPerAllocation - HdrSize)/m_real_node_size : 0)
//General purpose allocator
, mp_segment_mngr_base(segment_mngr_base)
, m_block_container()
, m_totally_free_blocks(0)
{
if(!AlignOnly){
calculate_num_subblocks
( m_real_block_alignment
, m_real_node_size
, nodes_per_block
, m_num_subblocks
, m_real_num_node
, (size_type)overhead_percent
, HdrSize
, HdrOffsetSize
, PayloadPerAllocation);
}
}
//!Destructor. Deallocates all allocated blocks. Never throws
~private_adaptive_node_pool_impl()
{ this->priv_clear(); }
size_type get_real_num_node() const
{ return m_real_num_node; }
//!Returns the segment manager. Never throws
segment_manager_base_type* get_segment_manager_base()const
{ return container_detail::to_raw_pointer(mp_segment_mngr_base); }
//!Allocates array of count elements. Can throw
void *allocate_node()
{
this->priv_invariants();
//If there are no free nodes we allocate a new block
if(!m_block_container.empty()){
//We take the first free node the multiset can't be empty
free_nodes_t &free_nodes = m_block_container.begin()->free_nodes;
BOOST_ASSERT(!free_nodes.empty());
const size_type free_nodes_count = free_nodes.size();
void *first_node = container_detail::to_raw_pointer(free_nodes.pop_front());
if(free_nodes.empty()){
block_container_traits_t::erase_first(m_block_container);
}
m_totally_free_blocks -= static_cast<size_type>(free_nodes_count == m_real_num_node);
this->priv_invariants();
return first_node;
}
else{
multiallocation_chain chain;
this->priv_append_from_new_blocks(1, chain, IsAlignOnly());
return container_detail::to_raw_pointer(chain.pop_front());
}
}
//!Deallocates an array pointed by ptr. Never throws
void deallocate_node(void *pElem)
{
this->priv_invariants();
block_info_t &block_info = *this->priv_block_from_node(pElem);
BOOST_ASSERT(block_info.free_nodes.size() < m_real_num_node);
//We put the node at the beginning of the free node list
block_info.free_nodes.push_back(void_pointer(pElem));
//The loop reinserts all blocks except the last one
this->priv_reinsert_block(block_info, block_info.free_nodes.size() == 1);
this->priv_deallocate_free_blocks(m_max_free_blocks);
this->priv_invariants();
}
//!Allocates n nodes.
//!Can throw
void allocate_nodes(const size_type n, multiallocation_chain &chain)
{
size_type i = 0;
BOOST_TRY{
this->priv_invariants();
while(i != n){
//If there are no free nodes we allocate all needed blocks
if (m_block_container.empty()){
this->priv_append_from_new_blocks(n - i, chain, IsAlignOnly());
BOOST_ASSERT(m_block_container.empty() || (++m_block_container.cbegin() == m_block_container.cend()));
BOOST_ASSERT(chain.size() == n);
break;
}
free_nodes_t &free_nodes = m_block_container.begin()->free_nodes;
const size_type free_nodes_count_before = free_nodes.size();
m_totally_free_blocks -= static_cast<size_type>(free_nodes_count_before == m_real_num_node);
const size_type num_left = n-i;
const size_type num_elems = (num_left < free_nodes_count_before) ? num_left : free_nodes_count_before;
typedef typename free_nodes_t::iterator free_nodes_iterator;
if(num_left < free_nodes_count_before){
const free_nodes_iterator it_bbeg(free_nodes.before_begin());
free_nodes_iterator it_bend(it_bbeg);
for(size_type j = 0; j != num_elems; ++j){
++it_bend;
}
free_nodes_iterator it_end = it_bend; ++it_end;
free_nodes_iterator it_beg = it_bbeg; ++it_beg;
free_nodes.erase_after(it_bbeg, it_end, num_elems);
chain.incorporate_after(chain.last(), &*it_beg, &*it_bend, num_elems);
//chain.splice_after(chain.last(), free_nodes, it_bbeg, it_bend, num_elems);
BOOST_ASSERT(!free_nodes.empty());
}
else{
const free_nodes_iterator it_beg(free_nodes.begin()), it_bend(free_nodes.last());
free_nodes.clear();
chain.incorporate_after(chain.last(), &*it_beg, &*it_bend, num_elems);
block_container_traits_t::erase_first(m_block_container);
}
i += num_elems;
}
}
BOOST_CATCH(...){
this->deallocate_nodes(chain);
BOOST_RETHROW
}
BOOST_CATCH_END
this->priv_invariants();
}
//!Deallocates a linked list of nodes. Never throws
void deallocate_nodes(multiallocation_chain &nodes)
{
this->priv_invariants();
//To take advantage of node locality, wait until two
//nodes belong to different blocks. Only then reinsert
//the block of the first node in the block tree.
//Cache of the previous block
block_info_t *prev_block_info = 0;
//If block was empty before this call, it's not already
//inserted in the block tree.
bool prev_block_was_empty = false;
typedef typename free_nodes_t::iterator free_nodes_iterator;
{
const free_nodes_iterator itbb(nodes.before_begin()), ite(nodes.end());
free_nodes_iterator itf(nodes.begin()), itbf(itbb);
size_type splice_node_count = size_type(-1);
while(itf != ite){
void *pElem = container_detail::to_raw_pointer(container_detail::iterator_to_pointer(itf));
block_info_t &block_info = *this->priv_block_from_node(pElem);
BOOST_ASSERT(block_info.free_nodes.size() < m_real_num_node);
++splice_node_count;
//If block change is detected calculate the cached block position in the tree
if(&block_info != prev_block_info){
if(prev_block_info){ //Make sure we skip the initial "dummy" cache
free_nodes_iterator it(itbb); ++it;
nodes.erase_after(itbb, itf, splice_node_count);
prev_block_info->free_nodes.incorporate_after(prev_block_info->free_nodes.last(), &*it, &*itbf, splice_node_count);
this->priv_reinsert_block(*prev_block_info, prev_block_was_empty);
splice_node_count = 0;
}
//Update cache with new data
prev_block_was_empty = block_info.free_nodes.empty();
prev_block_info = &block_info;
}
itbf = itf;
++itf;
}
}
if(prev_block_info){
//The loop reinserts all blocks except the last one
const free_nodes_iterator itfirst(nodes.begin()), itlast(nodes.last());
const size_type splice_node_count = nodes.size();
nodes.clear();
prev_block_info->free_nodes.incorporate_after(prev_block_info->free_nodes.last(), &*itfirst, &*itlast, splice_node_count);
this->priv_reinsert_block(*prev_block_info, prev_block_was_empty);
this->priv_invariants();
this->priv_deallocate_free_blocks(m_max_free_blocks);
}
}
void deallocate_free_blocks()
{ this->priv_deallocate_free_blocks(0); }
size_type num_free_nodes()
{
typedef typename block_container_t::const_iterator citerator;
size_type count = 0;
citerator it (m_block_container.begin()), itend(m_block_container.end());
for(; it != itend; ++it){
count += it->free_nodes.size();
}
return count;
}
void swap(private_adaptive_node_pool_impl &other)
{
BOOST_ASSERT(m_max_free_blocks == other.m_max_free_blocks);
BOOST_ASSERT(m_real_node_size == other.m_real_node_size);
BOOST_ASSERT(m_real_block_alignment == other.m_real_block_alignment);
BOOST_ASSERT(m_real_num_node == other.m_real_num_node);
std::swap(mp_segment_mngr_base, other.mp_segment_mngr_base);
std::swap(m_totally_free_blocks, other.m_totally_free_blocks);
m_block_container.swap(other.m_block_container);
}
//Deprecated, use deallocate_free_blocks
void deallocate_free_chunks()
{ this->priv_deallocate_free_blocks(0); }
private:
void priv_deallocate_free_blocks(size_type max_free_blocks)
{ //Trampoline function to ease inlining
if(m_totally_free_blocks > max_free_blocks){
this->priv_deallocate_free_blocks_impl(max_free_blocks);
}
}
void priv_deallocate_free_blocks_impl(size_type max_free_blocks)
{
this->priv_invariants();
//Now check if we've reached the free nodes limit
//and check if we have free blocks. If so, deallocate as much
//as we can to stay below the limit
multiallocation_chain chain;
{
const const_block_iterator itend = m_block_container.cend();
const_block_iterator it = itend;
--it;
size_type totally_free_blocks = m_totally_free_blocks;
for( ; totally_free_blocks > max_free_blocks; --totally_free_blocks){
BOOST_ASSERT(it->free_nodes.size() == m_real_num_node);
void *addr = priv_first_subblock_from_block(const_cast<block_info_t*>(&*it));
--it;
block_container_traits_t::erase_last(m_block_container);
chain.push_front(void_pointer(addr));
}
BOOST_ASSERT((m_totally_free_blocks - max_free_blocks) == chain.size());
m_totally_free_blocks = max_free_blocks;
}
this->mp_segment_mngr_base->deallocate_many(chain);
}
void priv_reinsert_block(block_info_t &prev_block_info, const bool prev_block_was_empty)
{
//Cache the free nodes from the block
const size_type this_block_free_nodes = prev_block_info.free_nodes.size();
const bool is_full = this_block_free_nodes == m_real_num_node;
//Update free block count
m_totally_free_blocks += static_cast<size_type>(is_full);
if(prev_block_was_empty){
block_container_traits_t::insert_was_empty(m_block_container, prev_block_info, is_full);
}
else{
block_container_traits_t::reinsert_was_used(m_block_container, prev_block_info, is_full);
}
}
class block_destroyer;
friend class block_destroyer;
class block_destroyer
{
public:
block_destroyer(const this_type *impl, multiallocation_chain &chain)
: mp_impl(impl), m_chain(chain)
{}
void operator()(typename block_container_t::pointer to_deallocate)
{ return this->do_destroy(to_deallocate, IsAlignOnly()); }
private:
void do_destroy(typename block_container_t::pointer to_deallocate, AlignOnlyTrue)
{
BOOST_ASSERT(to_deallocate->free_nodes.size() == mp_impl->m_real_num_node);
m_chain.push_back(to_deallocate);
}
void do_destroy(typename block_container_t::pointer to_deallocate, AlignOnlyFalse)
{
BOOST_ASSERT(to_deallocate->free_nodes.size() == mp_impl->m_real_num_node);
BOOST_ASSERT(0 == to_deallocate->hdr_offset);
hdr_offset_holder *hdr_off_holder =
mp_impl->priv_first_subblock_from_block(container_detail::to_raw_pointer(to_deallocate));
m_chain.push_back(hdr_off_holder);
}
const this_type *mp_impl;
multiallocation_chain &m_chain;
};
//This macro will activate invariant checking. Slow, but helpful for debugging the code.
//#define BOOST_CONTAINER_ADAPTIVE_NODE_POOL_CHECK_INVARIANTS
void priv_invariants()
#ifdef BOOST_CONTAINER_ADAPTIVE_NODE_POOL_CHECK_INVARIANTS
#undef BOOST_CONTAINER_ADAPTIVE_NODE_POOL_CHECK_INVARIANTS
{
const const_block_iterator itend(m_block_container.end());
{ //We iterate through the block tree to free the memory
const_block_iterator it(m_block_container.begin());
if(it != itend){
for(++it; it != itend; ++it){
const_block_iterator prev(it);
--prev;
BOOST_ASSERT(*prev < *it);
(void)prev; (void)it;
}
}
}
{ //Check that the total free nodes are correct
const_block_iterator it(m_block_container.cbegin());
size_type total_free_nodes = 0;
for(; it != itend; ++it){
total_free_nodes += it->free_nodes.size();
}
BOOST_ASSERT(total_free_nodes >= m_totally_free_blocks*m_real_num_node);
}
{ //Check that the total totally free blocks are correct
BOOST_ASSERT(m_block_container.size() >= m_totally_free_blocks);
const_block_iterator it = m_block_container.cend();
size_type total_free_blocks = m_totally_free_blocks;
while(total_free_blocks--){
BOOST_ASSERT((--it)->free_nodes.size() == m_real_num_node);
}
}
if(!AlignOnly){
//Check that header offsets are correct
const_block_iterator it = m_block_container.begin();
for(; it != itend; ++it){
hdr_offset_holder *hdr_off_holder = this->priv_first_subblock_from_block(const_cast<block_info_t *>(&*it));
for(size_type i = 0, max = m_num_subblocks; i < max; ++i){
const size_type offset = reinterpret_cast<char*>(const_cast<block_info_t *>(&*it)) - reinterpret_cast<char*>(hdr_off_holder);
BOOST_ASSERT(hdr_off_holder->hdr_offset == offset);
BOOST_ASSERT(0 == ((size_type)hdr_off_holder & (m_real_block_alignment - 1)));
BOOST_ASSERT(0 == (hdr_off_holder->hdr_offset & (m_real_block_alignment - 1)));
hdr_off_holder = reinterpret_cast<hdr_offset_holder *>(reinterpret_cast<char*>(hdr_off_holder) + m_real_block_alignment);
}
}
}
}
#else
{} //empty
#endif
//!Deallocates all used memory. Never throws
void priv_clear()
{
#ifndef NDEBUG
block_iterator it = m_block_container.begin();
block_iterator itend = m_block_container.end();
size_type n_free_nodes = 0;
for(; it != itend; ++it){
//Check for memory leak
BOOST_ASSERT(it->free_nodes.size() == m_real_num_node);
++n_free_nodes;
}
BOOST_ASSERT(n_free_nodes == m_totally_free_blocks);
#endif
//Check for memory leaks
this->priv_invariants();
multiallocation_chain chain;
m_block_container.clear_and_dispose(block_destroyer(this, chain));
this->mp_segment_mngr_base->deallocate_many(chain);
m_totally_free_blocks = 0;
}
block_info_t *priv_block_from_node(void *node, AlignOnlyFalse) const
{
hdr_offset_holder *hdr_off_holder =
reinterpret_cast<hdr_offset_holder*>((std::size_t)node & size_type(~(m_real_block_alignment - 1)));
BOOST_ASSERT(0 == ((std::size_t)hdr_off_holder & (m_real_block_alignment - 1)));
BOOST_ASSERT(0 == (hdr_off_holder->hdr_offset & (m_real_block_alignment - 1)));
block_info_t *block = reinterpret_cast<block_info_t *>
(reinterpret_cast<char*>(hdr_off_holder) + hdr_off_holder->hdr_offset);
BOOST_ASSERT(block->hdr_offset == 0);
return block;
}
block_info_t *priv_block_from_node(void *node, AlignOnlyTrue) const
{
return (block_info_t *)((std::size_t)node & std::size_t(~(m_real_block_alignment - 1)));
}
block_info_t *priv_block_from_node(void *node) const
{ return this->priv_block_from_node(node, IsAlignOnly()); }
hdr_offset_holder *priv_first_subblock_from_block(block_info_t *block) const
{ return this->priv_first_subblock_from_block(block, IsAlignOnly()); }
hdr_offset_holder *priv_first_subblock_from_block(block_info_t *block, AlignOnlyFalse) const
{
hdr_offset_holder *const hdr_off_holder = reinterpret_cast<hdr_offset_holder*>
(reinterpret_cast<char*>(block) - (m_num_subblocks-1)*m_real_block_alignment);
BOOST_ASSERT(hdr_off_holder->hdr_offset == size_type(reinterpret_cast<char*>(block) - reinterpret_cast<char*>(hdr_off_holder)));
BOOST_ASSERT(0 == ((std::size_t)hdr_off_holder & (m_real_block_alignment - 1)));
BOOST_ASSERT(0 == (hdr_off_holder->hdr_offset & (m_real_block_alignment - 1)));
return hdr_off_holder;
}
hdr_offset_holder *priv_first_subblock_from_block(block_info_t *block, AlignOnlyTrue) const
{
return reinterpret_cast<hdr_offset_holder*>(block);
}
void priv_dispatch_block_chain_or_free
( multiallocation_chain &chain, block_info_t &c_info, size_type num_node
, char *mem_address, size_type total_elements, bool insert_block_if_free)
{
BOOST_ASSERT(chain.size() <= total_elements);
//First add all possible nodes to the chain
const size_type left = total_elements - chain.size();
const size_type max_chain = (num_node < left) ? num_node : left;
mem_address = static_cast<char *>(container_detail::to_raw_pointer
(chain.incorporate_after(chain.last(), void_pointer(mem_address), m_real_node_size, max_chain)));
//Now store remaining nodes in the free list
if(const size_type max_free = num_node - max_chain){
free_nodes_t & free_nodes = c_info.free_nodes;
free_nodes.incorporate_after(free_nodes.last(), void_pointer(mem_address), m_real_node_size, max_free);
if(insert_block_if_free){
m_block_container.push_front(c_info);
}
}
}
//!Allocates a several blocks of nodes. Can throw
void priv_append_from_new_blocks(size_type min_elements, multiallocation_chain &chain, AlignOnlyTrue)
{
BOOST_ASSERT(m_block_container.empty());
BOOST_ASSERT(min_elements > 0);
const size_type n = (min_elements - 1)/m_real_num_node + 1;
const size_type real_block_size = m_real_block_alignment - PayloadPerAllocation;
const size_type total_elements = chain.size() + min_elements;
for(size_type i = 0; i != n; ++i){
//We allocate a new NodeBlock and put it the last
//element of the tree
char *mem_address = static_cast<char*>
(mp_segment_mngr_base->allocate_aligned(real_block_size, m_real_block_alignment));
if(!mem_address){
//In case of error, free memory deallocating all nodes (the new ones allocated
//in this function plus previously stored nodes in chain).
this->deallocate_nodes(chain);
throw_bad_alloc();
}
block_info_t &c_info = *new(mem_address)block_info_t();
mem_address += HdrSize;
if(i != (n-1)){
chain.incorporate_after(chain.last(), void_pointer(mem_address), m_real_node_size, m_real_num_node);
}
else{
this->priv_dispatch_block_chain_or_free(chain, c_info, m_real_num_node, mem_address, total_elements, true);
}
}
}
void priv_append_from_new_blocks(size_type min_elements, multiallocation_chain &chain, AlignOnlyFalse)
{
BOOST_ASSERT(m_block_container.empty());
BOOST_ASSERT(min_elements > 0);
const size_type n = (min_elements - 1)/m_real_num_node + 1;
const size_type real_block_size = m_real_block_alignment*m_num_subblocks - PayloadPerAllocation;
const size_type elements_per_subblock = (m_real_block_alignment - HdrOffsetSize)/m_real_node_size;
const size_type hdr_subblock_elements = (m_real_block_alignment - HdrSize - PayloadPerAllocation)/m_real_node_size;
const size_type total_elements = chain.size() + min_elements;
for(size_type i = 0; i != n; ++i){
//We allocate a new NodeBlock and put it the last
//element of the tree
char *mem_address = static_cast<char*>
(mp_segment_mngr_base->allocate_aligned(real_block_size, m_real_block_alignment));
if(!mem_address){
//In case of error, free memory deallocating all nodes (the new ones allocated
//in this function plus previously stored nodes in chain).
this->deallocate_nodes(chain);
throw_bad_alloc();
}
//First initialize header information on the last subblock
char *hdr_addr = mem_address + m_real_block_alignment*(m_num_subblocks-1);
block_info_t &c_info = *new(hdr_addr)block_info_t();
//Some structural checks
BOOST_ASSERT(static_cast<void*>(&static_cast<hdr_offset_holder&>(c_info).hdr_offset) ==
static_cast<void*>(&c_info)); (void)c_info;
if(i != (n-1)){
for( size_type subblock = 0, maxsubblock = m_num_subblocks - 1
; subblock < maxsubblock
; ++subblock, mem_address += m_real_block_alignment){
//Initialize header offset mark
new(mem_address) hdr_offset_holder(size_type(hdr_addr - mem_address));
chain.incorporate_after
(chain.last(), void_pointer(mem_address + HdrOffsetSize), m_real_node_size, elements_per_subblock);
}
chain.incorporate_after(chain.last(), void_pointer(hdr_addr + HdrSize), m_real_node_size, hdr_subblock_elements);
}
else{
for( size_type subblock = 0, maxsubblock = m_num_subblocks - 1
; subblock < maxsubblock
; ++subblock, mem_address += m_real_block_alignment){
//Initialize header offset mark
new(mem_address) hdr_offset_holder(size_type(hdr_addr - mem_address));
this->priv_dispatch_block_chain_or_free
(chain, c_info, elements_per_subblock, mem_address + HdrOffsetSize, total_elements, false);
}
this->priv_dispatch_block_chain_or_free
(chain, c_info, hdr_subblock_elements, hdr_addr + HdrSize, total_elements, true);
}
}
}
private:
typedef typename boost::intrusive::pointer_traits
<void_pointer>::template rebind_pointer<segment_manager_base_type>::type segment_mngr_base_ptr_t;
const size_type m_max_free_blocks;
const size_type m_real_node_size;
//Round the size to a power of two value.
//This is the total memory size (including payload) that we want to
//allocate from the general-purpose allocator
const size_type m_real_block_alignment;
size_type m_num_subblocks;
//This is the real number of nodes per block
//const
size_type m_real_num_node;
segment_mngr_base_ptr_t mp_segment_mngr_base; //Segment manager
block_container_t m_block_container; //Intrusive block list
size_type m_totally_free_blocks; //Free blocks
};
} //namespace container_detail {
} //namespace container {
} //namespace boost {
#include <boost/container/detail/config_end.hpp>
#endif //#ifndef BOOST_CONTAINER_DETAIL_ADAPTIVE_NODE_POOL_IMPL_HPP

View file

@ -0,0 +1,477 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2008-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_ADVANCED_INSERT_INT_HPP
#define BOOST_CONTAINER_ADVANCED_INSERT_INT_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/allocator_traits.hpp>
#include <boost/container/detail/destroyers.hpp>
#include <boost/aligned_storage.hpp>
#include <boost/move/utility_core.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/utilities.hpp>
#include <boost/container/detail/type_traits.hpp>
#include <boost/container/detail/iterators.hpp>
#include <iterator> //std::iterator_traits
#include <boost/assert.hpp>
#include <boost/core/no_exceptions_support.hpp>
namespace boost { namespace container { namespace container_detail {
template<class A, class FwdIt, class Iterator>
struct move_insert_range_proxy
{
typedef typename allocator_traits<A>::size_type size_type;
typedef typename allocator_traits<A>::value_type value_type;
explicit move_insert_range_proxy(FwdIt first)
: first_(first)
{}
void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n)
{
this->first_ = ::boost::container::uninitialized_move_alloc_n_source
(a, this->first_, n, p);
}
void copy_n_and_update(A &, Iterator p, size_type n)
{
this->first_ = ::boost::container::move_n_source(this->first_, n, p);
}
FwdIt first_;
};
template<class A, class FwdIt, class Iterator>
struct insert_range_proxy
{
typedef typename allocator_traits<A>::size_type size_type;
typedef typename allocator_traits<A>::value_type value_type;
explicit insert_range_proxy(FwdIt first)
: first_(first)
{}
void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n)
{
this->first_ = ::boost::container::uninitialized_copy_alloc_n_source(a, this->first_, n, p);
}
void copy_n_and_update(A &, Iterator p, size_type n)
{
this->first_ = ::boost::container::copy_n_source(this->first_, n, p);
}
FwdIt first_;
};
template<class A, class Iterator>
struct insert_n_copies_proxy
{
typedef typename allocator_traits<A>::size_type size_type;
typedef typename allocator_traits<A>::value_type value_type;
explicit insert_n_copies_proxy(const value_type &v)
: v_(v)
{}
void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n) const
{ boost::container::uninitialized_fill_alloc_n(a, v_, n, p); }
void copy_n_and_update(A &, Iterator p, size_type n) const
{
for (; 0 < n; --n, ++p){
*p = v_;
}
}
const value_type &v_;
};
template<class A, class Iterator>
struct insert_value_initialized_n_proxy
{
typedef ::boost::container::allocator_traits<A> alloc_traits;
typedef typename allocator_traits<A>::size_type size_type;
typedef typename allocator_traits<A>::value_type value_type;
void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n) const
{ boost::container::uninitialized_value_init_alloc_n(a, n, p); }
void copy_n_and_update(A &, Iterator, size_type) const
{ BOOST_ASSERT(false); }
};
template<class A, class Iterator>
struct insert_default_initialized_n_proxy
{
typedef ::boost::container::allocator_traits<A> alloc_traits;
typedef typename allocator_traits<A>::size_type size_type;
typedef typename allocator_traits<A>::value_type value_type;
void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n) const
{ boost::container::uninitialized_default_init_alloc_n(a, n, p); }
void copy_n_and_update(A &, Iterator, size_type) const
{ BOOST_ASSERT(false); }
};
template<class A, class Iterator>
struct insert_copy_proxy
{
typedef boost::container::allocator_traits<A> alloc_traits;
typedef typename alloc_traits::size_type size_type;
typedef typename alloc_traits::value_type value_type;
explicit insert_copy_proxy(const value_type &v)
: v_(v)
{}
void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n) const
{
BOOST_ASSERT(n == 1); (void)n;
alloc_traits::construct( a, iterator_to_raw_pointer(p), v_);
}
void copy_n_and_update(A &, Iterator p, size_type n) const
{
BOOST_ASSERT(n == 1); (void)n;
*p =v_;
}
const value_type &v_;
};
template<class A, class Iterator>
struct insert_move_proxy
{
typedef boost::container::allocator_traits<A> alloc_traits;
typedef typename alloc_traits::size_type size_type;
typedef typename alloc_traits::value_type value_type;
explicit insert_move_proxy(value_type &v)
: v_(v)
{}
void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n) const
{
BOOST_ASSERT(n == 1); (void)n;
alloc_traits::construct( a, iterator_to_raw_pointer(p), ::boost::move(v_) );
}
void copy_n_and_update(A &, Iterator p, size_type n) const
{
BOOST_ASSERT(n == 1); (void)n;
*p = ::boost::move(v_);
}
value_type &v_;
};
template<class It, class A>
insert_move_proxy<A, It> get_insert_value_proxy(BOOST_RV_REF(typename std::iterator_traits<It>::value_type) v)
{
return insert_move_proxy<A, It>(v);
}
template<class It, class A>
insert_copy_proxy<A, It> get_insert_value_proxy(const typename std::iterator_traits<It>::value_type &v)
{
return insert_copy_proxy<A, It>(v);
}
}}} //namespace boost { namespace container { namespace container_detail {
#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
#include <boost/container/detail/variadic_templates_tools.hpp>
#include <boost/move/utility_core.hpp>
#include <typeinfo>
//#include <iostream> //For debugging purposes
namespace boost {
namespace container {
namespace container_detail {
template<class A, class Iterator, class ...Args>
struct insert_non_movable_emplace_proxy
{
typedef boost::container::allocator_traits<A> alloc_traits;
typedef typename alloc_traits::size_type size_type;
typedef typename alloc_traits::value_type value_type;
typedef typename build_number_seq<sizeof...(Args)>::type index_tuple_t;
explicit insert_non_movable_emplace_proxy(Args&&... args)
: args_(args...)
{}
void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n)
{ this->priv_uninitialized_copy_some_and_update(a, index_tuple_t(), p, n); }
private:
template<int ...IdxPack>
void priv_uninitialized_copy_some_and_update(A &a, const index_tuple<IdxPack...>&, Iterator p, size_type n)
{
BOOST_ASSERT(n == 1); (void)n;
alloc_traits::construct( a, iterator_to_raw_pointer(p), ::boost::forward<Args>(get<IdxPack>(this->args_))... );
}
protected:
tuple<Args&...> args_;
};
template<class A, class Iterator, class ...Args>
struct insert_emplace_proxy
: public insert_non_movable_emplace_proxy<A, Iterator, Args...>
{
typedef insert_non_movable_emplace_proxy<A, Iterator, Args...> base_t;
typedef boost::container::allocator_traits<A> alloc_traits;
typedef typename base_t::value_type value_type;
typedef typename base_t::size_type size_type;
typedef typename base_t::index_tuple_t index_tuple_t;
explicit insert_emplace_proxy(Args&&... args)
: base_t(::boost::forward<Args>(args)...)
{}
void copy_n_and_update(A &a, Iterator p, size_type n)
{ this->priv_copy_some_and_update(a, index_tuple_t(), p, n); }
private:
template<int ...IdxPack>
void priv_copy_some_and_update(A &a, const index_tuple<IdxPack...>&, Iterator p, size_type n)
{
BOOST_ASSERT(n ==1); (void)n;
aligned_storage<sizeof(value_type), alignment_of<value_type>::value> v;
value_type *vp = static_cast<value_type *>(static_cast<void *>(&v));
alloc_traits::construct(a, vp,
::boost::forward<Args>(get<IdxPack>(this->args_))...);
BOOST_TRY{
*p = ::boost::move(*vp);
}
BOOST_CATCH(...){
alloc_traits::destroy(a, vp);
BOOST_RETHROW
}
BOOST_CATCH_END
alloc_traits::destroy(a, vp);
}
};
//Specializations to avoid an unneeded temporary when emplacing from a single argument o type value_type
template<class A, class Iterator>
struct insert_emplace_proxy<A, Iterator, typename boost::container::allocator_traits<A>::value_type>
: public insert_move_proxy<A, Iterator>
{
explicit insert_emplace_proxy(typename boost::container::allocator_traits<A>::value_type &&v)
: insert_move_proxy<A, Iterator>(v)
{}
};
//We use "add_const" here as adding "const" only confuses MSVC12(and maybe later) provoking
//compiler error C2752 (“more than one partial specialization matches”).
//Any problem is solvable with an extra layer of indirection? ;-)
template<class A, class Iterator>
struct insert_emplace_proxy<A, Iterator
, typename boost::container::container_detail::add_const<typename boost::container::allocator_traits<A>::value_type>::type
>
: public insert_copy_proxy<A, Iterator>
{
explicit insert_emplace_proxy(const typename boost::container::allocator_traits<A>::value_type &v)
: insert_copy_proxy<A, Iterator>(v)
{}
};
template<class A, class Iterator>
struct insert_emplace_proxy<A, Iterator, typename boost::container::allocator_traits<A>::value_type &>
: public insert_copy_proxy<A, Iterator>
{
explicit insert_emplace_proxy(const typename boost::container::allocator_traits<A>::value_type &v)
: insert_copy_proxy<A, Iterator>(v)
{}
};
template<class A, class Iterator>
struct insert_emplace_proxy<A, Iterator
, typename boost::container::container_detail::add_const<typename boost::container::allocator_traits<A>::value_type>::type &
>
: public insert_copy_proxy<A, Iterator>
{
explicit insert_emplace_proxy(const typename boost::container::allocator_traits<A>::value_type &v)
: insert_copy_proxy<A, Iterator>(v)
{}
};
}}} //namespace boost { namespace container { namespace container_detail {
#else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
#include <boost/container/detail/preprocessor.hpp>
#include <boost/container/detail/value_init.hpp>
namespace boost {
namespace container {
namespace container_detail {
#define BOOST_PP_LOCAL_MACRO(N) \
template<class A, class Iterator BOOST_PP_ENUM_TRAILING_PARAMS(N, class P) > \
struct BOOST_PP_CAT(insert_non_movable_emplace_proxy_arg, N) \
{ \
typedef boost::container::allocator_traits<A> alloc_traits; \
typedef typename alloc_traits::size_type size_type; \
typedef typename alloc_traits::value_type value_type; \
\
explicit BOOST_PP_CAT(insert_non_movable_emplace_proxy_arg, N) \
( BOOST_PP_ENUM(N, BOOST_CONTAINER_PP_PARAM_LIST, _) ) \
BOOST_PP_EXPR_IF(N, :) BOOST_PP_ENUM(N, BOOST_CONTAINER_PP_PARAM_INIT, _) \
{} \
\
void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n) \
{ \
BOOST_ASSERT(n == 1); (void)n; \
alloc_traits::construct \
( a, iterator_to_raw_pointer(p) \
BOOST_PP_ENUM_TRAILING(N, BOOST_CONTAINER_PP_MEMBER_FORWARD, _) \
); \
} \
\
void copy_n_and_update(A &, Iterator, size_type) \
{ BOOST_ASSERT(false); } \
\
protected: \
BOOST_PP_REPEAT(N, BOOST_CONTAINER_PP_PARAM_DEFINE, _) \
}; \
\
template<class A, class Iterator BOOST_PP_ENUM_TRAILING_PARAMS(N, class P) > \
struct BOOST_PP_CAT(insert_emplace_proxy_arg, N) \
: BOOST_PP_CAT(insert_non_movable_emplace_proxy_arg, N) \
< A, Iterator BOOST_PP_ENUM_TRAILING_PARAMS(N, P) > \
{ \
typedef BOOST_PP_CAT(insert_non_movable_emplace_proxy_arg, N) \
<A, Iterator BOOST_PP_ENUM_TRAILING_PARAMS(N, P) > base_t; \
typedef typename base_t::value_type value_type; \
typedef typename base_t::size_type size_type; \
typedef boost::container::allocator_traits<A> alloc_traits; \
\
explicit BOOST_PP_CAT(insert_emplace_proxy_arg, N) \
( BOOST_PP_ENUM(N, BOOST_CONTAINER_PP_PARAM_LIST, _) ) \
: base_t(BOOST_PP_ENUM(N, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ) \
{} \
\
void copy_n_and_update(A &a, Iterator p, size_type n) \
{ \
BOOST_ASSERT(n == 1); (void)n; \
aligned_storage<sizeof(value_type), alignment_of<value_type>::value> v; \
value_type *vp = static_cast<value_type *>(static_cast<void *>(&v)); \
alloc_traits::construct(a, vp \
BOOST_PP_ENUM_TRAILING(N, BOOST_CONTAINER_PP_MEMBER_FORWARD, _)); \
BOOST_TRY{ \
*p = ::boost::move(*vp); \
} \
BOOST_CATCH(...){ \
alloc_traits::destroy(a, vp); \
BOOST_RETHROW \
} \
BOOST_CATCH_END \
alloc_traits::destroy(a, vp); \
} \
}; \
//!
#define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
#include BOOST_PP_LOCAL_ITERATE()
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
//Specializations to avoid an unneeded temporary when emplacing from a single argument o type value_type
template<class A, class Iterator>
struct insert_emplace_proxy_arg1<A, Iterator, ::boost::rv<typename boost::container::allocator_traits<A>::value_type> >
: public insert_move_proxy<A, Iterator>
{
explicit insert_emplace_proxy_arg1(typename boost::container::allocator_traits<A>::value_type &v)
: insert_move_proxy<A, Iterator>(v)
{}
};
template<class A, class Iterator>
struct insert_emplace_proxy_arg1<A, Iterator, typename boost::container::allocator_traits<A>::value_type>
: public insert_copy_proxy<A, Iterator>
{
explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<A>::value_type &v)
: insert_copy_proxy<A, Iterator>(v)
{}
};
#else //e.g. MSVC10 & MSVC11
//Specializations to avoid an unneeded temporary when emplacing from a single argument o type value_type
template<class A, class Iterator>
struct insert_emplace_proxy_arg1<A, Iterator, typename boost::container::allocator_traits<A>::value_type>
: public insert_move_proxy<A, Iterator>
{
explicit insert_emplace_proxy_arg1(typename boost::container::allocator_traits<A>::value_type &&v)
: insert_move_proxy<A, Iterator>(v)
{}
};
//We use "add_const" here as adding "const" only confuses MSVC10&11 provoking
//compiler error C2752 (“more than one partial specialization matches”).
//Any problem is solvable with an extra layer of indirection? ;-)
template<class A, class Iterator>
struct insert_emplace_proxy_arg1<A, Iterator
, typename boost::container::container_detail::add_const<typename boost::container::allocator_traits<A>::value_type>::type
>
: public insert_copy_proxy<A, Iterator>
{
explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<A>::value_type &v)
: insert_copy_proxy<A, Iterator>(v)
{}
};
template<class A, class Iterator>
struct insert_emplace_proxy_arg1<A, Iterator, typename boost::container::allocator_traits<A>::value_type &>
: public insert_copy_proxy<A, Iterator>
{
explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<A>::value_type &v)
: insert_copy_proxy<A, Iterator>(v)
{}
};
template<class A, class Iterator>
struct insert_emplace_proxy_arg1<A, Iterator
, typename boost::container::container_detail::add_const<typename boost::container::allocator_traits<A>::value_type>::type &
>
: public insert_copy_proxy<A, Iterator>
{
explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<A>::value_type &v)
: insert_copy_proxy<A, Iterator>(v)
{}
};
#endif
}}} //namespace boost { namespace container { namespace container_detail {
#endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
#include <boost/container/detail/config_end.hpp>
#endif //#ifndef BOOST_CONTAINER_ADVANCED_INSERT_INT_HPP

View file

@ -0,0 +1,62 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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_ALGORITHMS_HPP
#define BOOST_CONTAINER_DETAIL_ALGORITHMS_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/allocator_traits.hpp>
#include <boost/container/detail/iterators.hpp>
namespace boost {
namespace container {
template<class A, class T, class InpIt>
inline void construct_in_place(A &a, T* dest, InpIt source)
{ boost::container::allocator_traits<A>::construct(a, dest, *source); }
template<class A, class T, class U, class D>
inline void construct_in_place(A &a, T *dest, value_init_construct_iterator<U, D>)
{
boost::container::allocator_traits<A>::construct(a, dest);
}
template <class T, class Difference>
class default_init_construct_iterator;
template<class A, class T, class U, class D>
inline void construct_in_place(A &a, T *dest, default_init_construct_iterator<U, D>)
{
boost::container::allocator_traits<A>::construct(a, dest, default_init);
}
template <class T, class EmplaceFunctor, class Difference>
class emplace_iterator;
template<class A, class T, class U, class EF, class D>
inline void construct_in_place(A &a, T *dest, emplace_iterator<U, EF, D> ei)
{
ei.construct_in_place(a, dest);
}
} //namespace container {
} //namespace boost {
#include <boost/container/detail/config_end.hpp>
#endif //#ifndef BOOST_CONTAINER_DETAIL_ALGORITHMS_HPP

View file

@ -0,0 +1,326 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_ALLOC_LIB_EXT_H
#define BOOST_CONTAINER_ALLOC_LIB_EXT_H
#include <stddef.h>
#ifdef _MSC_VER
#pragma warning (push)
#pragma warning (disable : 4127)
/*
we need to import/export our code only if the user has specifically
asked for it by defining either BOOST_ALL_DYN_LINK if they want all boost
libraries to be dynamically linked, or BOOST_CONTAINER_DYN_LINK
if they want just this one to be dynamically liked:
*/
#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_CONTAINER_DYN_LINK)
/* export if this is our own source, otherwise import: */
#ifdef BOOST_CONTAINER_SOURCE
# define BOOST_CONTAINER_DECL __declspec(dllexport)
#else
# define BOOST_CONTAINER_DECL __declspec(dllimport)
#endif /* BOOST_CONTAINER_SOURCE */
#endif /* DYN_LINK */
#endif /* _MSC_VER */
/* if BOOST_CONTAINER_DECL isn't defined yet define it now: */
#ifndef BOOST_CONTAINER_DECL
#define BOOST_CONTAINER_DECL
#endif
#ifdef __cplusplus
extern "C" {
#endif
/*!An forward iterator to traverse the elements of a memory chain container.*/
typedef struct multialloc_node_impl
{
struct multialloc_node_impl *next_node_ptr;
} boost_cont_memchain_node;
/*!An forward iterator to traverse the elements of a memory chain container.*/
typedef struct multialloc_it_impl
{
boost_cont_memchain_node *node_ptr;
} boost_cont_memchain_it;
/*!Memory chain: A container holding memory portions allocated by boost_cont_multialloc_nodes
and boost_cont_multialloc_arrays functions.*/
typedef struct boost_cont_memchain_impl
{
size_t num_mem;
boost_cont_memchain_node root_node;
boost_cont_memchain_node *last_node_ptr;
} boost_cont_memchain;
/*!Advances the iterator one position so that it points to the next element in the memory chain*/
#define BOOST_CONTAINER_MEMIT_NEXT(IT) (IT.node_ptr = IT.node_ptr->next_node_ptr)
/*!Returns the address of the memory chain currently pointed by the iterator*/
#define BOOST_CONTAINER_MEMIT_ADDR(IT) ((void*)IT.node_ptr)
/*!Initializer for an iterator pointing to the position before the first element*/
#define BOOST_CONTAINER_MEMCHAIN_BEFORE_BEGIN_IT(PMEMCHAIN) { &((PMEMCHAIN)->root_node) }
/*!Initializer for an iterator pointing to the first element*/
#define BOOST_CONTAINER_MEMCHAIN_BEGIN_IT(PMEMCHAIN) {(PMEMCHAIN)->root_node.next_node_ptr }
/*!Initializer for an iterator pointing to the last element*/
#define BOOST_CONTAINER_MEMCHAIN_LAST_IT(PMEMCHAIN) {(PMEMCHAIN)->last_node_ptr }
/*!Initializer for an iterator pointing to one past the last element (end iterator)*/
#define BOOST_CONTAINER_MEMCHAIN_END_IT(PMEMCHAIN) {(boost_cont_memchain_node *)0 }
/*!True if IT is the end iterator, false otherwise*/
#define BOOST_CONTAINER_MEMCHAIN_IS_END_IT(PMEMCHAIN, IT) (!(IT).node_ptr)
/*!The address of the first memory portion hold by the memory chain*/
#define BOOST_CONTAINER_MEMCHAIN_FIRSTMEM(PMEMCHAIN)((void*)((PMEMCHAIN)->root_node.next_node_ptr))
/*!The address of the last memory portion hold by the memory chain*/
#define BOOST_CONTAINER_MEMCHAIN_LASTMEM(PMEMCHAIN) ((void*)((PMEMCHAIN)->last_node_ptr))
/*!The number of memory portions hold by the memory chain*/
#define BOOST_CONTAINER_MEMCHAIN_SIZE(PMEMCHAIN) ((PMEMCHAIN)->num_mem)
/*!Initializes the memory chain from the first memory portion, the last memory
portion and number of portions obtained from another memory chain*/
#define BOOST_CONTAINER_MEMCHAIN_INIT_FROM(PMEMCHAIN, FIRST, LAST, NUM)\
(PMEMCHAIN)->last_node_ptr = (boost_cont_memchain_node *)(LAST), \
(PMEMCHAIN)->root_node.next_node_ptr = (boost_cont_memchain_node *)(FIRST), \
(PMEMCHAIN)->num_mem = (NUM);\
/**/
/*!Default initializes a memory chain. Postconditions: begin iterator is end iterator,
the number of portions is zero.*/
#define BOOST_CONTAINER_MEMCHAIN_INIT(PMEMCHAIN)\
((PMEMCHAIN)->root_node.next_node_ptr = 0, (PMEMCHAIN)->last_node_ptr = &((PMEMCHAIN)->root_node), (PMEMCHAIN)->num_mem = 0)\
/**/
/*!True if the memory chain is empty (holds no memory portions*/
#define BOOST_CONTAINER_MEMCHAIN_EMPTY(PMEMCHAIN)\
((PMEMCHAIN)->num_mem == 0)\
/**/
/*!Inserts a new memory portions in the front of the chain*/
#define BOOST_CONTAINER_MEMCHAIN_PUSH_BACK(PMEMCHAIN, MEM)\
do{\
boost_cont_memchain *____chain____ = (PMEMCHAIN);\
boost_cont_memchain_node *____tmp_mem____ = (boost_cont_memchain_node *)(MEM);\
____chain____->last_node_ptr->next_node_ptr = ____tmp_mem____;\
____tmp_mem____->next_node_ptr = 0;\
____chain____->last_node_ptr = ____tmp_mem____;\
++____chain____->num_mem;\
}while(0)\
/**/
/*!Inserts a new memory portions in the back of the chain*/
#define BOOST_CONTAINER_MEMCHAIN_PUSH_FRONT(PMEMCHAIN, MEM)\
do{\
boost_cont_memchain *____chain____ = (PMEMCHAIN);\
boost_cont_memchain_node *____tmp_mem____ = (boost_cont_memchain_node *)(MEM);\
boost_cont_memchain *____root____ = &((PMEMCHAIN)->root_node);\
if(!____chain____->root_node.next_node_ptr){\
____chain____->last_node_ptr = ____tmp_mem____;\
}\
boost_cont_memchain_node *____old_first____ = ____root____->next_node_ptr;\
____tmp_mem____->next_node_ptr = ____old_first____;\
____root____->next_node_ptr = ____tmp_mem____;\
++____chain____->num_mem;\
}while(0)\
/**/
/*!Erases the memory portion after the portion pointed by BEFORE_IT from the memory chain*/
/*!Precondition: BEFORE_IT must be a valid iterator of the memory chain and it can't be the end iterator*/
#define BOOST_CONTAINER_MEMCHAIN_ERASE_AFTER(PMEMCHAIN, BEFORE_IT)\
do{\
boost_cont_memchain *____chain____ = (PMEMCHAIN);\
boost_cont_memchain_node *____prev_node____ = (BEFORE_IT).node_ptr;\
boost_cont_memchain_node *____erase_node____ = ____prev_node____->next_node_ptr;\
if(____chain____->last_node_ptr == ____erase_node____){\
____chain____->last_node_ptr = &____chain____->root_node;\
}\
____prev_node____->next_node_ptr = ____erase_node____->next_node_ptr;\
--____chain____->num_mem;\
}while(0)\
/**/
/*!Erases the first portion from the memory chain.
Precondition: the memory chain must not be empty*/
#define BOOST_CONTAINER_MEMCHAIN_POP_FRONT(PMEMCHAIN)\
do{\
boost_cont_memchain *____chain____ = (PMEMCHAIN);\
boost_cont_memchain_node *____prev_node____ = &____chain____->root_node;\
boost_cont_memchain_node *____erase_node____ = ____prev_node____->next_node_ptr;\
if(____chain____->last_node_ptr == ____erase_node____){\
____chain____->last_node_ptr = &____chain____->root_node;\
}\
____prev_node____->next_node_ptr = ____erase_node____->next_node_ptr;\
--____chain____->num_mem;\
}while(0)\
/**/
/*!Joins two memory chains inserting the portions of the second chain at the back of the first chain*/
/*
#define BOOST_CONTAINER_MEMCHAIN_SPLICE_BACK(PMEMCHAIN, PMEMCHAIN2)\
do{\
boost_cont_memchain *____chain____ = (PMEMCHAIN);\
boost_cont_memchain *____chain2____ = (PMEMCHAIN2);\
if(!____chain2____->root_node.next_node_ptr){\
break;\
}\
else if(!____chain____->first_mem){\
____chain____->first_mem = ____chain2____->first_mem;\
____chain____->last_node_ptr = ____chain2____->last_node_ptr;\
____chain____->num_mem = ____chain2____->num_mem;\
BOOST_CONTAINER_MEMCHAIN_INIT(*____chain2____);\
}\
else{\
____chain____->last_node_ptr->next_node_ptr = ____chain2____->first_mem;\
____chain____->last_node_ptr = ____chain2____->last_node_ptr;\
____chain____->num_mem += ____chain2____->num_mem;\
}\
}while(0)\*/
/**/
/*!Joins two memory chains inserting the portions of the second chain at the back of the first chain*/
#define BOOST_CONTAINER_MEMCHAIN_INCORPORATE_AFTER(PMEMCHAIN, BEFORE_IT, FIRST, BEFORELAST, NUM)\
do{\
boost_cont_memchain *____chain____ = (PMEMCHAIN);\
boost_cont_memchain_node *____pnode____ = (BEFORE_IT).node_ptr;\
boost_cont_memchain_node *____next____ = ____pnode____->next_node_ptr;\
boost_cont_memchain_node *____first____ = (boost_cont_memchain_node *)(FIRST);\
boost_cont_memchain_node *____blast____ = (boost_cont_memchain_node *)(BEFORELAST);\
size_t ____num____ = (NUM);\
if(!____num____){\
break;\
}\
if(____pnode____ == ____chain____->last_node_ptr){\
____chain____->last_node_ptr = ____blast____;\
}\
____pnode____->next_node_ptr = ____first____;\
____blast____->next_node_ptr = ____next____;\
____chain____->num_mem += ____num____;\
}while(0)\
/**/
BOOST_CONTAINER_DECL size_t boost_cont_size(const void *p);
BOOST_CONTAINER_DECL void* boost_cont_malloc(size_t bytes);
BOOST_CONTAINER_DECL void boost_cont_free(void* mem);
BOOST_CONTAINER_DECL void* boost_cont_memalign(size_t bytes, size_t alignment);
/*!Indicates the all elements allocated by boost_cont_multialloc_nodes or boost_cont_multialloc_arrays
must be contiguous.*/
#define DL_MULTIALLOC_ALL_CONTIGUOUS ((size_t)(-1))
/*!Indicates the number of contiguous elements allocated by boost_cont_multialloc_nodes or boost_cont_multialloc_arrays
should be selected by those functions.*/
#define DL_MULTIALLOC_DEFAULT_CONTIGUOUS ((size_t)(0))
BOOST_CONTAINER_DECL int boost_cont_multialloc_nodes
(size_t n_elements, size_t elem_size, size_t contiguous_elements, boost_cont_memchain *pchain);
BOOST_CONTAINER_DECL int boost_cont_multialloc_arrays
(size_t n_elements, const size_t *sizes, size_t sizeof_element, size_t contiguous_elements, boost_cont_memchain *pchain);
BOOST_CONTAINER_DECL void boost_cont_multidealloc(boost_cont_memchain *pchain);
BOOST_CONTAINER_DECL size_t boost_cont_footprint();
BOOST_CONTAINER_DECL size_t boost_cont_allocated_memory();
BOOST_CONTAINER_DECL size_t boost_cont_chunksize(const void *p);
BOOST_CONTAINER_DECL int boost_cont_all_deallocated();
typedef struct boost_cont_malloc_stats_impl
{
size_t max_system_bytes;
size_t system_bytes;
size_t in_use_bytes;
} boost_cont_malloc_stats_t;
BOOST_CONTAINER_DECL boost_cont_malloc_stats_t boost_cont_malloc_stats();
BOOST_CONTAINER_DECL size_t boost_cont_in_use_memory();
BOOST_CONTAINER_DECL int boost_cont_trim(size_t pad);
BOOST_CONTAINER_DECL int boost_cont_mallopt
(int parameter_number, int parameter_value);
BOOST_CONTAINER_DECL int boost_cont_grow
(void* oldmem, size_t minbytes, size_t maxbytes, size_t *received);
BOOST_CONTAINER_DECL int boost_cont_shrink
(void* oldmem, size_t minbytes, size_t maxbytes, size_t *received, int do_commit);
BOOST_CONTAINER_DECL void* boost_cont_alloc
(size_t minbytes, size_t preferred_bytes, size_t *received_bytes);
BOOST_CONTAINER_DECL int boost_cont_malloc_check();
typedef unsigned int allocation_type;
enum
{
// constants for allocation commands
BOOST_CONTAINER_ALLOCATE_NEW = 0X01,
BOOST_CONTAINER_EXPAND_FWD = 0X02,
BOOST_CONTAINER_EXPAND_BWD = 0X04,
BOOST_CONTAINER_SHRINK_IN_PLACE = 0X08,
BOOST_CONTAINER_NOTHROW_ALLOCATION = 0X10,
// BOOST_CONTAINER_ZERO_MEMORY = 0X20,
BOOST_CONTAINER_TRY_SHRINK_IN_PLACE = 0X40,
BOOST_CONTAINER_EXPAND_BOTH = BOOST_CONTAINER_EXPAND_FWD | BOOST_CONTAINER_EXPAND_BWD,
BOOST_CONTAINER_EXPAND_OR_NEW = BOOST_CONTAINER_ALLOCATE_NEW | BOOST_CONTAINER_EXPAND_BOTH
};
//#define BOOST_CONTAINERDLMALLOC__FOOTERS
#ifndef BOOST_CONTAINERDLMALLOC__FOOTERS
enum { BOOST_CONTAINER_ALLOCATION_PAYLOAD = sizeof(size_t) };
#else
enum { BOOST_CONTAINER_ALLOCATION_PAYLOAD = sizeof(size_t)*2 };
#endif
typedef struct boost_cont_command_ret_impl
{
void *first;
int second;
}boost_cont_command_ret_t;
BOOST_CONTAINER_DECL boost_cont_command_ret_t boost_cont_allocation_command
( allocation_type command
, size_t sizeof_object
, size_t limit_objects
, size_t preferred_objects
, size_t *received_objects
, void *reuse_ptr
);
BOOST_CONTAINER_DECL int boost_cont_mallopt(int param_number, int value);
#ifdef __cplusplus
} //extern "C" {
#endif
#ifdef _MSC_VER
#pragma warning (pop)
#endif
#endif //#define BOOST_CONTAINERDLMALLOC__EXT_H

View file

@ -0,0 +1,20 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/container/detail/auto_link.hpp>
#include <boost/container/detail/alloc_lib.h>
#endif //#ifndef BOOST_CONTAINER_DETAIL_BOOST_CONT_EXT_AUTO_LINK_HPP

View file

@ -0,0 +1,54 @@
///////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_ALLOCATION_TYPE_HPP
#define BOOST_CONTAINER_ALLOCATION_TYPE_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
namespace boost {
namespace container {
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
enum allocation_type_v
{
// constants for allocation commands
allocate_new_v = 0x01,
expand_fwd_v = 0x02,
expand_bwd_v = 0x04,
// expand_both = expand_fwd | expand_bwd,
// expand_or_new = allocate_new | expand_both,
shrink_in_place_v = 0x08,
nothrow_allocation_v = 0x10,
zero_memory_v = 0x20,
try_shrink_in_place_v = 0x40
};
typedef int allocation_type;
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
static const allocation_type allocate_new = (allocation_type)allocate_new_v;
static const allocation_type expand_fwd = (allocation_type)expand_fwd_v;
static const allocation_type expand_bwd = (allocation_type)expand_bwd_v;
static const allocation_type shrink_in_place = (allocation_type)shrink_in_place_v;
static const allocation_type try_shrink_in_place= (allocation_type)try_shrink_in_place_v;
static const allocation_type nothrow_allocation = (allocation_type)nothrow_allocation_v;
static const allocation_type zero_memory = (allocation_type)zero_memory_v;
} //namespace container {
} //namespace boost {
#include <boost/container/detail/config_end.hpp>
#endif //BOOST_CONTAINER_ALLOCATION_TYPE_HPP

View file

@ -0,0 +1,168 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2012-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_DETAIL_ALLOCATOR_VERSION_TRAITS_HPP
#define BOOST_CONTAINER_DETAIL_ALLOCATOR_VERSION_TRAITS_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/allocator_traits.hpp> //allocator_traits
#include <boost/container/throw_exception.hpp>
#include <boost/container/detail/multiallocation_chain.hpp> //multiallocation_chain
#include <boost/container/detail/version_type.hpp> //version_type
#include <boost/container/detail/allocation_type.hpp> //allocation_type
#include <boost/container/detail/mpl.hpp> //integral_constant
#include <boost/intrusive/pointer_traits.hpp> //pointer_traits
#include <utility> //pair
#include <boost/core/no_exceptions_support.hpp> //BOOST_TRY
namespace boost {
namespace container {
namespace container_detail {
template<class Allocator, unsigned Version = boost::container::container_detail::version<Allocator>::value>
struct allocator_version_traits
{
typedef ::boost::container::container_detail::integral_constant
<unsigned, Version> alloc_version;
typedef typename Allocator::multiallocation_chain multiallocation_chain;
typedef typename boost::container::allocator_traits<Allocator>::pointer pointer;
typedef typename boost::container::allocator_traits<Allocator>::size_type size_type;
//Node allocation interface
static pointer allocate_one(Allocator &a)
{ return a.allocate_one(); }
static void deallocate_one(Allocator &a, const pointer &p)
{ a.deallocate_one(p); }
static void allocate_individual(Allocator &a, size_type n, multiallocation_chain &m)
{ return a.allocate_individual(n, m); }
static void deallocate_individual(Allocator &a, multiallocation_chain &holder)
{ a.deallocate_individual(holder); }
static std::pair<pointer, bool>
allocation_command(Allocator &a, allocation_type command,
size_type limit_size, size_type preferred_size,
size_type &received_size, const pointer &reuse)
{
return a.allocation_command
(command, limit_size, preferred_size, received_size, reuse);
}
};
template<class Allocator>
struct allocator_version_traits<Allocator, 1>
{
typedef ::boost::container::container_detail::integral_constant
<unsigned, 1> alloc_version;
typedef typename boost::container::allocator_traits<Allocator>::pointer pointer;
typedef typename boost::container::allocator_traits<Allocator>::size_type size_type;
typedef typename boost::container::allocator_traits<Allocator>::value_type value_type;
typedef typename boost::intrusive::pointer_traits<pointer>::
template rebind_pointer<void>::type void_ptr;
typedef container_detail::basic_multiallocation_chain
<void_ptr> multialloc_cached_counted;
typedef boost::container::container_detail::
transform_multiallocation_chain
< multialloc_cached_counted, value_type> multiallocation_chain;
//Node allocation interface
static pointer allocate_one(Allocator &a)
{ return a.allocate(1); }
static void deallocate_one(Allocator &a, const pointer &p)
{ a.deallocate(p, 1); }
static void deallocate_individual(Allocator &a, multiallocation_chain &holder)
{
size_type n = holder.size();
typename multiallocation_chain::iterator it = holder.begin();
while(n--){
pointer p = boost::intrusive::pointer_traits<pointer>::pointer_to(*it);
++it;
a.deallocate(p, 1);
}
}
struct allocate_individual_rollback
{
allocate_individual_rollback(Allocator &a, multiallocation_chain &chain)
: mr_a(a), mp_chain(&chain)
{}
~allocate_individual_rollback()
{
if(mp_chain)
allocator_version_traits::deallocate_individual(mr_a, *mp_chain);
}
void release()
{
mp_chain = 0;
}
Allocator &mr_a;
multiallocation_chain * mp_chain;
};
static void allocate_individual(Allocator &a, size_type n, multiallocation_chain &m)
{
allocate_individual_rollback rollback(a, m);
while(n--){
m.push_front(a.allocate(1));
}
rollback.release();
}
static std::pair<pointer, bool>
allocation_command(Allocator &a, allocation_type command,
size_type, size_type preferred_size,
size_type &received_size, const pointer &)
{
std::pair<pointer, bool> ret(pointer(), false);
if(!(command & allocate_new)){
if(!(command & nothrow_allocation)){
throw_logic_error("version 1 allocator without allocate_new flag");
}
}
else{
received_size = preferred_size;
BOOST_TRY{
ret.first = a.allocate(received_size);
}
BOOST_CATCH(...){
if(!(command & nothrow_allocation)){
BOOST_RETHROW
}
}
BOOST_CATCH_END
}
return ret;
}
};
} //namespace container_detail {
} //namespace container {
} //namespace boost {
#include <boost/container/detail/config_end.hpp>
#endif // ! defined(BOOST_CONTAINER_DETAIL_ALLOCATOR_VERSION_TRAITS_HPP)

View file

@ -0,0 +1,38 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2007-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_DETAIL_AUTO_LINK_HPP_INCLUDED
#define BOOST_CONTAINER_DETAIL_AUTO_LINK_HPP_INCLUDED
#if defined(_MSC_VER)
# pragma once
#endif
//
// Automatically link to the correct build variant where possible.
//
#if !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_CONTAINER_NO_LIB) && !defined(BOOST_CONTAINER_SOURCE)
//
// Set the name of our library, this will get undef'ed by auto_link.hpp
// once it's done with it:
//
#define BOOST_LIB_NAME boost_container
//
// If we're importing code from a dll, then tell auto_link.hpp about it:
//
#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_CONTAINER_DYN_LINK)
# define BOOST_DYN_LINK
#endif
//
// And include the header that does the work:
//
#include <boost/config/auto_link.hpp>
#endif // auto-linking disabled
#endif //#ifndef BOOST_CONTAINER_DETAIL_AUTO_LINK_HPP_INCLUDED

View file

@ -0,0 +1,48 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_CONTAINER_DETAIL_CONFIG_INCLUDED
#define BOOST_CONTAINER_CONTAINER_DETAIL_CONFIG_INCLUDED
#ifndef BOOST_CONFIG_HPP
#include <boost/config.hpp>
#endif
#endif //BOOST_CONTAINER_CONTAINER_DETAIL_CONFIG_INCLUDED
#ifdef BOOST_MSVC
#pragma warning (push)
#pragma warning (disable : 4702) // unreachable code
#pragma warning (disable : 4706) // assignment within conditional expression
#pragma warning (disable : 4127) // conditional expression is constant
#pragma warning (disable : 4146) // unary minus operator applied to unsigned type, result still unsigned
#pragma warning (disable : 4284) // odd return type for operator->
#pragma warning (disable : 4244) // possible loss of data
#pragma warning (disable : 4251) // "identifier" : class "type" needs to have dll-interface to be used by clients of class "type2"
#pragma warning (disable : 4267) // conversion from "X" to "Y", possible loss of data
#pragma warning (disable : 4275) // non DLL-interface classkey "identifier" used as base for DLL-interface classkey "identifier"
#pragma warning (disable : 4355) // "this" : used in base member initializer list
#pragma warning (disable : 4503) // "identifier" : decorated name length exceeded, name was truncated
#pragma warning (disable : 4511) // copy constructor could not be generated
#pragma warning (disable : 4512) // assignment operator could not be generated
#pragma warning (disable : 4514) // unreferenced inline removed
#pragma warning (disable : 4521) // Disable "multiple copy constructors specified"
#pragma warning (disable : 4522) // "class" : multiple assignment operators specified
#pragma warning (disable : 4675) // "method" should be declared "static" and have exactly one parameter
#pragma warning (disable : 4710) // function not inlined
#pragma warning (disable : 4711) // function selected for automatic inline expansion
#pragma warning (disable : 4786) // identifier truncated in debug info
#pragma warning (disable : 4996) // "function": was declared deprecated
#pragma warning (disable : 4197) // top-level volatile in cast is ignored
#pragma warning (disable : 4541) // 'typeid' used on polymorphic type 'boost::exception'
// with /GR-; unpredictable behavior may result
#pragma warning (disable : 4673) // throwing '' the following types will not be considered at the catch site
#pragma warning (disable : 4671) // the copy constructor is inaccessible
#pragma warning (disable : 4584) // X is already a base-class of Y
#pragma warning (disable : 4510) // default constructor could not be generated
#endif //BOOST_MSVC

View file

@ -0,0 +1,13 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#if defined BOOST_MSVC
#pragma warning (pop)
#endif

View file

@ -0,0 +1,380 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2013.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_DESTROYERS_HPP
#define BOOST_CONTAINER_DESTROYERS_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/detail/version_type.hpp>
#include <boost/container/detail/utilities.hpp>
#include <boost/container/allocator_traits.hpp>
namespace boost {
namespace container {
namespace container_detail {
//!A deleter for scoped_ptr that deallocates the memory
//!allocated for an object using a STL allocator.
template <class A>
struct scoped_deallocator
{
typedef allocator_traits<A> allocator_traits_type;
typedef typename allocator_traits_type::pointer pointer;
typedef container_detail::integral_constant<unsigned,
boost::container::container_detail::
version<A>::value> alloc_version;
typedef container_detail::integral_constant<unsigned, 1> allocator_v1;
typedef container_detail::integral_constant<unsigned, 2> allocator_v2;
private:
void priv_deallocate(allocator_v1)
{ m_alloc.deallocate(m_ptr, 1); }
void priv_deallocate(allocator_v2)
{ m_alloc.deallocate_one(m_ptr); }
BOOST_MOVABLE_BUT_NOT_COPYABLE(scoped_deallocator)
public:
pointer m_ptr;
A& m_alloc;
scoped_deallocator(pointer p, A& a)
: m_ptr(p), m_alloc(a)
{}
~scoped_deallocator()
{ if (m_ptr)priv_deallocate(alloc_version()); }
scoped_deallocator(BOOST_RV_REF(scoped_deallocator) o)
: m_ptr(o.m_ptr), m_alloc(o.m_alloc)
{ o.release(); }
pointer get() const
{ return m_ptr; }
void set(const pointer &p)
{ m_ptr = p; }
void release()
{ m_ptr = 0; }
};
template <class Allocator>
struct null_scoped_deallocator
{
typedef boost::container::allocator_traits<Allocator> AllocTraits;
typedef typename AllocTraits::pointer pointer;
typedef typename AllocTraits::size_type size_type;
null_scoped_deallocator(pointer, Allocator&, size_type)
{}
void release()
{}
pointer get() const
{ return pointer(); }
void set(const pointer &)
{}
};
//!A deleter for scoped_ptr that deallocates the memory
//!allocated for an array of objects using a STL allocator.
template <class Allocator>
struct scoped_array_deallocator
{
typedef boost::container::allocator_traits<Allocator> AllocTraits;
typedef typename AllocTraits::pointer pointer;
typedef typename AllocTraits::size_type size_type;
scoped_array_deallocator(pointer p, Allocator& a, size_type length)
: m_ptr(p), m_alloc(a), m_length(length) {}
~scoped_array_deallocator()
{ if (m_ptr) m_alloc.deallocate(m_ptr, m_length); }
void release()
{ m_ptr = 0; }
private:
pointer m_ptr;
Allocator& m_alloc;
size_type m_length;
};
template <class Allocator>
struct null_scoped_array_deallocator
{
typedef boost::container::allocator_traits<Allocator> AllocTraits;
typedef typename AllocTraits::pointer pointer;
typedef typename AllocTraits::size_type size_type;
null_scoped_array_deallocator(pointer, Allocator&, size_type)
{}
void release()
{}
};
template <class Allocator>
struct scoped_destroy_deallocator
{
typedef boost::container::allocator_traits<Allocator> AllocTraits;
typedef typename AllocTraits::pointer pointer;
typedef typename AllocTraits::size_type size_type;
typedef container_detail::integral_constant<unsigned,
boost::container::container_detail::
version<Allocator>::value> alloc_version;
typedef container_detail::integral_constant<unsigned, 1> allocator_v1;
typedef container_detail::integral_constant<unsigned, 2> allocator_v2;
scoped_destroy_deallocator(pointer p, Allocator& a)
: m_ptr(p), m_alloc(a) {}
~scoped_destroy_deallocator()
{
if(m_ptr){
AllocTraits::destroy(m_alloc, container_detail::to_raw_pointer(m_ptr));
priv_deallocate(m_ptr, alloc_version());
}
}
void release()
{ m_ptr = 0; }
private:
void priv_deallocate(const pointer &p, allocator_v1)
{ AllocTraits::deallocate(m_alloc, p, 1); }
void priv_deallocate(const pointer &p, allocator_v2)
{ m_alloc.deallocate_one(p); }
pointer m_ptr;
Allocator& m_alloc;
};
//!A deleter for scoped_ptr that destroys
//!an object using a STL allocator.
template <class Allocator>
struct scoped_destructor_n
{
typedef boost::container::allocator_traits<Allocator> AllocTraits;
typedef typename AllocTraits::pointer pointer;
typedef typename AllocTraits::value_type value_type;
typedef typename AllocTraits::size_type size_type;
scoped_destructor_n(pointer p, Allocator& a, size_type n)
: m_p(p), m_a(a), m_n(n)
{}
void release()
{ m_p = 0; }
void increment_size(size_type inc)
{ m_n += inc; }
void increment_size_backwards(size_type inc)
{ m_n += inc; m_p -= inc; }
void shrink_forward(size_type inc)
{ m_n -= inc; m_p += inc; }
~scoped_destructor_n()
{
if(!m_p) return;
value_type *raw_ptr = container_detail::to_raw_pointer(m_p);
while(m_n--){
AllocTraits::destroy(m_a, raw_ptr++);
}
}
private:
pointer m_p;
Allocator & m_a;
size_type m_n;
};
//!A deleter for scoped_ptr that destroys
//!an object using a STL allocator.
template <class Allocator>
struct null_scoped_destructor_n
{
typedef boost::container::allocator_traits<Allocator> AllocTraits;
typedef typename AllocTraits::pointer pointer;
typedef typename AllocTraits::size_type size_type;
null_scoped_destructor_n(pointer, Allocator&, size_type)
{}
void increment_size(size_type)
{}
void increment_size_backwards(size_type)
{}
void shrink_forward(size_type)
{}
void release()
{}
};
template<class A>
class scoped_destructor
{
typedef boost::container::allocator_traits<A> AllocTraits;
public:
typedef typename A::value_type value_type;
scoped_destructor(A &a, value_type *pv)
: pv_(pv), a_(a)
{}
~scoped_destructor()
{
if(pv_){
AllocTraits::destroy(a_, pv_);
}
}
void release()
{ pv_ = 0; }
void set(value_type *ptr) { pv_ = ptr; }
value_type *get() const { return pv_; }
private:
value_type *pv_;
A &a_;
};
template<class A>
class value_destructor
{
typedef boost::container::allocator_traits<A> AllocTraits;
public:
typedef typename A::value_type value_type;
value_destructor(A &a, value_type &rv)
: rv_(rv), a_(a)
{}
~value_destructor()
{
AllocTraits::destroy(a_, &rv_);
}
private:
value_type &rv_;
A &a_;
};
template <class Allocator>
class allocator_destroyer
{
typedef boost::container::allocator_traits<Allocator> AllocTraits;
typedef typename AllocTraits::value_type value_type;
typedef typename AllocTraits::pointer pointer;
typedef container_detail::integral_constant<unsigned,
boost::container::container_detail::
version<Allocator>::value> alloc_version;
typedef container_detail::integral_constant<unsigned, 1> allocator_v1;
typedef container_detail::integral_constant<unsigned, 2> allocator_v2;
private:
Allocator & a_;
private:
void priv_deallocate(const pointer &p, allocator_v1)
{ AllocTraits::deallocate(a_,p, 1); }
void priv_deallocate(const pointer &p, allocator_v2)
{ a_.deallocate_one(p); }
public:
allocator_destroyer(Allocator &a)
: a_(a)
{}
void operator()(const pointer &p)
{
AllocTraits::destroy(a_, container_detail::to_raw_pointer(p));
this->priv_deallocate(p, alloc_version());
}
};
template <class A>
class allocator_destroyer_and_chain_builder
{
typedef allocator_traits<A> allocator_traits_type;
typedef typename allocator_traits_type::value_type value_type;
typedef typename A::multiallocation_chain multiallocation_chain;
A & a_;
multiallocation_chain &c_;
public:
allocator_destroyer_and_chain_builder(A &a, multiallocation_chain &c)
: a_(a), c_(c)
{}
void operator()(const typename A::pointer &p)
{
allocator_traits<A>::destroy(a_, container_detail::to_raw_pointer(p));
c_.push_back(p);
}
};
template <class A>
class allocator_multialloc_chain_node_deallocator
{
typedef allocator_traits<A> allocator_traits_type;
typedef typename allocator_traits_type::value_type value_type;
typedef typename A::multiallocation_chain multiallocation_chain;
typedef allocator_destroyer_and_chain_builder<A> chain_builder;
A & a_;
multiallocation_chain c_;
public:
allocator_multialloc_chain_node_deallocator(A &a)
: a_(a), c_()
{}
chain_builder get_chain_builder()
{ return chain_builder(a_, c_); }
~allocator_multialloc_chain_node_deallocator()
{
a_.deallocate_individual(c_);
}
};
} //namespace container_detail {
} //namespace container {
} //namespace boost {
#include <boost/container/detail/config_end.hpp>
#endif //#ifndef BOOST_CONTAINER_DESTROYERS_HPP

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,92 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2009-2013.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
/////////////////////////////////////////////////////////////////////////////
// This code was modified from the code posted by Alexandre Courpron in his
// article "Interface Detection" in The Code Project:
// http://www.codeproject.com/KB/architecture/Detector.aspx
///////////////////////////////////////////////////////////////////////////////
// Copyright 2007 Alexandre Courpron
//
// Permission to use, copy, modify, redistribute and sell this software,
// provided that this copyright notice appears on all copies of the software.
///////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_DETAIL_FUNCTION_DETECTOR_HPP
#define BOOST_CONTAINER_DETAIL_FUNCTION_DETECTOR_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
namespace boost {
namespace container {
namespace function_detector {
typedef char NotFoundType;
struct StaticFunctionType { NotFoundType x [2]; };
struct NonStaticFunctionType { NotFoundType x [3]; };
enum
{ NotFound = 0,
StaticFunction = sizeof( StaticFunctionType ) - sizeof( NotFoundType ),
NonStaticFunction = sizeof( NonStaticFunctionType ) - sizeof( NotFoundType )
};
} //namespace boost {
} //namespace container {
} //namespace function_detector {
#define BOOST_CONTAINER_CREATE_FUNCTION_DETECTOR(Identifier, InstantiationKey) \
namespace boost { \
namespace container { \
namespace function_detector { \
template < class T, \
class NonStaticType, \
class NonStaticConstType, \
class StaticType > \
class DetectMember_##InstantiationKey_##Identifier { \
template < NonStaticType > \
struct TestNonStaticNonConst ; \
\
template < NonStaticConstType > \
struct TestNonStaticConst ; \
\
template < StaticType > \
struct TestStatic ; \
\
template <class U > \
static NonStaticFunctionType Test( TestNonStaticNonConst<&U::Identifier>*, int ); \
\
template <class U > \
static NonStaticFunctionType Test( TestNonStaticConst<&U::Identifier>*, int ); \
\
template <class U> \
static StaticFunctionType Test( TestStatic<&U::Identifier>*, int ); \
\
template <class U> \
static NotFoundType Test( ... ); \
public : \
static const int check = NotFound + (sizeof(Test<T>(0, 0)) - sizeof(NotFoundType));\
};\
}}} //namespace boost::container::function_detector {
#define BOOST_CONTAINER_DETECT_FUNCTION(Class, InstantiationKey, ReturnType, Identifier, Params) \
::boost::container::function_detector::DetectMember_##InstantiationKey_##Identifier< Class,\
ReturnType (Class::*)Params,\
ReturnType (Class::*)Params const,\
ReturnType (*)Params \
>::check
#include <boost/container/detail/config_end.hpp>
#endif //@ifndef BOOST_CONTAINER_DETAIL_FUNCTION_DETECTOR_HPP

View file

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

View file

@ -0,0 +1,821 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2013.
// (C) Copyright Gennaro Prota 2003 - 2004.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_DETAIL_ITERATORS_HPP
#define BOOST_CONTAINER_DETAIL_ITERATORS_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/allocator_traits.hpp>
#include <boost/container/detail/type_traits.hpp>
#include <boost/static_assert.hpp>
#include <boost/move/utility_core.hpp>
#include <boost/intrusive/detail/reverse_iterator.hpp>
#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
#include <boost/container/detail/variadic_templates_tools.hpp>
#else
#include <boost/container/detail/preprocessor.hpp>
#endif
#include <iterator>
namespace boost {
namespace container {
template <class T, class Difference = std::ptrdiff_t>
class constant_iterator
: public std::iterator
<std::random_access_iterator_tag, T, Difference, const T*, const T &>
{
typedef constant_iterator<T, Difference> this_type;
public:
explicit constant_iterator(const T &ref, Difference range_size)
: m_ptr(&ref), m_num(range_size){}
//Constructors
constant_iterator()
: m_ptr(0), m_num(0){}
constant_iterator& operator++()
{ increment(); return *this; }
constant_iterator operator++(int)
{
constant_iterator result (*this);
increment();
return result;
}
constant_iterator& operator--()
{ decrement(); return *this; }
constant_iterator operator--(int)
{
constant_iterator result (*this);
decrement();
return result;
}
friend bool operator== (const constant_iterator& i, const constant_iterator& i2)
{ return i.equal(i2); }
friend bool operator!= (const constant_iterator& i, const constant_iterator& i2)
{ return !(i == i2); }
friend bool operator< (const constant_iterator& i, const constant_iterator& i2)
{ return i.less(i2); }
friend bool operator> (const constant_iterator& i, const constant_iterator& i2)
{ return i2 < i; }
friend bool operator<= (const constant_iterator& i, const constant_iterator& i2)
{ return !(i > i2); }
friend bool operator>= (const constant_iterator& i, const constant_iterator& i2)
{ return !(i < i2); }
friend Difference operator- (const constant_iterator& i, const constant_iterator& i2)
{ return i2.distance_to(i); }
//Arithmetic
constant_iterator& operator+=(Difference off)
{ this->advance(off); return *this; }
constant_iterator operator+(Difference off) const
{
constant_iterator other(*this);
other.advance(off);
return other;
}
friend constant_iterator operator+(Difference off, const constant_iterator& right)
{ return right + off; }
constant_iterator& operator-=(Difference off)
{ this->advance(-off); return *this; }
constant_iterator operator-(Difference off) const
{ return *this + (-off); }
const T& operator*() const
{ return dereference(); }
const T& operator[] (Difference ) const
{ return dereference(); }
const T* operator->() const
{ return &(dereference()); }
private:
const T * m_ptr;
Difference m_num;
void increment()
{ --m_num; }
void decrement()
{ ++m_num; }
bool equal(const this_type &other) const
{ return m_num == other.m_num; }
bool less(const this_type &other) const
{ return other.m_num < m_num; }
const T & dereference() const
{ return *m_ptr; }
void advance(Difference n)
{ m_num -= n; }
Difference distance_to(const this_type &other)const
{ return m_num - other.m_num; }
};
template <class T, class Difference>
class value_init_construct_iterator
: public std::iterator
<std::random_access_iterator_tag, T, Difference, const T*, const T &>
{
typedef value_init_construct_iterator<T, Difference> this_type;
public:
explicit value_init_construct_iterator(Difference range_size)
: m_num(range_size){}
//Constructors
value_init_construct_iterator()
: m_num(0){}
value_init_construct_iterator& operator++()
{ increment(); return *this; }
value_init_construct_iterator operator++(int)
{
value_init_construct_iterator result (*this);
increment();
return result;
}
value_init_construct_iterator& operator--()
{ decrement(); return *this; }
value_init_construct_iterator operator--(int)
{
value_init_construct_iterator result (*this);
decrement();
return result;
}
friend bool operator== (const value_init_construct_iterator& i, const value_init_construct_iterator& i2)
{ return i.equal(i2); }
friend bool operator!= (const value_init_construct_iterator& i, const value_init_construct_iterator& i2)
{ return !(i == i2); }
friend bool operator< (const value_init_construct_iterator& i, const value_init_construct_iterator& i2)
{ return i.less(i2); }
friend bool operator> (const value_init_construct_iterator& i, const value_init_construct_iterator& i2)
{ return i2 < i; }
friend bool operator<= (const value_init_construct_iterator& i, const value_init_construct_iterator& i2)
{ return !(i > i2); }
friend bool operator>= (const value_init_construct_iterator& i, const value_init_construct_iterator& i2)
{ return !(i < i2); }
friend Difference operator- (const value_init_construct_iterator& i, const value_init_construct_iterator& i2)
{ return i2.distance_to(i); }
//Arithmetic
value_init_construct_iterator& operator+=(Difference off)
{ this->advance(off); return *this; }
value_init_construct_iterator operator+(Difference off) const
{
value_init_construct_iterator other(*this);
other.advance(off);
return other;
}
friend value_init_construct_iterator operator+(Difference off, const value_init_construct_iterator& right)
{ return right + off; }
value_init_construct_iterator& operator-=(Difference off)
{ this->advance(-off); return *this; }
value_init_construct_iterator operator-(Difference off) const
{ return *this + (-off); }
//This pseudo-iterator's dereference operations have no sense since value is not
//constructed until ::boost::container::construct_in_place is called.
//So comment them to catch bad uses
//const T& operator*() const;
//const T& operator[](difference_type) const;
//const T* operator->() const;
private:
Difference m_num;
void increment()
{ --m_num; }
void decrement()
{ ++m_num; }
bool equal(const this_type &other) const
{ return m_num == other.m_num; }
bool less(const this_type &other) const
{ return other.m_num < m_num; }
const T & dereference() const
{
static T dummy;
return dummy;
}
void advance(Difference n)
{ m_num -= n; }
Difference distance_to(const this_type &other)const
{ return m_num - other.m_num; }
};
template <class T, class Difference>
class default_init_construct_iterator
: public std::iterator
<std::random_access_iterator_tag, T, Difference, const T*, const T &>
{
typedef default_init_construct_iterator<T, Difference> this_type;
public:
explicit default_init_construct_iterator(Difference range_size)
: m_num(range_size){}
//Constructors
default_init_construct_iterator()
: m_num(0){}
default_init_construct_iterator& operator++()
{ increment(); return *this; }
default_init_construct_iterator operator++(int)
{
default_init_construct_iterator result (*this);
increment();
return result;
}
default_init_construct_iterator& operator--()
{ decrement(); return *this; }
default_init_construct_iterator operator--(int)
{
default_init_construct_iterator result (*this);
decrement();
return result;
}
friend bool operator== (const default_init_construct_iterator& i, const default_init_construct_iterator& i2)
{ return i.equal(i2); }
friend bool operator!= (const default_init_construct_iterator& i, const default_init_construct_iterator& i2)
{ return !(i == i2); }
friend bool operator< (const default_init_construct_iterator& i, const default_init_construct_iterator& i2)
{ return i.less(i2); }
friend bool operator> (const default_init_construct_iterator& i, const default_init_construct_iterator& i2)
{ return i2 < i; }
friend bool operator<= (const default_init_construct_iterator& i, const default_init_construct_iterator& i2)
{ return !(i > i2); }
friend bool operator>= (const default_init_construct_iterator& i, const default_init_construct_iterator& i2)
{ return !(i < i2); }
friend Difference operator- (const default_init_construct_iterator& i, const default_init_construct_iterator& i2)
{ return i2.distance_to(i); }
//Arithmetic
default_init_construct_iterator& operator+=(Difference off)
{ this->advance(off); return *this; }
default_init_construct_iterator operator+(Difference off) const
{
default_init_construct_iterator other(*this);
other.advance(off);
return other;
}
friend default_init_construct_iterator operator+(Difference off, const default_init_construct_iterator& right)
{ return right + off; }
default_init_construct_iterator& operator-=(Difference off)
{ this->advance(-off); return *this; }
default_init_construct_iterator operator-(Difference off) const
{ return *this + (-off); }
//This pseudo-iterator's dereference operations have no sense since value is not
//constructed until ::boost::container::construct_in_place is called.
//So comment them to catch bad uses
//const T& operator*() const;
//const T& operator[](difference_type) const;
//const T* operator->() const;
private:
Difference m_num;
void increment()
{ --m_num; }
void decrement()
{ ++m_num; }
bool equal(const this_type &other) const
{ return m_num == other.m_num; }
bool less(const this_type &other) const
{ return other.m_num < m_num; }
const T & dereference() const
{
static T dummy;
return dummy;
}
void advance(Difference n)
{ m_num -= n; }
Difference distance_to(const this_type &other)const
{ return m_num - other.m_num; }
};
template <class T, class Difference = std::ptrdiff_t>
class repeat_iterator
: public std::iterator
<std::random_access_iterator_tag, T, Difference>
{
typedef repeat_iterator<T, Difference> this_type;
public:
explicit repeat_iterator(T &ref, Difference range_size)
: m_ptr(&ref), m_num(range_size){}
//Constructors
repeat_iterator()
: m_ptr(0), m_num(0){}
this_type& operator++()
{ increment(); return *this; }
this_type operator++(int)
{
this_type result (*this);
increment();
return result;
}
this_type& operator--()
{ increment(); return *this; }
this_type operator--(int)
{
this_type result (*this);
increment();
return result;
}
friend bool operator== (const this_type& i, const this_type& i2)
{ return i.equal(i2); }
friend bool operator!= (const this_type& i, const this_type& i2)
{ return !(i == i2); }
friend bool operator< (const this_type& i, const this_type& i2)
{ return i.less(i2); }
friend bool operator> (const this_type& i, const this_type& i2)
{ return i2 < i; }
friend bool operator<= (const this_type& i, const this_type& i2)
{ return !(i > i2); }
friend bool operator>= (const this_type& i, const this_type& i2)
{ return !(i < i2); }
friend Difference operator- (const this_type& i, const this_type& i2)
{ return i2.distance_to(i); }
//Arithmetic
this_type& operator+=(Difference off)
{ this->advance(off); return *this; }
this_type operator+(Difference off) const
{
this_type other(*this);
other.advance(off);
return other;
}
friend this_type operator+(Difference off, const this_type& right)
{ return right + off; }
this_type& operator-=(Difference off)
{ this->advance(-off); return *this; }
this_type operator-(Difference off) const
{ return *this + (-off); }
T& operator*() const
{ return dereference(); }
T& operator[] (Difference ) const
{ return dereference(); }
T *operator->() const
{ return &(dereference()); }
private:
T * m_ptr;
Difference m_num;
void increment()
{ --m_num; }
void decrement()
{ ++m_num; }
bool equal(const this_type &other) const
{ return m_num == other.m_num; }
bool less(const this_type &other) const
{ return other.m_num < m_num; }
T & dereference() const
{ return *m_ptr; }
void advance(Difference n)
{ m_num -= n; }
Difference distance_to(const this_type &other)const
{ return m_num - other.m_num; }
};
template <class T, class EmplaceFunctor, class Difference /*= std::ptrdiff_t*/>
class emplace_iterator
: public std::iterator
<std::random_access_iterator_tag, T, Difference, const T*, const T &>
{
typedef emplace_iterator this_type;
public:
typedef Difference difference_type;
explicit emplace_iterator(EmplaceFunctor&e)
: m_num(1), m_pe(&e){}
emplace_iterator()
: m_num(0), m_pe(0){}
this_type& operator++()
{ increment(); return *this; }
this_type operator++(int)
{
this_type result (*this);
increment();
return result;
}
this_type& operator--()
{ decrement(); return *this; }
this_type operator--(int)
{
this_type result (*this);
decrement();
return result;
}
friend bool operator== (const this_type& i, const this_type& i2)
{ return i.equal(i2); }
friend bool operator!= (const this_type& i, const this_type& i2)
{ return !(i == i2); }
friend bool operator< (const this_type& i, const this_type& i2)
{ return i.less(i2); }
friend bool operator> (const this_type& i, const this_type& i2)
{ return i2 < i; }
friend bool operator<= (const this_type& i, const this_type& i2)
{ return !(i > i2); }
friend bool operator>= (const this_type& i, const this_type& i2)
{ return !(i < i2); }
friend difference_type operator- (const this_type& i, const this_type& i2)
{ return i2.distance_to(i); }
//Arithmetic
this_type& operator+=(difference_type off)
{ this->advance(off); return *this; }
this_type operator+(difference_type off) const
{
this_type other(*this);
other.advance(off);
return other;
}
friend this_type operator+(difference_type off, const this_type& right)
{ return right + off; }
this_type& operator-=(difference_type off)
{ this->advance(-off); return *this; }
this_type operator-(difference_type off) const
{ return *this + (-off); }
//This pseudo-iterator's dereference operations have no sense since value is not
//constructed until ::boost::container::construct_in_place is called.
//So comment them to catch bad uses
//const T& operator*() const;
//const T& operator[](difference_type) const;
//const T* operator->() const;
template<class A>
void construct_in_place(A &a, T* ptr)
{ (*m_pe)(a, ptr); }
private:
difference_type m_num;
EmplaceFunctor * m_pe;
void increment()
{ --m_num; }
void decrement()
{ ++m_num; }
bool equal(const this_type &other) const
{ return m_num == other.m_num; }
bool less(const this_type &other) const
{ return other.m_num < m_num; }
const T & dereference() const
{
static T dummy;
return dummy;
}
void advance(difference_type n)
{ m_num -= n; }
difference_type distance_to(const this_type &other)const
{ return difference_type(m_num - other.m_num); }
};
#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
template<class ...Args>
struct emplace_functor
{
typedef typename container_detail::build_number_seq<sizeof...(Args)>::type index_tuple_t;
emplace_functor(Args&&... args)
: args_(args...)
{}
template<class A, class T>
void operator()(A &a, T *ptr)
{ emplace_functor::inplace_impl(a, ptr, index_tuple_t()); }
template<class A, class T, int ...IdxPack>
void inplace_impl(A &a, T* ptr, const container_detail::index_tuple<IdxPack...>&)
{
allocator_traits<A>::construct
(a, ptr, ::boost::forward<Args>(container_detail::get<IdxPack>(args_))...);
}
container_detail::tuple<Args&...> args_;
};
#else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
#define BOOST_PP_LOCAL_MACRO(n) \
BOOST_PP_EXPR_IF(n, template <) \
BOOST_PP_ENUM_PARAMS(n, class P) \
BOOST_PP_EXPR_IF(n, >) \
struct BOOST_PP_CAT(BOOST_PP_CAT(emplace_functor, n), arg) \
{ \
BOOST_PP_CAT(BOOST_PP_CAT(emplace_functor, n), arg) \
( BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _) ) \
BOOST_PP_EXPR_IF(n, :) BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_INIT, _){} \
\
template<class A, class T> \
void operator()(A &a, T *ptr) \
{ \
allocator_traits<A>::construct \
(a, ptr BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_MEMBER_FORWARD, _) ); \
} \
BOOST_PP_REPEAT(n, BOOST_CONTAINER_PP_PARAM_DEFINE, _) \
}; \
//!
#define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
#include BOOST_PP_LOCAL_ITERATE()
#endif
namespace container_detail {
template<class T>
struct has_iterator_category
{
template <typename X>
static char test(int, typename X::iterator_category*);
template <typename X>
static int test(int, ...);
static const bool value = (1 == sizeof(test<T>(0, 0)));
};
template<class T, bool = has_iterator_category<T>::value >
struct is_input_iterator
{
static const bool value = is_same<typename T::iterator_category, std::input_iterator_tag>::value;
};
template<class T>
struct is_input_iterator<T, false>
{
static const bool value = false;
};
template<class T, bool = has_iterator_category<T>::value >
struct is_forward_iterator
{
static const bool value = is_same<typename T::iterator_category, std::forward_iterator_tag>::value;
};
template<class T>
struct is_forward_iterator<T, false>
{
static const bool value = false;
};
template<class T, bool = has_iterator_category<T>::value >
struct is_bidirectional_iterator
{
static const bool value = is_same<typename T::iterator_category, std::bidirectional_iterator_tag>::value;
};
template<class T>
struct is_bidirectional_iterator<T, false>
{
static const bool value = false;
};
template<class IINodeType>
struct iiterator_node_value_type {
typedef typename IINodeType::value_type type;
};
template<class IIterator>
struct iiterator_types
{
typedef typename IIterator::value_type it_value_type;
typedef typename iiterator_node_value_type<it_value_type>::type value_type;
typedef typename std::iterator_traits<IIterator>::pointer it_pointer;
typedef typename std::iterator_traits<IIterator>::difference_type difference_type;
typedef typename ::boost::intrusive::pointer_traits<it_pointer>::
template rebind_pointer<value_type>::type pointer;
typedef typename ::boost::intrusive::pointer_traits<it_pointer>::
template rebind_pointer<const value_type>::type const_pointer;
typedef typename ::boost::intrusive::
pointer_traits<pointer>::reference reference;
typedef typename ::boost::intrusive::
pointer_traits<const_pointer>::reference const_reference;
typedef typename IIterator::iterator_category iterator_category;
};
template<class IIterator, bool IsConst>
struct std_iterator
{
typedef typename std::iterator
< typename iiterator_types<IIterator>::iterator_category
, typename iiterator_types<IIterator>::value_type
, typename iiterator_types<IIterator>::difference_type
, typename iiterator_types<IIterator>::const_pointer
, typename iiterator_types<IIterator>::const_reference> type;
};
template<class IIterator>
struct std_iterator<IIterator, false>
{
typedef typename std::iterator
< typename iiterator_types<IIterator>::iterator_category
, typename iiterator_types<IIterator>::value_type
, typename iiterator_types<IIterator>::difference_type
, typename iiterator_types<IIterator>::pointer
, typename iiterator_types<IIterator>::reference> type;
};
template<class IIterator, bool IsConst>
class iterator
{
typedef typename std_iterator<IIterator, IsConst>::type types_t;
public:
typedef typename types_t::pointer pointer;
typedef typename types_t::reference reference;
typedef typename types_t::difference_type difference_type;
typedef typename types_t::iterator_category iterator_category;
typedef typename types_t::value_type value_type;
iterator()
{}
explicit iterator(IIterator iit) BOOST_CONTAINER_NOEXCEPT
: m_iit(iit)
{}
iterator(iterator<IIterator, false> const& other) BOOST_CONTAINER_NOEXCEPT
: m_iit(other.get())
{}
iterator& operator++() BOOST_CONTAINER_NOEXCEPT
{ ++this->m_iit; return *this; }
iterator operator++(int) BOOST_CONTAINER_NOEXCEPT
{
iterator result (*this);
++this->m_iit;
return result;
}
iterator& operator--() BOOST_CONTAINER_NOEXCEPT
{
//If the iterator is not a bidirectional iterator, operator-- should not exist
BOOST_STATIC_ASSERT((is_bidirectional_iterator<iterator>::value));
--this->m_iit; return *this;
}
iterator operator--(int) BOOST_CONTAINER_NOEXCEPT
{
iterator result (*this);
--this->m_iit;
return result;
}
friend bool operator== (const iterator& l, const iterator& r) BOOST_CONTAINER_NOEXCEPT
{ return l.m_iit == r.m_iit; }
friend bool operator!= (const iterator& l, const iterator& r) BOOST_CONTAINER_NOEXCEPT
{ return !(l == r); }
reference operator*() const BOOST_CONTAINER_NOEXCEPT
{ return (*this->m_iit).get_data(); }
pointer operator->() const BOOST_CONTAINER_NOEXCEPT
{ return ::boost::intrusive::pointer_traits<pointer>::pointer_to(this->operator*()); }
const IIterator &get() const BOOST_CONTAINER_NOEXCEPT
{ return this->m_iit; }
private:
IIterator m_iit;
};
using ::boost::intrusive::detail::reverse_iterator;
} //namespace container_detail {
} //namespace container {
} //namespace boost {
#include <boost/container/detail/config_end.hpp>
#endif //#ifndef BOOST_CONTAINER_DETAIL_ITERATORS_HPP

View file

@ -0,0 +1,119 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Stephen Cleary 2000.
// (C) Copyright Ion Gaztanaga 2007-2013.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
// This file is a slightly modified file from Boost.Pool
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_DETAIL_MATH_FUNCTIONS_HPP
#define BOOST_CONTAINER_DETAIL_MATH_FUNCTIONS_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <climits>
#include <boost/static_assert.hpp>
namespace boost {
namespace container {
namespace container_detail {
// Greatest common divisor and least common multiple
//
// gcd is an algorithm that calculates the greatest common divisor of two
// integers, using Euclid's algorithm.
//
// Pre: A > 0 && B > 0
// Recommended: A > B
template <typename Integer>
inline Integer gcd(Integer A, Integer B)
{
do
{
const Integer tmp(B);
B = A % B;
A = tmp;
} while (B != 0);
return A;
}
//
// lcm is an algorithm that calculates the least common multiple of two
// integers.
//
// Pre: A > 0 && B > 0
// Recommended: A > B
template <typename Integer>
inline Integer lcm(const Integer & A, const Integer & B)
{
Integer ret = A;
ret /= gcd(A, B);
ret *= B;
return ret;
}
template <typename Integer>
inline Integer log2_ceil(const Integer & A)
{
Integer i = 0;
Integer power_of_2 = 1;
while(power_of_2 < A){
power_of_2 <<= 1;
++i;
}
return i;
}
template <typename Integer>
inline Integer upper_power_of_2(const Integer & A)
{
Integer power_of_2 = 1;
while(power_of_2 < A){
power_of_2 <<= 1;
}
return power_of_2;
}
//This function uses binary search to discover the
//highest set bit of the integer
inline std::size_t floor_log2 (std::size_t x)
{
const std::size_t Bits = sizeof(std::size_t)*CHAR_BIT;
const bool Size_t_Bits_Power_2= !(Bits & (Bits-1));
BOOST_STATIC_ASSERT(((Size_t_Bits_Power_2)== true));
std::size_t n = x;
std::size_t log2 = 0;
for(std::size_t shift = Bits >> 1; shift; shift >>= 1){
std::size_t tmp = n >> shift;
if (tmp)
log2 += shift, n = tmp;
}
return log2;
}
} // namespace container_detail
} // namespace container
} // namespace boost
#include <boost/container/detail/config_end.hpp>
#endif

View file

@ -0,0 +1,90 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2011-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_ALLOCATOR_MEMORY_UTIL_HPP
#define BOOST_CONTAINER_ALLOCATOR_MEMORY_UTIL_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/detail/preprocessor.hpp>
#include <boost/intrusive/detail/mpl.hpp>
#include <boost/intrusive/detail/has_member_function_callable_with.hpp>
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME allocate
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace container { namespace container_detail {
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
#define BOOST_PP_ITERATION_PARAMS_1 (3, (2, 2, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
#include BOOST_PP_ITERATE()
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME destroy
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace container { namespace container_detail {
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
#define BOOST_PP_ITERATION_PARAMS_1 (3, (1, 1, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
#include BOOST_PP_ITERATE()
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME max_size
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace container { namespace container_detail {
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
#define BOOST_PP_ITERATION_PARAMS_1 (3, (0, 0, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
#include BOOST_PP_ITERATE()
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME select_on_container_copy_construction
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace container { namespace container_detail {
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
#define BOOST_PP_ITERATION_PARAMS_1 (3, (0, 0, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
#include BOOST_PP_ITERATE()
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME construct
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace container { namespace container_detail {
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
#ifdef BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_SINGLE_ITERATION
# define BOOST_PP_ITERATION_PARAMS_1 (3, (1, 1, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
#else
# define BOOST_PP_ITERATION_PARAMS_1 (3, (1, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS+1, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
#endif
#include BOOST_PP_ITERATE()
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME swap
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace container { namespace container_detail {
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
#define BOOST_PP_ITERATION_PARAMS_1 (3, (1, 1, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
#include BOOST_PP_ITERATE()
namespace boost {
namespace container {
namespace container_detail {
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(pointer)
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(const_pointer)
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(reference)
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(const_reference)
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(void_pointer)
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(const_void_pointer)
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(size_type)
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(propagate_on_container_copy_assignment)
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(propagate_on_container_move_assignment)
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(propagate_on_container_swap)
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(difference_type)
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(value_compare)
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(wrapped_value_compare)
} //namespace container_detail {
} //namespace container {
} //namespace boost {
#include <boost/container/detail/config_end.hpp>
#endif // ! defined(BOOST_CONTAINER_ALLOCATOR_MEMORY_UTIL_HPP)

View file

@ -0,0 +1,183 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2013.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_CONTAINER_DETAIL_MPL_HPP
#define BOOST_CONTAINER_CONTAINER_DETAIL_MPL_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <cstddef>
namespace boost {
namespace container {
namespace container_detail {
template <class T, T val>
struct integral_constant
{
static const T value = val;
typedef integral_constant<T,val> type;
};
template< bool C_ >
struct bool_ : integral_constant<bool, C_>
{
static const bool value = C_;
operator bool() const { return bool_::value; }
};
typedef bool_<true> true_;
typedef bool_<false> false_;
typedef true_ true_type;
typedef false_ false_type;
typedef char yes_type;
struct no_type
{
char padding[8];
};
template <bool B, class T = void>
struct enable_if_c {
typedef T type;
};
template <class T>
struct enable_if_c<false, T> {};
template <class Cond, class T = void>
struct enable_if : public enable_if_c<Cond::value, T> {};
template <class Cond, class T = void>
struct disable_if : public enable_if_c<!Cond::value, T> {};
template <bool B, class T = void>
struct disable_if_c : public enable_if_c<!B, T> {};
#if defined(_MSC_VER) && (_MSC_VER >= 1400)
template <class T, class U>
struct is_convertible
{
static const bool value = __is_convertible_to(T, U);
};
#else
template <class T, class U>
class is_convertible
{
typedef char true_t;
class false_t { char dummy[2]; };
//use any_conversion as first parameter since in MSVC
//overaligned types can't go through ellipsis
static false_t dispatch(...);
static true_t dispatch(U);
static T &trigger();
public:
static const bool value = sizeof(dispatch(trigger())) == sizeof(true_t);
};
#endif
template<
bool C
, typename T1
, typename T2
>
struct if_c
{
typedef T1 type;
};
template<
typename T1
, typename T2
>
struct if_c<false,T1,T2>
{
typedef T2 type;
};
template<
typename T1
, typename T2
, typename T3
>
struct if_
{
typedef typename if_c<0 != T1::value, T2, T3>::type type;
};
template <class Pair>
struct select1st
{
typedef Pair argument_type;
typedef typename Pair::first_type result_type;
template<class OtherPair>
const typename Pair::first_type& operator()(const OtherPair& x) const
{ return x.first; }
const typename Pair::first_type& operator()(const typename Pair::first_type& x) const
{ return x; }
};
// identity is an extension: it is not part of the standard.
template <class T>
struct identity
{
typedef T argument_type;
typedef T result_type;
typedef T type;
const T& operator()(const T& x) const
{ return x; }
};
template<std::size_t S>
struct ls_zeros
{
static const std::size_t value = (S & std::size_t(1)) ? 0 : (1u + ls_zeros<(S >> 1u)>::value);
};
template<>
struct ls_zeros<0>
{
static const std::size_t value = 0;
};
template<>
struct ls_zeros<1>
{
static const std::size_t value = 0;
};
template <typename T> struct unvoid { typedef T type; };
template <> struct unvoid<void> { struct type { }; };
template <> struct unvoid<const void> { struct type { }; };
} //namespace container_detail {
} //namespace container {
} //namespace boost {
#include <boost/container/detail/config_end.hpp>
#endif //#ifndef BOOST_CONTAINER_CONTAINER_DETAIL_MPL_HPP

View file

@ -0,0 +1,292 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_DETAIL_MULTIALLOCATION_CHAIN_HPP
#define BOOST_CONTAINER_DETAIL_MULTIALLOCATION_CHAIN_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/container_fwd.hpp>
#include <boost/container/detail/utilities.hpp>
#include <boost/container/detail/type_traits.hpp>
#include <boost/container/detail/transform_iterator.hpp>
#include <boost/intrusive/slist.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/type_traits/make_unsigned.hpp>
#include <boost/move/utility_core.hpp>
namespace boost {
namespace container {
namespace container_detail {
template<class VoidPointer>
class basic_multiallocation_chain
{
private:
typedef bi::slist_base_hook<bi::void_pointer<VoidPointer>
,bi::link_mode<bi::normal_link>
> node;
typedef typename boost::intrusive::pointer_traits
<VoidPointer>::template rebind_pointer<char>::type char_ptr;
typedef typename boost::intrusive::
pointer_traits<char_ptr>::difference_type difference_type;
typedef bi::slist< node
, bi::linear<true>
, bi::cache_last<true>
, bi::size_type<typename boost::make_unsigned<difference_type>::type>
> slist_impl_t;
slist_impl_t slist_impl_;
typedef typename boost::intrusive::pointer_traits
<VoidPointer>::template rebind_pointer<node>::type node_ptr;
typedef typename boost::intrusive::
pointer_traits<node_ptr> node_ptr_traits;
static node & to_node(const VoidPointer &p)
{ return *static_cast<node*>(static_cast<void*>(container_detail::to_raw_pointer(p))); }
static VoidPointer from_node(node &n)
{ return node_ptr_traits::pointer_to(n); }
static node_ptr to_node_ptr(const VoidPointer &p)
{ return node_ptr_traits::static_cast_from(p); }
BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_multiallocation_chain)
public:
typedef VoidPointer void_pointer;
typedef typename slist_impl_t::iterator iterator;
typedef typename slist_impl_t::size_type size_type;
basic_multiallocation_chain()
: slist_impl_()
{}
basic_multiallocation_chain(const void_pointer &b, const void_pointer &before_e, size_type n)
: slist_impl_(to_node_ptr(b), to_node_ptr(before_e), n)
{}
basic_multiallocation_chain(BOOST_RV_REF(basic_multiallocation_chain) other)
: slist_impl_(::boost::move(other.slist_impl_))
{}
basic_multiallocation_chain& operator=(BOOST_RV_REF(basic_multiallocation_chain) other)
{
slist_impl_ = ::boost::move(other.slist_impl_);
return *this;
}
bool empty() const
{ return slist_impl_.empty(); }
size_type size() const
{ return slist_impl_.size(); }
iterator before_begin()
{ return slist_impl_.before_begin(); }
iterator begin()
{ return slist_impl_.begin(); }
iterator end()
{ return slist_impl_.end(); }
iterator last()
{ return slist_impl_.last(); }
void clear()
{ slist_impl_.clear(); }
iterator insert_after(iterator it, void_pointer m)
{ return slist_impl_.insert_after(it, to_node(m)); }
void push_front(const void_pointer &m)
{ return slist_impl_.push_front(to_node(m)); }
void push_back(const void_pointer &m)
{ return slist_impl_.push_back(to_node(m)); }
void_pointer pop_front()
{
node & n = slist_impl_.front();
void_pointer ret = from_node(n);
slist_impl_.pop_front();
return ret;
}
void splice_after(iterator after_this, basic_multiallocation_chain &x, iterator before_b, iterator before_e, size_type n)
{ slist_impl_.splice_after(after_this, x.slist_impl_, before_b, before_e, n); }
void splice_after(iterator after_this, basic_multiallocation_chain &x)
{ slist_impl_.splice_after(after_this, x.slist_impl_); }
void erase_after(iterator before_b, iterator e, size_type n)
{ slist_impl_.erase_after(before_b, e, n); }
void_pointer incorporate_after(iterator after_this, const void_pointer &b, size_type unit_bytes, size_type num_units)
{
typedef typename boost::intrusive::pointer_traits<char_ptr> char_pointer_traits;
char_ptr elem = char_pointer_traits::static_cast_from(b);
if(num_units){
char_ptr prev_elem = elem;
elem += unit_bytes;
for(size_type i = 0; i != num_units-1; ++i, elem += unit_bytes){
::new (container_detail::to_raw_pointer(prev_elem)) void_pointer(elem);
prev_elem = elem;
}
slist_impl_.incorporate_after(after_this, to_node_ptr(b), to_node_ptr(prev_elem), num_units);
}
return elem;
}
void incorporate_after(iterator after_this, void_pointer b, void_pointer before_e, size_type n)
{ slist_impl_.incorporate_after(after_this, to_node_ptr(b), to_node_ptr(before_e), n); }
void swap(basic_multiallocation_chain &x)
{ slist_impl_.swap(x.slist_impl_); }
static iterator iterator_to(const void_pointer &p)
{ return slist_impl_t::s_iterator_to(to_node(p)); }
std::pair<void_pointer, void_pointer> extract_data()
{
std::pair<void_pointer, void_pointer> ret
(slist_impl_.begin().operator->()
,slist_impl_.last().operator->());
slist_impl_.clear();
return ret;
}
};
template<class T>
struct cast_functor
{
typedef typename container_detail::add_reference<T>::type result_type;
template<class U>
result_type operator()(U &ptr) const
{ return *static_cast<T*>(static_cast<void*>(&ptr)); }
};
template<class MultiallocationChain, class T>
class transform_multiallocation_chain
: public MultiallocationChain
{
private:
BOOST_MOVABLE_BUT_NOT_COPYABLE(transform_multiallocation_chain)
//transform_multiallocation_chain(const transform_multiallocation_chain &);
//transform_multiallocation_chain & operator=(const transform_multiallocation_chain &);
typedef typename MultiallocationChain::void_pointer void_pointer;
typedef typename boost::intrusive::pointer_traits
<void_pointer> void_pointer_traits;
typedef typename void_pointer_traits::template
rebind_pointer<T>::type pointer;
typedef typename boost::intrusive::pointer_traits
<pointer> pointer_traits;
static pointer cast(const void_pointer &p)
{ return pointer_traits::static_cast_from(p); }
public:
typedef transform_iterator
< typename MultiallocationChain::iterator
, container_detail::cast_functor <T> > iterator;
typedef typename MultiallocationChain::size_type size_type;
transform_multiallocation_chain()
: MultiallocationChain()
{}
transform_multiallocation_chain(BOOST_RV_REF(transform_multiallocation_chain) other)
: MultiallocationChain(::boost::move(static_cast<MultiallocationChain&>(other)))
{}
transform_multiallocation_chain(BOOST_RV_REF(MultiallocationChain) other)
: MultiallocationChain(::boost::move(static_cast<MultiallocationChain&>(other)))
{}
transform_multiallocation_chain& operator=(BOOST_RV_REF(transform_multiallocation_chain) other)
{
return static_cast<MultiallocationChain&>
(this->MultiallocationChain::operator=(::boost::move(static_cast<MultiallocationChain&>(other))));
}
/*
void push_front(const pointer &mem)
{ holder_.push_front(mem); }
void push_back(const pointer &mem)
{ return holder_.push_back(mem); }
void swap(transform_multiallocation_chain &other_chain)
{ holder_.swap(other_chain.holder_); }
void splice_after(iterator after_this, transform_multiallocation_chain &x, iterator before_b, iterator before_e, size_type n)
{ holder_.splice_after(after_this.base(), x.holder_, before_b.base(), before_e.base(), n); }
void incorporate_after(iterator after_this, pointer b, pointer before_e, size_type n)
{ holder_.incorporate_after(after_this.base(), b, before_e, n); }
*/
pointer pop_front()
{ return cast(this->MultiallocationChain::pop_front()); }
/*
bool empty() const
{ return holder_.empty(); }
iterator before_begin()
{ return iterator(holder_.before_begin()); }
*/
iterator begin()
{ return iterator(this->MultiallocationChain::begin()); }
/*
iterator end()
{ return iterator(holder_.end()); }
iterator last()
{ return iterator(holder_.last()); }
size_type size() const
{ return holder_.size(); }
void clear()
{ holder_.clear(); }
*/
iterator insert_after(iterator it, pointer m)
{ return iterator(this->MultiallocationChain::insert_after(it.base(), m)); }
static iterator iterator_to(const pointer &p)
{ return iterator(MultiallocationChain::iterator_to(p)); }
std::pair<pointer, pointer> extract_data()
{
std::pair<void_pointer, void_pointer> data(this->MultiallocationChain::extract_data());
return std::pair<pointer, pointer>(cast(data.first), cast(data.second));
}
/*
MultiallocationChain &extract_multiallocation_chain()
{ return holder_; }*/
};
}}}
// namespace container_detail {
// namespace container {
// namespace boost {
#include <boost/container/detail/config_end.hpp>
#endif //BOOST_CONTAINER_DETAIL_MULTIALLOCATION_CHAIN_HPP

View file

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

View file

@ -0,0 +1,399 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_DETAIL_NODE_ALLOC_HPP_
#define BOOST_CONTAINER_DETAIL_NODE_ALLOC_HPP_
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <utility>
#include <functional>
#include <boost/move/utility_core.hpp>
#include <boost/intrusive/options.hpp>
#include <boost/container/detail/version_type.hpp>
#include <boost/container/detail/type_traits.hpp>
#include <boost/container/detail/utilities.hpp>
#include <boost/container/allocator_traits.hpp>
#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/placement_new.hpp>
#include <boost/core/no_exceptions_support.hpp>
#ifndef BOOST_CONTAINER_PERFECT_FORWARDING
#include <boost/container/detail/preprocessor.hpp>
#endif
#include <boost/container/detail/algorithms.hpp>
namespace boost {
namespace container {
namespace container_detail {
template<class ValueCompare, class Node>
struct node_compare
: private ValueCompare
{
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 wrapped_value_compare &pred)
: wrapped_value_compare(pred)
{}
node_compare()
: wrapped_value_compare()
{}
wrapped_value_compare &value_comp()
{ return static_cast<wrapped_value_compare &>(*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 wrapped_value_compare::operator()(a.get_data(), b.get_data()); }
};
template<class A, class ICont>
struct node_alloc_holder
{
//If the intrusive container is an associative container, obtain the predicate, which will
//be of type node_compare<>. If not an associative container value_compare will be a "nat" type.
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, ICont,
value_compare, container_detail::nat) intrusive_value_compare;
//In that case obtain the value predicate from the node predicate via wrapped_value_compare
//if intrusive_value_compare is node_compare<>, nat otherwise
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, ICont,
wrapped_value_compare, container_detail::nat) value_compare;
typedef allocator_traits<A> allocator_traits_type;
typedef typename allocator_traits_type::value_type value_type;
typedef ICont intrusive_container;
typedef typename ICont::value_type Node;
typedef typename allocator_traits_type::template
portable_rebind_alloc<Node>::type NodeAlloc;
typedef allocator_traits<NodeAlloc> node_allocator_traits_type;
typedef container_detail::allocator_version_traits<NodeAlloc> node_allocator_version_traits_type;
typedef A ValAlloc;
typedef typename node_allocator_traits_type::pointer NodePtr;
typedef container_detail::scoped_deallocator<NodeAlloc> Deallocator;
typedef typename node_allocator_traits_type::size_type size_type;
typedef typename node_allocator_traits_type::difference_type difference_type;
typedef container_detail::integral_constant<unsigned, 1> allocator_v1;
typedef container_detail::integral_constant<unsigned, 2> allocator_v2;
typedef container_detail::integral_constant<unsigned,
boost::container::container_detail::
version<NodeAlloc>::value> alloc_version;
typedef typename ICont::iterator icont_iterator;
typedef typename ICont::const_iterator icont_citerator;
typedef allocator_destroyer<NodeAlloc> Destroyer;
typedef allocator_traits<NodeAlloc> NodeAllocTraits;
typedef allocator_version_traits<NodeAlloc> AllocVersionTraits;
private:
BOOST_COPYABLE_AND_MOVABLE(node_alloc_holder)
public:
//Constructors for sequence containers
node_alloc_holder()
: members_()
{}
explicit node_alloc_holder(const ValAlloc &a)
: members_(a)
{}
explicit node_alloc_holder(const node_alloc_holder &x)
: members_(NodeAllocTraits::select_on_container_copy_construction(x.node_alloc()))
{}
explicit node_alloc_holder(BOOST_RV_REF(node_alloc_holder) x)
: members_(boost::move(x.node_alloc()))
{ this->icont().swap(x.icont()); }
//Constructors for associative containers
explicit node_alloc_holder(const ValAlloc &a, const value_compare &c)
: members_(a, 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 value_compare &c)
: members_(c)
{}
//helpers for move assignments
explicit node_alloc_holder(BOOST_RV_REF(node_alloc_holder) x, const value_compare &c)
: members_(boost::move(x.node_alloc()), c)
{ this->icont().swap(x.icont()); }
void copy_assign_alloc(const node_alloc_holder &x)
{
container_detail::bool_<allocator_traits_type::propagate_on_container_copy_assignment::value> flag;
container_detail::assign_alloc( static_cast<NodeAlloc &>(this->members_)
, static_cast<const NodeAlloc &>(x.members_), flag);
}
void move_assign_alloc( node_alloc_holder &x)
{
container_detail::bool_<allocator_traits_type::propagate_on_container_move_assignment::value> flag;
container_detail::move_alloc( static_cast<NodeAlloc &>(this->members_)
, static_cast<NodeAlloc &>(x.members_), flag);
}
~node_alloc_holder()
{ this->clear(alloc_version()); }
size_type max_size() const
{ return allocator_traits_type::max_size(this->node_alloc()); }
NodePtr allocate_one()
{ return AllocVersionTraits::allocate_one(this->node_alloc()); }
void deallocate_one(const NodePtr &p)
{ AllocVersionTraits::deallocate_one(this->node_alloc(), p); }
#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
template<class ...Args>
NodePtr create_node(Args &&...args)
{
NodePtr p = this->allocate_one();
Deallocator node_deallocator(p, this->node_alloc());
allocator_traits<NodeAlloc>::construct
( this->node_alloc()
, container_detail::addressof(p->m_data), boost::forward<Args>(args)...);
node_deallocator.release();
//This does not throw
typedef typename Node::hook_type hook_type;
::new(static_cast<hook_type*>(container_detail::to_raw_pointer(p)), boost_container_new_t()) hook_type;
return (p);
}
#else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
#define BOOST_PP_LOCAL_MACRO(n) \
\
BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
NodePtr create_node(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
{ \
NodePtr p = this->allocate_one(); \
Deallocator node_deallocator(p, this->node_alloc()); \
allocator_traits<NodeAlloc>::construct \
(this->node_alloc(), container_detail::addressof(p->m_data) \
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \
node_deallocator.release(); \
typedef typename Node::hook_type hook_type; \
::new(static_cast<hook_type*>(container_detail::to_raw_pointer(p)), boost_container_new_t()) hook_type; \
return (p); \
} \
//!
#define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
#include BOOST_PP_LOCAL_ITERATE()
#endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
template<class It>
NodePtr create_node_from_it(const It &it)
{
NodePtr p = this->allocate_one();
Deallocator node_deallocator(p, this->node_alloc());
::boost::container::construct_in_place(this->node_alloc(), container_detail::addressof(p->m_data), it);
node_deallocator.release();
//This does not throw
typedef typename Node::hook_type hook_type;
::new(static_cast<hook_type*>(container_detail::to_raw_pointer(p)), boost_container_new_t()) hook_type;
return (p);
}
void destroy_node(const NodePtr &nodep)
{
allocator_traits<NodeAlloc>::destroy(this->node_alloc(), container_detail::to_raw_pointer(nodep));
this->deallocate_one(nodep);
}
void swap(node_alloc_holder &x)
{
this->icont().swap(x.icont());
container_detail::bool_<allocator_traits_type::propagate_on_container_swap::value> flag;
container_detail::swap_alloc(this->node_alloc(), x.node_alloc(), flag);
}
template<class FwdIterator, class Inserter>
void allocate_many_and_construct
(FwdIterator beg, difference_type n, Inserter inserter)
{
if(n){
typedef typename node_allocator_version_traits_type::multiallocation_chain multiallocation_chain;
//Try to allocate memory in a single block
typedef typename multiallocation_chain::iterator multialloc_iterator;
multiallocation_chain mem;
NodeAlloc &nalloc = this->node_alloc();
node_allocator_version_traits_type::allocate_individual(nalloc, n, mem);
multialloc_iterator itbeg(mem.begin()), itlast(mem.last());
mem.clear();
Node *p = 0;
BOOST_TRY{
Deallocator node_deallocator(NodePtr(), nalloc);
container_detail::scoped_destructor<NodeAlloc> sdestructor(nalloc, 0);
while(n--){
p = container_detail::to_raw_pointer(iterator_to_pointer(itbeg));
node_deallocator.set(p);
++itbeg;
//This can throw
boost::container::construct_in_place(nalloc, container_detail::addressof(p->m_data), beg);
sdestructor.set(p);
++beg;
//This does not throw
typedef typename Node::hook_type hook_type;
::new(static_cast<hook_type*>(p), boost_container_new_t()) hook_type;
//This can throw in some containers (predicate might throw).
//(sdestructor will destruct the node and node_deallocator will deallocate it in case of exception)
inserter(*p);
sdestructor.set(0);
}
sdestructor.release();
node_deallocator.release();
}
BOOST_CATCH(...){
mem.incorporate_after(mem.last(), &*itbeg, &*itlast, n);
node_allocator_version_traits_type::deallocate_individual(this->node_alloc(), mem);
BOOST_RETHROW
}
BOOST_CATCH_END
}
}
void clear(allocator_v1)
{ this->icont().clear_and_dispose(Destroyer(this->node_alloc())); }
void clear(allocator_v2)
{
typename NodeAlloc::multiallocation_chain chain;
allocator_destroyer_and_chain_builder<NodeAlloc> builder(this->node_alloc(), chain);
this->icont().clear_and_dispose(builder);
//BOOST_STATIC_ASSERT((::boost::has_move_emulation_enabled<typename NodeAlloc::multiallocation_chain>::value == true));
if(!chain.empty())
this->node_alloc().deallocate_individual(chain);
}
icont_iterator erase_range(const icont_iterator &first, const icont_iterator &last, allocator_v1)
{ return this->icont().erase_and_dispose(first, last, Destroyer(this->node_alloc())); }
icont_iterator erase_range(const icont_iterator &first, const icont_iterator &last, allocator_v2)
{
typedef typename NodeAlloc::multiallocation_chain multiallocation_chain;
NodeAlloc & nalloc = this->node_alloc();
multiallocation_chain chain;
allocator_destroyer_and_chain_builder<NodeAlloc> chain_builder(nalloc, chain);
icont_iterator ret_it = this->icont().erase_and_dispose(first, last, chain_builder);
nalloc.deallocate_individual(chain);
return ret_it;
}
template<class Key, class Comparator>
size_type erase_key(const Key& k, const Comparator &comp, allocator_v1)
{ return this->icont().erase_and_dispose(k, comp, Destroyer(this->node_alloc())); }
template<class Key, class Comparator>
size_type erase_key(const Key& k, const Comparator &comp, allocator_v2)
{
allocator_multialloc_chain_node_deallocator<NodeAlloc> chain_holder(this->node_alloc());
return this->icont().erase_and_dispose(k, comp, chain_holder.get_chain_builder());
}
protected:
struct cloner
{
cloner(node_alloc_holder &holder)
: m_holder(holder)
{}
NodePtr operator()(const Node &other) const
{ return m_holder.create_node(other.get_data()); }
node_alloc_holder &m_holder;
};
struct members_holder
: public NodeAlloc
{
private:
members_holder(const members_holder&);
members_holder & operator=(const members_holder&);
public:
members_holder()
: NodeAlloc(), m_icont()
{}
template<class ConvertibleToAlloc>
explicit members_holder(BOOST_FWD_REF(ConvertibleToAlloc) c2alloc)
: NodeAlloc(boost::forward<ConvertibleToAlloc>(c2alloc))
, m_icont()
{}
template<class ConvertibleToAlloc>
members_holder(BOOST_FWD_REF(ConvertibleToAlloc) c2alloc, const value_compare &c)
: NodeAlloc(boost::forward<ConvertibleToAlloc>(c2alloc))
, m_icont(typename ICont::value_compare(c))
{}
explicit members_holder(const value_compare &c)
: NodeAlloc()
, m_icont(typename ICont::value_compare(c))
{}
//The intrusive container
ICont m_icont;
};
ICont &non_const_icont() const
{ return const_cast<ICont&>(this->members_.m_icont); }
ICont &icont()
{ return this->members_.m_icont; }
const ICont &icont() const
{ return this->members_.m_icont; }
NodeAlloc &node_alloc()
{ return static_cast<NodeAlloc &>(this->members_); }
const NodeAlloc &node_alloc() const
{ return static_cast<const NodeAlloc &>(this->members_); }
members_holder members_;
};
} //namespace container_detail {
} //namespace container {
} //namespace boost {
#include <boost/container/detail/config_end.hpp>
#endif // BOOST_CONTAINER_DETAIL_NODE_ALLOC_HPP_

View file

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

View file

@ -0,0 +1,366 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_DETAIL_NODE_POOL_IMPL_HPP
#define BOOST_CONTAINER_DETAIL_NODE_POOL_IMPL_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/container_fwd.hpp>
#include <boost/container/detail/utilities.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/intrusive/set.hpp>
#include <boost/intrusive/slist.hpp>
#include <boost/container/detail/type_traits.hpp>
#include <boost/container/detail/math_functions.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/pool_common.hpp>
#include <boost/core/no_exceptions_support.hpp>
#include <boost/assert.hpp>
#include <cstddef>
namespace boost {
namespace container {
namespace container_detail {
template<class SegmentManagerBase>
class private_node_pool_impl
{
//Non-copyable
private_node_pool_impl();
private_node_pool_impl(const private_node_pool_impl &);
private_node_pool_impl &operator=(const private_node_pool_impl &);
//A node object will hold node_t when it's not allocated
public:
typedef typename SegmentManagerBase::void_pointer void_pointer;
typedef typename node_slist<void_pointer>::slist_hook_t slist_hook_t;
typedef typename node_slist<void_pointer>::node_t node_t;
typedef typename node_slist<void_pointer>::node_slist_t free_nodes_t;
typedef typename SegmentManagerBase::multiallocation_chain multiallocation_chain;
typedef typename SegmentManagerBase::size_type size_type;
private:
typedef typename bi::make_slist
< node_t, bi::base_hook<slist_hook_t>
, bi::linear<true>
, bi::constant_time_size<false> >::type blockslist_t;
public:
//!Segment manager typedef
typedef SegmentManagerBase segment_manager_base_type;
//!Constructor from a segment manager. Never throws
private_node_pool_impl(segment_manager_base_type *segment_mngr_base, size_type node_size, size_type nodes_per_block)
: m_nodes_per_block(nodes_per_block)
, m_real_node_size(lcm(node_size, size_type(alignment_of<node_t>::value)))
//General purpose allocator
, mp_segment_mngr_base(segment_mngr_base)
, m_blocklist()
, m_freelist()
//Debug node count
, m_allocated(0)
{}
//!Destructor. Deallocates all allocated blocks. Never throws
~private_node_pool_impl()
{ this->purge_blocks(); }
size_type get_real_num_node() const
{ return m_nodes_per_block; }
//!Returns the segment manager. Never throws
segment_manager_base_type* get_segment_manager_base()const
{ return container_detail::to_raw_pointer(mp_segment_mngr_base); }
void *allocate_node()
{ return this->priv_alloc_node(); }
//!Deallocates an array pointed by ptr. Never throws
void deallocate_node(void *ptr)
{ this->priv_dealloc_node(ptr); }
//!Allocates a singly linked list of n nodes ending in null pointer.
void allocate_nodes(const size_type n, multiallocation_chain &chain)
{
//Preallocate all needed blocks to fulfill the request
size_type cur_nodes = m_freelist.size();
if(cur_nodes < n){
this->priv_alloc_block(((n - cur_nodes) - 1)/m_nodes_per_block + 1);
}
//We just iterate the needed nodes to get the last we'll erase
typedef typename free_nodes_t::iterator free_iterator;
free_iterator before_last_new_it = m_freelist.before_begin();
for(size_type j = 0; j != n; ++j){
++before_last_new_it;
}
//Cache the first node of the allocated range before erasing
free_iterator first_node(m_freelist.begin());
free_iterator last_node (before_last_new_it);
//Erase the range. Since we already have the distance, this is O(1)
m_freelist.erase_after( m_freelist.before_begin()
, ++free_iterator(before_last_new_it)
, n);
//Now take the last erased node and just splice it in the end
//of the intrusive list that will be traversed by the multialloc iterator.
chain.incorporate_after(chain.before_begin(), &*first_node, &*last_node, n);
m_allocated += n;
}
void deallocate_nodes(multiallocation_chain &chain)
{
typedef typename multiallocation_chain::iterator iterator;
iterator it(chain.begin()), itend(chain.end());
while(it != itend){
void *pElem = &*it;
++it;
this->priv_dealloc_node(pElem);
}
}
//!Deallocates all the free blocks of memory. Never throws
void deallocate_free_blocks()
{
typedef typename free_nodes_t::iterator nodelist_iterator;
typename blockslist_t::iterator bit(m_blocklist.before_begin()),
it(m_blocklist.begin()),
itend(m_blocklist.end());
free_nodes_t backup_list;
nodelist_iterator backup_list_last = backup_list.before_begin();
//Execute the algorithm and get an iterator to the last value
size_type blocksize = get_rounded_size
(m_real_node_size*m_nodes_per_block, (size_type) alignment_of<node_t>::value);
while(it != itend){
//Collect all the nodes from the block pointed by it
//and push them in the list
free_nodes_t free_nodes;
nodelist_iterator last_it = free_nodes.before_begin();
const void *addr = get_block_from_hook(&*it, blocksize);
m_freelist.remove_and_dispose_if
(is_between(addr, blocksize), push_in_list(free_nodes, last_it));
//If the number of nodes is equal to m_nodes_per_block
//this means that the block can be deallocated
if(free_nodes.size() == m_nodes_per_block){
//Unlink the nodes
free_nodes.clear();
it = m_blocklist.erase_after(bit);
mp_segment_mngr_base->deallocate((void*)addr);
}
//Otherwise, insert them in the backup list, since the
//next "remove_if" does not need to check them again.
else{
//Assign the iterator to the last value if necessary
if(backup_list.empty() && !m_freelist.empty()){
backup_list_last = last_it;
}
//Transfer nodes. This is constant time.
backup_list.splice_after
( backup_list.before_begin()
, free_nodes
, free_nodes.before_begin()
, last_it
, free_nodes.size());
bit = it;
++it;
}
}
//We should have removed all the nodes from the free list
BOOST_ASSERT(m_freelist.empty());
//Now pass all the node to the free list again
m_freelist.splice_after
( m_freelist.before_begin()
, backup_list
, backup_list.before_begin()
, backup_list_last
, backup_list.size());
}
size_type num_free_nodes()
{ return m_freelist.size(); }
//!Deallocates all used memory. Precondition: all nodes allocated from this pool should
//!already be deallocated. Otherwise, undefined behaviour. Never throws
void purge_blocks()
{
//check for memory leaks
BOOST_ASSERT(m_allocated==0);
size_type blocksize = get_rounded_size
(m_real_node_size*m_nodes_per_block, (size_type)alignment_of<node_t>::value);
//We iterate though the NodeBlock list to free the memory
while(!m_blocklist.empty()){
void *addr = get_block_from_hook(&m_blocklist.front(), blocksize);
m_blocklist.pop_front();
mp_segment_mngr_base->deallocate((void*)addr);
}
//Just clear free node list
m_freelist.clear();
}
void swap(private_node_pool_impl &other)
{
BOOST_ASSERT(m_nodes_per_block == other.m_nodes_per_block);
BOOST_ASSERT(m_real_node_size == other.m_real_node_size);
std::swap(mp_segment_mngr_base, other.mp_segment_mngr_base);
m_blocklist.swap(other.m_blocklist);
m_freelist.swap(other.m_freelist);
std::swap(m_allocated, other.m_allocated);
}
private:
struct push_in_list
{
push_in_list(free_nodes_t &l, typename free_nodes_t::iterator &it)
: slist_(l), last_it_(it)
{}
void operator()(typename free_nodes_t::pointer p) const
{
slist_.push_front(*p);
if(slist_.size() == 1){ //Cache last element
++last_it_ = slist_.begin();
}
}
private:
free_nodes_t &slist_;
typename free_nodes_t::iterator &last_it_;
};
struct is_between
{
typedef typename free_nodes_t::value_type argument_type;
typedef bool result_type;
is_between(const void *addr, std::size_t size)
: beg_(static_cast<const char *>(addr)), end_(beg_+size)
{}
bool operator()(typename free_nodes_t::const_reference v) const
{
return (beg_ <= reinterpret_cast<const char *>(&v) &&
end_ > reinterpret_cast<const char *>(&v));
}
private:
const char * beg_;
const char * end_;
};
//!Allocates one node, using single segregated storage algorithm.
//!Never throws
node_t *priv_alloc_node()
{
//If there are no free nodes we allocate a new block
if (m_freelist.empty())
this->priv_alloc_block(1);
//We take the first free node
node_t *n = (node_t*)&m_freelist.front();
m_freelist.pop_front();
++m_allocated;
return n;
}
//!Deallocates one node, using single segregated storage algorithm.
//!Never throws
void priv_dealloc_node(void *pElem)
{
//We put the node at the beginning of the free node list
node_t * to_deallocate = static_cast<node_t*>(pElem);
m_freelist.push_front(*to_deallocate);
BOOST_ASSERT(m_allocated>0);
--m_allocated;
}
//!Allocates several blocks of nodes. Can throw
void priv_alloc_block(size_type num_blocks)
{
BOOST_ASSERT(num_blocks > 0);
size_type blocksize =
get_rounded_size(m_real_node_size*m_nodes_per_block, (size_type)alignment_of<node_t>::value);
BOOST_TRY{
for(size_type i = 0; i != num_blocks; ++i){
//We allocate a new NodeBlock and put it as first
//element in the free Node list
char *pNode = reinterpret_cast<char*>
(mp_segment_mngr_base->allocate(blocksize + sizeof(node_t)));
char *pBlock = pNode;
m_blocklist.push_front(get_block_hook(pBlock, blocksize));
//We initialize all Nodes in Node Block to insert
//them in the free Node list
for(size_type j = 0; j < m_nodes_per_block; ++j, pNode += m_real_node_size){
m_freelist.push_front(*new (pNode) node_t);
}
}
}
BOOST_CATCH(...){
//to-do: if possible, an efficient way to deallocate allocated blocks
BOOST_RETHROW
}
BOOST_CATCH_END
}
//!Deprecated, use deallocate_free_blocks
void deallocate_free_chunks()
{ this->deallocate_free_blocks(); }
//!Deprecated, use purge_blocks
void purge_chunks()
{ this->purge_blocks(); }
private:
//!Returns a reference to the block hook placed in the end of the block
static node_t & get_block_hook (void *block, size_type blocksize)
{
return *reinterpret_cast<node_t*>(reinterpret_cast<char*>(block) + blocksize);
}
//!Returns the starting address of the block reference to the block hook placed in the end of the block
void *get_block_from_hook (node_t *hook, size_type blocksize)
{
return (reinterpret_cast<char*>(hook) - blocksize);
}
private:
typedef typename boost::intrusive::pointer_traits
<void_pointer>::template rebind_pointer<segment_manager_base_type>::type segment_mngr_base_ptr_t;
const size_type m_nodes_per_block;
const size_type m_real_node_size;
segment_mngr_base_ptr_t mp_segment_mngr_base; //Segment manager
blockslist_t m_blocklist; //Intrusive container of blocks
free_nodes_t m_freelist; //Intrusive container of free nods
size_type m_allocated; //Used nodes for debugging
};
} //namespace container_detail {
} //namespace container {
} //namespace boost {
#include <boost/container/detail/config_end.hpp>
#endif //#ifndef BOOST_CONTAINER_DETAIL_ADAPTIVE_NODE_POOL_IMPL_HPP

View file

@ -0,0 +1,374 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2013.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_CONTAINER_DETAIL_PAIR_HPP
#define BOOST_CONTAINER_CONTAINER_DETAIL_PAIR_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/type_traits.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/type_traits.hpp>
#include <utility> //std::pair
#include <algorithm> //std::swap
#include <boost/move/utility_core.hpp>
#ifndef BOOST_CONTAINER_PERFECT_FORWARDING
#include <boost/container/detail/preprocessor.hpp>
#endif
namespace boost {
namespace container {
namespace container_detail {
template <class T1, class T2>
struct pair;
template <class T>
struct is_pair
{
static const bool value = false;
};
template <class T1, class T2>
struct is_pair< pair<T1, T2> >
{
static const bool value = true;
};
template <class T1, class T2>
struct is_pair< std::pair<T1, T2> >
{
static const bool value = true;
};
struct pair_nat;
struct piecewise_construct_t { };
static const piecewise_construct_t piecewise_construct = piecewise_construct_t();
/*
template <class T1, class T2>
struct pair
{
template <class U, class V> pair(pair<U, V>&& p);
template <class... Args1, class... Args2>
pair(piecewise_construct_t, tuple<Args1...> first_args,
tuple<Args2...> second_args);
template <class U, class V> pair& operator=(const pair<U, V>& p);
pair& operator=(pair&& p) noexcept(is_nothrow_move_assignable<T1>::value &&
is_nothrow_move_assignable<T2>::value);
template <class U, class V> pair& operator=(pair<U, V>&& p);
void swap(pair& p) noexcept(noexcept(swap(first, p.first)) &&
noexcept(swap(second, p.second)));
};
template <class T1, class T2> bool operator==(const pair<T1,T2>&, const pair<T1,T2>&);
template <class T1, class T2> bool operator!=(const pair<T1,T2>&, const pair<T1,T2>&);
template <class T1, class T2> bool operator< (const pair<T1,T2>&, const pair<T1,T2>&);
template <class T1, class T2> bool operator> (const pair<T1,T2>&, const pair<T1,T2>&);
template <class T1, class T2> bool operator>=(const pair<T1,T2>&, const pair<T1,T2>&);
template <class T1, class T2> bool operator<=(const pair<T1,T2>&, const pair<T1,T2>&);
*/
template <class T1, class T2>
struct pair
{
private:
BOOST_COPYABLE_AND_MOVABLE(pair)
public:
typedef T1 first_type;
typedef T2 second_type;
T1 first;
T2 second;
//Default constructor
pair()
: first(), second()
{}
//pair copy assignment
pair(const pair& x)
: first(x.first), second(x.second)
{}
//pair move constructor
pair(BOOST_RV_REF(pair) p)
: first(::boost::move(p.first)), second(::boost::move(p.second))
{}
template <class D, class S>
pair(const pair<D, S> &p)
: first(p.first), second(p.second)
{}
template <class D, class S>
pair(BOOST_RV_REF_BEG pair<D, S> BOOST_RV_REF_END p)
: first(::boost::move(p.first)), second(::boost::move(p.second))
{}
//pair from two values
pair(const T1 &t1, const T2 &t2)
: first(t1)
, second(t2)
{}
template<class U, class V>
pair(BOOST_FWD_REF(U) u, BOOST_FWD_REF(V) v)
: first(::boost::forward<U>(u))
, second(::boost::forward<V>(v))
{}
//And now compatibility with std::pair
pair(const std::pair<T1, T2>& x)
: first(x.first), second(x.second)
{}
template <class D, class S>
pair(const std::pair<D, S>& p)
: first(p.first), second(p.second)
{}
pair(BOOST_RV_REF_BEG std::pair<T1, T2> BOOST_RV_REF_END p)
: first(::boost::move(p.first)), second(::boost::move(p.second))
{}
template <class D, class S>
pair(BOOST_RV_REF_BEG std::pair<D, S> BOOST_RV_REF_END p)
: first(::boost::move(p.first)), second(::boost::move(p.second))
{}
//piecewise_construct missing
//template <class U, class V> pair(pair<U, V>&& p);
//template <class... Args1, class... Args2>
// pair(piecewise_construct_t, tuple<Args1...> first_args,
// tuple<Args2...> second_args);
/*
//Variadic versions
template<class U>
pair(BOOST_CONTAINER_PP_PARAM(U, u), typename container_detail::disable_if
< container_detail::is_pair< typename container_detail::remove_ref_const<U>::type >, pair_nat>::type* = 0)
: first(::boost::forward<U>(u))
, second()
{}
#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
template<class U, class V, class ...Args>
pair(U &&u, V &&v)
: first(::boost::forward<U>(u))
, second(::boost::forward<V>(v), ::boost::forward<Args>(args)...)
{}
#else
#define BOOST_PP_LOCAL_MACRO(n) \
template<class U, BOOST_PP_ENUM_PARAMS(n, class P)> \
pair(BOOST_CONTAINER_PP_PARAM(U, u) \
,BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
: first(::boost::forward<U>(u)) \
, second(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)) \
{} \
//!
#define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
#include BOOST_PP_LOCAL_ITERATE()
#endif
*/
//pair copy assignment
pair& operator=(BOOST_COPY_ASSIGN_REF(pair) p)
{
first = p.first;
second = p.second;
return *this;
}
//pair move assignment
pair& operator=(BOOST_RV_REF(pair) p)
{
first = ::boost::move(p.first);
second = ::boost::move(p.second);
return *this;
}
template <class D, class S>
typename ::boost::container::container_detail::enable_if_c
< !(::boost::container::container_detail::is_same<T1, D>::value &&
::boost::container::container_detail::is_same<T2, S>::value)
, pair &>::type
operator=(const pair<D, S>&p)
{
first = p.first;
second = p.second;
return *this;
}
template <class D, class S>
typename ::boost::container::container_detail::enable_if_c
< !(::boost::container::container_detail::is_same<T1, D>::value &&
::boost::container::container_detail::is_same<T2, S>::value)
, pair &>::type
operator=(BOOST_RV_REF_BEG pair<D, S> BOOST_RV_REF_END p)
{
first = ::boost::move(p.first);
second = ::boost::move(p.second);
return *this;
}
//std::pair copy assignment
pair& operator=(const std::pair<T1, T2> &p)
{
first = p.first;
second = p.second;
return *this;
}
template <class D, class S>
pair& operator=(const std::pair<D, S> &p)
{
first = ::boost::move(p.first);
second = ::boost::move(p.second);
return *this;
}
//std::pair move assignment
pair& operator=(BOOST_RV_REF_BEG std::pair<T1, T2> BOOST_RV_REF_END p)
{
first = ::boost::move(p.first);
second = ::boost::move(p.second);
return *this;
}
template <class D, class S>
pair& operator=(BOOST_RV_REF_BEG std::pair<D, S> BOOST_RV_REF_END p)
{
first = ::boost::move(p.first);
second = ::boost::move(p.second);
return *this;
}
//swap
void swap(pair& p)
{
using std::swap;
swap(this->first, p.first);
swap(this->second, p.second);
}
};
template <class T1, class T2>
inline bool operator==(const pair<T1,T2>& x, const pair<T1,T2>& y)
{ return static_cast<bool>(x.first == y.first && x.second == y.second); }
template <class T1, class T2>
inline bool operator< (const pair<T1,T2>& x, const pair<T1,T2>& y)
{ return static_cast<bool>(x.first < y.first ||
(!(y.first < x.first) && x.second < y.second)); }
template <class T1, class T2>
inline bool operator!=(const pair<T1,T2>& x, const pair<T1,T2>& y)
{ return static_cast<bool>(!(x == y)); }
template <class T1, class T2>
inline bool operator> (const pair<T1,T2>& x, const pair<T1,T2>& y)
{ return y < x; }
template <class T1, class T2>
inline bool operator>=(const pair<T1,T2>& x, const pair<T1,T2>& y)
{ return static_cast<bool>(!(x < y)); }
template <class T1, class T2>
inline bool operator<=(const pair<T1,T2>& x, const pair<T1,T2>& y)
{ return static_cast<bool>(!(y < x)); }
template <class T1, class T2>
inline pair<T1, T2> make_pair(T1 x, T2 y)
{ return pair<T1, T2>(x, y); }
template <class T1, class T2>
inline void swap(pair<T1, T2>& x, pair<T1, T2>& y)
{
swap(x.first, y.first);
swap(x.second, y.second);
}
} //namespace container_detail {
} //namespace container {
//Without this specialization recursive flat_(multi)map instantiation fails
//because is_enum needs to instantiate the recursive pair, leading to a compilation error).
//This breaks the cycle clearly stating that pair is not an enum avoiding any instantiation.
template<class T>
struct is_enum;
template<class T, class U>
struct is_enum< ::boost::container::container_detail::pair<T, U> >
{
static const bool value = false;
};
template <class T>
struct is_class;
//This specialization is needed to avoid instantiation of pair in
//is_class, and allow recursive maps.
template <class T1, class T2>
struct is_class< ::boost::container::container_detail::pair<T1, T2> >
{
static const bool value = true;
};
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
template<class T1, class T2>
struct has_move_emulation_enabled< ::boost::container::container_detail::pair<T1, T2> >
{
static const bool value = true;
};
#endif
namespace move_detail{
template<class T>
struct is_class_or_union;
template <class T1, class T2>
struct is_class_or_union< ::boost::container::container_detail::pair<T1, T2> >
//This specialization is needed to avoid instantiation of pair in
//is_class, and allow recursive maps.
{
static const bool value = true;
};
} //namespace move_detail{
} //namespace boost {
#include <boost/container/detail/config_end.hpp>
#endif //#ifndef BOOST_CONTAINER_DETAIL_PAIR_HPP

View file

@ -0,0 +1,27 @@
///////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2014-2014. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_DETAIL_PLACEMENT_NEW_HPP
#define BOOST_CONTAINER_DETAIL_PLACEMENT_NEW_HPP
#if defined(_MSC_VER)
# pragma once
#endif
struct boost_container_new_t{};
//avoid including <new>
inline void *operator new(std::size_t, void *p, boost_container_new_t)
{ return p; }
inline void operator delete(void *, void *, boost_container_new_t)
{}
#endif //BOOST_CONTAINER_DETAIL_PLACEMENT_NEW_HPP

View file

@ -0,0 +1,53 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_DETAIL_POOL_COMMON_HPP
#define BOOST_CONTAINER_DETAIL_POOL_COMMON_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/intrusive/slist.hpp>
namespace boost {
namespace container {
namespace container_detail {
template<class VoidPointer>
struct node_slist
{
//This hook will be used to chain the individual nodes
typedef typename bi::make_slist_base_hook
<bi::void_pointer<VoidPointer>, bi::link_mode<bi::normal_link> >::type slist_hook_t;
//A node object will hold node_t when it's not allocated
typedef slist_hook_t node_t;
typedef typename bi::make_slist
<node_t, bi::linear<true>, bi::cache_last<true>, bi::base_hook<slist_hook_t> >::type node_slist_t;
};
template<class T>
struct is_stateless_segment_manager
{
static const bool value = false;
};
} //namespace container_detail {
} //namespace container {
} //namespace boost {
#include <boost/container/detail/config_end.hpp>
#endif //#ifndef BOOST_CONTAINER_DETAIL_ADAPTIVE_NODE_POOL_IMPL_HPP

View file

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

View file

@ -0,0 +1,228 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2008-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_DETAIL_PREPROCESSOR_HPP
#define BOOST_CONTAINER_DETAIL_PREPROCESSOR_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/move/utility_core.hpp>
#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
//#error "This file is not needed when perfect forwarding is available"
#endif //BOOST_CONTAINER_PERFECT_FORWARDING
#include <boost/preprocessor/iteration/local.hpp>
#include <boost/preprocessor/punctuation/paren_if.hpp>
#include <boost/preprocessor/punctuation/comma_if.hpp>
#include <boost/preprocessor/control/expr_if.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/repetition/enum.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
#include <boost/preprocessor/repetition/enum_trailing.hpp>
#include <boost/preprocessor/repetition/repeat.hpp>
#include <boost/preprocessor/arithmetic/sub.hpp>
#include <boost/preprocessor/arithmetic/add.hpp>
#include <boost/preprocessor/iteration/iterate.hpp>
#define BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS 10
//Note:
//We define template parameters as const references to
//be able to bind temporaries. After that we will un-const them.
//This cast is ugly but it is necessary until "perfect forwarding"
//is achieved in C++0x. Meanwhile, if we want to be able to
//bind rvalues with non-const references, we have to be ugly
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
#define BOOST_CONTAINER_PP_PARAM_LIST(z, n, data) \
BOOST_PP_CAT(P, n) && BOOST_PP_CAT(p, n) \
//!
#else
#define BOOST_CONTAINER_PP_PARAM_LIST(z, n, data) \
const BOOST_PP_CAT(P, n) & BOOST_PP_CAT(p, n) \
//!
#endif //#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
#define BOOST_CONTAINER_PP_CONST_REF_PARAM_LIST_Q(z, n, Data) \
const BOOST_PP_CAT(Q, n) & BOOST_PP_CAT(q, n) \
//!
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
#define BOOST_CONTAINER_PP_PARAM(U, u) \
U && u \
//!
#else
#define BOOST_CONTAINER_PP_PARAM(U, u) \
const U & u \
//!
#endif //#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
#define BOOST_CONTAINER_PP_PARAM_INIT(z, n, data) \
BOOST_PP_CAT(m_p, n) (::boost::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(p, n) )) \
//!
#else //BOOST_NO_CXX11_RVALUE_REFERENCES
#define BOOST_CONTAINER_PP_PARAM_INIT(z, n, data) \
BOOST_PP_CAT(m_p, n) (const_cast<BOOST_PP_CAT(P, n) &>(BOOST_PP_CAT(p, n))) \
//!
#endif //#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
#if defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
namespace boost {
namespace container {
namespace container_detail {
template<class T>
struct ref_holder;
template<class T>
struct ref_holder<T &>
{
explicit ref_holder(T &t)
: t_(t)
{}
T &t_;
T & get() { return t_; }
};
template<class T>
struct ref_holder<const T>
{
explicit ref_holder(const T &t)
: t_(t)
{}
const T &t_;
const T & get() { return t_; }
};
template<class T>
struct ref_holder<const T &&>
{
explicit ref_holder(const T &t)
: t_(t)
{}
const T &t_;
const T & get() { return t_; }
};
template<class T>
struct ref_holder
{
explicit ref_holder(T &&t)
: t_(t)
{}
T &t_;
T && get() { return ::boost::move(t_); }
};
template<class T>
struct ref_holder<T &&>
{
explicit ref_holder(T &&t)
: t_(t)
{}
T &t_;
T && get() { return ::boost::move(t_); }
};
} //namespace container_detail {
} //namespace container {
} //namespace boost {
#define BOOST_CONTAINER_PP_PARAM_DEFINE(z, n, data) \
::boost::container::container_detail::ref_holder<BOOST_PP_CAT(P, n)> BOOST_PP_CAT(m_p, n); \
//!
#else //BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG
#define BOOST_CONTAINER_PP_PARAM_DEFINE(z, n, data) \
BOOST_PP_CAT(P, n) && BOOST_PP_CAT(m_p, n); \
//!
#endif //defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
#else //BOOST_NO_CXX11_RVALUE_REFERENCES
#define BOOST_CONTAINER_PP_PARAM_DEFINE(z, n, data) \
BOOST_PP_CAT(P, n) & BOOST_PP_CAT(m_p, n); \
//!
#endif //#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
#define BOOST_CONTAINER_PP_MEMBER_FORWARD(z, n, data) BOOST_PP_CAT(this->m_p, n).get() \
//!
#else //!defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
#define BOOST_CONTAINER_PP_MEMBER_FORWARD(z, n, data) \
::boost::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(this->m_p, n) ) \
//!
#endif //!defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
#define BOOST_CONTAINER_PP_PARAM_INC(z, n, data) \
BOOST_PP_CAT(++this->m_p, n) \
//!
#define BOOST_CONTAINER_PP_IDENTITY(z, n, data) data
#define BOOST_CONTAINER_PP_PARAM_FORWARD(z, n, data) \
::boost::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(p, n) ) \
//!
#define BOOST_CONTAINER_PP_DECLVAL(z, n, data) \
::boost::move_detail::declval< BOOST_PP_CAT(P, n) >() \
//!
#define BOOST_CONTAINER_PP_MEMBER_IT_FORWARD(z, n, data) \
BOOST_PP_CAT(*this->m_p, n) \
//!
#define BOOST_CONTAINER_PP_TEMPLATE_PARAM_VOID_DEFAULT(z, n, data) \
BOOST_PP_CAT(class P, n) = void \
//!
#define BOOST_CONTAINER_PP_TEMPLATE_PARAM_WITH_DEFAULT(z, n, default_type) \
BOOST_PP_CAT(class P, n) = default_type \
//!
#define BOOST_CONTAINER_PP_STATIC_PARAM_REF_DECLARE(z, n, data) \
static BOOST_PP_CAT(P, n) & BOOST_PP_CAT(p, n); \
//!
#define BOOST_CONTAINER_PP_PARAM_PASS(z, n, data) \
BOOST_PP_CAT(p, n) \
//!
#define BOOST_CONTAINER_PP_FWD_TYPE(z, n, data) \
typename ::boost::move_detail::forward_type< BOOST_PP_CAT(P, n) >::type \
//!
#include <boost/container/detail/config_end.hpp>
//#else
//#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
//#error "This file is not needed when perfect forwarding is available"
//#endif //BOOST_CONTAINER_PERFECT_FORWARDING
#endif //#ifndef BOOST_CONTAINER_DETAIL_PREPROCESSOR_HPP

View file

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

View file

@ -0,0 +1,59 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2014-2014. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_DETAIL_STD_FWD_HPP
#define BOOST_CONTAINER_DETAIL_STD_FWD_HPP
#if defined(_MSC_VER)
# pragma once
#endif
//////////////////////////////////////////////////////////////////////////////
// Standard predeclarations
//////////////////////////////////////////////////////////////////////////////
#if defined(__clang__) && defined(_LIBCPP_VERSION)
#define BOOST_CONTAINER_CLANG_INLINE_STD_NS
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wc++11-extensions"
#define BOOST_CONTAINER_STD_NS_BEG _LIBCPP_BEGIN_NAMESPACE_STD
#define BOOST_CONTAINER_STD_NS_END _LIBCPP_END_NAMESPACE_STD
#else
#define BOOST_CONTAINER_STD_NS_BEG namespace std{
#define BOOST_CONTAINER_STD_NS_END }
#endif
BOOST_CONTAINER_STD_NS_BEG
template<class T>
class allocator;
template<class T>
struct less;
template<class T1, class T2>
struct pair;
template<class T>
struct char_traits;
struct input_iterator_tag;
struct forward_iterator_tag;
struct bidirectional_iterator_tag;
struct random_access_iterator_tag;
BOOST_CONTAINER_STD_NS_END
#ifdef BOOST_CONTAINER_CLANG_INLINE_STD_NS
#pragma GCC diagnostic pop
#undef BOOST_CONTAINER_CLANG_INLINE_STD_NS
#endif //BOOST_CONTAINER_CLANG_INLINE_STD_NS
#endif //#ifndef BOOST_CONTAINER_DETAIL_STD_FWD_HPP

View file

@ -0,0 +1,177 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2013.
// (C) Copyright Gennaro Prota 2003 - 2004.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_DETAIL_TRANSFORM_ITERATORS_HPP
#define BOOST_CONTAINER_DETAIL_TRANSFORM_ITERATORS_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/detail/type_traits.hpp>
#include <iterator>
namespace boost {
namespace container {
template <class PseudoReference>
struct operator_arrow_proxy
{
operator_arrow_proxy(const PseudoReference &px)
: m_value(px)
{}
typedef PseudoReference element_type;
PseudoReference* operator->() const { return &m_value; }
mutable PseudoReference m_value;
};
template <class T>
struct operator_arrow_proxy<T&>
{
operator_arrow_proxy(T &px)
: m_value(px)
{}
typedef T element_type;
T* operator->() const { return const_cast<T*>(&m_value); }
T &m_value;
};
template <class Iterator, class UnaryFunction>
class transform_iterator
: public UnaryFunction
, public std::iterator
< typename Iterator::iterator_category
, typename container_detail::remove_reference<typename UnaryFunction::result_type>::type
, typename Iterator::difference_type
, operator_arrow_proxy<typename UnaryFunction::result_type>
, typename UnaryFunction::result_type>
{
public:
explicit transform_iterator(const Iterator &it, const UnaryFunction &f = UnaryFunction())
: UnaryFunction(f), m_it(it)
{}
explicit transform_iterator()
: UnaryFunction(), m_it()
{}
//Constructors
transform_iterator& operator++()
{ increment(); return *this; }
transform_iterator operator++(int)
{
transform_iterator result (*this);
increment();
return result;
}
friend bool operator== (const transform_iterator& i, const transform_iterator& i2)
{ return i.equal(i2); }
friend bool operator!= (const transform_iterator& i, const transform_iterator& i2)
{ return !(i == i2); }
/*
friend bool operator> (const transform_iterator& i, const transform_iterator& i2)
{ return i2 < i; }
friend bool operator<= (const transform_iterator& i, const transform_iterator& i2)
{ return !(i > i2); }
friend bool operator>= (const transform_iterator& i, const transform_iterator& i2)
{ return !(i < i2); }
*/
friend typename Iterator::difference_type operator- (const transform_iterator& i, const transform_iterator& i2)
{ return i2.distance_to(i); }
//Arithmetic
transform_iterator& operator+=(typename Iterator::difference_type off)
{ this->advance(off); return *this; }
transform_iterator operator+(typename Iterator::difference_type off) const
{
transform_iterator other(*this);
other.advance(off);
return other;
}
friend transform_iterator operator+(typename Iterator::difference_type off, const transform_iterator& right)
{ return right + off; }
transform_iterator& operator-=(typename Iterator::difference_type off)
{ this->advance(-off); return *this; }
transform_iterator operator-(typename Iterator::difference_type off) const
{ return *this + (-off); }
typename UnaryFunction::result_type operator*() const
{ return dereference(); }
operator_arrow_proxy<typename UnaryFunction::result_type>
operator->() const
{ return operator_arrow_proxy<typename UnaryFunction::result_type>(dereference()); }
Iterator & base()
{ return m_it; }
const Iterator & base() const
{ return m_it; }
private:
Iterator m_it;
void increment()
{ ++m_it; }
void decrement()
{ --m_it; }
bool equal(const transform_iterator &other) const
{ return m_it == other.m_it; }
bool less(const transform_iterator &other) const
{ return other.m_it < m_it; }
typename UnaryFunction::result_type dereference() const
{ return UnaryFunction::operator()(*m_it); }
void advance(typename Iterator::difference_type n)
{ std::advance(m_it, n); }
typename Iterator::difference_type distance_to(const transform_iterator &other)const
{ return std::distance(other.m_it, m_it); }
};
template <class Iterator, class UnaryFunc>
transform_iterator<Iterator, UnaryFunc>
make_transform_iterator(Iterator it, UnaryFunc fun)
{
return transform_iterator<Iterator, UnaryFunc>(it, fun);
}
} //namespace container {
} //namespace boost {
#include <boost/container/detail/config_end.hpp>
#endif //#ifndef BOOST_CONTAINER_DETAIL_TRANSFORM_ITERATORS_HPP

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,237 @@
//////////////////////////////////////////////////////////////////////////////
// (C) Copyright John Maddock 2000.
// (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.
//
// The alignment_of implementation comes from John Maddock's boost::alignment_of code
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_CONTAINER_DETAIL_TYPE_TRAITS_HPP
#define BOOST_CONTAINER_CONTAINER_DETAIL_TYPE_TRAITS_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
namespace boost {
namespace container {
namespace container_detail {
struct nat{};
template <typename U>
struct LowPriorityConversion
{
// Convertible from T with user-defined-conversion rank.
LowPriorityConversion(const U&) { }
};
//boost::alignment_of yields to 10K lines of preprocessed code, so we
//need an alternative
template <typename T> struct alignment_of;
template <typename T>
struct alignment_of_hack
{
char c;
T t;
alignment_of_hack();
};
template <unsigned A, unsigned S>
struct alignment_logic
{
enum{ value = A < S ? A : S };
};
template< typename T >
struct alignment_of
{
enum{ value = alignment_logic
< sizeof(alignment_of_hack<T>) - sizeof(T)
, sizeof(T)>::value };
};
//This is not standard, but should work with all compilers
union max_align
{
char char_;
short short_;
int int_;
long long_;
#ifdef BOOST_HAS_LONG_LONG
long long long_long_;
#endif
float float_;
double double_;
long double long_double_;
void * void_ptr_;
};
template<class T>
struct remove_reference
{
typedef T type;
};
template<class T>
struct remove_reference<T&>
{
typedef T type;
};
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template<class T>
struct remove_reference<T&&>
{
typedef T type;
};
#else
} // namespace container_detail {
} //namespace container {
template<class T>
class rv;
namespace container {
namespace container_detail {
template<class T>
struct remove_reference< ::boost::rv<T> >
{
typedef T type;
};
#endif
template<class T>
struct is_reference
{
enum { value = false };
};
template<class T>
struct is_reference<T&>
{
enum { value = true };
};
template<class T>
struct is_pointer
{
enum { value = false };
};
template<class T>
struct is_pointer<T*>
{
enum { value = true };
};
template <typename T>
struct add_reference
{
typedef T& type;
};
template<class T>
struct add_reference<T&>
{
typedef T& type;
};
template<>
struct add_reference<void>
{
typedef nat &type;
};
template<>
struct add_reference<const void>
{
typedef const nat &type;
};
template <class T>
struct add_const_reference
{ typedef const T &type; };
template <class T>
struct add_const_reference<T&>
{ typedef T& type; };
template <class T>
struct add_const
{ typedef const T type; };
template <typename T, typename U>
struct is_same
{
typedef char yes_type;
struct no_type
{
char padding[8];
};
template <typename V>
static yes_type is_same_tester(V*, V*);
static no_type is_same_tester(...);
static T *t;
static U *u;
static const bool value = sizeof(yes_type) == sizeof(is_same_tester(t,u));
};
template<class T>
struct remove_const
{
typedef T type;
};
template<class T>
struct remove_const< const T>
{
typedef T type;
};
template<class T>
struct remove_ref_const
{
typedef typename remove_const< typename remove_reference<T>::type >::type type;
};
template <class T>
struct make_unsigned
{
typedef T type;
};
template <> struct make_unsigned<bool> {};
template <> struct make_unsigned<signed char> {typedef unsigned char type;};
template <> struct make_unsigned<signed short> {typedef unsigned short type;};
template <> struct make_unsigned<signed int> {typedef unsigned int type;};
template <> struct make_unsigned<signed long> {typedef unsigned long type;};
#ifdef BOOST_HAS_LONG_LONG
template <> struct make_unsigned<signed long long> {typedef unsigned long long type;};
#endif
} // namespace container_detail
} //namespace container {
} //namespace boost {
#include <boost/container/detail/config_end.hpp>
#endif //#ifndef BOOST_CONTAINER_CONTAINER_DETAIL_TYPE_TRAITS_HPP

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,45 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2013.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_DETAIL_VALUE_INIT_HPP
#define BOOST_CONTAINER_DETAIL_VALUE_INIT_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
namespace boost {
namespace container {
namespace container_detail {
template<class T>
struct value_init
{
value_init()
: m_t()
{}
operator T &() { return m_t; }
T m_t;
};
} //namespace container_detail {
} //namespace container {
} //namespace boost {
#include <boost/container/detail/config_end.hpp>
#endif //#ifndef BOOST_CONTAINER_DETAIL_VALUE_INIT_HPP

View file

@ -0,0 +1,154 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2008-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP
#define BOOST_CONTAINER_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/detail/type_traits.hpp>
#include <cstddef> //std::size_t
namespace boost {
namespace container {
namespace container_detail {
template<typename... Values>
class tuple;
template<> class tuple<>
{};
template<typename Head, typename... Tail>
class tuple<Head, Tail...>
: private tuple<Tail...>
{
typedef tuple<Tail...> inherited;
public:
tuple() { }
// implicit copy-constructor is okay
// Construct tuple from separate arguments.
tuple(typename add_const_reference<Head>::type v,
typename add_const_reference<Tail>::type... vtail)
: inherited(vtail...), m_head(v)
{}
// Construct tuple from another tuple.
template<typename... VValues>
tuple(const tuple<VValues...>& other)
: m_head(other.head()), inherited(other.tail())
{}
template<typename... VValues>
tuple& operator=(const tuple<VValues...>& other)
{
m_head = other.head();
tail() = other.tail();
return this;
}
typename add_reference<Head>::type head() { return m_head; }
typename add_reference<const Head>::type head() const { return m_head; }
inherited& tail() { return *this; }
const inherited& tail() const { return *this; }
protected:
Head m_head;
};
template<typename... Values>
tuple<Values&&...> tie_forward(Values&&... values)
{ return tuple<Values&&...>(values...); }
template<int I, typename Tuple>
struct tuple_element;
template<int I, typename Head, typename... Tail>
struct tuple_element<I, tuple<Head, Tail...> >
{
typedef typename tuple_element<I-1, tuple<Tail...> >::type type;
};
template<typename Head, typename... Tail>
struct tuple_element<0, tuple<Head, Tail...> >
{
typedef Head type;
};
template<int I, typename Tuple>
class get_impl;
template<int I, typename Head, typename... Values>
class get_impl<I, tuple<Head, Values...> >
{
typedef typename tuple_element<I-1, tuple<Values...> >::type Element;
typedef get_impl<I-1, tuple<Values...> > Next;
public:
typedef typename add_reference<Element>::type type;
typedef typename add_const_reference<Element>::type const_type;
static type get(tuple<Head, Values...>& t) { return Next::get(t.tail()); }
static const_type get(const tuple<Head, Values...>& t) { return Next::get(t.tail()); }
};
template<typename Head, typename... Values>
class get_impl<0, tuple<Head, Values...> >
{
public:
typedef typename add_reference<Head>::type type;
typedef typename add_const_reference<Head>::type const_type;
static type get(tuple<Head, Values...>& t) { return t.head(); }
static const_type get(const tuple<Head, Values...>& t){ return t.head(); }
};
template<int I, typename... Values>
typename get_impl<I, tuple<Values...> >::type get(tuple<Values...>& t)
{ return get_impl<I, tuple<Values...> >::get(t); }
template<int I, typename... Values>
typename get_impl<I, tuple<Values...> >::const_type get(const tuple<Values...>& t)
{ return get_impl<I, tuple<Values...> >::get(t); }
////////////////////////////////////////////////////
// Builds an index_tuple<0, 1, 2, ..., Num-1>, that will
// be used to "unpack" into comma-separated values
// in a function call.
////////////////////////////////////////////////////
template<int... Indexes>
struct index_tuple{};
template<std::size_t Num, typename Tuple = index_tuple<> >
struct build_number_seq;
template<std::size_t Num, int... Indexes>
struct build_number_seq<Num, index_tuple<Indexes...> >
: build_number_seq<Num - 1, index_tuple<Indexes..., sizeof...(Indexes)> >
{};
template<int... Indexes>
struct build_number_seq<0, index_tuple<Indexes...> >
{ typedef index_tuple<Indexes...> type; };
}}} //namespace boost { namespace container { namespace container_detail {
#include <boost/container/detail/config_end.hpp>
#endif //#ifndef BOOST_CONTAINER_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP

View file

@ -0,0 +1,103 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
//
// This code comes from N1953 document by Howard E. Hinnant
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_DETAIL_VERSION_TYPE_HPP
#define BOOST_CONTAINER_DETAIL_VERSION_TYPE_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/type_traits.hpp>
namespace boost{
namespace container {
namespace container_detail {
//using namespace boost;
template <class T, unsigned V>
struct version_type
: public container_detail::integral_constant<unsigned, V>
{
typedef T type;
version_type(const version_type<T, 0>&);
};
namespace impl{
template <class T,
bool = container_detail::is_convertible<version_type<T, 0>, typename T::version>::value>
struct extract_version
{
static const unsigned value = 1;
};
template <class T>
struct extract_version<T, true>
{
static const unsigned value = T::version::value;
};
template <class T>
struct has_version
{
private:
struct two {char _[2];};
template <class U> static two test(...);
template <class U> static char test(const typename U::version*);
public:
static const bool value = sizeof(test<T>(0)) == 1;
void dummy(){}
};
template <class T, bool = has_version<T>::value>
struct version
{
static const unsigned value = 1;
};
template <class T>
struct version<T, true>
{
static const unsigned value = extract_version<T>::value;
};
} //namespace impl
template <class T>
struct version
: public container_detail::integral_constant<unsigned, impl::version<T>::value>
{};
template<class T, unsigned N>
struct is_version
{
static const bool value =
is_same< typename version<T>::type, integral_constant<unsigned, N> >::value;
};
} //namespace container_detail {
} //namespace container {
} //namespace boost{
#include <boost/container/detail/config_end.hpp>
#endif //#define BOOST_CONTAINER_DETAIL_VERSION_TYPE_HPP

View file

@ -0,0 +1,72 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_DETAIL_WORKAROUND_HPP
#define BOOST_CONTAINER_DETAIL_WORKAROUND_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)\
&& !defined(BOOST_INTERPROCESS_DISABLE_VARIADIC_TMPL)
#define BOOST_CONTAINER_PERFECT_FORWARDING
#endif
#if defined(BOOST_NO_CXX11_NOEXCEPT)
#if defined(BOOST_MSVC)
#define BOOST_CONTAINER_NOEXCEPT throw()
#else
#define BOOST_CONTAINER_NOEXCEPT
#endif
#define BOOST_CONTAINER_NOEXCEPT_IF(x)
#else
#define BOOST_CONTAINER_NOEXCEPT noexcept
#define BOOST_CONTAINER_NOEXCEPT_IF(x) noexcept(x)
#endif
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && defined(__GXX_EXPERIMENTAL_CXX0X__)\
&& (__GNUC__*10000 + __GNUC_MINOR__*100 + __GNUC_PATCHLEVEL__ < 40700)
#define BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST
#endif
#if !defined(BOOST_FALLTHOUGH)
#define BOOST_CONTAINER_FALLTHOUGH
#else
#define BOOST_CONTAINER_FALLTHOUGH BOOST_FALLTHOUGH;
#endif
//Macros for documentation purposes. For code, expands to the argument
#define BOOST_CONTAINER_IMPDEF(TYPE) TYPE
#define BOOST_CONTAINER_SEEDOC(TYPE) TYPE
//Macros for memset optimization. In most platforms
//memsetting pointers and floatings is safe and faster.
//
//If your platform does not offer these guarantees
//define these to value zero.
#ifndef BOOST_CONTAINER_MEMZEROED_FLOATING_POINT_IS_NOT_ZERO
#define BOOST_CONTAINER_MEMZEROED_FLOATING_POINT_IS_ZERO 1
#endif
#ifndef BOOST_CONTAINER_MEMZEROED_POINTER_IS_NOT_NULL
#define BOOST_CONTAINER_MEMZEROED_POINTER_IS_NULL
#endif
#define BOOST_CONTAINER_DOC1ST(TYPE1, TYPE2) TYPE2
#define BOOST_CONTAINER_I ,
#define BOOST_CONTAINER_DOCIGN(T) T
#define BOOST_CONTAINER_DOCONLY(T)
#include <boost/container/detail/config_end.hpp>
#endif //#ifndef BOOST_CONTAINER_DETAIL_WORKAROUND_HPP

1902
boost/container/flat_map.hpp Normal file

File diff suppressed because it is too large Load diff

1250
boost/container/flat_set.hpp Normal file

File diff suppressed because it is too large Load diff

1462
boost/container/list.hpp Normal file

File diff suppressed because it is too large Load diff

1406
boost/container/map.hpp Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,344 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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/assert.hpp>
#include <boost/utility/addressof.hpp>
#include <boost/static_assert.hpp>
#include <memory>
#include <algorithm>
#include <cstddef>
namespace boost {
namespace container {
//!An STL node allocator that uses a modified DlMalloc as memory
//!source.
//!
//!This node allocator shares a segregated storage between all instances
//!of node_allocator with equal sizeof(T).
//!
//!NodesPerBlock is the number of nodes allocated at once when the allocator
//!runs out of nodes
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
template
< class T
, std::size_t NodesPerBlock = NodeAlloc_nodes_per_block>
#else
template
< class T
, std::size_t NodesPerBlock
, std::size_t Version>
#endif
class node_allocator
{
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//! If Version is 1, the allocator is a STL conforming allocator. If Version is 2,
//! the allocator offers advanced expand in place and burst allocation capabilities.
public:
typedef unsigned int allocation_type;
typedef node_allocator<T, NodesPerBlock, Version> self_t;
static const std::size_t nodes_per_block = NodesPerBlock;
BOOST_STATIC_ASSERT((Version <=2));
#endif
public:
//-------
typedef T value_type;
typedef T * pointer;
typedef const T * const_pointer;
typedef typename ::boost::container::
container_detail::unvoid<T>::type & reference;
typedef const typename ::boost::container::
container_detail::unvoid<T>::type & const_reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef boost::container::container_detail::
version_type<self_t, Version> version;
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
typedef boost::container::container_detail::
basic_multiallocation_chain<void*> multiallocation_chain_void;
typedef boost::container::container_detail::
transform_multiallocation_chain
<multiallocation_chain_void, T> multiallocation_chain;
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//!Obtains node_allocator from
//!node_allocator
template<class T2>
struct rebind
{
typedef node_allocator< T2, NodesPerBlock
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
, Version
#endif
> other;
};
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
//!Not assignable from related node_allocator
template<class T2, std::size_t N2>
node_allocator& operator=
(const node_allocator<T2, N2>&);
//!Not assignable from other node_allocator
node_allocator& operator=(const node_allocator&);
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
public:
//!Default constructor
node_allocator() BOOST_CONTAINER_NOEXCEPT
{}
//!Copy constructor from other node_allocator.
node_allocator(const node_allocator &) BOOST_CONTAINER_NOEXCEPT
{}
//!Copy constructor from related node_allocator.
template<class T2>
node_allocator
(const node_allocator<T2, NodesPerBlock
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
, Version
#endif
> &) BOOST_CONTAINER_NOEXCEPT
{}
//!Destructor
~node_allocator() BOOST_CONTAINER_NOEXCEPT
{}
//!Returns the number of elements that could be allocated.
//!Never throws
size_type max_size() const
{ return size_type(-1)/sizeof(T); }
//!Allocate memory for an array of count elements.
//!Throws std::bad_alloc if there is no enough memory
pointer allocate(size_type count, const void * = 0)
{
if(count > this->max_size())
boost::container::throw_bad_alloc();
if(Version == 1 && count == 1){
typedef container_detail::shared_node_pool
<sizeof(T), NodesPerBlock> shared_pool_t;
typedef container_detail::singleton_default<shared_pool_t> singleton_t;
return pointer(static_cast<T*>(singleton_t::instance().allocate_node()));
}
else{
void *ret = boost_cont_malloc(count*sizeof(T));
if(!ret)
boost::container::throw_bad_alloc();
return static_cast<pointer>(ret);
}
}
//!Deallocate allocated memory.
//!Never throws
void deallocate(const pointer &ptr, size_type count) BOOST_CONTAINER_NOEXCEPT
{
(void)count;
if(Version == 1 && count == 1){
typedef container_detail::shared_node_pool
<sizeof(T), NodesPerBlock> shared_pool_t;
typedef container_detail::singleton_default<shared_pool_t> singleton_t;
singleton_t::instance().deallocate_node(ptr);
}
else{
boost_cont_free(ptr);
}
}
//!Deallocates all free blocks of the pool
static void deallocate_free_blocks() BOOST_CONTAINER_NOEXCEPT
{
typedef container_detail::shared_node_pool
<sizeof(T), NodesPerBlock> shared_pool_t;
typedef container_detail::singleton_default<shared_pool_t> singleton_t;
singleton_t::instance().deallocate_free_blocks();
}
std::pair<pointer, bool>
allocation_command(allocation_type command,
size_type limit_size,
size_type preferred_size,
size_type &received_size, pointer reuse = pointer())
{
BOOST_STATIC_ASSERT(( Version > 1 ));
std::pair<pointer, bool> ret =
priv_allocation_command(command, limit_size, preferred_size, received_size, reuse);
if(!ret.first && !(command & BOOST_CONTAINER_NOTHROW_ALLOCATION))
boost::container::throw_bad_alloc();
return ret;
}
//!Returns maximum the number of objects the previously allocated memory
//!pointed by p can hold.
size_type size(pointer p) const BOOST_CONTAINER_NOEXCEPT
{
BOOST_STATIC_ASSERT(( Version > 1 ));
return boost_cont_size(p);
}
//!Allocates just one object. Memory allocated with this function
//!must be deallocated only with deallocate_one().
//!Throws bad_alloc if there is no enough memory
pointer allocate_one()
{
BOOST_STATIC_ASSERT(( Version > 1 ));
typedef container_detail::shared_node_pool
<sizeof(T), NodesPerBlock> shared_pool_t;
typedef container_detail::singleton_default<shared_pool_t> singleton_t;
return (pointer)singleton_t::instance().allocate_node();
}
//!Allocates many elements of size == 1.
//!Elements must be individually deallocated with deallocate_one()
void allocate_individual(std::size_t num_elements, multiallocation_chain &chain)
{
BOOST_STATIC_ASSERT(( Version > 1 ));
typedef container_detail::shared_node_pool
<sizeof(T), NodesPerBlock> shared_pool_t;
typedef container_detail::singleton_default<shared_pool_t> singleton_t;
typename shared_pool_t::multiallocation_chain ch;
singleton_t::instance().allocate_nodes(num_elements, ch);
chain.incorporate_after(chain.before_begin(), (T*)&*ch.begin(), (T*)&*ch.last(), ch.size());
}
//!Deallocates memory previously allocated with allocate_one().
//!You should never use deallocate_one to deallocate memory allocated
//!with other functions different from allocate_one(). Never throws
void deallocate_one(pointer p) BOOST_CONTAINER_NOEXCEPT
{
BOOST_STATIC_ASSERT(( Version > 1 ));
typedef container_detail::shared_node_pool
<sizeof(T), NodesPerBlock> shared_pool_t;
typedef container_detail::singleton_default<shared_pool_t> singleton_t;
singleton_t::instance().deallocate_node(p);
}
void deallocate_individual(multiallocation_chain &chain) BOOST_CONTAINER_NOEXCEPT
{
BOOST_STATIC_ASSERT(( Version > 1 ));
typedef container_detail::shared_node_pool
<sizeof(T), NodesPerBlock> shared_pool_t;
typedef container_detail::singleton_default<shared_pool_t> singleton_t;
typename shared_pool_t::multiallocation_chain ch(&*chain.begin(), &*chain.last(), chain.size());
singleton_t::instance().deallocate_nodes(ch);
}
//!Allocates many elements of size elem_size.
//!Elements must be individually deallocated with deallocate()
void allocate_many(size_type elem_size, std::size_t n_elements, multiallocation_chain &chain)
{
BOOST_STATIC_ASSERT(( Version > 1 ));
boost_cont_memchain ch;
BOOST_CONTAINER_MEMCHAIN_INIT(&ch);
if(!boost_cont_multialloc_nodes(n_elements, elem_size*sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &ch)){
boost::container::throw_bad_alloc();
}
chain.incorporate_after( chain.before_begin()
, (T*)BOOST_CONTAINER_MEMCHAIN_LASTMEM(&ch)
, (T*)BOOST_CONTAINER_MEMCHAIN_LASTMEM(&ch)
, BOOST_CONTAINER_MEMCHAIN_SIZE(&ch));
}
//!Allocates n_elements elements, each one of size elem_sizes[i]
//!Elements must be individually deallocated with deallocate()
void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain)
{
BOOST_STATIC_ASSERT(( Version > 1 ));
boost_cont_memchain ch;
boost_cont_multialloc_arrays(n_elements, elem_sizes, sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &ch);
if(BOOST_CONTAINER_MEMCHAIN_EMPTY(&ch)){
boost::container::throw_bad_alloc();
}
chain.incorporate_after( chain.before_begin()
, (T*)BOOST_CONTAINER_MEMCHAIN_LASTMEM(&ch)
, (T*)BOOST_CONTAINER_MEMCHAIN_LASTMEM(&ch)
, BOOST_CONTAINER_MEMCHAIN_SIZE(&ch));
}
void deallocate_many(multiallocation_chain &chain) BOOST_CONTAINER_NOEXCEPT
{
BOOST_STATIC_ASSERT(( Version > 1 ));
void *first = &*chain.begin();
void *last = &*chain.last();
size_t num = chain.size();
boost_cont_memchain ch;
BOOST_CONTAINER_MEMCHAIN_INIT_FROM(&ch, first, last, num);
boost_cont_multidealloc(&ch);
}
//!Swaps allocators. Does not throw. If each allocator is placed in a
//!different memory segment, the result is undefined.
friend void swap(self_t &, self_t &) BOOST_CONTAINER_NOEXCEPT
{}
//!An allocator always compares to true, as memory allocated with one
//!instance can be deallocated by another instance
friend bool operator==(const node_allocator &, const node_allocator &) BOOST_CONTAINER_NOEXCEPT
{ return true; }
//!An allocator always compares to false, as memory allocated with one
//!instance can be deallocated by another instance
friend bool operator!=(const node_allocator &, const node_allocator &) BOOST_CONTAINER_NOEXCEPT
{ return false; }
private:
std::pair<pointer, bool> priv_allocation_command
(allocation_type command, std::size_t limit_size
,std::size_t preferred_size,std::size_t &received_size, void *reuse_ptr)
{
boost_cont_command_ret_t ret = {0 , 0};
if(limit_size > this->max_size() || preferred_size > this->max_size()){
//ret.first = 0;
return std::pair<pointer, bool>(pointer(), false);
}
std::size_t l_size = limit_size*sizeof(T);
std::size_t p_size = preferred_size*sizeof(T);
std::size_t r_size;
{
ret = boost_cont_allocation_command(command, sizeof(T), l_size, p_size, &r_size, reuse_ptr);
}
received_size = r_size/sizeof(T);
return std::pair<pointer, bool>(static_cast<pointer>(ret.first), !!ret.second);
}
};
} //namespace container {
} //namespace boost {
#include <boost/container/detail/config_end.hpp>
#endif //#ifndef BOOST_CONTAINER_POOLED_NODE_ALLOCATOR_HPP

View file

@ -0,0 +1,76 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2013-2013
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_OPTIONS_HPP
#define BOOST_CONTAINER_OPTIONS_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/container_fwd.hpp>
#include <boost/intrusive/pack_options.hpp>
namespace boost {
namespace container {
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
template<tree_type_enum TreeType, bool OptimizeSize>
struct tree_opt
{
static const boost::container::tree_type_enum tree_type = TreeType;
static const bool optimize_size = OptimizeSize;
};
#endif //!defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//!This option setter specifies the underlying tree type
//!(red-black, AVL, Scapegoat or Splay) for ordered associative containers
BOOST_INTRUSIVE_OPTION_CONSTANT(tree_type, tree_type_enum, TreeType, tree_type)
//!This option setter specifies if node size is optimized
//!storing rebalancing data masked into pointers for ordered associative containers
BOOST_INTRUSIVE_OPTION_CONSTANT(optimize_size, bool, Enabled, optimize_size)
//! Helper metafunction to combine options into a single type to be used
//! by \c boost::container::set, \c boost::container::multiset
//! \c boost::container::map and \c boost::container::multimap.
//! Supported options are: \c boost::container::optimize_size and \c boost::container::tree_type
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) || defined(BOOST_CONTAINER_VARIADIC_TEMPLATES)
template<class ...Options>
#else
template<class O1 = void, class O2 = void, class O3 = void, class O4 = void>
#endif
struct tree_assoc_options
{
/// @cond
typedef typename ::boost::intrusive::pack_options
< tree_assoc_defaults,
#if !defined(BOOST_CONTAINER_VARIADIC_TEMPLATES)
O1, O2, O3, O4
#else
Options...
#endif
>::type packed_options;
typedef tree_opt<packed_options::tree_type, packed_options::optimize_size> implementation_defined;
/// @endcond
typedef implementation_defined type;
};
} //namespace container {
} //namespace boost {
#include <boost/container/detail/config_end.hpp>
#endif //#ifndef BOOST_CONTAINER_OPTIONS_HPP

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,87 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2011-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_ALLOCATOR_SCOPED_ALLOCATOR_FWD_HPP
#define BOOST_CONTAINER_ALLOCATOR_SCOPED_ALLOCATOR_FWD_HPP
//! \file
//! This header file forward declares boost::container::scoped_allocator_adaptor
//! and defines the following types:
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#include <boost/container/detail/preprocessor.hpp>
#include <boost/container/detail/type_traits.hpp>
#endif
namespace boost { namespace container {
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#if !defined(BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST)
template <typename OuterAlloc, typename ...InnerAllocs>
class scoped_allocator_adaptor;
#else // #if !defined(BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST)
template <typename ...InnerAllocs>
class scoped_allocator_adaptor;
template <typename OuterAlloc, typename ...InnerAllocs>
class scoped_allocator_adaptor<OuterAlloc, InnerAllocs...>;
#endif // #if !defined(BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST)
#else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <typename OuterAlloc
BOOST_PP_ENUM_TRAILING( BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS
, BOOST_CONTAINER_PP_TEMPLATE_PARAM_WITH_DEFAULT, container_detail::nat)
>
class scoped_allocator_adaptor;
#endif
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//! The allocator_arg_t struct is an empty structure type used as a unique type to
//! disambiguate constructor and function overloading. Specifically, several types
//! have constructors with allocator_arg_t as the first argument, immediately followed
//! by an argument of a type that satisfies the Allocator requirements
struct allocator_arg_t{};
//! A instance of type allocator_arg_t
//!
static const allocator_arg_t allocator_arg = allocator_arg_t();
template <class T>
struct constructible_with_allocator_suffix;
template <class T>
struct constructible_with_allocator_prefix;
template <typename T, typename Alloc>
struct uses_allocator;
}} // namespace boost { namespace container {
#include <boost/container/detail/config_end.hpp>
#endif // BOOST_CONTAINER_ALLOCATOR_SCOPED_ALLOCATOR_FWD_HPP

1126
boost/container/set.hpp Normal file

File diff suppressed because it is too large Load diff

1730
boost/container/slist.hpp Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

2918
boost/container/string.hpp Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,166 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2012-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_THROW_EXCEPTION_HPP
#define BOOST_CONTAINER_THROW_EXCEPTION_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#ifndef BOOST_NO_EXCEPTIONS
#include <stdexcept> //for std exception types
#include <new> //for std::bad_alloc
#else
#include <boost/assert.hpp>
#include <cstdlib> //for std::abort
#endif
namespace boost {
namespace container {
#if defined(BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS)
//The user must provide definitions for the following functions
void throw_bad_alloc();
void throw_out_of_range(const char* str);
void throw_length_error(const char* str);
void throw_logic_error(const char* str);
void throw_runtime_error(const char* str);
#elif defined(BOOST_NO_EXCEPTIONS)
inline void throw_bad_alloc()
{
BOOST_ASSERT(!"boost::container bad_alloc thrown");
std::abort();
}
inline void throw_out_of_range(const char* str)
{
BOOST_ASSERT_MSG(!"boost::container out_of_range thrown", str);
std::abort();
}
inline void throw_length_error(const char* str)
{
BOOST_ASSERT_MSG(!"boost::container length_error thrown", str);
std::abort();
}
inline void throw_logic_error(const char* str)
{
BOOST_ASSERT_MSG(!"boost::container logic_error thrown", str);
std::abort();
}
inline void throw_runtime_error(const char* str)
{
BOOST_ASSERT_MSG(!"boost::container runtime_error thrown", str);
std::abort();
}
#else //defined(BOOST_NO_EXCEPTIONS)
//! Exception callback called by Boost.Container when fails to allocate the requested storage space.
//! <ul>
//! <li>If BOOST_NO_EXCEPTIONS is NOT defined <code>std::bad_alloc()</code> is thrown.</li>
//!
//! <li>If BOOST_NO_EXCEPTIONS is defined and BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS
//! is NOT defined <code>BOOST_ASSERT(!"boost::container bad_alloc thrown")</code> is called
//! and <code>std::abort()</code> if the former returns.</li>
//!
//! <li>If BOOST_NO_EXCEPTIONS and BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS are defined
//! the user must provide an implementation and the function should not return.</li>
//! </ul>
inline void throw_bad_alloc()
{
throw std::bad_alloc();
}
//! Exception callback called by Boost.Container to signal arguments out of range.
//! <ul>
//! <li>If BOOST_NO_EXCEPTIONS is NOT defined <code>std::out_of_range(str)</code> is thrown.</li>
//!
//! <li>If BOOST_NO_EXCEPTIONS is defined and BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS
//! is NOT defined <code>BOOST_ASSERT_MSG(!"boost::container out_of_range thrown", str)</code> is called
//! and <code>std::abort()</code> if the former returns.</li>
//!
//! <li>If BOOST_NO_EXCEPTIONS and BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS are defined
//! the user must provide an implementation and the function should not return.</li>
//! </ul>
inline void throw_out_of_range(const char* str)
{
throw std::out_of_range(str);
}
//! Exception callback called by Boost.Container to signal errors resizing.
//! <ul>
//! <li>If BOOST_NO_EXCEPTIONS is NOT defined <code>std::length_error(str)</code> is thrown.</li>
//!
//! <li>If BOOST_NO_EXCEPTIONS is defined and BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS
//! is NOT defined <code>BOOST_ASSERT_MSG(!"boost::container length_error thrown", str)</code> is called
//! and <code>std::abort()</code> if the former returns.</li>
//!
//! <li>If BOOST_NO_EXCEPTIONS and BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS are defined
//! the user must provide an implementation and the function should not return.</li>
//! </ul>
inline void throw_length_error(const char* str)
{
throw std::length_error(str);
}
//! Exception callback called by Boost.Container to report errors in the internal logical
//! of the program, such as violation of logical preconditions or class invariants.
//! <ul>
//! <li>If BOOST_NO_EXCEPTIONS is NOT defined <code>std::logic_error(str)</code> is thrown.</li>
//!
//! <li>If BOOST_NO_EXCEPTIONS is defined and BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS
//! is NOT defined <code>BOOST_ASSERT_MSG(!"boost::container logic_error thrown", str)</code> is called
//! and <code>std::abort()</code> if the former returns.</li>
//!
//! <li>If BOOST_NO_EXCEPTIONS and BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS are defined
//! the user must provide an implementation and the function should not return.</li>
//! </ul>
inline void throw_logic_error(const char* str)
{
throw std::logic_error(str);
}
//! Exception callback called by Boost.Container to report errors that can only be detected during runtime.
//! <ul>
//! <li>If BOOST_NO_EXCEPTIONS is NOT defined <code>std::runtime_error(str)</code> is thrown.</li>
//!
//! <li>If BOOST_NO_EXCEPTIONS is defined and BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS
//! is NOT defined <code>BOOST_ASSERT_MSG(!"boost::container runtime_error thrown", str)</code> is called
//! and <code>std::abort()</code> if the former returns.</li>
//!
//! <li>If BOOST_NO_EXCEPTIONS and BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS are defined
//! the user must provide an implementation and the function should not return.</li>
//! </ul>
inline void throw_runtime_error(const char* str)
{
throw std::runtime_error(str);
}
#endif
}} //namespace boost { namespace container {
#include <boost/container/detail/config_end.hpp>
#endif //#ifndef BOOST_CONTAINER_THROW_EXCEPTION_HPP

2984
boost/container/vector.hpp Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,336 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2006-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/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_ANY_HOOK_HPP
#define BOOST_INTRUSIVE_ANY_HOOK_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/intrusive/detail/config_begin.hpp>
#include <boost/intrusive/intrusive_fwd.hpp>
#include <boost/intrusive/detail/any_node_and_algorithms.hpp>
#include <boost/intrusive/options.hpp>
#include <boost/intrusive/detail/generic_hook.hpp>
#include <boost/intrusive/detail/mpl.hpp>
#include <boost/intrusive/pointer_rebind.hpp>
namespace boost {
namespace intrusive {
//! Helper metafunction to define a \c \c any_base_hook that yields to the same
//! type when the same options (either explicitly or implicitly) are used.
#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class ...Options>
#else
template<class O1 = void, class O2 = void, class O3 = void>
#endif
struct make_any_base_hook
{
/// @cond
typedef typename pack_options
< hook_defaults,
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
O1, O2, O3
#else
Options...
#endif
>::type packed_options;
typedef generic_hook
< any_algorithms<typename packed_options::void_pointer>
, typename packed_options::tag
, packed_options::link_mode
, AnyBaseHookId
> implementation_defined;
/// @endcond
typedef implementation_defined type;
};
//! Derive a class from this hook in order to store objects of that class
//! in an intrusive container.
//!
//! The hook admits the following options: \c tag<>, \c void_pointer<> and
//! \c link_mode<>.
//!
//! \c tag<> defines a tag to identify the node.
//! The same tag value can be used in different classes, but if a class is
//! derived from more than one \c any_base_hook, then each \c any_base_hook needs its
//! unique tag.
//!
//! \c link_mode<> will specify the linking mode of the hook (\c normal_link, \c safe_link).
//!
//! \c void_pointer<> is the pointer type that will be used internally in the hook
//! and the container configured to use this hook.
#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class ...Options>
#else
template<class O1, class O2, class O3>
#endif
class any_base_hook
: public make_any_base_hook
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
<O1, O2, O3>
#else
<Options...>
#endif
::type
{
#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
public:
//! <b>Effects</b>: If link_mode is or \c safe_link
//! initializes the node to an unlinked state.
//!
//! <b>Throws</b>: Nothing.
any_base_hook();
//! <b>Effects</b>: If link_mode is or \c safe_link
//! initializes the node to an unlinked state. The argument is ignored.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Rationale</b>: Providing a copy-constructor
//! makes classes using the hook STL-compliant without forcing the
//! user to do some additional work. \c swap can be used to emulate
//! move-semantics.
any_base_hook(const any_base_hook& );
//! <b>Effects</b>: Empty function. The argument is ignored.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Rationale</b>: Providing an assignment operator
//! makes classes using the hook STL-compliant without forcing the
//! user to do some additional work. \c swap can be used to emulate
//! move-semantics.
any_base_hook& operator=(const any_base_hook& );
//! <b>Effects</b>: If link_mode is \c normal_link, the destructor does
//! nothing (ie. no code is generated). If link_mode is \c safe_link and the
//! object is stored in a container an assertion is raised.
//!
//! <b>Throws</b>: Nothing.
~any_base_hook();
//! <b>Precondition</b>: link_mode must be \c safe_link.
//!
//! <b>Returns</b>: true, if the node belongs to a container, false
//! otherwise. This function can be used to test whether \c container::iterator_to
//! will return a valid iterator.
//!
//! <b>Complexity</b>: Constant
bool is_linked() const;
#endif
};
//! Helper metafunction to define a \c \c any_member_hook that yields to the same
//! type when the same options (either explicitly or implicitly) are used.
#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class ...Options>
#else
template<class O1 = void, class O2 = void, class O3 = void>
#endif
struct make_any_member_hook
{
/// @cond
typedef typename pack_options
< hook_defaults,
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
O1, O2, O3
#else
Options...
#endif
>::type packed_options;
typedef generic_hook
< any_algorithms<typename packed_options::void_pointer>
, member_tag
, packed_options::link_mode
, NoBaseHookId
> implementation_defined;
/// @endcond
typedef implementation_defined type;
};
//! Store this hook in a class to be inserted
//! in an intrusive container.
//!
//! The hook admits the following options: \c void_pointer<> and
//! \c link_mode<>.
//!
//! \c link_mode<> will specify the linking mode of the hook (\c normal_link or \c safe_link).
//!
//! \c void_pointer<> is the pointer type that will be used internally in the hook
//! and the container configured to use this hook.
#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class ...Options>
#else
template<class O1, class O2, class O3>
#endif
class any_member_hook
: public make_any_member_hook
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
<O1, O2, O3>
#else
<Options...>
#endif
::type
{
#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
public:
//! <b>Effects</b>: If link_mode is or \c safe_link
//! initializes the node to an unlinked state.
//!
//! <b>Throws</b>: Nothing.
any_member_hook();
//! <b>Effects</b>: If link_mode is or \c safe_link
//! initializes the node to an unlinked state. The argument is ignored.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Rationale</b>: Providing a copy-constructor
//! makes classes using the hook STL-compliant without forcing the
//! user to do some additional work. \c swap can be used to emulate
//! move-semantics.
any_member_hook(const any_member_hook& );
//! <b>Effects</b>: Empty function. The argument is ignored.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Rationale</b>: Providing an assignment operator
//! makes classes using the hook STL-compliant without forcing the
//! user to do some additional work. \c swap can be used to emulate
//! move-semantics.
any_member_hook& operator=(const any_member_hook& );
//! <b>Effects</b>: If link_mode is \c normal_link, the destructor does
//! nothing (ie. no code is generated). If link_mode is \c safe_link and the
//! object is stored in a container an assertion is raised.
//!
//! <b>Throws</b>: Nothing.
~any_member_hook();
//! <b>Precondition</b>: link_mode must be \c safe_link.
//!
//! <b>Returns</b>: true, if the node belongs to a container, false
//! otherwise. This function can be used to test whether \c container::iterator_to
//! will return a valid iterator.
//!
//! <b>Complexity</b>: Constant
bool is_linked() const;
#endif
};
/// @cond
namespace detail{
BOOST_INTRUSIVE_INTERNAL_STATIC_BOOL_IS_TRUE(old_proto_value_traits_base_hook, hooktags::is_base_hook)
//!This option setter specifies that the container
//!must use the specified base hook
template<class BasicHook, template <class> class NodeTraits>
struct any_to_some_hook
{
typedef typename BasicHook::template pack<empty>::proto_value_traits old_proto_value_traits;
template<class Base>
struct pack : public Base
{
struct proto_value_traits
{
//proto_value_traits::hooktags::is_base_hook is used by get_value_traits
//to detect base hooks, so mark it in case BasicHook has it.
struct hooktags
{
static const bool is_base_hook = old_proto_value_traits_base_hook_bool_is_true
<old_proto_value_traits>::value;
};
typedef old_proto_value_traits basic_hook_t;
static const bool is_any_hook = true;
template<class VoidPtr>
struct node_traits_from_voidptr
{ typedef NodeTraits<VoidPtr> type; };
};
};
};
} //namespace detail{
/// @endcond
//!This option setter specifies that
//!any hook should behave as an slist hook
template<class BasicHook>
struct any_to_slist_hook
/// @cond
: public detail::any_to_some_hook<BasicHook, any_slist_node_traits>
/// @endcond
{};
//!This option setter specifies that
//!any hook should behave as an list hook
template<class BasicHook>
struct any_to_list_hook
/// @cond
: public detail::any_to_some_hook<BasicHook, any_list_node_traits>
/// @endcond
{};
//!This option setter specifies that
//!any hook should behave as a set hook
template<class BasicHook>
struct any_to_set_hook
/// @cond
: public detail::any_to_some_hook<BasicHook, any_rbtree_node_traits>
/// @endcond
{};
//!This option setter specifies that
//!any hook should behave as an avl_set hook
template<class BasicHook>
struct any_to_avl_set_hook
/// @cond
: public detail::any_to_some_hook<BasicHook, any_avltree_node_traits>
/// @endcond
{};
//!This option setter specifies that any
//!hook should behave as a bs_set hook
template<class BasicHook>
struct any_to_bs_set_hook
/// @cond
: public detail::any_to_some_hook<BasicHook, any_tree_node_traits>
/// @endcond
{};
//!This option setter specifies that any hook
//!should behave as an unordered set hook
template<class BasicHook>
struct any_to_unordered_set_hook
/// @cond
: public detail::any_to_some_hook<BasicHook, any_unordered_node_traits>
/// @endcond
{};
} //namespace intrusive
} //namespace boost
#include <boost/intrusive/detail/config_end.hpp>
#endif //BOOST_INTRUSIVE_ANY_HOOK_HPP

950
boost/intrusive/avl_set.hpp Normal file
View file

@ -0,0 +1,950 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2007-2014
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_AVL_SET_HPP
#define BOOST_INTRUSIVE_AVL_SET_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/intrusive/detail/config_begin.hpp>
#include <boost/intrusive/intrusive_fwd.hpp>
#include <boost/intrusive/avltree.hpp>
#include <boost/intrusive/detail/mpl.hpp>
#include <boost/move/utility_core.hpp>
#include <boost/static_assert.hpp>
namespace boost {
namespace intrusive {
//! The class template avl_set is an intrusive container, that mimics most of
//! the interface of std::set as described in the C++ standard.
//!
//! The template parameter \c T is the type to be managed by the container.
//! The user can specify additional options and if no options are provided
//! default options are used.
//!
//! The container supports the following options:
//! \c base_hook<>/member_hook<>/value_traits<>,
//! \c constant_time_size<>, \c size_type<> and
//! \c compare<>.
#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class ValueTraits, class Compare, class SizeType, bool ConstantTimeSize, typename HeaderHolder>
#endif
class avl_set_impl
#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
: public bstree_impl<ValueTraits, Compare, SizeType, ConstantTimeSize, AvlTreeAlgorithms, HeaderHolder>
#endif
{
/// @cond
typedef bstree_impl<ValueTraits, Compare, SizeType, ConstantTimeSize, AvlTreeAlgorithms, HeaderHolder> tree_type;
BOOST_MOVABLE_BUT_NOT_COPYABLE(avl_set_impl)
typedef tree_type implementation_defined;
/// @endcond
public:
typedef typename implementation_defined::value_type value_type;
typedef typename implementation_defined::value_traits value_traits;
typedef typename implementation_defined::pointer pointer;
typedef typename implementation_defined::const_pointer const_pointer;
typedef typename implementation_defined::reference reference;
typedef typename implementation_defined::const_reference const_reference;
typedef typename implementation_defined::difference_type difference_type;
typedef typename implementation_defined::size_type size_type;
typedef typename implementation_defined::value_compare value_compare;
typedef typename implementation_defined::key_compare key_compare;
typedef typename implementation_defined::iterator iterator;
typedef typename implementation_defined::const_iterator const_iterator;
typedef typename implementation_defined::reverse_iterator reverse_iterator;
typedef typename implementation_defined::const_reverse_iterator const_reverse_iterator;
typedef typename implementation_defined::insert_commit_data insert_commit_data;
typedef typename implementation_defined::node_traits node_traits;
typedef typename implementation_defined::node node;
typedef typename implementation_defined::node_ptr node_ptr;
typedef typename implementation_defined::const_node_ptr const_node_ptr;
typedef typename implementation_defined::node_algorithms node_algorithms;
static const bool constant_time_size = tree_type::constant_time_size;
public:
//! @copydoc ::boost::intrusive::avltree::avltree(const value_compare &,const value_traits &)
explicit avl_set_impl( const value_compare &cmp = value_compare()
, const value_traits &v_traits = value_traits())
: tree_type(cmp, v_traits)
{}
//! @copydoc ::boost::intrusive::avltree::avltree(bool,Iterator,Iterator,const value_compare &,const value_traits &)
template<class Iterator>
avl_set_impl( Iterator b, Iterator e
, const value_compare &cmp = value_compare()
, const value_traits &v_traits = value_traits())
: tree_type(true, b, e, cmp, v_traits)
{}
//! @copydoc ::boost::intrusive::avltree::avltree(avltree &&)
avl_set_impl(BOOST_RV_REF(avl_set_impl) x)
: tree_type(::boost::move(static_cast<tree_type&>(x)))
{}
//! @copydoc ::boost::intrusive::avltree::operator=(avltree &&)
avl_set_impl& operator=(BOOST_RV_REF(avl_set_impl) x)
{ return static_cast<avl_set_impl&>(tree_type::operator=(::boost::move(static_cast<tree_type&>(x)))); }
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
//! @copydoc ::boost::intrusive::avltree::~avltree()
~avl_set_impl();
//! @copydoc ::boost::intrusive::avltree::begin()
iterator begin();
//! @copydoc ::boost::intrusive::avltree::begin()const
const_iterator begin() const;
//! @copydoc ::boost::intrusive::avltree::cbegin()const
const_iterator cbegin() const;
//! @copydoc ::boost::intrusive::avltree::end()
iterator end();
//! @copydoc ::boost::intrusive::avltree::end()const
const_iterator end() const;
//! @copydoc ::boost::intrusive::avltree::cend()const
const_iterator cend() const;
//! @copydoc ::boost::intrusive::avltree::begin()
reverse_iterator avlegin();
//! @copydoc ::boost::intrusive::avltree::begin()const
const_reverse_iterator avlegin() const;
//! @copydoc ::boost::intrusive::avltree::crbegin()const
const_reverse_iterator crbegin() const;
//! @copydoc ::boost::intrusive::avltree::rend()
reverse_iterator rend();
//! @copydoc ::boost::intrusive::avltree::rend()const
const_reverse_iterator rend() const;
//! @copydoc ::boost::intrusive::avltree::crend()const
const_reverse_iterator crend() const;
//! @copydoc ::boost::intrusive::avltree::container_from_end_iterator(iterator)
static avl_set_impl &container_from_end_iterator(iterator end_iterator);
//! @copydoc ::boost::intrusive::avltree::container_from_end_iterator(const_iterator)
static const avl_set_impl &container_from_end_iterator(const_iterator end_iterator);
//! @copydoc ::boost::intrusive::avltree::container_from_iterator(iterator)
static avl_set_impl &container_from_iterator(iterator it);
//! @copydoc ::boost::intrusive::avltree::container_from_iterator(const_iterator)
static const avl_set_impl &container_from_iterator(const_iterator it);
//! @copydoc ::boost::intrusive::avltree::key_comp()const
key_compare key_comp() const;
//! @copydoc ::boost::intrusive::avltree::value_comp()const
value_compare value_comp() const;
//! @copydoc ::boost::intrusive::avltree::empty()const
bool empty() const;
//! @copydoc ::boost::intrusive::avltree::size()const
size_type size() const;
//! @copydoc ::boost::intrusive::avltree::swap
void swap(avl_set_impl& other);
//! @copydoc ::boost::intrusive::avltree::clone_from
template <class Cloner, class Disposer>
void clone_from(const avl_set_impl &src, Cloner cloner, Disposer disposer);
#endif //#ifdef BOOST_iNTRUSIVE_DOXYGEN_INVOKED
//! @copydoc ::boost::intrusive::avltree::insert_unique(reference)
std::pair<iterator, bool> insert(reference value)
{ return tree_type::insert_unique(value); }
//! @copydoc ::boost::intrusive::avltree::insert_unique(const_iterator,reference)
iterator insert(const_iterator hint, reference value)
{ return tree_type::insert_unique(hint, value); }
//! @copydoc ::boost::intrusive::avltree::insert_unique_check(const KeyType&,KeyValueCompare,insert_commit_data&)
template<class KeyType, class KeyValueCompare>
std::pair<iterator, bool> insert_check
(const KeyType &key, KeyValueCompare key_value_comp, insert_commit_data &commit_data)
{ return tree_type::insert_unique_check(key, key_value_comp, commit_data); }
//! @copydoc ::boost::intrusive::avltree::insert_unique_check(const_iterator,const KeyType&,KeyValueCompare,insert_commit_data&)
template<class KeyType, class KeyValueCompare>
std::pair<iterator, bool> insert_check
(const_iterator hint, const KeyType &key
,KeyValueCompare key_value_comp, insert_commit_data &commit_data)
{ return tree_type::insert_unique_check(hint, key, key_value_comp, commit_data); }
//! @copydoc ::boost::intrusive::avltree::insert_unique(Iterator,Iterator)
template<class Iterator>
void insert(Iterator b, Iterator e)
{ tree_type::insert_unique(b, e); }
//! @copydoc ::boost::intrusive::avltree::insert_unique_commit
iterator insert_commit(reference value, const insert_commit_data &commit_data)
{ return tree_type::insert_unique_commit(value, commit_data); }
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
//! @copydoc ::boost::intrusive::avltree::insert_before
iterator insert_before(const_iterator pos, reference value);
//! @copydoc ::boost::intrusive::avltree::push_back
void push_back(reference value);
//! @copydoc ::boost::intrusive::avltree::push_front
void push_front(reference value);
//! @copydoc ::boost::intrusive::avltree::erase(const_iterator)
iterator erase(const_iterator i);
//! @copydoc ::boost::intrusive::avltree::erase(const_iterator,const_iterator)
iterator erase(const_iterator b, const_iterator e);
//! @copydoc ::boost::intrusive::avltree::erase(const_reference)
size_type erase(const_reference value);
//! @copydoc ::boost::intrusive::avltree::erase(const KeyType&,KeyValueCompare)
template<class KeyType, class KeyValueCompare>
size_type erase(const KeyType& key, KeyValueCompare comp);
//! @copydoc ::boost::intrusive::avltree::erase_and_dispose(const_iterator,Disposer)
template<class Disposer>
iterator erase_and_dispose(const_iterator i, Disposer disposer);
//! @copydoc ::boost::intrusive::avltree::erase_and_dispose(const_iterator,const_iterator,Disposer)
template<class Disposer>
iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer);
//! @copydoc ::boost::intrusive::avltree::erase_and_dispose(const_reference, Disposer)
template<class Disposer>
size_type erase_and_dispose(const_reference value, Disposer disposer);
//! @copydoc ::boost::intrusive::avltree::erase_and_dispose(const KeyType&,KeyValueCompare,Disposer)
template<class KeyType, class KeyValueCompare, class Disposer>
size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer);
//! @copydoc ::boost::intrusive::avltree::clear
void clear();
//! @copydoc ::boost::intrusive::avltree::clear_and_dispose
template<class Disposer>
void clear_and_dispose(Disposer disposer);
#endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
//! @copydoc ::boost::intrusive::avltree::count(const_reference)const
size_type count(const_reference value) const
{ return static_cast<size_type>(this->tree_type::find(value) != this->tree_type::cend()); }
//! @copydoc ::boost::intrusive::avltree::count(const KeyType&,KeyValueCompare)const
template<class KeyType, class KeyValueCompare>
size_type count(const KeyType& key, KeyValueCompare comp) const
{ return static_cast<size_type>(this->tree_type::find(key, comp) != this->tree_type::cend()); }
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
//! @copydoc ::boost::intrusive::avltree::lower_bound(const_reference)
iterator lower_bound(const_reference value);
//! @copydoc ::boost::intrusive::avltree::lower_bound(const KeyType&,KeyValueCompare)
template<class KeyType, class KeyValueCompare>
iterator lower_bound(const KeyType& key, KeyValueCompare comp);
//! @copydoc ::boost::intrusive::avltree::lower_bound(const_reference)const
const_iterator lower_bound(const_reference value) const;
//! @copydoc ::boost::intrusive::avltree::lower_bound(const KeyType&,KeyValueCompare)const
template<class KeyType, class KeyValueCompare>
const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const;
//! @copydoc ::boost::intrusive::avltree::upper_bound(const_reference)
iterator upper_bound(const_reference value);
//! @copydoc ::boost::intrusive::avltree::upper_bound(const KeyType&,KeyValueCompare)
template<class KeyType, class KeyValueCompare>
iterator upper_bound(const KeyType& key, KeyValueCompare comp);
//! @copydoc ::boost::intrusive::avltree::upper_bound(const_reference)const
const_iterator upper_bound(const_reference value) const;
//! @copydoc ::boost::intrusive::avltree::upper_bound(const KeyType&,KeyValueCompare)const
template<class KeyType, class KeyValueCompare>
const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const;
//! @copydoc ::boost::intrusive::avltree::find(const_reference)
iterator find(const_reference value);
//! @copydoc ::boost::intrusive::avltree::find(const KeyType&,KeyValueCompare)
template<class KeyType, class KeyValueCompare>
iterator find(const KeyType& key, KeyValueCompare comp);
//! @copydoc ::boost::intrusive::avltree::find(const_reference)const
const_iterator find(const_reference value) const;
//! @copydoc ::boost::intrusive::avltree::find(const KeyType&,KeyValueCompare)const
template<class KeyType, class KeyValueCompare>
const_iterator find(const KeyType& key, KeyValueCompare comp) const;
#endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
//! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference)
std::pair<iterator,iterator> equal_range(const_reference value)
{ return this->tree_type::lower_bound_range(value); }
//! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare)
template<class KeyType, class KeyValueCompare>
std::pair<iterator,iterator> equal_range(const KeyType& key, KeyValueCompare comp)
{ return this->tree_type::lower_bound_range(key, comp); }
//! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference)const
std::pair<const_iterator, const_iterator>
equal_range(const_reference value) const
{ return this->tree_type::lower_bound_range(value); }
//! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare)const
template<class KeyType, class KeyValueCompare>
std::pair<const_iterator, const_iterator>
equal_range(const KeyType& key, KeyValueCompare comp) const
{ return this->tree_type::lower_bound_range(key, comp); }
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
//! @copydoc ::boost::intrusive::avltree::bounded_range(const_reference,const_reference,bool,bool)
std::pair<iterator,iterator> bounded_range
(const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed);
//! @copydoc ::boost::intrusive::avltree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool)
template<class KeyType, class KeyValueCompare>
std::pair<iterator,iterator> bounded_range
(const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed);
//! @copydoc ::boost::intrusive::avltree::bounded_range(const_reference,const_reference,bool,bool)const
std::pair<const_iterator, const_iterator>
bounded_range(const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const;
//! @copydoc ::boost::intrusive::avltree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool)const
template<class KeyType, class KeyValueCompare>
std::pair<const_iterator, const_iterator> bounded_range
(const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const;
//! @copydoc ::boost::intrusive::avltree::s_iterator_to(reference)
static iterator s_iterator_to(reference value);
//! @copydoc ::boost::intrusive::avltree::s_iterator_to(const_reference)
static const_iterator s_iterator_to(const_reference value);
//! @copydoc ::boost::intrusive::avltree::iterator_to(reference)
iterator iterator_to(reference value);
//! @copydoc ::boost::intrusive::avltree::iterator_to(const_reference)const
const_iterator iterator_to(const_reference value) const;
//! @copydoc ::boost::intrusive::avltree::init_node(reference)
static void init_node(reference value);
//! @copydoc ::boost::intrusive::avltree::unlink_leftmost_without_rebalance
pointer unlink_leftmost_without_rebalance();
//! @copydoc ::boost::intrusive::avltree::replace_node
void replace_node(iterator replace_this, reference with_this);
//! @copydoc ::boost::intrusive::avltree::remove_node
void remove_node(reference value);
#endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
};
#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
bool operator!= (const avl_set_impl<T, Options...> &x, const avl_set_impl<T, Options...> &y);
template<class T, class ...Options>
bool operator>(const avl_set_impl<T, Options...> &x, const avl_set_impl<T, Options...> &y);
template<class T, class ...Options>
bool operator<=(const avl_set_impl<T, Options...> &x, const avl_set_impl<T, Options...> &y);
template<class T, class ...Options>
bool operator>=(const avl_set_impl<T, Options...> &x, const avl_set_impl<T, Options...> &y);
template<class T, class ...Options>
void swap(avl_set_impl<T, Options...> &x, avl_set_impl<T, Options...> &y);
#endif //#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
//! Helper metafunction to define a \c set that yields to the same type when the
//! same options (either explicitly or implicitly) are used.
#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class ...Options>
#else
template<class T, class O1 = void, class O2 = void
, class O3 = void, class O4 = void
, class O5 = void>
#endif
struct make_avl_set
{
/// @cond
typedef typename pack_options
< avltree_defaults,
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
O1, O2, O3, O4, O5
#else
Options...
#endif
>::type packed_options;
typedef typename detail::get_value_traits
<T, typename packed_options::proto_value_traits>::type value_traits;
typedef typename detail::get_header_holder_type
< value_traits, typename packed_options::header_holder_type >::type header_holder_type;
typedef avl_set_impl
< value_traits
, typename packed_options::compare
, typename packed_options::size_type
, packed_options::constant_time_size
, header_holder_type
> implementation_defined;
/// @endcond
typedef implementation_defined type;
};
#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class O1, class O2, class O3, class O4, class O5>
#else
template<class T, class ...Options>
#endif
class avl_set
: public make_avl_set<T,
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
O1, O2, O3, O4, O5
#else
Options...
#endif
>::type
{
typedef typename make_avl_set
<T,
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
O1, O2, O3, O4, O5
#else
Options...
#endif
>::type Base;
BOOST_MOVABLE_BUT_NOT_COPYABLE(avl_set)
public:
typedef typename Base::value_compare value_compare;
typedef typename Base::value_traits value_traits;
typedef typename Base::iterator iterator;
typedef typename Base::const_iterator const_iterator;
//Assert if passed value traits are compatible with the type
BOOST_STATIC_ASSERT((detail::is_same<typename value_traits::value_type, T>::value));
explicit avl_set( const value_compare &cmp = value_compare()
, const value_traits &v_traits = value_traits())
: Base(cmp, v_traits)
{}
template<class Iterator>
avl_set( Iterator b, Iterator e
, const value_compare &cmp = value_compare()
, const value_traits &v_traits = value_traits())
: Base(b, e, cmp, v_traits)
{}
avl_set(BOOST_RV_REF(avl_set) x)
: Base(::boost::move(static_cast<Base&>(x)))
{}
avl_set& operator=(BOOST_RV_REF(avl_set) x)
{ return static_cast<avl_set &>(this->Base::operator=(::boost::move(static_cast<Base&>(x)))); }
static avl_set &container_from_end_iterator(iterator end_iterator)
{ return static_cast<avl_set &>(Base::container_from_end_iterator(end_iterator)); }
static const avl_set &container_from_end_iterator(const_iterator end_iterator)
{ return static_cast<const avl_set &>(Base::container_from_end_iterator(end_iterator)); }
static avl_set &container_from_iterator(iterator it)
{ return static_cast<avl_set &>(Base::container_from_iterator(it)); }
static const avl_set &container_from_iterator(const_iterator it)
{ return static_cast<const avl_set &>(Base::container_from_iterator(it)); }
};
#endif
//! The class template avl_multiset is an intrusive container, that mimics most of
//! the interface of std::_multiset as described in the C++ standard.
//!
//! The template parameter \c T is the type to be managed by the container.
//! The user can specify additional options and if no options are provided
//! default options are used.
//!
//! The container supports the following options:
//! \c base_hook<>/member_hook<>/value_traits<>,
//! \c constant_time_size<>, \c size_type<> and
//! \c compare<>.
#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class ValueTraits, class Compare, class SizeType, bool ConstantTimeSize, typename HeaderHolder>
#endif
class avl_multiset_impl
#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
: public bstree_impl<ValueTraits, Compare, SizeType, ConstantTimeSize, AvlTreeAlgorithms, HeaderHolder>
#endif
{
/// @cond
typedef bstree_impl<ValueTraits, Compare, SizeType, ConstantTimeSize, AvlTreeAlgorithms, HeaderHolder> tree_type;
BOOST_MOVABLE_BUT_NOT_COPYABLE(avl_multiset_impl)
typedef tree_type implementation_defined;
/// @endcond
public:
typedef typename implementation_defined::value_type value_type;
typedef typename implementation_defined::value_traits value_traits;
typedef typename implementation_defined::pointer pointer;
typedef typename implementation_defined::const_pointer const_pointer;
typedef typename implementation_defined::reference reference;
typedef typename implementation_defined::const_reference const_reference;
typedef typename implementation_defined::difference_type difference_type;
typedef typename implementation_defined::size_type size_type;
typedef typename implementation_defined::value_compare value_compare;
typedef typename implementation_defined::key_compare key_compare;
typedef typename implementation_defined::iterator iterator;
typedef typename implementation_defined::const_iterator const_iterator;
typedef typename implementation_defined::reverse_iterator reverse_iterator;
typedef typename implementation_defined::const_reverse_iterator const_reverse_iterator;
typedef typename implementation_defined::insert_commit_data insert_commit_data;
typedef typename implementation_defined::node_traits node_traits;
typedef typename implementation_defined::node node;
typedef typename implementation_defined::node_ptr node_ptr;
typedef typename implementation_defined::const_node_ptr const_node_ptr;
typedef typename implementation_defined::node_algorithms node_algorithms;
static const bool constant_time_size = tree_type::constant_time_size;
public:
//! @copydoc ::boost::intrusive::avltree::avltree(const value_compare &,const value_traits &)
explicit avl_multiset_impl( const value_compare &cmp = value_compare()
, const value_traits &v_traits = value_traits())
: tree_type(cmp, v_traits)
{}
//! @copydoc ::boost::intrusive::avltree::avltree(bool,Iterator,Iterator,const value_compare &,const value_traits &)
template<class Iterator>
avl_multiset_impl( Iterator b, Iterator e
, const value_compare &cmp = value_compare()
, const value_traits &v_traits = value_traits())
: tree_type(false, b, e, cmp, v_traits)
{}
//! @copydoc ::boost::intrusive::avltree::avltree(avltree &&)
avl_multiset_impl(BOOST_RV_REF(avl_multiset_impl) x)
: tree_type(::boost::move(static_cast<tree_type&>(x)))
{}
//! @copydoc ::boost::intrusive::avltree::operator=(avltree &&)
avl_multiset_impl& operator=(BOOST_RV_REF(avl_multiset_impl) x)
{ return static_cast<avl_multiset_impl&>(tree_type::operator=(::boost::move(static_cast<tree_type&>(x)))); }
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
//! @copydoc ::boost::intrusive::avltree::~avltree()
~avl_multiset_impl();
//! @copydoc ::boost::intrusive::avltree::begin()
iterator begin();
//! @copydoc ::boost::intrusive::avltree::begin()const
const_iterator begin() const;
//! @copydoc ::boost::intrusive::avltree::cbegin()const
const_iterator cbegin() const;
//! @copydoc ::boost::intrusive::avltree::end()
iterator end();
//! @copydoc ::boost::intrusive::avltree::end()const
const_iterator end() const;
//! @copydoc ::boost::intrusive::avltree::cend()const
const_iterator cend() const;
//! @copydoc ::boost::intrusive::avltree::rbegin()
reverse_iterator rbegin();
//! @copydoc ::boost::intrusive::avltree::rbegin()const
const_reverse_iterator rbegin() const;
//! @copydoc ::boost::intrusive::avltree::crbegin()const
const_reverse_iterator crbegin() const;
//! @copydoc ::boost::intrusive::avltree::rend()
reverse_iterator rend();
//! @copydoc ::boost::intrusive::avltree::rend()const
const_reverse_iterator rend() const;
//! @copydoc ::boost::intrusive::avltree::crend()const
const_reverse_iterator crend() const;
//! @copydoc ::boost::intrusive::avltree::container_from_end_iterator(iterator)
static avl_multiset_impl &container_from_end_iterator(iterator end_iterator);
//! @copydoc ::boost::intrusive::avltree::container_from_end_iterator(const_iterator)
static const avl_multiset_impl &container_from_end_iterator(const_iterator end_iterator);
//! @copydoc ::boost::intrusive::avltree::container_from_iterator(iterator)
static avl_multiset_impl &container_from_iterator(iterator it);
//! @copydoc ::boost::intrusive::avltree::container_from_iterator(const_iterator)
static const avl_multiset_impl &container_from_iterator(const_iterator it);
//! @copydoc ::boost::intrusive::avltree::key_comp()const
key_compare key_comp() const;
//! @copydoc ::boost::intrusive::avltree::value_comp()const
value_compare value_comp() const;
//! @copydoc ::boost::intrusive::avltree::empty()const
bool empty() const;
//! @copydoc ::boost::intrusive::avltree::size()const
size_type size() const;
//! @copydoc ::boost::intrusive::avltree::swap
void swap(avl_multiset_impl& other);
//! @copydoc ::boost::intrusive::avltree::clone_from
template <class Cloner, class Disposer>
void clone_from(const avl_multiset_impl &src, Cloner cloner, Disposer disposer);
#endif //#ifdef BOOST_iNTRUSIVE_DOXYGEN_INVOKED
//! @copydoc ::boost::intrusive::avltree::insert_equal(reference)
iterator insert(reference value)
{ return tree_type::insert_equal(value); }
//! @copydoc ::boost::intrusive::avltree::insert_equal(const_iterator,reference)
iterator insert(const_iterator hint, reference value)
{ return tree_type::insert_equal(hint, value); }
//! @copydoc ::boost::intrusive::avltree::insert_equal(Iterator,Iterator)
template<class Iterator>
void insert(Iterator b, Iterator e)
{ tree_type::insert_equal(b, e); }
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
//! @copydoc ::boost::intrusive::avltree::insert_before
iterator insert_before(const_iterator pos, reference value);
//! @copydoc ::boost::intrusive::avltree::push_back
void push_back(reference value);
//! @copydoc ::boost::intrusive::avltree::push_front
void push_front(reference value);
//! @copydoc ::boost::intrusive::avltree::erase(const_iterator)
iterator erase(const_iterator i);
//! @copydoc ::boost::intrusive::avltree::erase(const_iterator,const_iterator)
iterator erase(const_iterator b, const_iterator e);
//! @copydoc ::boost::intrusive::avltree::erase(const_reference)
size_type erase(const_reference value);
//! @copydoc ::boost::intrusive::avltree::erase(const KeyType&,KeyValueCompare)
template<class KeyType, class KeyValueCompare>
size_type erase(const KeyType& key, KeyValueCompare comp);
//! @copydoc ::boost::intrusive::avltree::erase_and_dispose(const_iterator,Disposer)
template<class Disposer>
iterator erase_and_dispose(const_iterator i, Disposer disposer);
//! @copydoc ::boost::intrusive::avltree::erase_and_dispose(const_iterator,const_iterator,Disposer)
template<class Disposer>
iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer);
//! @copydoc ::boost::intrusive::avltree::erase_and_dispose(const_reference, Disposer)
template<class Disposer>
size_type erase_and_dispose(const_reference value, Disposer disposer);
//! @copydoc ::boost::intrusive::avltree::erase_and_dispose(const KeyType&,KeyValueCompare,Disposer)
template<class KeyType, class KeyValueCompare, class Disposer>
size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer);
//! @copydoc ::boost::intrusive::avltree::clear
void clear();
//! @copydoc ::boost::intrusive::avltree::clear_and_dispose
template<class Disposer>
void clear_and_dispose(Disposer disposer);
//! @copydoc ::boost::intrusive::avltree::count(const_reference)const
size_type count(const_reference value) const;
//! @copydoc ::boost::intrusive::avltree::count(const KeyType&,KeyValueCompare)const
template<class KeyType, class KeyValueCompare>
size_type count(const KeyType& key, KeyValueCompare comp) const;
//! @copydoc ::boost::intrusive::avltree::lower_bound(const_reference)
iterator lower_bound(const_reference value);
//! @copydoc ::boost::intrusive::avltree::lower_bound(const KeyType&,KeyValueCompare)
template<class KeyType, class KeyValueCompare>
iterator lower_bound(const KeyType& key, KeyValueCompare comp);
//! @copydoc ::boost::intrusive::avltree::lower_bound(const_reference)const
const_iterator lower_bound(const_reference value) const;
//! @copydoc ::boost::intrusive::avltree::lower_bound(const KeyType&,KeyValueCompare)const
template<class KeyType, class KeyValueCompare>
const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const;
//! @copydoc ::boost::intrusive::avltree::upper_bound(const_reference)
iterator upper_bound(const_reference value);
//! @copydoc ::boost::intrusive::avltree::upper_bound(const KeyType&,KeyValueCompare)
template<class KeyType, class KeyValueCompare>
iterator upper_bound(const KeyType& key, KeyValueCompare comp);
//! @copydoc ::boost::intrusive::avltree::upper_bound(const_reference)const
const_iterator upper_bound(const_reference value) const;
//! @copydoc ::boost::intrusive::avltree::upper_bound(const KeyType&,KeyValueCompare)const
template<class KeyType, class KeyValueCompare>
const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const;
//! @copydoc ::boost::intrusive::avltree::find(const_reference)
iterator find(const_reference value);
//! @copydoc ::boost::intrusive::avltree::find(const KeyType&,KeyValueCompare)
template<class KeyType, class KeyValueCompare>
iterator find(const KeyType& key, KeyValueCompare comp);
//! @copydoc ::boost::intrusive::avltree::find(const_reference)const
const_iterator find(const_reference value) const;
//! @copydoc ::boost::intrusive::avltree::find(const KeyType&,KeyValueCompare)const
template<class KeyType, class KeyValueCompare>
const_iterator find(const KeyType& key, KeyValueCompare comp) const;
//! @copydoc ::boost::intrusive::avltree::equal_range(const_reference)
std::pair<iterator,iterator> equal_range(const_reference value);
//! @copydoc ::boost::intrusive::avltree::equal_range(const KeyType&,KeyValueCompare)
template<class KeyType, class KeyValueCompare>
std::pair<iterator,iterator> equal_range(const KeyType& key, KeyValueCompare comp);
//! @copydoc ::boost::intrusive::avltree::equal_range(const_reference)const
std::pair<const_iterator, const_iterator>
equal_range(const_reference value) const;
//! @copydoc ::boost::intrusive::avltree::equal_range(const KeyType&,KeyValueCompare)const
template<class KeyType, class KeyValueCompare>
std::pair<const_iterator, const_iterator>
equal_range(const KeyType& key, KeyValueCompare comp) const;
//! @copydoc ::boost::intrusive::avltree::bounded_range(const_reference,const_reference,bool,bool)
std::pair<iterator,iterator> bounded_range
(const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed);
//! @copydoc ::boost::intrusive::avltree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool)
template<class KeyType, class KeyValueCompare>
std::pair<iterator,iterator> bounded_range
(const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed);
//! @copydoc ::boost::intrusive::avltree::bounded_range(const_reference,const_reference,bool,bool)const
std::pair<const_iterator, const_iterator>
bounded_range(const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const;
//! @copydoc ::boost::intrusive::avltree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool)const
template<class KeyType, class KeyValueCompare>
std::pair<const_iterator, const_iterator> bounded_range
(const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const;
//! @copydoc ::boost::intrusive::avltree::s_iterator_to(reference)
static iterator s_iterator_to(reference value);
//! @copydoc ::boost::intrusive::avltree::s_iterator_to(const_reference)
static const_iterator s_iterator_to(const_reference value);
//! @copydoc ::boost::intrusive::avltree::iterator_to(reference)
iterator iterator_to(reference value);
//! @copydoc ::boost::intrusive::avltree::iterator_to(const_reference)const
const_iterator iterator_to(const_reference value) const;
//! @copydoc ::boost::intrusive::avltree::init_node(reference)
static void init_node(reference value);
//! @copydoc ::boost::intrusive::avltree::unlink_leftmost_without_rebalance
pointer unlink_leftmost_without_rebalance();
//! @copydoc ::boost::intrusive::avltree::replace_node
void replace_node(iterator replace_this, reference with_this);
//! @copydoc ::boost::intrusive::avltree::remove_node
void remove_node(reference value);
#endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
};
#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
bool operator!= (const avl_multiset_impl<T, Options...> &x, const avl_multiset_impl<T, Options...> &y);
template<class T, class ...Options>
bool operator>(const avl_multiset_impl<T, Options...> &x, const avl_multiset_impl<T, Options...> &y);
template<class T, class ...Options>
bool operator<=(const avl_multiset_impl<T, Options...> &x, const avl_multiset_impl<T, Options...> &y);
template<class T, class ...Options>
bool operator>=(const avl_multiset_impl<T, Options...> &x, const avl_multiset_impl<T, Options...> &y);
template<class T, class ...Options>
void swap(avl_multiset_impl<T, Options...> &x, avl_multiset_impl<T, Options...> &y);
#endif //#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
//! Helper metafunction to define a \c avl_multiset that yields to the same type when the
//! same options (either explicitly or implicitly) are used.
#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class ...Options>
#else
template<class T, class O1 = void, class O2 = void
, class O3 = void, class O4 = void
, class O5 = void>
#endif
struct make_avl_multiset
{
/// @cond
typedef typename pack_options
< avltree_defaults,
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
O1, O2, O3, O4, O5
#else
Options...
#endif
>::type packed_options;
typedef typename detail::get_value_traits
<T, typename packed_options::proto_value_traits>::type value_traits;
typedef typename detail::get_header_holder_type
< value_traits, typename packed_options::header_holder_type >::type header_holder_type;
typedef avl_multiset_impl
< value_traits
, typename packed_options::compare
, typename packed_options::size_type
, packed_options::constant_time_size
, header_holder_type
> implementation_defined;
/// @endcond
typedef implementation_defined type;
};
#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class O1, class O2, class O3, class O4, class O5>
#else
template<class T, class ...Options>
#endif
class avl_multiset
: public make_avl_multiset<T,
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
O1, O2, O3, O4, O5
#else
Options...
#endif
>::type
{
typedef typename make_avl_multiset<T,
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
O1, O2, O3, O4, O5
#else
Options...
#endif
>::type Base;
BOOST_MOVABLE_BUT_NOT_COPYABLE(avl_multiset)
public:
typedef typename Base::value_compare value_compare;
typedef typename Base::value_traits value_traits;
typedef typename Base::iterator iterator;
typedef typename Base::const_iterator const_iterator;
//Assert if passed value traits are compatible with the type
BOOST_STATIC_ASSERT((detail::is_same<typename value_traits::value_type, T>::value));
explicit avl_multiset( const value_compare &cmp = value_compare()
, const value_traits &v_traits = value_traits())
: Base(cmp, v_traits)
{}
template<class Iterator>
avl_multiset( Iterator b, Iterator e
, const value_compare &cmp = value_compare()
, const value_traits &v_traits = value_traits())
: Base(b, e, cmp, v_traits)
{}
avl_multiset(BOOST_RV_REF(avl_multiset) x)
: Base(::boost::move(static_cast<Base&>(x)))
{}
avl_multiset& operator=(BOOST_RV_REF(avl_multiset) x)
{ return static_cast<avl_multiset &>(this->Base::operator=(::boost::move(static_cast<Base&>(x)))); }
static avl_multiset &container_from_end_iterator(iterator end_iterator)
{ return static_cast<avl_multiset &>(Base::container_from_end_iterator(end_iterator)); }
static const avl_multiset &container_from_end_iterator(const_iterator end_iterator)
{ return static_cast<const avl_multiset &>(Base::container_from_end_iterator(end_iterator)); }
static avl_multiset &container_from_iterator(iterator it)
{ return static_cast<avl_multiset &>(Base::container_from_iterator(it)); }
static const avl_multiset &container_from_iterator(const_iterator it)
{ return static_cast<const avl_multiset &>(Base::container_from_iterator(it)); }
};
#endif
} //namespace intrusive
} //namespace boost
#include <boost/intrusive/detail/config_end.hpp>
#endif //BOOST_INTRUSIVE_AVL_SET_HPP

View file

@ -0,0 +1,291 @@
/////////////////////////////////////////////////////////////////////////////
//
// (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/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_AVL_SET_HOOK_HPP
#define BOOST_INTRUSIVE_AVL_SET_HOOK_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/intrusive/detail/config_begin.hpp>
#include <boost/intrusive/intrusive_fwd.hpp>
#include <boost/intrusive/detail/avltree_node.hpp>
#include <boost/intrusive/avltree_algorithms.hpp>
#include <boost/intrusive/options.hpp>
#include <boost/intrusive/detail/generic_hook.hpp>
namespace boost {
namespace intrusive {
//! Helper metafunction to define a \c avl_set_base_hook that yields to the same
//! type when the same options (either explicitly or implicitly) are used.
#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class ...Options>
#else
template<class O1 = void, class O2 = void, class O3 = void, class O4 = void>
#endif
struct make_avl_set_base_hook
{
/// @cond
typedef typename pack_options
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
<hook_defaults, O1, O2, O3, O4>
#else
<hook_defaults, Options...>
#endif
::type packed_options;
typedef generic_hook
< avltree_algorithms<avltree_node_traits<typename packed_options::void_pointer, packed_options::optimize_size> >
, typename packed_options::tag
, packed_options::link_mode
, AvlTreeBaseHookId
> implementation_defined;
/// @endcond
typedef implementation_defined type;
};
//! Derive a class from avl_set_base_hook in order to store objects in
//! in an avl_set/avl_multiset. avl_set_base_hook holds the data necessary to maintain
//! the avl_set/avl_multiset and provides an appropriate value_traits class for avl_set/avl_multiset.
//!
//! The hook admits the following options: \c tag<>, \c void_pointer<>,
//! \c link_mode<> and \c optimize_size<>.
//!
//! \c tag<> defines a tag to identify the node.
//! The same tag value can be used in different classes, but if a class is
//! derived from more than one \c list_base_hook, then each \c list_base_hook needs its
//! unique tag.
//!
//! \c void_pointer<> is the pointer type that will be used internally in the hook
//! and the container configured to use this hook.
//!
//! \c link_mode<> will specify the linking mode of the hook (\c normal_link,
//! \c auto_unlink or \c safe_link).
//!
//! \c optimize_size<> will tell the hook to optimize the hook for size instead
//! of speed.
#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class ...Options>
#else
template<class O1, class O2, class O3, class O4>
#endif
class avl_set_base_hook
: public make_avl_set_base_hook
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
<O1, O2, O3, O4>
#else
<Options...>
#endif
::type
{
#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
public:
//! <b>Effects</b>: If link_mode is \c auto_unlink or \c safe_link
//! initializes the node to an unlinked state.
//!
//! <b>Throws</b>: Nothing.
avl_set_base_hook();
//! <b>Effects</b>: If link_mode is \c auto_unlink or \c safe_link
//! initializes the node to an unlinked state. The argument is ignored.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Rationale</b>: Providing a copy-constructor
//! makes classes using the hook STL-compliant without forcing the
//! user to do some additional work. \c swap can be used to emulate
//! move-semantics.
avl_set_base_hook(const avl_set_base_hook& );
//! <b>Effects</b>: Empty function. The argument is ignored.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Rationale</b>: Providing an assignment operator
//! makes classes using the hook STL-compliant without forcing the
//! user to do some additional work. \c swap can be used to emulate
//! move-semantics.
avl_set_base_hook& operator=(const avl_set_base_hook& );
//! <b>Effects</b>: If link_mode is \c normal_link, the destructor does
//! nothing (ie. no code is generated). If link_mode is \c safe_link and the
//! object is stored in a set an assertion is raised. If link_mode is
//! \c auto_unlink and \c is_linked() is true, the node is unlinked.
//!
//! <b>Throws</b>: Nothing.
~avl_set_base_hook();
//! <b>Effects</b>: Swapping two nodes swaps the position of the elements
//! related to those nodes in one or two containers. That is, if the node
//! this is part of the element e1, the node x is part of the element e2
//! and both elements are included in the containers s1 and s2, then after
//! the swap-operation e1 is in s2 at the position of e2 and e2 is in s1
//! at the position of e1. If one element is not in a container, then
//! after the swap-operation the other element is not in a container.
//! Iterators to e1 and e2 related to those nodes are invalidated.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
void swap_nodes(avl_set_base_hook &other);
//! <b>Precondition</b>: link_mode must be \c safe_link or \c auto_unlink.
//!
//! <b>Returns</b>: true, if the node belongs to a container, false
//! otherwise. This function can be used to test whether \c set::iterator_to
//! will return a valid iterator.
//!
//! <b>Complexity</b>: Constant
bool is_linked() const;
//! <b>Effects</b>: Removes the node if it's inserted in a container.
//! This function is only allowed if link_mode is \c auto_unlink.
//!
//! <b>Throws</b>: Nothing.
void unlink();
#endif
};
//! Helper metafunction to define a \c avl_set_member_hook that yields to the same
//! type when the same options (either explicitly or implicitly) are used.
#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class ...Options>
#else
template<class O1 = void, class O2 = void, class O3 = void, class O4 = void>
#endif
struct make_avl_set_member_hook
{
/// @cond
typedef typename pack_options
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
<hook_defaults, O1, O2, O3, O4>
#else
<hook_defaults, Options...>
#endif
::type packed_options;
typedef generic_hook
< avltree_algorithms<avltree_node_traits<typename packed_options::void_pointer, packed_options::optimize_size> >
, member_tag
, packed_options::link_mode
, NoBaseHookId
> implementation_defined;
/// @endcond
typedef implementation_defined type;
};
//! Put a public data member avl_set_member_hook in order to store objects of this class in
//! an avl_set/avl_multiset. avl_set_member_hook holds the data necessary for maintaining the
//! avl_set/avl_multiset and provides an appropriate value_traits class for avl_set/avl_multiset.
//!
//! The hook admits the following options: \c void_pointer<>,
//! \c link_mode<> and \c optimize_size<>.
//!
//! \c void_pointer<> is the pointer type that will be used internally in the hook
//! and the container configured to use this hook.
//!
//! \c link_mode<> will specify the linking mode of the hook (\c normal_link,
//! \c auto_unlink or \c safe_link).
//!
//! \c optimize_size<> will tell the hook to optimize the hook for size instead
//! of speed.
#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class ...Options>
#else
template<class O1, class O2, class O3, class O4>
#endif
class avl_set_member_hook
: public make_avl_set_member_hook
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
<O1, O2, O3, O4>
#else
<Options...>
#endif
::type
{
#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
public:
//! <b>Effects</b>: If link_mode is \c auto_unlink or \c safe_link
//! initializes the node to an unlinked state.
//!
//! <b>Throws</b>: Nothing.
avl_set_member_hook();
//! <b>Effects</b>: If link_mode is \c auto_unlink or \c safe_link
//! initializes the node to an unlinked state. The argument is ignored.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Rationale</b>: Providing a copy-constructor
//! makes classes using the hook STL-compliant without forcing the
//! user to do some additional work. \c swap can be used to emulate
//! move-semantics.
avl_set_member_hook(const avl_set_member_hook& );
//! <b>Effects</b>: Empty function. The argument is ignored.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Rationale</b>: Providing an assignment operator
//! makes classes using the hook STL-compliant without forcing the
//! user to do some additional work. \c swap can be used to emulate
//! move-semantics.
avl_set_member_hook& operator=(const avl_set_member_hook& );
//! <b>Effects</b>: If link_mode is \c normal_link, the destructor does
//! nothing (ie. no code is generated). If link_mode is \c safe_link and the
//! object is stored in a set an assertion is raised. If link_mode is
//! \c auto_unlink and \c is_linked() is true, the node is unlinked.
//!
//! <b>Throws</b>: Nothing.
~avl_set_member_hook();
//! <b>Effects</b>: Swapping two nodes swaps the position of the elements
//! related to those nodes in one or two containers. That is, if the node
//! this is part of the element e1, the node x is part of the element e2
//! and both elements are included in the containers s1 and s2, then after
//! the swap-operation e1 is in s2 at the position of e2 and e2 is in s1
//! at the position of e1. If one element is not in a container, then
//! after the swap-operation the other element is not in a container.
//! Iterators to e1 and e2 related to those nodes are invalidated.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
void swap_nodes(avl_set_member_hook &other);
//! <b>Precondition</b>: link_mode must be \c safe_link or \c auto_unlink.
//!
//! <b>Returns</b>: true, if the node belongs to a container, false
//! otherwise. This function can be used to test whether \c set::iterator_to
//! will return a valid iterator.
//!
//! <b>Complexity</b>: Constant
bool is_linked() const;
//! <b>Effects</b>: Removes the node if it's inserted in a container.
//! This function is only allowed if link_mode is \c auto_unlink.
//!
//! <b>Throws</b>: Nothing.
void unlink();
#endif
};
} //namespace intrusive
} //namespace boost
#include <boost/intrusive/detail/config_end.hpp>
#endif //BOOST_INTRUSIVE_AVL_SET_HOOK_HPP

549
boost/intrusive/avltree.hpp Normal file
View file

@ -0,0 +1,549 @@
/////////////////////////////////////////////////////////////////////////////
//
// (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/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_AVLTREE_HPP
#define BOOST_INTRUSIVE_AVLTREE_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/intrusive/detail/config_begin.hpp>
#include <boost/intrusive/intrusive_fwd.hpp>
#include <cstddef>
#include <functional>
#include <utility>
#include <boost/static_assert.hpp>
#include <boost/intrusive/avl_set_hook.hpp>
#include <boost/intrusive/detail/avltree_node.hpp>
#include <boost/intrusive/bstree.hpp>
#include <boost/intrusive/detail/tree_node.hpp>
#include <boost/intrusive/detail/ebo_functor_holder.hpp>
#include <boost/intrusive/detail/mpl.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/intrusive/detail/get_value_traits.hpp>
#include <boost/intrusive/avltree_algorithms.hpp>
#include <boost/intrusive/link_mode.hpp>
#include <boost/move/utility_core.hpp>
namespace boost {
namespace intrusive {
/// @cond
struct default_avltree_hook_applier
{ template <class T> struct apply{ typedef typename T::default_avltree_hook type; }; };
template<>
struct is_default_hook_tag<default_avltree_hook_applier>
{ static const bool value = true; };
struct avltree_defaults
{
typedef default_avltree_hook_applier proto_value_traits;
static const bool constant_time_size = true;
typedef std::size_t size_type;
typedef void compare;
typedef void header_holder_type;
};
/// @endcond
//! The class template avltree is an intrusive AVL tree container, that
//! is used to construct intrusive avl_set and avl_multiset containers.
//! The no-throw guarantee holds only, if the value_compare object
//! doesn't throw.
//!
//! The template parameter \c T is the type to be managed by the container.
//! The user can specify additional options and if no options are provided
//! default options are used.
//!
//! The container supports the following options:
//! \c base_hook<>/member_hook<>/value_traits<>,
//! \c constant_time_size<>, \c size_type<> and
//! \c compare<>.
#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class ValueTraits, class VoidOrKeyComp, class SizeType, bool ConstantTimeSize, typename HeaderHolder>
#endif
class avltree_impl
/// @cond
: public bstree_impl<ValueTraits, VoidOrKeyComp, SizeType, ConstantTimeSize, AvlTreeAlgorithms, HeaderHolder>
/// @endcond
{
public:
typedef ValueTraits value_traits;
/// @cond
typedef bstree_impl< ValueTraits, VoidOrKeyComp, SizeType
, ConstantTimeSize, AvlTreeAlgorithms
, HeaderHolder> tree_type;
typedef tree_type implementation_defined;
/// @endcond
typedef typename implementation_defined::pointer pointer;
typedef typename implementation_defined::const_pointer const_pointer;
typedef typename implementation_defined::value_type value_type;
typedef typename implementation_defined::key_type key_type;
typedef typename implementation_defined::reference reference;
typedef typename implementation_defined::const_reference const_reference;
typedef typename implementation_defined::difference_type difference_type;
typedef typename implementation_defined::size_type size_type;
typedef typename implementation_defined::value_compare value_compare;
typedef typename implementation_defined::key_compare key_compare;
typedef typename implementation_defined::iterator iterator;
typedef typename implementation_defined::const_iterator const_iterator;
typedef typename implementation_defined::reverse_iterator reverse_iterator;
typedef typename implementation_defined::const_reverse_iterator const_reverse_iterator;
typedef typename implementation_defined::node_traits node_traits;
typedef typename implementation_defined::node node;
typedef typename implementation_defined::node_ptr node_ptr;
typedef typename implementation_defined::const_node_ptr const_node_ptr;
typedef typename implementation_defined::node_algorithms node_algorithms;
static const bool constant_time_size = implementation_defined::constant_time_size;
/// @cond
private:
//noncopyable
BOOST_MOVABLE_BUT_NOT_COPYABLE(avltree_impl)
/// @endcond
public:
typedef typename implementation_defined::insert_commit_data insert_commit_data;
//! @copydoc ::boost::intrusive::bstree::bstree(const value_compare &,const value_traits &)
explicit avltree_impl( const value_compare &cmp = value_compare()
, const value_traits &v_traits = value_traits())
: tree_type(cmp, v_traits)
{}
//! @copydoc ::boost::intrusive::bstree::bstree(bool,Iterator,Iterator,const value_compare &,const value_traits &)
template<class Iterator>
avltree_impl( bool unique, Iterator b, Iterator e
, const value_compare &cmp = value_compare()
, const value_traits &v_traits = value_traits())
: tree_type(unique, b, e, cmp, v_traits)
{}
//! @copydoc ::boost::intrusive::bstree::bstree(bstree &&)
avltree_impl(BOOST_RV_REF(avltree_impl) x)
: tree_type(::boost::move(static_cast<tree_type&>(x)))
{}
//! @copydoc ::boost::intrusive::bstree::operator=(bstree &&)
avltree_impl& operator=(BOOST_RV_REF(avltree_impl) x)
{ return static_cast<avltree_impl&>(tree_type::operator=(::boost::move(static_cast<tree_type&>(x)))); }
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
//! @copydoc ::boost::intrusive::bstree::~bstree()
~avltree_impl();
//! @copydoc ::boost::intrusive::bstree::begin()
iterator begin();
//! @copydoc ::boost::intrusive::bstree::begin()const
const_iterator begin() const;
//! @copydoc ::boost::intrusive::bstree::cbegin()const
const_iterator cbegin() const;
//! @copydoc ::boost::intrusive::bstree::end()
iterator end();
//! @copydoc ::boost::intrusive::bstree::end()const
const_iterator end() const;
//! @copydoc ::boost::intrusive::bstree::cend()const
const_iterator cend() const;
//! @copydoc ::boost::intrusive::bstree::rbegin()
reverse_iterator rbegin();
//! @copydoc ::boost::intrusive::bstree::rbegin()const
const_reverse_iterator rbegin() const;
//! @copydoc ::boost::intrusive::bstree::crbegin()const
const_reverse_iterator crbegin() const;
//! @copydoc ::boost::intrusive::bstree::rend()
reverse_iterator rend();
//! @copydoc ::boost::intrusive::bstree::rend()const
const_reverse_iterator rend() const;
//! @copydoc ::boost::intrusive::bstree::crend()const
const_reverse_iterator crend() const;
//! @copydoc ::boost::intrusive::bstree::container_from_end_iterator(iterator)
static avltree_impl &container_from_end_iterator(iterator end_iterator);
//! @copydoc ::boost::intrusive::bstree::container_from_end_iterator(const_iterator)
static const avltree_impl &container_from_end_iterator(const_iterator end_iterator);
//! @copydoc ::boost::intrusive::bstree::container_from_iterator(iterator)
static avltree_impl &container_from_iterator(iterator it);
//! @copydoc ::boost::intrusive::bstree::container_from_iterator(const_iterator)
static const avltree_impl &container_from_iterator(const_iterator it);
//! @copydoc ::boost::intrusive::bstree::key_comp()const
key_compare key_comp() const;
//! @copydoc ::boost::intrusive::bstree::value_comp()const
value_compare value_comp() const;
//! @copydoc ::boost::intrusive::bstree::empty()const
bool empty() const;
//! @copydoc ::boost::intrusive::bstree::size()const
size_type size() const;
//! @copydoc ::boost::intrusive::bstree::swap
void swap(avltree_impl& other);
//! @copydoc ::boost::intrusive::bstree::clone_from
template <class Cloner, class Disposer>
void clone_from(const avltree_impl &src, Cloner cloner, Disposer disposer);
//! @copydoc ::boost::intrusive::bstree::insert_equal(reference)
iterator insert_equal(reference value);
//! @copydoc ::boost::intrusive::bstree::insert_equal(const_iterator,reference)
iterator insert_equal(const_iterator hint, reference value);
//! @copydoc ::boost::intrusive::bstree::insert_equal(Iterator,Iterator)
template<class Iterator>
void insert_equal(Iterator b, Iterator e);
//! @copydoc ::boost::intrusive::bstree::insert_unique(reference)
std::pair<iterator, bool> insert_unique(reference value);
//! @copydoc ::boost::intrusive::bstree::insert_unique(const_iterator,reference)
iterator insert_unique(const_iterator hint, reference value);
//! @copydoc ::boost::intrusive::bstree::insert_unique_check(const KeyType&,KeyValueCompare,insert_commit_data&)
template<class KeyType, class KeyValueCompare>
std::pair<iterator, bool> insert_unique_check
(const KeyType &key, KeyValueCompare key_value_comp, insert_commit_data &commit_data);
//! @copydoc ::boost::intrusive::bstree::insert_unique_check(const_iterator,const KeyType&,KeyValueCompare,insert_commit_data&)
template<class KeyType, class KeyValueCompare>
std::pair<iterator, bool> insert_unique_check
(const_iterator hint, const KeyType &key
,KeyValueCompare key_value_comp, insert_commit_data &commit_data);
//! @copydoc ::boost::intrusive::bstree::insert_unique_commit
iterator insert_unique_commit(reference value, const insert_commit_data &commit_data);
//! @copydoc ::boost::intrusive::bstree::insert_unique(Iterator,Iterator)
template<class Iterator>
void insert_unique(Iterator b, Iterator e);
//! @copydoc ::boost::intrusive::bstree::insert_before
iterator insert_before(const_iterator pos, reference value);
//! @copydoc ::boost::intrusive::bstree::push_back
void push_back(reference value);
//! @copydoc ::boost::intrusive::bstree::push_front
void push_front(reference value);
//! @copydoc ::boost::intrusive::bstree::erase(const_iterator)
iterator erase(const_iterator i);
//! @copydoc ::boost::intrusive::bstree::erase(const_iterator,const_iterator)
iterator erase(const_iterator b, const_iterator e);
//! @copydoc ::boost::intrusive::bstree::erase(const_reference)
size_type erase(const_reference value);
//! @copydoc ::boost::intrusive::bstree::erase(const KeyType&,KeyValueCompare)
template<class KeyType, class KeyValueCompare>
size_type erase(const KeyType& key, KeyValueCompare comp);
//! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const_iterator,Disposer)
template<class Disposer>
iterator erase_and_dispose(const_iterator i, Disposer disposer);
//! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const_iterator,const_iterator,Disposer)
template<class Disposer>
iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer);
//! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const_reference, Disposer)
template<class Disposer>
size_type erase_and_dispose(const_reference value, Disposer disposer);
//! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const KeyType&,KeyValueCompare,Disposer)
template<class KeyType, class KeyValueCompare, class Disposer>
size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer);
//! @copydoc ::boost::intrusive::bstree::clear
void clear();
//! @copydoc ::boost::intrusive::bstree::clear_and_dispose
template<class Disposer>
void clear_and_dispose(Disposer disposer);
//! @copydoc ::boost::intrusive::bstree::count(const_reference)const
size_type count(const_reference value) const;
//! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyValueCompare)const
template<class KeyType, class KeyValueCompare>
size_type count(const KeyType& key, KeyValueCompare comp) const;
//! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference)
iterator lower_bound(const_reference value);
//! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyValueCompare)
template<class KeyType, class KeyValueCompare>
iterator lower_bound(const KeyType& key, KeyValueCompare comp);
//! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference)const
const_iterator lower_bound(const_reference value) const;
//! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyValueCompare)const
template<class KeyType, class KeyValueCompare>
const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const;
//! @copydoc ::boost::intrusive::bstree::upper_bound(const_reference)
iterator upper_bound(const_reference value);
//! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyValueCompare)
template<class KeyType, class KeyValueCompare>
iterator upper_bound(const KeyType& key, KeyValueCompare comp);
//! @copydoc ::boost::intrusive::bstree::upper_bound(const_reference)const
const_iterator upper_bound(const_reference value) const;
//! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyValueCompare)const
template<class KeyType, class KeyValueCompare>
const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const;
//! @copydoc ::boost::intrusive::bstree::find(const_reference)
iterator find(const_reference value);
//! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyValueCompare)
template<class KeyType, class KeyValueCompare>
iterator find(const KeyType& key, KeyValueCompare comp);
//! @copydoc ::boost::intrusive::bstree::find(const_reference)const
const_iterator find(const_reference value) const;
//! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyValueCompare)const
template<class KeyType, class KeyValueCompare>
const_iterator find(const KeyType& key, KeyValueCompare comp) const;
//! @copydoc ::boost::intrusive::bstree::equal_range(const_reference)
std::pair<iterator,iterator> equal_range(const_reference value);
//! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyValueCompare)
template<class KeyType, class KeyValueCompare>
std::pair<iterator,iterator> equal_range(const KeyType& key, KeyValueCompare comp);
//! @copydoc ::boost::intrusive::bstree::equal_range(const_reference)const
std::pair<const_iterator, const_iterator>
equal_range(const_reference value) const;
//! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyValueCompare)const
template<class KeyType, class KeyValueCompare>
std::pair<const_iterator, const_iterator>
equal_range(const KeyType& key, KeyValueCompare comp) const;
//! @copydoc ::boost::intrusive::bstree::bounded_range(const_reference,const_reference,bool,bool)
std::pair<iterator,iterator> bounded_range
(const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed);
//! @copydoc ::boost::intrusive::bstree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool)
template<class KeyType, class KeyValueCompare>
std::pair<iterator,iterator> bounded_range
(const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed);
//! @copydoc ::boost::intrusive::bstree::bounded_range(const_reference,const_reference,bool,bool)const
std::pair<const_iterator, const_iterator>
bounded_range(const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const;
//! @copydoc ::boost::intrusive::bstree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool)const
template<class KeyType, class KeyValueCompare>
std::pair<const_iterator, const_iterator> bounded_range
(const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const;
//! @copydoc ::boost::intrusive::bstree::s_iterator_to(reference)
static iterator s_iterator_to(reference value);
//! @copydoc ::boost::intrusive::bstree::s_iterator_to(const_reference)
static const_iterator s_iterator_to(const_reference value);
//! @copydoc ::boost::intrusive::bstree::iterator_to(reference)
iterator iterator_to(reference value);
//! @copydoc ::boost::intrusive::bstree::iterator_to(const_reference)const
const_iterator iterator_to(const_reference value) const;
//! @copydoc ::boost::intrusive::bstree::init_node(reference)
static void init_node(reference value);
//! @copydoc ::boost::intrusive::bstree::unlink_leftmost_without_rebalance
pointer unlink_leftmost_without_rebalance();
//! @copydoc ::boost::intrusive::bstree::replace_node
void replace_node(iterator replace_this, reference with_this);
//! @copydoc ::boost::intrusive::bstree::remove_node
void remove_node(reference value);
#endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
};
#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
bool operator< (const avltree_impl<T, Options...> &x, const avltree_impl<T, Options...> &y);
template<class T, class ...Options>
bool operator==(const avltree_impl<T, Options...> &x, const avltree_impl<T, Options...> &y);
template<class T, class ...Options>
bool operator!= (const avltree_impl<T, Options...> &x, const avltree_impl<T, Options...> &y);
template<class T, class ...Options>
bool operator>(const avltree_impl<T, Options...> &x, const avltree_impl<T, Options...> &y);
template<class T, class ...Options>
bool operator<=(const avltree_impl<T, Options...> &x, const avltree_impl<T, Options...> &y);
template<class T, class ...Options>
bool operator>=(const avltree_impl<T, Options...> &x, const avltree_impl<T, Options...> &y);
template<class T, class ...Options>
void swap(avltree_impl<T, Options...> &x, avltree_impl<T, Options...> &y);
#endif //#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
//! Helper metafunction to define a \c avltree that yields to the same type when the
//! same options (either explicitly or implicitly) are used.
#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class ...Options>
#else
template<class T, class O1 = void, class O2 = void
, class O3 = void, class O4 = void
, class O5 = void>
#endif
struct make_avltree
{
/// @cond
typedef typename pack_options
< avltree_defaults,
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
O1, O2, O3, O4, O5
#else
Options...
#endif
>::type packed_options;
typedef typename detail::get_value_traits
<T, typename packed_options::proto_value_traits>::type value_traits;
typedef typename detail::get_header_holder_type
< value_traits, typename packed_options::header_holder_type >::type header_holder_type;
typedef avltree_impl
< value_traits
, typename packed_options::compare
, typename packed_options::size_type
, packed_options::constant_time_size
, header_holder_type
> implementation_defined;
/// @endcond
typedef implementation_defined type;
};
#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class O1, class O2, class O3, class O4, class O5>
#else
template<class T, class ...Options>
#endif
class avltree
: public make_avltree<T,
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
O1, O2, O3, O4, O5
#else
Options...
#endif
>::type
{
typedef typename make_avltree
<T,
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
O1, O2, O3, O4, O5
#else
Options...
#endif
>::type Base;
BOOST_MOVABLE_BUT_NOT_COPYABLE(avltree)
public:
typedef typename Base::value_compare value_compare;
typedef typename Base::value_traits value_traits;
typedef typename Base::iterator iterator;
typedef typename Base::const_iterator const_iterator;
typedef typename Base::reverse_iterator reverse_iterator;
typedef typename Base::const_reverse_iterator const_reverse_iterator;
//Assert if passed value traits are compatible with the type
BOOST_STATIC_ASSERT((detail::is_same<typename value_traits::value_type, T>::value));
explicit avltree( const value_compare &cmp = value_compare()
, const value_traits &v_traits = value_traits())
: Base(cmp, v_traits)
{}
template<class Iterator>
avltree( bool unique, Iterator b, Iterator e
, const value_compare &cmp = value_compare()
, const value_traits &v_traits = value_traits())
: Base(unique, b, e, cmp, v_traits)
{}
avltree(BOOST_RV_REF(avltree) x)
: Base(::boost::move(static_cast<Base&>(x)))
{}
avltree& operator=(BOOST_RV_REF(avltree) x)
{ return static_cast<avltree &>(this->Base::operator=(::boost::move(static_cast<Base&>(x)))); }
static avltree &container_from_end_iterator(iterator end_iterator)
{ return static_cast<avltree &>(Base::container_from_end_iterator(end_iterator)); }
static const avltree &container_from_end_iterator(const_iterator end_iterator)
{ return static_cast<const avltree &>(Base::container_from_end_iterator(end_iterator)); }
static avltree &container_from_iterator(iterator it)
{ return static_cast<avltree &>(Base::container_from_iterator(it)); }
static const avltree &container_from_iterator(const_iterator it)
{ return static_cast<const avltree &>(Base::container_from_iterator(it)); }
};
#endif
} //namespace intrusive
} //namespace boost
#include <boost/intrusive/detail/config_end.hpp>
#endif //BOOST_INTRUSIVE_AVLTREE_HPP

View file

@ -0,0 +1,687 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Daniel K. O. 2005.
// (C) Copyright Ion Gaztanaga 2007-2014
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_AVLTREE_ALGORITHMS_HPP
#define BOOST_INTRUSIVE_AVLTREE_ALGORITHMS_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/intrusive/detail/config_begin.hpp>
#include <boost/intrusive/intrusive_fwd.hpp>
#include <cstddef>
#include <boost/intrusive/detail/assert.hpp>
#include <boost/intrusive/detail/algo_type.hpp>
#include <boost/intrusive/detail/ebo_functor_holder.hpp>
#include <boost/intrusive/bstree_algorithms.hpp>
namespace boost {
namespace intrusive {
/// @cond
template<class NodeTraits, class F>
struct avltree_node_cloner
: private detail::ebo_functor_holder<F>
{
typedef typename NodeTraits::node_ptr node_ptr;
typedef detail::ebo_functor_holder<F> base_t;
avltree_node_cloner(F f)
: base_t(f)
{}
node_ptr operator()(const node_ptr & p)
{
node_ptr n = base_t::get()(p);
NodeTraits::set_balance(n, NodeTraits::get_balance(p));
return n;
}
};
namespace detail {
template<class ValueTraits, class NodePtrCompare, class ExtraChecker>
struct avltree_node_checker
: public bstree_node_checker<ValueTraits, NodePtrCompare, ExtraChecker>
{
typedef bstree_node_checker<ValueTraits, NodePtrCompare, ExtraChecker> base_checker_t;
typedef ValueTraits value_traits;
typedef typename value_traits::node_traits node_traits;
typedef typename node_traits::const_node_ptr const_node_ptr;
struct return_type
: public base_checker_t::return_type
{
return_type() : height(0) {}
int height;
};
avltree_node_checker(const NodePtrCompare& comp, ExtraChecker extra_checker)
: base_checker_t(comp, extra_checker)
{}
void operator () (const const_node_ptr& p,
const return_type& check_return_left, const return_type& check_return_right,
return_type& check_return)
{
const int height_diff = check_return_right.height - check_return_left.height; (void)height_diff;
BOOST_INTRUSIVE_INVARIANT_ASSERT(
(height_diff == -1 && node_traits::get_balance(p) == node_traits::negative()) ||
(height_diff == 0 && node_traits::get_balance(p) == node_traits::zero()) ||
(height_diff == 1 && node_traits::get_balance(p) == node_traits::positive())
);
check_return.height = 1 +
(check_return_left.height > check_return_right.height ? check_return_left.height : check_return_right.height);
base_checker_t::operator()(p, check_return_left, check_return_right, check_return);
}
};
} // namespace detail
/// @endcond
//! avltree_algorithms is configured with a NodeTraits class, which encapsulates the
//! information about the node to be manipulated. NodeTraits must support the
//! following interface:
//!
//! <b>Typedefs</b>:
//!
//! <tt>node</tt>: The type of the node that forms the binary search tree
//!
//! <tt>node_ptr</tt>: A pointer to a node
//!
//! <tt>const_node_ptr</tt>: A pointer to a const node
//!
//! <tt>balance</tt>: The type of the balance factor
//!
//! <b>Static functions</b>:
//!
//! <tt>static node_ptr get_parent(const_node_ptr n);</tt>
//!
//! <tt>static void set_parent(node_ptr n, node_ptr parent);</tt>
//!
//! <tt>static node_ptr get_left(const_node_ptr n);</tt>
//!
//! <tt>static void set_left(node_ptr n, node_ptr left);</tt>
//!
//! <tt>static node_ptr get_right(const_node_ptr n);</tt>
//!
//! <tt>static void set_right(node_ptr n, node_ptr right);</tt>
//!
//! <tt>static balance get_balance(const_node_ptr n);</tt>
//!
//! <tt>static void set_balance(node_ptr n, balance b);</tt>
//!
//! <tt>static balance negative();</tt>
//!
//! <tt>static balance zero();</tt>
//!
//! <tt>static balance positive();</tt>
template<class NodeTraits>
class avltree_algorithms
#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
: public bstree_algorithms<NodeTraits>
#endif
{
public:
typedef typename NodeTraits::node node;
typedef NodeTraits node_traits;
typedef typename NodeTraits::node_ptr node_ptr;
typedef typename NodeTraits::const_node_ptr const_node_ptr;
typedef typename NodeTraits::balance balance;
/// @cond
private:
typedef bstree_algorithms<NodeTraits> bstree_algo;
/// @endcond
public:
//! This type is the information that will be
//! filled by insert_unique_check
typedef typename bstree_algo::insert_commit_data insert_commit_data;
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
//! @copydoc ::boost::intrusive::bstree_algorithms::get_header(const const_node_ptr&)
static node_ptr get_header(const const_node_ptr & n);
//! @copydoc ::boost::intrusive::bstree_algorithms::begin_node
static node_ptr begin_node(const const_node_ptr & header);
//! @copydoc ::boost::intrusive::bstree_algorithms::end_node
static node_ptr end_node(const const_node_ptr & header);
//! @copydoc ::boost::intrusive::bstree_algorithms::swap_tree
static void swap_tree(const node_ptr & header1, const node_ptr & header2);
#endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
//! @copydoc ::boost::intrusive::bstree_algorithms::swap_nodes(const node_ptr&,const node_ptr&)
static void swap_nodes(const node_ptr & node1, const node_ptr & node2)
{
if(node1 == node2)
return;
node_ptr header1(bstree_algo::get_header(node1)), header2(bstree_algo::get_header(node2));
swap_nodes(node1, header1, node2, header2);
}
//! @copydoc ::boost::intrusive::bstree_algorithms::swap_nodes(const node_ptr&,const node_ptr&,const node_ptr&,const node_ptr&)
static void swap_nodes(const node_ptr & node1, const node_ptr & header1, const node_ptr & node2, const node_ptr & header2)
{
if(node1 == node2) return;
bstree_algo::swap_nodes(node1, header1, node2, header2);
//Swap balance
balance c = NodeTraits::get_balance(node1);
NodeTraits::set_balance(node1, NodeTraits::get_balance(node2));
NodeTraits::set_balance(node2, c);
}
//! @copydoc ::boost::intrusive::bstree_algorithms::replace_node(const node_ptr&,const node_ptr&)
static void replace_node(const node_ptr & node_to_be_replaced, const node_ptr & new_node)
{
if(node_to_be_replaced == new_node)
return;
replace_node(node_to_be_replaced, bstree_algo::get_header(node_to_be_replaced), new_node);
}
//! @copydoc ::boost::intrusive::bstree_algorithms::replace_node(const node_ptr&,const node_ptr&,const node_ptr&)
static void replace_node(const node_ptr & node_to_be_replaced, const node_ptr & header, const node_ptr & new_node)
{
bstree_algo::replace_node(node_to_be_replaced, header, new_node);
NodeTraits::set_balance(new_node, NodeTraits::get_balance(node_to_be_replaced));
}
//! @copydoc ::boost::intrusive::bstree_algorithms::unlink(const node_ptr&)
static void unlink(const node_ptr & node)
{
node_ptr x = NodeTraits::get_parent(node);
if(x){
while(!is_header(x))
x = NodeTraits::get_parent(x);
erase(x, node);
}
}
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
//! @copydoc ::boost::intrusive::bstree_algorithms::unlink_leftmost_without_rebalance
static node_ptr unlink_leftmost_without_rebalance(const node_ptr & header);
//! @copydoc ::boost::intrusive::bstree_algorithms::unique(const const_node_ptr&)
static bool unique(const const_node_ptr & node);
//! @copydoc ::boost::intrusive::bstree_algorithms::size(const const_node_ptr&)
static std::size_t size(const const_node_ptr & header);
//! @copydoc ::boost::intrusive::bstree_algorithms::next_node(const node_ptr&)
static node_ptr next_node(const node_ptr & node);
//! @copydoc ::boost::intrusive::bstree_algorithms::prev_node(const node_ptr&)
static node_ptr prev_node(const node_ptr & node);
//! @copydoc ::boost::intrusive::bstree_algorithms::init(const node_ptr&)
static void init(const node_ptr & node);
#endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
//! <b>Requires</b>: node must not be part of any tree.
//!
//! <b>Effects</b>: Initializes the header to represent an empty tree.
//! unique(header) == true.
//!
//! <b>Complexity</b>: Constant.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Nodes</b>: If node is inserted in a tree, this function corrupts the tree.
static void init_header(const node_ptr & header)
{
bstree_algo::init_header(header);
NodeTraits::set_balance(header, NodeTraits::zero());
}
//! @copydoc ::boost::intrusive::bstree_algorithms::erase(const node_ptr&,const node_ptr&)
static node_ptr erase(const node_ptr & header, const node_ptr & z)
{
typename bstree_algo::data_for_rebalance info;
bstree_algo::erase(header, z, info);
if(info.y != z){
NodeTraits::set_balance(info.y, NodeTraits::get_balance(z));
}
//Rebalance avltree
rebalance_after_erasure(header, info.x, info.x_parent);
return z;
}
//! @copydoc ::boost::intrusive::bstree_algorithms::clone(const const_node_ptr&,const node_ptr&,Cloner,Disposer)
template <class Cloner, class Disposer>
static void clone
(const const_node_ptr & source_header, const node_ptr & target_header, Cloner cloner, Disposer disposer)
{
avltree_node_cloner<NodeTraits, Cloner> new_cloner(cloner);
bstree_algo::clone(source_header, target_header, new_cloner, disposer);
}
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
//! @copydoc ::boost::intrusive::bstree_algorithms::clear_and_dispose(const node_ptr&,Disposer)
template<class Disposer>
static void clear_and_dispose(const node_ptr & header, Disposer disposer);
//! @copydoc ::boost::intrusive::bstree_algorithms::lower_bound(const const_node_ptr&,const KeyType&,KeyNodePtrCompare)
template<class KeyType, class KeyNodePtrCompare>
static node_ptr lower_bound
(const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp);
//! @copydoc ::boost::intrusive::bstree_algorithms::upper_bound(const const_node_ptr&,const KeyType&,KeyNodePtrCompare)
template<class KeyType, class KeyNodePtrCompare>
static node_ptr upper_bound
(const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp);
//! @copydoc ::boost::intrusive::bstree_algorithms::find(const const_node_ptr&,const KeyType&,KeyNodePtrCompare)
template<class KeyType, class KeyNodePtrCompare>
static node_ptr find
(const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp);
//! @copydoc ::boost::intrusive::bstree_algorithms::equal_range(const const_node_ptr&,const KeyType&,KeyNodePtrCompare)
template<class KeyType, class KeyNodePtrCompare>
static std::pair<node_ptr, node_ptr> equal_range
(const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp);
//! @copydoc ::boost::intrusive::bstree_algorithms::bounded_range(const const_node_ptr&,const KeyType&,const KeyType&,KeyNodePtrCompare,bool,bool)
template<class KeyType, class KeyNodePtrCompare>
static std::pair<node_ptr, node_ptr> bounded_range
(const const_node_ptr & header, const KeyType &lower_key, const KeyType &upper_key, KeyNodePtrCompare comp
, bool left_closed, bool right_closed);
//! @copydoc ::boost::intrusive::bstree_algorithms::count(const const_node_ptr&,const KeyType&,KeyNodePtrCompare)
template<class KeyType, class KeyNodePtrCompare>
static std::size_t count(const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp);
#endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
//! @copydoc ::boost::intrusive::bstree_algorithms::insert_equal_upper_bound(const node_ptr&,const node_ptr&,NodePtrCompare)
template<class NodePtrCompare>
static node_ptr insert_equal_upper_bound
(const node_ptr & h, const node_ptr & new_node, NodePtrCompare comp)
{
bstree_algo::insert_equal_upper_bound(h, new_node, comp);
rebalance_after_insertion(h, new_node);
return new_node;
}
//! @copydoc ::boost::intrusive::bstree_algorithms::insert_equal_lower_bound(const node_ptr&,const node_ptr&,NodePtrCompare)
template<class NodePtrCompare>
static node_ptr insert_equal_lower_bound
(const node_ptr & h, const node_ptr & new_node, NodePtrCompare comp)
{
bstree_algo::insert_equal_lower_bound(h, new_node, comp);
rebalance_after_insertion(h, new_node);
return new_node;
}
//! @copydoc ::boost::intrusive::bstree_algorithms::insert_equal(const node_ptr&,const node_ptr&,const node_ptr&,NodePtrCompare)
template<class NodePtrCompare>
static node_ptr insert_equal
(const node_ptr & header, const node_ptr & hint, const node_ptr & new_node, NodePtrCompare comp)
{
bstree_algo::insert_equal(header, hint, new_node, comp);
rebalance_after_insertion(header, new_node);
return new_node;
}
//! @copydoc ::boost::intrusive::bstree_algorithms::insert_before(const node_ptr&,const node_ptr&,const node_ptr&)
static node_ptr insert_before
(const node_ptr & header, const node_ptr & pos, const node_ptr & new_node)
{
bstree_algo::insert_before(header, pos, new_node);
rebalance_after_insertion(header, new_node);
return new_node;
}
//! @copydoc ::boost::intrusive::bstree_algorithms::push_back(const node_ptr&,const node_ptr&)
static void push_back(const node_ptr & header, const node_ptr & new_node)
{
bstree_algo::push_back(header, new_node);
rebalance_after_insertion(header, new_node);
}
//! @copydoc ::boost::intrusive::bstree_algorithms::push_front(const node_ptr&,const node_ptr&)
static void push_front(const node_ptr & header, const node_ptr & new_node)
{
bstree_algo::push_front(header, new_node);
rebalance_after_insertion(header, new_node);
}
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
//! @copydoc ::boost::intrusive::bstree_algorithms::insert_unique_check(const const_node_ptr&,const KeyType&,KeyNodePtrCompare,insert_commit_data&)
template<class KeyType, class KeyNodePtrCompare>
static std::pair<node_ptr, bool> insert_unique_check
(const const_node_ptr & header, const KeyType &key
,KeyNodePtrCompare comp, insert_commit_data &commit_data);
//! @copydoc ::boost::intrusive::bstree_algorithms::insert_unique_check(const const_node_ptr&,const node_ptr&,const KeyType&,KeyNodePtrCompare,insert_commit_data&)
template<class KeyType, class KeyNodePtrCompare>
static std::pair<node_ptr, bool> insert_unique_check
(const const_node_ptr & header, const node_ptr &hint, const KeyType &key
,KeyNodePtrCompare comp, insert_commit_data &commit_data);
#endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
//! @copydoc ::boost::intrusive::bstree_algorithms::insert_unique_commit(const node_ptr&,const node_ptr&,const insert_commit_data &)
static void insert_unique_commit
(const node_ptr & header, const node_ptr & new_value, const insert_commit_data &commit_data)
{
bstree_algo::insert_unique_commit(header, new_value, commit_data);
rebalance_after_insertion(header, new_value);
}
//! @copydoc ::boost::intrusive::bstree_algorithms::is_header
static bool is_header(const const_node_ptr & p)
{ return NodeTraits::get_balance(p) == NodeTraits::zero() && bstree_algo::is_header(p); }
/// @cond
static bool verify(const node_ptr &header)
{
std::size_t height;
std::size_t count;
return verify_recursion(NodeTraits::get_parent(header), count, height);
}
private:
static bool verify_recursion(node_ptr n, std::size_t &count, std::size_t &height)
{
if (!n){
count = 0;
height = 0;
return true;
}
std::size_t leftcount, rightcount;
std::size_t leftheight, rightheight;
if(!verify_recursion(NodeTraits::get_left (n), leftcount, leftheight) ||
!verify_recursion(NodeTraits::get_right(n), rightcount, rightheight) ){
return false;
}
count = 1u + leftcount + rightcount;
height = 1u + (leftheight > rightheight ? leftheight : rightheight);
//If equal height, balance must be zero
if(rightheight == leftheight){
if(NodeTraits::get_balance(n) != NodeTraits::zero()){
BOOST_ASSERT(0);
return false;
}
}
//If right is taller than left, then the difference must be at least 1 and the balance positive
else if(rightheight > leftheight){
if(rightheight - leftheight > 1 ){
BOOST_ASSERT(0);
return false;
}
else if(NodeTraits::get_balance(n) != NodeTraits::positive()){
BOOST_ASSERT(0);
return false;
}
}
//If left is taller than right, then the difference must be at least 1 and the balance negative
else{
if(leftheight - rightheight > 1 ){
BOOST_ASSERT(0);
return false;
}
else if(NodeTraits::get_balance(n) != NodeTraits::negative()){
BOOST_ASSERT(0);
return false;
}
}
return true;
}
static void rebalance_after_erasure(const node_ptr & header, node_ptr x, node_ptr x_parent)
{
for ( node_ptr root = NodeTraits::get_parent(header)
; x != root
; root = NodeTraits::get_parent(header), x_parent = NodeTraits::get_parent(x)) {
const balance x_parent_balance = NodeTraits::get_balance(x_parent);
//Don't cache x_is_leftchild or similar because x can be null and
//equal to both x_parent_left and x_parent_right
const node_ptr x_parent_left (NodeTraits::get_left(x_parent));
const node_ptr x_parent_right(NodeTraits::get_right(x_parent));
if(x_parent_balance == NodeTraits::zero()){
NodeTraits::set_balance( x_parent, x == x_parent_right ? NodeTraits::negative() : NodeTraits::positive() );
break; // the height didn't change, let's stop here
}
else if(x_parent_balance == NodeTraits::negative()){
if (x == x_parent_left) { ////x is left child or x and sibling are null
NodeTraits::set_balance(x_parent, NodeTraits::zero()); // balanced
x = x_parent;
}
else {
// x is right child (x_parent_left is the left child)
BOOST_INTRUSIVE_INVARIANT_ASSERT(x_parent_left);
if (NodeTraits::get_balance(x_parent_left) == NodeTraits::positive()) {
// x_parent_left MUST have a right child
BOOST_INTRUSIVE_INVARIANT_ASSERT(NodeTraits::get_right(x_parent_left));
x = avl_rotate_left_right(x_parent, x_parent_left, header);
}
else {
avl_rotate_right(x_parent, x_parent_left, header);
x = x_parent_left;
}
// if changed from negative to NodeTraits::positive(), no need to check above
if (NodeTraits::get_balance(x) == NodeTraits::positive()){
break;
}
}
}
else if(x_parent_balance == NodeTraits::positive()){
if (x == x_parent_right) { //x is right child or x and sibling are null
NodeTraits::set_balance(x_parent, NodeTraits::zero()); // balanced
x = x_parent;
}
else {
// x is left child (x_parent_right is the right child)
BOOST_INTRUSIVE_INVARIANT_ASSERT(x_parent_right);
if (NodeTraits::get_balance(x_parent_right) == NodeTraits::negative()) {
// x_parent_right MUST have then a left child
BOOST_INTRUSIVE_INVARIANT_ASSERT(NodeTraits::get_left(x_parent_right));
x = avl_rotate_right_left(x_parent, x_parent_right, header);
}
else {
avl_rotate_left(x_parent, x_parent_right, header);
x = x_parent_right;
}
// if changed from NodeTraits::positive() to negative, no need to check above
if (NodeTraits::get_balance(x) == NodeTraits::negative()){
break;
}
}
}
else{
BOOST_INTRUSIVE_INVARIANT_ASSERT(false); // never reached
}
}
}
static void rebalance_after_insertion(const node_ptr & header, node_ptr x)
{
NodeTraits::set_balance(x, NodeTraits::zero());
// Rebalance.
for(node_ptr root = NodeTraits::get_parent(header); x != root; root = NodeTraits::get_parent(header)){
node_ptr const x_parent(NodeTraits::get_parent(x));
node_ptr const x_parent_left(NodeTraits::get_left(x_parent));
const balance x_parent_balance = NodeTraits::get_balance(x_parent);
const bool x_is_leftchild(x == x_parent_left);
if(x_parent_balance == NodeTraits::zero()){
// if x is left, parent will have parent->bal_factor = negative
// else, parent->bal_factor = NodeTraits::positive()
NodeTraits::set_balance( x_parent, x_is_leftchild ? NodeTraits::negative() : NodeTraits::positive() );
x = x_parent;
}
else if(x_parent_balance == NodeTraits::positive()){
// if x is a left child, parent->bal_factor = zero
if (x_is_leftchild)
NodeTraits::set_balance(x_parent, NodeTraits::zero());
else{ // x is a right child, needs rebalancing
if (NodeTraits::get_balance(x) == NodeTraits::negative())
avl_rotate_right_left(x_parent, x, header);
else
avl_rotate_left(x_parent, x, header);
}
break;
}
else if(x_parent_balance == NodeTraits::negative()){
// if x is a left child, needs rebalancing
if (x_is_leftchild) {
if (NodeTraits::get_balance(x) == NodeTraits::positive())
avl_rotate_left_right(x_parent, x, header);
else
avl_rotate_right(x_parent, x, header);
}
else
NodeTraits::set_balance(x_parent, NodeTraits::zero());
break;
}
else{
BOOST_INTRUSIVE_INVARIANT_ASSERT(false); // never reached
}
}
}
static void left_right_balancing(const node_ptr & a, const node_ptr & b, const node_ptr & c)
{
// balancing...
const balance c_balance = NodeTraits::get_balance(c);
const balance zero_balance = NodeTraits::zero();
const balance posi_balance = NodeTraits::positive();
const balance nega_balance = NodeTraits::negative();
NodeTraits::set_balance(c, zero_balance);
if(c_balance == nega_balance){
NodeTraits::set_balance(a, posi_balance);
NodeTraits::set_balance(b, zero_balance);
}
else if(c_balance == zero_balance){
NodeTraits::set_balance(a, zero_balance);
NodeTraits::set_balance(b, zero_balance);
}
else if(c_balance == posi_balance){
NodeTraits::set_balance(a, zero_balance);
NodeTraits::set_balance(b, nega_balance);
}
else{
BOOST_INTRUSIVE_INVARIANT_ASSERT(false); // never reached
}
}
static node_ptr avl_rotate_left_right(const node_ptr a, const node_ptr a_oldleft, const node_ptr & hdr)
{ // [note: 'a_oldleft' is 'b']
// | | //
// a(-2) c //
// / \ / \ //
// / \ ==> / \ //
// (pos)b [g] b a //
// / \ / \ / \ //
// [d] c [d] e f [g] //
// / \ //
// e f //
const node_ptr c = NodeTraits::get_right(a_oldleft);
bstree_algo::rotate_left_no_parent_fix(a_oldleft, c);
//No need to link c with a [NodeTraits::set_parent(c, a) + NodeTraits::set_left(a, c)]
//as c is not root and another rotation is coming
bstree_algo::rotate_right(a, c, NodeTraits::get_parent(a), hdr);
left_right_balancing(a, a_oldleft, c);
return c;
}
static node_ptr avl_rotate_right_left(const node_ptr a, const node_ptr a_oldright, const node_ptr & hdr)
{ // [note: 'a_oldright' is 'b']
// | | //
// a(pos) c //
// / \ / \ //
// / \ / \ //
// [d] b(neg) ==> a b //
// / \ / \ / \ //
// c [g] [d] e f [g] //
// / \ //
// e f //
const node_ptr c (NodeTraits::get_left(a_oldright));
bstree_algo::rotate_right_no_parent_fix(a_oldright, c);
//No need to link c with a [NodeTraits::set_parent(c, a) + NodeTraits::set_right(a, c)]
//as c is not root and another rotation is coming.
bstree_algo::rotate_left(a, c, NodeTraits::get_parent(a), hdr);
left_right_balancing(a_oldright, a, c);
return c;
}
static void avl_rotate_left(const node_ptr &x, const node_ptr &x_oldright, const node_ptr & hdr)
{
bstree_algo::rotate_left(x, x_oldright, NodeTraits::get_parent(x), hdr);
// reset the balancing factor
if (NodeTraits::get_balance(x_oldright) == NodeTraits::positive()) {
NodeTraits::set_balance(x, NodeTraits::zero());
NodeTraits::set_balance(x_oldright, NodeTraits::zero());
}
else { // this doesn't happen during insertions
NodeTraits::set_balance(x, NodeTraits::positive());
NodeTraits::set_balance(x_oldright, NodeTraits::negative());
}
}
static void avl_rotate_right(const node_ptr &x, const node_ptr &x_oldleft, const node_ptr & hdr)
{
bstree_algo::rotate_right(x, x_oldleft, NodeTraits::get_parent(x), hdr);
// reset the balancing factor
if (NodeTraits::get_balance(x_oldleft) == NodeTraits::negative()) {
NodeTraits::set_balance(x, NodeTraits::zero());
NodeTraits::set_balance(x_oldleft, NodeTraits::zero());
}
else { // this doesn't happen during insertions
NodeTraits::set_balance(x, NodeTraits::negative());
NodeTraits::set_balance(x_oldleft, NodeTraits::positive());
}
}
/// @endcond
};
/// @cond
template<class NodeTraits>
struct get_algo<AvlTreeAlgorithms, NodeTraits>
{
typedef avltree_algorithms<NodeTraits> type;
};
template <class ValueTraits, class NodePtrCompare, class ExtraChecker>
struct get_node_checker<AvlTreeAlgorithms, ValueTraits, NodePtrCompare, ExtraChecker>
{
typedef detail::avltree_node_checker<ValueTraits, NodePtrCompare, ExtraChecker> type;
};
/// @endcond
} //namespace intrusive
} //namespace boost
#include <boost/intrusive/detail/config_end.hpp>
#endif //BOOST_INTRUSIVE_AVLTREE_ALGORITHMS_HPP

948
boost/intrusive/bs_set.hpp Normal file
View file

@ -0,0 +1,948 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2013-2014
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_BS_SET_HPP
#define BOOST_INTRUSIVE_BS_SET_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/intrusive/detail/config_begin.hpp>
#include <boost/intrusive/intrusive_fwd.hpp>
#include <boost/intrusive/detail/mpl.hpp>
#include <boost/intrusive/bstree.hpp>
#include <boost/move/utility_core.hpp>
#include <boost/static_assert.hpp>
namespace boost {
namespace intrusive {
//! The class template bs_set is an intrusive container, that mimics most of
//! the interface of std::set as described in the C++ standard.
//!
//! The template parameter \c T is the type to be managed by the container.
//! The user can specify additional options and if no options are provided
//! default options are used.
//!
//! The container supports the following options:
//! \c base_hook<>/member_hook<>/value_traits<>,
//! \c constant_time_size<>, \c size_type<> and
//! \c compare<>.
#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class ValueTraits, class Compare, class SizeType, bool ConstantTimeSize, typename HeaderHolder>
#endif
class bs_set_impl
#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
: public bstree_impl<ValueTraits, Compare, SizeType, ConstantTimeSize, BsTreeAlgorithms, HeaderHolder>
#endif
{
/// @cond
typedef bstree_impl<ValueTraits, Compare, SizeType, ConstantTimeSize, BsTreeAlgorithms, HeaderHolder> tree_type;
BOOST_MOVABLE_BUT_NOT_COPYABLE(bs_set_impl)
typedef tree_type implementation_defined;
/// @endcond
public:
typedef typename implementation_defined::value_type value_type;
typedef typename implementation_defined::value_traits value_traits;
typedef typename implementation_defined::pointer pointer;
typedef typename implementation_defined::const_pointer const_pointer;
typedef typename implementation_defined::reference reference;
typedef typename implementation_defined::const_reference const_reference;
typedef typename implementation_defined::difference_type difference_type;
typedef typename implementation_defined::size_type size_type;
typedef typename implementation_defined::value_compare value_compare;
typedef typename implementation_defined::key_compare key_compare;
typedef typename implementation_defined::iterator iterator;
typedef typename implementation_defined::const_iterator const_iterator;
typedef typename implementation_defined::reverse_iterator reverse_iterator;
typedef typename implementation_defined::const_reverse_iterator const_reverse_iterator;
typedef typename implementation_defined::insert_commit_data insert_commit_data;
typedef typename implementation_defined::node_traits node_traits;
typedef typename implementation_defined::node node;
typedef typename implementation_defined::node_ptr node_ptr;
typedef typename implementation_defined::const_node_ptr const_node_ptr;
typedef typename implementation_defined::node_algorithms node_algorithms;
static const bool constant_time_size = tree_type::constant_time_size;
public:
//! @copydoc ::boost::intrusive::bstree::bstree(const value_compare &,const value_traits &)
explicit bs_set_impl( const value_compare &cmp = value_compare()
, const value_traits &v_traits = value_traits())
: tree_type(cmp, v_traits)
{}
//! @copydoc ::boost::intrusive::bstree::bstree(bool,Iterator,Iterator,const value_compare &,const value_traits &)
template<class Iterator>
bs_set_impl( Iterator b, Iterator e
, const value_compare &cmp = value_compare()
, const value_traits &v_traits = value_traits())
: tree_type(true, b, e, cmp, v_traits)
{}
//! @copydoc ::boost::intrusive::bstree::bstree(bstree &&)
bs_set_impl(BOOST_RV_REF(bs_set_impl) x)
: tree_type(::boost::move(static_cast<tree_type&>(x)))
{}
//! @copydoc ::boost::intrusive::bstree::operator=(bstree &&)
bs_set_impl& operator=(BOOST_RV_REF(bs_set_impl) x)
{ return static_cast<bs_set_impl&>(tree_type::operator=(::boost::move(static_cast<tree_type&>(x)))); }
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
//! @copydoc ::boost::intrusive::bstree::~bstree()
~bs_set_impl();
//! @copydoc ::boost::intrusive::bstree::begin()
iterator begin();
//! @copydoc ::boost::intrusive::bstree::begin()const
const_iterator begin() const;
//! @copydoc ::boost::intrusive::bstree::cbegin()const
const_iterator cbegin() const;
//! @copydoc ::boost::intrusive::bstree::end()
iterator end();
//! @copydoc ::boost::intrusive::bstree::end()const
const_iterator end() const;
//! @copydoc ::boost::intrusive::bstree::cend()const
const_iterator cend() const;
//! @copydoc ::boost::intrusive::bstree::rbegin()
reverse_iterator rbegin();
//! @copydoc ::boost::intrusive::bstree::rbegin()const
const_reverse_iterator rbegin() const;
//! @copydoc ::boost::intrusive::bstree::crbegin()const
const_reverse_iterator crbegin() const;
//! @copydoc ::boost::intrusive::bstree::rend()
reverse_iterator rend();
//! @copydoc ::boost::intrusive::bstree::rend()const
const_reverse_iterator rend() const;
//! @copydoc ::boost::intrusive::bstree::crend()const
const_reverse_iterator crend() const;
//! @copydoc ::boost::intrusive::bstree::container_from_end_iterator(iterator)
static bs_set_impl &container_from_end_iterator(iterator end_iterator);
//! @copydoc ::boost::intrusive::bstree::container_from_end_iterator(const_iterator)
static const bs_set_impl &container_from_end_iterator(const_iterator end_iterator);
//! @copydoc ::boost::intrusive::bstree::container_from_iterator(iterator)
static bs_set_impl &container_from_iterator(iterator it);
//! @copydoc ::boost::intrusive::bstree::container_from_iterator(const_iterator)
static const bs_set_impl &container_from_iterator(const_iterator it);
//! @copydoc ::boost::intrusive::bstree::key_comp()const
key_compare key_comp() const;
//! @copydoc ::boost::intrusive::bstree::value_comp()const
value_compare value_comp() const;
//! @copydoc ::boost::intrusive::bstree::empty()const
bool empty() const;
//! @copydoc ::boost::intrusive::bstree::size()const
size_type size() const;
//! @copydoc ::boost::intrusive::bstree::swap
void swap(bs_set_impl& other);
//! @copydoc ::boost::intrusive::bstree::clone_from
template <class Cloner, class Disposer>
void clone_from(const bs_set_impl &src, Cloner cloner, Disposer disposer);
#endif //#ifdef BOOST_iNTRUSIVE_DOXYGEN_INVOKED
//! @copydoc ::boost::intrusive::bstree::insert_unique(reference)
std::pair<iterator, bool> insert(reference value)
{ return tree_type::insert_unique(value); }
//! @copydoc ::boost::intrusive::bstree::insert_unique(const_iterator,reference)
iterator insert(const_iterator hint, reference value)
{ return tree_type::insert_unique(hint, value); }
//! @copydoc ::boost::intrusive::bstree::insert_unique_check(const KeyType&,KeyValueCompare,insert_commit_data&)
template<class KeyType, class KeyValueCompare>
std::pair<iterator, bool> insert_check
(const KeyType &key, KeyValueCompare key_value_comp, insert_commit_data &commit_data)
{ return tree_type::insert_unique_check(key, key_value_comp, commit_data); }
//! @copydoc ::boost::intrusive::bstree::insert_unique_check(const_iterator,const KeyType&,KeyValueCompare,insert_commit_data&)
template<class KeyType, class KeyValueCompare>
std::pair<iterator, bool> insert_check
(const_iterator hint, const KeyType &key
,KeyValueCompare key_value_comp, insert_commit_data &commit_data)
{ return tree_type::insert_unique_check(hint, key, key_value_comp, commit_data); }
//! @copydoc ::boost::intrusive::bstree::insert_unique(Iterator,Iterator)
template<class Iterator>
void insert(Iterator b, Iterator e)
{ tree_type::insert_unique(b, e); }
//! @copydoc ::boost::intrusive::bstree::insert_unique_commit
iterator insert_commit(reference value, const insert_commit_data &commit_data)
{ return tree_type::insert_unique_commit(value, commit_data); }
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
//! @copydoc ::boost::intrusive::bstree::insert_before
iterator insert_before(const_iterator pos, reference value);
//! @copydoc ::boost::intrusive::bstree::push_back
void push_back(reference value);
//! @copydoc ::boost::intrusive::bstree::push_front
void push_front(reference value);
//! @copydoc ::boost::intrusive::bstree::erase(const_iterator)
iterator erase(const_iterator i);
//! @copydoc ::boost::intrusive::bstree::erase(const_iterator,const_iterator)
iterator erase(const_iterator b, const_iterator e);
//! @copydoc ::boost::intrusive::bstree::erase(const_reference)
size_type erase(const_reference value);
//! @copydoc ::boost::intrusive::bstree::erase(const KeyType&,KeyValueCompare)
template<class KeyType, class KeyValueCompare>
size_type erase(const KeyType& key, KeyValueCompare comp);
//! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const_iterator,Disposer)
template<class Disposer>
iterator erase_and_dispose(const_iterator i, Disposer disposer);
//! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const_iterator,const_iterator,Disposer)
template<class Disposer>
iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer);
//! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const_reference, Disposer)
template<class Disposer>
size_type erase_and_dispose(const_reference value, Disposer disposer);
//! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const KeyType&,KeyValueCompare,Disposer)
template<class KeyType, class KeyValueCompare, class Disposer>
size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer);
//! @copydoc ::boost::intrusive::bstree::clear
void clear();
//! @copydoc ::boost::intrusive::bstree::clear_and_dispose
template<class Disposer>
void clear_and_dispose(Disposer disposer);
#endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
//! @copydoc ::boost::intrusive::bstree::count(const_reference)const
size_type count(const_reference value) const
{ return static_cast<size_type>(this->tree_type::find(value) == this->tree_type::cend()); }
//! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyValueCompare)const
template<class KeyType, class KeyValueCompare>
size_type count(const KeyType& key, KeyValueCompare comp) const
{ return static_cast<size_type>(this->tree_type::find(key, comp) == this->tree_type::cend()); }
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
//! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference)
iterator lower_bound(const_reference value);
//! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyValueCompare)
template<class KeyType, class KeyValueCompare>
iterator lower_bound(const KeyType& key, KeyValueCompare comp);
//! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference)const
const_iterator lower_bound(const_reference value) const;
//! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyValueCompare)const
template<class KeyType, class KeyValueCompare>
const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const;
//! @copydoc ::boost::intrusive::bstree::upper_bound(const_reference)
iterator upper_bound(const_reference value);
//! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyValueCompare)
template<class KeyType, class KeyValueCompare>
iterator upper_bound(const KeyType& key, KeyValueCompare comp);
//! @copydoc ::boost::intrusive::bstree::upper_bound(const_reference)const
const_iterator upper_bound(const_reference value) const;
//! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyValueCompare)const
template<class KeyType, class KeyValueCompare>
const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const;
//! @copydoc ::boost::intrusive::bstree::find(const_reference)
iterator find(const_reference value);
//! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyValueCompare)
template<class KeyType, class KeyValueCompare>
iterator find(const KeyType& key, KeyValueCompare comp);
//! @copydoc ::boost::intrusive::bstree::find(const_reference)const
const_iterator find(const_reference value) const;
//! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyValueCompare)const
template<class KeyType, class KeyValueCompare>
const_iterator find(const KeyType& key, KeyValueCompare comp) const;
#endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
//! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference)
std::pair<iterator,iterator> equal_range(const_reference value)
{ return this->tree_type::lower_bound_range(value); }
//! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare)
template<class KeyType, class KeyValueCompare>
std::pair<iterator,iterator> equal_range(const KeyType& key, KeyValueCompare comp)
{ return this->tree_type::lower_bound_range(key, comp); }
//! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference)const
std::pair<const_iterator, const_iterator>
equal_range(const_reference value) const
{ return this->tree_type::lower_bound_range(value); }
//! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare)const
template<class KeyType, class KeyValueCompare>
std::pair<const_iterator, const_iterator>
equal_range(const KeyType& key, KeyValueCompare comp) const
{ return this->tree_type::lower_bound_range(key, comp); }
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
//! @copydoc ::boost::intrusive::bstree::bounded_range(const_reference,const_reference,bool,bool)
std::pair<iterator,iterator> bounded_range
(const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed);
//! @copydoc ::boost::intrusive::bstree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool)
template<class KeyType, class KeyValueCompare>
std::pair<iterator,iterator> bounded_range
(const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed);
//! @copydoc ::boost::intrusive::bstree::bounded_range(const_reference,const_reference,bool,bool)const
std::pair<const_iterator, const_iterator>
bounded_range(const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const;
//! @copydoc ::boost::intrusive::bstree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool)const
template<class KeyType, class KeyValueCompare>
std::pair<const_iterator, const_iterator> bounded_range
(const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const;
//! @copydoc ::boost::intrusive::bstree::s_iterator_to(reference)
static iterator s_iterator_to(reference value);
//! @copydoc ::boost::intrusive::bstree::s_iterator_to(const_reference)
static const_iterator s_iterator_to(const_reference value);
//! @copydoc ::boost::intrusive::bstree::iterator_to(reference)
iterator iterator_to(reference value);
//! @copydoc ::boost::intrusive::bstree::iterator_to(const_reference)const
const_iterator iterator_to(const_reference value) const;
//! @copydoc ::boost::intrusive::bstree::init_node(reference)
static void init_node(reference value);
//! @copydoc ::boost::intrusive::bstree::unlink_leftmost_without_rebalance
pointer unlink_leftmost_without_rebalance();
//! @copydoc ::boost::intrusive::bstree::replace_node
void replace_node(iterator replace_this, reference with_this);
//! @copydoc ::boost::intrusive::bstree::remove_node
void remove_node(reference value);
#endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
};
#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
bool operator!= (const bs_set_impl<T, Options...> &x, const bs_set_impl<T, Options...> &y);
template<class T, class ...Options>
bool operator>(const bs_set_impl<T, Options...> &x, const bs_set_impl<T, Options...> &y);
template<class T, class ...Options>
bool operator<=(const bs_set_impl<T, Options...> &x, const bs_set_impl<T, Options...> &y);
template<class T, class ...Options>
bool operator>=(const bs_set_impl<T, Options...> &x, const bs_set_impl<T, Options...> &y);
template<class T, class ...Options>
void swap(bs_set_impl<T, Options...> &x, bs_set_impl<T, Options...> &y);
#endif //#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
//! Helper metafunction to define a \c bs_set that yields to the same type when the
//! same options (either explicitly or implicitly) are used.
#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class ...Options>
#else
template<class T, class O1 = void, class O2 = void
, class O3 = void, class O4 = void
, class O5 = void>
#endif
struct make_bs_set
{
/// @cond
typedef typename pack_options
< bstree_defaults,
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
O1, O2, O3, O4, O5
#else
Options...
#endif
>::type packed_options;
typedef typename detail::get_value_traits
<T, typename packed_options::proto_value_traits>::type value_traits;
typedef typename detail::get_header_holder_type
< value_traits, typename packed_options::header_holder_type >::type header_holder_type;
typedef bs_set_impl
< value_traits
, typename packed_options::compare
, typename packed_options::size_type
, packed_options::constant_time_size
, header_holder_type
> implementation_defined;
/// @endcond
typedef implementation_defined type;
};
#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class O1, class O2, class O3, class O4, class O5>
#else
template<class T, class ...Options>
#endif
class bs_set
: public make_bs_set<T,
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
O1, O2, O3, O4, O5
#else
Options...
#endif
>::type
{
typedef typename make_bs_set
<T,
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
O1, O2, O3, O4, O5
#else
Options...
#endif
>::type Base;
BOOST_MOVABLE_BUT_NOT_COPYABLE(bs_set)
public:
typedef typename Base::value_compare value_compare;
typedef typename Base::value_traits value_traits;
typedef typename Base::iterator iterator;
typedef typename Base::const_iterator const_iterator;
//Assert if passed value traits are compatible with the type
BOOST_STATIC_ASSERT((detail::is_same<typename value_traits::value_type, T>::value));
explicit bs_set( const value_compare &cmp = value_compare()
, const value_traits &v_traits = value_traits())
: Base(cmp, v_traits)
{}
template<class Iterator>
bs_set( Iterator b, Iterator e
, const value_compare &cmp = value_compare()
, const value_traits &v_traits = value_traits())
: Base(b, e, cmp, v_traits)
{}
bs_set(BOOST_RV_REF(bs_set) x)
: Base(::boost::move(static_cast<Base&>(x)))
{}
bs_set& operator=(BOOST_RV_REF(bs_set) x)
{ return static_cast<bs_set &>(this->Base::operator=(::boost::move(static_cast<Base&>(x)))); }
static bs_set &container_from_end_iterator(iterator end_iterator)
{ return static_cast<bs_set &>(Base::container_from_end_iterator(end_iterator)); }
static const bs_set &container_from_end_iterator(const_iterator end_iterator)
{ return static_cast<const bs_set &>(Base::container_from_end_iterator(end_iterator)); }
static bs_set &container_from_iterator(iterator it)
{ return static_cast<bs_set &>(Base::container_from_iterator(it)); }
static const bs_set &container_from_iterator(const_iterator it)
{ return static_cast<const bs_set &>(Base::container_from_iterator(it)); }
};
#endif
//! The class template bs_multiset is an intrusive container, that mimics most of
//! the interface of std::multiset as described in the C++ standard.
//!
//! The template parameter \c T is the type to be managed by the container.
//! The user can specify additional options and if no options are provided
//! default options are used.
//!
//! The container supports the following options:
//! \c base_hook<>/member_hook<>/value_traits<>,
//! \c constant_time_size<>, \c size_type<> and
//! \c compare<>.
#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class ValueTraits, class Compare, class SizeType, bool ConstantTimeSize, typename HeaderHolder>
#endif
class bs_multiset_impl
#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
: public bstree_impl<ValueTraits, Compare, SizeType, ConstantTimeSize, RbTreeAlgorithms, HeaderHolder>
#endif
{
/// @cond
typedef bstree_impl<ValueTraits, Compare, SizeType, ConstantTimeSize, RbTreeAlgorithms, HeaderHolder> tree_type;
BOOST_MOVABLE_BUT_NOT_COPYABLE(bs_multiset_impl)
typedef tree_type implementation_defined;
/// @endcond
public:
typedef typename implementation_defined::value_type value_type;
typedef typename implementation_defined::value_traits value_traits;
typedef typename implementation_defined::pointer pointer;
typedef typename implementation_defined::const_pointer const_pointer;
typedef typename implementation_defined::reference reference;
typedef typename implementation_defined::const_reference const_reference;
typedef typename implementation_defined::difference_type difference_type;
typedef typename implementation_defined::size_type size_type;
typedef typename implementation_defined::value_compare value_compare;
typedef typename implementation_defined::key_compare key_compare;
typedef typename implementation_defined::iterator iterator;
typedef typename implementation_defined::const_iterator const_iterator;
typedef typename implementation_defined::reverse_iterator reverse_iterator;
typedef typename implementation_defined::const_reverse_iterator const_reverse_iterator;
typedef typename implementation_defined::insert_commit_data insert_commit_data;
typedef typename implementation_defined::node_traits node_traits;
typedef typename implementation_defined::node node;
typedef typename implementation_defined::node_ptr node_ptr;
typedef typename implementation_defined::const_node_ptr const_node_ptr;
typedef typename implementation_defined::node_algorithms node_algorithms;
static const bool constant_time_size = tree_type::constant_time_size;
public:
//! @copydoc ::boost::intrusive::bstree::bstree(const value_compare &,const value_traits &)
explicit bs_multiset_impl( const value_compare &cmp = value_compare()
, const value_traits &v_traits = value_traits())
: tree_type(cmp, v_traits)
{}
//! @copydoc ::boost::intrusive::bstree::bstree(bool,Iterator,Iterator,const value_compare &,const value_traits &)
template<class Iterator>
bs_multiset_impl( Iterator b, Iterator e
, const value_compare &cmp = value_compare()
, const value_traits &v_traits = value_traits())
: tree_type(false, b, e, cmp, v_traits)
{}
//! @copydoc ::boost::intrusive::bstree::bstree(bstree &&)
bs_multiset_impl(BOOST_RV_REF(bs_multiset_impl) x)
: tree_type(::boost::move(static_cast<tree_type&>(x)))
{}
//! @copydoc ::boost::intrusive::bstree::operator=(bstree &&)
bs_multiset_impl& operator=(BOOST_RV_REF(bs_multiset_impl) x)
{ return static_cast<bs_multiset_impl&>(tree_type::operator=(::boost::move(static_cast<tree_type&>(x)))); }
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
//! @copydoc ::boost::intrusive::bstree::~bstree()
~bs_multiset_impl();
//! @copydoc ::boost::intrusive::bstree::begin()
iterator begin();
//! @copydoc ::boost::intrusive::bstree::begin()const
const_iterator begin() const;
//! @copydoc ::boost::intrusive::bstree::cbegin()const
const_iterator cbegin() const;
//! @copydoc ::boost::intrusive::bstree::end()
iterator end();
//! @copydoc ::boost::intrusive::bstree::end()const
const_iterator end() const;
//! @copydoc ::boost::intrusive::bstree::cend()const
const_iterator cend() const;
//! @copydoc ::boost::intrusive::bstree::rbegin()
reverse_iterator rbegin();
//! @copydoc ::boost::intrusive::bstree::rbegin()const
const_reverse_iterator rbegin() const;
//! @copydoc ::boost::intrusive::bstree::crbegin()const
const_reverse_iterator crbegin() const;
//! @copydoc ::boost::intrusive::bstree::rend()
reverse_iterator rend();
//! @copydoc ::boost::intrusive::bstree::rend()const
const_reverse_iterator rend() const;
//! @copydoc ::boost::intrusive::bstree::crend()const
const_reverse_iterator crend() const;
//! @copydoc ::boost::intrusive::bstree::container_from_end_iterator(iterator)
static bs_multiset_impl &container_from_end_iterator(iterator end_iterator);
//! @copydoc ::boost::intrusive::bstree::container_from_end_iterator(const_iterator)
static const bs_multiset_impl &container_from_end_iterator(const_iterator end_iterator);
//! @copydoc ::boost::intrusive::bstree::container_from_iterator(iterator)
static bs_multiset_impl &container_from_iterator(iterator it);
//! @copydoc ::boost::intrusive::bstree::container_from_iterator(const_iterator)
static const bs_multiset_impl &container_from_iterator(const_iterator it);
//! @copydoc ::boost::intrusive::bstree::key_comp()const
key_compare key_comp() const;
//! @copydoc ::boost::intrusive::bstree::value_comp()const
value_compare value_comp() const;
//! @copydoc ::boost::intrusive::bstree::empty()const
bool empty() const;
//! @copydoc ::boost::intrusive::bstree::size()const
size_type size() const;
//! @copydoc ::boost::intrusive::bstree::swap
void swap(bs_multiset_impl& other);
//! @copydoc ::boost::intrusive::bstree::clone_from
template <class Cloner, class Disposer>
void clone_from(const bs_multiset_impl &src, Cloner cloner, Disposer disposer);
#endif //#ifdef BOOST_iNTRUSIVE_DOXYGEN_INVOKED
//! @copydoc ::boost::intrusive::bstree::insert_equal(reference)
iterator insert(reference value)
{ return tree_type::insert_equal(value); }
//! @copydoc ::boost::intrusive::bstree::insert_equal(const_iterator,reference)
iterator insert(const_iterator hint, reference value)
{ return tree_type::insert_equal(hint, value); }
//! @copydoc ::boost::intrusive::bstree::insert_equal(Iterator,Iterator)
template<class Iterator>
void insert(Iterator b, Iterator e)
{ tree_type::insert_equal(b, e); }
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
//! @copydoc ::boost::intrusive::bstree::insert_before
iterator insert_before(const_iterator pos, reference value);
//! @copydoc ::boost::intrusive::bstree::push_back
void push_back(reference value);
//! @copydoc ::boost::intrusive::bstree::push_front
void push_front(reference value);
//! @copydoc ::boost::intrusive::bstree::erase(const_iterator)
iterator erase(const_iterator i);
//! @copydoc ::boost::intrusive::bstree::erase(const_iterator,const_iterator)
iterator erase(const_iterator b, const_iterator e);
//! @copydoc ::boost::intrusive::bstree::erase(const_reference)
size_type erase(const_reference value);
//! @copydoc ::boost::intrusive::bstree::erase(const KeyType&,KeyValueCompare)
template<class KeyType, class KeyValueCompare>
size_type erase(const KeyType& key, KeyValueCompare comp);
//! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const_iterator,Disposer)
template<class Disposer>
iterator erase_and_dispose(const_iterator i, Disposer disposer);
//! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const_iterator,const_iterator,Disposer)
template<class Disposer>
iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer);
//! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const_reference, Disposer)
template<class Disposer>
size_type erase_and_dispose(const_reference value, Disposer disposer);
//! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const KeyType&,KeyValueCompare,Disposer)
template<class KeyType, class KeyValueCompare, class Disposer>
size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer);
//! @copydoc ::boost::intrusive::bstree::clear
void clear();
//! @copydoc ::boost::intrusive::bstree::clear_and_dispose
template<class Disposer>
void clear_and_dispose(Disposer disposer);
//! @copydoc ::boost::intrusive::bstree::count(const_reference)const
size_type count(const_reference value) const;
//! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyValueCompare)const
template<class KeyType, class KeyValueCompare>
size_type count(const KeyType& key, KeyValueCompare comp) const;
//! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference)
iterator lower_bound(const_reference value);
//! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyValueCompare)
template<class KeyType, class KeyValueCompare>
iterator lower_bound(const KeyType& key, KeyValueCompare comp);
//! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference)const
const_iterator lower_bound(const_reference value) const;
//! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyValueCompare)const
template<class KeyType, class KeyValueCompare>
const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const;
//! @copydoc ::boost::intrusive::bstree::upper_bound(const_reference)
iterator upper_bound(const_reference value);
//! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyValueCompare)
template<class KeyType, class KeyValueCompare>
iterator upper_bound(const KeyType& key, KeyValueCompare comp);
//! @copydoc ::boost::intrusive::bstree::upper_bound(const_reference)const
const_iterator upper_bound(const_reference value) const;
//! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyValueCompare)const
template<class KeyType, class KeyValueCompare>
const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const;
//! @copydoc ::boost::intrusive::bstree::find(const_reference)
iterator find(const_reference value);
//! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyValueCompare)
template<class KeyType, class KeyValueCompare>
iterator find(const KeyType& key, KeyValueCompare comp);
//! @copydoc ::boost::intrusive::bstree::find(const_reference)const
const_iterator find(const_reference value) const;
//! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyValueCompare)const
template<class KeyType, class KeyValueCompare>
const_iterator find(const KeyType& key, KeyValueCompare comp) const;
//! @copydoc ::boost::intrusive::bstree::equal_range(const_reference)
std::pair<iterator,iterator> equal_range(const_reference value);
//! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyValueCompare)
template<class KeyType, class KeyValueCompare>
std::pair<iterator,iterator> equal_range(const KeyType& key, KeyValueCompare comp);
//! @copydoc ::boost::intrusive::bstree::equal_range(const_reference)const
std::pair<const_iterator, const_iterator>
equal_range(const_reference value) const;
//! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyValueCompare)const
template<class KeyType, class KeyValueCompare>
std::pair<const_iterator, const_iterator>
equal_range(const KeyType& key, KeyValueCompare comp) const;
//! @copydoc ::boost::intrusive::bstree::bounded_range(const_reference,const_reference,bool,bool)
std::pair<iterator,iterator> bounded_range
(const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed);
//! @copydoc ::boost::intrusive::bstree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool)
template<class KeyType, class KeyValueCompare>
std::pair<iterator,iterator> bounded_range
(const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed);
//! @copydoc ::boost::intrusive::bstree::bounded_range(const_reference,const_reference,bool,bool)const
std::pair<const_iterator, const_iterator>
bounded_range(const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const;
//! @copydoc ::boost::intrusive::bstree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool)const
template<class KeyType, class KeyValueCompare>
std::pair<const_iterator, const_iterator> bounded_range
(const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const;
//! @copydoc ::boost::intrusive::bstree::s_iterator_to(reference)
static iterator s_iterator_to(reference value);
//! @copydoc ::boost::intrusive::bstree::s_iterator_to(const_reference)
static const_iterator s_iterator_to(const_reference value);
//! @copydoc ::boost::intrusive::bstree::iterator_to(reference)
iterator iterator_to(reference value);
//! @copydoc ::boost::intrusive::bstree::iterator_to(const_reference)const
const_iterator iterator_to(const_reference value) const;
//! @copydoc ::boost::intrusive::bstree::init_node(reference)
static void init_node(reference value);
//! @copydoc ::boost::intrusive::bstree::unlink_leftmost_without_rebalance
pointer unlink_leftmost_without_rebalance();
//! @copydoc ::boost::intrusive::bstree::replace_node
void replace_node(iterator replace_this, reference with_this);
//! @copydoc ::boost::intrusive::bstree::remove_node
void remove_node(reference value);
#endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
};
#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
bool operator!= (const bs_multiset_impl<T, Options...> &x, const bs_multiset_impl<T, Options...> &y);
template<class T, class ...Options>
bool operator>(const bs_multiset_impl<T, Options...> &x, const bs_multiset_impl<T, Options...> &y);
template<class T, class ...Options>
bool operator<=(const bs_multiset_impl<T, Options...> &x, const bs_multiset_impl<T, Options...> &y);
template<class T, class ...Options>
bool operator>=(const bs_multiset_impl<T, Options...> &x, const bs_multiset_impl<T, Options...> &y);
template<class T, class ...Options>
void swap(bs_multiset_impl<T, Options...> &x, bs_multiset_impl<T, Options...> &y);
#endif //#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
//! Helper metafunction to define a \c bs_multiset that yields to the same type when the
//! same options (either explicitly or implicitly) are used.
#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class ...Options>
#else
template<class T, class O1 = void, class O2 = void
, class O3 = void, class O4 = void
, class O5 = void>
#endif
struct make_bs_multiset
{
/// @cond
typedef typename pack_options
< bstree_defaults,
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
O1, O2, O3, O4, O5
#else
Options...
#endif
>::type packed_options;
typedef typename detail::get_value_traits
<T, typename packed_options::proto_value_traits>::type value_traits;
typedef typename detail::get_header_holder_type
< value_traits, typename packed_options::header_holder_type >::type header_holder_type;
typedef bs_multiset_impl
< value_traits
, typename packed_options::compare
, typename packed_options::size_type
, packed_options::constant_time_size
, header_holder_type
> implementation_defined;
/// @endcond
typedef implementation_defined type;
};
#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class O1, class O2, class O3, class O4, class O5>
#else
template<class T, class ...Options>
#endif
class bs_multiset
: public make_bs_multiset<T,
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
O1, O2, O3, O4, O5
#else
Options...
#endif
>::type
{
typedef typename make_bs_multiset<T,
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
O1, O2, O3, O4, O5
#else
Options...
#endif
>::type Base;
BOOST_MOVABLE_BUT_NOT_COPYABLE(bs_multiset)
public:
typedef typename Base::value_compare value_compare;
typedef typename Base::value_traits value_traits;
typedef typename Base::iterator iterator;
typedef typename Base::const_iterator const_iterator;
//Assert if passed value traits are compatible with the type
BOOST_STATIC_ASSERT((detail::is_same<typename value_traits::value_type, T>::value));
explicit bs_multiset( const value_compare &cmp = value_compare()
, const value_traits &v_traits = value_traits())
: Base(cmp, v_traits)
{}
template<class Iterator>
bs_multiset( Iterator b, Iterator e
, const value_compare &cmp = value_compare()
, const value_traits &v_traits = value_traits())
: Base(b, e, cmp, v_traits)
{}
bs_multiset(BOOST_RV_REF(bs_multiset) x)
: Base(::boost::move(static_cast<Base&>(x)))
{}
bs_multiset& operator=(BOOST_RV_REF(bs_multiset) x)
{ return static_cast<bs_multiset &>(this->Base::operator=(::boost::move(static_cast<Base&>(x)))); }
static bs_multiset &container_from_end_iterator(iterator end_iterator)
{ return static_cast<bs_multiset &>(Base::container_from_end_iterator(end_iterator)); }
static const bs_multiset &container_from_end_iterator(const_iterator end_iterator)
{ return static_cast<const bs_multiset &>(Base::container_from_end_iterator(end_iterator)); }
static bs_multiset &container_from_iterator(iterator it)
{ return static_cast<bs_multiset &>(Base::container_from_iterator(it)); }
static const bs_multiset &container_from_iterator(const_iterator it)
{ return static_cast<const bs_multiset &>(Base::container_from_iterator(it)); }
};
#endif
} //namespace intrusive
} //namespace boost
#include <boost/intrusive/detail/config_end.hpp>
#endif //BOOST_INTRUSIVE_BS_SET_HPP

View file

@ -0,0 +1,286 @@
/////////////////////////////////////////////////////////////////////////////
//
// (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/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_BS_SET_HOOK_HPP
#define BOOST_INTRUSIVE_BS_SET_HOOK_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/intrusive/detail/config_begin.hpp>
#include <boost/intrusive/intrusive_fwd.hpp>
#include <boost/intrusive/detail/tree_node.hpp>
#include <boost/intrusive/bstree_algorithms.hpp>
#include <boost/intrusive/options.hpp>
#include <boost/intrusive/detail/generic_hook.hpp>
namespace boost {
namespace intrusive {
//! Helper metafunction to define a \c bs_set_base_hook that yields to the same
//! type when the same options (either explicitly or implicitly) are used.
#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class ...Options>
#else
template<class O1 = void, class O2 = void, class O3 = void>
#endif
struct make_bs_set_base_hook
{
/// @cond
typedef typename pack_options
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
< hook_defaults, O1, O2, O3>
#else
< hook_defaults, Options...>
#endif
::type packed_options;
typedef generic_hook
< bstree_algorithms<tree_node_traits<typename packed_options::void_pointer> >
, typename packed_options::tag
, packed_options::link_mode
, BsTreeBaseHookId
> implementation_defined;
/// @endcond
typedef implementation_defined type;
};
//! Derive a class from bs_set_base_hook in order to store objects in
//! in a bs_set/bs_multiset. bs_set_base_hook holds the data necessary to maintain
//! the bs_set/bs_multiset and provides an appropriate value_traits class for bs_set/bs_multiset.
//!
//! The hook admits the following options: \c tag<>, \c void_pointer<>,
//! \c link_mode<>.
//!
//! \c tag<> defines a tag to identify the node.
//! The same tag value can be used in different classes, but if a class is
//! derived from more than one \c list_base_hook, then each \c list_base_hook needs its
//! unique tag.
//!
//! \c void_pointer<> is the pointer type that will be used internally in the hook
//! and the container configured to use this hook.
//!
//! \c link_mode<> will specify the linking mode of the hook (\c normal_link,
//! \c auto_unlink or \c safe_link).
#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class ...Options>
#else
template<class O1, class O2, class O3>
#endif
class bs_set_base_hook
: public make_bs_set_base_hook
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
<O1, O2, O3>
#else
<Options...>
#endif
::type
{
#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
public:
//! <b>Effects</b>: If link_mode is \c auto_unlink or \c safe_link
//! initializes the node to an unlinked state.
//!
//! <b>Throws</b>: Nothing.
bs_set_base_hook();
//! <b>Effects</b>: If link_mode is \c auto_unlink or \c safe_link
//! initializes the node to an unlinked state. The argument is ignored.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Rationale</b>: Providing a copy-constructor
//! makes classes using the hook STL-compliant without forcing the
//! user to do some additional work. \c swap can be used to emulate
//! move-semantics.
bs_set_base_hook(const bs_set_base_hook& );
//! <b>Effects</b>: Empty function. The argument is ignored.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Rationale</b>: Providing an assignment operator
//! makes classes using the hook STL-compliant without forcing the
//! user to do some additional work. \c swap can be used to emulate
//! move-semantics.
bs_set_base_hook& operator=(const bs_set_base_hook& );
//! <b>Effects</b>: If link_mode is \c normal_link, the destructor does
//! nothing (ie. no code is generated). If link_mode is \c safe_link and the
//! object is stored in a set an assertion is raised. If link_mode is
//! \c auto_unlink and \c is_linked() is true, the node is unlinked.
//!
//! <b>Throws</b>: Nothing.
~bs_set_base_hook();
//! <b>Effects</b>: Swapping two nodes swaps the position of the elements
//! related to those nodes in one or two containers. That is, if the node
//! this is part of the element e1, the node x is part of the element e2
//! and both elements are included in the containers s1 and s2, then after
//! the swap-operation e1 is in s2 at the position of e2 and e2 is in s1
//! at the position of e1. If one element is not in a container, then
//! after the swap-operation the other element is not in a container.
//! Iterators to e1 and e2 related to those nodes are invalidated.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
void swap_nodes(bs_set_base_hook &other);
//! <b>Precondition</b>: link_mode must be \c safe_link or \c auto_unlink.
//!
//! <b>Returns</b>: true, if the node belongs to a container, false
//! otherwise. This function can be used to test whether \c set::iterator_to
//! will return a valid iterator.
//!
//! <b>Complexity</b>: Constant
bool is_linked() const;
//! <b>Effects</b>: Removes the node if it's inserted in a container.
//! This function is only allowed if link_mode is \c auto_unlink.
//!
//! <b>Throws</b>: Nothing.
void unlink();
#endif
};
//! Helper metafunction to define a \c bs_set_member_hook that yields to the same
//! type when the same options (either explicitly or implicitly) are used.
#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class ...Options>
#else
template<class O1 = void, class O2 = void, class O3 = void>
#endif
struct make_bs_set_member_hook
{
/// @cond
typedef typename pack_options
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
< hook_defaults, O1, O2, O3>
#else
< hook_defaults, Options...>
#endif
::type packed_options;
typedef generic_hook
< bstree_algorithms<tree_node_traits<typename packed_options::void_pointer> >
, member_tag
, packed_options::link_mode
, NoBaseHookId
> implementation_defined;
/// @endcond
typedef implementation_defined type;
};
//! Put a public data member bs_set_member_hook in order to store objects of this class in
//! a bs_set/bs_multiset. bs_set_member_hook holds the data necessary for maintaining the
//! bs_set/bs_multiset and provides an appropriate value_traits class for bs_set/bs_multiset.
//!
//! The hook admits the following options: \c void_pointer<>, \c link_mode<>.
//!
//! \c void_pointer<> is the pointer type that will be used internally in the hook
//! and the container configured to use this hook.
//!
//! \c link_mode<> will specify the linking mode of the hook (\c normal_link,
//! \c auto_unlink or \c safe_link).
#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class ...Options>
#else
template<class O1, class O2, class O3>
#endif
class bs_set_member_hook
: public make_bs_set_member_hook
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
<O1, O2, O3>
#else
<Options...>
#endif
::type
{
#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
public:
//! <b>Effects</b>: If link_mode is \c auto_unlink or \c safe_link
//! initializes the node to an unlinked state.
//!
//! <b>Throws</b>: Nothing.
bs_set_member_hook();
//! <b>Effects</b>: If link_mode is \c auto_unlink or \c safe_link
//! initializes the node to an unlinked state. The argument is ignored.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Rationale</b>: Providing a copy-constructor
//! makes classes using the hook STL-compliant without forcing the
//! user to do some additional work. \c swap can be used to emulate
//! move-semantics.
bs_set_member_hook(const bs_set_member_hook& );
//! <b>Effects</b>: Empty function. The argument is ignored.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Rationale</b>: Providing an assignment operator
//! makes classes using the hook STL-compliant without forcing the
//! user to do some additional work. \c swap can be used to emulate
//! move-semantics.
bs_set_member_hook& operator=(const bs_set_member_hook& );
//! <b>Effects</b>: If link_mode is \c normal_link, the destructor does
//! nothing (ie. no code is generated). If link_mode is \c safe_link and the
//! object is stored in a set an assertion is raised. If link_mode is
//! \c auto_unlink and \c is_linked() is true, the node is unlinked.
//!
//! <b>Throws</b>: Nothing.
~bs_set_member_hook();
//! <b>Effects</b>: Swapping two nodes swaps the position of the elements
//! related to those nodes in one or two containers. That is, if the node
//! this is part of the element e1, the node x is part of the element e2
//! and both elements are included in the containers s1 and s2, then after
//! the swap-operation e1 is in s2 at the position of e2 and e2 is in s1
//! at the position of e1. If one element is not in a container, then
//! after the swap-operation the other element is not in a container.
//! Iterators to e1 and e2 related to those nodes are invalidated.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
void swap_nodes(bs_set_member_hook &other);
//! <b>Precondition</b>: link_mode must be \c safe_link or \c auto_unlink.
//!
//! <b>Returns</b>: true, if the node belongs to a container, false
//! otherwise. This function can be used to test whether \c set::iterator_to
//! will return a valid iterator.
//!
//! <b>Complexity</b>: Constant
bool is_linked() const;
//! <b>Effects</b>: Removes the node if it's inserted in a container.
//! This function is only allowed if link_mode is \c auto_unlink.
//!
//! <b>Throws</b>: Nothing.
void unlink();
#endif
};
} //namespace intrusive
} //namespace boost
#include <boost/intrusive/detail/config_end.hpp>
#endif //BOOST_INTRUSIVE_BS_SET_HOOK_HPP

2177
boost/intrusive/bstree.hpp Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,507 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Olaf Krzikalla 2004-2006.
// (C) Copyright Ion Gaztanaga 2006-2014
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_CIRCULAR_LIST_ALGORITHMS_HPP
#define BOOST_INTRUSIVE_CIRCULAR_LIST_ALGORITHMS_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/intrusive/detail/config_begin.hpp>
#include <boost/intrusive/intrusive_fwd.hpp>
#include <boost/intrusive/detail/algo_type.hpp>
#include <boost/core/no_exceptions_support.hpp>
#include <cstddef>
namespace boost {
namespace intrusive {
//! circular_list_algorithms provides basic algorithms to manipulate nodes
//! forming a circular doubly linked list. An empty circular list is formed by a node
//! whose pointers point to itself.
//!
//! circular_list_algorithms is configured with a NodeTraits class, which encapsulates the
//! information about the node to be manipulated. NodeTraits must support the
//! following interface:
//!
//! <b>Typedefs</b>:
//!
//! <tt>node</tt>: The type of the node that forms the circular list
//!
//! <tt>node_ptr</tt>: A pointer to a node
//!
//! <tt>const_node_ptr</tt>: A pointer to a const node
//!
//! <b>Static functions</b>:
//!
//! <tt>static node_ptr get_previous(const_node_ptr n);</tt>
//!
//! <tt>static void set_previous(node_ptr n, node_ptr prev);</tt>
//!
//! <tt>static node_ptr get_next(const_node_ptr n);</tt>
//!
//! <tt>static void set_next(node_ptr n, node_ptr next);</tt>
template<class NodeTraits>
class circular_list_algorithms
{
public:
typedef typename NodeTraits::node node;
typedef typename NodeTraits::node_ptr node_ptr;
typedef typename NodeTraits::const_node_ptr const_node_ptr;
typedef NodeTraits node_traits;
//! <b>Effects</b>: Constructs an non-used list element, so that
//! inited(this_node) == true
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void init(const node_ptr &this_node)
{
const node_ptr null_node((node_ptr()));
NodeTraits::set_next(this_node, null_node);
NodeTraits::set_previous(this_node, null_node);
}
//! <b>Effects</b>: Returns true is "this_node" is in a non-used state
//! as if it was initialized by the "init" function.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static bool inited(const const_node_ptr &this_node)
{ return !NodeTraits::get_next(this_node); }
//! <b>Effects</b>: Constructs an empty list, making this_node the only
//! node of the circular list:
//! <tt>NodeTraits::get_next(this_node) == NodeTraits::get_previous(this_node)
//! == this_node</tt>.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void init_header(const node_ptr &this_node)
{
NodeTraits::set_next(this_node, this_node);
NodeTraits::set_previous(this_node, this_node);
}
//! <b>Requires</b>: this_node must be in a circular list or be an empty circular list.
//!
//! <b>Effects</b>: Returns true is "this_node" is the only node of a circular list:
//! <tt>return NodeTraits::get_next(this_node) == this_node</tt>
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static bool unique(const const_node_ptr &this_node)
{
node_ptr next = NodeTraits::get_next(this_node);
return !next || next == this_node;
}
//! <b>Requires</b>: this_node must be in a circular list or be an empty circular list.
//!
//! <b>Effects</b>: Returns the number of nodes in a circular list. If the circular list
//! is empty, returns 1.
//!
//! <b>Complexity</b>: Linear
//!
//! <b>Throws</b>: Nothing.
static std::size_t count(const const_node_ptr &this_node)
{
std::size_t result = 0;
const_node_ptr p = this_node;
do{
p = NodeTraits::get_next(p);
++result;
}while (p != this_node);
return result;
}
//! <b>Requires</b>: this_node must be in a circular list or be an empty circular list.
//!
//! <b>Effects</b>: Unlinks the node from the circular list.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static node_ptr unlink(const node_ptr &this_node)
{
node_ptr next(NodeTraits::get_next(this_node));
node_ptr prev(NodeTraits::get_previous(this_node));
NodeTraits::set_next(prev, next);
NodeTraits::set_previous(next, prev);
return next;
}
//! <b>Requires</b>: b and e must be nodes of the same circular list or an empty range.
//!
//! <b>Effects</b>: Unlinks the node [b, e) from the circular list.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void unlink(const node_ptr &b, const node_ptr &e)
{
if (b != e) {
node_ptr prevb(NodeTraits::get_previous(b));
NodeTraits::set_previous(e, prevb);
NodeTraits::set_next(prevb, e);
}
}
//! <b>Requires</b>: nxt_node must be a node of a circular list.
//!
//! <b>Effects</b>: Links this_node before nxt_node in the circular list.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void link_before(const node_ptr &nxt_node, const node_ptr &this_node)
{
node_ptr prev(NodeTraits::get_previous(nxt_node));
NodeTraits::set_previous(this_node, prev);
NodeTraits::set_next(this_node, nxt_node);
//nxt_node might be an alias for prev->next_
//so use it before NodeTraits::set_next(prev, ...)
//is called and the reference changes it's value
NodeTraits::set_previous(nxt_node, this_node);
NodeTraits::set_next(prev, this_node);
}
//! <b>Requires</b>: prev_node must be a node of a circular list.
//!
//! <b>Effects</b>: Links this_node after prev_node in the circular list.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void link_after(const node_ptr &prev_node, const node_ptr &this_node)
{
node_ptr next(NodeTraits::get_next(prev_node));
NodeTraits::set_previous(this_node, prev_node);
NodeTraits::set_next(this_node, next);
//prev_node might be an alias for next->next_
//so use it before update it before NodeTraits::set_previous(next, ...)
//is called and the reference changes it's value
NodeTraits::set_next(prev_node, this_node);
NodeTraits::set_previous(next, this_node);
}
//! <b>Requires</b>: this_node and other_node must be nodes inserted
//! in circular lists or be empty circular lists.
//!
//! <b>Effects</b>: Swaps the position of the nodes: this_node is inserted in
//! other_nodes position in the second circular list and the other_node is inserted
//! in this_node's position in the first circular list.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
/*
static void swap_nodes(const node_ptr &this_node, const node_ptr &other_node)
{
if (other_node == this_node)
return;
bool empty1 = unique(this_node);
bool empty2 = unique(other_node);
node_ptr next_this(NodeTraits::get_next(this_node));
node_ptr prev_this(NodeTraits::get_previous(this_node));
node_ptr next_other(NodeTraits::get_next(other_node));
node_ptr prev_other(NodeTraits::get_previous(other_node));
//Do the swap
NodeTraits::set_next(this_node, next_other);
NodeTraits::set_next(other_node, next_this);
NodeTraits::set_previous(this_node, prev_other);
NodeTraits::set_previous(other_node, prev_this);
if (empty2){
init(this_node);
}
else{
NodeTraits::set_next(prev_other, this_node);
NodeTraits::set_previous(next_other, this_node);
}
if (empty1){
init(other_node);
}
else{
NodeTraits::set_next(prev_this, other_node);
NodeTraits::set_previous(next_this, other_node);
}
}
*/
//Watanabe version
private:
static void swap_prev(const node_ptr &this_node, const node_ptr &other_node)
{
node_ptr temp(NodeTraits::get_previous(this_node));
NodeTraits::set_previous(this_node, NodeTraits::get_previous(other_node));
NodeTraits::set_previous(other_node, temp);
}
static void swap_next(const node_ptr &this_node, const node_ptr &other_node)
{
node_ptr temp(NodeTraits::get_next(this_node));
NodeTraits::set_next(this_node, NodeTraits::get_next(other_node));
NodeTraits::set_next(other_node, temp);
}
public:
static void swap_nodes(const node_ptr &this_node, const node_ptr &other_node)
{
if (other_node == this_node)
return;
bool this_inited = inited(this_node);
bool other_inited = inited(other_node);
if(this_inited){
init_header(this_node);
}
if(other_inited){
init_header(other_node);
}
node_ptr next_this(NodeTraits::get_next(this_node));
node_ptr prev_this(NodeTraits::get_previous(this_node));
node_ptr next_other(NodeTraits::get_next(other_node));
node_ptr prev_other(NodeTraits::get_previous(other_node));
//these first two swaps must happen before the other two
swap_prev(next_this, next_other);
swap_next(prev_this, prev_other);
swap_next(this_node, other_node);
swap_prev(this_node, other_node);
if(this_inited){
init(other_node);
}
if(other_inited){
init(this_node);
}
}
//! <b>Requires</b>: b and e must be nodes of the same circular list or an empty range.
//! and p must be a node of a different circular list or may not be an iterator in
// [b, e).
//!
//! <b>Effects</b>: Removes the nodes from [b, e) range from their circular list and inserts
//! them before p in p's circular list.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void transfer(const node_ptr &p, const node_ptr &b, const node_ptr &e)
{
if (b != e) {
node_ptr prev_p(NodeTraits::get_previous(p));
node_ptr prev_b(NodeTraits::get_previous(b));
node_ptr prev_e(NodeTraits::get_previous(e));
NodeTraits::set_next(prev_e, p);
NodeTraits::set_previous(p, prev_e);
NodeTraits::set_next(prev_b, e);
NodeTraits::set_previous(e, prev_b);
NodeTraits::set_next(prev_p, b);
NodeTraits::set_previous(b, prev_p);
}
}
//! <b>Requires</b>: i must a node of a circular list
//! and p must be a node of a different circular list.
//!
//! <b>Effects</b>: Removes the node i from its circular list and inserts
//! it before p in p's circular list.
//! If p == i or p == NodeTraits::get_next(i), this function is a null operation.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void transfer(const node_ptr &p, const node_ptr &i)
{
node_ptr n(NodeTraits::get_next(i));
if(n != p && i != p){
node_ptr prev_p(NodeTraits::get_previous(p));
node_ptr prev_i(NodeTraits::get_previous(i));
NodeTraits::set_next(prev_p, i);
NodeTraits::set_previous(i, prev_p);
NodeTraits::set_next(i, p);
NodeTraits::set_previous(p, i);
NodeTraits::set_previous(n, prev_i);
NodeTraits::set_next(prev_i, n);
}
}
//! <b>Effects</b>: Reverses the order of elements in the list.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: This function is linear time.
static void reverse(const node_ptr &p)
{
node_ptr f(NodeTraits::get_next(p));
node_ptr i(NodeTraits::get_next(f)), e(p);
while(i != e) {
node_ptr n = i;
i = NodeTraits::get_next(i);
transfer(f, n, i);
f = n;
}
}
//! <b>Effects</b>: Moves the node p n positions towards the end of the list.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Linear to the number of moved positions.
static void move_backwards(const node_ptr &p, std::size_t n)
{
//Null shift, nothing to do
if(!n) return;
node_ptr first = NodeTraits::get_next(p);
//size() == 0 or 1, nothing to do
if(first == NodeTraits::get_previous(p)) return;
unlink(p);
//Now get the new first node
while(n--){
first = NodeTraits::get_next(first);
}
link_before(first, p);
}
//! <b>Effects</b>: Moves the node p n positions towards the beginning of the list.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Linear to the number of moved positions.
static void move_forward(const node_ptr &p, std::size_t n)
{
//Null shift, nothing to do
if(!n) return;
node_ptr last = NodeTraits::get_previous(p);
//size() == 0 or 1, nothing to do
if(last == NodeTraits::get_next(p)) return;
unlink(p);
//Now get the new last node
while(n--){
last = NodeTraits::get_previous(last);
}
link_after(last, p);
}
//! <b>Requires</b>: f and l must be in a circular list.
//!
//! <b>Effects</b>: Returns the number of nodes in the range [f, l).
//!
//! <b>Complexity</b>: Linear
//!
//! <b>Throws</b>: Nothing.
static std::size_t distance(const const_node_ptr &f, const const_node_ptr &l)
{
const_node_ptr i(f);
std::size_t result = 0;
while(i != l){
i = NodeTraits::get_next(i);
++result;
}
return result;
}
struct stable_partition_info
{
std::size_t num_1st_partition;
std::size_t num_2nd_partition;
node_ptr beg_2st_partition;
};
template<class Pred>
static void stable_partition(node_ptr beg, const node_ptr &end, Pred pred, stable_partition_info &info)
{
node_ptr bcur = node_traits::get_previous(beg);
node_ptr cur = beg;
node_ptr new_f = end;
std::size_t num1 = 0, num2 = 0;
while(cur != end){
if(pred(cur)){
++num1;
bcur = cur;
cur = node_traits::get_next(cur);
}
else{
++num2;
node_ptr last_to_remove = bcur;
new_f = cur;
bcur = cur;
cur = node_traits::get_next(cur);
BOOST_TRY{
//Main loop
while(cur != end){
if(pred(cur)){ //Might throw
++num1;
//Process current node
node_traits::set_next (last_to_remove, cur);
node_traits::set_previous(cur, last_to_remove);
last_to_remove = cur;
node_ptr nxt = node_traits::get_next(cur);
node_traits::set_next (bcur, nxt);
node_traits::set_previous(nxt, bcur);
cur = nxt;
}
else{
++num2;
bcur = cur;
cur = node_traits::get_next(cur);
}
}
}
BOOST_CATCH(...){
node_traits::set_next (last_to_remove, new_f);
node_traits::set_previous(new_f, last_to_remove);
throw;
}
BOOST_CATCH_END
node_traits::set_next(last_to_remove, new_f);
node_traits::set_previous(new_f, last_to_remove);
break;
}
}
info.num_1st_partition = num1;
info.num_2nd_partition = num2;
info.beg_2st_partition = new_f;
}
};
/// @cond
template<class NodeTraits>
struct get_algo<CircularListAlgorithms, NodeTraits>
{
typedef circular_list_algorithms<NodeTraits> type;
};
/// @endcond
} //namespace intrusive
} //namespace boost
#include <boost/intrusive/detail/config_end.hpp>
#endif //BOOST_INTRUSIVE_CIRCULAR_LIST_ALGORITHMS_HPP

View file

@ -0,0 +1,407 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Olaf Krzikalla 2004-2006.
// (C) Copyright Ion Gaztanaga 2006-2014
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_CIRCULAR_SLIST_ALGORITHMS_HPP
#define BOOST_INTRUSIVE_CIRCULAR_SLIST_ALGORITHMS_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <cstddef>
#include <boost/intrusive/detail/config_begin.hpp>
#include <boost/intrusive/intrusive_fwd.hpp>
#include <boost/intrusive/detail/common_slist_algorithms.hpp>
#include <boost/intrusive/detail/algo_type.hpp>
namespace boost {
namespace intrusive {
//! circular_slist_algorithms provides basic algorithms to manipulate nodes
//! forming a circular singly linked list. An empty circular list is formed by a node
//! whose pointer to the next node points to itself.
//!
//! circular_slist_algorithms is configured with a NodeTraits class, which encapsulates the
//! information about the node to be manipulated. NodeTraits must support the
//! following interface:
//!
//! <b>Typedefs</b>:
//!
//! <tt>node</tt>: The type of the node that forms the circular list
//!
//! <tt>node_ptr</tt>: A pointer to a node
//!
//! <tt>const_node_ptr</tt>: A pointer to a const node
//!
//! <b>Static functions</b>:
//!
//! <tt>static node_ptr get_next(const_node_ptr n);</tt>
//!
//! <tt>static void set_next(node_ptr n, node_ptr next);</tt>
template<class NodeTraits>
class circular_slist_algorithms
/// @cond
: public detail::common_slist_algorithms<NodeTraits>
/// @endcond
{
/// @cond
typedef detail::common_slist_algorithms<NodeTraits> base_t;
/// @endcond
public:
typedef typename NodeTraits::node node;
typedef typename NodeTraits::node_ptr node_ptr;
typedef typename NodeTraits::const_node_ptr const_node_ptr;
typedef NodeTraits node_traits;
#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
//! <b>Effects</b>: Constructs an non-used list element, putting the next
//! pointer to null:
//! <tt>NodeTraits::get_next(this_node) == node_ptr()</tt>
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void init(node_ptr this_node);
//! <b>Requires</b>: this_node must be in a circular list or be an empty circular list.
//!
//! <b>Effects</b>: Returns true is "this_node" is the only node of a circular list:
//! or it's a not inserted node:
//! <tt>return node_ptr() == NodeTraits::get_next(this_node) || NodeTraits::get_next(this_node) == this_node</tt>
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static bool unique(const_node_ptr this_node);
//! <b>Effects</b>: Returns true is "this_node" has the same state as
//! if it was inited using "init(node_ptr)"
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static bool inited(const_node_ptr this_node);
//! <b>Requires</b>: prev_node must be in a circular list or be an empty circular list.
//!
//! <b>Effects</b>: Unlinks the next node of prev_node from the circular list.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void unlink_after(node_ptr prev_node);
//! <b>Requires</b>: prev_node and last_node must be in a circular list
//! or be an empty circular list.
//!
//! <b>Effects</b>: Unlinks the range (prev_node, last_node) from the circular list.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void unlink_after(node_ptr prev_node, node_ptr last_node);
//! <b>Requires</b>: prev_node must be a node of a circular list.
//!
//! <b>Effects</b>: Links this_node after prev_node in the circular list.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void link_after(node_ptr prev_node, node_ptr this_node);
//! <b>Requires</b>: b and e must be nodes of the same circular list or an empty range.
//! and p must be a node of a different circular list.
//!
//! <b>Effects</b>: Removes the nodes from (b, e] range from their circular list and inserts
//! them after p in p's circular list.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void transfer_after(node_ptr p, node_ptr b, node_ptr e);
#endif //#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
//! <b>Effects</b>: Constructs an empty list, making this_node the only
//! node of the circular list:
//! <tt>NodeTraits::get_next(this_node) == this_node</tt>.
//!
//! <b>Complexity</b>: Constant
//!
//! <b>Throws</b>: Nothing.
static void init_header(const node_ptr &this_node)
{ NodeTraits::set_next(this_node, this_node); }
//! <b>Requires</b>: this_node and prev_init_node must be in the same circular list.
//!
//! <b>Effects</b>: Returns the previous node of this_node in the circular list starting.
//! the search from prev_init_node. The first node checked for equality
//! is NodeTraits::get_next(prev_init_node).
//!
//! <b>Complexity</b>: Linear to the number of elements between prev_init_node and this_node.
//!
//! <b>Throws</b>: Nothing.
static node_ptr get_previous_node(const node_ptr &prev_init_node, const node_ptr &this_node)
{ return base_t::get_previous_node(prev_init_node, this_node); }
//! <b>Requires</b>: this_node must be in a circular list or be an empty circular list.
//!
//! <b>Effects</b>: Returns the previous node of this_node in the circular list.
//!
//! <b>Complexity</b>: Linear to the number of elements in the circular list.
//!
//! <b>Throws</b>: Nothing.
static node_ptr get_previous_node(const node_ptr & this_node)
{ return base_t::get_previous_node(this_node, this_node); }
//! <b>Requires</b>: this_node must be in a circular list or be an empty circular list.
//!
//! <b>Effects</b>: Returns the previous node of the previous node of this_node in the circular list.
//!
//! <b>Complexity</b>: Linear to the number of elements in the circular list.
//!
//! <b>Throws</b>: Nothing.
static node_ptr get_previous_previous_node(const node_ptr & this_node)
{ return get_previous_previous_node(this_node, this_node); }
//! <b>Requires</b>: this_node and p must be in the same circular list.
//!
//! <b>Effects</b>: Returns the previous node of the previous node of this_node in the
//! circular list starting. the search from p. The first node checked
//! for equality is NodeTraits::get_next((NodeTraits::get_next(p)).
//!
//! <b>Complexity</b>: Linear to the number of elements in the circular list.
//!
//! <b>Throws</b>: Nothing.
static node_ptr get_previous_previous_node(node_ptr p, const node_ptr & this_node)
{
node_ptr p_next = NodeTraits::get_next(p);
node_ptr p_next_next = NodeTraits::get_next(p_next);
while (this_node != p_next_next){
p = p_next;
p_next = p_next_next;
p_next_next = NodeTraits::get_next(p_next);
}
return p;
}
//! <b>Requires</b>: this_node must be in a circular list or be an empty circular list.
//!
//! <b>Effects</b>: Returns the number of nodes in a circular list. If the circular list
//! is empty, returns 1.
//!
//! <b>Complexity</b>: Linear
//!
//! <b>Throws</b>: Nothing.
static std::size_t count(const const_node_ptr & this_node)
{
std::size_t result = 0;
const_node_ptr p = this_node;
do{
p = NodeTraits::get_next(p);
++result;
} while (p != this_node);
return result;
}
//! <b>Requires</b>: this_node must be in a circular list, be an empty circular list or be inited.
//!
//! <b>Effects</b>: Unlinks the node from the circular list.
//!
//! <b>Complexity</b>: Linear to the number of elements in the circular list
//!
//! <b>Throws</b>: Nothing.
static void unlink(const node_ptr & this_node)
{
if(NodeTraits::get_next(this_node))
base_t::unlink_after(get_previous_node(this_node));
}
//! <b>Requires</b>: nxt_node must be a node of a circular list.
//!
//! <b>Effects</b>: Links this_node before nxt_node in the circular list.
//!
//! <b>Complexity</b>: Linear to the number of elements in the circular list.
//!
//! <b>Throws</b>: Nothing.
static void link_before (const node_ptr & nxt_node, const node_ptr & this_node)
{ base_t::link_after(get_previous_node(nxt_node), this_node); }
//! <b>Requires</b>: this_node and other_node must be nodes inserted
//! in circular lists or be empty circular lists.
//!
//! <b>Effects</b>: Swaps the position of the nodes: this_node is inserted in
//! other_nodes position in the second circular list and the other_node is inserted
//! in this_node's position in the first circular list.
//!
//! <b>Complexity</b>: Linear to number of elements of both lists
//!
//! <b>Throws</b>: Nothing.
static void swap_nodes(const node_ptr & this_node, const node_ptr & other_node)
{
if (other_node == this_node)
return;
const node_ptr this_next = NodeTraits::get_next(this_node);
const node_ptr other_next = NodeTraits::get_next(other_node);
const bool this_null = !this_next;
const bool other_null = !other_next;
const bool this_empty = this_next == this_node;
const bool other_empty = other_next == other_node;
if(!(other_null || other_empty)){
NodeTraits::set_next(this_next == other_node ? other_node : get_previous_node(other_node), this_node );
}
if(!(this_null | this_empty)){
NodeTraits::set_next(other_next == this_node ? this_node : get_previous_node(this_node), other_node );
}
NodeTraits::set_next(this_node, other_empty ? this_node : (other_next == this_node ? other_node : other_next) );
NodeTraits::set_next(other_node, this_empty ? other_node : (this_next == other_node ? this_node : this_next ) );
}
//! <b>Effects</b>: Reverses the order of elements in the list.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: This function is linear to the contained elements.
static void reverse(const node_ptr & p)
{
node_ptr i = NodeTraits::get_next(p), e(p);
for (;;) {
node_ptr nxt(NodeTraits::get_next(i));
if (nxt == e)
break;
base_t::transfer_after(e, i, nxt);
}
}
//! <b>Effects</b>: Moves the node p n positions towards the end of the list.
//!
//! <b>Returns</b>: The previous node of p after the function if there has been any movement,
//! Null if n leads to no movement.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Linear to the number of elements plus the number moved positions.
static node_ptr move_backwards(const node_ptr & p, std::size_t n)
{
//Null shift, nothing to do
if(!n) return node_ptr();
node_ptr first = NodeTraits::get_next(p);
//count() == 1 or 2, nothing to do
if(NodeTraits::get_next(first) == p)
return node_ptr();
bool end_found = false;
node_ptr new_last = node_ptr();
//Now find the new last node according to the shift count.
//If we find p before finding the new last node
//unlink p, shortcut the search now that we know the size of the list
//and continue.
for(std::size_t i = 1; i <= n; ++i){
new_last = first;
first = NodeTraits::get_next(first);
if(first == p){
//Shortcut the shift with the modulo of the size of the list
n %= i;
if(!n)
return node_ptr();
i = 0;
//Unlink p and continue the new first node search
first = NodeTraits::get_next(p);
base_t::unlink_after(new_last);
end_found = true;
}
}
//If the p has not been found in the previous loop, find it
//starting in the new first node and unlink it
if(!end_found){
base_t::unlink_after(base_t::get_previous_node(first, p));
}
//Now link p after the new last node
base_t::link_after(new_last, p);
return new_last;
}
//! <b>Effects</b>: Moves the node p n positions towards the beginning of the list.
//!
//! <b>Returns</b>: The previous node of p after the function if there has been any movement,
//! Null if n leads equals to no movement.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Linear to the number of elements plus the number moved positions.
static node_ptr move_forward(const node_ptr & p, std::size_t n)
{
//Null shift, nothing to do
if(!n) return node_ptr();
node_ptr first = node_traits::get_next(p);
//count() == 1 or 2, nothing to do
if(node_traits::get_next(first) == p) return node_ptr();
//Iterate until p is found to know where the current last node is.
//If the shift count is less than the size of the list, we can also obtain
//the position of the new last node after the shift.
node_ptr old_last(first), next_to_it, new_last(p);
std::size_t distance = 1;
while(p != (next_to_it = node_traits::get_next(old_last))){
if(++distance > n)
new_last = node_traits::get_next(new_last);
old_last = next_to_it;
}
//If the shift was bigger or equal than the size, obtain the equivalent
//forward shifts and find the new last node.
if(distance <= n){
//Now find the equivalent forward shifts.
//Shortcut the shift with the modulo of the size of the list
std::size_t new_before_last_pos = (distance - (n % distance))% distance;
//If the shift is a multiple of the size there is nothing to do
if(!new_before_last_pos) return node_ptr();
for( new_last = p
; new_before_last_pos--
; new_last = node_traits::get_next(new_last)){
//empty
}
}
//Now unlink p and link it after the new last node
base_t::unlink_after(old_last);
base_t::link_after(new_last, p);
return new_last;
}
};
/// @cond
template<class NodeTraits>
struct get_algo<CircularSListAlgorithms, NodeTraits>
{
typedef circular_slist_algorithms<NodeTraits> type;
};
/// @endcond
} //namespace intrusive
} //namespace boost
#include <boost/intrusive/detail/config_end.hpp>
#endif //BOOST_INTRUSIVE_CIRCULAR_SLIST_ALGORITHMS_HPP

View file

@ -0,0 +1,77 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2006-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/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_DERIVATION_VALUE_TRAITS_HPP
#define BOOST_INTRUSIVE_DERIVATION_VALUE_TRAITS_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/intrusive/detail/config_begin.hpp>
#include <boost/intrusive/intrusive_fwd.hpp>
#include <boost/intrusive/link_mode.hpp>
#include <boost/intrusive/pointer_traits.hpp>
namespace boost {
namespace intrusive {
//!This value traits template is used to create value traits
//!from user defined node traits where value_traits::value_type will
//!derive from node_traits::node
template<class T, class NodeTraits, link_mode_type LinkMode
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
= safe_link
#endif
>
struct derivation_value_traits
{
public:
typedef NodeTraits node_traits;
typedef T value_type;
typedef typename node_traits::node node;
typedef typename node_traits::node_ptr node_ptr;
typedef typename node_traits::const_node_ptr const_node_ptr;
typedef typename pointer_traits<node_ptr>::
template rebind_pointer<value_type>::type pointer;
typedef typename pointer_traits<node_ptr>::
template rebind_pointer<const value_type>::type const_pointer;
typedef typename boost::intrusive::
pointer_traits<pointer>::reference reference;
typedef typename boost::intrusive::
pointer_traits<const_pointer>::reference const_reference;
static const link_mode_type link_mode = LinkMode;
static node_ptr to_node_ptr(reference value)
{ return node_ptr(&value); }
static const_node_ptr to_node_ptr(const_reference value)
{ return node_ptr(&value); }
static pointer to_value_ptr(const node_ptr &n)
{
return pointer_traits<pointer>::pointer_to(static_cast<reference>(*n));
}
static const_pointer to_value_ptr(const const_node_ptr &n)
{
return pointer_traits<pointer>::pointer_to(static_cast<const_reference>(*n));
}
};
} //namespace intrusive
} //namespace boost
#include <boost/intrusive/detail/config_end.hpp>
#endif //BOOST_INTRUSIVE_DERIVATION_VALUE_TRAITS_HPP

View file

@ -0,0 +1,46 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2014-2014
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_DETAIL_ALGO_TYPE_HPP
#define BOOST_INTRUSIVE_DETAIL_ALGO_TYPE_HPP
#if defined(_MSC_VER)
# pragma once
#endif
namespace boost {
namespace intrusive {
enum algo_types
{
CircularListAlgorithms,
CircularSListAlgorithms,
LinearSListAlgorithms,
CommonSListAlgorithms,
BsTreeAlgorithms,
RbTreeAlgorithms,
AvlTreeAlgorithms,
SgTreeAlgorithms,
SplayTreeAlgorithms,
TreapAlgorithms
};
template<algo_types AlgoType, class NodeTraits>
struct get_algo;
template<algo_types AlgoType, class ValueTraits, class NodePtrCompare, class ExtraChecker>
struct get_node_checker;
} //namespace intrusive
} //namespace boost
#endif //BOOST_INTRUSIVE_DETAIL_ALGO_TYPE_HPP

View file

@ -0,0 +1,280 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2006-2014
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_ANY_NODE_HPP
#define BOOST_INTRUSIVE_ANY_NODE_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/intrusive/pointer_rebind.hpp>
#include <cstddef>
#include <boost/intrusive/detail/mpl.hpp>
namespace boost {
namespace intrusive {
template<class VoidPointer>
struct any_node
{
typedef any_node node;
typedef typename pointer_rebind<VoidPointer, node>::type node_ptr;
typedef typename pointer_rebind<VoidPointer, const node>::type const_node_ptr;
node_ptr node_ptr_1;
node_ptr node_ptr_2;
node_ptr node_ptr_3;
std::size_t size_t_1;
};
template<class VoidPointer>
struct any_list_node_traits
{
typedef any_node<VoidPointer> node;
typedef typename node::node_ptr node_ptr;
typedef typename node::const_node_ptr const_node_ptr;
static const node_ptr &get_next(const const_node_ptr & n)
{ return n->node_ptr_1; }
static void set_next(const node_ptr & n, const node_ptr & next)
{ n->node_ptr_1 = next; }
static const node_ptr &get_previous(const const_node_ptr & n)
{ return n->node_ptr_2; }
static void set_previous(const node_ptr & n, const node_ptr & prev)
{ n->node_ptr_2 = prev; }
};
template<class VoidPointer>
struct any_slist_node_traits
{
typedef any_node<VoidPointer> node;
typedef typename node::node_ptr node_ptr;
typedef typename node::const_node_ptr const_node_ptr;
static const node_ptr &get_next(const const_node_ptr & n)
{ return n->node_ptr_1; }
static void set_next(const node_ptr & n, const node_ptr & next)
{ n->node_ptr_1 = next; }
};
template<class VoidPointer>
struct any_unordered_node_traits
: public any_slist_node_traits<VoidPointer>
{
typedef any_slist_node_traits<VoidPointer> reduced_slist_node_traits;
typedef typename reduced_slist_node_traits::node node;
typedef typename reduced_slist_node_traits::node_ptr node_ptr;
typedef typename reduced_slist_node_traits::const_node_ptr const_node_ptr;
static const bool store_hash = true;
static const bool optimize_multikey = true;
static const node_ptr &get_next(const const_node_ptr & n)
{ return n->node_ptr_1; }
static void set_next(const node_ptr & n, const node_ptr & next)
{ n->node_ptr_1 = next; }
static node_ptr get_prev_in_group(const const_node_ptr & n)
{ return n->node_ptr_2; }
static void set_prev_in_group(const node_ptr & n, const node_ptr & prev)
{ n->node_ptr_2 = prev; }
static std::size_t get_hash(const const_node_ptr & n)
{ return n->size_t_1; }
static void set_hash(const node_ptr & n, std::size_t h)
{ n->size_t_1 = h; }
};
template<class VoidPointer>
struct any_rbtree_node_traits
{
typedef any_node<VoidPointer> node;
typedef typename node::node_ptr node_ptr;
typedef typename node::const_node_ptr const_node_ptr;
typedef std::size_t color;
static const node_ptr &get_parent(const const_node_ptr & n)
{ return n->node_ptr_1; }
static void set_parent(const node_ptr & n, const node_ptr & p)
{ n->node_ptr_1 = p; }
static const node_ptr &get_left(const const_node_ptr & n)
{ return n->node_ptr_2; }
static void set_left(const node_ptr & n, const node_ptr & l)
{ n->node_ptr_2 = l; }
static const node_ptr &get_right(const const_node_ptr & n)
{ return n->node_ptr_3; }
static void set_right(const node_ptr & n, const node_ptr & r)
{ n->node_ptr_3 = r; }
static color get_color(const const_node_ptr & n)
{ return n->size_t_1; }
static void set_color(const node_ptr & n, color c)
{ n->size_t_1 = c; }
static color black()
{ return 0u; }
static color red()
{ return 1u; }
};
template<class VoidPointer>
struct any_avltree_node_traits
{
typedef any_node<VoidPointer> node;
typedef typename node::node_ptr node_ptr;
typedef typename node::const_node_ptr const_node_ptr;
typedef std::size_t balance;
static const node_ptr &get_parent(const const_node_ptr & n)
{ return n->node_ptr_1; }
static void set_parent(const node_ptr & n, const node_ptr & p)
{ n->node_ptr_1 = p; }
static const node_ptr &get_left(const const_node_ptr & n)
{ return n->node_ptr_2; }
static void set_left(const node_ptr & n, const node_ptr & l)
{ n->node_ptr_2 = l; }
static const node_ptr &get_right(const const_node_ptr & n)
{ return n->node_ptr_3; }
static void set_right(const node_ptr & n, const node_ptr & r)
{ n->node_ptr_3 = r; }
static balance get_balance(const const_node_ptr & n)
{ return n->size_t_1; }
static void set_balance(const node_ptr & n, balance b)
{ n->size_t_1 = b; }
static balance negative()
{ return 0u; }
static balance zero()
{ return 1u; }
static balance positive()
{ return 2u; }
};
template<class VoidPointer>
struct any_tree_node_traits
{
typedef any_node<VoidPointer> node;
typedef typename node::node_ptr node_ptr;
typedef typename node::const_node_ptr const_node_ptr;
static const node_ptr &get_parent(const const_node_ptr & n)
{ return n->node_ptr_1; }
static void set_parent(const node_ptr & n, const node_ptr & p)
{ n->node_ptr_1 = p; }
static const node_ptr &get_left(const const_node_ptr & n)
{ return n->node_ptr_2; }
static void set_left(const node_ptr & n, const node_ptr & l)
{ n->node_ptr_2 = l; }
static const node_ptr &get_right(const const_node_ptr & n)
{ return n->node_ptr_3; }
static void set_right(const node_ptr & n, const node_ptr & r)
{ n->node_ptr_3 = r; }
};
template<class VoidPointer>
class any_node_traits
{
public:
typedef any_node<VoidPointer> node;
typedef typename node::node_ptr node_ptr;
typedef typename node::const_node_ptr const_node_ptr;
};
template<class VoidPointer>
class any_algorithms
{
template <class T>
static void function_not_available_for_any_hooks(typename detail::enable_if<detail::is_same<T, bool> >::type)
{}
public:
typedef any_node<VoidPointer> node;
typedef typename node::node_ptr node_ptr;
typedef typename node::const_node_ptr const_node_ptr;
typedef any_node_traits<VoidPointer> node_traits;
//! <b>Requires</b>: node must not be part of any tree.
//!
//! <b>Effects</b>: After the function unique(node) == true.
//!
//! <b>Complexity</b>: Constant.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Nodes</b>: If node is inserted in a tree, this function corrupts the tree.
static void init(const node_ptr & node)
{ node->node_ptr_1 = 0; };
//! <b>Effects</b>: Returns true if node is in the same state as if called init(node)
//!
//! <b>Complexity</b>: Constant.
//!
//! <b>Throws</b>: Nothing.
static bool inited(const const_node_ptr & node)
{ return !node->node_ptr_1; };
static bool unique(const const_node_ptr & node)
{ return 0 == node->node_ptr_1; }
static void unlink(const node_ptr &)
{
//Auto-unlink hooks and unlink() are not available for any hooks
any_algorithms<VoidPointer>::template function_not_available_for_any_hooks<node_ptr>();
}
static void swap_nodes(const node_ptr &, const node_ptr &)
{
//Any nodes have no swap_nodes capability because they don't know
//what algorithm they must use to unlink the node from the container
any_algorithms<VoidPointer>::template function_not_available_for_any_hooks<node_ptr>();
}
};
} //namespace intrusive
} //namespace boost
#endif //BOOST_INTRUSIVE_ANY_NODE_HPP

View file

@ -0,0 +1,90 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2014-2014
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_DETAIL_ARRAY_INITIALIZER_HPP
#define BOOST_INTRUSIVE_DETAIL_ARRAY_INITIALIZER_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/core/no_exceptions_support.hpp>
namespace boost {
namespace intrusive {
namespace detail {
//This is not standard, but should work with all compilers
union max_align
{
char char_;
short short_;
int int_;
long long_;
#ifdef BOOST_HAS_LONG_LONG
long long long_long_;
#endif
float float_;
double double_;
long double long_double_;
void * void_ptr_;
};
template<class T, std::size_t N>
class array_initializer
{
public:
template<class CommonInitializer>
array_initializer(const CommonInitializer &init)
{
char *init_buf = (char*)rawbuf;
std::size_t i = 0;
BOOST_TRY{
for(; i != N; ++i){
new(init_buf)T(init);
init_buf += sizeof(T);
}
}
BOOST_CATCH(...){
while(i--){
init_buf -= sizeof(T);
((T*)init_buf)->~T();
}
BOOST_RETHROW;
}
BOOST_CATCH_END
}
operator T* ()
{ return (T*)(rawbuf); }
operator const T*() const
{ return (const T*)(rawbuf); }
~array_initializer()
{
char *init_buf = (char*)rawbuf + N*sizeof(T);
for(std::size_t i = 0; i != N; ++i){
init_buf -= sizeof(T);
((T*)init_buf)->~T();
}
}
private:
detail::max_align rawbuf[(N*sizeof(T)-1)/sizeof(detail::max_align)+1];
};
} //namespace detail{
} //namespace intrusive{
} //namespace boost{
#endif //BOOST_INTRUSIVE_DETAIL_ARRAY_INITIALIZER_HPP

View file

@ -0,0 +1,41 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2006-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/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_DETAIL_ASSERT_HPP
#define BOOST_INTRUSIVE_DETAIL_ASSERT_HPP
#if defined(_MSC_VER)
#pragma once
#endif
#if !defined(BOOST_INTRUSIVE_INVARIANT_ASSERT)
#include <boost/assert.hpp>
#define BOOST_INTRUSIVE_INVARIANT_ASSERT BOOST_ASSERT
#elif defined(BOOST_INTRUSIVE_INVARIANT_ASSERT_INCLUDE)
#include BOOST_INTRUSIVE_INVARIANT_ASSERT_INCLUDE
#endif
#if !defined(BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT)
#include <boost/assert.hpp>
#define BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT BOOST_ASSERT
#elif defined(BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT_INCLUDE)
#include BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT_INCLUDE
#endif
#if !defined(BOOST_INTRUSIVE_SAFE_HOOK_DESTRUCTOR_ASSERT)
#include <boost/assert.hpp>
#define BOOST_INTRUSIVE_SAFE_HOOK_DESTRUCTOR_ASSERT BOOST_ASSERT
#elif defined(BOOST_INTRUSIVE_SAFE_HOOK_DESTRUCTOR_ASSERT_INCLUDE)
#include BOOST_INTRUSIVE_SAFE_HOOK_DESTRUCTOR_ASSERT_INCLUDE
#endif
#endif //BOOST_INTRUSIVE_DETAIL_ASSERT_HPP

View file

@ -0,0 +1,188 @@
/////////////////////////////////////////////////////////////////////////////
//
// (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/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_AVLTREE_NODE_HPP
#define BOOST_INTRUSIVE_AVLTREE_NODE_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/intrusive/detail/config_begin.hpp>
#include <boost/intrusive/pointer_rebind.hpp>
#include <boost/intrusive/avltree_algorithms.hpp>
#include <boost/intrusive/pointer_plus_bits.hpp>
#include <boost/intrusive/detail/mpl.hpp>
namespace boost {
namespace intrusive {
/////////////////////////////////////////////////////////////////////////////
// //
// Generic node_traits for any pointer type //
// //
/////////////////////////////////////////////////////////////////////////////
//This is the compact representation: 3 pointers
template<class VoidPointer>
struct compact_avltree_node
{
typedef typename pointer_rebind<VoidPointer, compact_avltree_node<VoidPointer> >::type node_ptr;
typedef typename pointer_rebind<VoidPointer, const compact_avltree_node<VoidPointer> >::type const_node_ptr;
enum balance { negative_t, zero_t, positive_t };
node_ptr parent_, left_, right_;
};
//This is the normal representation: 3 pointers + enum
template<class VoidPointer>
struct avltree_node
{
typedef typename pointer_rebind<VoidPointer, avltree_node<VoidPointer> >::type node_ptr;
typedef typename pointer_rebind<VoidPointer, const avltree_node<VoidPointer> >::type const_node_ptr;
enum balance { negative_t, zero_t, positive_t };
node_ptr parent_, left_, right_;
balance balance_;
};
//This is the default node traits implementation
//using a node with 3 generic pointers plus an enum
template<class VoidPointer>
struct default_avltree_node_traits_impl
{
typedef avltree_node<VoidPointer> node;
typedef typename node::node_ptr node_ptr;
typedef typename node::const_node_ptr const_node_ptr;
typedef typename node::balance balance;
static node_ptr get_parent(const const_node_ptr & n)
{ return n->parent_; }
static node_ptr get_parent(const node_ptr & n)
{ return n->parent_; }
static void set_parent(const node_ptr & n, const node_ptr & p)
{ n->parent_ = p; }
static node_ptr get_left(const const_node_ptr & n)
{ return n->left_; }
static node_ptr get_left(const node_ptr & n)
{ return n->left_; }
static void set_left(const node_ptr & n, const node_ptr & l)
{ n->left_ = l; }
static node_ptr get_right(const const_node_ptr & n)
{ return n->right_; }
static node_ptr get_right(const node_ptr & n)
{ return n->right_; }
static void set_right(const node_ptr & n, const node_ptr & r)
{ n->right_ = r; }
static balance get_balance(const const_node_ptr & n)
{ return n->balance_; }
static balance get_balance(const node_ptr & n)
{ return n->balance_; }
static void set_balance(const node_ptr & n, balance b)
{ n->balance_ = b; }
static balance negative()
{ return node::negative_t; }
static balance zero()
{ return node::zero_t; }
static balance positive()
{ return node::positive_t; }
};
//This is the compact node traits implementation
//using a node with 3 generic pointers
template<class VoidPointer>
struct compact_avltree_node_traits_impl
{
typedef compact_avltree_node<VoidPointer> node;
typedef typename node::node_ptr node_ptr;
typedef typename node::const_node_ptr const_node_ptr;
typedef typename node::balance balance;
typedef pointer_plus_bits<node_ptr, 2> ptr_bit;
static node_ptr get_parent(const const_node_ptr & n)
{ return ptr_bit::get_pointer(n->parent_); }
static void set_parent(const node_ptr & n, const node_ptr & p)
{ ptr_bit::set_pointer(n->parent_, p); }
static node_ptr get_left(const const_node_ptr & n)
{ return n->left_; }
static void set_left(const node_ptr & n, const node_ptr & l)
{ n->left_ = l; }
static node_ptr get_right(const const_node_ptr & n)
{ return n->right_; }
static void set_right(const node_ptr & n, const node_ptr & r)
{ n->right_ = r; }
static balance get_balance(const const_node_ptr & n)
{ return (balance)ptr_bit::get_bits(n->parent_); }
static void set_balance(const node_ptr & n, balance b)
{ ptr_bit::set_bits(n->parent_, (std::size_t)b); }
static balance negative()
{ return node::negative_t; }
static balance zero()
{ return node::zero_t; }
static balance positive()
{ return node::positive_t; }
};
//Dispatches the implementation based on the boolean
template<class VoidPointer, bool Compact>
struct avltree_node_traits_dispatch
: public default_avltree_node_traits_impl<VoidPointer>
{};
template<class VoidPointer>
struct avltree_node_traits_dispatch<VoidPointer, true>
: public compact_avltree_node_traits_impl<VoidPointer>
{};
//Inherit from rbtree_node_traits_dispatch depending on the embedding capabilities
template<class VoidPointer, bool OptimizeSize = false>
struct avltree_node_traits
: public avltree_node_traits_dispatch
< VoidPointer
, OptimizeSize &&
max_pointer_plus_bits
< VoidPointer
, detail::alignment_of<compact_avltree_node<VoidPointer> >::value
>::value >= 2u
>
{};
} //namespace intrusive
} //namespace boost
#include <boost/intrusive/detail/config_end.hpp>
#endif //BOOST_INTRUSIVE_AVLTREE_NODE_HPP

View file

@ -0,0 +1,194 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2007-2014
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_COMMON_SLIST_ALGORITHMS_HPP
#define BOOST_INTRUSIVE_COMMON_SLIST_ALGORITHMS_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/intrusive/intrusive_fwd.hpp>
#include <boost/intrusive/detail/assert.hpp>
#include <boost/intrusive/detail/algo_type.hpp>
#include <boost/core/no_exceptions_support.hpp>
#include <cstddef>
namespace boost {
namespace intrusive {
namespace detail {
template<class NodeTraits>
class common_slist_algorithms
{
public:
typedef typename NodeTraits::node node;
typedef typename NodeTraits::node_ptr node_ptr;
typedef typename NodeTraits::const_node_ptr const_node_ptr;
typedef NodeTraits node_traits;
static node_ptr get_previous_node(node_ptr p, const node_ptr & this_node)
{
for( node_ptr p_next
; this_node != (p_next = NodeTraits::get_next(p))
; p = p_next){
//Logic error: possible use of linear lists with
//operations only permitted with lists
BOOST_INTRUSIVE_INVARIANT_ASSERT(p);
}
return p;
}
static void init(const node_ptr & this_node)
{ NodeTraits::set_next(this_node, node_ptr()); }
static bool unique(const const_node_ptr & this_node)
{
node_ptr next = NodeTraits::get_next(this_node);
return !next || next == this_node;
}
static bool inited(const const_node_ptr & this_node)
{ return !NodeTraits::get_next(this_node); }
static void unlink_after(const node_ptr & prev_node)
{
const_node_ptr this_node(NodeTraits::get_next(prev_node));
NodeTraits::set_next(prev_node, NodeTraits::get_next(this_node));
}
static void unlink_after(const node_ptr & prev_node, const node_ptr & last_node)
{ NodeTraits::set_next(prev_node, last_node); }
static void link_after(const node_ptr & prev_node, const node_ptr & this_node)
{
NodeTraits::set_next(this_node, NodeTraits::get_next(prev_node));
NodeTraits::set_next(prev_node, this_node);
}
static void incorporate_after(const node_ptr & bp, const node_ptr & b, const node_ptr & be)
{
node_ptr p(NodeTraits::get_next(bp));
NodeTraits::set_next(bp, b);
NodeTraits::set_next(be, p);
}
static void transfer_after(const node_ptr & bp, const node_ptr & bb, const node_ptr & be)
{
if (bp != bb && bp != be && bb != be) {
node_ptr next_b = NodeTraits::get_next(bb);
node_ptr next_e = NodeTraits::get_next(be);
node_ptr next_p = NodeTraits::get_next(bp);
NodeTraits::set_next(bb, next_e);
NodeTraits::set_next(be, next_p);
NodeTraits::set_next(bp, next_b);
}
}
struct stable_partition_info
{
std::size_t num_1st_partition;
std::size_t num_2nd_partition;
node_ptr beg_2st_partition;
node_ptr new_last_node;
};
template<class Pred>
static void stable_partition(node_ptr before_beg, const node_ptr &end, Pred pred, stable_partition_info &info)
{
node_ptr bcur = before_beg;
node_ptr cur = node_traits::get_next(bcur);
node_ptr new_f = end;
std::size_t num1 = 0, num2 = 0;
while(cur != end){
if(pred(cur)){
++num1;
bcur = cur;
cur = node_traits::get_next(cur);
}
else{
++num2;
node_ptr last_to_remove = bcur;
new_f = cur;
bcur = cur;
cur = node_traits::get_next(cur);
BOOST_TRY{
//Main loop
while(cur != end){
if(pred(cur)){ //Might throw
++num1;
//Process current node
node_traits::set_next(last_to_remove, cur);
last_to_remove = cur;
node_ptr nxt = node_traits::get_next(cur);
node_traits::set_next(bcur, nxt);
cur = nxt;
}
else{
++num2;
bcur = cur;
cur = node_traits::get_next(cur);
}
}
}
BOOST_CATCH(...){
node_traits::set_next(last_to_remove, new_f);
throw;
}
BOOST_CATCH_END
node_traits::set_next(last_to_remove, new_f);
break;
}
}
info.num_1st_partition = num1;
info.num_2nd_partition = num2;
info.beg_2st_partition = new_f;
info.new_last_node = bcur;
}
//! <b>Requires</b>: f and l must be in a circular list.
//!
//! <b>Effects</b>: Returns the number of nodes in the range [f, l).
//!
//! <b>Complexity</b>: Linear
//!
//! <b>Throws</b>: Nothing.
static std::size_t distance(const const_node_ptr &f, const const_node_ptr &l)
{
const_node_ptr i(f);
std::size_t result = 0;
while(i != l){
i = NodeTraits::get_next(i);
++result;
}
return result;
}
};
/// @endcond
} //namespace detail
/// @cond
template<class NodeTraits>
struct get_algo<CommonSListAlgorithms, NodeTraits>
{
typedef detail::common_slist_algorithms<NodeTraits> type;
};
} //namespace intrusive
} //namespace boost
#endif //BOOST_INTRUSIVE_COMMON_SLIST_ALGORITHMS_HPP

View file

@ -0,0 +1,51 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2006-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/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONFIG_HPP
#include <boost/config.hpp>
#endif
#ifdef BOOST_MSVC
#pragma warning (push)
//
//'function' : resolved overload was found by argument-dependent lookup
//A function found by argument-dependent lookup (Koenig lookup) was eventually
//chosen by overload resolution.
//
//In Visual C++ .NET and earlier compilers, a different function would have
//been called. To pick the original function, use an explicitly qualified name.
//
//warning C4275: non dll-interface class 'x' used as base for
//dll-interface class 'Y'
#pragma warning (disable : 4275)
//warning C4251: 'x' : class 'y' needs to have dll-interface to
//be used by clients of class 'z'
#pragma warning (disable : 4251)
#pragma warning (disable : 4675)
#pragma warning (disable : 4996)
#pragma warning (disable : 4503)
#pragma warning (disable : 4284) // odd return type for operator->
#pragma warning (disable : 4244) // possible loss of data
#pragma warning (disable : 4521) ////Disable "multiple copy constructors specified"
#pragma warning (disable : 4522)
#pragma warning (disable : 4146)
#pragma warning (disable : 4267) //conversion from 'X' to 'Y', possible loss of data
#pragma warning (disable : 4127) //conditional expression is constant
#pragma warning (disable : 4706) //assignment within conditional expression
#pragma warning (disable : 4541) //'typeid' used on polymorphic type 'boost::exception' with /GR-
#pragma warning (disable : 4512) //'typeid' used on polymorphic type 'boost::exception' with /GR-
#endif
//#define BOOST_INTRUSIVE_USE_ITERATOR_FACADE
//#define BOOST_INTRUSIVE_USE_ITERATOR_ENABLE_IF_CONVERTIBLE

View file

@ -0,0 +1,15 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2006-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/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#if defined BOOST_MSVC
#pragma warning (pop)
#endif

View file

@ -0,0 +1,65 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2014-2014
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_DETAIL_DEFAULT_HEADER_HOLDER_HPP
#define BOOST_INTRUSIVE_DETAIL_DEFAULT_HEADER_HOLDER_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/intrusive/detail/to_raw_pointer.hpp>
namespace boost {
namespace intrusive {
namespace detail {
// trivial header node holder
template < typename NodeTraits >
struct default_header_holder : public NodeTraits::node
{
typedef NodeTraits node_traits;
typedef typename node_traits::node node;
typedef typename node_traits::node_ptr node_ptr;
typedef typename node_traits::const_node_ptr const_node_ptr;
default_header_holder() : node() {}
const_node_ptr get_node() const
{ return pointer_traits< const_node_ptr >::pointer_to(*static_cast< const node* >(this)); }
node_ptr get_node()
{ return pointer_traits< node_ptr >::pointer_to(*static_cast< node* >(this)); }
// (unsafe) downcast used to implement container-from-iterator
static default_header_holder* get_holder(const node_ptr &p)
{ return static_cast< default_header_holder* >(boost::intrusive::detail::to_raw_pointer(p)); }
};
// type function producing the header node holder
template < typename Value_Traits, typename HeaderHolder >
struct get_header_holder_type
{
typedef HeaderHolder type;
};
template < typename Value_Traits >
struct get_header_holder_type< Value_Traits, void >
{
typedef default_header_holder< typename Value_Traits::node_traits > type;
};
} //namespace detail
} //namespace intrusive
} //namespace boost
#endif //BOOST_INTRUSIVE_DETAIL_DEFAULT_HEADER_HOLDER_HPP

View file

@ -0,0 +1,226 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Joaquin M Lopez Munoz 2006-2013
// (C) Copyright Ion Gaztanaga 2014-2014
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_DETAIL_EBO_HOLDER_HPP
#define BOOST_INTRUSIVE_DETAIL_EBO_HOLDER_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/config.hpp>
namespace boost {
namespace intrusive {
namespace detail {
#if defined(BOOST_MSVC) || defined(__BORLANDC_)
#define BOOST_INTRUSIVE_TT_DECL __cdecl
#else
#define BOOST_INTRUSIVE_TT_DECL
#endif
#if defined(_MSC_EXTENSIONS) && !defined(__BORLAND__) && !defined(_WIN64) && !defined(_M_ARM) && !defined(UNDER_CE)
#define BOOST_INTRUSIVE_TT_TEST_MSC_FUNC_SIGS
#endif
template <typename T>
struct is_unary_or_binary_function_impl
{ static const bool value = false; };
// see boost ticket #4094
// avoid duplicate definitions of is_unary_or_binary_function_impl
#ifndef BOOST_INTRUSIVE_TT_TEST_MSC_FUNC_SIGS
template <typename R>
struct is_unary_or_binary_function_impl<R (*)()>
{ static const bool value = true; };
template <typename R>
struct is_unary_or_binary_function_impl<R (*)(...)>
{ static const bool value = true; };
#else // BOOST_INTRUSIVE_TT_TEST_MSC_FUNC_SIGS
template <typename R>
struct is_unary_or_binary_function_impl<R (__stdcall*)()>
{ static const bool value = true; };
#ifndef _MANAGED
template <typename R>
struct is_unary_or_binary_function_impl<R (__fastcall*)()>
{ static const bool value = true; };
#endif
template <typename R>
struct is_unary_or_binary_function_impl<R (__cdecl*)()>
{ static const bool value = true; };
template <typename R>
struct is_unary_or_binary_function_impl<R (__cdecl*)(...)>
{ static const bool value = true; };
#endif
// see boost ticket #4094
// avoid duplicate definitions of is_unary_or_binary_function_impl
#ifndef BOOST_INTRUSIVE_TT_TEST_MSC_FUNC_SIGS
template <typename R, class T0>
struct is_unary_or_binary_function_impl<R (*)(T0)>
{ static const bool value = true; };
template <typename R, class T0>
struct is_unary_or_binary_function_impl<R (*)(T0...)>
{ static const bool value = true; };
#else // BOOST_INTRUSIVE_TT_TEST_MSC_FUNC_SIGS
template <typename R, class T0>
struct is_unary_or_binary_function_impl<R (__stdcall*)(T0)>
{ static const bool value = true; };
#ifndef _MANAGED
template <typename R, class T0>
struct is_unary_or_binary_function_impl<R (__fastcall*)(T0)>
{ static const bool value = true; };
#endif
template <typename R, class T0>
struct is_unary_or_binary_function_impl<R (__cdecl*)(T0)>
{ static const bool value = true; };
template <typename R, class T0>
struct is_unary_or_binary_function_impl<R (__cdecl*)(T0...)>
{ static const bool value = true; };
#endif
// see boost ticket #4094
// avoid duplicate definitions of is_unary_or_binary_function_impl
#ifndef BOOST_INTRUSIVE_TT_TEST_MSC_FUNC_SIGS
template <typename R, class T0, class T1>
struct is_unary_or_binary_function_impl<R (*)(T0, T1)>
{ static const bool value = true; };
template <typename R, class T0, class T1>
struct is_unary_or_binary_function_impl<R (*)(T0, T1...)>
{ static const bool value = true; };
#else // BOOST_INTRUSIVE_TT_TEST_MSC_FUNC_SIGS
template <typename R, class T0, class T1>
struct is_unary_or_binary_function_impl<R (__stdcall*)(T0, T1)>
{ static const bool value = true; };
#ifndef _MANAGED
template <typename R, class T0, class T1>
struct is_unary_or_binary_function_impl<R (__fastcall*)(T0, T1)>
{ static const bool value = true; };
#endif
template <typename R, class T0, class T1>
struct is_unary_or_binary_function_impl<R (__cdecl*)(T0, T1)>
{ static const bool value = true; };
template <typename R, class T0, class T1>
struct is_unary_or_binary_function_impl<R (__cdecl*)(T0, T1...)>
{ static const bool value = true; };
#endif
template <typename T>
struct is_unary_or_binary_function_impl<T&>
{ static const bool value = false; };
template<typename T>
struct is_unary_or_binary_function : is_unary_or_binary_function_impl<T>
{};
template<typename T, bool IsEmpty = true>
class ebo_functor_holder_impl
{
public:
ebo_functor_holder_impl()
{}
ebo_functor_holder_impl(const T& t)
: t_(t)
{}
template<class Arg1, class Arg2>
ebo_functor_holder_impl(const Arg1& arg1, const Arg2& arg2)
: t_(arg1, arg2)
{}
T& get(){return t_;}
const T& get()const{return t_;}
private:
T t_;
};
template<typename T>
class ebo_functor_holder_impl<T, false>
: public T
{
public:
ebo_functor_holder_impl()
{}
ebo_functor_holder_impl(const T& t)
: T(t)
{}
template<class Arg1, class Arg2>
ebo_functor_holder_impl(const Arg1& arg1, const Arg2& arg2)
: T(arg1, arg2)
{}
T& get(){return *this;}
const T& get()const{return *this;}
};
template<typename T>
class ebo_functor_holder
: public ebo_functor_holder_impl<T, is_unary_or_binary_function<T>::value>
{
private:
typedef ebo_functor_holder_impl<T, is_unary_or_binary_function<T>::value> super;
public:
ebo_functor_holder(){}
ebo_functor_holder(const T& t)
: super(t)
{}
template<class Arg1, class Arg2>
ebo_functor_holder(const Arg1& arg1, const Arg2& arg2)
: super(arg1, arg2)
{}
ebo_functor_holder& operator=(const ebo_functor_holder& x)
{
this->get()=x.get();
return *this;
}
};
} //namespace detail {
} //namespace intrusive {
} //namespace boost {
#endif //#ifndef BOOST_INTRUSIVE_DETAIL_EBO_HOLDER_HPP

View file

@ -0,0 +1,40 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2014-2014
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_DETAIL_EMPTY_NODE_CHECKER_HPP
#define BOOST_INTRUSIVE_DETAIL_EMPTY_NODE_CHECKER_HPP
#if defined(_MSC_VER)
# pragma once
#endif
namespace boost {
namespace intrusive {
namespace detail {
template<class ValueTraits>
struct empty_node_checker
{
typedef ValueTraits value_traits;
typedef typename value_traits::node_traits node_traits;
typedef typename node_traits::const_node_ptr const_node_ptr;
struct return_type {};
void operator () (const const_node_ptr&, const return_type&, const return_type&, return_type&) {}
};
} //namespace detail{
} //namespace intrusive{
} //namespace boost{
#endif //BOOST_INTRUSIVE_DETAIL_EMPTY_NODE_CHECKER_HPP

View file

@ -0,0 +1,44 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2014-2014
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_DETAIL_EQUAL_TO_VALUE_HPP
#define BOOST_INTRUSIVE_DETAIL_EQUAL_TO_VALUE_HPP
#if defined(_MSC_VER)
# pragma once
#endif
namespace boost {
namespace intrusive {
namespace detail {
//This functor compares a stored value
//and the one passed as an argument
template<class ConstReference>
class equal_to_value
{
ConstReference t_;
public:
equal_to_value(ConstReference t)
: t_(t)
{}
bool operator()(ConstReference t)const
{ return t_ == t; }
};
} //namespace detail{
} //namespace intrusive{
} //namespace boost{
#endif //BOOST_INTRUSIVE_DETAIL_EQUAL_TO_VALUE_HPP

View file

@ -0,0 +1,84 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2014-2014
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_DETAIL_EXCEPTION_DISPOSER_HPP
#define BOOST_INTRUSIVE_DETAIL_EXCEPTION_DISPOSER_HPP
#if defined(_MSC_VER)
# pragma once
#endif
namespace boost {
namespace intrusive {
namespace detail {
template<class Container, class Disposer>
class exception_disposer
{
Container *cont_;
Disposer &disp_;
exception_disposer(const exception_disposer&);
exception_disposer &operator=(const exception_disposer&);
public:
exception_disposer(Container &cont, Disposer &disp)
: cont_(&cont), disp_(disp)
{}
void release()
{ cont_ = 0; }
~exception_disposer()
{
if(cont_){
cont_->clear_and_dispose(disp_);
}
}
};
template<class Container, class Disposer, class SizeType>
class exception_array_disposer
{
Container *cont_;
Disposer &disp_;
SizeType &constructed_;
exception_array_disposer(const exception_array_disposer&);
exception_array_disposer &operator=(const exception_array_disposer&);
public:
exception_array_disposer
(Container &cont, Disposer &disp, SizeType &constructed)
: cont_(&cont), disp_(disp), constructed_(constructed)
{}
void release()
{ cont_ = 0; }
~exception_array_disposer()
{
SizeType n = constructed_;
if(cont_){
while(n--){
cont_[n].clear_and_dispose(disp_);
}
}
}
};
} //namespace detail{
} //namespace intrusive{
} //namespace boost{
#endif //BOOST_INTRUSIVE_DETAIL_EXCEPTION_DISPOSER_HPP

View file

@ -0,0 +1,88 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2009-2013.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
// This code was modified from the code posted by Alexandre Courpron in his
// article "Interface Detection" in The Code Project:
// http://www.codeproject.com/KB/architecture/Detector.aspx
///////////////////////////////////////////////////////////////////////////////
// Copyright 2007 Alexandre Courpron
//
// Permission to use, copy, modify, redistribute and sell this software,
// provided that this copyright notice appears on all copies of the software.
///////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_DETAIL_FUNCTION_DETECTOR_HPP
#define BOOST_INTRUSIVE_DETAIL_FUNCTION_DETECTOR_HPP
#if defined(_MSC_VER)
# pragma once
#endif
namespace boost {
namespace intrusive {
namespace function_detector {
typedef char NotFoundType;
struct StaticFunctionType { NotFoundType x [2]; };
struct NonStaticFunctionType { NotFoundType x [3]; };
enum
{ NotFound = 0,
StaticFunction = sizeof( StaticFunctionType ) - sizeof( NotFoundType ),
NonStaticFunction = sizeof( NonStaticFunctionType ) - sizeof( NotFoundType )
};
} //namespace boost {
} //namespace intrusive {
} //namespace function_detector {
#define BOOST_INTRUSIVE_CREATE_FUNCTION_DETECTOR(Identifier, InstantiationKey) \
namespace boost { \
namespace intrusive { \
namespace function_detector { \
template < class T, \
class NonStaticType, \
class NonStaticConstType, \
class StaticType > \
class DetectMember_##InstantiationKey_##Identifier { \
template < NonStaticType > \
struct TestNonStaticNonConst ; \
\
template < NonStaticConstType > \
struct TestNonStaticConst ; \
\
template < StaticType > \
struct TestStatic ; \
\
template <class U > \
static NonStaticFunctionType Test( TestNonStaticNonConst<&U::Identifier>*, int ); \
\
template <class U > \
static NonStaticFunctionType Test( TestNonStaticConst<&U::Identifier>*, int ); \
\
template <class U> \
static StaticFunctionType Test( TestStatic<&U::Identifier>*, int ); \
\
template <class U> \
static NotFoundType Test( ... ); \
public : \
static const int check = NotFound + (sizeof(Test<T>(0, 0)) - sizeof(NotFoundType));\
};\
}}} //namespace boost::intrusive::function_detector {
#define BOOST_INTRUSIVE_DETECT_FUNCTION(Class, InstantiationKey, ReturnType, Identifier, Params) \
::boost::intrusive::function_detector::DetectMember_##InstantiationKey_##Identifier< Class,\
ReturnType (Class::*)Params,\
ReturnType (Class::*)Params const,\
ReturnType (*)Params \
>::check
#endif //@ifndef BOOST_INTRUSIVE_DETAIL_FUNCTION_DETECTOR_HPP

View file

@ -0,0 +1,217 @@
/////////////////////////////////////////////////////////////////////////////
//
// (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/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_GENERIC_HOOK_HPP
#define BOOST_INTRUSIVE_GENERIC_HOOK_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/intrusive/link_mode.hpp>
#include <boost/intrusive/detail/mpl.hpp>
#include <boost/intrusive/detail/assert.hpp>
#include <boost/intrusive/detail/node_holder.hpp>
#include <boost/static_assert.hpp>
namespace boost {
namespace intrusive {
/// @cond
namespace detail {
template <link_mode_type LinkMode>
struct link_dispatch
{};
template<class Hook>
void destructor_impl(Hook &hook, detail::link_dispatch<safe_link>)
{ //If this assertion raises, you might have destroyed an object
//while it was still inserted in a container that is alive.
//If so, remove the object from the container before destroying it.
(void)hook; BOOST_INTRUSIVE_SAFE_HOOK_DESTRUCTOR_ASSERT(!hook.is_linked());
}
template<class Hook>
void destructor_impl(Hook &hook, detail::link_dispatch<auto_unlink>)
{ hook.unlink(); }
template<class Hook>
void destructor_impl(Hook &, detail::link_dispatch<normal_link>)
{}
} //namespace detail {
enum base_hook_type
{ NoBaseHookId
, ListBaseHookId
, SlistBaseHookId
, RbTreeBaseHookId
, HashBaseHookId
, AvlTreeBaseHookId
, BsTreeBaseHookId
, TreapTreeBaseHookId
, AnyBaseHookId
};
template <class HookTags, unsigned int>
struct hook_tags_definer{};
template <class HookTags>
struct hook_tags_definer<HookTags, ListBaseHookId>
{ typedef HookTags default_list_hook; };
template <class HookTags>
struct hook_tags_definer<HookTags, SlistBaseHookId>
{ typedef HookTags default_slist_hook; };
template <class HookTags>
struct hook_tags_definer<HookTags, RbTreeBaseHookId>
{ typedef HookTags default_rbtree_hook; };
template <class HookTags>
struct hook_tags_definer<HookTags, HashBaseHookId>
{ typedef HookTags default_hashtable_hook; };
template <class HookTags>
struct hook_tags_definer<HookTags, AvlTreeBaseHookId>
{ typedef HookTags default_avltree_hook; };
template <class HookTags>
struct hook_tags_definer<HookTags, BsTreeBaseHookId>
{ typedef HookTags default_bstree_hook; };
template <class HookTags>
struct hook_tags_definer<HookTags, AnyBaseHookId>
{ typedef HookTags default_any_hook; };
template
< class NodeTraits
, class Tag
, link_mode_type LinkMode
, base_hook_type BaseHookType
>
struct hooktags_impl
{
static const link_mode_type link_mode = LinkMode;
typedef Tag tag;
typedef NodeTraits node_traits;
static const bool is_base_hook = !detail::is_same<Tag, member_tag>::value;
static const bool safemode_or_autounlink = is_safe_autounlink<link_mode>::value;
static const unsigned int type = BaseHookType;
};
/// @endcond
template
< class NodeAlgorithms
, class Tag
, link_mode_type LinkMode
, base_hook_type BaseHookType
>
class generic_hook
/// @cond
//If the hook is a base hook, derive generic hook from node_holder
//so that a unique base class is created to convert from the node
//to the type. This mechanism will be used by bhtraits.
//
//If the hook is a member hook, generic hook will directly derive
//from the hook.
: public detail::if_c
< detail::is_same<Tag, member_tag>::value
, typename NodeAlgorithms::node
, node_holder<typename NodeAlgorithms::node, Tag, BaseHookType>
>::type
//If this is the a default-tagged base hook derive from a class that
//will define an special internal typedef. Containers will be able to detect this
//special typedef and obtain generic_hook's internal types in order to deduce
//value_traits for this hook.
, public hook_tags_definer
< generic_hook<NodeAlgorithms, Tag, LinkMode, BaseHookType>
, detail::is_same<Tag, default_tag>::value*BaseHookType>
/// @endcond
{
/// @cond
typedef NodeAlgorithms node_algorithms;
typedef typename node_algorithms::node node;
typedef typename node_algorithms::node_ptr node_ptr;
typedef typename node_algorithms::const_node_ptr const_node_ptr;
public:
typedef hooktags_impl
< typename NodeAlgorithms::node_traits
, Tag, LinkMode, BaseHookType> hooktags;
node_ptr this_ptr()
{ return pointer_traits<node_ptr>::pointer_to(static_cast<node&>(*this)); }
const_node_ptr this_ptr() const
{ return pointer_traits<const_node_ptr>::pointer_to(static_cast<const node&>(*this)); }
public:
/// @endcond
generic_hook()
{
if(hooktags::safemode_or_autounlink){
node_algorithms::init(this->this_ptr());
}
}
generic_hook(const generic_hook& )
{
if(hooktags::safemode_or_autounlink){
node_algorithms::init(this->this_ptr());
}
}
generic_hook& operator=(const generic_hook& )
{ return *this; }
~generic_hook()
{
destructor_impl
(*this, detail::link_dispatch<hooktags::link_mode>());
}
void swap_nodes(generic_hook &other)
{
node_algorithms::swap_nodes
(this->this_ptr(), other.this_ptr());
}
bool is_linked() const
{
//is_linked() can be only used in safe-mode or auto-unlink
BOOST_STATIC_ASSERT(( hooktags::safemode_or_autounlink ));
return !node_algorithms::unique(this->this_ptr());
}
void unlink()
{
BOOST_STATIC_ASSERT(( (int)hooktags::link_mode == (int)auto_unlink ));
node_ptr n(this->this_ptr());
if(!node_algorithms::inited(n)){
node_algorithms::unlink(n);
node_algorithms::init(n);
}
}
};
} //namespace intrusive
} //namespace boost
#endif //BOOST_INTRUSIVE_GENERIC_HOOK_HPP

View file

@ -0,0 +1,218 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2014-2014
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_DETAIL_GET_VALUE_TRAITS_HPP
#define BOOST_INTRUSIVE_DETAIL_GET_VALUE_TRAITS_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/intrusive/detail/config_begin.hpp>
#include <boost/intrusive/detail/mpl.hpp>
#include <boost/intrusive/detail/hook_traits.hpp>
namespace boost {
namespace intrusive {
#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
template<class SupposedValueTraits>
struct is_default_hook_tag
{ static const bool value = false; };
namespace detail{
template <class T, class BaseHook>
struct concrete_hook_base_value_traits
{
typedef typename BaseHook::hooktags tags;
typedef bhtraits
< T
, typename tags::node_traits
, tags::link_mode
, typename tags::tag
, tags::type> type;
};
template <class BaseHook>
struct concrete_hook_base_value_traits<void, BaseHook>
{
typedef typename BaseHook::hooktags type;
};
template <class T, class AnyToSomeHook_ProtoValueTraits>
struct any_hook_base_value_traits
{
//AnyToSomeHook value_traits derive from a generic_hook
//The generic_hook is configured with any_node_traits
//and AnyToSomeHook::value_traits with the correct
//node traits for the container, so use node_traits
//from AnyToSomeHook_ProtoValueTraits and the rest of
//elements from the hooktags member of the generic_hook
typedef typename AnyToSomeHook_ProtoValueTraits::basic_hook_t basic_hook_t;
typedef typename pointer_rebind
< typename basic_hook_t::hooktags::node_traits::node_ptr
, void>::type void_pointer;
typedef typename AnyToSomeHook_ProtoValueTraits::template
node_traits_from_voidptr<void_pointer>::type node_traits;
typedef bhtraits
< T
, node_traits
, basic_hook_t::hooktags::link_mode
, typename basic_hook_t::hooktags::tag
, basic_hook_t::hooktags::type
> type;
};
template <class AnyToSomeHook_ProtoValueTraits>
struct any_hook_base_value_traits<void, AnyToSomeHook_ProtoValueTraits>
{
typedef typename AnyToSomeHook_ProtoValueTraits::basic_hook_t basic_hook_t;
typedef typename pointer_rebind
< typename basic_hook_t::hooktags::node_traits::node_ptr
, void>::type void_pointer;
struct type
{
typedef typename AnyToSomeHook_ProtoValueTraits::template
node_traits_from_voidptr<void_pointer>::type node_traits;
};
};
template<class MemberHook>
struct get_member_value_traits
{
typedef typename MemberHook::member_value_traits type;
};
BOOST_INTRUSIVE_INTERNAL_STATIC_BOOL_IS_TRUE(internal_any_hook, is_any_hook)
BOOST_INTRUSIVE_INTERNAL_STATIC_BOOL_IS_TRUE(internal_base_hook, hooktags::is_base_hook)
template <class T>
struct internal_member_value_traits
{
template <class U> static one test(...);
template <class U> static two test(typename U::member_value_traits* = 0);
static const bool value = sizeof(test<T>(0)) == sizeof(two);
};
template<class SupposedValueTraits, class T, bool = is_default_hook_tag<SupposedValueTraits>::value>
struct supposed_value_traits;
template<class T, class BaseHook, bool = internal_any_hook_bool_is_true<BaseHook>::value>
struct get_base_value_traits;
template<class SupposedValueTraits, class T, bool = internal_base_hook_bool_is_true<SupposedValueTraits>::value>
struct supposed_base_value_traits;
template<class SupposedValueTraits, bool = internal_member_value_traits<SupposedValueTraits>::value>
struct supposed_member_value_traits;
template<class SupposedValueTraits, bool = internal_any_hook_bool_is_true<SupposedValueTraits>::value>
struct any_or_concrete_value_traits;
//Base any hook
template<class T, class BaseHook>
struct get_base_value_traits<T, BaseHook, true>
: any_hook_base_value_traits<T, BaseHook>
{};
//Non-any base hook
template<class T, class BaseHook>
struct get_base_value_traits<T, BaseHook, false>
: concrete_hook_base_value_traits<T, BaseHook>
{};
//...It's a default hook
template<class SupposedValueTraits, class T>
struct supposed_value_traits<SupposedValueTraits, T, true>
{ typedef typename SupposedValueTraits::template apply<T>::type type; };
//...Not a default hook
template<class SupposedValueTraits, class T>
struct supposed_value_traits<SupposedValueTraits, T, false>
{ typedef SupposedValueTraits type; };
//...It's a base hook
template<class BaseHook, class T>
struct supposed_base_value_traits<BaseHook, T, true>
: get_base_value_traits<T, BaseHook>
{};
//...Not a base hook, try if it's a member or value_traits
template<class SupposedValueTraits, class T>
struct supposed_base_value_traits<SupposedValueTraits, T, false>
: supposed_member_value_traits<SupposedValueTraits>
{};
//...It's a member hook
template<class MemberHook>
struct supposed_member_value_traits<MemberHook, true>
: get_member_value_traits<MemberHook>
{};
//...Not a member hook
template<class SupposedValueTraits>
struct supposed_member_value_traits<SupposedValueTraits, false>
: any_or_concrete_value_traits<SupposedValueTraits>
{};
template<class AnyToSomeHook_ProtoValueTraits>
struct any_or_concrete_value_traits<AnyToSomeHook_ProtoValueTraits, true>
{
//A hook node (non-base, e.g.: member or other value traits
typedef typename AnyToSomeHook_ProtoValueTraits::basic_hook_t basic_hook_t;
typedef typename pointer_rebind
<typename basic_hook_t::node_ptr, void>::type void_pointer;
typedef typename AnyToSomeHook_ProtoValueTraits::template
node_traits_from_voidptr<void_pointer>::type any_node_traits;
struct type : basic_hook_t
{
typedef any_node_traits node_traits;
};
};
template<class SupposedValueTraits>
struct any_or_concrete_value_traits<SupposedValueTraits, false>
{
typedef SupposedValueTraits type;
};
////////////////////////////////////////
// get_value_traits / get_node_traits
////////////////////////////////////////
template<class T, class SupposedValueTraits>
struct get_value_traits
: supposed_base_value_traits<typename supposed_value_traits<SupposedValueTraits, T>::type, T>
{};
template<class SupposedValueTraits>
struct get_node_traits
{
typedef typename get_value_traits<void, SupposedValueTraits>::type::node_traits type;
};
} //namespace detail{
#endif //BOOST_INTRUSIVE_DOXYGEN_INVOKED
} //namespace intrusive {
} //namespace boost {
#include <boost/intrusive/detail/config_end.hpp>
#endif //#ifndef BOOST_INTRUSIVE_DETAIL_GET_VALUE_TRAITS_HPP

View file

@ -0,0 +1,372 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2011-2014. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
//////////////////////////////////////////////////////////////////////////////
// sample.h
#if !defined(BOOST_PP_IS_ITERATING)
#ifndef BOOST_INTRUSIVE_DETAIL_HAS_MEMBER_FUNCTION_CALLABLE_WITH_DETAILS_INCLUDED
#define BOOST_INTRUSIVE_DETAIL_HAS_MEMBER_FUNCTION_CALLABLE_WITH_DETAILS_INCLUDED
#include <boost/intrusive/detail/preprocessor.hpp>
#include <boost/intrusive/detail/mpl.hpp>
#include <boost/move/utility_core.hpp>
//Mark that we don't support 0 arg calls due to compiler ICE in GCC 3.4/4.0/4.1 and
//wrong SFINAE for GCC 4.2/4.3
#if defined(__GNUC__) && !defined(__clang__) && ((__GNUC__*100 + __GNUC_MINOR__*10) >= 340) && ((__GNUC__*100 + __GNUC_MINOR__*10) <= 430)
#define BOOST_INTRUSIVE_DETAIL_HAS_MEMBER_FUNCTION_CALLABLE_WITH_0_ARGS_UNSUPPORTED
#elif defined(BOOST_INTEL) && (BOOST_INTEL < 1200 )
#define BOOST_INTRUSIVE_DETAIL_HAS_MEMBER_FUNCTION_CALLABLE_WITH_0_ARGS_UNSUPPORTED
#endif
namespace boost_intrusive_has_member_function_callable_with {
struct dont_care
{
dont_care(...);
};
template<class T>
struct make_dontcare
{
typedef boost_intrusive_has_member_function_callable_with::dont_care type;
};
struct private_type
{
static private_type p;
private_type const &operator,(int) const;
};
typedef char yes_type; // sizeof(yes_type) == 1
struct no_type{ char dummy[2]; }; // sizeof(no_type) == 2
template<typename T>
no_type is_private_type(T const &);
yes_type is_private_type(private_type const &);
} //boost_intrusive_has_member_function_callable_with
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_SINGLE_ITERATION
#endif
#endif //BOOST_INTRUSIVE_DETAIL_HAS_MEMBER_FUNCTION_CALLABLE_WITH_DETAILS_INCLUDED
#else //!BOOST_PP_IS_ITERATING
#ifndef BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME
#error "BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME not defined!"
#endif
#ifndef BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN
#error "BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN not defined!"
#endif
#ifndef BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END
#error "BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END not defined!"
#endif
#if BOOST_PP_ITERATION_START() > BOOST_PP_ITERATION_FINISH()
#error "BOOST_PP_ITERATION_START() must be <= BOOST_PP_ITERATION_FINISH()"
#endif
#if BOOST_PP_ITERATION() == BOOST_PP_ITERATION_START()
BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN
template <typename Type>
class BOOST_PP_CAT(has_member_function_named_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)
{
struct BaseMixin
{
void BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME();
};
struct Base : public ::boost::intrusive::detail::remove_cv<Type>::type, public BaseMixin { Base(); };
template <typename T, T t> class Helper{};
template <typename U>
static boost_intrusive_has_member_function_callable_with::no_type deduce
(U*, Helper<void (BaseMixin::*)(), &U::BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME>* = 0);
static boost_intrusive_has_member_function_callable_with::yes_type deduce(...);
public:
static const bool value =
sizeof(boost_intrusive_has_member_function_callable_with::yes_type) == sizeof(deduce((Base*)(0)));
};
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template<typename Fun, bool HasFunc
BOOST_PP_ENUM_TRAILING(BOOST_PP_ITERATION_FINISH(), BOOST_INTRUSIVE_PP_TEMPLATE_PARAM_VOID_DEFAULT, _)>
struct BOOST_PP_CAT(BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME), _impl);
//!
template<typename Fun BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION_FINISH(), class P)>
struct BOOST_PP_CAT(BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME), _impl)
<Fun, false BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION_FINISH(), P)>
{
static const bool value = false;
};
//!
#else //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template<typename Fun, bool HasFunc, class ...Args>
struct BOOST_PP_CAT(BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME),_impl);
template<typename Fun, class ...Args>
struct BOOST_PP_CAT(BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME),_impl)
<Fun, false, Args...>
{
static const bool value = false;
};
#ifdef BOOST_NO_CXX11_DECLTYPE
//Special case for 0 args
template< class F
, std::size_t N =
sizeof((boost::move_detail::declval<F>().
BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME (), 0))>
struct BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)
{
boost_intrusive_has_member_function_callable_with::yes_type dummy;
BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)(int);
};
//For buggy compilers like MSVC 7.1+ ((F*)0)->func() does not
//SFINAE-out the zeroarg_checker_ instantiation but sizeof yields to 0.
template<class F>
struct BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)<F, 0>
{
boost_intrusive_has_member_function_callable_with::no_type dummy;
BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)(int);
};
#endif //#ifdef BOOST_NO_CXX11_DECLTYPE
template<typename Fun>
struct BOOST_PP_CAT(BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME),_impl)
<Fun, true>
{
#ifndef BOOST_NO_CXX11_DECLTYPE
template<class U, class V = decltype(boost::move_detail::declval<U>().BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME()) >
static boost_intrusive_has_member_function_callable_with::yes_type Test(U*);
#else
template<class U>
static BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)
<U> Test(BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)<U>*);
#endif
template <class U>
static boost_intrusive_has_member_function_callable_with::no_type Test(...);
static const bool value = sizeof(Test< Fun >(0))
== sizeof(boost_intrusive_has_member_function_callable_with::yes_type);
};
template<typename Fun, class ...Args>
struct BOOST_PP_CAT( BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME), _impl)
<Fun, true , Args...>
{
template<class ...DontCares>
struct FunWrapTmpl : Fun
{
FunWrapTmpl();
using Fun::BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME;
boost_intrusive_has_member_function_callable_with::private_type
BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME
( DontCares...) const;
};
typedef FunWrapTmpl<typename boost_intrusive_has_member_function_callable_with::make_dontcare<Args>::type...> FunWrap;
static bool const value = (sizeof(boost_intrusive_has_member_function_callable_with::no_type) ==
sizeof(boost_intrusive_has_member_function_callable_with::is_private_type
( (::boost::move_detail::declval< FunWrap >().
BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME
( ::boost::move_detail::declval<Args>()... ), 0) )
)
);
};
template<typename Fun, class ...Args>
struct BOOST_PP_CAT( has_member_function_callable_with_
, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)
: public BOOST_PP_CAT( BOOST_PP_CAT(has_member_function_callable_with_
, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME),_impl)
< Fun
, BOOST_PP_CAT( has_member_function_named_
, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME )<Fun>::value
, Args... >
{};
#endif //defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END
#endif //BOOST_PP_ITERATION() == BOOST_PP_ITERATION_START()
#if BOOST_PP_ITERATION() == 0
BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#if !defined(_MSC_VER) || (_MSC_VER < 1600)
#if defined(BOOST_INTRUSIVE_DETAIL_HAS_MEMBER_FUNCTION_CALLABLE_WITH_0_ARGS_UNSUPPORTED)
template<typename Fun>
struct BOOST_PP_CAT(BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME),_impl)
<Fun, true BOOST_PP_ENUM_TRAILING(BOOST_PP_SUB(BOOST_PP_ITERATION_FINISH(), BOOST_PP_ITERATION()), BOOST_INTRUSIVE_PP_IDENTITY, void)>
{
//Mark that we don't support 0 arg calls due to compiler ICE in GCC 3.4/4.0/4.1 and
//wrong SFINAE for GCC 4.2/4.3
static const bool value = true;
};
#else //defined(BOOST_INTRUSIVE_DETAIL_HAS_MEMBER_FUNCTION_CALLABLE_WITH_0_ARGS_UNSUPPORTED)
//Special case for 0 args
template< class F
, std::size_t N =
sizeof((boost::move_detail::declval<F>().
BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME (), 0))>
struct BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)
{
boost_intrusive_has_member_function_callable_with::yes_type dummy;
BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)(int);
};
//For buggy compilers like MSVC 7.1+ ((F*)0)->func() does not
//SFINAE-out the zeroarg_checker_ instantiation but sizeof yields to 0.
template<class F>
struct BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)<F, 0>
{
boost_intrusive_has_member_function_callable_with::no_type dummy;
BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)(int);
};
template<typename Fun>
struct BOOST_PP_CAT(BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME),_impl)
<Fun, true BOOST_PP_ENUM_TRAILING(BOOST_PP_SUB(BOOST_PP_ITERATION_FINISH(), BOOST_PP_ITERATION()), BOOST_INTRUSIVE_PP_IDENTITY, void)>
{
template<class U>
static BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)<U>
Test(BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)<U>*);
template <class U>
static boost_intrusive_has_member_function_callable_with::no_type Test(...);
static const bool value = sizeof(Test< Fun >(0))
== sizeof(boost_intrusive_has_member_function_callable_with::yes_type);
};
#endif //defined(BOOST_INTRUSIVE_DETAIL_HAS_MEMBER_FUNCTION_CALLABLE_WITH_0_ARGS_UNSUPPORTED)
#else //#if !defined(_MSC_VER) || (_MSC_VER < 1600)
template<typename Fun>
struct BOOST_PP_CAT(BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME),_impl)
<Fun, true BOOST_PP_ENUM_TRAILING(BOOST_PP_SUB(BOOST_PP_ITERATION_FINISH(), BOOST_PP_ITERATION()), BOOST_INTRUSIVE_PP_IDENTITY, void)>
{
template<class U>
static decltype( boost::move_detail::declval<U>().BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME()
, boost_intrusive_has_member_function_callable_with::yes_type())
Test(U*);
template<class U>
static boost_intrusive_has_member_function_callable_with::no_type Test(...);
static const bool value = sizeof(Test<Fun>(0))
== sizeof(boost_intrusive_has_member_function_callable_with::yes_type);
};
#endif //#if !defined(_MSC_VER) || (_MSC_VER < 1600)
#else //#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#endif //#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END
#else //BOOST_PP_ITERATION() == 0
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN
template<typename Fun BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), class P)>
struct BOOST_PP_CAT( BOOST_PP_CAT(has_member_function_callable_with_
, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME),_impl)
<Fun, true
BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), P)
BOOST_PP_ENUM_TRAILING( BOOST_PP_SUB(BOOST_PP_ITERATION_FINISH(), BOOST_PP_ITERATION())
, BOOST_INTRUSIVE_PP_IDENTITY
, void)>
{
struct FunWrap : Fun
{
FunWrap();
using Fun::BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME;
boost_intrusive_has_member_function_callable_with::private_type
BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME
( BOOST_PP_ENUM(BOOST_PP_ITERATION()
, BOOST_INTRUSIVE_PP_IDENTITY
, boost_intrusive_has_member_function_callable_with::dont_care)) const;
};
static bool const value =
(sizeof(boost_intrusive_has_member_function_callable_with::no_type) ==
sizeof(boost_intrusive_has_member_function_callable_with::is_private_type
( (boost::move_detail::declval<FunWrap>().
BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME
( BOOST_PP_ENUM( BOOST_PP_ITERATION(), BOOST_INTRUSIVE_PP_DECLVAL, _) ), 0
)
)
)
);
};
BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END
#endif //#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#endif //BOOST_PP_ITERATION() == 0
#if BOOST_PP_ITERATION() == BOOST_PP_ITERATION_FINISH()
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN
template<typename Fun
BOOST_PP_ENUM_TRAILING(BOOST_PP_ITERATION_FINISH(), BOOST_INTRUSIVE_PP_TEMPLATE_PARAM_VOID_DEFAULT, _)>
struct BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)
: public BOOST_PP_CAT(BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME), _impl)
<Fun, BOOST_PP_CAT(has_member_function_named_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)<Fun>::value
BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION_FINISH(), P) >
{};
BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END
#endif //#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#undef BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME
#undef BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN
#undef BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END
#endif //#if BOOST_PP_ITERATION() == BOOST_PP_ITERATION_FINISH()
#endif //!BOOST_PP_IS_ITERATING

View file

@ -0,0 +1,287 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2007-2014
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_HASHTABLE_NODE_HPP
#define BOOST_INTRUSIVE_HASHTABLE_NODE_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/intrusive/detail/assert.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/intrusive/detail/mpl.hpp>
#include <boost/intrusive/trivial_value_traits.hpp>
#include <boost/intrusive/slist.hpp> //make_slist
#include <cstddef>
#include <climits>
#include <boost/move/core.hpp>
namespace boost {
namespace intrusive {
namespace detail {
template <class Slist>
struct bucket_impl : public Slist
{
typedef Slist slist_type;
bucket_impl()
{}
bucket_impl(const bucket_impl &)
{}
~bucket_impl()
{
//This bucket is still being used!
BOOST_INTRUSIVE_INVARIANT_ASSERT(Slist::empty());
}
bucket_impl &operator=(const bucket_impl&)
{
//This bucket is still in use!
BOOST_INTRUSIVE_INVARIANT_ASSERT(Slist::empty());
//Slist::clear();
return *this;
}
};
template<class Slist>
struct bucket_traits_impl
{
private:
BOOST_COPYABLE_AND_MOVABLE(bucket_traits_impl)
public:
/// @cond
typedef typename pointer_traits
<typename Slist::pointer>::template rebind_pointer
< bucket_impl<Slist> >::type bucket_ptr;
typedef Slist slist;
typedef typename Slist::size_type size_type;
/// @endcond
bucket_traits_impl(bucket_ptr buckets, size_type len)
: buckets_(buckets), buckets_len_(len)
{}
bucket_traits_impl(const bucket_traits_impl &x)
: buckets_(x.buckets_), buckets_len_(x.buckets_len_)
{}
bucket_traits_impl(BOOST_RV_REF(bucket_traits_impl) x)
: buckets_(x.buckets_), buckets_len_(x.buckets_len_)
{ x.buckets_ = bucket_ptr(); x.buckets_len_ = 0; }
bucket_traits_impl& operator=(BOOST_RV_REF(bucket_traits_impl) x)
{
buckets_ = x.buckets_; buckets_len_ = x.buckets_len_;
x.buckets_ = bucket_ptr(); x.buckets_len_ = 0; return *this;
}
bucket_traits_impl& operator=(BOOST_COPY_ASSIGN_REF(bucket_traits_impl) x)
{
buckets_ = x.buckets_; buckets_len_ = x.buckets_len_; return *this;
}
const bucket_ptr &bucket_begin() const
{ return buckets_; }
size_type bucket_count() const
{ return buckets_len_; }
private:
bucket_ptr buckets_;
size_type buckets_len_;
};
template <class NodeTraits>
struct hash_reduced_slist_node_traits
{
template <class U> static detail::one test(...);
template <class U> static detail::two test(typename U::reduced_slist_node_traits* = 0);
static const bool value = sizeof(test<NodeTraits>(0)) == sizeof(detail::two);
};
template <class NodeTraits>
struct apply_reduced_slist_node_traits
{
typedef typename NodeTraits::reduced_slist_node_traits type;
};
template <class NodeTraits>
struct reduced_slist_node_traits
{
typedef typename detail::eval_if_c
< hash_reduced_slist_node_traits<NodeTraits>::value
, apply_reduced_slist_node_traits<NodeTraits>
, detail::identity<NodeTraits>
>::type type;
};
template<class NodeTraits>
struct get_slist_impl
{
typedef trivial_value_traits<NodeTraits, normal_link> trivial_traits;
//Reducing symbol length
struct type : make_slist
< typename NodeTraits::node
, boost::intrusive::value_traits<trivial_traits>
, boost::intrusive::constant_time_size<false>
, boost::intrusive::size_type<std::size_t>
>::type
{};
};
} //namespace detail {
template<class BucketValueTraits, bool IsConst>
class hashtable_iterator
{
typedef boost::intrusive::iterator
< std::forward_iterator_tag
, typename BucketValueTraits::value_traits::value_type
, typename pointer_traits<typename BucketValueTraits::value_traits::value_type*>::difference_type
, typename detail::add_const_if_c
<typename BucketValueTraits::value_traits::value_type, IsConst>::type *
, typename detail::add_const_if_c
<typename BucketValueTraits::value_traits::value_type, IsConst>::type &
> iterator_traits;
typedef typename BucketValueTraits::value_traits value_traits;
typedef typename BucketValueTraits::bucket_traits bucket_traits;
typedef typename value_traits::node_traits node_traits;
typedef typename detail::get_slist_impl
<typename detail::reduced_slist_node_traits
<typename value_traits::node_traits>::type
>::type slist_impl;
typedef typename slist_impl::iterator siterator;
typedef typename slist_impl::const_iterator const_siterator;
typedef detail::bucket_impl<slist_impl> bucket_type;
typedef typename pointer_traits
<typename value_traits::pointer>::template rebind_pointer
< const BucketValueTraits >::type const_bucketvaltraits_ptr;
typedef typename slist_impl::size_type size_type;
static typename node_traits::node_ptr downcast_bucket(typename bucket_type::node_ptr p)
{
return pointer_traits<typename node_traits::node_ptr>::
pointer_to(static_cast<typename node_traits::node&>(*p));
}
public:
typedef typename iterator_traits::difference_type difference_type;
typedef typename iterator_traits::value_type value_type;
typedef typename iterator_traits::pointer pointer;
typedef typename iterator_traits::reference reference;
typedef typename iterator_traits::iterator_category iterator_category;
hashtable_iterator ()
: slist_it_() //Value initialization to achieve "null iterators" (N3644)
{}
explicit hashtable_iterator(siterator ptr, const BucketValueTraits *cont)
: slist_it_ (ptr), traitsptr_ (cont ? pointer_traits<const_bucketvaltraits_ptr>::pointer_to(*cont) : const_bucketvaltraits_ptr() )
{}
hashtable_iterator(const hashtable_iterator<BucketValueTraits, false> &other)
: slist_it_(other.slist_it()), traitsptr_(other.get_bucket_value_traits())
{}
const siterator &slist_it() const
{ return slist_it_; }
hashtable_iterator<BucketValueTraits, false> unconst() const
{ return hashtable_iterator<BucketValueTraits, false>(this->slist_it(), this->get_bucket_value_traits()); }
public:
hashtable_iterator& operator++()
{ this->increment(); return *this; }
hashtable_iterator operator++(int)
{
hashtable_iterator result (*this);
this->increment();
return result;
}
friend bool operator== (const hashtable_iterator& i, const hashtable_iterator& i2)
{ return i.slist_it_ == i2.slist_it_; }
friend bool operator!= (const hashtable_iterator& i, const hashtable_iterator& i2)
{ return !(i == i2); }
reference operator*() const
{ return *this->operator ->(); }
pointer operator->() const
{
return boost::intrusive::detail::to_raw_pointer(this->priv_value_traits().to_value_ptr
(downcast_bucket(slist_it_.pointed_node())));
}
const const_bucketvaltraits_ptr &get_bucket_value_traits() const
{ return traitsptr_; }
const value_traits &priv_value_traits() const
{ return traitsptr_->priv_value_traits(); }
const bucket_traits &priv_bucket_traits() const
{ return traitsptr_->priv_bucket_traits(); }
private:
void increment()
{
const bucket_traits &rbuck_traits = this->priv_bucket_traits();
bucket_type* const buckets = boost::intrusive::detail::to_raw_pointer(rbuck_traits.bucket_begin());
const size_type buckets_len = rbuck_traits.bucket_count();
++slist_it_;
const typename slist_impl::node_ptr n = slist_it_.pointed_node();
const siterator first_bucket_bbegin = buckets->end();
if(first_bucket_bbegin.pointed_node() <= n && n <= buckets[buckets_len-1].cend().pointed_node()){
//If one-past the node is inside the bucket then look for the next non-empty bucket
//1. get the bucket_impl from the iterator
const bucket_type &b = static_cast<const bucket_type&>
(bucket_type::slist_type::container_from_end_iterator(slist_it_));
//2. Now just calculate the index b has in the bucket array
size_type n_bucket = static_cast<size_type>(&b - buckets);
//3. Iterate until a non-empty bucket is found
do{
if (++n_bucket >= buckets_len){ //bucket overflow, return end() iterator
slist_it_ = buckets->before_begin();
return;
}
}
while (buckets[n_bucket].empty());
slist_it_ = buckets[n_bucket].begin();
}
else{
//++slist_it_ yield to a valid object
}
}
siterator slist_it_;
const_bucketvaltraits_ptr traitsptr_;
};
} //namespace intrusive {
} //namespace boost {
#endif

View file

@ -0,0 +1,182 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2006-2014
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_DETAIL_HOOK_TRAITS_HPP
#define BOOST_INTRUSIVE_DETAIL_HOOK_TRAITS_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/intrusive/detail/parent_from_member.hpp>
#include <boost/intrusive/link_mode.hpp>
#include <boost/intrusive/detail/mpl.hpp>
#include <boost/intrusive/detail/to_raw_pointer.hpp>
#include <boost/intrusive/detail/node_holder.hpp>
namespace boost {
namespace intrusive {
template<class T, class NodePtr, class Tag, unsigned int Type>
struct bhtraits_base
{
public:
typedef NodePtr node_ptr;
typedef typename pointer_traits<node_ptr>::element_type node;
typedef node_holder<node, Tag, Type> node_holder_type;
typedef T value_type;
typedef typename pointer_traits<node_ptr>::
template rebind_pointer<const node>::type const_node_ptr;
typedef typename pointer_traits<node_ptr>::
template rebind_pointer<T>::type pointer;
typedef typename pointer_traits<node_ptr>::
template rebind_pointer<const T>::type const_pointer;
//typedef typename pointer_traits<pointer>::reference reference;
//typedef typename pointer_traits<const_pointer>::reference const_reference;
typedef T & reference;
typedef const T & const_reference;
typedef node_holder_type & node_holder_reference;
typedef const node_holder_type & const_node_holder_reference;
typedef node& node_reference;
typedef const node & const_node_reference;
static pointer to_value_ptr(const node_ptr & n)
{
return pointer_traits<pointer>::pointer_to
(static_cast<reference>(static_cast<node_holder_reference>(*n)));
}
static const_pointer to_value_ptr(const const_node_ptr & n)
{
return pointer_traits<const_pointer>::pointer_to
(static_cast<const_reference>(static_cast<const_node_holder_reference>(*n)));
}
static node_ptr to_node_ptr(reference value)
{
return pointer_traits<node_ptr>::pointer_to
(static_cast<node_reference>(static_cast<node_holder_reference>(value)));
}
static const_node_ptr to_node_ptr(const_reference value)
{
return pointer_traits<const_node_ptr>::pointer_to
(static_cast<const_node_reference>(static_cast<const_node_holder_reference>(value)));
}
};
template<class T, class NodeTraits, link_mode_type LinkMode, class Tag, unsigned int Type>
struct bhtraits
: public bhtraits_base<T, typename NodeTraits::node_ptr, Tag, Type>
{
static const link_mode_type link_mode = LinkMode;
typedef NodeTraits node_traits;
};
template<class T, class Hook, Hook T::* P>
struct mhtraits
{
public:
typedef Hook hook_type;
typedef typename hook_type::hooktags::node_traits node_traits;
typedef typename node_traits::node node;
typedef T value_type;
typedef typename node_traits::node_ptr node_ptr;
typedef typename node_traits::const_node_ptr const_node_ptr;
typedef typename pointer_traits<node_ptr>::
template rebind_pointer<T>::type pointer;
typedef typename pointer_traits<node_ptr>::
template rebind_pointer<const T>::type const_pointer;
typedef T & reference;
typedef const T & const_reference;
typedef node& node_reference;
typedef const node & const_node_reference;
typedef hook_type& hook_reference;
typedef const hook_type & const_hook_reference;
static const link_mode_type link_mode = Hook::hooktags::link_mode;
static node_ptr to_node_ptr(reference value)
{
return pointer_traits<node_ptr>::pointer_to
(static_cast<node_reference>(static_cast<hook_reference>(value.*P)));
}
static const_node_ptr to_node_ptr(const_reference value)
{
return pointer_traits<const_node_ptr>::pointer_to
(static_cast<const_node_reference>(static_cast<const_hook_reference>(value.*P)));
}
static pointer to_value_ptr(const node_ptr & n)
{
return pointer_traits<pointer>::pointer_to
(*detail::parent_from_member<T, Hook>
(static_cast<Hook*>(boost::intrusive::detail::to_raw_pointer(n)), P));
}
static const_pointer to_value_ptr(const const_node_ptr & n)
{
return pointer_traits<const_pointer>::pointer_to
(*detail::parent_from_member<T, Hook>
(static_cast<const Hook*>(boost::intrusive::detail::to_raw_pointer(n)), P));
}
};
template<class Functor>
struct fhtraits
{
public:
typedef typename Functor::hook_type hook_type;
typedef typename Functor::hook_ptr hook_ptr;
typedef typename Functor::const_hook_ptr const_hook_ptr;
typedef typename hook_type::hooktags::node_traits node_traits;
typedef typename node_traits::node node;
typedef typename Functor::value_type value_type;
typedef typename node_traits::node_ptr node_ptr;
typedef typename node_traits::const_node_ptr const_node_ptr;
typedef typename pointer_traits<node_ptr>::
template rebind_pointer<value_type>::type pointer;
typedef typename pointer_traits<node_ptr>::
template rebind_pointer<const value_type>::type const_pointer;
typedef value_type & reference;
typedef const value_type & const_reference;
static const link_mode_type link_mode = hook_type::hooktags::link_mode;
static node_ptr to_node_ptr(reference value)
{ return static_cast<node*>(boost::intrusive::detail::to_raw_pointer(Functor::to_hook_ptr(value))); }
static const_node_ptr to_node_ptr(const_reference value)
{ return static_cast<const node*>(boost::intrusive::detail::to_raw_pointer(Functor::to_hook_ptr(value))); }
static pointer to_value_ptr(const node_ptr & n)
{ return Functor::to_value_ptr(to_hook_ptr(n)); }
static const_pointer to_value_ptr(const const_node_ptr & n)
{ return Functor::to_value_ptr(to_hook_ptr(n)); }
private:
static hook_ptr to_hook_ptr(const node_ptr & n)
{ return hook_ptr(&*static_cast<hook_type*>(&*n)); }
static const_hook_ptr to_hook_ptr(const const_node_ptr & n)
{ return const_hook_ptr(&*static_cast<const hook_type*>(&*n)); }
};
} //namespace intrusive
} //namespace boost
#endif //BOOST_INTRUSIVE_DETAIL_HOOK_TRAITS_HPP

View file

@ -0,0 +1,227 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2006-2014
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_DETAIL_IITERATOR_HPP
#define BOOST_INTRUSIVE_DETAIL_IITERATOR_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/intrusive/detail/mpl.hpp>
#include <boost/intrusive/detail/is_stateful_value_traits.hpp>
#include <boost/intrusive/detail/std_fwd.hpp>
#include <cstddef>
namespace boost {
namespace intrusive {
template<class Category, class T, class Distance, class Pointer, class Reference>
struct iterator
{
typedef Category iterator_category;
typedef T value_type;
typedef Distance difference_type;
typedef Pointer pointer;
typedef Reference reference;
};
template<class Iterator>
struct iterator_traits
{
typedef typename Iterator::difference_type difference_type;
typedef typename Iterator::value_type value_type;
typedef typename Iterator::pointer pointer;
typedef typename Iterator::reference reference;
typedef typename Iterator::iterator_category iterator_category;
};
template<class T>
struct iterator_traits<T*>
{
typedef std::ptrdiff_t difference_type;
typedef T value_type;
typedef T* pointer;
typedef T& reference;
typedef std::random_access_iterator_tag iterator_category;
};
template<class T>
struct iterator_traits<const T*>
{
typedef std::ptrdiff_t difference_type;
typedef T value_type;
typedef const T* pointer;
typedef const T& reference;
typedef std::random_access_iterator_tag iterator_category;
};
template<class ValueTraits>
struct value_traits_pointers
{
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT
(boost::intrusive::detail::
, ValueTraits, value_traits_ptr
, typename pointer_traits<typename ValueTraits::node_traits::node_ptr>::template
rebind_pointer<ValueTraits>::type) value_traits_ptr;
typedef typename pointer_traits<value_traits_ptr>::template
rebind_pointer<ValueTraits const>::type const_value_traits_ptr;
};
template<class ValueTraits, bool IsConst, class Category>
struct iiterator
{
typedef ValueTraits value_traits;
typedef typename value_traits::node_traits node_traits;
typedef typename node_traits::node node;
typedef typename node_traits::node_ptr node_ptr;
typedef ::boost::intrusive::pointer_traits<node_ptr> nodepointer_traits_t;
typedef typename nodepointer_traits_t::template
rebind_pointer<void>::type void_pointer;
typedef typename ValueTraits::value_type value_type;
typedef typename ValueTraits::pointer nonconst_pointer;
typedef typename ValueTraits::const_pointer yesconst_pointer;
typedef typename ::boost::intrusive::pointer_traits
<nonconst_pointer>::reference nonconst_reference;
typedef typename ::boost::intrusive::pointer_traits
<yesconst_pointer>::reference yesconst_reference;
typedef typename nodepointer_traits_t::difference_type difference_type;
typedef typename detail::if_c
<IsConst, yesconst_pointer, nonconst_pointer>::type pointer;
typedef typename detail::if_c
<IsConst, yesconst_reference, nonconst_reference>::type reference;
typedef iterator
< Category
, value_type
, difference_type
, pointer
, reference
> iterator_traits;
typedef typename value_traits_pointers
<ValueTraits>::value_traits_ptr value_traits_ptr;
typedef typename value_traits_pointers
<ValueTraits>::const_value_traits_ptr const_value_traits_ptr;
static const bool stateful_value_traits =
detail::is_stateful_value_traits<value_traits>::value;
};
template<class NodePtr, class StoredPointer, bool StatefulValueTraits = true>
struct iiterator_members
{
iiterator_members()
: nodeptr_()//Value initialization to achieve "null iterators" (N3644)
{}
iiterator_members(const NodePtr &n_ptr, const StoredPointer &data)
: nodeptr_(n_ptr), ptr_(data)
{}
StoredPointer get_ptr() const
{ return ptr_; }
NodePtr nodeptr_;
StoredPointer ptr_;
};
template<class NodePtr, class StoredPointer>
struct iiterator_members<NodePtr, StoredPointer, false>
{
iiterator_members()
: nodeptr_()//Value initialization to achieve "null iterators" (N3644)
{}
iiterator_members(const NodePtr &n_ptr, const StoredPointer &)
: nodeptr_(n_ptr)
{}
StoredPointer get_ptr() const
{ return StoredPointer(); }
NodePtr nodeptr_;
};
namespace detail {
template<class InputIt, class Distance> inline
void advance_impl(InputIt& it, Distance n, const std::input_iterator_tag&)
{
while(n--)
++it;
}
template<class InputIt, class Distance> inline
void advance_impl(InputIt& it, Distance n, std::forward_iterator_tag &)
{
while(n--)
++it;
}
template<class InputIt, class Distance> inline
void advance_impl(InputIt& it, Distance n, std::bidirectional_iterator_tag &)
{
for (; 0 < n; --n)
++it;
for (; n < 0; ++n)
--it;
}
template<class InputIt, class Distance>
inline void advance_impl(InputIt& it, Distance n, const std::random_access_iterator_tag &)
{
it += n;
}
} //namespace detail
template<class InputIt, class Distance>
inline void iterator_advance(InputIt& it, Distance n)
{ // increment iterator by offset, arbitrary iterators
boost::intrusive::detail::advance_impl(it, n, boost::intrusive::iterator_traits<InputIt>::iterator_category());
}
namespace detail{
template<class InputIt, class Distance, class Category>
inline void distance_impl(InputIt first, InputIt last, Distance& off, const Category &)
{
while(first != last){
++off;
++first;
}
}
template<class InputIt, class Distance> inline
void distance_impl(InputIt first, InputIt last, Distance& off, const std::random_access_iterator_tag&)
{
off += last - first;
}
} //namespace detail
template<class InputIt> inline
typename iterator_traits<InputIt>::difference_type iterator_distance(InputIt first, InputIt last)
{
typename iterator_traits<InputIt>::difference_type off = 0;
boost::intrusive::detail::distance_impl(first, last, off, boost::intrusive::iterator_traits<InputIt>::iterator_category());
return off;
}
} //namespace intrusive
} //namespace boost
#endif //BOOST_INTRUSIVE_DETAIL_IITERATOR_HPP

View file

@ -0,0 +1,77 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2009-2013.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_DETAIL_IS_STATEFUL_VALUE_TRAITS_HPP
#define BOOST_INTRUSIVE_DETAIL_IS_STATEFUL_VALUE_TRAITS_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#if defined(_MSC_VER) && (_MSC_VER <= 1310)
#include <boost/intrusive/detail/mpl.hpp>
namespace boost {
namespace intrusive {
namespace detail {
template<class ValueTraits>
struct is_stateful_value_traits
{
static const bool value = !detail::is_empty_class<ValueTraits>::value;
};
}}}
#else
#include <boost/intrusive/detail/function_detector.hpp>
BOOST_INTRUSIVE_CREATE_FUNCTION_DETECTOR(to_node_ptr, boost_intrusive)
BOOST_INTRUSIVE_CREATE_FUNCTION_DETECTOR(to_value_ptr, boost_intrusive)
namespace boost {
namespace intrusive {
namespace detail {
template<class ValueTraits>
struct is_stateful_value_traits
{
typedef typename ValueTraits::node_ptr node_ptr;
typedef typename ValueTraits::pointer pointer;
typedef typename ValueTraits::value_type value_type;
typedef typename ValueTraits::const_node_ptr const_node_ptr;
typedef typename ValueTraits::const_pointer const_pointer;
typedef ValueTraits value_traits;
static const bool value =
(boost::intrusive::function_detector::NonStaticFunction ==
(BOOST_INTRUSIVE_DETECT_FUNCTION(ValueTraits, boost_intrusive, node_ptr, to_node_ptr, (value_type&) )))
||
(boost::intrusive::function_detector::NonStaticFunction ==
(BOOST_INTRUSIVE_DETECT_FUNCTION(ValueTraits, boost_intrusive, pointer, to_value_ptr, (node_ptr) )))
||
(boost::intrusive::function_detector::NonStaticFunction ==
(BOOST_INTRUSIVE_DETECT_FUNCTION(ValueTraits, boost_intrusive, const_node_ptr, to_node_ptr, (const value_type&) )))
||
(boost::intrusive::function_detector::NonStaticFunction ==
(BOOST_INTRUSIVE_DETECT_FUNCTION(ValueTraits, boost_intrusive, const_pointer, to_value_ptr, (const_node_ptr) )))
;
};
}}}
#endif
#endif //@ifndef BOOST_INTRUSIVE_DETAIL_IS_STATEFUL_VALUE_TRAITS_HPP

View file

@ -0,0 +1,72 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2014-2014
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_DETAIL_KEY_NODEPTR_COMP_HPP
#define BOOST_INTRUSIVE_DETAIL_KEY_NODEPTR_COMP_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/intrusive/detail/mpl.hpp>
#include <boost/intrusive/detail/ebo_functor_holder.hpp>
namespace boost {
namespace intrusive {
namespace detail {
template<class KeyValueCompare, class ValueTraits>
struct key_nodeptr_comp
: private ebo_functor_holder<KeyValueCompare>
{
typedef ValueTraits value_traits;
typedef typename value_traits::value_type value_type;
typedef typename value_traits::node_ptr node_ptr;
typedef typename value_traits::const_node_ptr const_node_ptr;
typedef ebo_functor_holder<KeyValueCompare> base_t;
key_nodeptr_comp(KeyValueCompare kcomp, const ValueTraits *traits)
: base_t(kcomp), traits_(traits)
{}
template<class T>
struct is_node_ptr
{
static const bool value = is_same<T, const_node_ptr>::value || is_same<T, node_ptr>::value;
};
template<class T>
const value_type & key_forward
(const T &node, typename enable_if_c<is_node_ptr<T>::value>::type * = 0) const
{ return *traits_->to_value_ptr(node); }
template<class T>
const T & key_forward(const T &key, typename enable_if_c<!is_node_ptr<T>::value>::type* = 0) const
{ return key; }
template<class KeyType, class KeyType2>
bool operator()(const KeyType &key1, const KeyType2 &key2) const
{ return base_t::get()(this->key_forward(key1), this->key_forward(key2)); }
template<class KeyType>
bool operator()(const KeyType &key1) const
{ return base_t::get()(this->key_forward(key1)); }
const ValueTraits *const traits_;
};
} //namespace detail{
} //namespace intrusive{
} //namespace boost{
#endif //BOOST_INTRUSIVE_DETAIL_KEY_NODEPTR_COMP_HPP

View file

@ -0,0 +1,129 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Olaf Krzikalla 2004-2006.
// (C) Copyright Ion Gaztanaga 2006-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/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_LIST_ITERATOR_HPP
#define BOOST_INTRUSIVE_LIST_ITERATOR_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/intrusive/detail/std_fwd.hpp>
#include <boost/intrusive/detail/iiterator.hpp>
#include <boost/intrusive/detail/mpl.hpp>
namespace boost {
namespace intrusive {
// list_iterator provides some basic functions for a
// node oriented bidirectional iterator:
template<class ValueTraits, bool IsConst>
class list_iterator
{
protected:
typedef iiterator
<ValueTraits, IsConst, std::bidirectional_iterator_tag> types_t;
static const bool stateful_value_traits = types_t::stateful_value_traits;
typedef ValueTraits value_traits;
typedef typename types_t::node_traits node_traits;
typedef typename types_t::node node;
typedef typename types_t::node_ptr node_ptr;
typedef typename types_t::const_value_traits_ptr const_value_traits_ptr;
public:
typedef typename types_t::iterator_traits::difference_type difference_type;
typedef typename types_t::iterator_traits::value_type value_type;
typedef typename types_t::iterator_traits::pointer pointer;
typedef typename types_t::iterator_traits::reference reference;
typedef typename types_t::iterator_traits::iterator_category iterator_category;
list_iterator()
{}
explicit list_iterator(const node_ptr & nodeptr, const const_value_traits_ptr &traits_ptr)
: members_(nodeptr, traits_ptr)
{}
list_iterator(list_iterator<ValueTraits, false> const& other)
: members_(other.pointed_node(), other.get_value_traits())
{}
const node_ptr &pointed_node() const
{ return members_.nodeptr_; }
list_iterator &operator=(const node_ptr &node)
{ members_.nodeptr_ = node; return static_cast<list_iterator&>(*this); }
const_value_traits_ptr get_value_traits() const
{ return members_.get_ptr(); }
public:
list_iterator& operator++()
{
node_ptr p = node_traits::get_next(members_.nodeptr_);
members_.nodeptr_ = p;
return static_cast<list_iterator&> (*this);
}
list_iterator operator++(int)
{
list_iterator result (*this);
members_.nodeptr_ = node_traits::get_next(members_.nodeptr_);
return result;
}
list_iterator& operator--()
{
members_.nodeptr_ = node_traits::get_previous(members_.nodeptr_);
return static_cast<list_iterator&> (*this);
}
list_iterator operator--(int)
{
list_iterator result (*this);
members_.nodeptr_ = node_traits::get_previous(members_.nodeptr_);
return result;
}
friend bool operator== (const list_iterator& l, const list_iterator& r)
{ return l.pointed_node() == r.pointed_node(); }
friend bool operator!= (const list_iterator& l, const list_iterator& r)
{ return !(l == r); }
reference operator*() const
{ return *operator->(); }
pointer operator->() const
{ return this->operator_arrow(detail::bool_<stateful_value_traits>()); }
list_iterator<ValueTraits, false> unconst() const
{ return list_iterator<ValueTraits, false>(this->pointed_node(), this->get_value_traits()); }
private:
pointer operator_arrow(detail::false_) const
{ return ValueTraits::to_value_ptr(members_.nodeptr_); }
pointer operator_arrow(detail::true_) const
{ return this->get_value_traits()->to_value_ptr(members_.nodeptr_); }
iiterator_members<node_ptr, const_value_traits_ptr, stateful_value_traits> members_;
};
} //namespace intrusive
} //namespace boost
#endif //BOOST_INTRUSIVE_LIST_ITERATOR_HPP

View file

@ -0,0 +1,67 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Olaf Krzikalla 2004-2006.
// (C) Copyright Ion Gaztanaga 2006-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/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_LIST_NODE_HPP
#define BOOST_INTRUSIVE_LIST_NODE_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/intrusive/pointer_rebind.hpp>
namespace boost {
namespace intrusive {
// list_node_traits can be used with circular_list_algorithms and supplies
// a list_node holding the pointers needed for a double-linked list
// it is used by list_derived_node and list_member_node
template<class VoidPointer>
struct list_node
{
typedef typename pointer_rebind<VoidPointer, list_node>::type node_ptr;
node_ptr next_;
node_ptr prev_;
};
template<class VoidPointer>
struct list_node_traits
{
typedef list_node<VoidPointer> node;
typedef typename node::node_ptr node_ptr;
typedef typename pointer_rebind<VoidPointer, const node>::type const_node_ptr;
static node_ptr get_previous(const const_node_ptr & n)
{ return n->prev_; }
static node_ptr get_previous(const node_ptr & n)
{ return n->prev_; }
static void set_previous(const node_ptr & n, const node_ptr & prev)
{ n->prev_ = prev; }
static node_ptr get_next(const const_node_ptr & n)
{ return n->next_; }
static node_ptr get_next(const node_ptr & n)
{ return n->next_; }
static void set_next(const node_ptr & n, const node_ptr & next)
{ n->next_ = next; }
};
} //namespace intrusive
} //namespace boost
#endif //BOOST_INTRUSIVE_LIST_NODE_HPP

View file

@ -0,0 +1,271 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2014-2014
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_DETAIL_MATH_HPP
#define BOOST_INTRUSIVE_DETAIL_MATH_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <cstddef>
#include <climits>
namespace boost {
namespace intrusive {
namespace detail {
///////////////////////////
// floor_log2 Dispatcher
////////////////////////////
#if defined(_MSC_VER) && (_MSC_VER >= 1300)
}}} //namespace boost::intrusive::detail
//Use _BitScanReverseXX intrinsics
#if defined(_M_X64) || defined(_M_AMD64) || defined(_M_IA64) //64 bit target
#define BOOST_INTRUSIVE_BSR_INTRINSIC_64_BIT
#endif
#ifndef __INTRIN_H_ // Avoid including any windows system header
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
#if defined(BOOST_INTRUSIVE_BSR_INTRINSIC_64_BIT) //64 bit target
unsigned char _BitScanReverse64(unsigned long *index, unsigned __int64 mask);
#pragma intrinsic(_BitScanReverse64)
#else //32 bit target
unsigned char _BitScanReverse(unsigned long *index, unsigned long mask);
#pragma intrinsic(_BitScanReverse)
#endif
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // __INTRIN_H_
#ifdef BOOST_INTRUSIVE_BSR_INTRINSIC_64_BIT
#define BOOST_INTRUSIVE_BSR_INTRINSIC _BitScanReverse64
#undef BOOST_INTRUSIVE_BSR_INTRINSIC_64_BIT
#else
#define BOOST_INTRUSIVE_BSR_INTRINSIC _BitScanReverse
#endif
namespace boost {
namespace intrusive {
namespace detail {
inline std::size_t floor_log2 (std::size_t x)
{
unsigned long log2;
BOOST_INTRUSIVE_BSR_INTRINSIC( &log2, (unsigned long)x );
return log2;
}
#undef BOOST_INTRUSIVE_BSR_INTRINSIC
#elif defined(__GNUC__) && ((__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) //GCC >=3.4
//Compile-time error in case of missing specialization
template<class Uint>
struct builtin_clz_dispatch;
#if defined(BOOST_HAS_LONG_LONG)
template<>
struct builtin_clz_dispatch<unsigned long long>
{
static unsigned long long call(unsigned long long n)
{ return __builtin_clzll(n); }
};
#endif
template<>
struct builtin_clz_dispatch<unsigned long>
{
static unsigned long call(unsigned long n)
{ return __builtin_clzl(n); }
};
template<>
struct builtin_clz_dispatch<unsigned int>
{
static unsigned int call(unsigned int n)
{ return __builtin_clz(n); }
};
inline std::size_t floor_log2(std::size_t n)
{
return sizeof(std::size_t)*CHAR_BIT - std::size_t(1) - builtin_clz_dispatch<std::size_t>::call(n);
}
#else //Portable methods
////////////////////////////
// Generic method
////////////////////////////
inline std::size_t floor_log2_get_shift(std::size_t n, true_ )//power of two size_t
{ return n >> 1; }
inline std::size_t floor_log2_get_shift(std::size_t n, false_ )//non-power of two size_t
{ return (n >> 1) + ((n & 1u) & (n != 1)); }
template<std::size_t N>
inline std::size_t floor_log2 (std::size_t x, integer<std::size_t, N>)
{
const std::size_t Bits = N;
const bool Size_t_Bits_Power_2= !(Bits & (Bits-1));
std::size_t n = x;
std::size_t log2 = 0;
std::size_t remaining_bits = Bits;
std::size_t shift = floor_log2_get_shift(remaining_bits, bool_<Size_t_Bits_Power_2>());
while(shift){
std::size_t tmp = n >> shift;
if (tmp){
log2 += shift, n = tmp;
}
shift = floor_log2_get_shift(shift, bool_<Size_t_Bits_Power_2>());
}
return log2;
}
////////////////////////////
// DeBruijn method
////////////////////////////
//Taken from:
//http://stackoverflow.com/questions/11376288/fast-computing-of-log2-for-64-bit-integers
//Thanks to Desmond Hume
inline std::size_t floor_log2 (std::size_t v, integer<std::size_t, 32>)
{
static const int MultiplyDeBruijnBitPosition[32] =
{
0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30,
8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31
};
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
return MultiplyDeBruijnBitPosition[(std::size_t)(v * 0x07C4ACDDU) >> 27];
}
inline std::size_t floor_log2 (std::size_t v, integer<std::size_t, 64>)
{
static const std::size_t MultiplyDeBruijnBitPosition[64] = {
63, 0, 58, 1, 59, 47, 53, 2,
60, 39, 48, 27, 54, 33, 42, 3,
61, 51, 37, 40, 49, 18, 28, 20,
55, 30, 34, 11, 43, 14, 22, 4,
62, 57, 46, 52, 38, 26, 32, 41,
50, 36, 17, 19, 29, 10, 13, 21,
56, 45, 25, 31, 35, 16, 9, 12,
44, 24, 15, 8, 23, 7, 6, 5};
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
v |= v >> 32;
return MultiplyDeBruijnBitPosition[((std::size_t)((v - (v >> 1))*0x07EDD5E59A4E28C2ULL)) >> 58];
}
inline std::size_t floor_log2 (std::size_t x)
{
const std::size_t Bits = sizeof(std::size_t)*CHAR_BIT;
return floor_log2(x, integer<std::size_t, Bits>());
}
#endif
//Thanks to Laurent de Soras in
//http://www.flipcode.com/archives/Fast_log_Function.shtml
inline float fast_log2 (float val)
{
union caster_t
{
unsigned x;
float val;
} caster;
caster.val = val;
unsigned x = caster.x;
const int log_2 = int((x >> 23) & 255) - 128;
x &= ~(unsigned(255u) << 23u);
x += unsigned(127) << 23u;
caster.x = x;
val = caster.val;
//1+log2(m), m ranging from 1 to 2
//3rd degree polynomial keeping first derivate continuity.
//For less precision the line can be commented out
val = ((-1.f/3.f) * val + 2.f) * val - (2.f/3.f);
return val + static_cast<float>(log_2);
}
inline std::size_t ceil_log2 (std::size_t x)
{
return static_cast<std::size_t>((x & (x-1)) != 0) + floor_log2(x);
}
template<class SizeType, std::size_t N>
struct numbits_eq
{
static const bool value = sizeof(SizeType)*CHAR_BIT == N;
};
template<class SizeType, class Enabler = void >
struct sqrt2_pow_max;
template <class SizeType>
struct sqrt2_pow_max<SizeType, typename enable_if< numbits_eq<SizeType, 32> >::type>
{
static const SizeType value = 0xb504f334;
static const std::size_t pow = 31;
};
#ifndef BOOST_NO_INT64_T
template <class SizeType>
struct sqrt2_pow_max<SizeType, typename enable_if< numbits_eq<SizeType, 64> >::type>
{
static const SizeType value = 0xb504f333f9de6484ull;
static const std::size_t pow = 63;
};
#endif //BOOST_NO_INT64_T
// Returns floor(pow(sqrt(2), x * 2 + 1)).
// Defined for X from 0 up to the number of bits in size_t minus 1.
inline std::size_t sqrt2_pow_2xplus1 (std::size_t x)
{
const std::size_t value = (std::size_t)sqrt2_pow_max<std::size_t>::value;
const std::size_t pow = (std::size_t)sqrt2_pow_max<std::size_t>::pow;
return (value >> (pow - x)) + 1;
}
} //namespace detail
} //namespace intrusive
} //namespace boost
#endif //BOOST_INTRUSIVE_DETAIL_MATH_HPP

View file

@ -0,0 +1,92 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Pablo Halpern 2009. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2011-2014. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_ALLOCATOR_MEMORY_UTIL_HPP
#define BOOST_INTRUSIVE_ALLOCATOR_MEMORY_UTIL_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/intrusive/detail/workaround.hpp>
#include <boost/intrusive/detail/mpl.hpp>
#include <boost/intrusive/detail/preprocessor.hpp>
#include <boost/preprocessor/iteration/iterate.hpp>
namespace boost {
namespace intrusive {
namespace detail {
template <typename T>
inline T* addressof(T& obj)
{
return static_cast<T*>
(static_cast<void*>
(const_cast<char*>
(&reinterpret_cast<const char&>(obj))
)
);
}
template <typename T>
struct LowPriorityConversion
{
// Convertible from T with user-defined-conversion rank.
LowPriorityConversion(const T&) { }
};
}}} //namespace boost::intrusive::detail
#include <boost/intrusive/detail/has_member_function_callable_with.hpp>
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME pointer_to
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace intrusive { namespace detail {
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
#define BOOST_PP_ITERATION_PARAMS_1 (3, (1, 1, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
#include BOOST_PP_ITERATE()
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME static_cast_from
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace intrusive { namespace detail {
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
#define BOOST_PP_ITERATION_PARAMS_1 (3, (1, 1, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
#include BOOST_PP_ITERATE()
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME const_cast_from
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace intrusive { namespace detail {
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
#define BOOST_PP_ITERATION_PARAMS_1 (3, (1, 1, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
#include BOOST_PP_ITERATE()
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME dynamic_cast_from
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace intrusive { namespace detail {
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
#define BOOST_PP_ITERATION_PARAMS_1 (3, (1, 1, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
#include BOOST_PP_ITERATE()
namespace boost {
namespace intrusive {
namespace detail {
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(element_type)
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(difference_type)
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(reference)
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(value_traits_ptr)
} //namespace detail {
} //namespace intrusive {
} //namespace boost {
#endif // ! defined(BOOST_INTRUSIVE_ALLOCATOR_MEMORY_UTIL_HPP)

View file

@ -0,0 +1,376 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2006-2014
// (C) Copyright Microsoft Corporation 2014
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_DETAIL_MPL_HPP
#define BOOST_INTRUSIVE_DETAIL_MPL_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/intrusive/detail/config_begin.hpp>
#include <cstddef>
namespace boost {
namespace intrusive {
namespace detail {
template <typename T, typename U>
struct is_same
{
static const bool value = false;
};
template <typename T>
struct is_same<T, T>
{
static const bool value = true;
};
template<typename T>
struct add_const
{ typedef const T type; };
template<typename T>
struct remove_const
{ typedef T type; };
template<typename T>
struct remove_const<const T>
{ typedef T type; };
template<typename T>
struct remove_cv
{ typedef T type; };
template<typename T>
struct remove_cv<const T>
{ typedef T type; };
template<typename T>
struct remove_cv<const volatile T>
{ typedef T type; };
template<typename T>
struct remove_cv<volatile T>
{ typedef T type; };
template<class T>
struct remove_reference
{
typedef T type;
};
template<class T>
struct remove_reference<T&>
{
typedef T type;
};
template<class T>
struct remove_pointer
{
typedef T type;
};
template<class T>
struct remove_pointer<T*>
{
typedef T type;
};
template<class T>
struct add_pointer
{
typedef T *type;
};
typedef char one;
struct two {one _[2];};
template< bool C_ >
struct bool_
{
static const bool value = C_;
};
template< class Integer, Integer Value >
struct integer
{
static const Integer value = Value;
};
typedef bool_<true> true_;
typedef bool_<false> false_;
typedef true_ true_type;
typedef false_ false_type;
typedef char yes_type;
struct no_type
{
char padding[8];
};
template <bool B, class T = void>
struct enable_if_c {
typedef T type;
};
template <class T>
struct enable_if_c<false, T> {};
template <class Cond, class T = void>
struct enable_if : public enable_if_c<Cond::value, T>{};
template<class F, class Param>
struct apply
{
typedef typename F::template apply<Param>::type type;
};
#if defined(_MSC_VER) && (_MSC_VER >= 1400)
template <class T, class U>
struct is_convertible
{
static const bool value = __is_convertible_to(T, U);
};
#else
template <class T, class U>
class is_convertible
{
typedef char true_t;
class false_t { char dummy[2]; };
//use any_conversion as first parameter since in MSVC
//overaligned types can't go through ellipsis
static false_t dispatch(...);
static true_t dispatch(U);
static typename remove_reference<T>::type &trigger();
public:
static const bool value = sizeof(dispatch(trigger())) == sizeof(true_t);
};
#endif
template<
bool C
, typename T1
, typename T2
>
struct if_c
{
typedef T1 type;
};
template<
typename T1
, typename T2
>
struct if_c<false,T1,T2>
{
typedef T2 type;
};
template<
typename C
, typename T1
, typename T2
>
struct if_
{
typedef typename if_c<0 != C::value, T1, T2>::type type;
};
template<
bool C
, typename F1
, typename F2
>
struct eval_if_c
: if_c<C,F1,F2>::type
{};
template<
typename C
, typename T1
, typename T2
>
struct eval_if
: if_<C,T1,T2>::type
{};
// identity is an extension: it is not part of the standard.
template <class T>
struct identity
{
typedef T type;
};
template<class T, bool Add>
struct add_const_if_c
{
typedef typename if_c
< Add
, typename add_const<T>::type
, T
>::type type;
};
//boost::alignment_of yields to 10K lines of preprocessed code, so we
//need an alternative
template <typename T> struct alignment_of;
template <typename T>
struct alignment_of_hack
{
char c;
T t;
alignment_of_hack();
};
template <unsigned A, unsigned S>
struct alignment_logic
{
static const std::size_t value = A < S ? A : S;
};
template< typename T >
struct alignment_of
{
static const std::size_t value = alignment_logic
< sizeof(alignment_of_hack<T>) - sizeof(T)
, sizeof(T)
>::value;
};
template<class Class>
class is_empty_class
{
template <typename T>
struct empty_helper_t1 : public T
{
empty_helper_t1();
int i[256];
};
struct empty_helper_t2
{ int i[256]; };
public:
static const bool value = sizeof(empty_helper_t1<Class>) == sizeof(empty_helper_t2);
};
template<std::size_t S>
struct ls_zeros
{
static const std::size_t value = (S & std::size_t(1)) ? 0 : (1 + ls_zeros<(S>>1u)>::value);
};
template<>
struct ls_zeros<0>
{
static const std::size_t value = 0;
};
template<>
struct ls_zeros<1>
{
static const std::size_t value = 0;
};
template <typename T> struct unvoid_ref { typedef T &type; };
template <> struct unvoid_ref<void> { struct type_impl { }; typedef type_impl & type; };
template <> struct unvoid_ref<const void> { struct type_impl { }; typedef type_impl & type; };
// Infrastructure for providing a default type for T::TNAME if absent.
#define BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(TNAME) \
template <typename T, typename DefaultType> \
struct boost_intrusive_default_type_ ## TNAME \
{ \
template <typename X> \
static char test(int, typename X::TNAME*); \
\
template <typename X> \
static int test(...); \
\
struct DefaultWrap { typedef DefaultType TNAME; }; \
\
static const bool value = (1 == sizeof(test<T>(0, 0))); \
\
typedef typename \
::boost::intrusive::detail::if_c \
<value, T, DefaultWrap>::type::TNAME type; \
}; \
\
template <typename T, typename DefaultType> \
struct boost_intrusive_eval_default_type_ ## TNAME \
{ \
template <typename X> \
static char test(int, typename X::TNAME*); \
\
template <typename X> \
static int test(...); \
\
struct DefaultWrap \
{ typedef typename DefaultType::type TNAME; }; \
\
static const bool value = (1 == sizeof(test<T>(0, 0))); \
\
typedef typename \
::boost::intrusive::detail::eval_if_c \
< value \
, ::boost::intrusive::detail::identity<T> \
, ::boost::intrusive::detail::identity<DefaultWrap> \
>::type::TNAME type; \
}; \
//
#define BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(INSTANTIATION_NS_PREFIX, T, TNAME, TIMPL) \
typename INSTANTIATION_NS_PREFIX \
boost_intrusive_default_type_ ## TNAME< T, TIMPL >::type \
//
#define BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_EVAL_DEFAULT(INSTANTIATION_NS_PREFIX, T, TNAME, TIMPL) \
typename INSTANTIATION_NS_PREFIX \
boost_intrusive_eval_default_type_ ## TNAME< T, TIMPL >::type \
//
#define BOOST_INTRUSIVE_INTERNAL_STATIC_BOOL_IS_TRUE(TRAITS_PREFIX, TYPEDEF_TO_FIND) \
template <class T>\
struct TRAITS_PREFIX##_bool\
{\
template<bool Add>\
struct two_or_three {one _[2 + Add];};\
template <class U> static one test(...);\
template <class U> static two_or_three<U::TYPEDEF_TO_FIND> test (int);\
static const std::size_t value = sizeof(test<T>(0));\
};\
\
template <class T>\
struct TRAITS_PREFIX##_bool_is_true\
{\
static const bool value = TRAITS_PREFIX##_bool<T>::value > sizeof(one)*2;\
};\
//
} //namespace detail
} //namespace intrusive
} //namespace boost
#include <boost/intrusive/detail/config_end.hpp>
#endif //BOOST_INTRUSIVE_DETAIL_MPL_HPP

View file

@ -0,0 +1,109 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2014-2014
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_DETAIL_NODE_CLONER_DISPOSER_HPP
#define BOOST_INTRUSIVE_DETAIL_NODE_CLONER_DISPOSER_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/intrusive/link_mode.hpp>
#include <boost/intrusive/detail/ebo_functor_holder.hpp>
#include <boost/intrusive/detail/algo_type.hpp>
#include <boost/intrusive/detail/assert.hpp>
namespace boost {
namespace intrusive {
namespace detail {
template<class F, class ValueTraits, algo_types AlgoType>
struct node_cloner
: private ebo_functor_holder<F>
{
typedef ValueTraits value_traits;
typedef typename value_traits::node_traits node_traits;
typedef typename node_traits::node_ptr node_ptr;
typedef ebo_functor_holder<F> base_t;
typedef typename get_algo< AlgoType
, node_traits>::type node_algorithms;
static const bool safemode_or_autounlink =
is_safe_autounlink<value_traits::link_mode>::value;
typedef typename value_traits::value_type value_type;
typedef typename value_traits::pointer pointer;
typedef typename node_traits::node node;
typedef typename value_traits::const_node_ptr const_node_ptr;
typedef typename value_traits::reference reference;
typedef typename value_traits::const_reference const_reference;
node_cloner(F f, const ValueTraits *traits)
: base_t(f), traits_(traits)
{}
// tree-based containers use this method, which is proxy-reference friendly
node_ptr operator()(const node_ptr & p)
{
const_reference v = *traits_->to_value_ptr(p);
node_ptr n = traits_->to_node_ptr(*base_t::get()(v));
//Cloned node must be in default mode if the linking mode requires it
if(safemode_or_autounlink)
BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(n));
return n;
}
// hashtables use this method, which is proxy-reference unfriendly
node_ptr operator()(const node &to_clone)
{
const value_type &v =
*traits_->to_value_ptr
(pointer_traits<const_node_ptr>::pointer_to(to_clone));
node_ptr n = traits_->to_node_ptr(*base_t::get()(v));
//Cloned node must be in default mode if the linking mode requires it
if(safemode_or_autounlink)
BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(n));
return n;
}
const ValueTraits * const traits_;
};
template<class F, class ValueTraits, algo_types AlgoType>
struct node_disposer
: private ebo_functor_holder<F>
{
typedef ValueTraits value_traits;
typedef typename value_traits::node_traits node_traits;
typedef typename node_traits::node_ptr node_ptr;
typedef ebo_functor_holder<F> base_t;
typedef typename get_algo< AlgoType
, node_traits>::type node_algorithms;
static const bool safemode_or_autounlink =
is_safe_autounlink<value_traits::link_mode>::value;
node_disposer(F f, const ValueTraits *cont)
: base_t(f), traits_(cont)
{}
void operator()(const node_ptr & p)
{
if(safemode_or_autounlink)
node_algorithms::init(p);
base_t::get()(traits_->to_value_ptr(p));
}
const ValueTraits * const traits_;
};
} //namespace detail{
} //namespace intrusive{
} //namespace boost{
#endif //BOOST_INTRUSIVE_DETAIL_NODE_CLONER_DISPOSER_HPP

Some files were not shown because too many files have changed in this diff Show more