mirror of
https://github.com/yuzu-emu/ext-boost.git
synced 2024-12-22 17:55:38 +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
|
||||
========================================
|
||||
|
||||
This is a subset of Boost v1.57.0.
|
||||
|
||||
Currently imported libraries:
|
||||
-----------------------------
|
||||
* concept
|
||||
* config
|
||||
* container
|
||||
* core
|
||||
* intrusive
|
||||
* iterator
|
||||
* move
|
||||
* mpl
|
||||
* preprocessor
|
||||
* 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