mirror of
https://github.com/yuzu-emu/ext-boost.git
synced 2024-12-22 18:25:36 +00:00
Merge pull request #1 from yuriks/add-container
Add container library (for static_vector)
This commit is contained in:
commit
97052c28ac
|
@ -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
|
||||||
|
|
349
boost/container/adaptive_pool.hpp
Normal file
349
boost/container/adaptive_pool.hpp
Normal 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
|
367
boost/container/allocator.hpp
Normal file
367
boost/container/allocator.hpp
Normal 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
|
||||||
|
|
409
boost/container/allocator_traits.hpp
Normal file
409
boost/container/allocator_traits.hpp
Normal 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)
|
270
boost/container/container_fwd.hpp
Normal file
270
boost/container/container_fwd.hpp
Normal 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
2069
boost/container/deque.hpp
Normal file
File diff suppressed because it is too large
Load diff
162
boost/container/detail/adaptive_node_pool.hpp
Normal file
162
boost/container/detail/adaptive_node_pool.hpp
Normal 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
|
875
boost/container/detail/adaptive_node_pool_impl.hpp
Normal file
875
boost/container/detail/adaptive_node_pool_impl.hpp
Normal 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
|
477
boost/container/detail/advanced_insert_int.hpp
Normal file
477
boost/container/detail/advanced_insert_int.hpp
Normal 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
|
62
boost/container/detail/algorithms.hpp
Normal file
62
boost/container/detail/algorithms.hpp
Normal 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
|
||||||
|
|
326
boost/container/detail/alloc_lib.h
Normal file
326
boost/container/detail/alloc_lib.h
Normal 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
|
20
boost/container/detail/alloc_lib_auto_link.hpp
Normal file
20
boost/container/detail/alloc_lib_auto_link.hpp
Normal 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
|
54
boost/container/detail/allocation_type.hpp
Normal file
54
boost/container/detail/allocation_type.hpp
Normal 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
|
168
boost/container/detail/allocator_version_traits.hpp
Normal file
168
boost/container/detail/allocator_version_traits.hpp
Normal 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)
|
38
boost/container/detail/auto_link.hpp
Normal file
38
boost/container/detail/auto_link.hpp
Normal 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
|
48
boost/container/detail/config_begin.hpp
Normal file
48
boost/container/detail/config_begin.hpp
Normal 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
|
13
boost/container/detail/config_end.hpp
Normal file
13
boost/container/detail/config_end.hpp
Normal 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
|
||||||
|
|
380
boost/container/detail/destroyers.hpp
Normal file
380
boost/container/detail/destroyers.hpp
Normal 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
|
1021
boost/container/detail/flat_tree.hpp
Normal file
1021
boost/container/detail/flat_tree.hpp
Normal file
File diff suppressed because it is too large
Load diff
92
boost/container/detail/function_detector.hpp
Normal file
92
boost/container/detail/function_detector.hpp
Normal 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
|
383
boost/container/detail/hash_table.hpp
Normal file
383
boost/container/detail/hash_table.hpp
Normal 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);
|
||||||
|
};
|
821
boost/container/detail/iterators.hpp
Normal file
821
boost/container/detail/iterators.hpp
Normal 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
|
119
boost/container/detail/math_functions.hpp
Normal file
119
boost/container/detail/math_functions.hpp
Normal 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
|
90
boost/container/detail/memory_util.hpp
Normal file
90
boost/container/detail/memory_util.hpp
Normal 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)
|
183
boost/container/detail/mpl.hpp
Normal file
183
boost/container/detail/mpl.hpp
Normal 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
|
||||||
|
|
292
boost/container/detail/multiallocation_chain.hpp
Normal file
292
boost/container/detail/multiallocation_chain.hpp
Normal 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
|
284
boost/container/detail/mutex.hpp
Normal file
284
boost/container/detail/mutex.hpp
Normal 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
|
399
boost/container/detail/node_alloc_holder.hpp
Normal file
399
boost/container/detail/node_alloc_holder.hpp
Normal 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_
|
156
boost/container/detail/node_pool.hpp
Normal file
156
boost/container/detail/node_pool.hpp
Normal 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
|
366
boost/container/detail/node_pool_impl.hpp
Normal file
366
boost/container/detail/node_pool_impl.hpp
Normal 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
|
374
boost/container/detail/pair.hpp
Normal file
374
boost/container/detail/pair.hpp
Normal 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
|
27
boost/container/detail/placement_new.hpp
Normal file
27
boost/container/detail/placement_new.hpp
Normal 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
|
53
boost/container/detail/pool_common.hpp
Normal file
53
boost/container/detail/pool_common.hpp
Normal 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
|
98
boost/container/detail/pool_common_alloc.hpp
Normal file
98
boost/container/detail/pool_common_alloc.hpp
Normal 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
|
228
boost/container/detail/preprocessor.hpp
Normal file
228
boost/container/detail/preprocessor.hpp
Normal 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
|
117
boost/container/detail/singleton.hpp
Normal file
117
boost/container/detail/singleton.hpp
Normal 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
|
59
boost/container/detail/std_fwd.hpp
Normal file
59
boost/container/detail/std_fwd.hpp
Normal 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
|
177
boost/container/detail/transform_iterator.hpp
Normal file
177
boost/container/detail/transform_iterator.hpp
Normal 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
|
1182
boost/container/detail/tree.hpp
Normal file
1182
boost/container/detail/tree.hpp
Normal file
File diff suppressed because it is too large
Load diff
237
boost/container/detail/type_traits.hpp
Normal file
237
boost/container/detail/type_traits.hpp
Normal 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
|
1267
boost/container/detail/utilities.hpp
Normal file
1267
boost/container/detail/utilities.hpp
Normal file
File diff suppressed because it is too large
Load diff
45
boost/container/detail/value_init.hpp
Normal file
45
boost/container/detail/value_init.hpp
Normal 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
|
154
boost/container/detail/variadic_templates_tools.hpp
Normal file
154
boost/container/detail/variadic_templates_tools.hpp
Normal 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
|
103
boost/container/detail/version_type.hpp
Normal file
103
boost/container/detail/version_type.hpp
Normal 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
|
72
boost/container/detail/workaround.hpp
Normal file
72
boost/container/detail/workaround.hpp
Normal 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
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
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
1462
boost/container/list.hpp
Normal file
File diff suppressed because it is too large
Load diff
1406
boost/container/map.hpp
Normal file
1406
boost/container/map.hpp
Normal file
File diff suppressed because it is too large
Load diff
344
boost/container/node_allocator.hpp
Normal file
344
boost/container/node_allocator.hpp
Normal 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
|
76
boost/container/options.hpp
Normal file
76
boost/container/options.hpp
Normal 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
|
1534
boost/container/scoped_allocator.hpp
Normal file
1534
boost/container/scoped_allocator.hpp
Normal file
File diff suppressed because it is too large
Load diff
87
boost/container/scoped_allocator_fwd.hpp
Normal file
87
boost/container/scoped_allocator_fwd.hpp
Normal 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
1126
boost/container/set.hpp
Normal file
File diff suppressed because it is too large
Load diff
1730
boost/container/slist.hpp
Normal file
1730
boost/container/slist.hpp
Normal file
File diff suppressed because it is too large
Load diff
1949
boost/container/stable_vector.hpp
Normal file
1949
boost/container/stable_vector.hpp
Normal file
File diff suppressed because it is too large
Load diff
1156
boost/container/static_vector.hpp
Normal file
1156
boost/container/static_vector.hpp
Normal file
File diff suppressed because it is too large
Load diff
2918
boost/container/string.hpp
Normal file
2918
boost/container/string.hpp
Normal file
File diff suppressed because it is too large
Load diff
166
boost/container/throw_exception.hpp
Normal file
166
boost/container/throw_exception.hpp
Normal 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
2984
boost/container/vector.hpp
Normal file
File diff suppressed because it is too large
Load diff
336
boost/intrusive/any_hook.hpp
Normal file
336
boost/intrusive/any_hook.hpp
Normal 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
950
boost/intrusive/avl_set.hpp
Normal 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
|
291
boost/intrusive/avl_set_hook.hpp
Normal file
291
boost/intrusive/avl_set_hook.hpp
Normal 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
549
boost/intrusive/avltree.hpp
Normal 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
|
687
boost/intrusive/avltree_algorithms.hpp
Normal file
687
boost/intrusive/avltree_algorithms.hpp
Normal 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
948
boost/intrusive/bs_set.hpp
Normal 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
|
286
boost/intrusive/bs_set_hook.hpp
Normal file
286
boost/intrusive/bs_set_hook.hpp
Normal 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
2177
boost/intrusive/bstree.hpp
Normal file
File diff suppressed because it is too large
Load diff
2127
boost/intrusive/bstree_algorithms.hpp
Normal file
2127
boost/intrusive/bstree_algorithms.hpp
Normal file
File diff suppressed because it is too large
Load diff
507
boost/intrusive/circular_list_algorithms.hpp
Normal file
507
boost/intrusive/circular_list_algorithms.hpp
Normal 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
|
407
boost/intrusive/circular_slist_algorithms.hpp
Normal file
407
boost/intrusive/circular_slist_algorithms.hpp
Normal 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
|
77
boost/intrusive/derivation_value_traits.hpp
Normal file
77
boost/intrusive/derivation_value_traits.hpp
Normal 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
|
46
boost/intrusive/detail/algo_type.hpp
Normal file
46
boost/intrusive/detail/algo_type.hpp
Normal 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
|
280
boost/intrusive/detail/any_node_and_algorithms.hpp
Normal file
280
boost/intrusive/detail/any_node_and_algorithms.hpp
Normal 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
|
90
boost/intrusive/detail/array_initializer.hpp
Normal file
90
boost/intrusive/detail/array_initializer.hpp
Normal 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
|
41
boost/intrusive/detail/assert.hpp
Normal file
41
boost/intrusive/detail/assert.hpp
Normal 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
|
188
boost/intrusive/detail/avltree_node.hpp
Normal file
188
boost/intrusive/detail/avltree_node.hpp
Normal 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
|
194
boost/intrusive/detail/common_slist_algorithms.hpp
Normal file
194
boost/intrusive/detail/common_slist_algorithms.hpp
Normal 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
|
51
boost/intrusive/detail/config_begin.hpp
Normal file
51
boost/intrusive/detail/config_begin.hpp
Normal 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
|
15
boost/intrusive/detail/config_end.hpp
Normal file
15
boost/intrusive/detail/config_end.hpp
Normal 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
|
65
boost/intrusive/detail/default_header_holder.hpp
Normal file
65
boost/intrusive/detail/default_header_holder.hpp
Normal 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
|
226
boost/intrusive/detail/ebo_functor_holder.hpp
Normal file
226
boost/intrusive/detail/ebo_functor_holder.hpp
Normal 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
|
40
boost/intrusive/detail/empty_node_checker.hpp
Normal file
40
boost/intrusive/detail/empty_node_checker.hpp
Normal 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
|
44
boost/intrusive/detail/equal_to_value.hpp
Normal file
44
boost/intrusive/detail/equal_to_value.hpp
Normal 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
|
84
boost/intrusive/detail/exception_disposer.hpp
Normal file
84
boost/intrusive/detail/exception_disposer.hpp
Normal 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
|
88
boost/intrusive/detail/function_detector.hpp
Normal file
88
boost/intrusive/detail/function_detector.hpp
Normal 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
|
217
boost/intrusive/detail/generic_hook.hpp
Normal file
217
boost/intrusive/detail/generic_hook.hpp
Normal 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
|
218
boost/intrusive/detail/get_value_traits.hpp
Normal file
218
boost/intrusive/detail/get_value_traits.hpp
Normal 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
|
372
boost/intrusive/detail/has_member_function_callable_with.hpp
Normal file
372
boost/intrusive/detail/has_member_function_callable_with.hpp
Normal 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
|
287
boost/intrusive/detail/hashtable_node.hpp
Normal file
287
boost/intrusive/detail/hashtable_node.hpp
Normal 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
|
182
boost/intrusive/detail/hook_traits.hpp
Normal file
182
boost/intrusive/detail/hook_traits.hpp
Normal 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
|
227
boost/intrusive/detail/iiterator.hpp
Normal file
227
boost/intrusive/detail/iiterator.hpp
Normal 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
|
77
boost/intrusive/detail/is_stateful_value_traits.hpp
Normal file
77
boost/intrusive/detail/is_stateful_value_traits.hpp
Normal 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
|
72
boost/intrusive/detail/key_nodeptr_comp.hpp
Normal file
72
boost/intrusive/detail/key_nodeptr_comp.hpp
Normal 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
|
129
boost/intrusive/detail/list_iterator.hpp
Normal file
129
boost/intrusive/detail/list_iterator.hpp
Normal 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
|
67
boost/intrusive/detail/list_node.hpp
Normal file
67
boost/intrusive/detail/list_node.hpp
Normal 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
|
271
boost/intrusive/detail/math.hpp
Normal file
271
boost/intrusive/detail/math.hpp
Normal 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
|
92
boost/intrusive/detail/memory_util.hpp
Normal file
92
boost/intrusive/detail/memory_util.hpp
Normal 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)
|
376
boost/intrusive/detail/mpl.hpp
Normal file
376
boost/intrusive/detail/mpl.hpp
Normal 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
|
109
boost/intrusive/detail/node_cloner_disposer.hpp
Normal file
109
boost/intrusive/detail/node_cloner_disposer.hpp
Normal 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
Loading…
Reference in a new issue