1 // Copyright (C) 2011 Tim Blechmann
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)
7 #include <boost/lockfree/spsc_queue.hpp>
9 #define BOOST_TEST_MAIN
10 #ifdef BOOST_LOCKFREE_INCLUDE_TESTS
11 #include <boost/test/included/unit_test.hpp>
13 #include <boost/test/unit_test.hpp>
19 #include "test_helpers.hpp"
20 #include "test_common.hpp"
22 using namespace boost
;
23 using namespace boost::lockfree
;
26 BOOST_AUTO_TEST_CASE( simple_spsc_queue_test
)
28 spsc_queue
<int, capacity
<64> > f
;
30 BOOST_REQUIRE(f
.empty());
36 BOOST_REQUIRE(f
.pop(i1
));
37 BOOST_REQUIRE_EQUAL(i1
, 1);
39 BOOST_REQUIRE(f
.pop(i2
));
40 BOOST_REQUIRE_EQUAL(i2
, 2);
41 BOOST_REQUIRE(f
.empty());
44 BOOST_AUTO_TEST_CASE( simple_spsc_queue_test_compile_time_size
)
46 spsc_queue
<int> f(64);
48 BOOST_REQUIRE(f
.empty());
54 BOOST_REQUIRE(f
.pop(i1
));
55 BOOST_REQUIRE_EQUAL(i1
, 1);
57 BOOST_REQUIRE(f
.pop(i2
));
58 BOOST_REQUIRE_EQUAL(i2
, 2);
59 BOOST_REQUIRE(f
.empty());
62 BOOST_AUTO_TEST_CASE( ranged_push_test
)
64 spsc_queue
<int> stk(64);
68 BOOST_REQUIRE_EQUAL(stk
.push(data
, data
+ 2), data
+ 2);
71 BOOST_REQUIRE(stk
.pop(out
)); BOOST_REQUIRE_EQUAL(out
, 1);
72 BOOST_REQUIRE(stk
.pop(out
)); BOOST_REQUIRE_EQUAL(out
, 2);
73 BOOST_REQUIRE(!stk
.pop(out
));
76 BOOST_AUTO_TEST_CASE( spsc_queue_consume_one_test
)
78 spsc_queue
<int> f(64);
80 BOOST_WARN(f
.is_lock_free());
81 BOOST_REQUIRE(f
.empty());
86 #ifdef BOOST_NO_CXX11_LAMBDAS
87 bool success1
= f
.consume_one(test_equal(1));
88 bool success2
= f
.consume_one(test_equal(2));
90 bool success1
= f
.consume_one([] (int i
) {
91 BOOST_REQUIRE_EQUAL(i
, 1);
94 bool success2
= f
.consume_one([] (int i
) {
95 BOOST_REQUIRE_EQUAL(i
, 2);
99 BOOST_REQUIRE(success1
);
100 BOOST_REQUIRE(success2
);
102 BOOST_REQUIRE(f
.empty());
105 BOOST_AUTO_TEST_CASE( spsc_queue_consume_all_test
)
107 spsc_queue
<int> f(64);
109 BOOST_WARN(f
.is_lock_free());
110 BOOST_REQUIRE(f
.empty());
115 #ifdef BOOST_NO_CXX11_LAMBDAS
116 size_t consumed
= f
.consume_all(dummy_functor());
118 size_t consumed
= f
.consume_all([] (int i
) {
122 BOOST_REQUIRE_EQUAL(consumed
, 2u);
124 BOOST_REQUIRE(f
.empty());
134 BOOST_AUTO_TEST_CASE( spsc_queue_capacity_test
)
136 spsc_queue
<int, capacity
<2> > f
;
138 BOOST_REQUIRE(f
.push(1));
139 BOOST_REQUIRE(f
.push(2));
140 BOOST_REQUIRE(!f
.push(3));
142 spsc_queue
<int> g(2);
144 BOOST_REQUIRE(g
.push(1));
145 BOOST_REQUIRE(g
.push(2));
146 BOOST_REQUIRE(!g
.push(3));
149 template <typename QueueType
>
150 void spsc_queue_avail_test_run(QueueType
& q
)
152 BOOST_REQUIRE_EQUAL( q
.write_available(), 16 );
153 BOOST_REQUIRE_EQUAL( q
.read_available(), 0 );
155 for (size_t i
= 0; i
!= 8; ++i
) {
156 BOOST_REQUIRE_EQUAL( q
.write_available(), 16 - i
);
157 BOOST_REQUIRE_EQUAL( q
.read_available(), i
);
167 for (size_t i
= 0; i
!= 16; ++i
) {
168 BOOST_REQUIRE_EQUAL( q
.write_available(), 16 - i
);
169 BOOST_REQUIRE_EQUAL( q
.read_available(), i
);
175 BOOST_AUTO_TEST_CASE( spsc_queue_avail_test
)
177 spsc_queue
<int, capacity
<16> > f
;
178 spsc_queue_avail_test_run(f
);
180 spsc_queue
<int> g(16);
181 spsc_queue_avail_test_run(g
);
185 template <int EnqueueMode
>
186 void spsc_queue_buffer_push_return_value(void)
188 const size_t xqueue_size
= 64;
189 const size_t buffer_size
= 100;
190 spsc_queue
<int, capacity
<100> > rb
;
192 int data
[xqueue_size
];
193 for (size_t i
= 0; i
!= xqueue_size
; ++i
)
196 switch (EnqueueMode
) {
197 case pointer_and_size
:
198 BOOST_REQUIRE_EQUAL(rb
.push(data
, xqueue_size
), xqueue_size
);
201 case reference_to_array
:
202 BOOST_REQUIRE_EQUAL(rb
.push(data
), xqueue_size
);
206 BOOST_REQUIRE_EQUAL(rb
.push(data
, data
+ xqueue_size
), data
+ xqueue_size
);
213 switch (EnqueueMode
) {
214 case pointer_and_size
:
215 BOOST_REQUIRE_EQUAL(rb
.push(data
, xqueue_size
), buffer_size
- xqueue_size
);
218 case reference_to_array
:
219 BOOST_REQUIRE_EQUAL(rb
.push(data
), buffer_size
- xqueue_size
);
223 BOOST_REQUIRE_EQUAL(rb
.push(data
, data
+ xqueue_size
), data
+ buffer_size
- xqueue_size
);
231 BOOST_AUTO_TEST_CASE( spsc_queue_buffer_push_return_value_test
)
233 spsc_queue_buffer_push_return_value
<pointer_and_size
>();
234 spsc_queue_buffer_push_return_value
<reference_to_array
>();
235 spsc_queue_buffer_push_return_value
<iterator_pair
>();
238 template <int EnqueueMode
,
241 int NumberOfIterations
243 void spsc_queue_buffer_push(void)
245 const size_t xqueue_size
= ElementCount
;
246 spsc_queue
<int, capacity
<BufferSize
> > rb
;
248 int data
[xqueue_size
];
249 for (size_t i
= 0; i
!= xqueue_size
; ++i
)
252 std::vector
<int> vdata(data
, data
+ xqueue_size
);
254 for (int i
= 0; i
!= NumberOfIterations
; ++i
) {
255 BOOST_REQUIRE(rb
.empty());
256 switch (EnqueueMode
) {
257 case pointer_and_size
:
258 BOOST_REQUIRE_EQUAL(rb
.push(data
, xqueue_size
), xqueue_size
);
261 case reference_to_array
:
262 BOOST_REQUIRE_EQUAL(rb
.push(data
), xqueue_size
);
266 BOOST_REQUIRE_EQUAL(rb
.push(data
, data
+ xqueue_size
), data
+ xqueue_size
);
273 int out
[xqueue_size
];
274 BOOST_REQUIRE_EQUAL(rb
.pop(out
, xqueue_size
), xqueue_size
);
275 for (size_t i
= 0; i
!= xqueue_size
; ++i
)
276 BOOST_REQUIRE_EQUAL(data
[i
], out
[i
]);
280 BOOST_AUTO_TEST_CASE( spsc_queue_buffer_push_test
)
282 spsc_queue_buffer_push
<pointer_and_size
, 7, 16, 64>();
283 spsc_queue_buffer_push
<reference_to_array
, 7, 16, 64>();
284 spsc_queue_buffer_push
<iterator_pair
, 7, 16, 64>();
287 template <int EnqueueMode
,
290 int NumberOfIterations
292 void spsc_queue_buffer_pop(void)
294 const size_t xqueue_size
= ElementCount
;
295 spsc_queue
<int, capacity
<BufferSize
> > rb
;
297 int data
[xqueue_size
];
298 for (size_t i
= 0; i
!= xqueue_size
; ++i
)
301 std::vector
<int> vdata(data
, data
+ xqueue_size
);
303 for (int i
= 0; i
!= NumberOfIterations
; ++i
) {
304 BOOST_REQUIRE(rb
.empty());
305 BOOST_REQUIRE_EQUAL(rb
.push(data
), xqueue_size
);
307 int out
[xqueue_size
];
310 switch (EnqueueMode
) {
311 case pointer_and_size
:
312 BOOST_REQUIRE_EQUAL(rb
.pop(out
, xqueue_size
), xqueue_size
);
315 case reference_to_array
:
316 BOOST_REQUIRE_EQUAL(rb
.pop(out
), xqueue_size
);
319 case output_iterator_
:
320 BOOST_REQUIRE_EQUAL(rb
.pop(std::back_inserter(vout
)), xqueue_size
);
327 if (EnqueueMode
== output_iterator_
) {
328 BOOST_REQUIRE_EQUAL(vout
.size(), xqueue_size
);
329 for (size_t i
= 0; i
!= xqueue_size
; ++i
)
330 BOOST_REQUIRE_EQUAL(data
[i
], vout
[i
]);
332 for (size_t i
= 0; i
!= xqueue_size
; ++i
)
333 BOOST_REQUIRE_EQUAL(data
[i
], out
[i
]);
338 BOOST_AUTO_TEST_CASE( spsc_queue_buffer_pop_test
)
340 spsc_queue_buffer_pop
<pointer_and_size
, 7, 16, 64>();
341 spsc_queue_buffer_pop
<reference_to_array
, 7, 16, 64>();
342 spsc_queue_buffer_pop
<output_iterator_
, 7, 16, 64>();
345 // Test front() and pop()
346 template < typename Queue
>
347 void spsc_queue_front_pop(Queue
& queue
)
353 // front as ref and const ref
354 int& rfront
= queue
.front();
355 const int& crfront
= queue
.front();
357 BOOST_REQUIRE_EQUAL(1, rfront
);
358 BOOST_REQUIRE_EQUAL(1, crfront
);
362 // access element pushed first
363 front
= queue
.front();
364 BOOST_REQUIRE_EQUAL(1, front
);
366 // front is still the same
367 front
= queue
.front();
368 BOOST_REQUIRE_EQUAL(1, front
);
372 front
= queue
.front();
373 BOOST_REQUIRE_EQUAL(2, front
);
375 queue
.pop(); // pop 2
377 bool pop_ret
= queue
.pop(); // pop 3
378 BOOST_REQUIRE(pop_ret
);
380 pop_ret
= queue
.pop(); // pop on empty queue
381 BOOST_REQUIRE( ! pop_ret
);
384 BOOST_AUTO_TEST_CASE( spsc_queue_buffer_front_and_pop_runtime_sized_test
)
386 spsc_queue
<int, capacity
<64> > queue
;
387 spsc_queue_front_pop(queue
);
390 BOOST_AUTO_TEST_CASE( spsc_queue_buffer_front_and_pop_compiletime_sized_test
)
392 spsc_queue
<int> queue(64);
393 spsc_queue_front_pop(queue
);
396 BOOST_AUTO_TEST_CASE( spsc_queue_reset_test
)
398 spsc_queue
<int, capacity
<64> > f
;
400 BOOST_REQUIRE(f
.empty());
406 BOOST_REQUIRE(f
.empty());