Moved smart_ptr contents to subdirectories, switched to a local test/Jamfile.

[SVN r17042]
This commit is contained in:
Peter Dimov
2003-01-25 16:17:17 +00:00
parent d030182e87
commit abb0d9e725
20 changed files with 25 additions and 0 deletions
+25
View File
@@ -0,0 +1,25 @@
# Boost.SmartPtr Library test Jamfile
subproject libs/smart_ptr/test ;
# bring in rules for testing
SEARCH on testing.jam = $(BOOST_BUILD_PATH) ;
include testing.jam ;
# Make tests run by default.
DEPENDS all : test ;
{
# look in BOOST_ROOT for sources first, just in this Jamfile
local SEARCH_SOURCE = $(BOOST_ROOT) $(SEARCH_SOURCE) ;
test-suite "smart_ptr"
: [ run libs/smart_ptr/test/smart_ptr_test.cpp ]
[ run libs/smart_ptr/test/shared_ptr_basic_test.cpp : : : <gcc><*><cxxflags>-Wno-non-virtual-dtor ]
[ run libs/smart_ptr/test/shared_ptr_test.cpp : : : <gcc><*><cxxflags>-Wno-non-virtual-dtor ]
[ run libs/smart_ptr/test/weak_ptr_test.cpp ]
[ run libs/smart_ptr/test/shared_from_this_test.cpp : : : <gcc><*><cxxflags>-Wno-non-virtual-dtor ]
[ run libs/smart_ptr/test/get_deleter_test.cpp ]
[ compile-fail libs/smart_ptr/test/shared_ptr_assign_fail.cpp ]
;
}
+96
View File
@@ -0,0 +1,96 @@
//
// get_deleter_test.cpp
//
// Copyright (c) 2002 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 <boost/shared_ptr.hpp>
#include <boost/detail/lightweight_test.hpp>
struct deleter
{
int data;
deleter(): data(0)
{
}
void operator()(void *)
{
BOOST_TEST(data == 17041);
}
};
struct deleter2
{
};
struct X
{
};
int main()
{
{
boost::shared_ptr<X> p;
BOOST_TEST(boost::get_deleter<void>(p) == 0);
BOOST_TEST(boost::get_deleter<void const>(p) == 0);
BOOST_TEST(boost::get_deleter<int>(p) == 0);
BOOST_TEST(boost::get_deleter<int const>(p) == 0);
BOOST_TEST(boost::get_deleter<X>(p) == 0);
BOOST_TEST(boost::get_deleter<X const>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter const>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter2>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter2 const>(p) == 0);
}
{
boost::shared_ptr<X> p(new X);
BOOST_TEST(boost::get_deleter<void>(p) == 0);
BOOST_TEST(boost::get_deleter<void const>(p) == 0);
BOOST_TEST(boost::get_deleter<int>(p) == 0);
BOOST_TEST(boost::get_deleter<int const>(p) == 0);
BOOST_TEST(boost::get_deleter<X>(p) == 0);
BOOST_TEST(boost::get_deleter<X const>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter const>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter2>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter2 const>(p) == 0);
}
{
X x;
boost::shared_ptr<X> p(&x, deleter());
BOOST_TEST(boost::get_deleter<void>(p) == 0);
BOOST_TEST(boost::get_deleter<void const>(p) == 0);
BOOST_TEST(boost::get_deleter<int>(p) == 0);
BOOST_TEST(boost::get_deleter<int const>(p) == 0);
BOOST_TEST(boost::get_deleter<X>(p) == 0);
BOOST_TEST(boost::get_deleter<X const>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter2>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter2 const>(p) == 0);
deleter * q = boost::get_deleter<deleter>(p);
BOOST_TEST(q != 0);
BOOST_TEST(q->data == 0);
q->data = 17041;
deleter const * r = boost::get_deleter<deleter const>(p);
BOOST_TEST(r == q);
BOOST_TEST(r->data == 17041);
}
return boost::report_errors();
}
+553
View File
@@ -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 <boost/detail/lightweight_test.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/config.hpp>
#include <algorithm>
#include <functional>
//
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<X>::element_type T;
T t;
f(t);
}
} // namespace n_element_type
namespace n_constructors
{
void default_constructor()
{
boost::intrusive_ptr<X> px;
BOOST_TEST(px.get() == 0);
}
void pointer_constructor()
{
{
boost::intrusive_ptr<X> px(0);
BOOST_TEST(px.get() == 0);
}
{
boost::intrusive_ptr<X> px(0, false);
BOOST_TEST(px.get() == 0);
}
{
X * p = new X;
BOOST_TEST(p->use_count() == 0);
boost::intrusive_ptr<X> 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<X> px(p, false);
BOOST_TEST(px.get() == p);
BOOST_TEST(px->use_count() == 1);
}
}
void copy_constructor()
{
{
boost::intrusive_ptr<X> px;
boost::intrusive_ptr<X> px2(px);
BOOST_TEST(px2.get() == px.get());
}
{
boost::intrusive_ptr<Y> py;
boost::intrusive_ptr<X> px(py);
BOOST_TEST(px.get() == py.get());
}
{
boost::intrusive_ptr<X> px(0);
boost::intrusive_ptr<X> px2(px);
BOOST_TEST(px2.get() == px.get());
}
{
boost::intrusive_ptr<Y> py(0);
boost::intrusive_ptr<X> px(py);
BOOST_TEST(px.get() == py.get());
}
{
boost::intrusive_ptr<X> px(0, false);
boost::intrusive_ptr<X> px2(px);
BOOST_TEST(px2.get() == px.get());
}
{
boost::intrusive_ptr<Y> py(0, false);
boost::intrusive_ptr<X> px(py);
BOOST_TEST(px.get() == py.get());
}
{
boost::intrusive_ptr<X> px(new X);
boost::intrusive_ptr<X> px2(px);
BOOST_TEST(px2.get() == px.get());
}
{
boost::intrusive_ptr<Y> py(new Y);
boost::intrusive_ptr<X> 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<X> px(new X);
BOOST_TEST(px->use_count() == 1);
{
boost::intrusive_ptr<X> 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<X> 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<X> 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<X> 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<X> px;
boost::intrusive_ptr<X> 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<X> px;
boost::intrusive_ptr<X> px2(p);
boost::intrusive_ptr<X> 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<X> px(p1);
boost::intrusive_ptr<X> px2(p2);
boost::intrusive_ptr<X> 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<class T, class U> void test2(boost::intrusive_ptr<T> const & p, boost::intrusive_ptr<U> const & q)
{
BOOST_TEST((p == q) == (p.get() == q.get()));
BOOST_TEST((p != q) == (p.get() != q.get()));
}
template<class T> void test3(boost::intrusive_ptr<T> const & p, boost::intrusive_ptr<T> 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<T*> less;
BOOST_TEST((p < q) == less(p.get(), q.get()));
}
void test()
{
{
boost::intrusive_ptr<X> px;
test3(px, px);
boost::intrusive_ptr<X> px2;
test3(px, px2);
boost::intrusive_ptr<X> px3(px);
test3(px3, px3);
test3(px, px3);
}
{
boost::intrusive_ptr<X> px;
boost::intrusive_ptr<X> px2(new X);
test3(px, px2);
test3(px2, px2);
boost::intrusive_ptr<X> px3(new X);
test3(px2, px3);
boost::intrusive_ptr<X> px4(px2);
test3(px2, px4);
test3(px4, px4);
}
{
boost::intrusive_ptr<X> px(new X);
boost::intrusive_ptr<Y> py(new Y);
test2(px, py);
boost::intrusive_ptr<X> 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<X> next;
};
void test()
{
boost::intrusive_ptr<X> p(new X);
p->next = boost::intrusive_ptr<X>(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<foo> 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();
}
+112
View File
@@ -0,0 +1,112 @@
#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
#endif
//
// shared_from_this_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 <boost/enable_shared_from_this.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/detail/lightweight_test.hpp>
//
class X
{
public:
virtual void f() = 0;
protected:
~X() {}
};
class Y
{
public:
virtual boost::shared_ptr<X> getX() = 0;
protected:
~Y() {}
};
boost::shared_ptr<Y> createY();
void test()
{
boost::shared_ptr<Y> py = createY();
BOOST_TEST(py.get() != 0);
BOOST_TEST(py.use_count() == 1);
boost::shared_ptr<X> px = py->getX();
BOOST_TEST(px.get() != 0);
BOOST_TEST(py.use_count() == 2);
px->f();
boost::shared_ptr<Y> py2 = boost::dynamic_pointer_cast<Y>(px);
BOOST_TEST(py.get() == py2.get());
BOOST_TEST(!(py < py2 || py2 < py));
BOOST_TEST(py.use_count() == 3);
}
void test2();
int main()
{
test();
test2();
return boost::report_errors();
}
// virtual inheritance from Y to stress the implementation
// (prevents Y* -> impl* casts)
class impl: public X, public virtual Y, public boost::enable_shared_from_this<impl>
{
public:
virtual void f()
{
}
virtual boost::shared_ptr<X> getX()
{
boost::shared_ptr<impl> pi = shared_from_this();
BOOST_TEST(pi.get() == this);
return pi;
}
};
// intermediate impl2 to stress the implementation
class impl2: public impl
{
};
boost::shared_ptr<Y> createY()
{
boost::shared_ptr<Y> pi(new impl2);
return pi;
}
void test2()
{
boost::shared_ptr<Y> pi(static_cast<impl2*>(0));
}
+94
View File
@@ -0,0 +1,94 @@
//
// shared_ptr_alloc_test.cpp - use to evaluate the impact of count allocations
//
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
//
// 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 <boost/shared_ptr.hpp>
#include <boost/config.hpp>
#include <iostream>
#include <vector>
#include <ctime>
#include <memory>
int const n = 1024 * 1024;
template<class T> void test(T * = 0)
{
std::vector< boost::shared_ptr<T> > v;
std::clock_t t = std::clock();
for(int i = 0; i < n; ++i)
{
boost::shared_ptr<T> pi(new T(i));
v.push_back(pi);
}
t = std::clock() - t;
std::cout << static_cast<double>(t) / CLOCKS_PER_SEC << '\n';
}
class X
{
public:
explicit X(int n): n_(n)
{
}
void * operator new(std::size_t)
{
return std::allocator<X>().allocate(1, static_cast<X*>(0));
}
void operator delete(void * p)
{
std::allocator<X>().deallocate(static_cast<X*>(p), 1);
}
private:
X(X const &);
X & operator=(X const &);
int n_;
};
int main()
{
std::cout << BOOST_COMPILER "\n";
std::cout << BOOST_PLATFORM "\n";
std::cout << BOOST_STDLIB "\n";
#if defined(BOOST_HAS_THREADS)
std::cout << "BOOST_HAS_THREADS: (defined)\n";
#else
std::cout << "BOOST_HAS_THREADS: (not defined)\n";
#endif
#if defined(BOOST_SP_USE_STD_ALLOCATOR)
std::cout << "BOOST_SP_USE_STD_ALLOCATOR: (defined)\n";
#else
std::cout << "BOOST_SP_USE_STD_ALLOCATOR: (not defined)\n";
#endif
std::cout << n << " shared_ptr<int> allocations + deallocations:\n";
test<int>();
test<int>();
test<int>();
std::cout << n << " shared_ptr<X> allocations + deallocations:\n";
test<X>();
test<X>();
test<X>();
}
+31
View File
@@ -0,0 +1,31 @@
#if defined(_MSC_VER) && !defined(__ICL)
#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
#endif
//
// shared_ptr_assign_fail.cpp - a negative test for shared_ptr assignment
//
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
//
// 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 <boost/shared_ptr.hpp>
bool boost_error(char const *, char const *, char const *, long)
{
return true;
}
int main()
{
boost::shared_ptr<int> p;
p = new int(42); // assignment must fail
return 0;
}
+284
View File
@@ -0,0 +1,284 @@
//
// shared_ptr_basic_test.cpp
//
// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
//
// 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 <boost/detail/lightweight_test.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
int cnt = 0;
struct X
{
X()
{
++cnt;
}
~X() // virtual destructor deliberately omitted
{
--cnt;
}
virtual int id() const
{
return 1;
}
private:
X(X const &);
X & operator= (X const &);
};
struct Y: public X
{
Y()
{
++cnt;
}
~Y()
{
--cnt;
}
virtual int id() const
{
return 2;
}
private:
Y(Y const &);
Y & operator= (Y const &);
};
int * get_object()
{
++cnt;
return &cnt;
}
void release_object(int * p)
{
BOOST_TEST(p == &cnt);
--cnt;
}
template<class T> void test_is_X(boost::shared_ptr<T> const & p)
{
BOOST_TEST(p->id() == 1);
BOOST_TEST((*p).id() == 1);
}
template<class T> void test_is_X(boost::weak_ptr<T> const & p)
{
BOOST_TEST(p.get() != 0);
BOOST_TEST(p.get()->id() == 1);
}
template<class T> void test_is_Y(boost::shared_ptr<T> const & p)
{
BOOST_TEST(p->id() == 2);
BOOST_TEST((*p).id() == 2);
}
template<class T> void test_is_Y(boost::weak_ptr<T> const & p)
{
boost::shared_ptr<T> q = boost::make_shared(p);
BOOST_TEST(q.get() != 0);
BOOST_TEST(q->id() == 2);
}
template<class T> void test_eq(T const & a, T const & b)
{
BOOST_TEST(a == b);
BOOST_TEST(!(a != b));
BOOST_TEST(!(a < b));
BOOST_TEST(!(b < a));
}
template<class T> void test_ne(T const & a, T const & b)
{
BOOST_TEST(!(a == b));
BOOST_TEST(a != b);
BOOST_TEST(a < b || b < a);
BOOST_TEST(!(a < b && b < a));
}
template<class T, class U> void test_shared(boost::weak_ptr<T> const & a, boost::weak_ptr<U> const & b)
{
BOOST_TEST(!(a < b));
BOOST_TEST(!(b < a));
}
template<class T, class U> void test_nonshared(boost::weak_ptr<T> const & a, boost::weak_ptr<U> const & b)
{
BOOST_TEST(a < b || b < a);
BOOST_TEST(!(a < b && b < a));
}
template<class T, class U> void test_eq2(T const & a, U const & b)
{
BOOST_TEST(a == b);
BOOST_TEST(!(a != b));
}
template<class T, class U> void test_ne2(T const & a, U const & b)
{
BOOST_TEST(!(a == b));
BOOST_TEST(a != b);
}
template<class T> void test_is_zero(boost::shared_ptr<T> const & p)
{
BOOST_TEST(!p);
BOOST_TEST(p.get() == 0);
}
template<class T> void test_is_nonzero(boost::shared_ptr<T> const & p)
{
// p? true: false is used to test p in a boolean context.
// BOOST_TEST(p) is not guaranteed to test the conversion,
// as the macro might test !!p instead.
BOOST_TEST(p? true: false);
BOOST_TEST(p.get() != 0);
}
int main()
{
using namespace boost;
{
shared_ptr<X> p(new Y);
shared_ptr<X> p2(new X);
test_is_nonzero(p);
test_is_nonzero(p2);
test_is_Y(p);
test_is_X(p2);
test_ne(p, p2);
{
shared_ptr<X> q(p);
test_eq(p, q);
}
shared_ptr<Y> p3 = dynamic_pointer_cast<Y>(p);
shared_ptr<Y> p4 = dynamic_pointer_cast<Y>(p2);
test_is_nonzero(p3);
test_is_zero(p4);
BOOST_TEST(p.use_count() == 2);
BOOST_TEST(p2.use_count() == 1);
BOOST_TEST(p3.use_count() == 2);
test_is_Y(p3);
test_eq2(p, p3);
test_ne2(p2, p4);
shared_ptr<void> p5(p);
test_is_nonzero(p5);
test_eq2(p, p5);
weak_ptr<X> wp1(p2);
BOOST_TEST(!wp1.expired());
BOOST_TEST(wp1.use_count() != 0);
p.reset();
p2.reset();
p3.reset();
p4.reset();
test_is_zero(p);
test_is_zero(p2);
test_is_zero(p3);
test_is_zero(p4);
BOOST_TEST(p5.use_count() == 1);
BOOST_TEST(wp1.expired());
BOOST_TEST(wp1.use_count() == 0);
try
{
shared_ptr<X> sp1(wp1);
BOOST_ERROR("shared_ptr<X> sp1(wp1) failed to throw");
}
catch(boost::bad_weak_ptr const &)
{
}
test_is_zero(boost::make_shared(wp1));
weak_ptr<X> wp2 = static_pointer_cast<X>(p5);
BOOST_TEST(wp2.use_count() == 1);
test_is_Y(wp2);
test_nonshared(wp1, wp2);
// Scoped to not affect the subsequent use_count() tests.
{
shared_ptr<X> sp2(wp2);
test_is_nonzero(boost::make_shared(wp2));
}
weak_ptr<Y> wp3 = dynamic_pointer_cast<Y>(boost::make_shared(wp2));
BOOST_TEST(wp3.use_count() == 1);
test_shared(wp2, wp3);
weak_ptr<X> wp4(wp3);
BOOST_TEST(wp4.use_count() == 1);
test_shared(wp2, wp4);
wp1 = p2;
test_is_zero(boost::make_shared(wp1));
wp1 = p4;
wp1 = wp3;
wp1 = wp2;
BOOST_TEST(wp1.use_count() == 1);
test_shared(wp1, wp2);
weak_ptr<X> wp5;
bool b1 = wp1 < wp5;
bool b2 = wp5 < wp1;
p5.reset();
BOOST_TEST(wp1.use_count() == 0);
BOOST_TEST(wp2.use_count() == 0);
BOOST_TEST(wp3.use_count() == 0);
// Test operator< stability for std::set< weak_ptr<> >
// Thanks to Joe Gottman for pointing this out
BOOST_TEST(b1 == (wp1 < wp5));
BOOST_TEST(b2 == (wp5 < wp1));
{
// note that both get_object and release_object deal with int*
shared_ptr<void> p6(get_object(), release_object);
}
}
BOOST_TEST(cnt == 0);
return boost::report_errors();
}
+178
View File
@@ -0,0 +1,178 @@
#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
#endif
//
// shared_ptr_mt_test.cpp - tests shared_ptr with multiple threads
//
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
//
// 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 <boost/shared_ptr.hpp>
#include <boost/bind.hpp>
#include <vector>
#include <memory>
#include <stdexcept>
#include <cstdio>
#include <ctime>
// 'portable' thread framework
class abstract_thread
{
public:
virtual ~abstract_thread() {}
virtual void run() = 0;
};
#if !defined(BOOST_HAS_PTHREADS) && defined(BOOST_HAS_WINTHREADS)
char const * title = "Using Windows threads";
#include <windows.h>
#include <process.h>
typedef HANDLE pthread_t;
unsigned __stdcall common_thread_routine(void * pv)
{
abstract_thread * pt = static_cast<abstract_thread *>(pv);
pt->run();
delete pt;
return 0;
}
int pthread_create(pthread_t * thread, void const *, unsigned (__stdcall * start_routine) (void*), void* arg)
{
HANDLE h = (HANDLE)_beginthreadex(0, 0, start_routine, arg, 0, 0);
if(h != 0)
{
*thread = h;
return 0;
}
else
{
return 1; // return errno;
}
}
int pthread_join(pthread_t thread, void ** /*value_ptr*/)
{
::WaitForSingleObject(thread, INFINITE);
::CloseHandle(thread);
return 0;
}
#else
char const * title = "Using POSIX threads";
#include <pthread.h>
extern "C" void * common_thread_routine(void * pv)
{
abstract_thread * pt = static_cast<abstract_thread *>(pv);
pt->run();
delete pt;
return 0;
}
#endif
//
template<class F> class thread: public abstract_thread
{
public:
explicit thread(F f): f_(f)
{
}
void run()
{
f_();
}
private:
F f_;
};
template<class F> pthread_t createThread(F f)
{
std::auto_ptr<abstract_thread> p(new thread<F>(f));
pthread_t r;
if(pthread_create(&r, 0, common_thread_routine, p.get()) == 0)
{
p.release();
return r;
}
throw std::runtime_error("createThread failed.");
}
//
int const n = 1024 * 1024;
void test(boost::shared_ptr<int> const & pi)
{
std::vector< boost::shared_ptr<int> > v;
for(int i = 0; i < n; ++i)
{
v.push_back(pi);
}
}
int const m = 16; // threads
#if defined(BOOST_LWM_USE_CRITICAL_SECTION)
char const * implementation = "critical section";
#elif defined(BOOST_LWM_USE_PTHREADS)
char const * implementation = "pthread_mutex";
#else
char const * implementation = "spinlock";
#endif
int main()
{
std::printf("%s: %s, %d threads, %d iterations: ", title, implementation, m, n);
boost::shared_ptr<int> pi(new int(42));
std::clock_t t = std::clock();
pthread_t a[m];
for(int i = 0; i < m; ++i)
{
a[i] = createThread( boost::bind(test, pi) );
}
for(int i = 0; i < m; ++i)
{
pthread_join(a[i], 0);
}
t = std::clock() - t;
std::printf("\n\n%.3f seconds.\n", static_cast<double>(t) / CLOCKS_PER_SEC);
return 0;
}
File diff suppressed because it is too large Load Diff
+41
View File
@@ -0,0 +1,41 @@
#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
#endif
//
// shared_ptr_timing_test.cpp - use to evaluate the impact of thread safety
//
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
//
// 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 <boost/shared_ptr.hpp>
#include <iostream>
#include <vector>
#include <ctime>
int const n = 8 * 1024 * 1024;
int main()
{
std::vector< boost::shared_ptr<int> > v;
boost::shared_ptr<int> pi(new int);
std::clock_t t = std::clock();
for(int i = 0; i < n; ++i)
{
v.push_back(pi);
}
t = std::clock() - t;
std::cout << static_cast<double>(t) / CLOCKS_PER_SEC << '\n';
}
+290
View File
@@ -0,0 +1,290 @@
// smart pointer test program ----------------------------------------------//
// (C) Copyright Beman Dawes 1998, 1999. 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.
// Revision History
// 24 May 01 use Boost test library for error detection, reporting, add tests
// for operations on incomplete types (Beman Dawes)
// 29 Nov 99 added std::swap and associative container tests (Darin Adler)
// 25 Sep 99 added swap tests
// 20 Jul 99 header name changed to .hpp
// 20 Apr 99 additional error tests added.
#include <boost/scoped_ptr.hpp>
#include <boost/scoped_array.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/shared_array.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <cstring>
#include <iostream>
#include <set>
class Incomplete;
Incomplete * get_ptr( boost::shared_ptr<Incomplete>& incomplete )
{
return incomplete.get();
}
using namespace std;
using boost::scoped_ptr;
using boost::scoped_array;
using boost::shared_ptr;
using boost::shared_array;
template<class T>
void ck( const T* v1, T v2 ) { BOOST_TEST( *v1 == v2 ); }
namespace {
int UDT_use_count; // independent of pointer maintained counts
}
// user defined type -------------------------------------------------------//
class UDT {
long value_;
public:
explicit UDT( long value=0 ) : value_(value) { ++UDT_use_count; }
~UDT() {
--UDT_use_count;
cout << "UDT with value " << value_ << " being destroyed\n";
}
long value() const { return value_; }
void value( long v ) { value_ = v;; }
}; // UDT
// tests on incomplete types -----------------------------------------------//
// Certain smart pointer operations are specified to work on incomplete types,
// and some uses depend upon this feature. These tests verify compilation
// only - the functions aren't actually invoked.
class Incomplete;
Incomplete * check_incomplete( scoped_ptr<Incomplete>& incomplete )
{
return incomplete.get();
}
Incomplete * check_incomplete( shared_ptr<Incomplete>& incomplete,
shared_ptr<Incomplete>& i2 )
{
incomplete.swap(i2);
cout << incomplete.use_count() << ' ' << incomplete.unique() << '\n';
return incomplete.get();
}
// This isn't a very systematic test; it just hits some of the basics.
void test()
{
BOOST_TEST( UDT_use_count == 0 ); // reality check
// test scoped_ptr with a built-in type
long * lp = new long;
scoped_ptr<long> sp ( lp );
BOOST_TEST( sp.get() == lp );
BOOST_TEST( lp == sp.get() );
BOOST_TEST( &*sp == lp );
*sp = 1234568901L;
BOOST_TEST( *sp == 1234568901L );
BOOST_TEST( *lp == 1234568901L );
ck( static_cast<long*>(sp.get()), 1234568901L );
ck( lp, *sp );
sp.reset();
BOOST_TEST( sp.get() == 0 );
// test scoped_ptr with a user defined type
scoped_ptr<UDT> udt_sp ( new UDT( 999888777 ) );
BOOST_TEST( udt_sp->value() == 999888777 );
udt_sp.reset();
udt_sp.reset( new UDT( 111222333 ) );
BOOST_TEST( udt_sp->value() == 111222333 );
udt_sp.reset( new UDT( 333222111 ) );
BOOST_TEST( udt_sp->value() == 333222111 );
// test scoped_array with a build-in type
char * sap = new char [ 100 ];
scoped_array<char> sa ( sap );
BOOST_TEST( sa.get() == sap );
BOOST_TEST( sap == sa.get() );
strcpy( sa.get(), "Hot Dog with mustard and relish" );
BOOST_TEST( strcmp( sa.get(), "Hot Dog with mustard and relish" ) == 0 );
BOOST_TEST( strcmp( sap, "Hot Dog with mustard and relish" ) == 0 );
BOOST_TEST( sa[0] == 'H' );
BOOST_TEST( sa[30] == 'h' );
sa[0] = 'N';
sa[4] = 'd';
BOOST_TEST( strcmp( sap, "Not dog with mustard and relish" ) == 0 );
sa.reset();
BOOST_TEST( sa.get() == 0 );
// test shared_ptr with a built-in type
int * ip = new int;
shared_ptr<int> cp ( ip );
BOOST_TEST( ip == cp.get() );
BOOST_TEST( cp.use_count() == 1 );
*cp = 54321;
BOOST_TEST( *cp == 54321 );
BOOST_TEST( *ip == 54321 );
ck( static_cast<int*>(cp.get()), 54321 );
ck( static_cast<int*>(ip), *cp );
shared_ptr<int> cp2 ( cp );
BOOST_TEST( ip == cp2.get() );
BOOST_TEST( cp.use_count() == 2 );
BOOST_TEST( cp2.use_count() == 2 );
BOOST_TEST( *cp == 54321 );
BOOST_TEST( *cp2 == 54321 );
ck( static_cast<int*>(cp2.get()), 54321 );
ck( static_cast<int*>(ip), *cp2 );
shared_ptr<int> cp3 ( cp );
BOOST_TEST( cp.use_count() == 3 );
BOOST_TEST( cp2.use_count() == 3 );
BOOST_TEST( cp3.use_count() == 3 );
cp.reset();
BOOST_TEST( cp2.use_count() == 2 );
BOOST_TEST( cp3.use_count() == 2 );
cp.reset( new int );
*cp = 98765;
BOOST_TEST( *cp == 98765 );
*cp3 = 87654;
BOOST_TEST( *cp3 == 87654 );
BOOST_TEST( *cp2 == 87654 );
cp.swap( cp3 );
BOOST_TEST( *cp == 87654 );
BOOST_TEST( *cp2 == 87654 );
BOOST_TEST( *cp3 == 98765 );
cp.swap( cp3 );
BOOST_TEST( *cp == 98765 );
BOOST_TEST( *cp2 == 87654 );
BOOST_TEST( *cp3 == 87654 );
cp2 = cp2;
BOOST_TEST( cp2.use_count() == 2 );
BOOST_TEST( *cp2 == 87654 );
cp = cp2;
BOOST_TEST( cp2.use_count() == 3 );
BOOST_TEST( *cp2 == 87654 );
BOOST_TEST( cp.use_count() == 3 );
BOOST_TEST( *cp == 87654 );
shared_ptr<int> cp4;
swap( cp2, cp4 );
BOOST_TEST( cp4.use_count() == 3 );
BOOST_TEST( *cp4 == 87654 );
BOOST_TEST( cp2.get() == 0 );
set< shared_ptr<int> > scp;
scp.insert(cp4);
BOOST_TEST( scp.find(cp4) != scp.end() );
BOOST_TEST( scp.find(cp4) == scp.find( shared_ptr<int>(cp4) ) );
// test shared_array with a built-in type
char * cap = new char [ 100 ];
shared_array<char> ca ( cap );
BOOST_TEST( ca.get() == cap );
BOOST_TEST( cap == ca.get() );
BOOST_TEST( &ca[0] == cap );
strcpy( ca.get(), "Hot Dog with mustard and relish" );
BOOST_TEST( strcmp( ca.get(), "Hot Dog with mustard and relish" ) == 0 );
BOOST_TEST( strcmp( cap, "Hot Dog with mustard and relish" ) == 0 );
BOOST_TEST( ca[0] == 'H' );
BOOST_TEST( ca[30] == 'h' );
shared_array<char> ca2 ( ca );
shared_array<char> ca3 ( ca2 );
ca[0] = 'N';
ca[4] = 'd';
BOOST_TEST( strcmp( ca.get(), "Not dog with mustard and relish" ) == 0 );
BOOST_TEST( strcmp( ca2.get(), "Not dog with mustard and relish" ) == 0 );
BOOST_TEST( strcmp( ca3.get(), "Not dog with mustard and relish" ) == 0 );
BOOST_TEST( ca.use_count() == 3 );
BOOST_TEST( ca2.use_count() == 3 );
BOOST_TEST( ca3.use_count() == 3 );
ca2.reset();
BOOST_TEST( ca.use_count() == 2 );
BOOST_TEST( ca3.use_count() == 2 );
BOOST_TEST( ca2.use_count() == 1 );
ca.reset();
BOOST_TEST( ca.get() == 0 );
shared_array<char> ca4;
swap( ca3, ca4 );
BOOST_TEST( ca4.use_count() == 1 );
BOOST_TEST( strcmp( ca4.get(), "Not dog with mustard and relish" ) == 0 );
BOOST_TEST( ca3.get() == 0 );
set< shared_array<char> > sca;
sca.insert(ca4);
BOOST_TEST( sca.find(ca4) != sca.end() );
BOOST_TEST( sca.find(ca4) == sca.find( shared_array<char>(ca4) ) );
// test shared_array with user defined type
shared_array<UDT> udta ( new UDT[3] );
udta[0].value( 111 );
udta[1].value( 222 );
udta[2].value( 333 );
shared_array<UDT> udta2 ( udta );
BOOST_TEST( udta[0].value() == 111 );
BOOST_TEST( udta[1].value() == 222 );
BOOST_TEST( udta[2].value() == 333 );
BOOST_TEST( udta2[0].value() == 111 );
BOOST_TEST( udta2[1].value() == 222 );
BOOST_TEST( udta2[2].value() == 333 );
udta2.reset();
BOOST_TEST( udta2.get() == 0 );
BOOST_TEST( udta.use_count() == 1 );
BOOST_TEST( udta2.use_count() == 1 );
BOOST_TEST( UDT_use_count == 4 ); // reality check
// test shared_ptr with a user defined type
UDT * up = new UDT;
shared_ptr<UDT> sup ( up );
BOOST_TEST( up == sup.get() );
BOOST_TEST( sup.use_count() == 1 );
sup->value( 54321 ) ;
BOOST_TEST( sup->value() == 54321 );
BOOST_TEST( up->value() == 54321 );
shared_ptr<UDT> sup2;
sup2 = sup;
BOOST_TEST( sup2->value() == 54321 );
BOOST_TEST( sup.use_count() == 2 );
BOOST_TEST( sup2.use_count() == 2 );
sup2 = sup2;
BOOST_TEST( sup2->value() == 54321 );
BOOST_TEST( sup.use_count() == 2 );
BOOST_TEST( sup2.use_count() == 2 );
cout << "OK\n";
new char[12345]; // deliberate memory leak to verify leaks detected
}
int main()
{
test();
return boost::report_errors();
}
File diff suppressed because it is too large Load Diff