jaulib v1.3.0
Jau Support Library (C++, Java, ..)
test_lfringbuffer13.cpp
Go to the documentation of this file.
1/*
2 * Author: Sven Gothel <sgothel@jausoft.com>
3 * Copyright (c) 2020 Gothel Software e.K.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24#include <cassert>
25#include <cinttypes>
26#include <cstring>
27#include <memory>
28#include <thread>
29#include <pthread.h>
30
32
33#include <jau/ringbuffer.hpp>
34
35using namespace jau;
36using namespace jau::fractions_i64_literals;
37
39
40class Integer {
41 public:
43
45
46 Integer(const Integer &o) noexcept = default;
47 Integer(Integer &&o) noexcept = default;
48 Integer& operator=(const Integer &o) noexcept = default;
49 Integer& operator=(Integer &&o) noexcept = default;
50
51 operator IntegralType() const {
52 return value;
53 }
54 IntegralType intValue() const { return value; }
55 static Integer valueOf(const IntegralType i) { return Integer(i); }
56};
57
58typedef std::shared_ptr<Integer> SharedType;
59constexpr const std::nullptr_t SharedTypeNullElem = nullptr ;
61
62// Test examples.
64 private:
65
66 std::shared_ptr<SharedTypeRingbuffer> createEmpty(jau::nsize_t initialCapacity) {
67 return std::make_shared<SharedTypeRingbuffer>(initialCapacity);
68 }
69 std::shared_ptr<SharedTypeRingbuffer> createFull(const std::vector<std::shared_ptr<Integer>> & source) {
70 return std::make_shared<SharedTypeRingbuffer>(source);
71 }
72
73 std::vector<SharedType> createIntArray(const jau::nsize_t capacity, const IntegralType startValue) {
74 std::vector<SharedType> array(capacity);
75 for(jau::nsize_t i=0; i<capacity; i++) {
76 array[i] = std::make_shared<Integer>(startValue+i);
77 }
78 return array;
79 }
80
81 void getThreadType01(const std::string& msg, const std::shared_ptr<SharedTypeRingbuffer>& rb, jau::nsize_t len) {
82 // std::thread::id this_id = std::this_thread::get_id();
83 // pthread_t this_id = pthread_self();
84
85 // INFO_STR, INFO: Not thread safe yet
86 // INFO_STR(msg+": Created / " + rb->toString());
87 for(jau::nsize_t i=0; i<len; i++) {
88 SharedType svI;
89 REQUIRE_MSG("not empty at read #"+std::to_string(i+1)+": "+rb->toString(), rb->getBlocking(svI, 0_s));
90 // INFO_STR("Got "+std::to_string(svI->intValue())+" / " + rb->toString());
91 }
92 // INFO_STR(msg+": Dies / " + rb->toString());
93 (void)msg;
94 }
95
96 void getRangeThreadType02(const std::string& msg, const std::shared_ptr<SharedTypeRingbuffer>& rb, jau::nsize_t len) {
97 // std::thread::id this_id = std::this_thread::get_id();
98 // pthread_t this_id = pthread_self();
99
100 // INFO_STR, INFO: Not thread safe yet
101 // INFO_STR(msg+": Created / " + rb->toString());
102 std::vector<SharedType> array(len);
103 REQUIRE_MSG("get-range of "+std::to_string(array.size())+" elem in "+rb->toString(), len==rb->getBlocking( &(*array.begin()), len, len, 0_s) );
104
105 for(jau::nsize_t i=0; i<len; i++) {
106 SharedType svI = array[i];
107 REQUIRE_MSG("not empty at read #"+std::to_string(i+1)+": "+rb->toString(), svI!=SharedTypeNullElem);
108 // INFO_STR("Got "+std::to_string(svI.intValue())+" / " + rb->toString());
109 }
110 // INFO_STR(msg+": Dies / " + rb->toString());
111 (void)msg;
112 }
113
114 void putThreadType01(const std::string& msg, const std::shared_ptr<SharedTypeRingbuffer>& rb, jau::nsize_t len, IntegralType startValue) {
115 // std::thread::id this_id = std::this_thread::get_id();
116 // pthread_t this_id = pthread_self();
117
118 // INFO_STR(msg+": Created / " + rb->toString());
119 for(jau::nsize_t i=0; i<len; i++) {
120 Integer * vI = new Integer(static_cast<IntegralType>(startValue+i));
121 // INFO_STR("Putting "+std::to_string(vI->intValue())+" ... / " + rb->toString());
122 REQUIRE( true == rb->putBlocking( SharedType( vI ), 0_s ) );
123 }
124 // INFO_STR(msg+": Dies / " + rb->toString());
125 (void)msg;
126 }
127
128 void putRangeThreadType02(const std::string& msg, const std::shared_ptr<SharedTypeRingbuffer>& rb, jau::nsize_t len, IntegralType startValue) {
129 // std::thread::id this_id = std::this_thread::get_id();
130 // pthread_t this_id = pthread_self();
131
132 // INFO_STR(msg+": Created / " + rb->toString());
133 std::vector<SharedType> data = createIntArray(len, startValue);
134 REQUIRE_MSG("put-range of "+std::to_string(data.size())+" elem in "+rb->toString(), rb->put( &(*data.begin()), &(*data.end()) ) );
135
136 // INFO_STR(msg+": Dies / " + rb->toString());
137 (void)msg;
138 }
139
140 public:
141
143 INFO_STR("\n\ntest01a_Read1Write1\n");
144 jau::nsize_t capacity = 100;
145 std::shared_ptr<SharedTypeRingbuffer> rb = createEmpty(capacity);
146
147 fprintf(stderr, "test01a_Read1Write1: %s\n", rb->get_info().c_str());
148 REQUIRE_MSG("empty size "+rb->toString(), 0 == rb->size());
149 REQUIRE_MSG("empty "+rb->toString(), rb->isEmpty());
150
151 std::thread getThread01(&TestRingbuffer13::getThreadType01, this, "test01a.get01", rb, capacity); // @suppress("Invalid arguments")
152 std::thread putThread01(&TestRingbuffer13::putThreadType01, this, "test01a.put01", rb, capacity, 0); // @suppress("Invalid arguments")
153 putThread01.join();
154 getThread01.join();
155
156 REQUIRE_MSG("empty "+rb->toString(), rb->isEmpty());
157 REQUIRE_MSG("empty size "+rb->toString(), 0 == rb->size());
158 }
159
161 INFO_STR("\n\ntest01b_Read1Write1_Range\n");
162 jau::nsize_t capacity = 100;
163 std::shared_ptr<SharedTypeRingbuffer> rb = createEmpty(capacity);
164
165 fprintf(stderr, "test01b_Read1Write1_Range: %s\n", rb->get_info().c_str());
166 REQUIRE_MSG("empty size "+rb->toString(), 0 == rb->size());
167 REQUIRE_MSG("empty "+rb->toString(), rb->isEmpty());
168
169 std::thread getThread01(&TestRingbuffer13::getRangeThreadType02, this, "test01b.getR01", rb, capacity); // @suppress("Invalid arguments")
170 std::thread putThread01(&TestRingbuffer13::putRangeThreadType02, this, "test01b.putR01", rb, capacity, 0); // @suppress("Invalid arguments")
171 putThread01.join();
172 getThread01.join();
173
174 REQUIRE_MSG("empty "+rb->toString(), rb->isEmpty());
175 REQUIRE_MSG("empty size "+rb->toString(), 0 == rb->size());
176 }
177
179 INFO_STR("\n\ntest02a_Read4Write1\n");
180 jau::nsize_t capacity = 400;
181 std::shared_ptr<SharedTypeRingbuffer> rb = createEmpty(capacity);
182 rb->setMultiPCEnabled(true);
183
184 fprintf(stderr, "test02a_Read4Write1: %s\n", rb->get_info().c_str());
185 REQUIRE_MSG("empty size "+rb->toString(), 0 == rb->size());
186 REQUIRE_MSG("empty "+rb->toString(), rb->isEmpty());
187
188 std::thread getThread01(&TestRingbuffer13::getThreadType01, this, "test02a.get01", rb, capacity/4); // @suppress("Invalid arguments")
189 std::thread getThread02(&TestRingbuffer13::getThreadType01, this, "test02a.get02", rb, capacity/4); // @suppress("Invalid arguments")
190 std::thread putThread01(&TestRingbuffer13::putThreadType01, this, "test02a.put01", rb, capacity, 0); // @suppress("Invalid arguments")
191 std::thread getThread03(&TestRingbuffer13::getThreadType01, this, "test02a.get03", rb, capacity/4); // @suppress("Invalid arguments")
192 std::thread getThread04(&TestRingbuffer13::getThreadType01, this, "test02a.get04", rb, capacity/4); // @suppress("Invalid arguments")
193 putThread01.join();
194 getThread01.join();
195 getThread02.join();
196 getThread03.join();
197 getThread04.join();
198
199 REQUIRE_MSG("empty "+rb->toString(), rb->isEmpty());
200 REQUIRE_MSG("empty size "+rb->toString(), 0 == rb->size());
201 }
202
204 INFO_STR("\n\ntest02b_Read4Write1_Range\n");
205 jau::nsize_t capacity = 400;
206 std::shared_ptr<SharedTypeRingbuffer> rb = createEmpty(capacity);
207 rb->setMultiPCEnabled(true);
208
209 fprintf(stderr, "test02b_Read4Write1_Range: %s\n", rb->get_info().c_str());
210 REQUIRE_MSG("empty size "+rb->toString(), 0 == rb->size());
211 REQUIRE_MSG("empty "+rb->toString(), rb->isEmpty());
212
213 std::thread getThread01(&TestRingbuffer13::getRangeThreadType02, this, "test02b.getR01", rb, capacity/4); // @suppress("Invalid arguments")
214 std::thread getThread02(&TestRingbuffer13::getRangeThreadType02, this, "test02b.getR02", rb, capacity/4); // @suppress("Invalid arguments")
215 std::thread putThread01(&TestRingbuffer13::putRangeThreadType02, this, "test02b.putR01", rb, capacity, 0); // @suppress("Invalid arguments")
216 std::thread getThread03(&TestRingbuffer13::getRangeThreadType02, this, "test02b.getR03", rb, capacity/4); // @suppress("Invalid arguments")
217 std::thread getThread04(&TestRingbuffer13::getRangeThreadType02, this, "test02b.getR04", rb, capacity/4); // @suppress("Invalid arguments")
218 putThread01.join();
219 getThread01.join();
220 getThread02.join();
221 getThread03.join();
222 getThread04.join();
223
224 REQUIRE_MSG("empty "+rb->toString(), rb->isEmpty());
225 REQUIRE_MSG("empty size "+rb->toString(), 0 == rb->size());
226 }
227
229 INFO_STR("\n\ntest03a_Read8Write2\n");
230 jau::nsize_t capacity = 800;
231 std::shared_ptr<SharedTypeRingbuffer> rb = createEmpty(capacity);
232 rb->setMultiPCEnabled(true);
233
234 fprintf(stderr, "test03a_Read8Write2: %s\n", rb->get_info().c_str());
235 REQUIRE_MSG("empty size "+rb->toString(), 0 == rb->size());
236 REQUIRE_MSG("empty "+rb->toString(), rb->isEmpty());
237
238 std::thread getThread01(&TestRingbuffer13::getThreadType01, this, "test03a.get01", rb, capacity/8); // @suppress("Invalid arguments")
239 std::thread getThread02(&TestRingbuffer13::getThreadType01, this, "test03a.get02", rb, capacity/8); // @suppress("Invalid arguments")
240 std::thread putThread01(&TestRingbuffer13::putThreadType01, this, "test03a.put01", rb, capacity/2, 0); // @suppress("Invalid arguments")
241 std::thread getThread03(&TestRingbuffer13::getThreadType01, this, "test03a.get03", rb, capacity/8); // @suppress("Invalid arguments")
242 std::thread getThread04(&TestRingbuffer13::getThreadType01, this, "test03a.get04", rb, capacity/8); // @suppress("Invalid arguments")
243
244 std::thread getThread05(&TestRingbuffer13::getThreadType01, this, "test03a.get05", rb, capacity/8); // @suppress("Invalid arguments")
245 std::thread getThread06(&TestRingbuffer13::getThreadType01, this, "test03a.get06", rb, capacity/8); // @suppress("Invalid arguments")
246 std::thread putThread02(&TestRingbuffer13::putThreadType01, this, "test03a.put02", rb, capacity/2, 400); // @suppress("Invalid arguments")
247 std::thread getThread07(&TestRingbuffer13::getThreadType01, this, "test03a.get07", rb, capacity/8); // @suppress("Invalid arguments")
248 std::thread getThread08(&TestRingbuffer13::getThreadType01, this, "test03a.get08", rb, capacity/8); // @suppress("Invalid arguments")
249
250 putThread01.join();
251 putThread02.join();
252 getThread01.join();
253 getThread02.join();
254 getThread03.join();
255 getThread04.join();
256 getThread05.join();
257 getThread06.join();
258 getThread07.join();
259 getThread08.join();
260
261 REQUIRE_MSG("empty "+rb->toString(), rb->isEmpty());
262 REQUIRE_MSG("empty size "+rb->toString(), 0 == rb->size());
263 }
264
266 INFO_STR("\n\ntest03b_Read8Write2_Range\n");
267 jau::nsize_t capacity = 800;
268 std::shared_ptr<SharedTypeRingbuffer> rb = createEmpty(capacity);
269 rb->setMultiPCEnabled(true);
270
271 fprintf(stderr, "test03b_Read8Write2_Range: %s\n", rb->get_info().c_str());
272 REQUIRE_MSG("empty size "+rb->toString(), 0 == rb->size());
273 REQUIRE_MSG("empty "+rb->toString(), rb->isEmpty());
274
275 std::thread getThread01(&TestRingbuffer13::getRangeThreadType02, this, "test03b.getR01", rb, capacity/8); // @suppress("Invalid arguments")
276 std::thread getThread02(&TestRingbuffer13::getRangeThreadType02, this, "test03b.getR02", rb, capacity/8); // @suppress("Invalid arguments")
277 std::thread putThread01(&TestRingbuffer13::putRangeThreadType02, this, "test03b.putR01", rb, capacity/2, 0); // @suppress("Invalid arguments")
278 std::thread getThread03(&TestRingbuffer13::getRangeThreadType02, this, "test03b.getR03", rb, capacity/8); // @suppress("Invalid arguments")
279 std::thread getThread04(&TestRingbuffer13::getRangeThreadType02, this, "test03b.getR04", rb, capacity/8); // @suppress("Invalid arguments")
280
281 std::thread getThread05(&TestRingbuffer13::getRangeThreadType02, this, "test03b.getR05", rb, capacity/8); // @suppress("Invalid arguments")
282 std::thread getThread06(&TestRingbuffer13::getRangeThreadType02, this, "test03b.getR06", rb, capacity/8); // @suppress("Invalid arguments")
283 std::thread putThread02(&TestRingbuffer13::putRangeThreadType02, this, "test03b.putR02", rb, capacity/2, 400); // @suppress("Invalid arguments")
284 std::thread getThread07(&TestRingbuffer13::getRangeThreadType02, this, "test03b.getR07", rb, capacity/8); // @suppress("Invalid arguments")
285 std::thread getThread08(&TestRingbuffer13::getRangeThreadType02, this, "test03b.getR08", rb, capacity/8); // @suppress("Invalid arguments")
286
287 putThread01.join();
288 putThread02.join();
289 getThread01.join();
290 getThread02.join();
291 getThread03.join();
292 getThread04.join();
293 getThread05.join();
294 getThread06.join();
295 getThread07.join();
296 getThread08.join();
297
298 REQUIRE_MSG("empty "+rb->toString(), rb->isEmpty());
299 REQUIRE_MSG("empty size "+rb->toString(), 0 == rb->size());
300 }
301
306#if 1
310
314#endif
315 }
316
317 void test_range() {
321#if 1
325
329#endif
330 }
331};
332
333METHOD_AS_TEST_CASE( TestRingbuffer13::test_sequential, "Test TestRingbuffer 13- test_sequential");
334METHOD_AS_TEST_CASE( TestRingbuffer13::test_range, "Test TestRingbuffer 13- test_range");
#define INFO_STR(msg)
Definition: catch2_ext.hpp:75
#define REQUIRE_MSG(MSG,...)
Definition: catch2_ext.hpp:58
Integer(const Integer &o) noexcept=default
static Integer valueOf(const IntegralType i)
Integral_type value
Integer(Integer &&o) noexcept=default
Integer(IntegralType v)
Integer & operator=(Integer &&o) noexcept=default
Integer() noexcept
IntegralType intValue() const
Integer & operator=(const Integer &o) noexcept=default
Ring buffer implementation, a.k.a circular buffer, exposing lock-free get*(..) and put*(....
Definition: ringbuffer.hpp:182
std::string to_string(const alphabet &v) noexcept
Definition: base_codec.hpp:97
uint_fast32_t nsize_t
Natural 'size_t' alternative using uint_fast32_t as its natural sized type.
Definition: int_types.hpp:53
int_fast32_t snsize_t
Natural 'ssize_t' alternative using int_fast32_t as its natural sized type.
Definition: int_types.hpp:65
__pack(...): Produces MSVC, clang and gcc compatible lead-in and -out macros.
Definition: backtrace.hpp:32
uint8_t IntegralType
jau::snsize_t IntegralType
std::shared_ptr< Integer > SharedType
constexpr const std::nullptr_t SharedTypeNullElem
METHOD_AS_TEST_CASE(TestRingbuffer13::test_sequential, "Test TestRingbuffer 13- test_sequential")
ringbuffer< SharedType, jau::nsize_t > SharedTypeRingbuffer