spsc_queue_test.cpp 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407
  1. // Copyright (C) 2011 Tim Blechmann
  2. //
  3. // Distributed under the Boost Software License, Version 1.0. (See
  4. // accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. #include <boost/lockfree/spsc_queue.hpp>
  7. #define BOOST_TEST_MAIN
  8. #ifdef BOOST_LOCKFREE_INCLUDE_TESTS
  9. #include <boost/test/included/unit_test.hpp>
  10. #else
  11. #include <boost/test/unit_test.hpp>
  12. #endif
  13. #include <iostream>
  14. #include <memory>
  15. #include "test_helpers.hpp"
  16. #include "test_common.hpp"
  17. using namespace boost;
  18. using namespace boost::lockfree;
  19. using namespace std;
  20. BOOST_AUTO_TEST_CASE( simple_spsc_queue_test )
  21. {
  22. spsc_queue<int, capacity<64> > f;
  23. BOOST_REQUIRE(f.empty());
  24. f.push(1);
  25. f.push(2);
  26. int i1(0), i2(0);
  27. BOOST_REQUIRE(f.pop(i1));
  28. BOOST_REQUIRE_EQUAL(i1, 1);
  29. BOOST_REQUIRE(f.pop(i2));
  30. BOOST_REQUIRE_EQUAL(i2, 2);
  31. BOOST_REQUIRE(f.empty());
  32. }
  33. BOOST_AUTO_TEST_CASE( simple_spsc_queue_test_compile_time_size )
  34. {
  35. spsc_queue<int> f(64);
  36. BOOST_REQUIRE(f.empty());
  37. f.push(1);
  38. f.push(2);
  39. int i1(0), i2(0);
  40. BOOST_REQUIRE(f.pop(i1));
  41. BOOST_REQUIRE_EQUAL(i1, 1);
  42. BOOST_REQUIRE(f.pop(i2));
  43. BOOST_REQUIRE_EQUAL(i2, 2);
  44. BOOST_REQUIRE(f.empty());
  45. }
  46. BOOST_AUTO_TEST_CASE( ranged_push_test )
  47. {
  48. spsc_queue<int> stk(64);
  49. int data[2] = {1, 2};
  50. BOOST_REQUIRE_EQUAL(stk.push(data, data + 2), data + 2);
  51. int out;
  52. BOOST_REQUIRE(stk.pop(out)); BOOST_REQUIRE_EQUAL(out, 1);
  53. BOOST_REQUIRE(stk.pop(out)); BOOST_REQUIRE_EQUAL(out, 2);
  54. BOOST_REQUIRE(!stk.pop(out));
  55. }
  56. BOOST_AUTO_TEST_CASE( spsc_queue_consume_one_test )
  57. {
  58. spsc_queue<int> f(64);
  59. BOOST_WARN(f.is_lock_free());
  60. BOOST_REQUIRE(f.empty());
  61. f.push(1);
  62. f.push(2);
  63. #ifdef BOOST_NO_CXX11_LAMBDAS
  64. bool success1 = f.consume_one(test_equal(1));
  65. bool success2 = f.consume_one(test_equal(2));
  66. #else
  67. bool success1 = f.consume_one([] (int i) {
  68. BOOST_REQUIRE_EQUAL(i, 1);
  69. });
  70. bool success2 = f.consume_one([] (int i) {
  71. BOOST_REQUIRE_EQUAL(i, 2);
  72. });
  73. #endif
  74. BOOST_REQUIRE(success1);
  75. BOOST_REQUIRE(success2);
  76. BOOST_REQUIRE(f.empty());
  77. }
  78. BOOST_AUTO_TEST_CASE( spsc_queue_consume_all_test )
  79. {
  80. spsc_queue<int> f(64);
  81. BOOST_WARN(f.is_lock_free());
  82. BOOST_REQUIRE(f.empty());
  83. f.push(1);
  84. f.push(2);
  85. #ifdef BOOST_NO_CXX11_LAMBDAS
  86. size_t consumed = f.consume_all(dummy_functor());
  87. #else
  88. size_t consumed = f.consume_all([] (int i) {
  89. });
  90. #endif
  91. BOOST_REQUIRE_EQUAL(consumed, 2u);
  92. BOOST_REQUIRE(f.empty());
  93. }
  94. enum {
  95. pointer_and_size,
  96. reference_to_array,
  97. iterator_pair,
  98. output_iterator_
  99. };
  100. BOOST_AUTO_TEST_CASE( spsc_queue_capacity_test )
  101. {
  102. spsc_queue<int, capacity<2> > f;
  103. BOOST_REQUIRE(f.push(1));
  104. BOOST_REQUIRE(f.push(2));
  105. BOOST_REQUIRE(!f.push(3));
  106. spsc_queue<int> g(2);
  107. BOOST_REQUIRE(g.push(1));
  108. BOOST_REQUIRE(g.push(2));
  109. BOOST_REQUIRE(!g.push(3));
  110. }
  111. template <typename QueueType>
  112. void spsc_queue_avail_test_run(QueueType & q)
  113. {
  114. BOOST_REQUIRE_EQUAL( q.write_available(), 16 );
  115. BOOST_REQUIRE_EQUAL( q.read_available(), 0 );
  116. for (size_t i = 0; i != 8; ++i) {
  117. BOOST_REQUIRE_EQUAL( q.write_available(), 16 - i );
  118. BOOST_REQUIRE_EQUAL( q.read_available(), i );
  119. q.push( 1 );
  120. }
  121. // empty queue
  122. int dummy;
  123. while (q.pop(dummy))
  124. {}
  125. for (size_t i = 0; i != 16; ++i) {
  126. BOOST_REQUIRE_EQUAL( q.write_available(), 16 - i );
  127. BOOST_REQUIRE_EQUAL( q.read_available(), i );
  128. q.push( 1 );
  129. }
  130. }
  131. BOOST_AUTO_TEST_CASE( spsc_queue_avail_test )
  132. {
  133. spsc_queue<int, capacity<16> > f;
  134. spsc_queue_avail_test_run(f);
  135. spsc_queue<int> g(16);
  136. spsc_queue_avail_test_run(g);
  137. }
  138. template <int EnqueueMode>
  139. void spsc_queue_buffer_push_return_value(void)
  140. {
  141. const size_t xqueue_size = 64;
  142. const size_t buffer_size = 100;
  143. spsc_queue<int, capacity<100> > rb;
  144. int data[xqueue_size];
  145. for (size_t i = 0; i != xqueue_size; ++i)
  146. data[i] = (int)i*2;
  147. switch (EnqueueMode) {
  148. case pointer_and_size:
  149. BOOST_REQUIRE_EQUAL(rb.push(data, xqueue_size), xqueue_size);
  150. break;
  151. case reference_to_array:
  152. BOOST_REQUIRE_EQUAL(rb.push(data), xqueue_size);
  153. break;
  154. case iterator_pair:
  155. BOOST_REQUIRE_EQUAL(rb.push(data, data + xqueue_size), data + xqueue_size);
  156. break;
  157. default:
  158. assert(false);
  159. }
  160. switch (EnqueueMode) {
  161. case pointer_and_size:
  162. BOOST_REQUIRE_EQUAL(rb.push(data, xqueue_size), buffer_size - xqueue_size);
  163. break;
  164. case reference_to_array:
  165. BOOST_REQUIRE_EQUAL(rb.push(data), buffer_size - xqueue_size);
  166. break;
  167. case iterator_pair:
  168. BOOST_REQUIRE_EQUAL(rb.push(data, data + xqueue_size), data + buffer_size - xqueue_size);
  169. break;
  170. default:
  171. assert(false);
  172. }
  173. }
  174. BOOST_AUTO_TEST_CASE( spsc_queue_buffer_push_return_value_test )
  175. {
  176. spsc_queue_buffer_push_return_value<pointer_and_size>();
  177. spsc_queue_buffer_push_return_value<reference_to_array>();
  178. spsc_queue_buffer_push_return_value<iterator_pair>();
  179. }
  180. template <int EnqueueMode,
  181. int ElementCount,
  182. int BufferSize,
  183. int NumberOfIterations
  184. >
  185. void spsc_queue_buffer_push(void)
  186. {
  187. const size_t xqueue_size = ElementCount;
  188. spsc_queue<int, capacity<BufferSize> > rb;
  189. int data[xqueue_size];
  190. for (size_t i = 0; i != xqueue_size; ++i)
  191. data[i] = (int)i*2;
  192. std::vector<int> vdata(data, data + xqueue_size);
  193. for (int i = 0; i != NumberOfIterations; ++i) {
  194. BOOST_REQUIRE(rb.empty());
  195. switch (EnqueueMode) {
  196. case pointer_and_size:
  197. BOOST_REQUIRE_EQUAL(rb.push(data, xqueue_size), xqueue_size);
  198. break;
  199. case reference_to_array:
  200. BOOST_REQUIRE_EQUAL(rb.push(data), xqueue_size);
  201. break;
  202. case iterator_pair:
  203. BOOST_REQUIRE_EQUAL(rb.push(data, data + xqueue_size), data + xqueue_size);
  204. break;
  205. default:
  206. assert(false);
  207. }
  208. int out[xqueue_size];
  209. BOOST_REQUIRE_EQUAL(rb.pop(out, xqueue_size), xqueue_size);
  210. for (size_t i = 0; i != xqueue_size; ++i)
  211. BOOST_REQUIRE_EQUAL(data[i], out[i]);
  212. }
  213. }
  214. BOOST_AUTO_TEST_CASE( spsc_queue_buffer_push_test )
  215. {
  216. spsc_queue_buffer_push<pointer_and_size, 7, 16, 64>();
  217. spsc_queue_buffer_push<reference_to_array, 7, 16, 64>();
  218. spsc_queue_buffer_push<iterator_pair, 7, 16, 64>();
  219. }
  220. template <int EnqueueMode,
  221. int ElementCount,
  222. int BufferSize,
  223. int NumberOfIterations
  224. >
  225. void spsc_queue_buffer_pop(void)
  226. {
  227. const size_t xqueue_size = ElementCount;
  228. spsc_queue<int, capacity<BufferSize> > rb;
  229. int data[xqueue_size];
  230. for (size_t i = 0; i != xqueue_size; ++i)
  231. data[i] = (int)i*2;
  232. std::vector<int> vdata(data, data + xqueue_size);
  233. for (int i = 0; i != NumberOfIterations; ++i) {
  234. BOOST_REQUIRE(rb.empty());
  235. BOOST_REQUIRE_EQUAL(rb.push(data), xqueue_size);
  236. int out[xqueue_size];
  237. vector<int> vout;
  238. switch (EnqueueMode) {
  239. case pointer_and_size:
  240. BOOST_REQUIRE_EQUAL(rb.pop(out, xqueue_size), xqueue_size);
  241. break;
  242. case reference_to_array:
  243. BOOST_REQUIRE_EQUAL(rb.pop(out), xqueue_size);
  244. break;
  245. case output_iterator_:
  246. BOOST_REQUIRE_EQUAL(rb.pop(std::back_inserter(vout)), xqueue_size);
  247. break;
  248. default:
  249. assert(false);
  250. }
  251. if (EnqueueMode == output_iterator_) {
  252. BOOST_REQUIRE_EQUAL(vout.size(), xqueue_size);
  253. for (size_t i = 0; i != xqueue_size; ++i)
  254. BOOST_REQUIRE_EQUAL(data[i], vout[i]);
  255. } else {
  256. for (size_t i = 0; i != xqueue_size; ++i)
  257. BOOST_REQUIRE_EQUAL(data[i], out[i]);
  258. }
  259. }
  260. }
  261. BOOST_AUTO_TEST_CASE( spsc_queue_buffer_pop_test )
  262. {
  263. spsc_queue_buffer_pop<pointer_and_size, 7, 16, 64>();
  264. spsc_queue_buffer_pop<reference_to_array, 7, 16, 64>();
  265. spsc_queue_buffer_pop<output_iterator_, 7, 16, 64>();
  266. }
  267. // Test front() and pop()
  268. template < typename Queue >
  269. void spsc_queue_front_pop(Queue& queue)
  270. {
  271. queue.push(1);
  272. queue.push(2);
  273. queue.push(3);
  274. // front as ref and const ref
  275. int& rfront = queue.front();
  276. const int& crfront = queue.front();
  277. BOOST_REQUIRE_EQUAL(1, rfront);
  278. BOOST_REQUIRE_EQUAL(1, crfront);
  279. int front = 0;
  280. // access element pushed first
  281. front = queue.front();
  282. BOOST_REQUIRE_EQUAL(1, front);
  283. // front is still the same
  284. front = queue.front();
  285. BOOST_REQUIRE_EQUAL(1, front);
  286. queue.pop();
  287. front = queue.front();
  288. BOOST_REQUIRE_EQUAL(2, front);
  289. queue.pop(); // pop 2
  290. bool pop_ret = queue.pop(); // pop 3
  291. BOOST_REQUIRE(pop_ret);
  292. pop_ret = queue.pop(); // pop on empty queue
  293. BOOST_REQUIRE( ! pop_ret);
  294. }
  295. BOOST_AUTO_TEST_CASE( spsc_queue_buffer_front_and_pop_runtime_sized_test )
  296. {
  297. spsc_queue<int, capacity<64> > queue;
  298. spsc_queue_front_pop(queue);
  299. }
  300. BOOST_AUTO_TEST_CASE( spsc_queue_buffer_front_and_pop_compiletime_sized_test )
  301. {
  302. spsc_queue<int> queue(64);
  303. spsc_queue_front_pop(queue);
  304. }
  305. BOOST_AUTO_TEST_CASE( spsc_queue_reset_test )
  306. {
  307. spsc_queue<int, capacity<64> > f;
  308. BOOST_REQUIRE(f.empty());
  309. f.push(1);
  310. f.push(2);
  311. f.reset();
  312. BOOST_REQUIRE(f.empty());
  313. }