intrusive_ptr_test.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546
  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Peter Dimov 2002-2005.
  4. // (C) Copyright Ion Gaztanaga 2006-2012. Distributed under the Boost
  5. // Software License, Version 1.0. (See accompanying file
  6. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. //
  8. // See http://www.boost.org/libs/interprocess for documentation.
  9. //
  10. //////////////////////////////////////////////////////////////////////////////
  11. #include <boost/interprocess/detail/config_begin.hpp>
  12. #include <boost/interprocess/offset_ptr.hpp>
  13. #include <boost/interprocess/smart_ptr/intrusive_ptr.hpp>
  14. #include <boost/interprocess/managed_shared_memory.hpp>
  15. #include <boost/core/lightweight_test.hpp>
  16. #include <boost/config.hpp>
  17. #include <boost/move/adl_move_swap.hpp>
  18. #include <boost/move/core.hpp>
  19. #include <functional>
  20. typedef boost::interprocess::offset_ptr<void> VP;
  21. namespace {
  22. int addref_release_calls = 0;
  23. }
  24. namespace N
  25. {
  26. class base
  27. {
  28. private:
  29. int use_count_;
  30. base(base const &);
  31. base & operator=(base const &);
  32. protected:
  33. base(): use_count_(0)
  34. {
  35. }
  36. virtual ~base()
  37. {
  38. }
  39. public:
  40. long use_count() const
  41. {
  42. return use_count_;
  43. }
  44. void add_ref()
  45. {
  46. ++addref_release_calls;
  47. ++use_count_;
  48. }
  49. void release()
  50. {
  51. ++addref_release_calls;
  52. if(--use_count_ == 0) delete this;
  53. }
  54. };
  55. inline void intrusive_ptr_add_ref(N::base *p)
  56. { p->add_ref(); }
  57. inline void intrusive_ptr_release(N::base *p)
  58. { p->release(); }
  59. } // namespace N
  60. struct X: public virtual N::base
  61. {
  62. };
  63. struct Y: public X
  64. {
  65. };
  66. //
  67. namespace n_element_type
  68. {
  69. void f(X &)
  70. {
  71. }
  72. void test()
  73. {
  74. typedef boost::interprocess::intrusive_ptr<X, VP>::element_type T;
  75. T t;
  76. f(t);
  77. }
  78. } // namespace n_element_type
  79. namespace n_constructors
  80. {
  81. void default_constructor()
  82. {
  83. boost::interprocess::intrusive_ptr<X, VP> px;
  84. BOOST_TEST(px.get() == 0);
  85. }
  86. void pointer_constructor()
  87. {
  88. {
  89. boost::interprocess::intrusive_ptr<X, VP> px(0);
  90. BOOST_TEST(px.get() == 0);
  91. }
  92. {
  93. boost::interprocess::intrusive_ptr<X, VP> px(0, false);
  94. BOOST_TEST(px.get() == 0);
  95. }
  96. {
  97. boost::interprocess::offset_ptr<X> p = new X;
  98. BOOST_TEST(p->use_count() == 0);
  99. boost::interprocess::intrusive_ptr<X, VP> px(p);
  100. BOOST_TEST(px.get() == p);
  101. BOOST_TEST(px->use_count() == 1);
  102. }
  103. {
  104. boost::interprocess::offset_ptr<X> p = new X;
  105. BOOST_TEST(p->use_count() == 0);
  106. intrusive_ptr_add_ref(p.get());
  107. BOOST_TEST(p->use_count() == 1);
  108. boost::interprocess::intrusive_ptr<X, VP> px(p, false);
  109. BOOST_TEST(px.get() == p);
  110. BOOST_TEST(px->use_count() == 1);
  111. }
  112. }
  113. void copy_constructor()
  114. {
  115. {
  116. boost::interprocess::intrusive_ptr<X, VP> px;
  117. boost::interprocess::intrusive_ptr<X, VP> px2(px);
  118. BOOST_TEST(px2.get() == px.get());
  119. }
  120. {
  121. boost::interprocess::intrusive_ptr<Y, VP> py;
  122. boost::interprocess::intrusive_ptr<X, VP> px(py);
  123. BOOST_TEST(px.get() == py.get());
  124. }
  125. {
  126. boost::interprocess::intrusive_ptr<X, VP> px(0);
  127. boost::interprocess::intrusive_ptr<X, VP> px2(px);
  128. BOOST_TEST(px2.get() == px.get());
  129. }
  130. {
  131. boost::interprocess::intrusive_ptr<Y, VP> py(0);
  132. boost::interprocess::intrusive_ptr<X, VP> px(py);
  133. BOOST_TEST(px.get() == py.get());
  134. }
  135. {
  136. boost::interprocess::intrusive_ptr<X, VP> px(0, false);
  137. boost::interprocess::intrusive_ptr<X, VP> px2(px);
  138. BOOST_TEST(px2.get() == px.get());
  139. }
  140. {
  141. boost::interprocess::intrusive_ptr<Y, VP> py(0, false);
  142. boost::interprocess::intrusive_ptr<X, VP> px(py);
  143. BOOST_TEST(px.get() == py.get());
  144. }
  145. {
  146. boost::interprocess::intrusive_ptr<X, VP> px(new X);
  147. boost::interprocess::intrusive_ptr<X, VP> px2(px);
  148. BOOST_TEST(px2.get() == px.get());
  149. }
  150. {
  151. boost::interprocess::intrusive_ptr<Y, VP> py(new Y);
  152. boost::interprocess::intrusive_ptr<X, VP> px(py);
  153. BOOST_TEST(px.get() == py.get());
  154. }
  155. }
  156. void move_constructor()
  157. {
  158. {
  159. int prev_addref_release_calls = addref_release_calls;
  160. X* x = new X();
  161. boost::interprocess::intrusive_ptr<X, VP> px(x);
  162. BOOST_TEST(addref_release_calls == prev_addref_release_calls + 1);
  163. //static_assert(std::is_nothrow_move_constructible< boost::interprocess::intrusive_ptr<X, VP> >::value, "test instrusive_ptr is nothrow move constructible");
  164. boost::interprocess::intrusive_ptr<X, VP> px2(boost::move(px));
  165. BOOST_TEST(px2.get() == x);
  166. BOOST_TEST(!px.get());
  167. BOOST_TEST(px2->use_count() == 1);
  168. BOOST_TEST(addref_release_calls == prev_addref_release_calls + 1);
  169. }
  170. }
  171. void test()
  172. {
  173. default_constructor();
  174. pointer_constructor();
  175. copy_constructor();
  176. move_constructor();
  177. }
  178. } // namespace n_constructors
  179. namespace n_destructor
  180. {
  181. void test()
  182. {
  183. boost::interprocess::intrusive_ptr<X, VP> px(new X);
  184. BOOST_TEST(px->use_count() == 1);
  185. {
  186. boost::interprocess::intrusive_ptr<X, VP> px2(px);
  187. BOOST_TEST(px->use_count() == 2);
  188. }
  189. BOOST_TEST(px->use_count() == 1);
  190. }
  191. } // namespace n_destructor
  192. namespace n_assignment
  193. {
  194. void copy_assignment()
  195. {
  196. }
  197. void move_assignment()
  198. {
  199. {
  200. int prev_addref_release_calls = addref_release_calls;
  201. X* x = new X();
  202. boost::interprocess::intrusive_ptr<X, VP> px(x);
  203. BOOST_TEST(px->use_count() == 1);
  204. BOOST_TEST(addref_release_calls == prev_addref_release_calls + 1);
  205. //static_assert(std::is_nothrow_move_assignable< boost::interprocess::intrusive_ptr<X, VP> >::value, "test if nothrow move assignable ");
  206. boost::interprocess::intrusive_ptr<X, VP> px2;
  207. px2 = boost::move(px);
  208. BOOST_TEST(px2.get() == x);
  209. BOOST_TEST(!px.get());
  210. BOOST_TEST(px2->use_count() == 1);
  211. BOOST_TEST(addref_release_calls == prev_addref_release_calls + 1);
  212. }
  213. }
  214. void conversion_assignment()
  215. {
  216. }
  217. void pointer_assignment()
  218. {
  219. }
  220. void test()
  221. {
  222. copy_assignment();
  223. conversion_assignment();
  224. pointer_assignment();
  225. move_assignment();
  226. }
  227. } // namespace n_assignment
  228. namespace n_access
  229. {
  230. void test()
  231. {
  232. {
  233. boost::interprocess::intrusive_ptr<X, VP> px;
  234. BOOST_TEST(px? false: true);
  235. BOOST_TEST(!px);
  236. }
  237. {
  238. boost::interprocess::intrusive_ptr<X, VP> px(0);
  239. BOOST_TEST(px? false: true);
  240. BOOST_TEST(!px);
  241. }
  242. {
  243. boost::interprocess::intrusive_ptr<X, VP> px
  244. (boost::interprocess::offset_ptr<X>(new X));
  245. BOOST_TEST(px? true: false);
  246. BOOST_TEST(!!px);
  247. BOOST_TEST(&*px == boost::interprocess::ipcdetail::to_raw_pointer(px.get()));
  248. BOOST_TEST(px.operator ->() == px.get());
  249. }
  250. }
  251. } // namespace n_access
  252. namespace n_swap
  253. {
  254. void test()
  255. {
  256. {
  257. boost::interprocess::intrusive_ptr<X, VP> px;
  258. boost::interprocess::intrusive_ptr<X, VP> px2;
  259. px.swap(px2);
  260. BOOST_TEST(px.get() == 0);
  261. BOOST_TEST(px2.get() == 0);
  262. ::boost::adl_move_swap(px, px2);
  263. BOOST_TEST(px.get() == 0);
  264. BOOST_TEST(px2.get() == 0);
  265. }
  266. {
  267. boost::interprocess::offset_ptr<X> p = new X;
  268. boost::interprocess::intrusive_ptr<X, VP> px;
  269. boost::interprocess::intrusive_ptr<X, VP> px2(p);
  270. boost::interprocess::intrusive_ptr<X, VP> px3(px2);
  271. px.swap(px2);
  272. BOOST_TEST(px.get() == p);
  273. BOOST_TEST(px->use_count() == 2);
  274. BOOST_TEST(px2.get() == 0);
  275. BOOST_TEST(px3.get() == p);
  276. BOOST_TEST(px3->use_count() == 2);
  277. ::boost::adl_move_swap(px, px2);
  278. BOOST_TEST(px.get() == 0);
  279. BOOST_TEST(px2.get() == p);
  280. BOOST_TEST(px2->use_count() == 2);
  281. BOOST_TEST(px3.get() == p);
  282. BOOST_TEST(px3->use_count() == 2);
  283. }
  284. {
  285. boost::interprocess::offset_ptr<X> p1 = new X;
  286. boost::interprocess::offset_ptr<X> p2 = new X;
  287. boost::interprocess::intrusive_ptr<X, VP> px(p1);
  288. boost::interprocess::intrusive_ptr<X, VP> px2(p2);
  289. boost::interprocess::intrusive_ptr<X, VP> px3(px2);
  290. px.swap(px2);
  291. BOOST_TEST(px.get() == p2);
  292. BOOST_TEST(px->use_count() == 2);
  293. BOOST_TEST(px2.get() == p1);
  294. BOOST_TEST(px2->use_count() == 1);
  295. BOOST_TEST(px3.get() == p2);
  296. BOOST_TEST(px3->use_count() == 2);
  297. ::boost::adl_move_swap(px, px2);
  298. BOOST_TEST(px.get() == p1);
  299. BOOST_TEST(px->use_count() == 1);
  300. BOOST_TEST(px2.get() == p2);
  301. BOOST_TEST(px2->use_count() == 2);
  302. BOOST_TEST(px3.get() == p2);
  303. BOOST_TEST(px3->use_count() == 2);
  304. }
  305. }
  306. } // namespace n_swap
  307. namespace n_comparison
  308. {
  309. template<class T, class U, class VP>
  310. void test2(boost::interprocess::intrusive_ptr<T, VP> const & p,
  311. boost::interprocess::intrusive_ptr<U, VP> const & q)
  312. {
  313. BOOST_TEST((p == q) == (p.get() == q.get()));
  314. BOOST_TEST((p != q) == (p.get() != q.get()));
  315. }
  316. template<class T, class VP>
  317. void test3(boost::interprocess::intrusive_ptr<T, VP> const & p,
  318. boost::interprocess::intrusive_ptr<T, VP> const & q)
  319. {
  320. BOOST_TEST((p == q) == (p.get() == q.get()));
  321. BOOST_TEST((p.get() == q) == (p.get() == q.get()));
  322. BOOST_TEST((p == q.get()) == (p.get() == q.get()));
  323. BOOST_TEST((p != q) == (p.get() != q.get()));
  324. BOOST_TEST((p.get() != q) == (p.get() != q.get()));
  325. BOOST_TEST((p != q.get()) == (p.get() != q.get()));
  326. // 'less' moved here as a g++ 2.9x parse error workaround
  327. std::less<boost::interprocess::offset_ptr<T> > less;
  328. BOOST_TEST((p < q) == less(p.get(), q.get()));
  329. }
  330. void test()
  331. {
  332. {
  333. boost::interprocess::intrusive_ptr<X, VP> px;
  334. test3(px, px);
  335. boost::interprocess::intrusive_ptr<X, VP> px2;
  336. test3(px, px2);
  337. boost::interprocess::intrusive_ptr<X, VP> px3(px);
  338. test3(px3, px3);
  339. test3(px, px3);
  340. }
  341. {
  342. boost::interprocess::intrusive_ptr<X, VP> px;
  343. boost::interprocess::intrusive_ptr<X, VP> px2(new X);
  344. test3(px, px2);
  345. test3(px2, px2);
  346. boost::interprocess::intrusive_ptr<X, VP> px3(new X);
  347. test3(px2, px3);
  348. boost::interprocess::intrusive_ptr<X, VP> px4(px2);
  349. test3(px2, px4);
  350. test3(px4, px4);
  351. }
  352. {
  353. boost::interprocess::intrusive_ptr<X, VP> px(new X);
  354. boost::interprocess::intrusive_ptr<Y, VP> py(new Y);
  355. test2(px, py);
  356. boost::interprocess::intrusive_ptr<X, VP> px2(py);
  357. test2(px2, py);
  358. test3(px, px2);
  359. test3(px2, px2);
  360. }
  361. }
  362. } // namespace n_comparison
  363. namespace n_static_cast
  364. {
  365. void test()
  366. {
  367. }
  368. } // namespace n_static_cast
  369. namespace n_dynamic_cast
  370. {
  371. void test()
  372. {
  373. }
  374. } // namespace n_dynamic_cast
  375. namespace n_transitive
  376. {
  377. struct X: public N::base
  378. {
  379. boost::interprocess::intrusive_ptr<X, VP> next;
  380. };
  381. void test()
  382. {
  383. boost::interprocess::intrusive_ptr<X, VP> p(new X);
  384. p->next = boost::interprocess::intrusive_ptr<X, VP>(new X);
  385. BOOST_TEST(!p->next->next);
  386. p = p->next;
  387. BOOST_TEST(!p->next);
  388. }
  389. } // namespace n_transitive
  390. namespace n_report_1
  391. {
  392. class foo: public N::base
  393. {
  394. public:
  395. foo(): m_self(this)
  396. {
  397. }
  398. void suicide()
  399. {
  400. m_self = 0;
  401. }
  402. private:
  403. boost::interprocess::intrusive_ptr<foo, VP> m_self;
  404. };
  405. void test()
  406. {
  407. boost::interprocess::offset_ptr<foo> foo_ptr = new foo;
  408. foo_ptr->suicide();
  409. }
  410. } // namespace n_report_1
  411. int main()
  412. {
  413. n_element_type::test();
  414. n_constructors::test();
  415. n_destructor::test();
  416. n_assignment::test();
  417. n_access::test();
  418. n_swap::test();
  419. n_comparison::test();
  420. n_static_cast::test();
  421. n_dynamic_cast::test();
  422. n_transitive::test();
  423. n_report_1::test();
  424. return boost::report_errors();
  425. }
  426. #include <boost/interprocess/detail/config_end.hpp>