libmoost
/home/mhx/git/github/libmoost/test/safe_shared_ptr/safe_shared_ptr.cpp
Go to the documentation of this file.
00001 /* vim:set ts=3 sw=3 sts=3 et: */
00028 #include <csignal>
00029 
00030 #include <iostream>
00031 
00032 #include <boost/test/unit_test.hpp>
00033 #include <boost/test/test_tools.hpp>
00034 #include <boost/thread.hpp>
00035 #include <boost/bind.hpp>
00036 
00037 #include "../../include/moost/safe_shared_ptr.hpp"
00038 
00039 using namespace moost;
00040 
00041 namespace {
00042 
00043 class deref_helper
00044 {
00045 public:
00046    class impl
00047    {
00048    public:
00049       impl(size_t num)
00050          : m_num(num)
00051          , m_accu(new sig_atomic_t(0))
00052       {
00053       }
00054 
00055       void call(size_t no)
00056       {
00057          boost::this_thread::sleep(boost::posix_time::milliseconds(5));
00058          *m_accu += m_num + no;
00059          boost::this_thread::sleep(boost::posix_time::milliseconds(5));
00060          BOOST_CHECK(m_accu);
00061       }
00062 
00063       sig_atomic_t read() const
00064       {
00065          return *m_accu;
00066       }
00067 
00068    private:
00069       const size_t m_num;
00070       boost::shared_ptr<volatile sig_atomic_t> m_accu;
00071    };
00072 
00073    deref_helper()
00074       : m_impl(new impl(0))
00075       , m_num(0)
00076    {
00077    }
00078 
00079    void run_thread()
00080    {
00081       boost::thread(boost::bind(&deref_helper::run, this)).swap(m_thread);
00082    }
00083 
00084    void invalidate()
00085    {
00086       for (size_t i = 0; i < 4; ++i)
00087       {
00088          boost::this_thread::sleep(boost::posix_time::milliseconds(25));
00089          BOOST_CHECK(m_impl->read() >= 0);
00090          m_impl.reset(new impl(++m_num));
00091       }
00092    }
00093 
00094    void join()
00095    {
00096       m_thread.join();
00097    }
00098 
00099 private:
00100    void run()
00101    {
00102       for (size_t i = 0; i < 10; ++i)
00103       {
00104          m_impl->call(i);
00105       }
00106    }
00107 
00108    safe_shared_ptr<impl> m_impl;
00109    boost::thread m_thread;
00110    size_t m_num;
00111 };
00112 
00113 struct int_wrapper
00114 {
00115    int_wrapper(int value)
00116       : value(value)
00117    {
00118    }
00119 
00120    int value;
00121 };
00122 
00123 }
00124 
00125 BOOST_AUTO_TEST_SUITE( safe_shared_ptr_test )
00126 
00127 BOOST_AUTO_TEST_CASE( test_shared_ptr )
00128 {
00129   safe_shared_ptr<int_wrapper> p(new int_wrapper(3));
00130 
00131   BOOST_CHECK_EQUAL(p->value, 3);
00132 }
00133 
00134 BOOST_AUTO_TEST_CASE( test_shared_ptr_ctors )
00135 {
00136   boost::shared_ptr<int_wrapper> sp(new int_wrapper(4));
00137 
00138   BOOST_CHECK_EQUAL(sp.use_count(), 1);
00139 
00140   safe_shared_ptr<int_wrapper> p(sp);
00141 
00142   BOOST_CHECK_EQUAL(sp.use_count(), 2);
00143   BOOST_CHECK_EQUAL(p.use_count(), 2);
00144 
00145   safe_shared_ptr<int_wrapper> p2(p);
00146 
00147   BOOST_CHECK_EQUAL(sp.use_count(), 3);
00148   BOOST_CHECK_EQUAL(p.use_count(), 3);
00149   BOOST_CHECK_EQUAL(p2.use_count(), 3);
00150 
00151   safe_shared_ptr<int_wrapper const> p3(p);
00152 
00153   BOOST_CHECK_EQUAL(sp.use_count(), 4);
00154   BOOST_CHECK_EQUAL(p.use_count(), 4);
00155   BOOST_CHECK_EQUAL(p2.use_count(), 4);
00156   BOOST_CHECK_EQUAL(p3.use_count(), 4);
00157 
00158   BOOST_CHECK_EQUAL(p->value, 4);
00159   BOOST_CHECK_EQUAL(p2->value, 4);
00160   BOOST_CHECK_EQUAL(p3->value, 4);
00161 }
00162 
00163 BOOST_AUTO_TEST_CASE( test_shared_ptr_assign )
00164 {
00165   safe_shared_ptr<int_wrapper> p(new int_wrapper(3));
00166   safe_shared_ptr<int_wrapper> p2;
00167 
00168   p2 = p;
00169 
00170   BOOST_CHECK_EQUAL(p2->value, 3);
00171   BOOST_CHECK_EQUAL(p2.use_count(), 2);
00172 
00173   boost::shared_ptr<int_wrapper> p3(new int_wrapper(4));
00174 
00175   p = p3;
00176 
00177   BOOST_CHECK_EQUAL(p2->value, 3);
00178   BOOST_CHECK_EQUAL(p->value, 4);
00179   BOOST_CHECK_EQUAL(p3->value, 4);
00180   BOOST_CHECK_EQUAL(p2.use_count(), 1);
00181   BOOST_CHECK_EQUAL(p2.unique(), true);
00182   BOOST_CHECK_EQUAL(p.use_count(), 2);
00183   BOOST_CHECK_EQUAL(p.unique(), false);
00184   BOOST_CHECK_EQUAL(p3.use_count(), 2);
00185 
00186   boost::shared_ptr<int_wrapper> p4 = p.get_shared();
00187 
00188   BOOST_CHECK_EQUAL(p.use_count(), 3);
00189   BOOST_CHECK_EQUAL(p4.use_count(), 3);
00190   BOOST_CHECK_EQUAL(p4->value, 4);
00191 }
00192 
00193 namespace {
00194   struct a {
00195     void x() {}
00196   };
00197   struct b : public a {
00198     void y() {}
00199   };
00200 }
00201 
00202 BOOST_AUTO_TEST_CASE( test_shared_ptr_compare )
00203 {
00204   safe_shared_ptr<int_wrapper> p(new int_wrapper(3));
00205   safe_shared_ptr<int_wrapper> p2 = p;
00206   safe_shared_ptr<int_wrapper> p3(new int_wrapper(3));
00207   safe_shared_ptr<int_wrapper const> p4(p);
00208   safe_shared_ptr<int_wrapper const> p5(new int_wrapper(3));
00209 
00210   BOOST_CHECK_EQUAL(p == p2, true);
00211   BOOST_CHECK_EQUAL(p == p3, false);
00212   BOOST_CHECK_EQUAL(p == p4, true);
00213   BOOST_CHECK_EQUAL(p == p5, false);
00214   BOOST_CHECK_EQUAL(p == p, true);
00215 
00216   safe_shared_ptr<b> pb(new b());
00217   safe_shared_ptr<a> pa(pb);
00218 
00219   BOOST_CHECK_EQUAL(pa == pb, true);
00220 }
00221 
00222 BOOST_AUTO_TEST_CASE( test_shared_ptr_reset )
00223 {
00224   safe_shared_ptr<int_wrapper> p(new int_wrapper(2));
00225 
00226   BOOST_CHECK_EQUAL(p->value, 2);
00227 
00228   p.reset(new int_wrapper(3));
00229 
00230   BOOST_CHECK_EQUAL(p->value, 3);
00231 }
00232 
00233 BOOST_AUTO_TEST_CASE( test_swap )
00234 {
00235   safe_shared_ptr<int_wrapper> p(new int_wrapper(3));
00236   safe_shared_ptr<int_wrapper> p2(new int_wrapper(4));
00237 
00238   p2.swap(p);
00239 
00240   BOOST_CHECK_EQUAL(p2->value, 3);
00241   BOOST_CHECK_EQUAL(p->value, 4);
00242 
00243   p.swap(p);
00244 
00245   BOOST_CHECK_EQUAL(p->value, 4);
00246 }
00247 
00248 BOOST_AUTO_TEST_CASE( test_scoped_lock )
00249 {
00250   safe_shared_ptr<int_wrapper> p(new int_wrapper(3));
00251   {
00252     safe_shared_ptr<int_wrapper>::scoped_lock sp(p);
00253 
00254     BOOST_CHECK_EQUAL(sp->value, 3);
00255 
00256     sp->value = 4;
00257   }
00258   BOOST_CHECK_EQUAL(p->value, 4);
00259 }
00260 
00261 BOOST_AUTO_TEST_CASE( test_deref_thread )
00262 {
00263   deref_helper dh;
00264 
00265   dh.run_thread();
00266   dh.invalidate();
00267   dh.join();
00268 }
00269 
00270 BOOST_AUTO_TEST_SUITE_END()