intrusive_fcstack.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450
  1. // Copyright (c) 2006-2018 Maxim Khizhinsky
  2. //
  3. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  4. // file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. #include <cds_test/ext_gtest.h>
  6. #include <cds/intrusive/fcstack.h>
  7. #include <boost/intrusive/list.hpp>
  8. namespace {
  9. class IntrusiveFCStack : public ::testing::Test
  10. {
  11. protected:
  12. template <typename Hook>
  13. struct base_hook_item : public Hook
  14. {
  15. int nVal;
  16. int nDisposeCount;
  17. base_hook_item()
  18. : nDisposeCount( 0 )
  19. {}
  20. };
  21. template <typename Hook>
  22. struct member_hook_item
  23. {
  24. int nVal;
  25. int nDisposeCount;
  26. Hook hMember;
  27. member_hook_item()
  28. : nDisposeCount( 0 )
  29. {}
  30. };
  31. struct mock_disposer
  32. {
  33. template <typename T>
  34. void operator ()( T * p )
  35. {
  36. ++p->nDisposeCount;
  37. }
  38. };
  39. template <class Stack>
  40. void test()
  41. {
  42. typedef typename Stack::value_type value_type;
  43. typedef typename Stack::container_type underlying_stack_type;
  44. Stack stack;
  45. ASSERT_TRUE( stack.empty());
  46. value_type v1, v2, v3;
  47. v1.nVal = 1;
  48. v2.nVal = 2;
  49. v3.nVal = 3;
  50. ASSERT_TRUE( stack.push( v1 ));
  51. ASSERT_TRUE( !stack.empty());
  52. ASSERT_TRUE( stack.push( v2 ));
  53. ASSERT_TRUE( !stack.empty());
  54. ASSERT_TRUE( stack.push( v3 ));
  55. ASSERT_TRUE( !stack.empty());
  56. unsigned sum = 0;
  57. stack.apply( [&sum]( underlying_stack_type& stack )
  58. {
  59. for ( auto const& el : stack )
  60. sum += el.nVal;
  61. } );
  62. EXPECT_EQ( sum, 6 );
  63. value_type * pv;
  64. pv = stack.pop();
  65. ASSERT_TRUE( pv != nullptr );
  66. ASSERT_EQ( pv->nVal, 3 );
  67. ASSERT_TRUE( !stack.empty());
  68. pv = stack.pop();
  69. ASSERT_TRUE( pv != nullptr );
  70. ASSERT_EQ( pv->nVal, 2 );
  71. ASSERT_TRUE( !stack.empty());
  72. pv = stack.pop();
  73. ASSERT_TRUE( pv != nullptr );
  74. ASSERT_EQ( pv->nVal, 1 );
  75. ASSERT_TRUE( stack.empty());
  76. pv = stack.pop();
  77. ASSERT_TRUE( pv == nullptr );
  78. ASSERT_TRUE( stack.empty());
  79. if ( !std::is_same<typename Stack::disposer, cds::intrusive::opt::v::empty_disposer>::value ) {
  80. int v1disp = v1.nDisposeCount;
  81. int v2disp = v2.nDisposeCount;
  82. int v3disp = v3.nDisposeCount;
  83. ASSERT_TRUE( stack.push( v1 ));
  84. ASSERT_TRUE( stack.push( v2 ));
  85. ASSERT_TRUE( stack.push( v3 ));
  86. stack.clear();
  87. ASSERT_TRUE( stack.empty());
  88. EXPECT_EQ( v1.nDisposeCount, v1disp);
  89. EXPECT_EQ( v2.nDisposeCount, v2disp);
  90. EXPECT_EQ( v3.nDisposeCount, v3disp);
  91. ASSERT_TRUE( stack.push( v1 ));
  92. ASSERT_TRUE( stack.push( v2 ));
  93. ASSERT_TRUE( stack.push( v3 ));
  94. ASSERT_TRUE( !stack.empty());
  95. stack.clear( true );
  96. ASSERT_TRUE( stack.empty());
  97. EXPECT_EQ( v1.nDisposeCount, v1disp + 1 );
  98. EXPECT_EQ( v2.nDisposeCount, v2disp + 1 );
  99. EXPECT_EQ( v3.nDisposeCount, v3disp + 1 );
  100. }
  101. }
  102. };
  103. TEST_F( IntrusiveFCStack, slist )
  104. {
  105. typedef base_hook_item< boost::intrusive::slist_base_hook<> > value_type;
  106. typedef cds::intrusive::FCStack< value_type, boost::intrusive::slist< value_type > > stack_type;
  107. test<stack_type>();
  108. }
  109. TEST_F( IntrusiveFCStack, slist_empty_wait_strategy )
  110. {
  111. typedef base_hook_item< boost::intrusive::slist_base_hook<> > value_type;
  112. struct stack_traits: public cds::intrusive::fcstack::traits
  113. {
  114. typedef cds::algo::flat_combining::wait_strategy::empty wait_strategy;
  115. };
  116. typedef cds::intrusive::FCStack< value_type, boost::intrusive::slist< value_type >, stack_traits > stack_type;
  117. test<stack_type>();
  118. }
  119. TEST_F( IntrusiveFCStack, slist_single_mutex_single_condvar )
  120. {
  121. typedef base_hook_item< boost::intrusive::slist_base_hook<> > value_type;
  122. struct stack_traits: public cds::intrusive::fcstack::traits
  123. {
  124. typedef cds::algo::flat_combining::wait_strategy::single_mutex_single_condvar<> wait_strategy;
  125. };
  126. typedef cds::intrusive::FCStack< value_type, boost::intrusive::slist< value_type >, stack_traits > stack_type;
  127. test<stack_type>();
  128. }
  129. TEST_F( IntrusiveFCStack, slist_single_mutex_multi_condvar )
  130. {
  131. typedef base_hook_item< boost::intrusive::slist_base_hook<> > value_type;
  132. struct stack_traits: public cds::intrusive::fcstack::traits
  133. {
  134. typedef cds::algo::flat_combining::wait_strategy::single_mutex_multi_condvar<> wait_strategy;
  135. };
  136. typedef cds::intrusive::FCStack< value_type, boost::intrusive::slist< value_type >, stack_traits > stack_type;
  137. test<stack_type>();
  138. }
  139. TEST_F( IntrusiveFCStack, slist_multi_mutex_multi_condvar )
  140. {
  141. typedef base_hook_item< boost::intrusive::slist_base_hook<> > value_type;
  142. struct stack_traits: public cds::intrusive::fcstack::traits
  143. {
  144. typedef cds::algo::flat_combining::wait_strategy::multi_mutex_multi_condvar<> wait_strategy;
  145. };
  146. typedef cds::intrusive::FCStack< value_type, boost::intrusive::slist< value_type >, stack_traits > stack_type;
  147. test<stack_type>();
  148. }
  149. TEST_F( IntrusiveFCStack, slist_single_mutex_single_condvar_2ms )
  150. {
  151. typedef base_hook_item< boost::intrusive::slist_base_hook<> > value_type;
  152. struct stack_traits: public cds::intrusive::fcstack::traits
  153. {
  154. typedef cds::algo::flat_combining::wait_strategy::single_mutex_single_condvar<2> wait_strategy;
  155. };
  156. typedef cds::intrusive::FCStack< value_type, boost::intrusive::slist< value_type >, stack_traits > stack_type;
  157. test<stack_type>();
  158. }
  159. TEST_F( IntrusiveFCStack, slist_single_mutex_multi_condvar_3ms )
  160. {
  161. typedef base_hook_item< boost::intrusive::slist_base_hook<> > value_type;
  162. struct stack_traits: public cds::intrusive::fcstack::traits
  163. {
  164. typedef cds::algo::flat_combining::wait_strategy::single_mutex_multi_condvar<3> wait_strategy;
  165. };
  166. typedef cds::intrusive::FCStack< value_type, boost::intrusive::slist< value_type >, stack_traits > stack_type;
  167. test<stack_type>();
  168. }
  169. TEST_F( IntrusiveFCStack, slist_multi_mutex_multi_condvar_2ms )
  170. {
  171. typedef base_hook_item< boost::intrusive::slist_base_hook<> > value_type;
  172. struct stack_traits: public cds::intrusive::fcstack::traits
  173. {
  174. typedef cds::algo::flat_combining::wait_strategy::multi_mutex_multi_condvar<2> wait_strategy;
  175. };
  176. typedef cds::intrusive::FCStack< value_type, boost::intrusive::slist< value_type >, stack_traits > stack_type;
  177. test<stack_type>();
  178. }
  179. TEST_F( IntrusiveFCStack, slist_disposer )
  180. {
  181. typedef base_hook_item< boost::intrusive::slist_base_hook<> > value_type;
  182. struct stack_traits : public cds::intrusive::fcstack::traits
  183. {
  184. typedef mock_disposer disposer;
  185. };
  186. typedef cds::intrusive::FCStack< value_type, boost::intrusive::slist< value_type >, stack_traits > stack_type;
  187. test<stack_type>();
  188. }
  189. TEST_F( IntrusiveFCStack, slist_mutex )
  190. {
  191. typedef base_hook_item< boost::intrusive::slist_base_hook<> > value_type;
  192. struct stack_traits : public cds::intrusive::fcstack::traits
  193. {
  194. typedef std::mutex lock_type;
  195. };
  196. typedef cds::intrusive::FCStack< value_type, boost::intrusive::slist< value_type >, stack_traits > stack_type;
  197. test<stack_type>();
  198. }
  199. TEST_F( IntrusiveFCStack, slist_elimination )
  200. {
  201. typedef base_hook_item< boost::intrusive::slist_base_hook<> > value_type;
  202. struct stack_traits : public
  203. cds::intrusive::fcstack::make_traits <
  204. cds::opt::enable_elimination < true >
  205. > ::type
  206. {};
  207. typedef cds::intrusive::FCStack< value_type, boost::intrusive::slist< value_type >, stack_traits > stack_type;
  208. test<stack_type>();
  209. }
  210. TEST_F( IntrusiveFCStack, slist_elimination_disposer )
  211. {
  212. typedef base_hook_item< boost::intrusive::slist_base_hook<> > value_type;
  213. struct stack_traits : public
  214. cds::intrusive::fcstack::make_traits <
  215. cds::opt::enable_elimination < true >,
  216. cds::intrusive::opt::disposer< mock_disposer >,
  217. cds::opt::wait_strategy< cds::algo::flat_combining::wait_strategy::multi_mutex_multi_condvar<>>
  218. > ::type
  219. {};
  220. typedef cds::intrusive::FCStack< value_type, boost::intrusive::slist< value_type >, stack_traits > stack_type;
  221. test<stack_type>();
  222. }
  223. TEST_F( IntrusiveFCStack, slist_elimination_stat )
  224. {
  225. typedef base_hook_item< boost::intrusive::slist_base_hook<> > value_type;
  226. typedef cds::intrusive::FCStack< value_type, boost::intrusive::slist< value_type >,
  227. cds::intrusive::fcstack::make_traits<
  228. cds::opt::enable_elimination< true >
  229. , cds::opt::stat< cds::intrusive::fcstack::stat<> >
  230. , cds::opt::wait_strategy< cds::algo::flat_combining::wait_strategy::single_mutex_multi_condvar<>>
  231. >::type
  232. > stack_type;
  233. test<stack_type>();
  234. }
  235. TEST_F( IntrusiveFCStack, slist_member )
  236. {
  237. typedef member_hook_item< boost::intrusive::slist_member_hook<> > value_type;
  238. typedef boost::intrusive::member_hook<value_type, boost::intrusive::slist_member_hook<>, &value_type::hMember> member_option;
  239. typedef cds::intrusive::FCStack< value_type, boost::intrusive::slist< value_type, member_option > > stack_type;
  240. test<stack_type>();
  241. }
  242. TEST_F( IntrusiveFCStack, slist_member_empty_wait_strategy )
  243. {
  244. typedef member_hook_item< boost::intrusive::slist_member_hook<> > value_type;
  245. typedef boost::intrusive::member_hook<value_type, boost::intrusive::slist_member_hook<>, &value_type::hMember> member_option;
  246. struct stack_traits: public cds::intrusive::fcstack::traits
  247. {
  248. typedef cds::algo::flat_combining::wait_strategy::empty wait_strategy;
  249. };
  250. typedef cds::intrusive::FCStack< value_type, boost::intrusive::slist< value_type, member_option >, stack_traits > stack_type;
  251. test<stack_type>();
  252. }
  253. TEST_F( IntrusiveFCStack, slist_member_single_mutex_single_condvar )
  254. {
  255. typedef member_hook_item< boost::intrusive::slist_member_hook<> > value_type;
  256. typedef boost::intrusive::member_hook<value_type, boost::intrusive::slist_member_hook<>, &value_type::hMember> member_option;
  257. struct stack_traits: public cds::intrusive::fcstack::traits
  258. {
  259. typedef cds::algo::flat_combining::wait_strategy::single_mutex_single_condvar<> wait_strategy;
  260. };
  261. typedef cds::intrusive::FCStack< value_type, boost::intrusive::slist< value_type, member_option >, stack_traits > stack_type;
  262. test<stack_type>();
  263. }
  264. TEST_F( IntrusiveFCStack, slist_member_single_mutex_multi_condvar )
  265. {
  266. typedef member_hook_item< boost::intrusive::slist_member_hook<> > value_type;
  267. typedef boost::intrusive::member_hook<value_type, boost::intrusive::slist_member_hook<>, &value_type::hMember> member_option;
  268. struct stack_traits: public cds::intrusive::fcstack::traits
  269. {
  270. typedef cds::algo::flat_combining::wait_strategy::single_mutex_multi_condvar<> wait_strategy;
  271. };
  272. typedef cds::intrusive::FCStack< value_type, boost::intrusive::slist< value_type, member_option >, stack_traits > stack_type;
  273. test<stack_type>();
  274. }
  275. TEST_F( IntrusiveFCStack, slist_member_multi_mutex_multi_condvar )
  276. {
  277. typedef member_hook_item< boost::intrusive::slist_member_hook<> > value_type;
  278. typedef boost::intrusive::member_hook<value_type, boost::intrusive::slist_member_hook<>, &value_type::hMember> member_option;
  279. struct stack_traits: public cds::intrusive::fcstack::traits
  280. {
  281. typedef cds::algo::flat_combining::wait_strategy::multi_mutex_multi_condvar<> wait_strategy;
  282. };
  283. typedef cds::intrusive::FCStack< value_type, boost::intrusive::slist< value_type, member_option >, stack_traits > stack_type;
  284. test<stack_type>();
  285. }
  286. TEST_F( IntrusiveFCStack, slist_member_disposer )
  287. {
  288. typedef member_hook_item< boost::intrusive::slist_member_hook<> > value_type;
  289. typedef boost::intrusive::member_hook<value_type, boost::intrusive::slist_member_hook<>, &value_type::hMember> member_option;
  290. struct stack_traits : public cds::intrusive::fcstack::traits
  291. {
  292. typedef mock_disposer disposer;
  293. };
  294. typedef cds::intrusive::FCStack< value_type, boost::intrusive::slist< value_type, member_option >, stack_traits > stack_type;
  295. test<stack_type>();
  296. }
  297. TEST_F( IntrusiveFCStack, slist_member_elimination )
  298. {
  299. typedef member_hook_item< boost::intrusive::slist_member_hook<> > value_type;
  300. typedef boost::intrusive::member_hook<value_type, boost::intrusive::slist_member_hook<>, &value_type::hMember> member_option;
  301. typedef cds::intrusive::FCStack< value_type, boost::intrusive::slist< value_type, member_option >,
  302. cds::intrusive::fcstack::make_traits<
  303. cds::opt::enable_elimination< true >
  304. >::type
  305. > stack_type;
  306. test<stack_type>();
  307. }
  308. TEST_F( IntrusiveFCStack, slist_member_elimination_stat )
  309. {
  310. typedef member_hook_item< boost::intrusive::slist_member_hook<> > value_type;
  311. typedef boost::intrusive::member_hook<value_type, boost::intrusive::slist_member_hook<>, &value_type::hMember> member_option;
  312. typedef cds::intrusive::FCStack< value_type, boost::intrusive::slist< value_type, member_option >,
  313. cds::intrusive::fcstack::make_traits<
  314. cds::opt::enable_elimination< true >
  315. , cds::opt::stat< cds::intrusive::fcstack::stat<> >
  316. , cds::opt::wait_strategy< cds::algo::flat_combining::wait_strategy::single_mutex_multi_condvar<>>
  317. >::type
  318. > stack_type;
  319. test<stack_type>();
  320. }
  321. TEST_F( IntrusiveFCStack, list )
  322. {
  323. typedef base_hook_item< boost::intrusive::list_base_hook<> > value_type;
  324. typedef cds::intrusive::FCStack< value_type, boost::intrusive::list< value_type > > stack_type;
  325. test<stack_type>();
  326. }
  327. TEST_F( IntrusiveFCStack, list_mutex )
  328. {
  329. typedef base_hook_item< boost::intrusive::list_base_hook<> > value_type;
  330. typedef cds::intrusive::FCStack< value_type, boost::intrusive::list< value_type >,
  331. cds::intrusive::fcstack::make_traits<
  332. cds::opt::lock_type< std::mutex >
  333. >::type
  334. > stack_type;
  335. test<stack_type>();
  336. }
  337. TEST_F( IntrusiveFCStack, list_elimination )
  338. {
  339. typedef base_hook_item< boost::intrusive::list_base_hook<> > value_type;
  340. typedef cds::intrusive::FCStack< value_type, boost::intrusive::list< value_type >,
  341. cds::intrusive::fcstack::make_traits<
  342. cds::opt::enable_elimination< true >
  343. >::type
  344. > stack_type;
  345. test<stack_type>();
  346. }
  347. TEST_F( IntrusiveFCStack, list_elimination_stat )
  348. {
  349. typedef base_hook_item< boost::intrusive::list_base_hook<> > value_type;
  350. typedef cds::intrusive::FCStack< value_type, boost::intrusive::list< value_type >,
  351. cds::intrusive::fcstack::make_traits<
  352. cds::opt::enable_elimination< true >
  353. , cds::opt::stat< cds::intrusive::fcstack::stat<> >
  354. , cds::opt::wait_strategy< cds::algo::flat_combining::wait_strategy::multi_mutex_multi_condvar<>>
  355. >::type
  356. > stack_type;
  357. test<stack_type>();
  358. }
  359. TEST_F( IntrusiveFCStack, list_member )
  360. {
  361. typedef member_hook_item< boost::intrusive::list_member_hook<> > value_type;
  362. typedef boost::intrusive::member_hook<value_type, boost::intrusive::list_member_hook<>, &value_type::hMember> member_option;
  363. typedef cds::intrusive::FCStack< value_type, boost::intrusive::list< value_type, member_option > > stack_type;
  364. test<stack_type>();
  365. }
  366. TEST_F( IntrusiveFCStack, list_member_elimination )
  367. {
  368. typedef member_hook_item< boost::intrusive::list_member_hook<> > value_type;
  369. typedef boost::intrusive::member_hook<value_type, boost::intrusive::list_member_hook<>, &value_type::hMember> member_option;
  370. typedef cds::intrusive::FCStack< value_type, boost::intrusive::list< value_type, member_option >,
  371. cds::intrusive::fcstack::make_traits<
  372. cds::opt::enable_elimination< true >
  373. >::type
  374. > stack_type;
  375. test<stack_type>();
  376. }
  377. TEST_F( IntrusiveFCStack, list_member_elimination_stat )
  378. {
  379. typedef member_hook_item< boost::intrusive::list_member_hook<> > value_type;
  380. typedef boost::intrusive::member_hook<value_type, boost::intrusive::list_member_hook<>, &value_type::hMember> member_option;
  381. typedef cds::intrusive::FCStack< value_type, boost::intrusive::list< value_type, member_option >,
  382. cds::intrusive::fcstack::make_traits<
  383. cds::opt::enable_elimination< true >
  384. , cds::opt::stat< cds::intrusive::fcstack::stat<> >
  385. , cds::opt::wait_strategy< cds::algo::flat_combining::wait_strategy::single_mutex_single_condvar<>>
  386. >::type
  387. > stack_type;
  388. test<stack_type>();
  389. }
  390. } // namespace