From d030182e87e51f8da69af3065e845c5b0de02ab2 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 22 Jan 2003 15:22:30 +0000 Subject: [PATCH] intrusive_ptr_test added. [SVN r16993] --- include/boost/intrusive_ptr.hpp | 17 + intrusive_ptr_test.cpp | 553 ++++++++++++++++++++++++++++++++ 2 files changed, 570 insertions(+) create mode 100644 intrusive_ptr_test.cpp diff --git a/include/boost/intrusive_ptr.hpp b/include/boost/intrusive_ptr.hpp index 074720f..3b988a8 100644 --- a/include/boost/intrusive_ptr.hpp +++ b/include/boost/intrusive_ptr.hpp @@ -126,6 +126,12 @@ public: return p_ == 0? 0: &intrusive_ptr::get; } + // operator! is a Borland-specific workaround + bool operator! () const + { + return p_ == 0; + } + void swap(intrusive_ptr & rhs) { T * tmp = p_; @@ -168,6 +174,17 @@ template inline bool operator!=(T * a, intrusive_ptr const & b) return a != b.get(); } +#if __GNUC__ == 2 && __GNUC_MINOR__ <= 96 + +// Resolve the ambiguity between our op!= and the one in rel_ops + +template inline bool operator!=(intrusive_ptr const & a, intrusive_ptr const & b) +{ + return a.get() != b.get(); +} + +#endif + template inline bool operator<(intrusive_ptr const & a, intrusive_ptr const & b) { return std::less()(a.get(), b.get()); diff --git a/intrusive_ptr_test.cpp b/intrusive_ptr_test.cpp new file mode 100644 index 0000000..f780d19 --- /dev/null +++ b/intrusive_ptr_test.cpp @@ -0,0 +1,553 @@ +#if defined(_MSC_VER) && !defined(__ICL) && !defined(__COMO__) +#pragma warning(disable: 4786) // identifier truncated in debug info +#pragma warning(disable: 4710) // function not inlined +#pragma warning(disable: 4711) // function selected for automatic inline expansion +#pragma warning(disable: 4514) // unreferenced inline removed +#pragma warning(disable: 4355) // 'this' : used in base member initializer list +#pragma warning(disable: 4511) // copy constructor could not be generated +#pragma warning(disable: 4512) // assignment operator could not be generated +#endif + +// +// intrusive_ptr_test.cpp +// +// Copyright (c) 2002, 2003 Peter Dimov +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// + +#include +#include +#include +#include +#include + +// + +namespace N +{ + +class base +{ +private: + + long use_count_; + + base(base const &); + base & operator=(base const &); + +protected: + + base(): use_count_(0) + { + } + + virtual ~base() + { + } + +public: + + long use_count() const + { + return use_count_; + } + +#if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) + + inline friend void intrusive_ptr_add_ref(base * p) + { + ++p->use_count_; + } + + inline friend void intrusive_ptr_release(base * p) + { + if(--p->use_count_ == 0) delete p; + } + +#else + + void add_ref() + { + ++use_count_; + } + + void release() + { + if(--use_count_ == 0) delete this; + } + +#endif +}; + +} // namespace N + +#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) + +namespace boost +{ + +inline void intrusive_ptr_add_ref(N::base * p) +{ + p->add_ref(); +} + +inline void intrusive_ptr_release(N::base * p) +{ + p->release(); +} + +} // namespace boost + +#endif + +// + +struct X: public virtual N::base +{ +}; + +struct Y: public X +{ +}; + +// + +namespace n_element_type +{ + +void f(X &) +{ +} + +void test() +{ + typedef boost::intrusive_ptr::element_type T; + T t; + f(t); +} + +} // namespace n_element_type + +namespace n_constructors +{ + +void default_constructor() +{ + boost::intrusive_ptr px; + BOOST_TEST(px.get() == 0); +} + +void pointer_constructor() +{ + { + boost::intrusive_ptr px(0); + BOOST_TEST(px.get() == 0); + } + + { + boost::intrusive_ptr px(0, false); + BOOST_TEST(px.get() == 0); + } + + { + X * p = new X; + BOOST_TEST(p->use_count() == 0); + + boost::intrusive_ptr px(p); + BOOST_TEST(px.get() == p); + BOOST_TEST(px->use_count() == 1); + } + + { + X * p = new X; + BOOST_TEST(p->use_count() == 0); + +#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) + using boost::intrusive_ptr_add_ref; +#endif + intrusive_ptr_add_ref(p); + BOOST_TEST(p->use_count() == 1); + + boost::intrusive_ptr px(p, false); + BOOST_TEST(px.get() == p); + BOOST_TEST(px->use_count() == 1); + } +} + +void copy_constructor() +{ + { + boost::intrusive_ptr px; + boost::intrusive_ptr px2(px); + BOOST_TEST(px2.get() == px.get()); + } + + { + boost::intrusive_ptr py; + boost::intrusive_ptr px(py); + BOOST_TEST(px.get() == py.get()); + } + + { + boost::intrusive_ptr px(0); + boost::intrusive_ptr px2(px); + BOOST_TEST(px2.get() == px.get()); + } + + { + boost::intrusive_ptr py(0); + boost::intrusive_ptr px(py); + BOOST_TEST(px.get() == py.get()); + } + + { + boost::intrusive_ptr px(0, false); + boost::intrusive_ptr px2(px); + BOOST_TEST(px2.get() == px.get()); + } + + { + boost::intrusive_ptr py(0, false); + boost::intrusive_ptr px(py); + BOOST_TEST(px.get() == py.get()); + } + + { + boost::intrusive_ptr px(new X); + boost::intrusive_ptr px2(px); + BOOST_TEST(px2.get() == px.get()); + } + + { + boost::intrusive_ptr py(new Y); + boost::intrusive_ptr px(py); + BOOST_TEST(px.get() == py.get()); + } +} + +void test() +{ + default_constructor(); + pointer_constructor(); + copy_constructor(); +} + +} // namespace n_constructors + +namespace n_destructor +{ + +void test() +{ + boost::intrusive_ptr px(new X); + BOOST_TEST(px->use_count() == 1); + + { + boost::intrusive_ptr px2(px); + BOOST_TEST(px->use_count() == 2); + } + + BOOST_TEST(px->use_count() == 1); +} + +} // namespace n_destructor + +namespace n_assignment +{ + +void copy_assignment() +{ +} + +void conversion_assignment() +{ +} + +void pointer_assignment() +{ +} + +void test() +{ + copy_assignment(); + conversion_assignment(); + pointer_assignment(); +} + +} // namespace n_assignment + +namespace n_access +{ + +void test() +{ + { + boost::intrusive_ptr px; + BOOST_TEST(px? false: true); + BOOST_TEST(!px); + +#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) + using boost::get_pointer; +#endif + + BOOST_TEST(get_pointer(px) == px.get()); + } + + { + boost::intrusive_ptr px(0); + BOOST_TEST(px? false: true); + BOOST_TEST(!px); + +#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) + using boost::get_pointer; +#endif + + BOOST_TEST(get_pointer(px) == px.get()); + } + + { + boost::intrusive_ptr px(new X); + BOOST_TEST(px? true: false); + BOOST_TEST(!!px); + BOOST_TEST(&*px == px.get()); + BOOST_TEST(px.operator ->() == px.get()); + +#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) + using boost::get_pointer; +#endif + + BOOST_TEST(get_pointer(px) == px.get()); + } +} + +} // namespace n_access + +namespace n_swap +{ + +void test() +{ + { + boost::intrusive_ptr px; + boost::intrusive_ptr px2; + + px.swap(px2); + + BOOST_TEST(px.get() == 0); + BOOST_TEST(px2.get() == 0); + + using std::swap; + swap(px, px2); + + BOOST_TEST(px.get() == 0); + BOOST_TEST(px2.get() == 0); + } + + { + X * p = new X; + boost::intrusive_ptr px; + boost::intrusive_ptr px2(p); + boost::intrusive_ptr px3(px2); + + px.swap(px2); + + BOOST_TEST(px.get() == p); + BOOST_TEST(px->use_count() == 2); + BOOST_TEST(px2.get() == 0); + BOOST_TEST(px3.get() == p); + BOOST_TEST(px3->use_count() == 2); + + using std::swap; + swap(px, px2); + + BOOST_TEST(px.get() == 0); + BOOST_TEST(px2.get() == p); + BOOST_TEST(px2->use_count() == 2); + BOOST_TEST(px3.get() == p); + BOOST_TEST(px3->use_count() == 2); + } + + { + X * p1 = new X; + X * p2 = new X; + boost::intrusive_ptr px(p1); + boost::intrusive_ptr px2(p2); + boost::intrusive_ptr px3(px2); + + px.swap(px2); + + BOOST_TEST(px.get() == p2); + BOOST_TEST(px->use_count() == 2); + BOOST_TEST(px2.get() == p1); + BOOST_TEST(px2->use_count() == 1); + BOOST_TEST(px3.get() == p2); + BOOST_TEST(px3->use_count() == 2); + + using std::swap; + swap(px, px2); + + BOOST_TEST(px.get() == p1); + BOOST_TEST(px->use_count() == 1); + BOOST_TEST(px2.get() == p2); + BOOST_TEST(px2->use_count() == 2); + BOOST_TEST(px3.get() == p2); + BOOST_TEST(px3->use_count() == 2); + } +} + +} // namespace n_swap + +namespace n_comparison +{ + +template void test2(boost::intrusive_ptr const & p, boost::intrusive_ptr const & q) +{ + BOOST_TEST((p == q) == (p.get() == q.get())); + BOOST_TEST((p != q) == (p.get() != q.get())); +} + +template void test3(boost::intrusive_ptr const & p, boost::intrusive_ptr const & q) +{ + BOOST_TEST((p == q) == (p.get() == q.get())); + BOOST_TEST((p.get() == q) == (p.get() == q.get())); + BOOST_TEST((p == q.get()) == (p.get() == q.get())); + BOOST_TEST((p != q) == (p.get() != q.get())); + BOOST_TEST((p.get() != q) == (p.get() != q.get())); + BOOST_TEST((p != q.get()) == (p.get() != q.get())); + + // 'less' moved here as a g++ 2.9x parse error workaround + std::less less; + BOOST_TEST((p < q) == less(p.get(), q.get())); +} + +void test() +{ + { + boost::intrusive_ptr px; + test3(px, px); + + boost::intrusive_ptr px2; + test3(px, px2); + + boost::intrusive_ptr px3(px); + test3(px3, px3); + test3(px, px3); + } + + { + boost::intrusive_ptr px; + + boost::intrusive_ptr px2(new X); + test3(px, px2); + test3(px2, px2); + + boost::intrusive_ptr px3(new X); + test3(px2, px3); + + boost::intrusive_ptr px4(px2); + test3(px2, px4); + test3(px4, px4); + } + + { + boost::intrusive_ptr px(new X); + + boost::intrusive_ptr py(new Y); + test2(px, py); + + boost::intrusive_ptr px2(py); + test2(px2, py); + test3(px, px2); + test3(px2, px2); + } +} + +} // namespace n_comparison + +namespace n_static_cast +{ + +void test() +{ +} + +} // namespace n_static_cast + +namespace n_dynamic_cast +{ + +void test() +{ +} + +} // namespace n_dynamic_cast + +namespace n_transitive +{ + +struct X: public N::base +{ + boost::intrusive_ptr next; +}; + +void test() +{ + boost::intrusive_ptr p(new X); + p->next = boost::intrusive_ptr(new X); + BOOST_TEST(!p->next->next); + p = p->next; + BOOST_TEST(!p->next); +} + +} // namespace n_transitive + +namespace n_report_1 +{ + +class foo: public N::base +{ +public: + + foo(): m_self(this) + { + } + + void suicide() + { + m_self = 0; + } + +private: + + boost::intrusive_ptr m_self; +}; + +void test() +{ + foo * foo_ptr = new foo; + foo_ptr->suicide(); +} + +} // namespace n_report_1 + +int main() +{ + n_element_type::test(); + n_constructors::test(); + n_destructor::test(); + n_assignment::test(); + n_access::test(); + n_swap::test(); + n_comparison::test(); + n_static_cast::test(); + n_dynamic_cast::test(); + + n_transitive::test(); + n_report_1::test(); + + return boost::report_errors(); +}