intrusive_mspqueue.cpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  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 "test_data.h"
  6. #include <cds/intrusive/mspriority_queue.h>
  7. namespace {
  8. struct disposer {
  9. size_t m_nCallCount;
  10. disposer()
  11. : m_nCallCount( 0 )
  12. {}
  13. template <typename T>
  14. void operator()( T& )
  15. {
  16. ++m_nCallCount;
  17. }
  18. };
  19. class IntrusiveMSPQueue : public cds_test::PQueueTest
  20. {
  21. typedef cds_test::PQueueTest base_class;
  22. protected:
  23. template <class PQueue>
  24. void test( PQueue& pq )
  25. {
  26. data_array<value_type> arr( pq.capacity());
  27. value_type * pFirst = arr.begin();
  28. value_type * pLast = arr.end();
  29. ASSERT_TRUE( pq.empty());
  30. ASSERT_FALSE( pq.full());
  31. ASSERT_EQ( pq.size(), 0u );
  32. ASSERT_EQ( pq.capacity(), static_cast<size_t>( base_class::c_nCapacity - 1 ));
  33. size_t nSize = 0;
  34. // Push test
  35. for ( value_type * p = pFirst; p < pLast; ++p ) {
  36. ASSERT_TRUE( pq.push( *p ));
  37. ASSERT_FALSE( pq.empty());
  38. ASSERT_EQ( pq.size(), ++nSize );
  39. }
  40. ASSERT_TRUE( pq.full());
  41. ASSERT_EQ( pq.size(), pq.capacity());
  42. // The queue is full
  43. {
  44. value_type k( base_class::c_nMinValue + key_type( base_class::c_nCapacity ));
  45. ASSERT_FALSE( pq.push( k ));
  46. ASSERT_TRUE( pq.full());
  47. ASSERT_EQ( pq.size(), pq.capacity());
  48. }
  49. // Pop test
  50. key_type nPrev = base_class::c_nMinValue + key_type( pq.capacity()) - 1;
  51. value_type * p = pq.pop();
  52. ASSERT_TRUE( p != nullptr );
  53. EXPECT_EQ( p->k, nPrev );
  54. ASSERT_EQ( pq.size(), pq.capacity() - 1 );
  55. ASSERT_FALSE( pq.full());
  56. ASSERT_FALSE( pq.empty());
  57. nSize = pq.size();
  58. while ( pq.size() > 1u ) {
  59. p = pq.pop();
  60. ASSERT_TRUE( p != nullptr );
  61. EXPECT_EQ( p->k, nPrev - 1 );
  62. nPrev = p->k;
  63. --nSize;
  64. ASSERT_EQ( pq.size(), nSize );
  65. }
  66. ASSERT_FALSE( pq.full());
  67. ASSERT_FALSE( pq.empty());
  68. ASSERT_EQ( pq.size(), 1u );
  69. p = pq.pop();
  70. ASSERT_TRUE( p != nullptr );
  71. EXPECT_EQ( p->k, base_class::c_nMinValue );
  72. ASSERT_FALSE( pq.full());
  73. ASSERT_TRUE( pq.empty());
  74. ASSERT_EQ( pq.size(), 0u );
  75. // Clear test
  76. for ( p = pFirst; p < pLast; ++p ) {
  77. ASSERT_TRUE( pq.push( *p ));
  78. }
  79. EXPECT_FALSE( pq.empty());
  80. EXPECT_TRUE( pq.full());
  81. EXPECT_EQ( pq.size(), pq.capacity());
  82. pq.clear();
  83. EXPECT_TRUE( pq.empty());
  84. EXPECT_FALSE( pq.full());
  85. EXPECT_EQ( pq.size(), 0u );
  86. // clear_with test
  87. for ( p = pFirst; p < pLast; ++p ) {
  88. ASSERT_TRUE( pq.push( *p ));
  89. }
  90. ASSERT_FALSE( pq.empty());
  91. ASSERT_TRUE( pq.full());
  92. ASSERT_EQ( pq.size(), pq.capacity());
  93. {
  94. disposer disp;
  95. pq.clear_with( std::ref( disp ));
  96. ASSERT_TRUE( pq.empty());
  97. ASSERT_FALSE( pq.full());
  98. ASSERT_EQ( pq.size(), 0u );
  99. ASSERT_EQ( disp.m_nCallCount, pq.capacity());
  100. }
  101. }
  102. };
  103. typedef cds::opt::v::initialized_dynamic_buffer< char > dyn_buffer_type;
  104. typedef cds::opt::v::initialized_static_buffer< char, IntrusiveMSPQueue::c_nCapacity > static_buffer_type;
  105. TEST_F( IntrusiveMSPQueue, dynamic )
  106. {
  107. struct traits : public cds::intrusive::mspriority_queue::traits
  108. {
  109. typedef dyn_buffer_type buffer;
  110. };
  111. typedef cds::intrusive::MSPriorityQueue< value_type, traits > pqueue;
  112. pqueue pq( c_nCapacity );
  113. test( pq );
  114. }
  115. TEST_F( IntrusiveMSPQueue, dynamic_cmp )
  116. {
  117. struct traits : public cds::intrusive::mspriority_queue::traits
  118. {
  119. typedef dyn_buffer_type buffer;
  120. typedef IntrusiveMSPQueue::compare compare;
  121. };
  122. typedef cds::intrusive::MSPriorityQueue< value_type, traits > pqueue;
  123. pqueue pq( c_nCapacity );
  124. test( pq );
  125. }
  126. TEST_F( IntrusiveMSPQueue, dynamic_less )
  127. {
  128. typedef cds::intrusive::MSPriorityQueue< value_type,
  129. cds::intrusive::mspriority_queue::make_traits<
  130. cds::opt::buffer< dyn_buffer_type >
  131. ,cds::opt::less< std::less<value_type> >
  132. >::type
  133. > pqueue;
  134. pqueue pq( c_nCapacity );
  135. test( pq );
  136. }
  137. TEST_F( IntrusiveMSPQueue, dynamic_cmp_less )
  138. {
  139. typedef cds::intrusive::MSPriorityQueue< value_type,
  140. cds::intrusive::mspriority_queue::make_traits<
  141. cds::opt::buffer< dyn_buffer_type >
  142. ,cds::opt::less< std::less<value_type> >
  143. ,cds::opt::compare< IntrusiveMSPQueue::compare >
  144. >::type
  145. > pqueue;
  146. pqueue pq( c_nCapacity );
  147. test( pq );
  148. }
  149. TEST_F( IntrusiveMSPQueue, dynamic_mutex )
  150. {
  151. struct traits : public cds::intrusive::mspriority_queue::traits
  152. {
  153. typedef dyn_buffer_type buffer;
  154. typedef IntrusiveMSPQueue::compare compare;
  155. typedef std::mutex lock_type;
  156. };
  157. typedef cds::intrusive::MSPriorityQueue< value_type, traits > pqueue;
  158. pqueue pq( c_nCapacity );
  159. test( pq );
  160. }
  161. TEST_F( IntrusiveMSPQueue, stat )
  162. {
  163. struct traits : public cds::intrusive::mspriority_queue::traits
  164. {
  165. typedef static_buffer_type buffer;
  166. };
  167. typedef cds::intrusive::MSPriorityQueue< value_type, traits > pqueue;
  168. std::unique_ptr<pqueue> pq( new pqueue(0));
  169. test( *pq );
  170. }
  171. TEST_F( IntrusiveMSPQueue, stat_cmp )
  172. {
  173. typedef cds::intrusive::MSPriorityQueue< value_type,
  174. cds::intrusive::mspriority_queue::make_traits<
  175. cds::opt::buffer< static_buffer_type >
  176. ,cds::opt::compare< compare >
  177. >::type
  178. > pqueue;
  179. std::unique_ptr<pqueue> pq( new pqueue( 0 ));
  180. test( *pq );
  181. }
  182. TEST_F( IntrusiveMSPQueue, stat_less )
  183. {
  184. typedef cds::intrusive::MSPriorityQueue< value_type,
  185. cds::intrusive::mspriority_queue::make_traits<
  186. cds::opt::buffer< static_buffer_type >
  187. ,cds::opt::less< less >
  188. >::type
  189. > pqueue;
  190. std::unique_ptr<pqueue> pq( new pqueue( 0 ));
  191. test( *pq );
  192. }
  193. TEST_F( IntrusiveMSPQueue, stat_mutex )
  194. {
  195. struct traits : public cds::intrusive::mspriority_queue::traits
  196. {
  197. typedef static_buffer_type buffer;
  198. typedef IntrusiveMSPQueue::compare compare;
  199. typedef std::mutex lock_type;
  200. };
  201. typedef cds::intrusive::MSPriorityQueue< value_type, traits > pqueue;
  202. std::unique_ptr<pqueue> pq( new pqueue( 0 ));
  203. test( *pq );
  204. }
  205. } // namespace