2 This file is a part of libcds - Concurrent Data Structures library
4 (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
6 Source code repo: http://github.com/khizmax/libcds/
7 Download: http://sourceforge.net/projects/libcds/files/
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions are met:
12 * Redistributions of source code must retain the above copyright notice,
14 list of conditions and the following disclaimer.
16 * Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
32 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 #include "../misc/common.h"
36 #include "../queue/queue_type.h"
39 #include <type_traits>
42 // Sequential queue push/pop test
45 static size_t s_nEnqueueCount = 4000000;
46 // Call 's_nEnqueueStride' number of enqueue before dequeue.
47 static size_t s_nEnqueueStride = 10000;
48 static size_t s_nQueueSize = 100000;
49 static size_t s_nVyukovQueuePushCount = 300000;
55 template <class Value = old_value>
56 class sequential_queue : public cds_test::stress_fixture {
58 using value_type = Value;
60 template <typename Queue>
61 void test(Queue &q, size_t enqueue_count = s_nEnqueueCount) {
64 size_t push_failure = 0;
67 while (v.nNo < enqueue_count) {
68 size_t curr_push_count =
69 std::min(enqueue_count - v.nNo, s_nEnqueueStride);
70 for (size_t i = 0; i < curr_push_count; i++) {
84 std::cout << "Sequential queue push error count: " << push_failure
87 size_t supposed_sum = enqueue_count * (enqueue_count - 1) / 2;
88 if (pop_sum != supposed_sum) {
89 std::cout << "Sequential queue pop sum: " << pop_sum
90 << " != " << supposed_sum << "\n";
95 static void SetUpTestCase() {
96 cds_test::config const &cfg = get_config("SequentialQueue");
97 GetConfig(EnqueueCount);
98 GetConfig(EnqueueStride);
100 GetConfig(VyukovQueuePushCount);
104 using simple_sequential_queue = sequential_queue<>;
106 #define CDSSTRESS_Sequential_Queue_F(test_fixture, type_name) \
107 TEST_F(test_fixture, type_name) { \
108 typedef queue::Types<value_type>::type_name queue_type; \
109 std::unique_ptr<queue_type> queue(new queue_type(s_nQueueSize)); \
110 test(*queue, s_nVyukovQueuePushCount); \
113 #define CDSSTRESS_Sequential_VyukovQueue(test_fixture) \
114 CDSSTRESS_Sequential_Queue_F(test_fixture, VyukovMPMCCycleQueue_dyn); \
115 CDSSTRESS_Sequential_Queue_F(test_fixture, VyukovMPMCCycleQueue_dyn_ic);
117 CDSSTRESS_Sequential_VyukovQueue(simple_sequential_queue);
119 #undef CDSSTRESS_Sequential_Queue_F
120 #define CDSSTRESS_Sequential_Queue_F(test_fixture, type_name) \
121 TEST_F(test_fixture, type_name) { \
122 typedef queue::Types<value_type>::type_name queue_type; \
123 std::unique_ptr<queue_type> queue(new queue_type()); \
127 #define CDSSTRESS_Sequential_MSQueue(test_fixture) \
128 CDSSTRESS_Sequential_Queue_F(test_fixture, MSQueue_HP); \
129 CDSSTRESS_Sequential_Queue_F(test_fixture, MSQueue_DHP);
131 #define CDSSTRESS_Sequential_MoirQueue(test_fixture) \
132 CDSSTRESS_Sequential_Queue_F(test_fixture, MoirQueue_HP); \
133 CDSSTRESS_Sequential_Queue_F(test_fixture, MoirQueue_DHP);
135 #define CDSSTRESS_Sequential_OptimsticQueue(test_fixture) \
136 CDSSTRESS_Sequential_Queue_F(test_fixture, OptimisticQueue_HP); \
137 CDSSTRESS_Sequential_Queue_F(test_fixture, OptimisticQueue_DHP);
139 #define CDSSTRESS_Sequential_BasketQueue(test_fixture) \
140 CDSSTRESS_Sequential_Queue_F(test_fixture, BasketQueue_HP); \
141 CDSSTRESS_Sequential_Queue_F(test_fixture, BasketQueue_DHP);
143 #define CDSSTRESS_Sequential_RWQueue(test_fixture) \
144 CDSSTRESS_Sequential_Queue_F(test_fixture, RWQueue_Spin);
146 #define CDSSTRESS_Sequential_WeakRingBuffer(test_fixture) \
147 CDSSTRESS_Sequential_Queue_F(test_fixture, WeakRingBuffer_dyn);
149 CDSSTRESS_Sequential_MSQueue(simple_sequential_queue);
150 CDSSTRESS_Sequential_MoirQueue(simple_sequential_queue);
151 CDSSTRESS_Sequential_BasketQueue(simple_sequential_queue);
152 CDSSTRESS_Sequential_OptimsticQueue(simple_sequential_queue);
153 CDSSTRESS_Sequential_RWQueue(simple_sequential_queue);
154 //CDSSTRESS_Sequential_WeakRingBuffer(simple_sequential_queue);
156 // ********************************************************************
157 // SegmentedQueue test
159 class sequential_segmented_queue
160 : public sequential_queue<>,
161 public ::testing::WithParamInterface<size_t> {
162 typedef sequential_queue<> base_class;
165 template <typename Queue> void test() {
166 size_t quasi_factor = GetParam();
167 Queue q(quasi_factor);
172 static std::vector<size_t> get_test_parameters() {
173 cds_test::config const &cfg =
174 cds_test::stress_fixture::get_config("SequentialQueue");
175 bool bIterative = cfg.get_bool("SegmentedQueue_Iterate", false);
176 size_t quasi_factor = cfg.get_size_t("SegmentedQueue_SegmentSize", 256);
178 std::vector<size_t> args;
179 if (bIterative && quasi_factor > 4) {
180 for (size_t qf = 4; qf <= quasi_factor; qf *= 2)
183 if (quasi_factor > 2)
184 args.push_back(quasi_factor);
193 #undef CDSSTRESS_Sequential_Queue_F
194 #define CDSSTRESS_Sequential_Queue_F(test_fixture, type_name) \
195 TEST_P(test_fixture, type_name) { \
196 typedef typename queue::Types<value_type>::type_name queue_type; \
197 test<queue_type>(); \
200 #define CDSSTRESS_Sequential_SegmentedQueue(test_fixture) \
201 CDSSTRESS_Sequential_Queue_F(test_fixture, SegmentedQueue_HP_spin); \
202 CDSSTRESS_Sequential_Queue_F(test_fixture, SegmentedQueue_HP_spin_padding); \
203 CDSSTRESS_Sequential_Queue_F(test_fixture, SegmentedQueue_DHP_spin);
205 CDSSTRESS_Sequential_SegmentedQueue(sequential_segmented_queue)
207 #ifdef CDSTEST_GTEST_INSTANTIATE_TEST_CASE_P_HAS_4TH_ARG
209 get_test_parameter_name(testing::TestParamInfo<size_t> const &p) {
210 return std::to_string(p.param);
212 INSTANTIATE_TEST_CASE_P(
213 SQ, sequential_segmented_queue,
214 ::testing::ValuesIn(sequential_segmented_queue::get_test_parameters()),
215 get_test_parameter_name);
217 INSTANTIATE_TEST_CASE_P(
218 SQ, sequential_segmented_queue,
219 ::testing::ValuesIn(sequential_segmented_queue::get_test_parameters()));
222 // ********************************************************************
223 // SPSC WeakRingBuffer
224 static size_t s_nBufferSize = 1024 * 1024;
225 static size_t s_nPushCount = 1000000;
227 class sequential_weak_ring_buffer : public cds_test::stress_fixture {
229 typedef size_t value_type;
231 template <typename Queue> void test(Queue &m_Queue) {
232 size_t const nPushCount = s_nPushCount;
233 size_t m_nPushed = 0;
234 size_t m_nPushFailed = 0;
235 size_t m_nPopped = 0;
236 size_t m_nBadValue = 0;
237 size_t m_nPopFrontFailed = 0;
238 size_t m_nPopEmpty = 0;
240 for (size_t i = 0; i < nPushCount; ++i) {
241 size_t len = rand(1024) + 64;
242 void *buf = m_Queue.back(len);
244 memset(buf, len % 256, len);
252 auto buf = m_Queue.front();
254 m_nPopped += buf.second;
256 uint8_t val = static_cast<uint8_t>(buf.second % 256);
257 uint8_t const *p = reinterpret_cast<uint8_t *>(buf.first);
258 for (uint8_t const *pEnd = p + buf.second; p < pEnd; ++p) {
265 if (!m_Queue.pop_front())
276 static void SetUpTestCase() {
277 cds_test::config const &cfg = get_config("SequentialRingBuffer");
279 s_nBufferSize = cfg.get_size_t("BufferSize", s_nBufferSize);
280 s_nPushCount = cfg.get_size_t("PushCount", s_nPushCount);
282 if (s_nBufferSize < 1024 * 64)
283 s_nBufferSize = 1024 * 64;
284 if (s_nPushCount == 0u)
289 #undef CDSSTRESS_Sequential_Queue_F
290 #define CDSSTRESS_Sequential_Queue_F(test_fixture, type_name) \
291 TEST_F(test_fixture, type_name) { \
292 typedef queue::Types<value_type>::type_name queue_type; \
293 std::unique_ptr<queue_type> queue(new queue_type(s_nBufferSize)); \
297 CDSSTRESS_WeakRingBuffer_void(sequential_weak_ring_buffer)
299 #undef CDSSTRESS_Queue_F