Fixed ABI regression introduced in Boost 1.55

This commit is contained in:
Ion Gaztañaga
2014-01-30 14:22:04 +01:00
parent f162078264
commit 2ffe6b2f82
23 changed files with 971 additions and 1165 deletions
+187
View File
@@ -0,0 +1,187 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2014-2014
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#include <boost/intrusive/detail/config_begin.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <cstddef>
#include <boost/intrusive/list.hpp>
#include <boost/intrusive/slist.hpp>
#include <boost/intrusive/set.hpp>
#include <boost/intrusive/avl_set.hpp>
#include <boost/intrusive/bs_set.hpp>
#include <boost/intrusive/sg_set.hpp>
#include <boost/intrusive/splay_set.hpp>
#include <boost/intrusive/treap_set.hpp>
#include <boost/intrusive/unordered_set.hpp>
#include <boost/static_assert.hpp>
using namespace boost::intrusive;
template<bool Value>
struct boolean
{
static const bool value = Value;
};
template<class A, class B>
struct pow2_and_equal_sizes
{
static const std::size_t a_size = sizeof(A);
static const std::size_t b_size = sizeof(B);
static const bool a_b_sizes_equal = a_size == b_size;
static const bool value = !(a_size & (a_size - 1u));
};
template<class Hook>
struct node : Hook
{};
//Avoid testing for uncommon architectures
void test_sizes(boolean<false>, std::size_t)
{}
template<class C>
void test_iterator_sizes(C &, std::size_t size)
{
typedef typename C::iterator iterator;
typedef typename C::const_iterator const_iterator;
BOOST_TEST_EQ(sizeof(iterator), size);
BOOST_TEST_EQ(sizeof(const_iterator), size);
}
//Test sizes for common 32 and 64 bit architectures
void test_sizes(boolean<true>, std::size_t wordsize)
{
{ //list
list<node< node<list_base_hook<> > > > c;
BOOST_TEST_EQ(sizeof(c), wordsize*3);
test_iterator_sizes(c, wordsize);
}
{
list<node< node<list_base_hook<> > >, constant_time_size<false> > c;
BOOST_TEST_EQ(sizeof(c), wordsize*2);
test_iterator_sizes(c, wordsize);
}
{ //slist
slist<node< node< slist_base_hook<> > > > c;
BOOST_TEST_EQ(sizeof(c), wordsize*2);
test_iterator_sizes(c, wordsize);
}
{
slist<node< node< slist_base_hook<> > > , constant_time_size<false> > c;
BOOST_TEST_EQ(sizeof(c), wordsize*1);
test_iterator_sizes(c, wordsize);
}
{
slist<node< node< slist_base_hook<> > > , cache_last<true> > c;
BOOST_TEST_EQ(sizeof(c), wordsize*3);
test_iterator_sizes(c, wordsize);
}
{ //set
set<node< node< set_base_hook<> > > > c;
BOOST_TEST_EQ(sizeof(c), wordsize*5);
test_iterator_sizes(c, wordsize);
}
{
set<node< node< set_base_hook<> > > , constant_time_size<false> > c;
BOOST_TEST_EQ(sizeof(c), wordsize*4);
test_iterator_sizes(c, wordsize);
}
{
set<node< node< set_base_hook<optimize_size<true> > > > , constant_time_size<false> > c;
BOOST_TEST_EQ(sizeof(c), wordsize*3);
test_iterator_sizes(c, wordsize);
}
{ //avl
avl_set<node< node< avl_set_base_hook<> > > > c;
BOOST_TEST_EQ(sizeof(c), wordsize*5);
test_iterator_sizes(c, wordsize);
}
{
avl_set<node< node< avl_set_base_hook<> > > , constant_time_size<false> > c;
BOOST_TEST_EQ(sizeof(c), wordsize*4);
test_iterator_sizes(c, wordsize);
}
{
avl_set<node< node< avl_set_base_hook<optimize_size<true> > > > , constant_time_size<false> > c;
BOOST_TEST_EQ(sizeof(c), wordsize*3);
test_iterator_sizes(c, wordsize);
}
{ //splay
splay_set<node< node< bs_set_base_hook<> > > > c;
BOOST_TEST_EQ(sizeof(c), wordsize*4);
test_iterator_sizes(c, wordsize);
}
{
splay_set<node< node< bs_set_base_hook<> > > , constant_time_size<false> > c;
BOOST_TEST_EQ(sizeof(c), wordsize*3);
test_iterator_sizes(c, wordsize);
}
{ //scapegoat
sg_set<node< bs_set_base_hook<> > > c;
BOOST_TEST_EQ(sizeof(c), (wordsize*5+sizeof(float)*2));
test_iterator_sizes(c, wordsize);
}
{ //treap
treap_set<node< bs_set_base_hook<> > > c;
BOOST_TEST_EQ(sizeof(c), wordsize*4);
test_iterator_sizes(c, wordsize);
}
{
treap_set<node< bs_set_base_hook<> > , constant_time_size<false> > c;
BOOST_TEST_EQ(sizeof(c), wordsize*3);
test_iterator_sizes(c, wordsize);
}
{ //unordered
typedef unordered_set<node< unordered_set_base_hook<> > > cont_type;
cont_type::bucket_type buckets[1];
cont_type c(cont_type::bucket_traits(buckets, 1));
BOOST_TEST_EQ(sizeof(c), wordsize*3);
test_iterator_sizes(c, wordsize*2);
}
{
typedef unordered_set<node< unordered_set_base_hook<> > , power_2_buckets<true> > cont_type;
cont_type::bucket_type buckets[1];
cont_type c(cont_type::bucket_traits(buckets, 1));
BOOST_TEST_EQ(sizeof(c), wordsize*3);
test_iterator_sizes(c, wordsize*2);
}
{
typedef unordered_set<node< unordered_set_base_hook<> >, constant_time_size<false> > cont_type;
cont_type::bucket_type buckets[1];
cont_type c(cont_type::bucket_traits(buckets, 1));
BOOST_TEST_EQ(sizeof(c), wordsize*2);
test_iterator_sizes(c, wordsize*2);
}
{
typedef unordered_set<node< unordered_set_base_hook< optimize_multikey<true> > >, constant_time_size<false> > cont_type;
cont_type::bucket_type buckets[1];
cont_type c(cont_type::bucket_traits(buckets, 1));
BOOST_TEST_EQ(sizeof(c), wordsize*2);
test_iterator_sizes(c, wordsize*2);
}
{
typedef unordered_set<node< unordered_set_base_hook< optimize_multikey<true> > >, incremental<true> > cont_type;
cont_type::bucket_type buckets[1];
cont_type c(cont_type::bucket_traits(buckets, 1));
BOOST_TEST_EQ(sizeof(c), wordsize*4);
test_iterator_sizes(c, wordsize*2);
}
}
int main()
{
test_sizes(boolean< pow2_and_equal_sizes<std::size_t, void*>::value >(), sizeof(std::size_t));
return ::boost::report_errors();
}
#include <boost/intrusive/detail/config_end.hpp>
-241
View File
@@ -1,241 +0,0 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2007-2013
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#include <boost/intrusive/list.hpp>
#include <boost/intrusive/slist.hpp>
#include <boost/intrusive/rbtree.hpp>
#include <boost/intrusive/hashtable.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include <functional>
#include <vector>
using namespace boost::intrusive;
class MyClass
{
public:
int int_;
MyClass(int i = 0)
: int_(i)
{}
friend bool operator > (const MyClass &l, const MyClass &r)
{ return l.int_ > r.int_; }
friend bool operator == (const MyClass &l, const MyClass &r)
{ return l.int_ == r.int_; }
friend std::size_t hash_value(const MyClass &v)
{ return boost::hash_value(v.int_); }
};
const int NumElements = 100;
template<class NodeTraits>
struct external_traits
{
typedef NodeTraits node_traits;
typedef typename node_traits::node node;
typedef typename node_traits::node_ptr node_ptr;
typedef typename node_traits::const_node_ptr const_node_ptr;
typedef MyClass value_type;
typedef typename pointer_traits<node_ptr>::
template rebind_pointer<MyClass>::type pointer;
typedef typename pointer_traits<node_ptr>::
template rebind_pointer
<const MyClass>::type const_pointer;
static const link_mode_type link_mode = normal_link;
external_traits(pointer values, std::size_t NumElem)
: values_(values), node_array_(NumElem)
{}
node_ptr to_node_ptr (value_type &value)
{ return (&node_array_[0]) + (&value - values_); }
const_node_ptr to_node_ptr (const value_type &value) const
{ return &node_array_[0] + (&value - values_); }
pointer to_value_ptr(node_ptr n)
{ return values_ + (n - &node_array_[0]); }
const_pointer to_value_ptr(const_node_ptr n) const
{ return values_ + (n - &node_array_[0]); }
pointer values_;
std::vector<node> node_array_;
};
template<class NodeTraits>
struct value_traits_proxy;
template<class T>
struct traits_holder
: public T
{};
typedef value_traits_proxy<list_node_traits<void*> > list_value_traits_proxy;
typedef value_traits_proxy<slist_node_traits<void*> > slist_value_traits_proxy;
typedef value_traits_proxy<rbtree_node_traits<void*> > rbtree_value_traits_proxy;
typedef value_traits_proxy<traits_holder<slist_node_traits<void*> > > hash_value_traits_proxy;
struct uset_bucket_traits
{
private:
typedef unordered_bucket<value_traits<external_traits
<traits_holder<slist_node_traits<void*> > > > >::type bucket_type;
//Non-copyable
uset_bucket_traits(const uset_bucket_traits &other);
uset_bucket_traits & operator=(const uset_bucket_traits &other);
public:
static const std::size_t NumBuckets = 100;
uset_bucket_traits(){}
bucket_type * bucket_begin() const
{ return buckets_; }
std::size_t bucket_count() const
{ return NumBuckets; }
mutable bucket_type buckets_[NumBuckets];
};
struct bucket_traits_proxy
{
static const bool external_bucket_traits = true;
typedef uset_bucket_traits bucket_traits;
template<class Container>
bucket_traits &get_bucket_traits(Container &cont);
template<class Container>
const bucket_traits &get_bucket_traits(const Container &cont) const;
};
//Define a list that will store MyClass using the external hook
typedef list<MyClass, value_traits<list_value_traits_proxy> > List;
//Define a slist that will store MyClass using the external hook
typedef slist<MyClass, value_traits<slist_value_traits_proxy> > Slist;
//Define a rbtree that will store MyClass using the external hook
typedef rbtree< MyClass
, value_traits<rbtree_value_traits_proxy>
, compare<std::greater<MyClass> > > Rbtree;
//Define a hashtable that will store MyClass using the external hook
typedef hashtable< MyClass
, value_traits<hash_value_traits_proxy>
, bucket_traits<bucket_traits_proxy>
> Hash;
template<class NodeTraits>
struct value_traits_proxy
{
static const bool external_value_traits = true;
typedef external_traits<NodeTraits> value_traits;
template<class Container>
const value_traits &get_value_traits(const Container &cont) const;
template<class Container>
value_traits &get_value_traits(Container &cont);
};
struct ContainerHolder
: public uset_bucket_traits
, public List
, public external_traits<list_node_traits<void*> >
, public Slist
, public external_traits<slist_node_traits<void*> >
, public Rbtree
, public external_traits<rbtree_node_traits<void*> >
, public Hash
, public external_traits<traits_holder<slist_node_traits<void*> > >
{
static const std::size_t NumBucket = 100;
ContainerHolder(MyClass *values, std::size_t num_elem)
: uset_bucket_traits()
, List()
, external_traits<list_node_traits<void*> >(values, num_elem)
, Slist()
, external_traits<slist_node_traits<void*> >(values, num_elem)
, Rbtree()
, external_traits<rbtree_node_traits<void*> >(values, num_elem)
, Hash(Hash::bucket_traits())
, external_traits<traits_holder<slist_node_traits<void*> > >(values, num_elem)
{}
};
template<class NodeTraits>
template<class Container>
typename value_traits_proxy<NodeTraits>::value_traits &
value_traits_proxy<NodeTraits>::get_value_traits(Container &cont)
{ return static_cast<value_traits&>(static_cast<ContainerHolder&>(cont)); }
template<class NodeTraits>
template<class Container>
const typename value_traits_proxy<NodeTraits>::value_traits &
value_traits_proxy<NodeTraits>::get_value_traits(const Container &cont) const
{ return static_cast<const value_traits&>(static_cast<const ContainerHolder&>(cont)); }
template<class Container>
typename bucket_traits_proxy::bucket_traits &
bucket_traits_proxy::get_bucket_traits(Container &cont)
{ return static_cast<bucket_traits&>(static_cast<ContainerHolder&>(cont)); }
template<class Container>
const typename bucket_traits_proxy::bucket_traits &
bucket_traits_proxy::get_bucket_traits(const Container &cont) const
{ return static_cast<const bucket_traits&>(static_cast<const ContainerHolder&>(cont)); }
int main()
{
MyClass values [NumElements];
//Create several MyClass objects, each one with a different value
for(int i = 0; i < NumElements; ++i)
values[i].int_ = i;
ContainerHolder cont_holder(values, NumElements);
List &my_list = static_cast<List &> (cont_holder);
Slist &my_slist = static_cast<Slist &> (cont_holder);
Rbtree &my_rbtree = static_cast<Rbtree &> (cont_holder);
Hash &my_hash = static_cast<Hash &> (cont_holder);
//Now insert them in containers
for(MyClass * it(&values[0]), *itend(&values[NumElements])
; it != itend; ++it){
my_list.push_front(*it);
my_slist.push_front(*it);
my_rbtree.insert_unique(*it);
my_hash.insert_unique(*it);
}
//Now test containers
{
List::const_iterator list_it (my_list.cbegin());
Slist::const_iterator slist_it (my_slist.cbegin());
Rbtree::const_iterator rbtree_it (my_rbtree.cbegin());
Hash::const_iterator hash_it (my_hash.cbegin());
MyClass *it_val(&values[NumElements] - 1), *it_rbeg_val(&values[0]-1);
//Test inserted objects
for(; it_val != it_rbeg_val; --it_val, ++list_it, ++slist_it, ++rbtree_it){
if(&*list_it != &*it_val) return 1;
if(&*slist_it != &*it_val) return 1;
if(&*rbtree_it != &*it_val) return 1;
hash_it = my_hash.find(*it_val);
if(hash_it == my_hash.cend() || &*hash_it != &*it_val)
return 1;
}
}
return 0;
}