libmoost
|
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()