Merge branch 'develop'

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

View File

@@ -21,7 +21,7 @@ rule test_all
for local fileb in [ glob *.cpp ]
{
all_rules += [ run $(fileb) /boost/timer//boost_timer
all_rules += [ run $(fileb) /boost/timer//boost_timer /boost/container//boost_container
: # additional args
: # test-files
: # requirements
@@ -31,4 +31,4 @@ rule test_all
return $(all_rules) ;
}
test-suite container_test : [ test_all r ] ;
test-suite container_bench : [ test_all r ] ;

View File

@@ -0,0 +1,327 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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.
//
//////////////////////////////////////////////////////////////////////////////
#ifdef _MSC_VER
#pragma warning (disable : 4512)
#pragma warning (disable : 4127)
#pragma warning (disable : 4244)
#pragma warning (disable : 4267)
#endif
#include <boost/container/adaptive_pool.hpp>
#include <boost/container/node_allocator.hpp>
#include <boost/container/allocator.hpp>
#include <boost/container/list.hpp>
#include <memory> //std::allocator
#include <iostream> //std::cout, std::endl
#include <vector> //std::vector
#include <cstddef> //std::size_t
#include <boost/timer/timer.hpp>
using boost::timer::cpu_timer;
using boost::timer::cpu_times;
using boost::timer::nanosecond_type;
namespace bc = boost::container;
typedef std::allocator<int> StdAllocator;
typedef bc::allocator<int, 2> AllocatorPlusV2;
typedef bc::allocator<int, 1> AllocatorPlusV1;
typedef bc::adaptive_pool
< int
, bc::ADP_nodes_per_block
, bc::ADP_max_free_blocks
, bc::ADP_only_alignment
, 1> AdPoolAlignOnlyV1;
typedef bc::adaptive_pool
< int
, bc::ADP_nodes_per_block
, bc::ADP_max_free_blocks
, bc::ADP_only_alignment
, 2> AdPoolAlignOnlyV2;
typedef bc::adaptive_pool
< int
, bc::ADP_nodes_per_block
, bc::ADP_max_free_blocks
, 2
, 1> AdPool2PercentV1;
typedef bc::adaptive_pool
< int
, bc::ADP_nodes_per_block
, bc::ADP_max_free_blocks
, 2
, 2> AdPool2PercentV2;
typedef bc::node_allocator
< int
, bc::NodeAlloc_nodes_per_block
, 1> SimpleSegregatedStorageV1;
typedef bc::node_allocator
< int
, bc::NodeAlloc_nodes_per_block
, 2> SimpleSegregatedStorageV2;
//Explicit instantiation
template class bc::adaptive_pool
< int
, bc::ADP_nodes_per_block
, bc::ADP_max_free_blocks
, bc::ADP_only_alignment
, 2>;
template class bc::node_allocator
< int
, bc::NodeAlloc_nodes_per_block
, 2>;
template<class Allocator> struct get_allocator_name;
template<> struct get_allocator_name<StdAllocator>
{ static const char *get() { return "StdAllocator"; } };
template<> struct get_allocator_name<AllocatorPlusV2>
{ static const char *get() { return "AllocatorPlusV2"; } };
template<> struct get_allocator_name<AllocatorPlusV1>
{ static const char *get() { return "AllocatorPlusV1"; } };
template<> struct get_allocator_name<AdPoolAlignOnlyV1>
{ static const char *get() { return "AdPoolAlignOnlyV1"; } };
template<> struct get_allocator_name<AdPoolAlignOnlyV2>
{ static const char *get() { return "AdPoolAlignOnlyV2"; } };
template<> struct get_allocator_name<AdPool2PercentV1>
{ static const char *get() { return "AdPool2PercentV1"; } };
template<> struct get_allocator_name<AdPool2PercentV2>
{ static const char *get() { return "AdPool2PercentV2"; } };
template<> struct get_allocator_name<SimpleSegregatedStorageV1>
{ static const char *get() { return "SimpleSegregatedStorageV1"; } };
template<> struct get_allocator_name<SimpleSegregatedStorageV2>
{ static const char *get() { return "SimpleSegregatedStorageV2"; } };
class MyInt
{
std::size_t int_;
public:
explicit MyInt(std::size_t i = 0) : int_(i){}
MyInt(const MyInt &other)
: int_(other.int_)
{}
MyInt & operator=(const MyInt &other)
{
int_ = other.int_;
return *this;
}
};
template<class Allocator>
void list_test_template(std::size_t num_iterations, std::size_t num_elements, bool csv_output)
{
typedef typename Allocator::template rebind<MyInt>::other IntAllocator;
nanosecond_type tinsert, terase;
boost_cont_malloc_stats_t insert_stats, erase_stats;
std::size_t insert_inuse, erase_inuse;
const size_t sizeof_node = 2*sizeof(void*)+sizeof(int);
typedef bc::list<MyInt, IntAllocator> list_t;
typedef typename list_t::iterator iterator_t;
{
cpu_timer timer;
timer.resume();
list_t l;
for(std::size_t r = 0; r != num_iterations; ++r){
l.insert(l.end(), num_elements, MyInt(r));
}
timer.stop();
tinsert = timer.elapsed().wall;
insert_inuse = boost_cont_in_use_memory();
insert_stats = boost_cont_malloc_stats();
/*
iterator_t it(l.begin());
iterator_t last(--l.end());
for(std::size_t n_elem = 0, n_max = l.size()/2-1; n_elem != n_max; ++n_elem)
{
l.splice(it++, l, last--);
}
*/
//l.reverse();
//Now preprocess erase ranges
std::vector<iterator_t> ranges_to_erase;
ranges_to_erase.push_back(l.begin());
for(std::size_t r = 0; r != num_iterations; ++r){
iterator_t next_pos(ranges_to_erase[r]);
std::size_t n = num_elements;
while(n--){ ++next_pos; }
ranges_to_erase.push_back(next_pos);
}
//Measure range erasure function
timer.start();
for(std::size_t r = 0; r != num_iterations; ++r){
assert((r+1) < ranges_to_erase.size());
l.erase(ranges_to_erase[r], ranges_to_erase[r+1]);
}
timer.stop();
terase = timer.elapsed().wall;
erase_inuse = boost_cont_in_use_memory();
erase_stats = boost_cont_malloc_stats();
}
if(csv_output){
std::cout << get_allocator_name<Allocator>::get()
<< ";"
<< num_iterations
<< ";"
<< num_elements
<< ";"
<< float(tinsert)/(num_iterations*num_elements)
<< ";"
<< (unsigned int)insert_stats.system_bytes
<< ";"
<< float(insert_stats.system_bytes)/(num_iterations*num_elements*sizeof_node)*100.0-100.0
<< ";"
<< (unsigned int)insert_inuse
<< ";"
<< (float(insert_inuse)/(num_iterations*num_elements*sizeof_node)*100.0)-100.0
<< ";";
std::cout << float(terase)/(num_iterations*num_elements)
<< ";"
<< (unsigned int)erase_stats.system_bytes
<< ";"
<< (unsigned int)erase_inuse
<< std::endl;
}
else{
std::cout << std::endl
<< "Allocator: " << get_allocator_name<Allocator>::get()
<< std::endl
<< " allocation/deallocation(ns): " << float(tinsert)/(num_iterations*num_elements) << '\t' << float(terase)/(num_iterations*num_elements)
<< std::endl
<< " Sys MB(overh.)/Inuse MB(overh.): " << (float)insert_stats.system_bytes/(1024*1024) << "(" << float(insert_stats.system_bytes)/(num_iterations*num_elements*sizeof_node)*100.0-100.0 << "%)"
<< " / "
<< (float)insert_inuse/(1024*1024) << "(" << (float(insert_inuse)/(num_iterations*num_elements*sizeof_node)*100.0)-100.0 << "%)"
<< std::endl
<< " system MB/inuse bytes after: " << (float)erase_stats.system_bytes/(1024*1024) << '\t' << boost_cont_in_use_memory()
<< std::endl << std::endl;
}
//Release node_allocator cache
typedef boost::container::container_detail::shared_node_pool
< (2*sizeof(void*)+sizeof(int))
, AdPoolAlignOnlyV2::nodes_per_block> shared_node_pool_t;
boost::container::container_detail::singleton_default
<shared_node_pool_t>::instance().purge_blocks();
//Release adaptive_pool cache
typedef boost::container::container_detail::shared_adaptive_node_pool
< (2*sizeof(void*)+sizeof(int))
, AdPool2PercentV2::nodes_per_block
, AdPool2PercentV2::max_free_blocks
, AdPool2PercentV2::overhead_percent> shared_adaptive_pool_plus_t;
boost::container::container_detail::singleton_default
<shared_adaptive_pool_plus_t>::instance().deallocate_free_blocks();
//Release adaptive_pool cache
typedef boost::container::container_detail::shared_adaptive_node_pool
< (2*sizeof(void*)+sizeof(int))
, AdPool2PercentV2::nodes_per_block
, AdPool2PercentV2::max_free_blocks
, 0u> shared_adaptive_pool_plus_align_only_t;
boost::container::container_detail::singleton_default
<shared_adaptive_pool_plus_align_only_t>::instance().deallocate_free_blocks();
//Release dlmalloc memory
boost_cont_trim(0);
}
void print_header()
{
std::cout << "Allocator" << ";" << "Iterations" << ";" << "Size" << ";"
<< "Insertion time(ns)" << ";"
<< "System bytes" << ";"
<< "System overhead(%)" << ";"
<< "In use bytes" << ";"
<< "In use overhead(%)" << ";"
<< "Erasure time (ns)" << ";"
<< "System bytes after" << ";"
<< "In use bytes after"
<< std::endl;
}
int main(int argc, const char *argv[])
{
#define SINGLE_TEST
#ifndef SINGLE_TEST
#ifdef NDEBUG
std::size_t numrep [] = { 3000, 30000, 300000, 3000000, 6000000, 15000000, 30000000 };
#else
std::size_t numrep [] = { 20, 200, 2000, 20000, 40000, 100000, 200000 };
#endif
std::size_t numele [] = { 10000, 1000, 100, 10, 5, 2, 1 };
#else
#ifdef NDEBUG
std::size_t numrep [] = { 1500000 };
#else
std::size_t numrep [] = { 10000 };
#endif
std::size_t numele [] = { 10 };
#endif
bool csv_output = argc == 2 && (strcmp(argv[1], "--csv-output") == 0);
if(csv_output){/*
print_header();
for(std::size_t i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
list_test_template<AllocatorPlusV1>(numrep[i], numele[i], csv_output);
}
for(std::size_t i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
list_test_template<AllocatorPlusV2>(numrep[i], numele[i], csv_output);
}
for(std::size_t i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
list_test_template<AdPoolAlignOnlyV1>(numrep[i], numele[i], csv_output);
}
for(std::size_t i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
list_test_template<AdPoolAlignOnlyV2>(numrep[i], numele[i], csv_output);
}
for(std::size_t i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
list_test_template<AdPool2PercentV1>(numrep[i], numele[i], csv_output);
}
for(std::size_t i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
list_test_template<AdPool2PercentV2>(numrep[i], numele[i], csv_output);
}
for(std::size_t i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
list_test_template<SimpleSegregatedStorageV1>(numrep[i], numele[i], csv_output);
}
for(std::size_t i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
list_test_template<SimpleSegregatedStorageV2>(numrep[i], numele[i], csv_output);
}*/
}
else{
for(std::size_t i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
std::cout << "\n ----------------------------------- \n"
<< " Iterations/Elements: " << numrep[i] << "/" << numele[i]
<< "\n ----------------------------------- \n";
list_test_template<AllocatorPlusV1>(numrep[i], numele[i], csv_output);
list_test_template<AllocatorPlusV2>(numrep[i], numele[i], csv_output);
list_test_template<AdPoolAlignOnlyV1>(numrep[i], numele[i], csv_output);
list_test_template<AdPoolAlignOnlyV2>(numrep[i], numele[i], csv_output);
list_test_template<AdPool2PercentV1>(numrep[i], numele[i], csv_output);
list_test_template<AdPool2PercentV2>(numrep[i], numele[i], csv_output);
list_test_template<SimpleSegregatedStorageV1>(numrep[i], numele[i], csv_output);
list_test_template<SimpleSegregatedStorageV2>(numrep[i], numele[i], csv_output);
}
}
return 0;
}

181
bench/bench_alloc.cpp Normal file
View File

@@ -0,0 +1,181 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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.
//
//////////////////////////////////////////////////////////////////////////////
#ifdef _MSC_VER
#pragma warning (disable : 4512)
#endif
#include <boost/container/detail/alloc_lib_auto_link.hpp>
#define BOOST_INTERPROCESS_VECTOR_ALLOC_STATS
#include <iostream> //std::cout, std::endl
#include <typeinfo> //typeid
#include <boost/timer/timer.hpp>
using boost::timer::cpu_timer;
using boost::timer::cpu_times;
using boost::timer::nanosecond_type;
template <class POD>
void allocation_timing_test(unsigned int num_iterations, unsigned int num_elements)
{
size_t capacity = 0;
unsigned int numalloc = 0, numexpand = 0;
std::cout
<< " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \n"
<< " Iterations/Elements: " << num_iterations << "/" << num_elements << '\n'
<< " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \n"
<< std::endl;
allocation_type malloc_types[] = { BOOST_CONTAINER_EXPAND_BWD, BOOST_CONTAINER_EXPAND_FWD, BOOST_CONTAINER_ALLOCATE_NEW };
const char * malloc_names[] = { "Backwards expansion", "Forward expansion", "New allocation" };
for(size_t i = 0; i < sizeof(malloc_types)/sizeof(allocation_type); ++i){
numalloc = 0; numexpand = 0;
const allocation_type m_mode = malloc_types[i];
const char *malloc_name = malloc_names[i];
cpu_timer timer;
timer.resume();
for(unsigned int r = 0; r != num_iterations; ++r){
void *first_mem = 0;
if(m_mode != BOOST_CONTAINER_EXPAND_FWD)
first_mem = boost_cont_malloc(sizeof(POD)*num_elements*3/2);
void *addr = boost_cont_malloc(1*sizeof(POD));
if(m_mode == BOOST_CONTAINER_EXPAND_FWD)
first_mem = boost_cont_malloc(sizeof(POD)*num_elements*3/2);
capacity = boost_cont_size(addr)/sizeof(POD);
boost_cont_free(first_mem);
++numalloc;
try{
boost_cont_command_ret_t ret;
for(size_t e = capacity + 1; e < num_elements; ++e){
size_t received_size;
size_t min = (capacity+1)*sizeof(POD);
size_t max = (capacity*3/2)*sizeof(POD);
if(min > max)
max = min;
ret = boost_cont_allocation_command
( m_mode, sizeof(POD)
, min, max, &received_size, addr);
if(!ret.first){
std::cout << "(!ret.first)!" << std::endl;
throw int(0);
}
if(!ret.second){
assert(m_mode == BOOST_CONTAINER_ALLOCATE_NEW);
if(m_mode != BOOST_CONTAINER_ALLOCATE_NEW){
std::cout << "m_mode != BOOST_CONTAINER_ALLOCATE_NEW!" << std::endl;
return;
}
boost_cont_free(addr);
addr = ret.first;
++numalloc;
}
else{
assert(m_mode != BOOST_CONTAINER_ALLOCATE_NEW);
if(m_mode == BOOST_CONTAINER_ALLOCATE_NEW){
std::cout << "m_mode == BOOST_CONTAINER_ALLOCATE_NEW!" << std::endl;
return;
}
++numexpand;
}
capacity = received_size/sizeof(POD);
addr = ret.first;
e = capacity + 1;
}
boost_cont_free(addr);
}
catch(...){
boost_cont_free(addr);
throw;
}
}
assert( boost_cont_allocated_memory() == 0);
if(boost_cont_allocated_memory()!= 0){
std::cout << "Memory leak!" << std::endl;
return;
}
timer.stop();
nanosecond_type nseconds = timer.elapsed().wall;
std::cout << " Malloc type: " << malloc_name
<< std::endl
<< " allocation ns: "
<< float(nseconds)/(num_iterations*num_elements)
<< std::endl
<< " capacity - alloc calls (new/expand): "
<< (unsigned int)capacity << " - "
<< (float(numalloc) + float(numexpand))/num_iterations
<< "(" << float(numalloc)/num_iterations << "/" << float(numexpand)/num_iterations << ")"
<< std::endl << std::endl;
boost_cont_trim(0);
}
}
template<unsigned N>
struct char_holder
{
char ints_[N];
};
template<class POD>
int allocation_loop()
{
std::cout << std::endl
<< "-------------------------------------------\n"
<< "-------------------------------------------\n"
<< " Type(sizeof): " << typeid(POD).name() << " (" << sizeof(POD) << ")\n"
<< "-------------------------------------------\n"
<< "-------------------------------------------\n"
<< std::endl;
#define SINGLE_TEST
#ifndef SINGLE_TEST
#ifdef NDEBUG
unsigned int numrep [] = { /*10000, */100000, 1000000, 10000000 };
#else
unsigned int numrep [] = { /*10000, */10000, 100000, 1000000 };
#endif
unsigned int numele [] = { /*10000, */1000, 100, 10 };
#else
#ifdef NDEBUG
unsigned int numrep [] = { 500000 };
#else
unsigned int numrep [] = { 50000 };
#endif
unsigned int numele [] = { 100 };
#endif
for(unsigned int i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
allocation_timing_test<POD>(numrep[i], numele[i]);
}
return 0;
}
int main()
{
boost_cont_mallopt( (-3)//M_MMAP_THRESHOLD
, 100*10000000);
//allocation_loop<char_holder<4> >();
//allocation_loop<char_holder<6> >();
allocation_loop<char_holder<8> >();
allocation_loop<char_holder<12> >();
//allocation_loop<char_holder<14> >();
allocation_loop<char_holder<24> >();
return 0;
}

View File

@@ -0,0 +1,216 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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.
//
//////////////////////////////////////////////////////////////////////////////
#ifdef _MSC_VER
#pragma warning (disable : 4512)
#endif
#include <boost/container/allocator.hpp>
#define BOOST_CONTAINER_VECTOR_ALLOC_STATS
#include <boost/container/vector.hpp>
#include <memory> //std::allocator
#include <iostream> //std::cout, std::endl
#include <boost/timer/timer.hpp>
using boost::timer::cpu_timer;
using boost::timer::cpu_times;
using boost::timer::nanosecond_type;
namespace bc = boost::container;
typedef std::allocator<int> StdAllocator;
typedef bc::allocator<int, 2, bc::expand_bwd | bc::expand_fwd> AllocatorPlusV2Mask;
typedef bc::allocator<int, 2, bc::expand_fwd> AllocatorPlusV2;
typedef bc::allocator<int, 1> AllocatorPlusV1;
template<class Allocator> struct get_allocator_name;
template<> struct get_allocator_name<StdAllocator>
{ static const char *get() { return "StdAllocator"; } };
template<> struct get_allocator_name<AllocatorPlusV2Mask>
{ static const char *get() { return "AllocatorPlusV2Mask"; } };
template<> struct get_allocator_name<AllocatorPlusV2>
{ static const char *get() { return "AllocatorPlusV2"; } };
template<> struct get_allocator_name<AllocatorPlusV1>
{ static const char *get() { return "AllocatorPlusV1"; } };
//typedef int MyInt;
class MyInt
{
int int_;
public:
MyInt(int i = 0)
: int_(i)
{}
MyInt(const MyInt &other)
: int_(other.int_)
{}
MyInt & operator=(const MyInt &other)
{
int_ = other.int_;
return *this;
}
~MyInt()
{
int_ = 0;
}
};
namespace boost{
template<>
struct has_trivial_destructor_after_move<MyInt>
{
static const bool value = true;
//static const bool value = false;
};
} //namespace boost{
void print_header()
{
std::cout << "Allocator" << ";" << "Iterations" << ";" << "Size" << ";"
<< "Capacity" << ";" << "push_back(ns)" << ";" << "Allocator calls" << ";"
<< "New allocations" << ";" << "Bwd expansions" << std::endl;
}
template<class Allocator>
void vector_test_template(unsigned int num_iterations, unsigned int num_elements, bool csv_output)
{
typedef typename Allocator::template rebind<MyInt>::other IntAllocator;
unsigned int numalloc = 0, numexpand = 0;
cpu_timer timer;
timer.resume();
unsigned int capacity = 0;
for(unsigned int r = 0; r != num_iterations; ++r){
bc::vector<MyInt, IntAllocator> v;
v.reset_alloc_stats();
void *first_mem = 0;
try{
first_mem = boost_cont_malloc(sizeof(MyInt)*num_elements*3/2);
v.push_back(MyInt(0));
boost_cont_free(first_mem);
for(unsigned int e = 0; e != num_elements; ++e){
v.push_back(MyInt(e));
}
numalloc += v.num_alloc;
numexpand += v.num_expand_bwd;
capacity = static_cast<unsigned int>(v.capacity());
}
catch(...){
boost_cont_free(first_mem);
throw;
}
}
assert(boost_cont_allocated_memory() == 0);
timer.stop();
nanosecond_type nseconds = timer.elapsed().wall;
if(csv_output){
std::cout << get_allocator_name<Allocator>::get()
<< ";"
<< num_iterations
<< ";"
<< num_elements
<< ";"
<< capacity
<< ";"
<< float(nseconds)/(num_iterations*num_elements)
<< ";"
<< (float(numalloc) + float(numexpand))/num_iterations
<< ";"
<< float(numalloc)/num_iterations
<< ";"
<< float(numexpand)/num_iterations
<< std::endl;
}
else{
std::cout << std::endl
<< "Allocator: " << get_allocator_name<Allocator>::get()
<< std::endl
<< " push_back ns: "
<< float(nseconds)/(num_iterations*num_elements)
<< std::endl
<< " capacity - alloc calls (new/expand): "
<< (unsigned int)capacity << " - "
<< (float(numalloc) + float(numexpand))/num_iterations
<< "(" << float(numalloc)/num_iterations << "/" << float(numexpand)/num_iterations << ")"
<< std::endl;
std::cout << '\n'
<< " ----------------------------------- "
<< std::endl;
}
boost_cont_trim(0);
}
int main(int argc, const char *argv[])
{
#define SINGLE_TEST
#ifndef SINGLE_TEST
#ifdef NDEBUG
unsigned int numit [] = { 20000, 200000, 2000000, 20000000 };
#else
unsigned int numit [] = { 100, 1000, 10000, 100000 };
#endif
unsigned int numele [] = { 10000, 1000, 100, 10 };
#else
#ifdef NDEBUG
unsigned int numit [] = { 20000 };
#else
unsigned int numit [] = { 100 };
#endif
unsigned int numele [] = { 10000 };
#endif
bool csv_output = argc == 2 && (strcmp(argv[1], "--csv-output") == 0);
if(csv_output){
print_header();
for(unsigned int i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
vector_test_template<StdAllocator>(numit[i], numele[i], csv_output);
}
for(unsigned int i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
vector_test_template<AllocatorPlusV1>(numit[i], numele[i], csv_output);
}
for(unsigned int i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
vector_test_template<AllocatorPlusV2Mask>(numit[i], numele[i], csv_output);
}
for(unsigned int i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
vector_test_template<AllocatorPlusV2>(numit[i], numele[i], csv_output);
}
}
else{
for(unsigned int i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
std::cout << "\n ----------------------------------- \n"
<< " Iterations/Elements: " << numit[i] << "/" << numele[i]
<< "\n ----------------------------------- \n";
vector_test_template<StdAllocator>(numit[i], numele[i], csv_output);
vector_test_template<AllocatorPlusV1>(numit[i], numele[i], csv_output);
vector_test_template<AllocatorPlusV2Mask>(numit[i], numele[i], csv_output);
vector_test_template<AllocatorPlusV2>(numit[i], numele[i], csv_output);
}
}
return 0;
}

View File

@@ -0,0 +1,285 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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.
//
//////////////////////////////////////////////////////////////////////////////
#ifdef _MSC_VER
#pragma warning (disable : 4512)
#pragma warning (disable : 4267)
#pragma warning (disable : 4244)
#endif
#define BOOST_CONTAINER_VECTOR_ALLOC_STATS
#include <boost/container/allocator.hpp>
#include <vector>
#include <boost/container/vector.hpp>
#include <memory> //std::allocator
#include <iostream> //std::cout, std::endl
#include <cstring> //std::strcmp
#include <boost/timer/timer.hpp>
using boost::timer::cpu_timer;
using boost::timer::cpu_times;
using boost::timer::nanosecond_type;
namespace bc = boost::container;
typedef std::allocator<int> StdAllocator;
typedef bc::allocator<int, 2, bc::expand_bwd | bc::expand_fwd> AllocatorPlusV2Mask;
typedef bc::allocator<int, 2> AllocatorPlusV2;
typedef bc::allocator<int, 1> AllocatorPlusV1;
template<class Allocator> struct get_allocator_name;
template<> struct get_allocator_name<StdAllocator>
{ static const char *get() { return "StdAllocator"; } };
template<> struct get_allocator_name<AllocatorPlusV2Mask>
{ static const char *get() { return "AllocatorPlusV2Mask"; } };
template<> struct get_allocator_name<AllocatorPlusV2>
{ static const char *get() { return "AllocatorPlusV2"; } };
template<> struct get_allocator_name<AllocatorPlusV1>
{ static const char *get() { return "AllocatorPlusV1"; } };
#if defined(BOOST_CONTAINER_VECTOR_ALLOC_STATS)
//
// stats_traits;
//
template<template<class, class> class Vector>
struct stats_traits;
template<>
struct stats_traits<std::vector>
{
template<class T, class A>
static void reset_alloc_stats(std::vector<T, A> &)
{}
template<class T, class A>
static std::size_t get_num_alloc(std::vector<T, A> &)
{ return 0; }
template<class T, class A>
static std::size_t get_num_expand(std::vector<T, A> &)
{ return 0; }
};
template<>
struct stats_traits<bc::vector>
{
template<class T, class A>
static void reset_alloc_stats(bc::vector<T, A> &v)
{ v.reset_alloc_stats(); }
template<class T, class A>
static std::size_t get_num_alloc(bc::vector<T, A> &v)
{ return v.num_alloc; }
template<class T, class A>
static std::size_t get_num_expand(bc::vector<T, A> &v)
{ return v.num_expand_fwd; }
};
#endif //BOOST_CONTAINER_VECTOR_ALLOC_STATS
template<template<class, class> class Vector> struct get_container_name;
template<> struct get_container_name<std::vector>
{ static const char *get() { return "StdVector"; } };
template<> struct get_container_name<bc::vector>
{ static const char *get() { return "BoostContainerVector"; } };
class MyInt
{
int int_;
public:
explicit MyInt(int i = 0)
: int_(i)
{}
MyInt(const MyInt &other)
: int_(other.int_)
{}
MyInt & operator=(const MyInt &other)
{
int_ = other.int_;
return *this;
}
~MyInt()
{
int_ = 0;
}
};
template<class Allocator, template <class, class> class Vector>
void vector_test_template(unsigned int num_iterations, unsigned int num_elements, bool csv_output)
{
typedef typename Allocator::template rebind<MyInt>::other IntAllocator;
unsigned int numalloc = 0, numexpand = 0;
#ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
typedef stats_traits<Vector> stats_traits_t;
#endif
cpu_timer timer;
timer.resume();
unsigned int capacity = 0;
for(unsigned int r = 0; r != num_iterations; ++r){
Vector<MyInt, IntAllocator> v;
#ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
stats_traits_t::reset_alloc_stats(v);
#endif
//v.reserve(num_elements);
//MyInt a[3];
/*
for(unsigned int e = 0; e != num_elements/3; ++e){
v.insert(v.end(), &a[0], &a[0]+3);
}*/
/*
for(unsigned int e = 0; e != num_elements/3; ++e){
v.insert(v.end(), 3, MyInt(e));
}*/
/*
for(unsigned int e = 0; e != num_elements/3; ++e){
v.insert(v.empty() ? v.end() : --v.end(), &a[0], &a[0]+3);
}*/
/*
for(unsigned int e = 0; e != num_elements/3; ++e){
v.insert(v.empty() ? v.end() : --v.end(), 3, MyInt(e));
}*/
/*
for(unsigned int e = 0; e != num_elements/3; ++e){
v.insert(v.size() >= 3 ? v.end()-3 : v.begin(), &a[0], &a[0]+3);
}*/
/*
for(unsigned int e = 0; e != num_elements/3; ++e){
v.insert(v.size() >= 3 ? v.end()-3 : v.begin(), 3, MyInt(e));
}*/
/*
for(unsigned int e = 0; e != num_elements; ++e){
v.insert(v.end(), MyInt(e));
}*/
/*
for(unsigned int e = 0; e != num_elements; ++e){
v.insert(v.empty() ? v.end() : --v.end(), MyInt(e));
}*/
for(unsigned int e = 0; e != num_elements; ++e){
v.push_back(MyInt(e));
}
#ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
numalloc += stats_traits_t::get_num_alloc(v);
numexpand += stats_traits_t::get_num_expand(v);
#endif
capacity = static_cast<unsigned int>(v.capacity());
}
timer.stop();
nanosecond_type nseconds = timer.elapsed().wall;
if(csv_output){
std::cout << get_allocator_name<Allocator>::get()
<< ";"
<< num_iterations
<< ";"
<< num_elements
<< ";"
<< capacity
<< ";"
<< float(nseconds)/(num_iterations*num_elements)
<< ";"
<< (float(numalloc) + float(numexpand))/num_iterations
<< ";"
<< float(numalloc)/num_iterations
<< ";"
<< float(numexpand)/num_iterations
<< std::endl;
}
else{
std::cout << std::endl
<< "Allocator: " << get_allocator_name<Allocator>::get()
<< std::endl
<< " push_back ns: "
<< float(nseconds)/(num_iterations*num_elements)
<< std::endl
<< " capacity - alloc calls (new/expand): "
<< (unsigned int)capacity << " - "
<< (float(numalloc) + float(numexpand))/num_iterations
<< "(" << float(numalloc)/num_iterations << "/" << float(numexpand)/num_iterations << ")"
<< std::endl << std::endl;
}
boost_cont_trim(0);
}
void print_header()
{
std::cout << "Allocator" << ";" << "Iterations" << ";" << "Size" << ";"
<< "Capacity" << ";" << "push_back(ns)" << ";" << "Allocator calls" << ";"
<< "New allocations" << ";" << "Fwd expansions" << std::endl;
}
int main(int argc, const char *argv[])
{
#define SINGLE_TEST
#ifndef SINGLE_TEST
#ifdef NDEBUG
unsigned int numit [] = { 10000, 100000, 1000000, 10000000 };
#else
unsigned int numit [] = { 100, 1000, 10000, 100000 };
#endif
unsigned int numele [] = { 10000, 1000, 100, 10 };
#else
#ifdef NDEBUG
std::size_t numit [] = { 10000 };
#else
std::size_t numit [] = { 100 };
#endif
std::size_t numele [] = { 10000 };
#endif
bool csv_output = argc == 2 && (strcmp(argv[1], "--csv-output") == 0);
if(csv_output){
print_header();
for(unsigned int i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
vector_test_template<StdAllocator, bc::vector>(numit[i], numele[i], csv_output);
}
for(unsigned int i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
vector_test_template<AllocatorPlusV1, bc::vector>(numit[i], numele[i], csv_output);
}
for(unsigned int i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
vector_test_template<AllocatorPlusV2Mask, bc::vector>(numit[i], numele[i], csv_output);
}
for(unsigned int i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
vector_test_template<AllocatorPlusV2, bc::vector>(numit[i], numele[i], csv_output);
}
}
else{
for(unsigned int i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
std::cout << "\n ----------------------------------- \n"
<< " Iterations/Elements: " << numit[i] << "/" << numele[i]
<< "\n ----------------------------------- \n";
vector_test_template<StdAllocator, std::vector>(numit[i], numele[i], csv_output);
vector_test_template<StdAllocator, bc::vector>(numit[i], numele[i], csv_output);
vector_test_template<AllocatorPlusV1, bc::vector>(numit[i], numele[i], csv_output);
vector_test_template<AllocatorPlusV2Mask, bc::vector>(numit[i], numele[i], csv_output);
vector_test_template<AllocatorPlusV2, bc::vector>(numit[i], numele[i], csv_output);
}
}
return 0;
}

View File

@@ -0,0 +1,168 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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.
//
//////////////////////////////////////////////////////////////////////////////
#ifdef _MSC_VER
#pragma warning (disable : 4512)
#endif
#include <boost/container/allocator.hpp>
#define BOOST_CONTAINER_VECTOR_ALLOC_STATS
#include <boost/container/vector.hpp>
#undef BOOST_CONTAINER_VECTOR_ALLOC_STATS
#include <memory> //std::allocator
#include <iostream> //std::cout, std::endl
#include <boost/timer/timer.hpp>
using boost::timer::cpu_timer;
using boost::timer::cpu_times;
using boost::timer::nanosecond_type;
namespace bc = boost::container;
typedef std::allocator<int> StdAllocator;
typedef bc::allocator<int, 2> AllocatorPlusV2;
typedef bc::allocator<int, 1> AllocatorPlusV1;
template<class Allocator> struct get_allocator_name;
template<> struct get_allocator_name<StdAllocator>
{ static const char *get() { return "StdAllocator"; } };
template<> struct get_allocator_name<AllocatorPlusV2>
{ static const char *get() { return "AllocatorPlusV2"; } };
template<> struct get_allocator_name<AllocatorPlusV1>
{ static const char *get() { return "AllocatorPlusV1"; } };
class MyInt
{
int int_;
public:
MyInt(int i = 0) : int_(i){}
MyInt(const MyInt &other)
: int_(other.int_)
{}
MyInt & operator=(const MyInt &other)
{
int_ = other.int_;
return *this;
}
};
void print_header()
{
std::cout << "Allocator" << ";" << "Iterations" << ";" << "Size" << ";"
<< "num_shrink" << ";" << "shrink_to_fit(ns)" << std::endl;
}
template<class Allocator>
void vector_test_template(unsigned int num_iterations, unsigned int num_elements, bool csv_output)
{
typedef typename Allocator::template rebind<MyInt>::other IntAllocator;
unsigned int capacity = 0;
const std::size_t Step = 5;
unsigned int num_shrink = 0;
(void)capacity;
cpu_timer timer;
timer.resume();
#ifndef NDEBUG
typedef bc::container_detail::integral_constant
<unsigned, bc::container_detail::version<Allocator>::value> alloc_version;
#endif
for(unsigned int r = 0; r != num_iterations; ++r){
bc::vector<MyInt, IntAllocator> v(num_elements);
v.reset_alloc_stats();
num_shrink = 0;
for(unsigned int e = num_elements; e != 0; e -= Step){
v.erase(v.end() - Step, v.end());
v.shrink_to_fit();
assert( (alloc_version::value != 2) || (e == Step) || (v.num_shrink > num_shrink) );
num_shrink = v.num_shrink;
}
assert(v.empty());
assert(0 == v.capacity());
}
timer.stop();
nanosecond_type nseconds = timer.elapsed().wall;
if(csv_output){
std::cout << get_allocator_name<Allocator>::get()
<< ";"
<< num_iterations
<< ";"
<< num_elements
<< ";"
<< num_shrink
<< ";"
<< float(nseconds)/(num_iterations*num_elements)
<< std::endl;
}
else{
std::cout << std::endl
<< "Allocator: " << get_allocator_name<Allocator>::get()
<< std::endl
<< " num_shrink: " << num_shrink
<< std::endl
<< " shrink_to_fit ns: "
<< float(nseconds)/(num_iterations*num_elements)
<< std::endl << std::endl;
}
boost_cont_trim(0);
}
int main(int argc, const char *argv[])
{
#define SINGLE_TEST
#ifndef SINGLE_TEST
unsigned int numit [] = { 100, 1000, 10000 };
unsigned int numele [] = { 10000, 2000, 500 };
#else
unsigned int numit [] = { 500 };
unsigned int numele [] = { 2000 };
#endif
bool csv_output = argc == 2 && (strcmp(argv[1], "--csv-output") == 0);
if(csv_output){
print_header();
for(unsigned int i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
vector_test_template<StdAllocator>(numit[i], numele[i], csv_output);
}
for(unsigned int i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
vector_test_template<AllocatorPlusV1>(numit[i], numele[i], csv_output);
}
for(unsigned int i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
vector_test_template<AllocatorPlusV2>(numit[i], numele[i], csv_output);
}
}
else{
for(unsigned int i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
std::cout << "\n ----------------------------------- \n"
<< " Iterations/Elements: " << numit[i] << "/" << numele[i]
<< "\n ----------------------------------- \n";
vector_test_template<StdAllocator>(numit[i], numele[i], csv_output);
vector_test_template<AllocatorPlusV1>(numit[i], numele[i], csv_output);
vector_test_template<AllocatorPlusV2>(numit[i], numele[i], csv_output);
}
}
return 0;
}

View File

@@ -0,0 +1,287 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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.
//
//////////////////////////////////////////////////////////////////////////////
#ifdef _MSC_VER
#pragma warning (disable : 4512)
#pragma warning (disable : 4541)
#pragma warning (disable : 4673)
#pragma warning (disable : 4671)
#pragma warning (disable : 4244)
#endif
#include <memory> //std::allocator
#include <iostream> //std::cout, std::endl
#include <vector> //std::vector
#include <cstddef> //std::size_t
#include <boost/container/allocator.hpp>
#include <boost/container/adaptive_pool.hpp>
#include <boost/container/stable_vector.hpp>
#include <boost/container/vector.hpp>
#include <boost/timer/timer.hpp>
using boost::timer::cpu_timer;
using boost::timer::cpu_times;
using boost::timer::nanosecond_type;
namespace bc = boost::container;
typedef std::allocator<int> StdAllocator;
typedef bc::allocator<int, 1> AllocatorPlusV1;
typedef bc::allocator<int, 2> AllocatorPlusV2;
typedef bc::adaptive_pool
< int
, bc::ADP_nodes_per_block
, 0//bc::ADP_max_free_blocks
, 2
, 2> AdPool2PercentV2;
template<class Allocator> struct get_allocator_name;
template<> struct get_allocator_name<StdAllocator>
{ static const char *get() { return "StdAllocator"; } };
template<> struct get_allocator_name<AllocatorPlusV1>
{ static const char *get() { return "AllocatorPlusV1"; } };
template<> struct get_allocator_name<AllocatorPlusV2>
{ static const char *get() { return "AllocatorPlusV2"; } };
template<> struct get_allocator_name<AdPool2PercentV2>
{ static const char *get() { return "AdPool2PercentV2"; } };
class MyInt
{
int int_;
public:
MyInt(int i = 0) : int_(i){}
MyInt(const MyInt &other)
: int_(other.int_)
{}
MyInt & operator=(const MyInt &other)
{
int_ = other.int_;
return *this;
}
};
template<class Allocator>
struct get_vector
{
typedef bc::vector
<MyInt, typename Allocator::template rebind<MyInt>::other> type;
static const char *vector_name()
{
return "vector<MyInt>";
}
};
template<class Allocator>
struct get_stable_vector
{
typedef bc::stable_vector
<MyInt, typename Allocator::template rebind<MyInt>::other> type;
static const char *vector_name()
{
return "stable_vector<MyInt>";
}
};
template<template<class> class GetContainer, class Allocator>
void stable_vector_test_template(unsigned int num_iterations, unsigned int num_elements, bool csv_output)
{
typedef typename GetContainer<Allocator>::type vector_type;
//std::size_t top_capacity = 0;
nanosecond_type nseconds;
{
{
vector_type l;
cpu_timer timer;
timer.resume();
for(unsigned int r = 0; r != num_iterations; ++r){
l.insert(l.end(), num_elements, MyInt(r));
}
timer.stop();
nseconds = timer.elapsed().wall;
if(csv_output){
std::cout << get_allocator_name<Allocator>::get()
<< ";"
<< GetContainer<Allocator>::vector_name()
<< ";"
<< num_iterations
<< ";"
<< num_elements
<< ";"
<< float(nseconds)/(num_iterations*num_elements)
<< ";";
}
else{
std::cout << "Allocator: " << get_allocator_name<Allocator>::get()
<< '\t'
<< GetContainer<Allocator>::vector_name()
<< std::endl
<< " allocation ns: "
<< float(nseconds)/(num_iterations*num_elements);
}
// top_capacity = l.capacity();
//Now preprocess ranges to erase
std::vector<typename vector_type::iterator> ranges_to_erase;
ranges_to_erase.push_back(l.begin());
for(unsigned int r = 0; r != num_iterations; ++r){
typename vector_type::iterator next_pos(ranges_to_erase[r]);
std::size_t n = num_elements;
while(n--){ ++next_pos; }
ranges_to_erase.push_back(next_pos);
}
//Measure range erasure function
timer.stop();
timer.start();
for(unsigned int r = 0; r != num_iterations; ++r){
std::size_t init_pos = (num_iterations-1)-r;
l.erase(ranges_to_erase[init_pos], l.end());
}
timer.stop();
nseconds = timer.elapsed().wall;
assert(l.empty());
}
}
if(csv_output){
std::cout << float(nseconds)/(num_iterations*num_elements)
<< std::endl;
}
else{
std::cout << '\t'
<< " deallocation ns: "
<< float(nseconds)/(num_iterations*num_elements)/*
<< std::endl
<< " max capacity: "
<< static_cast<unsigned int>(top_capacity)
<< std::endl
<< " remaining cap. "
<< static_cast<unsigned int>(top_capacity - num_iterations*num_elements)
<< " (" << (float(top_capacity)/float(num_iterations*num_elements) - 1)*100 << " %)"*/
<< std::endl << std::endl;
}
assert(boost_cont_all_deallocated());
boost_cont_trim(0);
}
void print_header()
{
std::cout << "Allocator" << ";" << "Iterations" << ";" << "Size" << ";"
<< "Insertion time(ns)" << ";" << "Erasure time(ns)" << ";"
<< std::endl;
}
void stable_vector_operations()
{
{
bc::stable_vector<int> a(bc::stable_vector<int>::size_type(5), 4);
bc::stable_vector<int> b(a);
bc::stable_vector<int> c(a.cbegin(), a.cend());
b.insert(b.cend(), 0);
c.pop_back();
a.assign(b.cbegin(), b.cend());
a.assign(c.cbegin(), c.cend());
a.assign(1, 2);
}
{
typedef bc::stable_vector<int, std::allocator<int> > stable_vector_t;
stable_vector_t a(bc::stable_vector<int>::size_type(5), 4);
stable_vector_t b(a);
stable_vector_t c(a.cbegin(), a.cend());
b.insert(b.cend(), 0);
c.pop_back();
assert(static_cast<std::size_t>(a.end() - a.begin()) == a.size());
a.assign(b.cbegin(), b.cend());
assert(static_cast<std::size_t>(a.end() - a.begin()) == a.size());
a.assign(c.cbegin(), c.cend());
assert(static_cast<std::size_t>(a.end() - a.begin()) == a.size());
a.assign(1, 2);
assert(static_cast<std::size_t>(a.end() - a.begin()) == a.size());
a.reserve(100);
assert(static_cast<std::size_t>(a.end() - a.begin()) == a.size());
}
}
int main(int argc, const char *argv[])
{
#define SINGLE_TEST
#ifndef SINGLE_TEST
#ifdef NDEBUG
unsigned int numit [] = { 400, 4000, 40000, 400000 };
#else
unsigned int numit [] = { 4, 40, 400, 4000 };
#endif
unsigned int numele [] = { 10000, 1000, 100, 10 };
#else
#ifdef NDEBUG
unsigned int numit [] = { 400 };
#else
unsigned int numit [] = { 4 };
#endif
unsigned int numele [] = { 10000 };
#endif
//Warning: range erasure is buggy. Vector iterators are not stable, so it is not
//possible to cache iterators, but indexes!!!
bool csv_output = argc == 2 && (strcmp(argv[1], "--csv-output") == 0);
if(csv_output){
print_header();
for(unsigned int i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
stable_vector_test_template<get_stable_vector, StdAllocator>(numit[i], numele[i], csv_output);
}
for(unsigned int i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
stable_vector_test_template<get_vector, StdAllocator>(numit[i], numele[i], csv_output);
}
for(unsigned int i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
stable_vector_test_template<get_stable_vector, AllocatorPlusV1>(numit[i], numele[i], csv_output);
}
for(unsigned int i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
stable_vector_test_template<get_vector, AllocatorPlusV1>(numit[i], numele[i], csv_output);
}
for(unsigned int i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
stable_vector_test_template<get_stable_vector, AllocatorPlusV2>(numit[i], numele[i], csv_output);
}
for(unsigned int i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
stable_vector_test_template<get_vector, AllocatorPlusV2>(numit[i], numele[i], csv_output);
}
for(unsigned int i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
stable_vector_test_template<get_stable_vector, AdPool2PercentV2>(numit[i], numele[i], csv_output);
}
for(unsigned int i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
stable_vector_test_template<get_vector, AdPool2PercentV2>(numit[i], numele[i], csv_output);
}
}
else{
for(unsigned int i = 0; i < sizeof(numele)/sizeof(numele[0]); ++i){
std::cout << "\n ----------------------------------- \n"
<< " Iterations/Elements: " << numit[i] << "/" << numele[i]
<< "\n ----------------------------------- \n";
stable_vector_test_template<get_stable_vector, StdAllocator>(numit[i], numele[i], csv_output);
stable_vector_test_template<get_vector, StdAllocator>(numit[i], numele[i], csv_output);
stable_vector_test_template<get_stable_vector, AllocatorPlusV1>(numit[i], numele[i], csv_output);
stable_vector_test_template<get_vector, AllocatorPlusV1>(numit[i], numele[i], csv_output);
stable_vector_test_template<get_stable_vector, AllocatorPlusV2>(numit[i], numele[i], csv_output);
stable_vector_test_template<get_vector, AllocatorPlusV2>(numit[i], numele[i], csv_output);
stable_vector_test_template<get_stable_vector, AdPool2PercentV2>(numit[i], numele[i], csv_output);
stable_vector_test_template<get_vector, AdPool2PercentV2>(numit[i], numele[i], csv_output);
}
}
return 0;
}

View File

@@ -0,0 +1,29 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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.
//
//////////////////////////////////////////////////////////////////////////////
#include "boost/container/set.hpp"
#include "boost/container/flat_set.hpp"
#include "bench_set.hpp"
int main()
{
using namespace boost::container;
fill_range_ints();
fill_range_strings();
//flat_set vs set
launch_tests< flat_multiset<int> , multiset<int> >
("flat_multiset<int>", "multiset<int>");
launch_tests< flat_multiset<string> , multiset<string> >
("flat_multiset<string>", "multiset<string>");
return 0;
}

29
bench/bench_flat_set.cpp Normal file
View File

@@ -0,0 +1,29 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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.
//
//////////////////////////////////////////////////////////////////////////////
#include "boost/container/set.hpp"
#include "boost/container/flat_set.hpp"
#include "bench_set.hpp"
int main()
{
using namespace boost::container;
fill_range_ints();
fill_range_strings();
//flat_set vs set
launch_tests< flat_set<int> , set<int> >
("flat_set<int>", "set<int>");
launch_tests< flat_set<string> , set<string> >
("flat_set<string>", "set<string>");
return 0;
}

View File

@@ -9,340 +9,27 @@
//////////////////////////////////////////////////////////////////////////////
#include "boost/container/set.hpp"
#include "boost/container/flat_set.hpp"
#include <set>
#include <vector>
#include <iostream>
#include <boost/timer/timer.hpp>
#include <algorithm>
#include <exception>
using boost::timer::cpu_timer;
using boost::timer::cpu_times;
using boost::timer::nanosecond_type;
#ifdef NDEBUG
static const std::size_t N = 5000;
#else
static const std::size_t N = 500;
#endif
void compare_times(cpu_times time_numerator, cpu_times time_denominator){
std::cout << "----------------------------------------------" << '\n';
std::cout << " wall = " << ((double)time_numerator.wall/(double)time_denominator.wall) << std::endl;
std::cout << "----------------------------------------------" << '\n' << std::endl;
}
std::vector<int> sorted_unique_range;
std::vector<int> sorted_range;
std::vector<int> random_unique_range;
std::vector<int> random_range;
void fill_ranges()
{
sorted_unique_range.resize(N);
sorted_range.resize(N);
random_unique_range.resize(N);
random_range.resize(N);
std::srand (0);
//random_range
std::generate(random_unique_range.begin(), random_unique_range.end(), std::rand);
random_unique_range.erase(std::unique(random_unique_range.begin(), random_unique_range.end()), random_unique_range.end());
//random_range
random_range = random_unique_range;
random_range.insert(random_range.end(), random_unique_range.begin(), random_unique_range.end());
//sorted_unique_range
for(std::size_t i = 0, max = sorted_unique_range.size(); i != max; ++i){
sorted_unique_range[i] = static_cast<int>(i);
}
//sorted_range
sorted_range = sorted_unique_range;
sorted_range.insert(sorted_range.end(), sorted_unique_range.begin(), sorted_unique_range.end());
std::sort(sorted_range.begin(), sorted_range.end());
}
template<typename T>
cpu_times construct_time()
{
cpu_timer sur_timer, sr_timer, rur_timer, rr_timer, copy_timer, assign_timer, destroy_timer;
//sur_timer.stop();sr_timer.stop();rur_timer.stop();rr_timer.stop();destroy_timer.stop();
cpu_timer total_time;
total_time.resume();
for(std::size_t i = 0; i != N; ++i){
{
sur_timer.resume();
T t(sorted_unique_range.begin(), sorted_unique_range.end());
sur_timer.stop();
}
{
sr_timer.resume();
T t(sorted_range.begin(), sorted_range.end());
sr_timer.stop();
copy_timer.resume();
T taux(t);
copy_timer.stop();
assign_timer.resume();
t = taux;;
assign_timer.stop();
}
{
rur_timer.resume();
T t(random_unique_range.begin(), random_unique_range.end());
rur_timer.stop();
}
{
rr_timer.resume();
T t(random_range.begin(), random_range.end());
rr_timer.stop();
destroy_timer.resume();
}
destroy_timer.stop();
}
total_time.stop();
std::cout << " Construct sorted_unique_range " << boost::timer::format(sur_timer.elapsed(), boost::timer::default_places, "%ws wall\n");
std::cout << " Construct sorted_range " << boost::timer::format(sr_timer.elapsed(), boost::timer::default_places, "%ws wall\n");
std::cout << " Copy sorted range " << boost::timer::format(copy_timer.elapsed(), boost::timer::default_places, "%ws wall\n");
std::cout << " Assign sorted range " << boost::timer::format(assign_timer.elapsed(), boost::timer::default_places, "%ws wall\n");
std::cout << " Construct random_unique_range " << boost::timer::format(rur_timer.elapsed(), boost::timer::default_places, "%ws wall\n");
std::cout << " Construct random_range " << boost::timer::format(rr_timer.elapsed(), boost::timer::default_places, "%ws wall\n");
std::cout << " Destroy " << boost::timer::format(destroy_timer.elapsed(), boost::timer::default_places, "%ws wall\n");
std::cout << " Total time = " << boost::timer::format(total_time.elapsed(), boost::timer::default_places, "%ws wall\n") << std::endl;
return total_time.elapsed();
}
template<typename T>
cpu_times insert_time()
{
cpu_timer sur_timer,sr_timer,rur_timer,rr_timer,destroy_timer;
sur_timer.stop();sr_timer.stop();rur_timer.stop();rr_timer.stop();
cpu_timer total_time;
total_time.resume();
for(std::size_t i = 0; i != N; ++i){
{
sur_timer.resume();
T t;
t.insert(sorted_unique_range.begin(), sorted_unique_range.end());
sur_timer.stop();
}
{
sr_timer.resume();
T t;
t.insert(sorted_range.begin(), sorted_range.end());
sr_timer.stop();
}
{
rur_timer.resume();
T t;
t.insert(random_unique_range.begin(), random_unique_range.end());
rur_timer.stop();
}
{
rr_timer.resume();
T t;
t.insert(random_range.begin(), random_range.end());
rr_timer.stop();
}
}
total_time.stop();
std::cout << " Insert sorted_unique_range " << boost::timer::format(sur_timer.elapsed(), boost::timer::default_places, "%ws wall\n");
std::cout << " Insert sorted_range " << boost::timer::format(sr_timer.elapsed(), boost::timer::default_places, "%ws wall\n");
std::cout << " Insert random_unique_range " << boost::timer::format(rur_timer.elapsed(), boost::timer::default_places, "%ws wall\n");
std::cout << " Insert random_range " << boost::timer::format(rr_timer.elapsed(), boost::timer::default_places, "%ws wall\n");
std::cout << " Total time = " << boost::timer::format(total_time.elapsed(), boost::timer::default_places, "%ws wall\n") << std::endl;
return total_time.elapsed();
}
template<typename T>
cpu_times search_time()
{
cpu_timer find_timer, lower_timer, upper_timer, equal_range_timer, count_timer;
T t(sorted_unique_range.begin(), sorted_unique_range.end());
cpu_timer total_time;
total_time.resume();
for(std::size_t i = 0; i != N; ++i){
//Find
{
std::size_t found = 0;
find_timer.resume();
for(std::size_t i = 0, max = sorted_unique_range.size(); i != max; ++i){
found += static_cast<std::size_t>(t.end() != t.find(sorted_unique_range[i]));
}
for(std::size_t i = 0, max = sorted_unique_range.size(); i != max; ++i){
found += static_cast<std::size_t>(t.end() != t.find(sorted_unique_range[i]));
}
find_timer.stop();
if(found/2 != t.size()){
std::cout << "ERROR! all elements not found" << std::endl;
}
}
//Lower
{
std::size_t found = 0;
lower_timer.resume();
for(std::size_t i = 0, max = sorted_unique_range.size(); i != max; ++i){
found += static_cast<std::size_t>(t.end() != t.lower_bound(sorted_unique_range[i]));
}
for(std::size_t i = 0, max = sorted_unique_range.size(); i != max; ++i){
found += static_cast<std::size_t>(t.end() != t.lower_bound(sorted_unique_range[i]));
}
lower_timer.stop();
if(found/2 != t.size()){
std::cout << "ERROR! all elements not found" << std::endl;
}
}
//Upper
{
std::size_t found = 0;
upper_timer.resume();
for(std::size_t i = 0, max = sorted_unique_range.size(); i != max; ++i){
found += static_cast<std::size_t>(t.end() != t.upper_bound(sorted_unique_range[i]));
}
for(std::size_t i = 0, max = sorted_unique_range.size(); i != max; ++i){
found += static_cast<std::size_t>(t.end() != t.upper_bound(sorted_unique_range[i]));
}
upper_timer.stop();
if(found/2 != (t.size()-1)){
std::cout << "ERROR! all elements not found" << std::endl;
}
}
//Equal
{
std::size_t found = 0;
std::pair<typename T::iterator,typename T::iterator> ret;
equal_range_timer.resume();
for(std::size_t i = 0, max = sorted_unique_range.size(); i != max; ++i){
ret = t.equal_range(sorted_unique_range[i]);
found += static_cast<std::size_t>(ret.first != ret.second);
}
for(std::size_t i = 0, max = sorted_unique_range.size(); i != max; ++i){
ret = t.equal_range(sorted_unique_range[i]);
found += static_cast<std::size_t>(ret.first != ret.second);
}
equal_range_timer.stop();
if(found/2 != t.size()){
std::cout << "ERROR! all elements not found" << std::endl;
}
}
//Count
{
std::size_t found = 0;
std::pair<typename T::iterator,typename T::iterator> ret;
count_timer.resume();
for(std::size_t i = 0, max = sorted_unique_range.size(); i != max; ++i){
found += static_cast<std::size_t>(t.count(sorted_unique_range[i]));
}
for(std::size_t i = 0, max = sorted_unique_range.size(); i != max; ++i){
found += static_cast<std::size_t>(t.count(sorted_unique_range[i]));
}
count_timer.stop();
if(found/2 != t.size()){
std::cout << "ERROR! all elements not found" << std::endl;
}
}
}
total_time.stop();
std::cout << " Find " << boost::timer::format(find_timer.elapsed(), boost::timer::default_places, "%ws wall\n");
std::cout << " Lower Bound " << boost::timer::format(lower_timer.elapsed(), boost::timer::default_places, "%ws wall\n");
std::cout << " Upper Bound " << boost::timer::format(upper_timer.elapsed(), boost::timer::default_places, "%ws wall\n");
std::cout << " Equal Range " << boost::timer::format(equal_range_timer.elapsed(), boost::timer::default_places, "%ws wall\n");
std::cout << " Count " << boost::timer::format(count_timer.elapsed(), boost::timer::default_places, "%ws wall\n");
std::cout << " Total time = " << boost::timer::format(total_time.elapsed(), boost::timer::default_places, "%ws wall\n") << std::endl;
return total_time.elapsed();
}
template<typename T>
void extensions_time()
{
cpu_timer sur_timer,sur_opt_timer;
sur_timer.stop();sur_opt_timer.stop();
for(std::size_t i = 0; i != N; ++i){
{
sur_timer.resume();
T t(sorted_unique_range.begin(), sorted_unique_range.end());
sur_timer.stop();
}
{
sur_opt_timer.resume();
T t(boost::container::ordered_unique_range, sorted_unique_range.begin(), sorted_unique_range.end());
sur_opt_timer.stop();
}
}
std::cout << " Construct sorted_unique_range " << boost::timer::format(sur_timer.elapsed(), boost::timer::default_places, "%ws wall\n");
std::cout << " Construct sorted_unique_range (extension) " << boost::timer::format(sur_opt_timer.elapsed(), boost::timer::default_places, "%ws wall\n");
std::cout << "Total time (Extension/Standard):\n";
compare_times(sur_opt_timer.elapsed(), sur_timer.elapsed());
}
template<class BoostClass, class StdClass>
void launch_tests(const char *BoostContName, const char *StdContName)
{
try {
fill_ranges();
{
std::cout << "Construct benchmark:" << BoostContName << std::endl;
cpu_times boost_set_time = construct_time< BoostClass >();
std::cout << "Construct benchmark:" << StdContName << std::endl;
cpu_times std_set_time = construct_time< StdClass >();
std::cout << "Total time (" << BoostContName << "/" << StdContName << "):\n";
compare_times(boost_set_time, std_set_time);
}
{
std::cout << "Insert benchmark:" << BoostContName << std::endl;
cpu_times boost_set_time = insert_time< BoostClass >();
std::cout << "Insert benchmark:" << StdContName << std::endl;
cpu_times std_set_time = insert_time< StdClass >();
std::cout << "Total time (" << BoostContName << "/" << StdContName << "):\n";
compare_times(boost_set_time, std_set_time);
}
{
std::cout << "Search benchmark:" << BoostContName << std::endl;
cpu_times boost_set_time = search_time< BoostClass >();
std::cout << "Search benchmark:" << StdContName << std::endl;
cpu_times std_set_time = search_time< StdClass >();
std::cout << "Total time (" << BoostContName << "/" << StdContName << "):\n";
compare_times(boost_set_time, std_set_time);
}
{
std::cout << "Extensions benchmark:" << BoostContName << std::endl;
extensions_time< BoostClass >();
}
}catch(std::exception e){
std::cout << e.what();
}
}
#include "bench_set.hpp"
int main()
{
using namespace boost::container;
fill_range_ints();
fill_range_strings();
//set vs std::set
launch_tests< boost::container::set<int> , std::set<int> >
("boost::container::set<int>", "std::set<int>");/*
//multiset vs std::set
launch_tests< boost::container::multiset<int> , std::multiset<int> >
("boost::container::multiset<int>", "std::multiset<int>");*/
//flat_set vs set
//launch_tests< boost::container::flat_set<int> , boost::container::set<int> >
//("boost::container::flat_set<int>", "boost::container::set<int>");
//flat_multiset vs multiset
//launch_tests< boost::container::flat_multiset<int> , boost::container::multiset<int> >
//("boost::container::flat_multiset<int>", "boost::container::multiset<int>");
return 1;
launch_tests< set<int> , std::set<int> >
("set<int>", "std::set<int>");
launch_tests< set<string> , std::set<string> >
("set<string>", "std::set<string>");
//set(sizeopt) vs set(!sizeopt)
launch_tests< set<int>, set<int, std::less<int>, std::allocator<int>, tree_assoc_options< optimize_size<false> >::type > >
("set<int>(sizeopt=true)", "set<int>(sizeopt=false)");
launch_tests< set<string>, set<string, std::less<string>, std::allocator<string>, tree_assoc_options< optimize_size<false> >::type > >
("set<string>(sizeopt=true)", "set<string>(sizeopt=false)");
return 0;
}

462
bench/bench_set.hpp Normal file
View File

@@ -0,0 +1,462 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_BENCH_BENCH_SET_HPP
#define BOOST_CONTAINER_BENCH_BENCH_SET_HPP
#include <iostream>
#include <boost/timer/timer.hpp>
#include <algorithm>
#include <exception>
#include <sstream>
#include <iomanip>
#include <boost/container/vector.hpp>
#include <boost/container/string.hpp>
using boost::timer::cpu_timer;
using boost::timer::cpu_times;
using boost::timer::nanosecond_type;
using namespace boost::container;
#ifdef NDEBUG
static const std::size_t NElements = 1000;
#else
static const std::size_t NElements = 100;
#endif
#ifdef NDEBUG
static const std::size_t NIter = 500;
#else
static const std::size_t NIter = 50;
#endif
void compare_times(cpu_times time_numerator, cpu_times time_denominator){
std::cout << ((double)time_numerator.wall/(double)time_denominator.wall) << std::endl;
std::cout << "----------------------------------------------" << '\n' << std::endl;
}
vector<int> sorted_unique_range_int;
vector<int> sorted_range_int;
vector<int> random_unique_range_int;
vector<int> random_range_int;
void fill_range_ints()
{
//sorted_unique_range_int
sorted_unique_range_int.resize(NElements);
for(std::size_t i = 0, max = sorted_unique_range_int.size(); i != max; ++i){
sorted_unique_range_int[i] = static_cast<int>(i);
}
//sorted_range_int
sorted_range_int = sorted_unique_range_int;
sorted_range_int.insert(sorted_range_int.end(), sorted_unique_range_int.begin(), sorted_unique_range_int.end());
std::sort(sorted_range_int.begin(), sorted_range_int.end());
//random_range_int
std::srand(0);
random_range_int.assign(sorted_range_int.begin(), sorted_range_int.end());
std::random_shuffle(random_range_int.begin(), random_range_int.end());
//random_unique_range_int
std::srand(0);
random_unique_range_int.assign(sorted_unique_range_int.begin(), sorted_unique_range_int.end());
std::random_shuffle(random_unique_range_int.begin(), random_unique_range_int.end());
}
vector<string> sorted_unique_range_string;
vector<string> sorted_range_string;
vector<string> random_unique_range_string;
vector<string> random_range_string;
void fill_range_strings()
{
//sorted_unique_range_int
sorted_unique_range_string.resize(NElements);
for(std::size_t i = 0, max = sorted_unique_range_string.size(); i != max; ++i){
std::stringstream sstr;
sstr << std::setfill('0') << std::setw(10) << i;
sorted_unique_range_string[i] = "really_long_long_prefix_to_ssb_and_increase_comparison_costs_";
const std::string &s = sstr.str();
sorted_unique_range_string[i].append(s.begin(), s.end());
}
//sorted_range_string
sorted_range_string = sorted_unique_range_string;
sorted_range_string.insert(sorted_range_string.end(), sorted_unique_range_string.begin(), sorted_unique_range_string.end());
std::sort(sorted_range_string.begin(), sorted_range_string.end());
//random_range_string
std::srand(0);
random_range_string.assign(sorted_range_string.begin(), sorted_range_string.end());
std::random_shuffle(random_range_string.begin(), random_range_string.end());
//random_unique_range_string
std::srand(0);
random_unique_range_string.assign(sorted_unique_range_string.begin(), sorted_unique_range_string.end());
std::random_shuffle(random_unique_range_string.begin(), random_unique_range_string.end());
}
template<class T>
struct range_provider;
template<>
struct range_provider<int>
{
typedef vector<int> type;
static type &sorted_unique()
{ return sorted_unique_range_int; }
static type &sorted()
{ return sorted_range_int; }
static type &random_unique()
{ return random_unique_range_int; }
static type &random()
{ return random_range_int; }
};
template<>
struct range_provider<string>
{
typedef vector<string> type;
static type &sorted_unique()
{ return sorted_unique_range_string; }
static type &sorted()
{ return sorted_range_string; }
static type &random_unique()
{ return random_unique_range_string; }
static type &random()
{ return random_range_string; }
};
template<typename C>
cpu_times copy_destroy_time(vector<typename C::value_type> &unique_range)
{
cpu_timer copy_timer, assign_timer, destroy_timer;
cpu_timer total_time;
for(std::size_t i = 0; i != NIter; ++i){
{
C c(unique_range.begin(), unique_range.end());
total_time.resume();
copy_timer.resume();
C caux(c);
copy_timer.stop();
assign_timer.resume();
c = caux;
assign_timer.stop();
destroy_timer.resume();
}
destroy_timer.stop();
total_time.stop();
}
total_time.stop();
std::cout << " Copy sorted range " << boost::timer::format(copy_timer.elapsed(), boost::timer::default_places, "%ws\n");
std::cout << " Assign sorted range " << boost::timer::format(assign_timer.elapsed(), boost::timer::default_places, "%ws\n");
std::cout << " Destroy " << boost::timer::format(destroy_timer.elapsed(), boost::timer::default_places, "%ws\n");
std::cout << " Total time = " << boost::timer::format(total_time.elapsed(), boost::timer::default_places, "%ws\n") << std::endl;
return total_time.elapsed();
}
template<typename C>
cpu_times construct_time(vector<typename C::value_type> &unique_range, vector<typename C::value_type> &range, const char *RangeType)
{
cpu_timer sur_timer, sr_timer;
cpu_timer total_time;
for(std::size_t i = 0; i != NIter; ++i){
{
sur_timer.resume();
total_time.resume();
C c(unique_range.begin(), unique_range.end());
sur_timer.stop();
total_time.stop();
}
{
total_time.resume();
sr_timer.resume();
C c(range.begin(), range.end());
sr_timer.stop();
total_time.stop();
}
}
std::cout << " Construct " << RangeType << " unique_range " << boost::timer::format(sur_timer.elapsed(), boost::timer::default_places, "%ws\n");
std::cout << " Construct " << RangeType << " range " << boost::timer::format(sr_timer.elapsed(), boost::timer::default_places, "%ws\n");
std::cout << " Total time = " << boost::timer::format(total_time.elapsed(), boost::timer::default_places, "%ws\n") << std::endl;
return total_time.elapsed();
}
template<typename C>
cpu_times insert_time(vector<typename C::value_type> &unique_range, vector<typename C::value_type> &range, const char *RangeType)
{
cpu_timer ur_timer,r_timer;
ur_timer.stop();r_timer.stop();
cpu_timer total_time;
total_time.resume();
for(std::size_t i = 0; i != NIter; ++i){
{
total_time.resume();
ur_timer.resume();
C c;
c.insert(unique_range.begin(), unique_range.end());
ur_timer.stop();
total_time.stop();
}
{
total_time.resume();
r_timer.resume();
C c;
c.insert(range.begin(), range.end());
r_timer.stop();
total_time.stop();
}
}
std::cout << " Insert " << RangeType << " unique_range " << boost::timer::format(ur_timer.elapsed(), boost::timer::default_places, "%ws\n");
std::cout << " Insert " << RangeType << " range " << boost::timer::format(r_timer.elapsed(), boost::timer::default_places, "%ws\n");
std::cout << " Total time = " << boost::timer::format(total_time.elapsed(), boost::timer::default_places, "%ws\n") << std::endl;
return total_time.elapsed();
}
template<typename Iterator>
bool check_not_end(vector<Iterator> &iterators, Iterator itend, std::size_t number_of_ends = 0)
{
std::size_t end_count = 0;
for(std::size_t i = 0, max = iterators.size(); i != max; ++i){
if(iterators[i] == itend && (++end_count > number_of_ends) )
return false;
}
return true;
}
template<typename Iterator>
bool check_all_not_empty(vector< std::pair<Iterator, Iterator > > &iterator_pairs)
{
for(std::size_t i = 0, max = iterator_pairs.size(); i != max; ++i){
if(iterator_pairs[i].first == iterator_pairs[i].second)
return false;
}
return true;
}
template<typename C>
cpu_times search_time(vector<typename C::value_type> &unique_range, const char *RangeType)
{
cpu_timer find_timer, lower_timer, upper_timer, equal_range_timer, count_timer;
C c(unique_range.begin(), unique_range.end());
cpu_timer total_time;
total_time.resume();
vector<typename C::iterator> v_it(NElements);
vector< std::pair<typename C::iterator, typename C::iterator> > v_itp(NElements);
for(std::size_t i = 0; i != NIter; ++i){
//Find
{
find_timer.resume();
for(std::size_t rep = 0; rep != 2; ++rep)
for(std::size_t i = 0, max = unique_range.size(); i != max; ++i){
v_it[i] = c.find(unique_range[i]);
}
find_timer.stop();
if(!check_not_end(v_it, c.end())){
std::cout << "ERROR! find all elements not found" << std::endl;
}
}
//Lower
{
lower_timer.resume();
for(std::size_t rep = 0; rep != 2; ++rep)
for(std::size_t i = 0, max = unique_range.size(); i != max; ++i){
v_it[i] = c.lower_bound(unique_range[i]);
}
lower_timer.stop();
if(!check_not_end(v_it, c.end())){
std::cout << "ERROR! lower_bound all elements not found" << std::endl;
}
}
//Upper
{
upper_timer.resume();
for(std::size_t rep = 0; rep != 2; ++rep)
for(std::size_t i = 0, max = unique_range.size(); i != max; ++i){
v_it[i] = c.upper_bound(unique_range[i]);
}
upper_timer.stop();
if(!check_not_end(v_it, c.end(), 1u)){
std::cout << "ERROR! upper_bound all elements not found" << std::endl;
}
}
//Equal
{
equal_range_timer.resume();
for(std::size_t rep = 0; rep != 2; ++rep)
for(std::size_t i = 0, max = unique_range.size(); i != max; ++i){
v_itp[i] = c.equal_range(unique_range[i]);
}
equal_range_timer.stop();
if(!check_all_not_empty(v_itp)){
std::cout << "ERROR! equal_range all elements not found" << std::endl;
}
}
//Count
{
std::size_t count = 0;
count_timer.resume();
for(std::size_t rep = 0; rep != 2; ++rep)
for(std::size_t i = 0, max = unique_range.size(); i != max; ++i){
count += c.count(unique_range[i]);
}
count_timer.stop();
if(count/2 != c.size()){
std::cout << "ERROR! count all elements not found" << std::endl;
}
}
}
total_time.stop();
std::cout << " Find " << RangeType << " " << boost::timer::format(find_timer.elapsed(), boost::timer::default_places, "%ws\n");
std::cout << " Lower Bound " << RangeType << " " << boost::timer::format(lower_timer.elapsed(), boost::timer::default_places, "%ws\n");
std::cout << " Upper Bound " << RangeType << " " << boost::timer::format(upper_timer.elapsed(), boost::timer::default_places, "%ws\n");
std::cout << " Equal Range " << RangeType << " " << boost::timer::format(equal_range_timer.elapsed(), boost::timer::default_places, "%ws\n");
std::cout << " Count " << RangeType << " " << boost::timer::format(count_timer.elapsed(), boost::timer::default_places, "%ws\n");
std::cout << " Total time = " << boost::timer::format(total_time.elapsed(), boost::timer::default_places, "%ws\n") << std::endl;
return total_time.elapsed();
}
template<typename C>
void extensions_time(vector<typename C::value_type> &sorted_unique_range)
{
cpu_timer sur_timer,sur_opt_timer;
sur_timer.stop();sur_opt_timer.stop();
for(std::size_t i = 0; i != NIter; ++i){
{
sur_timer.resume();
C c(sorted_unique_range.begin(), sorted_unique_range.end());
sur_timer.stop();
}
{
sur_opt_timer.resume();
C c(boost::container::ordered_unique_range, sorted_unique_range.begin(), sorted_unique_range.end());
sur_opt_timer.stop();
}
}
std::cout << " Construct sorted_unique_range " << boost::timer::format(sur_timer.elapsed(), boost::timer::default_places, "%ws\n");
std::cout << " Construct sorted_unique_range (extension) " << boost::timer::format(sur_opt_timer.elapsed(), boost::timer::default_places, "%ws\n");
std::cout << "Extension/Standard: ";
compare_times(sur_opt_timer.elapsed(), sur_timer.elapsed());
}
template<class BoostClass, class StdClass>
void launch_tests(const char *BoostContName, const char *StdContName)
{
typedef range_provider<typename BoostClass::value_type> get_range_t;
try {
std::cout << "**********************************************" << '\n';
std::cout << "**********************************************" << '\n';
std::cout << '\n';
std::cout << BoostContName << " .VS " << StdContName << '\n';
std::cout << '\n';
std::cout << "**********************************************" << '\n';
std::cout << "**********************************************" << '\n' << std::endl;
{
std::cout << "Copy/Assign/Destroy benchmark:" << BoostContName << std::endl;
cpu_times boost_set_time = copy_destroy_time< BoostClass >(get_range_t::sorted_unique());
std::cout << "Copy/Assign/Destroy benchmark:" << StdContName << std::endl;
cpu_times std_set_time = copy_destroy_time< StdClass >(get_range_t::sorted_unique());
std::cout << BoostContName << "/" << StdContName << ": ";
compare_times(boost_set_time, std_set_time);
}
{
std::cout << "Ordered construct benchmark:" << BoostContName << std::endl;
cpu_times boost_set_time = construct_time< BoostClass >(get_range_t::sorted_unique(), get_range_t::sorted(), "(ord)");
std::cout << "Ordered construct benchmark:" << StdContName << std::endl;
cpu_times std_set_time = construct_time< StdClass >(get_range_t::sorted_unique(), get_range_t::sorted(), "(ord)");;
std::cout << BoostContName << "/" << StdContName << ": ";
compare_times(boost_set_time, std_set_time);
}
{
std::cout << "Random construct benchmark:" << BoostContName << std::endl;
cpu_times boost_set_time = construct_time< BoostClass >(get_range_t::random_unique(), get_range_t::random(), "(rnd)");
std::cout << "Random construct benchmark:" << StdContName << std::endl;
cpu_times std_set_time = construct_time< StdClass >(get_range_t::random_unique(), get_range_t::random(), "(rnd)");;
std::cout << BoostContName << "/" << StdContName << ": ";
compare_times(boost_set_time, std_set_time);
}
{
std::cout << "Ordered Insert benchmark:" << BoostContName << std::endl;
cpu_times boost_set_time = insert_time< BoostClass >(get_range_t::sorted_unique(), get_range_t::sorted(), "(ord)");
std::cout << "Ordered Insert benchmark:" << StdContName << std::endl;
cpu_times std_set_time = insert_time< StdClass >(get_range_t::sorted_unique(), get_range_t::sorted(), "(ord)");
std::cout << BoostContName << "/" << StdContName << ": ";
compare_times(boost_set_time, std_set_time);
}
{
std::cout << "Random Insert benchmark:" << BoostContName << std::endl;
cpu_times boost_set_time = insert_time< BoostClass >(get_range_t::random_unique(), get_range_t::random(), "(rnd)");
std::cout << "Random Insert benchmark:" << StdContName << std::endl;
cpu_times std_set_time = insert_time< StdClass >(get_range_t::random_unique(), get_range_t::random(), "(rnd)");
std::cout << BoostContName << "/" << StdContName << ": ";
compare_times(boost_set_time, std_set_time);
}
{
std::cout << "Ordered Search benchmark:" << BoostContName << std::endl;
cpu_times boost_set_time = search_time< BoostClass >(get_range_t::sorted_unique(), "(ord)");
std::cout << "Ordered Search benchmark:" << StdContName << std::endl;
cpu_times std_set_time = search_time< StdClass >(get_range_t::sorted_unique(), "(ord)");
std::cout << BoostContName << "/" << StdContName << ": ";
compare_times(boost_set_time, std_set_time);
}
{
std::cout << "Random Search benchmark:" << BoostContName << std::endl;
cpu_times boost_set_time = search_time< BoostClass >(get_range_t::random_unique(), "(rnd)");
std::cout << "Random Search benchmark:" << StdContName << std::endl;
cpu_times std_set_time = search_time< StdClass >(get_range_t::random_unique(), "(rnd)");
std::cout << BoostContName << "/" << StdContName << ": ";
compare_times(boost_set_time, std_set_time);
}
{
std::cout << "Extensions benchmark:" << BoostContName << std::endl;
extensions_time< BoostClass >(get_range_t::sorted_unique());
}
}catch(std::exception e){
std::cout << e.what();
}
}
#endif //#ifndef BOOST_CONTAINER_BENCH_BENCH_SET_HPP

View File

@@ -0,0 +1,29 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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.
//
//////////////////////////////////////////////////////////////////////////////
#include "boost/container/set.hpp"
#include "boost/container/allocator.hpp"
#include "bench_set.hpp"
int main()
{
using namespace boost::container;
fill_range_ints();
fill_range_strings();
//set<..., allocator_v2> vs. set
launch_tests< set<int, std::less<int>, allocator<int> >, set<int> >
("set<int, ..., allocator<int>", "set<int>");
launch_tests< set<string, std::less<string>, allocator<string> >, set<string> >
("set<string, ..., allocator<string>", "set<string>");
return 0;
}

38
bench/bench_set_avl.cpp Normal file
View File

@@ -0,0 +1,38 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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.
//
//////////////////////////////////////////////////////////////////////////////
#include "boost/container/set.hpp"
#include <set>
#include "bench_set.hpp"
int main()
{
using namespace boost::container;
fill_range_ints();
fill_range_strings();
//set(AVL) vs set(RB)
launch_tests< set<int, std::less<int>, std::allocator<int>, tree_assoc_options< tree_type<avl_tree> >::type >, set<int> >
("set<int>(AVL)", "set<int>(RB)");
launch_tests< set<string, std::less<string>, std::allocator<string>, tree_assoc_options< tree_type<avl_tree> >::type >, set<string> >
("set<string>(AVL)", "set<string>(RB)");
//set(AVL,sizeopt) vs set(AVL,!sizeopt)
launch_tests< set<int, std::less<int>, std::allocator<int>, tree_assoc_options< tree_type<avl_tree> >::type >
, set<int, std::less<int>, std::allocator<int>, tree_assoc_options< tree_type<avl_tree>, optimize_size<false> >::type > >
("set<int>(AVL,sizeopt=true)", "set<int>(AVL,sizeopt=false)");
launch_tests< set<string, std::less<string>, std::allocator<string>, tree_assoc_options< tree_type<avl_tree> >::type >
, set<string, std::less<string>, std::allocator<string>, tree_assoc_options< tree_type<avl_tree>, optimize_size<false> >::type > >
("set<string>(AVL,sizeopt=true)", "set<string>(AVL,sizeopt=false)");
return 0;
}

30
bench/bench_set_multi.cpp Normal file
View File

@@ -0,0 +1,30 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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.
//
//////////////////////////////////////////////////////////////////////////////
#include "boost/container/set.hpp"
#include <set>
#include "bench_set.hpp"
int main()
{
using namespace boost::container;
fill_range_ints();
fill_range_strings();
//multiset vs std::multiset
launch_tests< multiset<int> , std::multiset<int> >
("multiset<int>", "std::multiset<int>");
launch_tests< multiset<string> , std::multiset<string> >
("multiset<string>", "std::multiset<string>");
return 0;
}

28
bench/bench_set_sg.cpp Normal file
View File

@@ -0,0 +1,28 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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.
//
//////////////////////////////////////////////////////////////////////////////
#include "boost/container/set.hpp"
#include "bench_set.hpp"
int main()
{
using namespace boost::container;
fill_range_ints();
fill_range_strings();
//set(RB) vs set(SG)
launch_tests< set<int, std::less<int>, std::allocator<int>, tree_assoc_options< tree_type<scapegoat_tree> >::type >, set<int> >
("set<int>(SG)", "set<int>(RB)");
launch_tests< set<string, std::less<string>, std::allocator<string>, tree_assoc_options< tree_type<scapegoat_tree> >::type >, set<string> >
("set<string>(SG)", "set<string>(RB)");
return 0;
}

28
bench/bench_set_sp.cpp Normal file
View File

@@ -0,0 +1,28 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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.
//
//////////////////////////////////////////////////////////////////////////////
#include "boost/container/set.hpp"
#include "bench_set.hpp"
int main()
{
using namespace boost::container;
fill_range_ints();
fill_range_strings();
//set(RB) vs set(SP)
launch_tests< set<int, std::less<int>, std::allocator<int>, tree_assoc_options< tree_type<splay_tree> >::type >, set<int> >
("set<int>(SP)", "set<int>(RB)");
launch_tests< set<string, std::less<string>, std::allocator<string>, tree_assoc_options< tree_type<splay_tree> >::type >, set<string> >
("set<string>(SP)", "set<string>(RB)");
return 0;
}

View File

@@ -4,8 +4,8 @@
// @date Aug 14, 2011
// @author Andrew Hundt <ATHundt@gmail.com>
//
// (C) 2011-2012 Andrew Hundt <ATHundt@gmail.com>
// (C) 2013 Ion Gaztanaga
// (C) 2011-2013 Andrew Hundt <ATHundt@gmail.com>
// (C) 2013-2013 Ion Gaztanaga
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -28,7 +28,7 @@ using boost::timer::cpu_times;
using boost::timer::nanosecond_type;
#ifdef NDEBUG
static const std::size_t N = 1000;
static const std::size_t N = 300;
#else
static const std::size_t N = 100;
#endif
@@ -141,5 +141,5 @@ int main()
}catch(std::exception e){
std::cout << e.what();
}
return 1;
return 0;
}

View File

@@ -10,7 +10,7 @@
#ifndef BOOST_CONTAINER_DETAIL_VARRAY_HPP
#define BOOST_CONTAINER_DETAIL_VARRAY_HPP
#if (defined _MSC_VER)
#if defined(_MSC_VER)
# pragma once
#endif
@@ -19,8 +19,8 @@
#include <boost/container/detail/preprocessor.hpp>
#include "varray_util.hpp"
#include "varray_concept.hpp"
#include <boost/iterator/iterator_concepts.hpp>
//#include "varray_concept.hpp"
//#include <boost/iterator/iterator_concepts.hpp>
#ifndef BOOST_NO_EXCEPTIONS
#include <stdexcept>
@@ -229,7 +229,7 @@ class varray
(varray)
);
BOOST_CONCEPT_ASSERT((concept::VArrayStrategy<Strategy>));
//BOOST_CONCEPT_ASSERT((concept::VArrayStrategy<Strategy>));
typedef boost::aligned_storage<
sizeof(Value[Capacity]),
@@ -353,7 +353,7 @@ public:
varray(Iterator first, Iterator last)
: m_size(0)
{
BOOST_CONCEPT_ASSERT((boost_concepts::ForwardTraversal<Iterator>)); // Make sure you passed a ForwardIterator
//BOOST_CONCEPT_ASSERT((boost_concepts::ForwardTraversal<Iterator>)); // Make sure you passed a ForwardIterator
this->assign(first, last); // may throw
}
@@ -890,7 +890,7 @@ public:
template <typename Iterator>
iterator insert(iterator position, Iterator first, Iterator last)
{
BOOST_CONCEPT_ASSERT((boost_concepts::ForwardTraversal<Iterator>)); // Make sure you passed a ForwardIterator
//BOOST_CONCEPT_ASSERT((boost_concepts::ForwardTraversal<Iterator>)); // Make sure you passed a ForwardIterator
typedef typename boost::iterator_traversal<Iterator>::type traversal;
this->insert_dispatch(position, first, last, traversal());
@@ -975,7 +975,7 @@ public:
template <typename Iterator>
void assign(Iterator first, Iterator last)
{
BOOST_CONCEPT_ASSERT((boost_concepts::ForwardTraversal<Iterator>)); // Make sure you passed a ForwardIterator
//BOOST_CONCEPT_ASSERT((boost_concepts::ForwardTraversal<Iterator>)); // Make sure you passed a ForwardIterator
typedef typename boost::iterator_traversal<Iterator>::type traversal;
this->assign_dispatch(first, last, traversal()); // may throw
@@ -1728,7 +1728,7 @@ private:
template <typename Iterator>
void insert_dispatch(iterator position, Iterator first, Iterator last, boost::random_access_traversal_tag const&)
{
BOOST_CONCEPT_ASSERT((boost_concepts::RandomAccessTraversal<Iterator>)); // Make sure you passed a RandomAccessIterator
//BOOST_CONCEPT_ASSERT((boost_concepts::RandomAccessTraversal<Iterator>)); // Make sure you passed a RandomAccessIterator
errh::check_iterator_end_eq(*this, position);
@@ -2015,7 +2015,7 @@ public:
void insert(iterator, Iterator first, Iterator last)
{
// TODO - add MPL_ASSERT, check if Iterator is really an iterator
typedef typename boost::iterator_traversal<Iterator>::type traversal;
//typedef typename boost::iterator_traversal<Iterator>::type traversal;
errh::check_capacity(*this, std::distance(first, last)); // may throw
}
@@ -2039,7 +2039,7 @@ public:
void assign(Iterator first, Iterator last)
{
// TODO - add MPL_ASSERT, check if Iterator is really an iterator
typedef typename boost::iterator_traversal<Iterator>::type traversal;
//typedef typename boost::iterator_traversal<Iterator>::type traversal;
errh::check_capacity(*this, std::distance(first, last)); // may throw
}

View File

@@ -566,13 +566,6 @@ template <typename DisableTrivialInit, typename I, typename P>
inline
void construct(DisableTrivialInit const&, I pos, BOOST_RV_REF(P) p)
{
typedef typename
::boost::mpl::and_<
is_corresponding_value<I, P>,
::boost::has_trivial_copy<P>
>::type
use_memcpy;
typedef typename boost::iterator_value<I>::type V;
new (static_cast<void*>(boost::addressof(*pos))) V(::boost::move(p)); // may throw
}

View File

@@ -10,13 +10,14 @@
#ifndef BOOST_CONTAINER_VARRAY_HPP
#define BOOST_CONTAINER_VARRAY_HPP
#if (defined _MSC_VER)
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
#include "detail/varray.hpp"
#include <boost/move/move.hpp>
namespace boost { namespace container {

23
build/Jamfile.v2 Normal file
View File

@@ -0,0 +1,23 @@
# (C) Copyright Vladimir Prus, David Abrahams, Michael Stevens, Hartmut Kaiser,
# Ion Gaztanaga 2007-2008
# Use, modification and distribution are subject to the
# Boost Software License, Version 1.0. (See accompanying file
# LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
project boost/container
: source-location ../src
: usage-requirements # pass these requirement to dependents (i.e. users)
<link>shared:<define>BOOST_CONTAINER_DYN_LINK=1
<link>static:<define>BOOST_CONTAINER_STATIC_LINK=1
;
# Base names of the source files for libboost_container
CPP_SOURCES = alloc_lib ;
lib boost_container
: $(CPP_SOURCES).c
: <link>shared:<define>BOOST_CONTAINER_DYN_LINK=1
<link>static:<define>BOOST_CONTAINER_STATIC_LINK=1
;
boost-install boost_container ;

View File

@@ -1,6 +1,6 @@
# Boost.Container library documentation Jamfile ---------------------------------
#
# Copyright Ion Gaztanaga 2009-2012. Use, modification and
# Copyright Ion Gaztanaga 2009-2013. Use, modification and
# distribution is subject to the Boost Software License, Version
# 1.0. (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
@@ -35,7 +35,9 @@ doxygen autodoc
\"BOOST_RV_REF_BEG=\" \\
\"BOOST_RV_REF_END=&&\" \\
\"BOOST_COPY_ASSIGN_REF(T)=const T &\" \\
\"BOOST_FWD_REF(a)=a &&\""
\"BOOST_FWD_REF(a)=a &&\" \\
\"BOOST_INTRUSIVE_OPTION_CONSTANT(OPTION_NAME, TYPE, VALUE, CONSTANT_NAME) = template<TYPE VALUE> struct OPTION_NAME{};\" \\
\"BOOST_INTRUSIVE_OPTION_TYPE(OPTION_NAME, TYPE, TYPEDEF_EXPR, TYPEDEF_NAME) = template<class TYPE> struct OPTION_NAME{};\" "
<xsl:param>"boost.doxygen.reftitle=Boost.Container Header Reference"
;

View File

@@ -49,9 +49,13 @@ In short, what does [*Boost.Container] offer?
[section:introduction_building_container Building Boost.Container]
There is no need to compile [*Boost.Container], since it's
a header only library. Just include your Boost header directory in your
compiler include path.
There is no need to compile [*Boost.Container] if you don't use [link container.extended_functionality.extended_allocators Extended Allocators]
since in that case it's a header-only library. Just include your Boost header directory in your compiler include path.
[link container.extended_functionality.extended_allocators Extended Allocators] are
implemented as a separately compiled library, so you must install binaries in a location that can be found by your linker
when using these classes. If you followed the [@http://www.boost.org/doc/libs/release/more/getting_started/index.html Boost Getting Started] instructions,
that's already been done for you.
[endsect]
@@ -148,12 +152,19 @@ today, in fact, implementors would have to go out of their way to prohibit it!]]
C++11 standard is also cautious about incomplete types and STL: ["['17.6.4.8 Other functions (...) 2.
the effects are undefined in the following cases: (...) In particular - if an incomplete type (3.9)
is used as a template argument when instantiating a template component,
unless specifically allowed for that component]]. Fortunately [*Boost.Container] containers are designed
to support type erasure and recursive types, so let's see some examples:
unless specifically allowed for that component]].
Fortunately all [*Boost.Container] containers except
[classref boost::container::static_vector static_vector] and
[classref boost::container::basic_string basic_string] are designed to support incomplete types.
[classref boost::container::static_vector static_vector] is special because
it statically allocates memory for `value_type` and this requires complete types and
[classref boost::container::basic_string basic_string] implements Small String Optimization which
also requires complete types.
[section:recursive_containers Recursive containers]
All containers offered by [*Boost.Container] can be used to define recursive containers:
Most [*Boost.Container] containers can be used to define recursive containers:
[import ../example/doc_recursive_containers.cpp]
[doc_recursive_containers]
@@ -261,8 +272,8 @@ When dealing with user-defined classes, (e.g. when constructing user-defined cla
propagate error situations internally as no error will be propagated through [*Boost.Container].
* If `BOOST_NO_EXCEPTIONS` is *not* defined, the library propagates exceptions offering the exception guarantees detailed in the documentation.
When the library needs to throw an exception (such as `out_of_range` when an incorrect index is used in `vector::at`)], the library calls
a throw callback declared in `<boost/container/throw_exception.hpp>`:
When the library needs to throw an exception (such as `out_of_range` when an incorrect index is used in `vector::at`), the library calls
a throw-callback declared in [headerref boost/container/throw_exception.hpp]:
* If `BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS` is defined, then the programmer must provide its own definition for all
`throw_xxx` functions. Those functions can't return, they must throw an exception or call `std::exit` or `std::abort`.
@@ -522,6 +533,168 @@ using [@http://en.cppreference.com/w/cpp/language/default_initialization default
[endsect]
[section:ordered_range_insertion Ordered range insertion for associative containers (['ordered_unique_range], ['ordered_range]) ]
When filling associative containers big performance gains can be achieved if the input range to be inserted
is guaranteed by the user to be ordered according to the predicate. This can happen when inserting values from a `set` to
a `multiset` or between different associative container families (`[multi]set/map` vs. `flat_[multi]set/map`).
[*Boost.Container] has some overloads for constructors and insertions taking an `ordered_unique_range_t` or
an `ordered_range_t` tag parameters as the first argument. When an `ordered_unique_range_t` overload is used, the
user notifies the container that the input range is ordered according to the container predicate and has no
duplicates. When an `ordered_range_t` overload is used, the
user notifies the container that the input range is ordered according to the container predicate but it might
have duplicates. With this information, the container can avoid multiple predicate calls and improve insertion
times.
[endsect]
[section:configurable_tree_based_associative_containers Configurable tree-based associative ordered containers]
[classref boost::container::set set], [classref boost::container::multiset multiset],
[classref boost::container::map map] and [classref boost::container::multimap multimap] associative containers
are implemented as binary search trees which offer the needed complexity and stability guarantees required by the
C++ standard for associative containers.
[*Boost.Container] offers the possibility to configure at compile time some parameters of the binary search tree
implementation. This configuration is passed as the last template parameter and defined using the utility class
[classref boost::container::tree_assoc_options tree_assoc_options].
The following parameters can be configured:
* The underlying [*tree implementation] type ([classref boost::container::tree_type tree_type]).
By default these containers use a red-black tree but the user can use other tree types:
* [@http://en.wikipedia.org/wiki/Red%E2%80%93black_tree Red-Black Tree]
* [@http://en.wikipedia.org/wiki/Avl_trees AVL tree]
* [@http://en.wikipedia.org/wiki/Scapegoat_tree Scapegoat tree]. In this case Insertion and Deletion
are amortized O(log n) instead of O(log n).
* [@http://en.wikipedia.org/wiki/Splay_tree Splay tree]. In this case Searches, Insertions and Deletions
are amortized O(log n) instead of O(log n).
* Whether the [*size saving] mechanisms are used to implement the tree nodes
([classref boost::container::optimize_size optimize_size]). By default this option is activated and is only
meaningful to red-black and avl trees (in other cases, this option will be ignored).
This option will try to put rebalancing metadata inside the "parent" pointer of the node if the pointer
type has enough alignment. Usually, due to alignment issues, the metadata uses the size of a pointer yielding
to four pointer size overhead per node, whereas activating this option usually leads to 3 pointer size overhead.
Although some mask operations must be performed to extract
data from this special "parent" pointer, in several systems this option also improves performance due to the
improved cache usage produced by the node size reduction.
See the following example to see how [classref boost::container::tree_assoc_options tree_assoc_options] can be
used to customize these containers:
[import ../example/doc_custom_tree.cpp]
[doc_custom_tree]
[endsect]
[section:constant_time_range_splice Constant-time range splice for `(s)list`]
In the first C++ standard `list::size()` was not required to be constant-time,
and that caused some controversy in the C++ community. Quoting Howard Hinnant's
[@http://home.roadrunner.com/~hinnant/On_list_size.html ['On List Size]] paper:
[: ['There is a considerable debate on whether `std::list<T>::size()` should be O(1) or O(N).
The usual argument notes that it is a tradeoff with:]
`splice(iterator position, list& x, iterator first, iterator last);`
['If size() is O(1) and this != &x, then this method must perform a linear operation so that it
can adjust the size member in each list]]
C++11 definitely required `size()` to be O(1), so range splice became O(N). However,
Howard Hinnant's paper proposed a new `splice` overload so that even O(1) `list:size()`
implementations could achieve O(1) range splice when the range size was known to the caller:
[: `void splice(iterator position, list& x, iterator first, iterator last, size_type n);`
[*Effects]: Inserts elements in the range [first, last) before position and removes the elements from x.
[*Requires]: [first, last) is a valid range in x. The result is undefined if position is an iterator in the range [first, last). Invalidates only the iterators and references to the spliced elements. n == distance(first, last).
[*Throws]: Nothing.
[*Complexity]: Constant time.
]
This new splice signature allows the client to pass the distance of the input range in.
This information is often available at the call site. If it is passed in,
then the operation is constant time, even with an O(1) size.
[*Boost.Container] implements this overload for `list` and a modified version of it for `slist`
(as `slist::size()` is also `O(1)`).
[endsect]
[section:extended_allocators Extended allocators]
Many C++ programmers have ever wondered where does good old realloc fit in C++. And that's a good question.
Could we improve [classref boost::container::vector vector] performance using memory expansion mechanisms
to avoid too many copies? But [classref boost::container::vector vector] is not the only container that
could benefit from an improved allocator interface: we could take advantage of the insertion of multiple
elements in [classref boost::container::list list] using a burst allocation mechanism that could amortize
costs (mutex locks, free memory searches...) that can't be amortized when using single node allocation
strategies.
These improvements require extending the STL allocator interface and use make use of a new
general purpose allocator since new and delete don't offer expansion and burst capabilities.
* [*Boost.Container] containers support an extended allocator interface based on an evolution of proposals
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1953.html N1953: Upgrading the Interface of Allocators using API Versioning],
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2045.html N2045: Improving STL allocators]
and the article
[@http://www.drivehq.com/web/igaztanaga/allocplus/ Applying classic memory allocation strategies to C++ containers].
The extended allocator interface is implemented by [classref boost::container::allocator allocator],
[classref boost::container::adaptive_pool adaptive_pool] and [classref boost::container::node_allocator node_allocator]
classes.
* Extended allocators use a modified [@http://g.oswego.edu/dl/html/malloc.html Doug Lea Malloc (DLMalloc)] low-level
allocator and offers an C API to implement memory expansion and burst allocations. DLmalloc is known to be very size
and speed efficient, and this allocator is used as the basis of many malloc implementations, including multithreaded
allocators built above DLmalloc (See [@http://www.malloc.de/en/ ptmalloc2, ptmalloc3] or
[@http://www.nedprod.com/programs/portable/nedmalloc/ nedmalloc]). This low-level allocator is implemented as
a separately compiled library whereas [classref boost::container::allocator allocator],
[classref boost::container::adaptive_pool adaptive_pool] and [classref boost::container::node_allocator node_allocator]
are header-only classes.
The following extended allocators are provided:
* [classref boost::container::allocator allocator]: This extended allocator offers expansion, shrink-in place
and burst allocation capabilities implemented as a thin wrapper around the modified DLMalloc.
It can be used with all containers and it should be the default choice when the programmer wants to use
extended allocator capabilities.
* [classref boost::container::node_allocator node_allocator]: It's a
[@http://www.boost.org/doc/libs/1_55_0/libs/pool/doc/html/boost_pool/pool/pooling.html#boost_pool.pool.pooling.simple Simple Segregated Storage]
allocator, similar to [*Boost.Pool] that takes advantage of the modified DLMalloc burst interface. It does not return
memory to the DLMalloc allocator (and thus, to the system), unless explicitly requested. It does offer a very small
memory overhead so it's suitable for node containers ([boost::container::list list], [boost::container::slist slist]
[boost::container::set set]...) that allocate very small `value_type`s and it offers improved node allocation times
for single node allocations with respecto to [classref boost::container::allocator allocator].
* [classref boost::container::adaptive_pool adaptive_pool]: It's a low-overhead node allocator that can return memory
to the system. The overhead can be very low (< 5% for small nodes) and it's nearly as fast as [classref boost::container::node_allocator node_allocator].
It's also suitable for node containers.
Use them simply specifying the new allocator in the corresponding template argument of your favourite container:
[import ../example/doc_extended_allocators.cpp]
[doc_extended_allocators]
[endsect]
[/
/a__section:previous_element_slist Previous element for slist__a
/
/The C++11 `std::forward_list` class implement a singly linked list, similar to `slist`, and these
/containers only offer forward iterators and implement insertions and splice operations that operate with ranges
/to be inserted ['after] that position. In those cases, sometimes it's interesting to obtain an iterator pointing
/to the previous element of another element. This operation can be implemented
/
/a__endsect__a
]
[/
/a__section:get_stored_allocator Obtain stored allocator__a
/
@@ -532,18 +705,6 @@ using [@http://en.cppreference.com/w/cpp/language/default_initialization default
/http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2271.html
/
/a__endsect__a
/
/a__section:ordered_range_insertion Ordered range insertion (a__'ordered_unique_range__a, a__'ordered_range__a) __a
/
/a__endsect__a
/
/a__section:constant_time_range_splice Constant-time range splice__a
/
/a__endsect__a
/
/a__section:previous_element_slist Slist previous element__a
/
/a__endsect__a
/]
[endsect]
@@ -709,9 +870,10 @@ use [*Boost.Container]? There are several reasons for that:
* Default constructors don't allocate memory at all, which improves performance and
usually implies a no-throw guarantee (if predicate's or allocator's default constructor doesn't throw).
* Small string optimization for [classref boost::container::basic_string basic_string].
* New extensions beyond the standard based on user feedback to improve code performance.
* [link container.extended_functionality Extended functionality] beyond the standard based
on user feedback to improve code performance.
* You need a portable implementation that works when compiling without exceptions support or
you need to customize the error handling when a container needs to signall an exceptional error.
you need to customize the error handling when a container needs to signal an exceptional error.
[endsect]
@@ -759,6 +921,21 @@ use [*Boost.Container]? There are several reasons for that:
[section:release_notes Release Notes]
[section:release_notes_boost_1_56_00 Boost 1.56 Release]
* Added DlMalloc-based [link container.extended_functionality.extended_allocators Extended Allocators].
* [link container.extended_functionality.configurable_tree_based_associative_containers Improved configurability]
of tree-based ordered associative containers. AVL, Scapegoat and Splay trees are now available
to implement [classref boost::container::set set], [classref boost::container::multiset multiset],
[classref boost::container::map map] and [classref boost::container::multimap multimap].
* Fixed bugs:
* [@https://svn.boost.org/trac/boost/ticket/9338 #9338: ['"VS2005 compiler errors in swap() definition after including container/memory_util.hpp"]].
* [@https://svn.boost.org/trac/boost/ticket/9648 #9648: ['"string construction optimization - char_traits::copy could be used ..."]].
[endsect]
[section:release_notes_boost_1_55_00 Boost 1.55 Release]
* Implemented [link container.main_features.scary_iterators SCARY iterators].
@@ -769,7 +946,8 @@ use [*Boost.Container]? There are several reasons for that:
[@https://svn.boost.org/trac/boost/ticket/9009 #9009],
[@https://svn.boost.org/trac/boost/ticket/9064 #9064],
[@https://svn.boost.org/trac/boost/ticket/9092 #9092],
[@https://svn.boost.org/trac/boost/ticket/9108 #9108].
[@https://svn.boost.org/trac/boost/ticket/9108 #9108],
[@https://svn.boost.org/trac/boost/ticket/9166 #9166],
[endsect]

View File

@@ -21,7 +21,7 @@ rule test_all
for local fileb in [ glob doc_*.cpp ]
{
all_rules += [ run $(fileb)
all_rules += [ run $(fileb) /boost/container//boost_container /boost/timer//boost_timer
: # additional args
: # test-files
: # requirements

View File

@@ -0,0 +1,64 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
//[doc_custom_tree
#include <boost/container/set.hpp>
#include <cassert>
int main ()
{
using namespace boost::container;
//First define several options
//
//This option specifies an AVL tree based associative container
typedef tree_assoc_options< tree_type<avl_tree> >::type AVLTree;
//This option specifies an AVL tree based associative container
//disabling node size optimization.
typedef tree_assoc_options< tree_type<avl_tree>
, optimize_size<false> >::type AVLTreeNoSizeOpt;
//This option specifies an Splay tree based associative container
typedef tree_assoc_options< tree_type<splay_tree> >::type SplayTree;
//Now define new tree-based associative containers
//
//AVLTree based set container
typedef set<int, std::less<int>, std::allocator<int>, AVLTree> AvlSet;
//AVLTree based set container without size optimization
typedef set<int, std::less<int>, std::allocator<int>, AVLTreeNoSizeOpt> AvlSetNoSizeOpt;
//Splay tree based multiset container
typedef multiset<int, std::less<int>, std::allocator<int>, SplayTree> SplayMultiset;
//Use them
//
AvlSet avl_set;
avl_set.insert(0);
assert(avl_set.find(0) != avl_set.end());
AvlSetNoSizeOpt avl_set_no_szopt;
avl_set_no_szopt.insert(1);
avl_set_no_szopt.insert(1);
assert(avl_set_no_szopt.count(1) == 1);
SplayMultiset splay_mset;
splay_mset.insert(2);
splay_mset.insert(2);
assert(splay_mset.count(2) == 2);
return 0;
}
//]
#include <boost/container/detail/config_end.hpp>

View File

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

View File

@@ -0,0 +1,54 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
//[doc_extended_allocators
#include <boost/container/vector.hpp>
#include <boost/container/flat_set.hpp>
#include <boost/container/list.hpp>
#include <boost/container/set.hpp>
//"allocator" is a general purpose allocator that can reallocate
//memory, something useful for vector and flat associative containers
#include <boost/container/allocator.hpp>
//"adaptive_pool" is a node allocator, specially suited for
//node-based containers
#include <boost/container/adaptive_pool.hpp>
int main ()
{
using namespace boost::container;
//A vector that can reallocate memory to implement faster insertions
vector<int, allocator<int> > extended_alloc_vector;
//A flat set that can reallocate memory to implement faster insertions
flat_set<int, std::less<int>, allocator<int> > extended_alloc_flat_set;
//A list that can manages nodes to implement faster
//range insertions and deletions
list<int, adaptive_pool<int> > extended_alloc_list;
//A set that can recycle nodes to implement faster
//range insertions and deletions
set<int, std::less<int>, adaptive_pool<int> > extended_alloc_set;
//Now user them as always
extended_alloc_vector.push_back(0);
extended_alloc_flat_set.insert(0);
extended_alloc_list.push_back(0);
extended_alloc_set.insert(0);
//...
return 0;
}
//]
#include <boost/container/detail/config_end.hpp>

View File

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

View File

@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2009-2012. Distributed under the Boost
// (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)
//
@@ -11,9 +11,10 @@
#include <boost/container/detail/workaround.hpp>
//[doc_recursive_containers
#include <boost/container/vector.hpp>
#include <boost/container/stable_vector.hpp>
#include <boost/container/deque.hpp>
#include <boost/container/list.hpp>
#include <boost/container/map.hpp>
#include <boost/container/stable_vector.hpp>
#include <boost/container/string.hpp>
using namespace boost::container;
@@ -23,6 +24,10 @@ struct data
int i_;
//A vector holding still undefined class 'data'
vector<data> v_;
//A stable_vector holding still undefined class 'data'
stable_vector<data> sv_;
//A stable_vector holding still undefined class 'data'
deque<data> d_;
//A list holding still undefined 'data'
list<data> l_;
//A map holding still undefined 'data'

View File

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

View File

@@ -0,0 +1,390 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_ADAPTIVE_POOL_HPP
#define BOOST_CONTAINER_ADAPTIVE_POOL_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/container_fwd.hpp>
#include <boost/container/detail/version_type.hpp>
#include <boost/container/throw_exception.hpp>
#include <boost/container/detail/adaptive_node_pool.hpp>
#include <boost/container/detail/multiallocation_chain.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/alloc_lib_auto_link.hpp>
#include <boost/container/detail/singleton.hpp>
#include <boost/iterator/transform_iterator.hpp>
#include <boost/assert.hpp>
#include <boost/utility/addressof.hpp>
#include <boost/static_assert.hpp>
#include <boost/move/move.hpp>
#include <memory>
#include <algorithm>
#include <cstddef>
#include <new>
namespace boost {
namespace container {
//!An STL node allocator that uses a modified DLMalloc as memory
//!source.
//!
//!This node allocator shares a segregated storage between all instances
//!of adaptive_pool with equal sizeof(T).
//!
//!NodesPerBlock is the number of nodes allocated at once when the allocator
//!needs runs out of nodes. MaxFreeBlocks is the maximum number of totally free blocks
//!that the adaptive node pool will hold. The rest of the totally free blocks will be
//!deallocated to the memory manager.
//!
//!OverheadPercent is the (approximated) maximum size overhead (1-20%) of the allocator:
//!(memory usable for nodes / total memory allocated from the memory allocator)
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
template < class T
, std::size_t NodesPerBlock = ADP_nodes_per_block
, std::size_t MaxFreeBlocks = ADP_max_free_blocks
, std::size_t OverheadPercent = ADP_overhead_percent
>
#else
template < class T
, std::size_t NodesPerBlock
, std::size_t MaxFreeBlocks
, std::size_t OverheadPercent
, unsigned Version
>
#endif
class adaptive_pool
{
//!If Version is 1, the allocator is a STL conforming allocator. If Version is 2,
//!the allocator offers advanced expand in place and burst allocation capabilities.
public:
typedef unsigned int allocation_type;
typedef adaptive_pool
<T, NodesPerBlock, MaxFreeBlocks, OverheadPercent
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
, Version
#endif
> self_t;
static const std::size_t nodes_per_block = NodesPerBlock;
static const std::size_t max_free_blocks = MaxFreeBlocks;
static const std::size_t overhead_percent = OverheadPercent;
static const std::size_t real_nodes_per_block = NodesPerBlock;
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
BOOST_STATIC_ASSERT((Version <=2));
#endif
public:
//-------
typedef T value_type;
typedef T * pointer;
typedef const T * const_pointer;
typedef typename ::boost::container::
container_detail::unvoid<T>::type & reference;
typedef const typename ::boost::container::
container_detail::unvoid<T>::type & const_reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef boost::container::container_detail::
version_type<self_t, Version> version;
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
typedef boost::container::container_detail::
basic_multiallocation_chain<void*> multiallocation_chain_void;
typedef boost::container::container_detail::
transform_multiallocation_chain
<multiallocation_chain_void, T> multiallocation_chain;
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//!Obtains adaptive_pool from
//!adaptive_pool
template<class T2>
struct rebind
{
typedef adaptive_pool
< T2
, NodesPerBlock
, MaxFreeBlocks
, OverheadPercent
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
, Version
#endif
> other;
};
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
//!Not assignable from related adaptive_pool
template<class T2, unsigned Version2, std::size_t N2, std::size_t F2>
adaptive_pool& operator=
(const adaptive_pool<T2, Version2, N2, F2>&);
//!Not assignable from other adaptive_pool
adaptive_pool& operator=(const adaptive_pool&);
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
public:
//!Default constructor
adaptive_pool() BOOST_CONTAINER_NOEXCEPT
{}
//!Copy constructor from other adaptive_pool.
adaptive_pool(const adaptive_pool &) BOOST_CONTAINER_NOEXCEPT
{}
//!Copy constructor from related adaptive_pool.
template<class T2>
adaptive_pool
(const adaptive_pool<T2, NodesPerBlock, MaxFreeBlocks, OverheadPercent
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
, Version
#endif
> &) BOOST_CONTAINER_NOEXCEPT
{}
//!Destructor
~adaptive_pool() BOOST_CONTAINER_NOEXCEPT
{}
//!Returns the number of elements that could be allocated.
//!Never throws
size_type max_size() const BOOST_CONTAINER_NOEXCEPT
{ return size_type(-1)/sizeof(T); }
//!Allocate memory for an array of count elements.
//!Throws std::bad_alloc if there is no enough memory
pointer allocate(size_type count, const void * = 0)
{
if(count > this->max_size())
boost::container::throw_bad_alloc();
if(Version == 1 && count == 1){
typedef typename container_detail::shared_adaptive_node_pool
<sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> shared_pool_t;
typedef container_detail::singleton_default<shared_pool_t> singleton_t;
return pointer(static_cast<T*>(singleton_t::instance().allocate_node()));
}
else{
return static_cast<pointer>(boost_cont_malloc(count*sizeof(T)));
}
}
//!Deallocate allocated memory.
//!Never throws
void deallocate(const pointer &ptr, size_type count) BOOST_CONTAINER_NOEXCEPT
{
(void)count;
if(Version == 1 && count == 1){
typedef container_detail::shared_adaptive_node_pool
<sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> shared_pool_t;
typedef container_detail::singleton_default<shared_pool_t> singleton_t;
singleton_t::instance().deallocate_node(ptr);
}
else{
boost_cont_free(ptr);
}
}
std::pair<pointer, bool>
allocation_command(allocation_type command,
size_type limit_size,
size_type preferred_size,
size_type &received_size, pointer reuse = pointer())
{
std::pair<pointer, bool> ret =
this->priv_allocation_command(command, limit_size, preferred_size, received_size, reuse);
if(!ret.first && !(command & BOOST_CONTAINER_NOTHROW_ALLOCATION))
boost::container::throw_bad_alloc();
return ret;
}
//!Returns maximum the number of objects the previously allocated memory
//!pointed by p can hold.
size_type size(pointer p) const BOOST_CONTAINER_NOEXCEPT
{ return boost_cont_size(p); }
//!Allocates just one object. Memory allocated with this function
//!must be deallocated only with deallocate_one().
//!Throws bad_alloc if there is no enough memory
pointer allocate_one()
{
typedef container_detail::shared_adaptive_node_pool
<sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> shared_pool_t;
typedef container_detail::singleton_default<shared_pool_t> singleton_t;
return (pointer)singleton_t::instance().allocate_node();
}
//!Allocates many elements of size == 1.
//!Elements must be individually deallocated with deallocate_one()
void allocate_individual(std::size_t num_elements, multiallocation_chain &chain)
{
typedef container_detail::shared_adaptive_node_pool
<sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> shared_pool_t;
typedef container_detail::singleton_default<shared_pool_t> singleton_t;
singleton_t::instance().allocate_nodes(num_elements, static_cast<typename shared_pool_t::multiallocation_chain&>(chain));
//typename shared_pool_t::multiallocation_chain ch;
//singleton_t::instance().allocate_nodes(num_elements, ch);
//chain.incorporate_after
//(chain.before_begin(), (T*)&*ch.begin(), (T*)&*ch.last(), ch.size());
}
//!Deallocates memory previously allocated with allocate_one().
//!You should never use deallocate_one to deallocate memory allocated
//!with other functions different from allocate_one(). Never throws
void deallocate_one(pointer p) BOOST_CONTAINER_NOEXCEPT
{
typedef container_detail::shared_adaptive_node_pool
<sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> shared_pool_t;
typedef container_detail::singleton_default<shared_pool_t> singleton_t;
singleton_t::instance().deallocate_node(p);
}
void deallocate_individual(multiallocation_chain &chain) BOOST_CONTAINER_NOEXCEPT
{
typedef container_detail::shared_adaptive_node_pool
<sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> shared_pool_t;
typedef container_detail::singleton_default<shared_pool_t> singleton_t;
//typename shared_pool_t::multiallocation_chain ch(&*chain.begin(), &*chain.last(), chain.size());
//singleton_t::instance().deallocate_nodes(ch);
singleton_t::instance().deallocate_nodes(chain);
}
//!Allocates many elements of size elem_size.
//!Elements must be individually deallocated with deallocate()
void allocate_many(size_type elem_size, std::size_t n_elements, multiallocation_chain &chain)
{
BOOST_STATIC_ASSERT(( Version > 1 ));/*
boost_cont_memchain ch;
BOOST_CONTAINER_MEMCHAIN_INIT(&ch);
if(!boost_cont_multialloc_nodes(n_elements, elem_size*sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &ch)){
boost::container::throw_bad_alloc();
}
chain.incorporate_after(chain.before_begin()
,(T*)BOOST_CONTAINER_MEMCHAIN_FIRSTMEM(&ch)
,(T*)BOOST_CONTAINER_MEMCHAIN_LASTMEM(&ch)
,BOOST_CONTAINER_MEMCHAIN_SIZE(&ch) );*/
if(!boost_cont_multialloc_nodes(n_elements, elem_size*sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, reinterpret_cast<boost_cont_memchain *>(&chain))){
boost::container::throw_bad_alloc();
}
}
//!Allocates n_elements elements, each one of size elem_sizes[i]
//!Elements must be individually deallocated with deallocate()
void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain)
{
BOOST_STATIC_ASSERT(( Version > 1 ));/*
boost_cont_memchain ch;
BOOST_CONTAINER_MEMCHAIN_INIT(&ch);
if(!boost_cont_multialloc_arrays(n_elements, elem_sizes, sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &ch)){
boost::container::throw_bad_alloc();
}
chain.incorporate_after(chain.before_begin()
,(T*)BOOST_CONTAINER_MEMCHAIN_FIRSTMEM(&ch)
,(T*)BOOST_CONTAINER_MEMCHAIN_LASTMEM(&ch)
,BOOST_CONTAINER_MEMCHAIN_SIZE(&ch) );*/
if(!boost_cont_multialloc_arrays(n_elements, elem_sizes, sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, reinterpret_cast<boost_cont_memchain *>(&chain))){
boost::container::throw_bad_alloc();
}
}
void deallocate_many(multiallocation_chain &chain) BOOST_CONTAINER_NOEXCEPT
{/*
boost_cont_memchain ch;
void *beg(&*chain.begin()), *last(&*chain.last());
size_t size(chain.size());
BOOST_CONTAINER_MEMCHAIN_INIT_FROM(&ch, beg, last, size);
boost_cont_multidealloc(&ch);*/
boost_cont_multidealloc(reinterpret_cast<boost_cont_memchain *>(&chain));
}
//!Deallocates all free blocks of the pool
static void deallocate_free_blocks() BOOST_CONTAINER_NOEXCEPT
{
typedef container_detail::shared_adaptive_node_pool
<sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> shared_pool_t;
typedef container_detail::singleton_default<shared_pool_t> singleton_t;
singleton_t::instance().deallocate_free_blocks();
}
//!Swaps allocators. Does not throw. If each allocator is placed in a
//!different memory segment, the result is undefined.
friend void swap(adaptive_pool &, adaptive_pool &) BOOST_CONTAINER_NOEXCEPT
{}
//!An allocator always compares to true, as memory allocated with one
//!instance can be deallocated by another instance
friend bool operator==(const adaptive_pool &, const adaptive_pool &) BOOST_CONTAINER_NOEXCEPT
{ return true; }
//!An allocator always compares to false, as memory allocated with one
//!instance can be deallocated by another instance
friend bool operator!=(const adaptive_pool &, const adaptive_pool &) BOOST_CONTAINER_NOEXCEPT
{ return false; }
/*
//!Returns address of mutable object.
//!Never throws
pointer address(reference value) const
{ return pointer(boost::addressof(value)); }
//!Returns address of non mutable object.
//!Never throws
const_pointer address(const_reference value) const
{ return const_pointer(boost::addressof(value)); }
//!Default construct an object.
//!Throws if T's default constructor throws
void construct(const pointer &ptr)
{ new(ptr) value_type; }
//!Construct a copy of the passed object.
//!Throws if T's copy constructor throws
void construct(pointer ptr, const_reference t)
{ new(ptr) value_type(t); }
//!Destroys object. Throws if object's
//!destructor throws
void destroy(const pointer &ptr)
{ (void)ptr; BOOST_ASSERT(ptr); (*ptr).~value_type(); }
*/
private:
std::pair<pointer, bool> priv_allocation_command
(allocation_type command, std::size_t limit_size
,std::size_t preferred_size,std::size_t &received_size, void *reuse_ptr)
{
boost_cont_command_ret_t ret = {0 , 0};
if(limit_size > this->max_size() || preferred_size > this->max_size()){
// ret.first = 0;
return std::pair<pointer, bool>(pointer(), false);
}
std::size_t l_size = limit_size*sizeof(T);
std::size_t p_size = preferred_size*sizeof(T);
std::size_t r_size;
{
ret = boost_cont_allocation_command(command, sizeof(T), l_size, p_size, &r_size, reuse_ptr);
}
received_size = r_size/sizeof(T);
return std::pair<pointer, bool>(static_cast<pointer>(ret.first), !!ret.second);
}
};
} //namespace container {
} //namespace boost {
#include <boost/container/detail/config_end.hpp>
#endif //#ifndef BOOST_CONTAINER_ADAPTIVE_POOL_HPP

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -15,9 +15,10 @@
# pragma once
#endif
#include "config_begin.hpp"
#include <boost/container/container_fwd.hpp>
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/container_fwd.hpp>
#include <boost/container/detail/utilities.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/intrusive/set.hpp>

View File

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

View File

@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2012.
// (C) Copyright Ion Gaztanaga 2005-2013.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
@@ -17,7 +17,7 @@
# pragma once
#endif
#include "config_begin.hpp"
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/type_traits/has_trivial_copy.hpp>

View File

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

View File

@@ -0,0 +1,16 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_DETAIL_BOOST_CONT_EXT_AUTO_LINK_HPP
#define BOOST_CONTAINER_DETAIL_BOOST_CONT_EXT_AUTO_LINK_HPP
#include <boost/container/detail/auto_link.hpp>
#include <boost/container/detail/alloc_lib.h>
#endif //#ifndef BOOST_CONTAINER_DETAIL_BOOST_CONT_EXT_AUTO_LINK_HPP

View File

@@ -1,6 +1,6 @@
///////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -15,13 +15,13 @@
# pragma once
#endif
#include "config_begin.hpp"
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
namespace boost {
namespace container {
/// @cond
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
enum allocation_type_v
{
// constants for allocation commands
@@ -37,7 +37,7 @@ enum allocation_type_v
};
typedef int allocation_type;
/// @endcond
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
static const allocation_type allocate_new = (allocation_type)allocate_new_v;
static const allocation_type expand_fwd = (allocation_type)expand_fwd_v;
static const allocation_type expand_bwd = (allocation_type)expand_bwd_v;

View File

@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2012-2012. Distributed under the Boost
// (C) Copyright Ion Gaztanaga 2012-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -17,6 +17,7 @@
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/allocator_traits.hpp> //allocator_traits
#include <boost/container/throw_exception.hpp>
#include <boost/container/detail/multiallocation_chain.hpp> //multiallocation_chain

View File

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

View File

@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -18,6 +18,10 @@
#define BOOST_CONTAINER_DETAIL_CRT_SECURE_NO_DEPRECATE
#define _CRT_SECURE_NO_DEPRECATE
#endif
#ifndef _SCL_SECURE_NO_WARNINGS
#define BOOST_CONTAINER_DETAIL_SCL_SECURE_NO_WARNINGS
#define _SCL_SECURE_NO_WARNINGS
#endif
#pragma warning (push)
#pragma warning (disable : 4702) // unreachable code
#pragma warning (disable : 4706) // assignment within conditional expression

View File

@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -13,5 +13,9 @@
#undef BOOST_CONTAINER_DETAIL_CRT_SECURE_NO_DEPRECATE
#undef _CRT_SECURE_NO_DEPRECATE
#endif
#ifdef BOOST_CONTAINER_DETAIL_SCL_SECURE_NO_WARNINGS
#undef BOOST_CONTAINER_DETAIL_SCL_SECURE_NO_WARNINGS
#undef _SCL_SECURE_NO_WARNINGS
#endif
#endif

View File

@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2012.
// (C) Copyright Ion Gaztanaga 2005-2013.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
@@ -17,8 +17,9 @@
# pragma once
#endif
#include "config_begin.hpp"
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/detail/version_type.hpp>
#include <boost/container/detail/utilities.hpp>
#include <boost/container/allocator_traits.hpp>
@@ -231,6 +232,9 @@ struct null_scoped_destructor_n
void increment_size_backwards(size_type)
{}
void shrink_forward(size_type)
{}
void release()
{}
};

View File

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

View File

@@ -1,6 +1,6 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2009-2012.
// (C) Copyright Ion Gaztanaga 2009-2013.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at

View File

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

View File

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

View File

@@ -1,7 +1,7 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Stephen Cleary 2000.
// (C) Copyright Ion Gaztanaga 2007-2012.
// (C) Copyright Ion Gaztanaga 2007-2013.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
@@ -16,7 +16,9 @@
#ifndef BOOST_CONTAINER_DETAIL_MATH_FUNCTIONS_HPP
#define BOOST_CONTAINER_DETAIL_MATH_FUNCTIONS_HPP
#include "config_begin.hpp"
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <climits>
#include <boost/static_assert.hpp>

View File

@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2011-2012. Distributed under the Boost
// (C) Copyright Ion Gaztanaga 2011-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -17,20 +17,22 @@
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/detail/preprocessor.hpp>
#include <boost/intrusive/detail/memory_util.hpp>
#include <boost/intrusive/detail/has_member_function_callable_with.hpp>
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME allocate
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace container { namespace container_detail {
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
#define BOOST_PP_ITERATION_PARAMS_1 (3, (0, 2, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
#define BOOST_PP_ITERATION_PARAMS_1 (3, (2, 2, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
#include BOOST_PP_ITERATE()
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME destroy
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace container { namespace container_detail {
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
#define BOOST_PP_ITERATION_PARAMS_1 (3, (0, 3, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
#define BOOST_PP_ITERATION_PARAMS_1 (3, (1, 1, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
#include BOOST_PP_ITERATE()
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME max_size
@@ -48,20 +50,19 @@
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME construct
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace container { namespace container_detail {
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
#define BOOST_PP_ITERATION_PARAMS_1 (3, (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS+1, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
#define BOOST_PP_ITERATION_PARAMS_1 (3, (1, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS+1, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
#include BOOST_PP_ITERATE()
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME swap
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace container { namespace container_detail {
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
#define BOOST_PP_ITERATION_PARAMS_1 (3, (0, 1, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
#define BOOST_PP_ITERATION_PARAMS_1 (3, (1, 1, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
#include BOOST_PP_ITERATE()
namespace boost {
namespace container {
namespace container_detail {
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(pointer)
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(const_pointer)
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(reference)
@@ -73,6 +74,8 @@ BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(propagate_on_container_copy_assig
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(propagate_on_container_move_assignment)
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(propagate_on_container_swap)
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(difference_type)
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(value_compare)
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(wrapped_value_compare)
} //namespace container_detail {
} //namespace container {

View File

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

View File

@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,9 @@
#ifndef BOOST_CONTAINER_DETAIL_MULTIALLOCATION_CHAIN_HPP
#define BOOST_CONTAINER_DETAIL_MULTIALLOCATION_CHAIN_HPP
#include "config_begin.hpp"
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/container_fwd.hpp>
#include <boost/container/detail/utilities.hpp>
#include <boost/container/detail/type_traits.hpp>

View File

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

View File

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

View File

@@ -0,0 +1,157 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_DETAIL_NODE_POOL_HPP
#define BOOST_CONTAINER_DETAIL_NODE_POOL_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/detail/mutex.hpp>
#include <boost/container/detail/pool_common_alloc.hpp>
#include <boost/container/detail/node_pool_impl.hpp>
#include <boost/container/detail/mutex.hpp>
#include <boost/intrusive/slist.hpp>
#include <boost/move/move.hpp>
#include <cstddef>
#include <new>
#include <functional> //std::unary_function
#include <algorithm> //std::swap
#include <cassert>
namespace boost {
namespace container {
namespace container_detail {
//!Pooled memory allocator using single segregated storage. Includes
//!a reference count but the class does not delete itself, this is
//!responsibility of user classes. Node size (NodeSize) and the number of
//!nodes allocated per block (NodesPerBlock) are known at compile time
template< std::size_t NodeSize, std::size_t NodesPerBlock >
class private_node_pool
//Inherit from the implementation to avoid template bloat
: public boost::container::container_detail::
private_node_pool_impl<fake_segment_manager>
{
typedef boost::container::container_detail::
private_node_pool_impl<fake_segment_manager> base_t;
//Non-copyable
private_node_pool(const private_node_pool &);
private_node_pool &operator=(const private_node_pool &);
public:
typedef typename base_t::multiallocation_chain multiallocation_chain;
static const std::size_t nodes_per_block = NodesPerBlock;
//!Constructor from a segment manager. Never throws
private_node_pool()
: base_t(0, NodeSize, NodesPerBlock)
{}
};
template< std::size_t NodeSize
, std::size_t NodesPerBlock
>
class shared_node_pool
: public private_node_pool<NodeSize, NodesPerBlock>
{
private:
typedef private_node_pool<NodeSize, NodesPerBlock> private_node_allocator_t;
public:
typedef typename private_node_allocator_t::free_nodes_t free_nodes_t;
typedef typename private_node_allocator_t::multiallocation_chain multiallocation_chain;
//!Constructor from a segment manager. Never throws
shared_node_pool()
: private_node_allocator_t(){}
//!Destructor. Deallocates all allocated blocks. Never throws
~shared_node_pool()
{}
//!Allocates array of count elements. Can throw std::bad_alloc
void *allocate_node()
{
//-----------------------
scoped_lock<default_mutex> guard(mutex_);
//-----------------------
return private_node_allocator_t::allocate_node();
}
//!Deallocates an array pointed by ptr. Never throws
void deallocate_node(void *ptr)
{
//-----------------------
scoped_lock<default_mutex> guard(mutex_);
//-----------------------
private_node_allocator_t::deallocate_node(ptr);
}
//!Allocates a singly linked list of n nodes ending in null pointer.
//!can throw std::bad_alloc
void allocate_nodes(const std::size_t n, multiallocation_chain &chain)
{
//-----------------------
scoped_lock<default_mutex> guard(mutex_);
//-----------------------
return private_node_allocator_t::allocate_nodes(n, chain);
}
void deallocate_nodes(multiallocation_chain &chain)
{
//-----------------------
scoped_lock<default_mutex> guard(mutex_);
//-----------------------
private_node_allocator_t::deallocate_nodes(chain);
}
//!Deallocates all the free blocks of memory. Never throws
void deallocate_free_blocks()
{
//-----------------------
scoped_lock<default_mutex> guard(mutex_);
//-----------------------
private_node_allocator_t::deallocate_free_blocks();
}
//!Deallocates all blocks. Never throws
void purge_blocks()
{
//-----------------------
scoped_lock<default_mutex> guard(mutex_);
//-----------------------
private_node_allocator_t::purge_blocks();
}
std::size_t num_free_nodes()
{
//-----------------------
scoped_lock<default_mutex> guard(mutex_);
//-----------------------
return private_node_allocator_t::num_free_nodes();
}
private:
default_mutex mutex_;
};
} //namespace container_detail {
} //namespace container {
} //namespace boost {
#include <boost/container/detail/config_end.hpp>
#endif //#ifndef BOOST_CONTAINER_DETAIL_NODE_POOL_HPP

View File

@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -15,9 +15,10 @@
# pragma once
#endif
#include "config_begin.hpp"
#include <boost/container/container_fwd.hpp>
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/container_fwd.hpp>
#include <boost/container/detail/utilities.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/intrusive/set.hpp>
@@ -29,8 +30,6 @@
#include <boost/detail/no_exceptions_support.hpp>
#include <boost/assert.hpp>
#include <cstddef>
#include <functional> //std::unary_function
namespace boost {
namespace container {
@@ -251,8 +250,10 @@ class private_node_pool_impl
};
struct is_between
: std::unary_function<typename free_nodes_t::value_type, bool>
{
typedef typename free_nodes_t::value_type argument_type;
typedef bool result_type;
is_between(const void *addr, std::size_t size)
: beg_(static_cast<const char *>(addr)), end_(beg_+size)
{}

View File

@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2012.
// (C) Copyright Ion Gaztanaga 2005-2013.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
@@ -17,7 +17,7 @@
# pragma once
#endif
#include "config_begin.hpp"
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/detail/mpl.hpp>

View File

@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -8,14 +8,16 @@
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_DETAIL_NODE_POOL_COMMON_HPP
#define BOOST_CONTAINER_DETAIL_NODE_POOL_COMMON_HPP
#ifndef BOOST_CONTAINER_DETAIL_POOL_COMMON_HPP
#define BOOST_CONTAINER_DETAIL_POOL_COMMON_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include "config_begin.hpp"
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/intrusive/slist.hpp>
#include <new>

View File

@@ -0,0 +1,94 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_DETAIL_POOL_COMMON_ALLOC_HPP
#define BOOST_CONTAINER_DETAIL_POOL_COMMON_ALLOC_HPP
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/throw_exception.hpp>
#include <boost/intrusive/slist.hpp>
#include <boost/container/detail/pool_common.hpp>
#include <boost/container/detail/alloc_lib.h>
#include <cstddef>
namespace boost{
namespace container{
namespace container_detail{
struct node_slist_helper
: public boost::container::container_detail::node_slist<void*>
{};
struct fake_segment_manager
{
typedef void * void_pointer;
static const std::size_t PayloadPerAllocation = BOOST_CONTAINER_ALLOCATION_PAYLOAD;
typedef boost::container::container_detail::
basic_multiallocation_chain<void*> multiallocation_chain;
static void deallocate(void_pointer p)
{ boost_cont_free(p); }
static void deallocate_many(multiallocation_chain &chain)
{
std::size_t size = chain.size();
std::pair<void*, void*> ptrs = chain.extract_data();
boost_cont_memchain dlchain;
BOOST_CONTAINER_MEMCHAIN_INIT_FROM(&dlchain, ptrs.first, ptrs.second, size);
boost_cont_multidealloc(&dlchain);
}
typedef std::ptrdiff_t difference_type;
typedef std::size_t size_type;
static void *allocate_aligned(std::size_t nbytes, std::size_t alignment)
{
void *ret = boost_cont_memalign(nbytes, alignment);
if(!ret)
boost::container::throw_bad_alloc();
return ret;
}
static void *allocate(std::size_t nbytes)
{
void *ret = boost_cont_malloc(nbytes);
if(!ret)
boost::container::throw_bad_alloc();
return ret;
}
};
} //namespace boost{
} //namespace container{
} //namespace container_detail{
namespace boost {
namespace container {
namespace container_detail {
template<class T>
struct is_stateless_segment_manager;
template<>
struct is_stateless_segment_manager
<boost::container::container_detail::fake_segment_manager>
{
static const bool value = true;
};
} //namespace container_detail {
} //namespace container {
} //namespace boost {
#include <boost/container/detail/config_end.hpp>
#endif //BOOST_CONTAINER_DETAIL_POOL_COMMON_ALLOC_HPP

View File

@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost
// (C) Copyright Ion Gaztanaga 2008-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//

View File

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

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
// (C) Copyright John Maddock 2000.
// (C) Copyright Ion Gaztanaga 2005-2012.
// (C) Copyright Ion Gaztanaga 2005-2013.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
@@ -19,7 +19,8 @@
# pragma once
#endif
#include "config_begin.hpp"
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/move/utility.hpp>

View File

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

View File

@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2012.
// (C) Copyright Ion Gaztanaga 2005-2013.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
@@ -17,7 +17,7 @@
# pragma once
#endif
#include "config_begin.hpp"
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
namespace boost {

View File

@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost
// (C) Copyright Ion Gaztanaga 2008-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -15,8 +15,9 @@
# pragma once
#endif
#include "config_begin.hpp"
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/detail/type_traits.hpp>
#include <cstddef> //std::size_t

View File

@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -16,7 +16,8 @@
#ifndef BOOST_CONTAINER_DETAIL_VERSION_TYPE_HPP
#define BOOST_CONTAINER_DETAIL_VERSION_TYPE_HPP
#include "config_begin.hpp"
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/type_traits.hpp>
@@ -87,6 +88,6 @@ struct version
} //namespace container {
} //namespace boost{
#include "config_end.hpp"
#include <boost/container/detail/config_end.hpp>
#endif //#define BOOST_CONTAINER_DETAIL_VERSION_TYPE_HPP

View File

@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//

View File

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

File diff suppressed because it is too large Load Diff

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2011-2012. Distributed under the Boost
// (C) Copyright Ion Gaztanaga 2011-2013. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,6 +11,10 @@
#ifndef BOOST_CONTAINER_ALLOCATOR_SCOPED_ALLOCATOR_FWD_HPP
#define BOOST_CONTAINER_ALLOCATOR_SCOPED_ALLOCATOR_FWD_HPP
//! \file
//! This header file forward declares boost::container::scoped_allocator_adaptor
//! and defines the following types:
#if defined(_MSC_VER)
# pragma once
#endif
@@ -25,7 +29,7 @@
namespace boost { namespace container {
///@cond
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
@@ -55,7 +59,7 @@ class scoped_allocator_adaptor;
#endif
///@endcond
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//! The allocator_arg_t struct is an empty structure type used as a unique type to
//! disambiguate constructor and function overloading. Specifically, several types

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
<!--
Copyright 2005-2012 Ion Gaztanaga
Copyright 2005-2013 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)
-->

View File

@@ -60,4 +60,6 @@ Add hash for containers
Add std:: hashing support
Fix trivial destructor after move and other optimizing traits
Fix trivial destructor after move and other optimizing traits
Implement n3586, "Splicing Maps and Sets" (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3586.pdf)

View File

@@ -0,0 +1,138 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="alloc_basic_test"
ProjectGUID="{CD57C283-1862-42FE-BF87-B96D3A2A7912}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="../../Bin/Win32/Debug"
IntermediateDirectory="Debug/alloc_basic_test"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="BOOST_CONTAINER_NO_LIB"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
TreatWChar_tAsBuiltInType="TRUE"
ForceConformanceInForLoopScope="FALSE"
UsePrecompiledHeader="0"
WarningLevel="4"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="alloc_lib.lib"
OutputFile="$(OutDir)/alloc_basic_test_d.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../bin/debug"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/alloc_basic_test.pdb"
SubSystem="1"
TargetMachine="1"
FixedBaseAddress="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="../../Bin/Win32/Release"
IntermediateDirectory="Release/alloc_basic_test"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="WIN32;NDEBUG;BOOST_CONTAINER_NO_LIB"
RuntimeLibrary="2"
TreatWChar_tAsBuiltInType="TRUE"
ForceConformanceInForLoopScope="FALSE"
UsePrecompiledHeader="0"
WarningLevel="4"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib alloc_lib.lib"
OutputFile="$(OutDir)/alloc_basic_test.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../bin/release"
GenerateDebugInformation="TRUE"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{34957FC1-7BC5-1646-05A6-27542AA2A2FF}">
<File
RelativePath="..\..\test\alloc_basic_test.cpp">
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93A78280-B78D-4B31-7E8B-6255ACE1E5FB}">
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -0,0 +1,133 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="alloc_full_test"
ProjectGUID="{CD57C283-1862-9FE5-BF87-BA91293A76D3}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="../../Bin/Win32/Debug"
IntermediateDirectory="Debug/alloc_full_test"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="BOOST_CONTAINER_NO_LIB"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
TreatWChar_tAsBuiltInType="TRUE"
ForceConformanceInForLoopScope="FALSE"
UsePrecompiledHeader="0"
WarningLevel="4"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="alloc_lib.lib"
OutputFile="$(OutDir)/alloc_full_test_d.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../bin/debug"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/alloc_full_test.pdb"
SubSystem="1"
TargetMachine="1"
FixedBaseAddress="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="../../Bin/Win32/Release"
IntermediateDirectory="Release/alloc_full_test"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="WIN32;NDEBUG;BOOST_CONTAINER_NO_LIB"
RuntimeLibrary="2"
TreatWChar_tAsBuiltInType="TRUE"
ForceConformanceInForLoopScope="FALSE"
UsePrecompiledHeader="0"
WarningLevel="4"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib alloc_lib.lib"
OutputFile="$(OutDir)/alloc_full_test.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../bin/release"
GenerateDebugInformation="TRUE"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{3857F2C1-BC75-1646-05A6-2AF850A42A2E}">
<File
RelativePath="..\..\test\alloc_full_test.cpp">
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -0,0 +1,199 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="_alloc_lib"
ProjectGUID="{685AC59C-E667-4096-9DAA-AB76083C7092}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="..\..\Bin\Debug"
IntermediateDirectory="Debug"
ConfigurationType="4"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\..\.."
PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLibrarianTool"
OutputFile="$(OutDir)/alloc_lib.lib"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="..\..\Bin\Release"
IntermediateDirectory="Release"
ConfigurationType="4"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\..\.."
PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
RuntimeLibrary="2"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLibrarianTool"
OutputFile="$(OutDir)/alloc_lib.lib"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
<File
RelativePath="..\..\src\alloc_lib.c">
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
<File
RelativePath="..\..\..\..\boost\container\adaptive_pool.hpp">
</File>
<File
RelativePath="..\..\..\..\boost\container\allocator.hpp">
</File>
<File
RelativePath="..\..\..\..\boost\container\node_allocator.hpp">
</File>
<Filter
Name="detail"
Filter="">
<File
RelativePath="..\..\..\..\boost\container\detail\adaptive_node_pool.hpp">
</File>
<File
RelativePath="..\..\..\..\boost\container\detail\alloc_lib.h">
</File>
<File
RelativePath="..\..\..\..\boost\container\detail\alloc_lib_auto_link.hpp">
</File>
<File
RelativePath="..\..\..\..\boost\container\detail\auto_link.hpp">
</File>
<File
RelativePath="..\..\..\..\boost\container\detail\mutex.hpp">
</File>
<File
RelativePath="..\..\..\..\boost\container\detail\node_pool.hpp">
</File>
<File
RelativePath="..\..\..\..\boost\container\detail\pool_common_alloc.hpp">
</File>
<File
RelativePath="..\..\..\..\boost\container\detail\singleton.hpp">
</File>
<Filter
Name="Included Sources"
Filter="">
<File
RelativePath="..\..\src\dlmalloc_2_8_6.c">
<FileConfiguration
Name="Debug|Win32"
ExcludedFromBuild="TRUE">
<Tool
Name="VCCLCompilerTool"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
ExcludedFromBuild="TRUE">
<Tool
Name="VCCLCompilerTool"/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\src\dlmalloc_ext_2_8_6.c">
<FileConfiguration
Name="Debug|Win32"
ExcludedFromBuild="TRUE">
<Tool
Name="VCCLCompilerTool"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
ExcludedFromBuild="TRUE">
<Tool
Name="VCCLCompilerTool"/>
</FileConfiguration>
</File>
</Filter>
</Filter>
</Filter>
<Filter
Name="test"
Filter="">
<File
RelativePath="..\..\test\Jamfile.v2">
</File>
</Filter>
<Filter
Name="doc"
Filter="">
<File
RelativePath="..\..\doc\Applying classic memory allocation improvements to C++ containers.html">
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -20,7 +20,7 @@
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
GeneratePreprocessedFile="0"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
@@ -74,7 +74,7 @@
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
TreatWChar_tAsBuiltInType="TRUE"
ForceConformanceInForLoopScope="FALSE"
@@ -128,14 +128,6 @@
RelativePath="..\..\test\allocator_traits_test.cpp">
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93815995-89BD-b043-5E8B-65FBE52E2AFB}">
<File
RelativePath="..\..\..\..\boost\container\detail\node_alloc_holder.hpp">
</File>
</Filter>
</Files>
<Globals>
</Globals>

View File

@@ -0,0 +1,133 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="bench_adaptive_node_pool"
ProjectGUID="{C8AD2618-79EB-8612-42FE-2A3AC9667A13}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="../../Bin/Win32/Debug"
IntermediateDirectory="Debug/bench_adaptive_node_pool"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="BOOST_CONTAINER_NO_LIB"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
TreatWChar_tAsBuiltInType="TRUE"
ForceConformanceInForLoopScope="FALSE"
UsePrecompiledHeader="0"
WarningLevel="4"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="alloc_lib.lib"
OutputFile="$(OutDir)/bench_adaptive_node_pool_d.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../bin/debug;../../../../stage/lib"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/bench_adaptive_node_pool.pdb"
SubSystem="1"
TargetMachine="1"
FixedBaseAddress="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="../../Bin/Win32/Release"
IntermediateDirectory="Release/bench_adaptive_node_pool"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="WIN32;NDEBUG;BOOST_CONTAINER_NO_LIB"
RuntimeLibrary="2"
TreatWChar_tAsBuiltInType="TRUE"
ForceConformanceInForLoopScope="FALSE"
UsePrecompiledHeader="0"
WarningLevel="4"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib alloc_lib.lib"
OutputFile="$(OutDir)/bench_adaptive_node_pool.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../bin/release;../../../../stage/lib"
GenerateDebugInformation="TRUE"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{818563C3-6640-0A65-55CB-202E5BAD7FAF}">
<File
RelativePath="..\..\bench\bench_adaptive_node_pool.cpp">
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -0,0 +1,133 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="bench_alloc"
ProjectGUID="{7CC83A22-8612-7BF8-2F4E-BD9493C6A071}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="../../Bin/Win32/Debug"
IntermediateDirectory="Debug/bench_alloc"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="BOOST_CONTAINER_NO_LIB"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
TreatWChar_tAsBuiltInType="TRUE"
ForceConformanceInForLoopScope="FALSE"
UsePrecompiledHeader="0"
WarningLevel="4"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="alloc_lib.lib"
OutputFile="$(OutDir)/bench_alloc_d.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../bin/debug;../../../../stage/lib"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/bench_alloc.pdb"
SubSystem="1"
TargetMachine="1"
FixedBaseAddress="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="../../Bin/Win32/Release"
IntermediateDirectory="Release/bench_alloc"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="WIN32;NDEBUG;BOOST_CONTAINER_NO_LIB"
RuntimeLibrary="2"
TreatWChar_tAsBuiltInType="TRUE"
ForceConformanceInForLoopScope="FALSE"
UsePrecompiledHeader="0"
WarningLevel="4"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib alloc_lib.lib"
OutputFile="$(OutDir)/bench_alloc.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../bin/release;../../../../stage/lib"
GenerateDebugInformation="TRUE"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{D127F725-A615-C5B6-6640-27A2AE5757AF}">
<File
RelativePath="..\..\bench\bench_alloc.cpp">
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -0,0 +1,133 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="bench_alloc_expand_bwd"
ProjectGUID="{C7C283A2-7BF8-8612-42FE-B9D26A0793A1}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="../../Bin/Win32/Debug"
IntermediateDirectory="Debug/bench_alloc_expand_bwd"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="BOOST_CONTAINER_NO_LIB"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
TreatWChar_tAsBuiltInType="TRUE"
ForceConformanceInForLoopScope="FALSE"
UsePrecompiledHeader="0"
WarningLevel="4"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="alloc_lib.lib"
OutputFile="$(OutDir)/bench_alloc_expand_bwd_d.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../bin/debug;../../../../stage/lib"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/bench_alloc_expand_bwd.pdb"
SubSystem="1"
TargetMachine="1"
FixedBaseAddress="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="../../Bin/Win32/Release"
IntermediateDirectory="Release/bench_alloc_expand_bwd"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="WIN32;NDEBUG;BOOST_CONTAINER_NO_LIB"
RuntimeLibrary="2"
TreatWChar_tAsBuiltInType="TRUE"
ForceConformanceInForLoopScope="FALSE"
UsePrecompiledHeader="0"
WarningLevel="4"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib alloc_lib.lib"
OutputFile="$(OutDir)/bench_alloc_expand_bwd.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../bin/release;../../../../stage/lib"
GenerateDebugInformation="TRUE"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{D1217F85-BC56-6640-05A6-247AF7A2A58F}">
<File
RelativePath="..\..\bench\bench_alloc_expand_bwd.cpp">
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -0,0 +1,133 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="bench_alloc_expand_fwd"
ProjectGUID="{C7C283A2-7BF8-8612-42FE-B9D26A0793A1}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="../../Bin/Win32/Debug"
IntermediateDirectory="Debug/bench_alloc_expand_fwd"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="BOOST_CONTAINER_NO_LIB"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
TreatWChar_tAsBuiltInType="TRUE"
ForceConformanceInForLoopScope="FALSE"
UsePrecompiledHeader="0"
WarningLevel="4"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="alloc_lib.lib"
OutputFile="$(OutDir)/bench_alloc_expand_fwd_d.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../bin/debug;../../../../stage/lib"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/bench_alloc_expand_fwd.pdb"
SubSystem="1"
TargetMachine="1"
FixedBaseAddress="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="../../Bin/Win32/Release"
IntermediateDirectory="Release/bench_alloc_expand_fwd"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="WIN32;NDEBUG;BOOST_CONTAINER_NO_LIB"
RuntimeLibrary="2"
TreatWChar_tAsBuiltInType="TRUE"
ForceConformanceInForLoopScope="FALSE"
UsePrecompiledHeader="0"
WarningLevel="4"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib alloc_lib.lib"
OutputFile="$(OutDir)/bench_alloc_expand_fwd.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../bin/release;../../../../stage/lib"
GenerateDebugInformation="TRUE"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{D1217F85-BC56-6640-05A6-247AF7A2A58F}">
<File
RelativePath="..\..\bench\bench_alloc_expand_fwd.cpp">
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -0,0 +1,133 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="bench_alloc_shrink_to_fit"
ProjectGUID="{C7C283A2-7BF8-8612-42FE-B9D26A0793A1}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="../../Bin/Win32/Debug"
IntermediateDirectory="Debug/bench_alloc_shrink_to_fit"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="BOOST_CONTAINER_NO_LIB"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
TreatWChar_tAsBuiltInType="TRUE"
ForceConformanceInForLoopScope="FALSE"
UsePrecompiledHeader="0"
WarningLevel="4"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="alloc_lib.lib"
OutputFile="$(OutDir)/bench_alloc_shrink_to_fit_d.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../bin/debug;../../../../stage/lib"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/bench_alloc_shrink_to_fit.pdb"
SubSystem="1"
TargetMachine="1"
FixedBaseAddress="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="../../Bin/Win32/Release"
IntermediateDirectory="Release/bench_alloc_shrink_to_fit"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="WIN32;NDEBUG;BOOST_CONTAINER_NO_LIB"
RuntimeLibrary="2"
TreatWChar_tAsBuiltInType="TRUE"
ForceConformanceInForLoopScope="FALSE"
UsePrecompiledHeader="0"
WarningLevel="4"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib alloc_lib.lib"
OutputFile="$(OutDir)/bench_alloc_shrink_to_fit.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../bin/release;../../../../stage/lib"
GenerateDebugInformation="TRUE"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{D1217F85-BC56-6640-05A6-247AF7A2A58F}">
<File
RelativePath="..\..\bench\bench_alloc_shrink_to_fit.cpp">
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -0,0 +1,134 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="bench_alloc_stable_vector_burst_allocation"
ProjectGUID="{C3AD2582-79BF-2FE1-8612-BD707552A6A1}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="../../Bin/Win32/Debug"
IntermediateDirectory="Debug/bench_alloc_stable_vector_burst_allocation"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="BOOST_CONTAINER_NO_LIB"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
TreatWChar_tAsBuiltInType="TRUE"
ForceConformanceInForLoopScope="FALSE"
UsePrecompiledHeader="0"
WarningLevel="4"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="alloc_lib.lib"
OutputFile="$(OutDir)/bench_alloc_stable_vector_burst_allocation_d.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../bin/debug;../../../../stage/lib"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/bench_alloc_stable_vector_burst_allocation.pdb"
SubSystem="1"
TargetMachine="1"
FixedBaseAddress="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="../../Bin/Win32/Release"
IntermediateDirectory="Release/bench_alloc_stable_vector_burst_allocation"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="1"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="WIN32;NDEBUG;BOOST_CONTAINER_NO_LIB"
RuntimeLibrary="2"
TreatWChar_tAsBuiltInType="TRUE"
ForceConformanceInForLoopScope="FALSE"
UsePrecompiledHeader="0"
WarningLevel="4"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib alloc_lib.lib"
OutputFile="$(OutDir)/bench_alloc_stable_vector_burst_allocation.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../bin/release;../../../../stage/lib"
GenerateDebugInformation="TRUE"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{D80184F5-6450-3A65-55CB-2375A7BCDAEF}">
<File
RelativePath="..\..\bench\bench_alloc_stable_vector_burst_allocation.cpp">
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -0,0 +1,134 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="bench_flat_multiset"
ProjectGUID="{E5C01323-3F2C-D074-F4A9-D16B31CC275B}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="../../Bin/Win32/Debug"
IntermediateDirectory="Debug/bench_flat_multiset"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="TRUE"
ExceptionHandling="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
TreatWChar_tAsBuiltInType="TRUE"
ForceConformanceInForLoopScope="FALSE"
UsePrecompiledHeader="0"
WarningLevel="4"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib"
OutputFile="$(OutDir)/bench_flat_multiset_d.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../../../stage/lib"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/bench_flat_multiset.pdb"
SubSystem="1"
TargetMachine="1"
FixedBaseAddress="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="../../Bin/Win32/Release"
IntermediateDirectory="Release/bench_flat_multiset"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
TreatWChar_tAsBuiltInType="TRUE"
ForceConformanceInForLoopScope="FALSE"
UsePrecompiledHeader="0"
WarningLevel="4"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib"
OutputFile="$(OutDir)/bench_flat_multiset.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../../../stage/lib"
GenerateDebugInformation="TRUE"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{CF7232AE-72A6-3417-8ABF-5418BA30DA7A}">
<File
RelativePath="..\..\bench\bench_flat_multiset.cpp">
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

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