1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <benchmark/benchmark.h>
17 #include "safe_block_queue.h"
18 #include <array>
19 #include <future>
20 #include <iostream>
21 #include <thread>
22 #include <chrono>
23 #include <thread>
24 #include "benchmark_log.h"
25 #include "benchmark_assert.h"
26 using namespace std;
27
28 namespace OHOS {
29 namespace {
30
31 class BenchmarkSafeBlockQueue : public benchmark::Fixture {
32 public:
SetUp(const::benchmark::State & state)33 void SetUp(const ::benchmark::State& state) override
34 {
35 }
36
TearDown(const::benchmark::State & state)37 void TearDown(const ::benchmark::State& state) override
38 {
39 }
40
BenchmarkSafeBlockQueue()41 BenchmarkSafeBlockQueue()
42 {
43 Iterations(iterations);
44 Repetitions(repetitions);
45 ReportAggregatesOnly();
46 }
47
48 ~BenchmarkSafeBlockQueue() override = default;
49
50 protected:
51 const int32_t repetitions = 3;
52 const int32_t iterations = 100;
53 };
54
55 const unsigned int QUEUE_SLOTS = 10;
56 const unsigned int THREAD_NUM = QUEUE_SLOTS + 1;
57 const int QUEUE_CAPACITY = 10;
58 const int SLEEP_FOR_TWENTY_MILLISECOND = 20;
59
60 class DemoThreadData {
61 public:
DemoThreadData()62 DemoThreadData()
63 {
64 putStatus = false;
65 getStatus = false;
66 }
67 static SafeBlockQueue<int> shareQueue;
68 bool putStatus;
69 bool getStatus;
Get()70 void Get()
71 {
72 shareQueue.Pop();
73 getStatus = true;
74 }
75
Put(int i)76 void Put(int i)
77 {
78 shareQueue.Push(i);
79 putStatus = true;
80 }
81 };
82
83 SafeBlockQueue<int> DemoThreadData::shareQueue(QUEUE_SLOTS);
84
PutHandleThreadData(DemoThreadData & q,int i)85 void PutHandleThreadData(DemoThreadData& q, int i)
86 {
87 q.Put(i);
88 }
89
GetThreadDateGetedStatus(std::array<DemoThreadData,THREAD_NUM> & demoDatas,unsigned int & getedOut,unsigned int & ungetedOut)90 void GetThreadDateGetedStatus(std::array<DemoThreadData, THREAD_NUM>& demoDatas, unsigned int& getedOut,
91 unsigned int& ungetedOut)
92 {
93 ungetedOut = 0;
94 getedOut = 0;
95 for (auto& t : demoDatas) {
96 if (t.getStatus) {
97 getedOut++;
98 } else {
99 ungetedOut++;
100 }
101 }
102 }
103
GetThreadDatePushedStatus(std::array<DemoThreadData,THREAD_NUM> & demoDatas,unsigned int & pushedIn,unsigned int & unpushedIn)104 void GetThreadDatePushedStatus(std::array<DemoThreadData, THREAD_NUM>& demoDatas, unsigned int& pushedIn,
105 unsigned int& unpushedIn)
106 {
107 unpushedIn = 0;
108 pushedIn = 0;
109 for (auto& t : demoDatas) {
110 if (t.putStatus) {
111 pushedIn++;
112 } else {
113 unpushedIn++;
114 }
115 }
116 }
117
PutHandleThreadDataTime(DemoThreadData & q,int i,std::chrono::time_point<std::chrono::high_resolution_clock> absTime)118 void PutHandleThreadDataTime(DemoThreadData& q, int i,
119 std::chrono::time_point<std::chrono::high_resolution_clock> absTime)
120 {
121 std::this_thread::sleep_until(absTime);
122 q.Put(i);
123 }
124
GetHandleThreadDataTime(DemoThreadData & q,int i,std::chrono::time_point<std::chrono::high_resolution_clock> absTime)125 void GetHandleThreadDataTime(DemoThreadData& q, int i,
126 std::chrono::time_point<std::chrono::high_resolution_clock> absTime)
127 {
128 std::this_thread::sleep_until(absTime);
129 q.Get();
130 }
131
GetTimeOfSleepTwentyMillisecond()132 auto GetTimeOfSleepTwentyMillisecond()
133 {
134 using std::chrono::system_clock;
135 auto timeT = std::chrono::high_resolution_clock::now();
136 timeT += std::chrono::milliseconds(SLEEP_FOR_TWENTY_MILLISECOND);
137 return timeT;
138 }
139
QueuePushFullEquivalent(const int equivalent,benchmark::State & state)140 static void QueuePushFullEquivalent(const int equivalent, benchmark::State& state)
141 {
142 for (unsigned int i = 0; i < QUEUE_SLOTS; i++) {
143 DemoThreadData::shareQueue.Push(equivalent);
144 }
145 AssertTrue((DemoThreadData::shareQueue.IsFull()), "shareQueue.IsFull() did not equal true.", state);
146 }
147
QueuePushInnotfullNotEquivalent(const unsigned int remain)148 static void QueuePushInnotfullNotEquivalent(const unsigned int remain)
149 {
150 for (unsigned int i = 0; i < QUEUE_SLOTS - remain; i++) {
151 int t = i;
152 DemoThreadData::shareQueue.Push(t);
153 }
154 }
155
156 /*
157 * @tc.name: testPut001
158 * @tc.desc: Single-threaded call put and get to determine that the normal scenario
159 */
BENCHMARK_F(BenchmarkSafeBlockQueue,testPut001)160 BENCHMARK_F(BenchmarkSafeBlockQueue, testPut001)(benchmark::State& state)
161 {
162 BENCHMARK_LOGD("SafeBlockQueue testPut001 start.");
163 while (state.KeepRunning()) {
164 SafeBlockQueue<int> qi(QUEUE_CAPACITY);
165 int i = 1;
166 qi.Push(i);
167 const unsigned int expectedQueueSize = 1;
168 AssertEqual(static_cast<unsigned>(expectedQueueSize), qi.Size(),
169 "static_cast<unsigned>(expectedQueueSize) did not equal qi.Size() as expected.", state);
170 }
171 BENCHMARK_LOGD("SafeBlockQueue testPut001 end.");
172 }
173
174 /*
175 * @tc.name: testGet001
176 * @tc.desc: Single-threaded call put and get to determine that the normal scenario
177 */
BENCHMARK_F(BenchmarkSafeBlockQueue,testGet001)178 BENCHMARK_F(BenchmarkSafeBlockQueue, testGet001)(benchmark::State& state)
179 {
180 BENCHMARK_LOGD("SafeBlockQueue testGet001 start.");
181 const int pushCount = 3;
182 const unsigned int expectedQueueSize = 3;
183 const int expectedFirstElement = 0;
184 while (state.KeepRunning()) {
185 SafeBlockQueue<int> qi(QUEUE_CAPACITY);
186 for (int i = 0; i < pushCount; i++) {
187 qi.Push(i);
188 }
189 AssertEqual(static_cast<unsigned>(expectedQueueSize), qi.Size(),
190 "static_cast<unsigned>(expectedQueueSize) did not equal qi.Size() as expected.", state);
191 int t = qi.Pop();
192 AssertEqual(t, expectedFirstElement, "t did not equal expectedFirstElement as expected.", state);
193 }
194 BENCHMARK_LOGD("SafeBlockQueue testGet001 end.");
195 }
196
QueueFullHandler(std::thread (& threads)[THREAD_NUM],std::array<DemoThreadData,THREAD_NUM> & demoDatas,benchmark::State & state)197 void QueueFullHandler(std::thread (&threads)[THREAD_NUM], std::array<DemoThreadData, THREAD_NUM>& demoDatas,
198 benchmark::State& state)
199 {
200 // 1. queue is full and some threads is blocked
201 std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_FOR_TWENTY_MILLISECOND));
202 AssertTrue((DemoThreadData::shareQueue.IsFull()),
203 "DemoThreadData::shareQueue.IsFull() did not equal true as expected.", state);
204 unsigned int pushedIn = 0;
205 unsigned int unpushedIn = 0;
206 unsigned int getedOut = 0;
207 unsigned int ungetedOut = 0;
208 GetThreadDatePushedStatus(demoDatas, pushedIn, unpushedIn);
209 AssertEqual(pushedIn, QUEUE_SLOTS, "pushedIn did not equal QUEUE_SLOTS as expected.", state);
210 AssertEqual(unpushedIn, THREAD_NUM - QUEUE_SLOTS,
211 "unpushedIn did not equal THREAD_NUM - QUEUE_SLOTS as expected.", state);
212 // 2. get one out and wait some put in
213 for (unsigned int i = 0; i < THREAD_NUM - QUEUE_SLOTS; i++) {
214 demoDatas[0].Get();
215 }
216 std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_FOR_TWENTY_MILLISECOND));
217 // queue is full and some threads is blocked and is not joined
218 AssertTrue((DemoThreadData::shareQueue.IsFull()),
219 "DemoThreadData::shareQueue.IsFull() did not equal true as expected.", state);
220 GetThreadDatePushedStatus(demoDatas, pushedIn, unpushedIn);
221 GetThreadDateGetedStatus(demoDatas, getedOut, ungetedOut);
222 AssertEqual(pushedIn, THREAD_NUM, "pushedIn did not equal THREAD_NUM as expected.", state);
223 AssertEqual(getedOut, THREAD_NUM - QUEUE_SLOTS,
224 "getedOut did not equal THREAD_NUM - QUEUE_SLOTS as expected.", state);
225 for (auto& t : threads) {
226 t.join();
227 }
228 while (!DemoThreadData::shareQueue.IsEmpty()) {
229 demoDatas[0].Get();
230 }
231 }
232
233 /*
234 * @tc.name: testMutilthreadPutAndBlock001
235 * @tc.desc: Multiple threads put until blocking runs, one thread gets, all threads finish running normally
236 */
BENCHMARK_F(BenchmarkSafeBlockQueue,testMutilthreadPutAndBlock001)237 BENCHMARK_F(BenchmarkSafeBlockQueue, testMutilthreadPutAndBlock001)(benchmark::State& state)
238 {
239 BENCHMARK_LOGD("SafeBlockQueue testMutilthreadPutAndBlock001 start.");
240 std::thread threads[THREAD_NUM];
241 std::array<DemoThreadData, THREAD_NUM> demoDatas;
242 while (state.KeepRunning()) {
243 demoDatas.fill(DemoThreadData());
244 for (unsigned int i = 0; i < THREAD_NUM; i++) {
245 threads[i] = std::thread(PutHandleThreadData, std::ref(demoDatas[i]), i);
246 }
247
248 QueueFullHandler(threads, demoDatas, state);
249 }
250 BENCHMARK_LOGD("SafeBlockQueue testMutilthreadPutAndBlock001 end.");
251 }
252
253 /*
254 * @tc.name: testMutilthreadConcurrentPutAndBlockInblankqueue001
255 * @tc.desc: Multi-threaded put() on the empty queue. When n threads are waiting to reach a certain
256 * time-point, everyone puts concurrent to see the status of the queue and the state of the thread.
257 */
BENCHMARK_F(BenchmarkSafeBlockQueue,testMutilthreadConcurrentPutAndBlockInblankqueue001)258 BENCHMARK_F(BenchmarkSafeBlockQueue, testMutilthreadConcurrentPutAndBlockInblankqueue001)(benchmark::State& state)
259 {
260 BENCHMARK_LOGD("SafeBlockQueue testMutilthreadConcurrentPutAndBlockInblankqueue001 start.");
261 std::thread threads[THREAD_NUM];
262 std::array<DemoThreadData, THREAD_NUM> demoDatas;
263 while (state.KeepRunning()) {
264 demoDatas.fill(DemoThreadData());
265 auto timeT = GetTimeOfSleepTwentyMillisecond();
266 AssertTrue((DemoThreadData::shareQueue.IsEmpty()),
267 "DemoThreadData::shareQueue.IsEmpty() did not equal true as expected.", state);
268 for (unsigned int i = 0; i < THREAD_NUM; i++) {
269 threads[i] = std::thread(PutHandleThreadDataTime,
270 std::ref(demoDatas[i]), i, timeT);
271 }
272
273 QueueFullHandler(threads, demoDatas, state);
274 }
275 BENCHMARK_LOGD("SafeBlockQueue testMutilthreadConcurrentPutAndBlockInblankqueue001 end.");
276 }
277
278 /*
279 * @tc.name: testMutilthreadConcurrentPutAndBlockInfullqueue001
280 * @tc.desc: Multi-threaded put() on the full queue. When n threads are waiting to reach a certain
281 * time-point, everyone puts concurrent to see the status of the queue and the state of the thread.
282 */
BENCHMARK_F(BenchmarkSafeBlockQueue,testMutilthreadConcurrentPutAndBlockInfullqueue001)283 BENCHMARK_F(BenchmarkSafeBlockQueue, testMutilthreadConcurrentPutAndBlockInfullqueue001)(benchmark::State& state)
284 {
285 BENCHMARK_LOGD("SafeBlockQueue testMutilthreadConcurrentPutAndBlockInfullqueue001 start.");
286 std::thread threads[THREAD_NUM];
287 std::array<DemoThreadData, THREAD_NUM> demoDatas;
288 while (state.KeepRunning()) {
289 demoDatas.fill(DemoThreadData());
290 auto timeT = GetTimeOfSleepTwentyMillisecond();
291 AssertTrue((DemoThreadData::shareQueue.IsEmpty()),
292 "DemoThreadData::shareQueue.IsEmpty() did not equal true as expected.", state);
293 for (unsigned int i = 0; i < QUEUE_SLOTS; i++) {
294 int t = i;
295 DemoThreadData::shareQueue.Push(t);
296 }
297 AssertTrue((DemoThreadData::shareQueue.IsFull()),
298 "DemoThreadData::shareQueue.IsFull() did not equal true as expected.", state);
299 for (unsigned int i = 0; i < THREAD_NUM; i++) {
300 threads[i] = std::thread(PutHandleThreadDataTime,
301 std::ref(demoDatas[i]), i, timeT);
302 }
303 std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_FOR_TWENTY_MILLISECOND));
304 unsigned int pushedIn = 0;
305 unsigned int unpushedIn = 0;
306 GetThreadDatePushedStatus(demoDatas, pushedIn, unpushedIn);
307 AssertEqual(pushedIn, static_cast<unsigned int>(0),
308 "pushedIn did not equal static_cast<unsigned int>(0) as expected.", state);
309 AssertEqual(unpushedIn, THREAD_NUM, "unpushedIn did not equal THREAD_NUM.", state);
310 AssertTrue((DemoThreadData::shareQueue.IsFull()),
311 "DemoThreadData::shareQueue.IsFull() did not equal true as expected.", state);
312 for (unsigned int i = 0; i < THREAD_NUM; i++) {
313 DemoThreadData::shareQueue.Pop();
314 std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_FOR_TWENTY_MILLISECOND));
315 AssertTrue((DemoThreadData::shareQueue.IsFull()),
316 "DemoThreadData::shareQueue.IsFull() did not equal true as expected.", state);
317 GetThreadDatePushedStatus(demoDatas, pushedIn, unpushedIn);
318 AssertEqual(pushedIn, i + 1, "pushedIn did not equal i + 1 as expected.", state);
319 AssertEqual(unpushedIn, THREAD_NUM - (i + 1), "unpushedIn did not equal THREAD_NUM - (i + 1).", state);
320 }
321 for (auto& t : threads) {
322 t.join();
323 }
324 while (!DemoThreadData::shareQueue.IsEmpty()) {
325 demoDatas[0].Get();
326 }
327 }
328 BENCHMARK_LOGD("SafeBlockQueue testMutilthreadConcurrentPutAndBlockInfullqueue001 end.");
329 }
330
331 /*
332 * @tc.name: testMutilthreadConcurrentGetAndBlockInblankqueue001
333 * @tc.desc: Multi-threaded get() on the empty queue. When n threads are waiting to reach a certain
334 * time-point, everyone gets concurrent to see the status of the queue and the state of the thread.
335 */
BENCHMARK_F(BenchmarkSafeBlockQueue,testMutilthreadConcurrentGetAndBlockInblankqueue001)336 BENCHMARK_F(BenchmarkSafeBlockQueue, testMutilthreadConcurrentGetAndBlockInblankqueue001)(benchmark::State& state)
337 {
338 BENCHMARK_LOGD("SafeBlockQueue testMutilthreadConcurrentGetAndBlockInblankqueue001 start.");
339 std::thread threads[THREAD_NUM];
340 std::array<DemoThreadData, THREAD_NUM> demoDatas;
341 while (state.KeepRunning()) {
342 demoDatas.fill(DemoThreadData());
343 auto timeT = GetTimeOfSleepTwentyMillisecond();
344 AssertTrue((DemoThreadData::shareQueue.IsEmpty()),
345 "DemoThreadData::shareQueue.IsEmpty() did not equal true as expected.", state);
346 for (unsigned int i = 0; i < THREAD_NUM; i++) {
347 threads[i] = std::thread(GetHandleThreadDataTime,
348 std::ref(demoDatas[i]), i, timeT);
349 }
350 std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_FOR_TWENTY_MILLISECOND));
351 unsigned int getedOut = 0;
352 unsigned int ungetedOut = 0;
353 GetThreadDateGetedStatus(demoDatas, getedOut, ungetedOut);
354 AssertEqual(getedOut, static_cast<unsigned int>(0),
355 "getedOut did not equal static_cast<unsigned int>(0) as expected.", state);
356 AssertEqual(ungetedOut, THREAD_NUM, "ungetedOut did not equal THREAD_NUM as expected.", state);
357 AssertTrue((DemoThreadData::shareQueue.IsEmpty()),
358 "DemoThreadData::shareQueue.IsEmpty() did not equal true as expected.", state);
359
360 int value = 1;
361 for (unsigned int i = 0; i < THREAD_NUM; i++) {
362 DemoThreadData::shareQueue.Push(value);
363 std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_FOR_TWENTY_MILLISECOND));
364 AssertTrue((DemoThreadData::shareQueue.IsEmpty()),
365 "DemoThreadData::shareQueue.IsEmpty() did not equal true as expected.", state);
366 GetThreadDateGetedStatus(demoDatas, getedOut, ungetedOut);
367 AssertEqual(getedOut, i + 1, "getedOut did not equal i + 1 as expected.", state);
368 AssertEqual(ungetedOut, THREAD_NUM - (i + 1),
369 "ungetedOut did not equal THREAD_NUM - (i + 1) as expected.", state);
370 }
371 for (auto& t : threads) {
372 t.join();
373 }
374
375 while (!DemoThreadData::shareQueue.IsEmpty()) {
376 demoDatas[0].Get();
377 }
378 }
379 BENCHMARK_LOGD("SafeBlockQueue testMutilthreadConcurrentGetAndBlockInblankqueue001 end.");
380 }
381
382 /*
383 * @tc.name: testMutilthreadConcurrentGetAndBlockInfullqueue001
384 * @tc.desc: Multi-threaded get() on the full queue. When n threads are waiting to reach a certain
385 * time-point, everyone gets concurrent to see the status of the queue and the state of the thread.
386 */
BENCHMARK_F(BenchmarkSafeBlockQueue,testMutilthreadConcurrentGetAndBlockInfullqueue001)387 BENCHMARK_F(BenchmarkSafeBlockQueue, testMutilthreadConcurrentGetAndBlockInfullqueue001)(benchmark::State& state)
388 {
389 BENCHMARK_LOGD("SafeBlockQueue testMutilthreadConcurrentGetAndBlockInfullqueue001 start.");
390 std::thread threads[THREAD_NUM];
391 std::array<DemoThreadData, THREAD_NUM> demoDatas;
392 while (state.KeepRunning()) {
393 demoDatas.fill(DemoThreadData());
394 auto timeT = GetTimeOfSleepTwentyMillisecond();
395 AssertTrue((DemoThreadData::shareQueue.IsEmpty()),
396 "DemoThreadData::shareQueue.IsEmpty() did not equal true as expected.", state);
397 int t = 1;
398 QueuePushFullEquivalent(t, state);
399 for (unsigned int i = 0; i < THREAD_NUM; i++) {
400 threads[i] = std::thread(GetHandleThreadDataTime,
401 std::ref(demoDatas[i]), i, timeT);
402 }
403 std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_FOR_TWENTY_MILLISECOND));
404 AssertTrue((DemoThreadData::shareQueue.IsEmpty()),
405 "DemoThreadData::shareQueue.IsEmpty() did not equal true as expected.", state);
406 unsigned int getedOut = 0;
407 unsigned int ungetedOut = 0;
408 GetThreadDateGetedStatus(demoDatas, getedOut, ungetedOut);
409 AssertEqual(getedOut, QUEUE_SLOTS, "getedOut did not equal QUEUE_SLOTS as expected.", state);
410 AssertEqual(ungetedOut, THREAD_NUM - QUEUE_SLOTS, "ungetedOut did not equal THREAD_NUM - QUEUE_SLOTS.", state);
411 for (unsigned int i = 0; i < THREAD_NUM - QUEUE_SLOTS; i++) {
412 demoDatas[0].Put(t);
413 }
414 std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_FOR_TWENTY_MILLISECOND));
415 AssertTrue((DemoThreadData::shareQueue.IsEmpty()),
416 "DemoThreadData::shareQueue.IsEmpty() did not equal true as expected.", state);
417 GetThreadDateGetedStatus(demoDatas, getedOut, ungetedOut);
418 AssertEqual(getedOut, THREAD_NUM, "getedOut did not equal THREAD_NUM as expected.", state);
419 AssertEqual(ungetedOut, static_cast<unsigned int>(0),
420 "ungetedOut did not equal static_cast<unsigned int>(0) as expected.", state);
421 for (auto& singleThread : threads) {
422 singleThread.join();
423 }
424 while (!DemoThreadData::shareQueue.IsEmpty()) {
425 demoDatas[0].Get();
426 }
427 }
428 BENCHMARK_LOGD("SafeBlockQueue testMutilthreadConcurrentGetAndBlockInfullqueue001 end.");
429 }
430
431 /*
432 * @tc.name: testMutilthreadConcurrentGetAndBlockInnotfullqueue001
433 * @tc.desc: Multi-threaded get() on the notfull queue. When n threads are waiting to reach a certain
434 * time-point, everyone get concurrent to see the status of the queue and the state of the thread.
435 */
BENCHMARK_F(BenchmarkSafeBlockQueue,testMutilthreadConcurrentGetAndBlockInnotfullqueue001)436 BENCHMARK_F(BenchmarkSafeBlockQueue, testMutilthreadConcurrentGetAndBlockInnotfullqueue001)(benchmark::State& state)
437 {
438 BENCHMARK_LOGD("SafeBlockQueue testMutilthreadConcurrentGetAndBlockInnotfullqueue001 start.");
439 std::thread threads[THREAD_NUM];
440 std::array<DemoThreadData, THREAD_NUM> demoDatas;
441 while (state.KeepRunning()) {
442 demoDatas.fill(DemoThreadData());
443 auto timeT = GetTimeOfSleepTwentyMillisecond();
444 const unsigned int REMAIN_SLOTS = 5;
445 AssertTrue((DemoThreadData::shareQueue.IsEmpty()), "shareQueue.IsEmpty() did not equal true.", state);
446 QueuePushInnotfullNotEquivalent(REMAIN_SLOTS);
447 for (unsigned int i = 0; i < THREAD_NUM; i++) {
448 threads[i] = std::thread(GetHandleThreadDataTime,
449 std::ref(demoDatas[i]), i, timeT);
450 }
451 std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_FOR_TWENTY_MILLISECOND));
452 unsigned int getedOut = 0;
453 unsigned int ungetedOut = 0;
454 GetThreadDateGetedStatus(demoDatas, getedOut, ungetedOut);
455 AssertEqual(getedOut, QUEUE_SLOTS - REMAIN_SLOTS,
456 "getedOut did not equal QUEUE_SLOTS - REMAIN_SLOTS as expected.", state);
457 AssertEqual(ungetedOut, THREAD_NUM - (QUEUE_SLOTS - REMAIN_SLOTS),
458 "ungetedOut did not equal THREAD_NUM - (QUEUE_SLOTS - REMAIN_SLOTS) as expected.", state);
459 for (unsigned int i = 0; i < ungetedOut; i++) {
460 int t = i;
461 DemoThreadData::shareQueue.Push(t);
462 }
463 std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_FOR_TWENTY_MILLISECOND));
464 GetThreadDateGetedStatus(demoDatas, getedOut, ungetedOut);
465 AssertEqual(getedOut, THREAD_NUM, "getedOut did not equal THREAD_NUM as expected.", state);
466 AssertEqual(ungetedOut, static_cast<unsigned int>(0),
467 "ungetedOut did not equal static_cast<unsigned int>(0) as expected.", state);
468 for (auto& t : threads) {
469 t.join();
470 }
471 while (!DemoThreadData::shareQueue.IsEmpty()) {
472 demoDatas[0].Get();
473 }
474 }
475 BENCHMARK_LOGD("SafeBlockQueue testMutilthreadConcurrentGetAndBlockInnotfullqueue001 end.");
476 }
477
478 /*
479 * @tc.name: testMutilthreadConcurrentPutAndBlockInnotfullqueue001
480 * @tc.desc: Multi-threaded put() on the not full queue. When n threads are waiting to reach a certain
481 * time-point, everyone puts concurrent to see the status of the queue and the state of the thread.
482 */
BENCHMARK_F(BenchmarkSafeBlockQueue,testMutilthreadConcurrentPutAndBlockInnotfullqueue001)483 BENCHMARK_F(BenchmarkSafeBlockQueue, testMutilthreadConcurrentPutAndBlockInnotfullqueue001)(benchmark::State& state)
484 {
485 BENCHMARK_LOGD("SafeBlockQueue testMutilthreadConcurrentPutAndBlockInnotfullqueue001 start.");
486 std::thread threads[THREAD_NUM];
487 std::array<DemoThreadData, THREAD_NUM> demoDatas;
488 while (state.KeepRunning()) {
489 demoDatas.fill(DemoThreadData());
490 auto timeT = GetTimeOfSleepTwentyMillisecond();
491 const unsigned int REMAIN_SLOTS = 5;
492 AssertTrue((DemoThreadData::shareQueue.IsEmpty()), "shareQueue.IsEmpty() did not equal true.", state);
493 QueuePushInnotfullNotEquivalent(REMAIN_SLOTS);
494 for (unsigned int i = 0; i < THREAD_NUM; i++) {
495 threads[i] = std::thread(PutHandleThreadDataTime,
496 std::ref(demoDatas[i]), i, timeT);
497 }
498 std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_FOR_TWENTY_MILLISECOND));
499 unsigned int putedin = 0;
500 unsigned int unputedin = 0;
501 GetThreadDatePushedStatus(demoDatas, putedin, unputedin);
502 AssertEqual(putedin, REMAIN_SLOTS, "putedin did not equal REMAIN_SLOTS as expected.", state);
503 AssertEqual(unputedin, THREAD_NUM - REMAIN_SLOTS,
504 "unputedin did not equal THREAD_NUM - REMAIN_SLOTS as expected.", state);
505 for (unsigned int i = 0; i < unputedin; i++) {
506 DemoThreadData::shareQueue.Pop();
507 }
508 std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_FOR_TWENTY_MILLISECOND));
509 GetThreadDatePushedStatus(demoDatas, putedin, unputedin);
510 AssertEqual(putedin, THREAD_NUM, "putedin did not equal THREAD_NUM as expected.", state);
511 AssertEqual(unputedin, static_cast<unsigned int>(0),
512 "unputedin did not equal static_cast<unsigned int>(0) as expected.", state);
513 for (auto& t : threads) {
514 t.join();
515 }
516 while (!DemoThreadData::shareQueue.IsEmpty()) {
517 demoDatas[0].Get();
518 }
519 }
520 BENCHMARK_LOGD("SafeBlockQueue testMutilthreadConcurrentPutAndBlockInnotfullqueue001 end.");
521 }
522
523 /*
524 * @tc.name: testMutilthreadConcurrentGetAndPopInblankqueue001
525 * @tc.desc: Multi-threaded put() and Multi-threaded get() on the empty queue. When all threads are waiting to reach
526 * a certain time-point, everyone run concurrently to see the status of the queue and the state of the thread.
527 */
BENCHMARK_F(BenchmarkSafeBlockQueue,testMutilthreadConcurrentGetAndPopInblankqueue001)528 BENCHMARK_F(BenchmarkSafeBlockQueue, testMutilthreadConcurrentGetAndPopInblankqueue001)(benchmark::State& state)
529 {
530 BENCHMARK_LOGD("SafeBlockQueue testMutilthreadConcurrentGetAndPopInblankqueue001 start.");
531 std::thread threadsout[THREAD_NUM];
532 std::array<DemoThreadData, THREAD_NUM> demoDatas;
533 while (state.KeepRunning()) {
534 demoDatas.fill(DemoThreadData());
535 std::thread threadsin[THREAD_NUM];
536 auto timeT = GetTimeOfSleepTwentyMillisecond();
537 AssertTrue((DemoThreadData::shareQueue.IsEmpty()),
538 "DemoThreadData::shareQueue.IsEmpty() did not equal true as expected.", state);
539 for (unsigned int i = 0; i < THREAD_NUM; i++) {
540 threadsout[i] = std::thread(GetHandleThreadDataTime,
541 std::ref(demoDatas[i]), i, timeT);
542 }
543 for (unsigned int i = 0; i < THREAD_NUM; i++) {
544 threadsin[i] = std::thread(PutHandleThreadDataTime,
545 std::ref(demoDatas[i]), i, timeT);
546 }
547 std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_FOR_TWENTY_MILLISECOND));
548 AssertTrue((DemoThreadData::shareQueue.IsEmpty()),
549 "DemoThreadData::shareQueue.IsEmpty() did not equal true as expected.", state);
550 unsigned int getedOut = 0;
551 unsigned int ungetedOut = 0;
552 unsigned int pushedIn = 0;
553 unsigned int unpushedIn = 0;
554 GetThreadDateGetedStatus(demoDatas, getedOut, ungetedOut);
555 GetThreadDatePushedStatus(demoDatas, pushedIn, unpushedIn);
556 AssertEqual(pushedIn, THREAD_NUM, "pushedIn did not equal THREAD_NUM as expected.", state);
557 AssertEqual(getedOut, THREAD_NUM, "getedOut did not equal THREAD_NUM as expected.", state);
558 for (auto& t : threadsout) {
559 t.join();
560 }
561 for (auto& t : threadsin) {
562 t.join();
563 }
564 while (!DemoThreadData::shareQueue.IsEmpty()) {
565 demoDatas[0].Get();
566 }
567 }
568 BENCHMARK_LOGD("SafeBlockQueue testMutilthreadConcurrentGetAndPopInblankqueue001 end.");
569 }
570
571 /*
572 * @tc.name: testMutilthreadConcurrentGetAndPopInfullqueue001
573 * @tc.desc: Multi-threaded put() and Multi-threaded get() on the full queue.
574 * When all threads are waiting to reach a certain
575 * time-point, everyone run concurrently to see the status of the queue and the state of the thread.
576 */
BENCHMARK_F(BenchmarkSafeBlockQueue,testMutilthreadConcurrentGetAndPopInfullqueue001)577 BENCHMARK_F(BenchmarkSafeBlockQueue, testMutilthreadConcurrentGetAndPopInfullqueue001)(benchmark::State& state)
578 {
579 BENCHMARK_LOGD("SafeBlockQueue testMutilthreadConcurrentGetAndPopInfullqueue001 start.");
580 std::thread threadsout[THREAD_NUM];
581 std::array<DemoThreadData, THREAD_NUM> demoDatas;
582 while (state.KeepRunning()) {
583 demoDatas.fill(DemoThreadData());
584 std::thread threadsin[THREAD_NUM];
585 auto timeT = GetTimeOfSleepTwentyMillisecond();
586 AssertTrue((DemoThreadData::shareQueue.IsEmpty()),
587 "DemoThreadData::shareQueue.IsEmpty() did not equal true as expected.", state);
588 int t = 1;
589 QueuePushFullEquivalent(t, state);
590 for (unsigned int i = 0; i < THREAD_NUM; i++) {
591 threadsin[i] = std::thread(PutHandleThreadDataTime,
592 std::ref(demoDatas[i]), i, timeT);
593 }
594 for (unsigned int i = 0; i < THREAD_NUM; i++) {
595 threadsout[i] = std::thread(GetHandleThreadDataTime,
596 std::ref(demoDatas[i]), i, timeT);
597 }
598 std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_FOR_TWENTY_MILLISECOND));
599 AssertTrue((DemoThreadData::shareQueue.IsFull()),
600 "DemoThreadData::shareQueue.IsFull() did not equal true as expected.", state);
601 unsigned int getedOut = 0;
602 unsigned int ungetedOut = 0;
603 unsigned int pushedIn = 0;
604 unsigned int unpushedIn = 0;
605 GetThreadDateGetedStatus(demoDatas, getedOut, ungetedOut);
606 GetThreadDatePushedStatus(demoDatas, pushedIn, unpushedIn);
607 AssertEqual(pushedIn, THREAD_NUM, "pushedIn did not equal THREAD_NUM as expected.", state);
608 AssertEqual(getedOut, THREAD_NUM, "getedOut did not equal THREAD_NUM as expected.", state);
609 for (auto& outThread : threadsout) {
610 outThread.join();
611 }
612 for (auto& inThread : threadsin) {
613 inThread.join();
614 }
615 while (!DemoThreadData::shareQueue.IsEmpty()) {
616 demoDatas[0].Get();
617 }
618 }
619 BENCHMARK_LOGD("SafeBlockQueue testMutilthreadConcurrentGetAndPopInfullqueue001 end.");
620 }
621
622 /*
623 * @tc.name: testPushNoWait001
624 * @tc.desc: Single-threaded call PushNoWait and check the performance
625 */
BENCHMARK_F(BenchmarkSafeBlockQueue,testPushNoWait001)626 BENCHMARK_F(BenchmarkSafeBlockQueue, testPushNoWait001)(benchmark::State& state)
627 {
628 BENCHMARK_LOGD("SafeBlockQueue testPushNoWait001 start.");
629 while (state.KeepRunning()) {
630 SafeBlockQueue<int> qi(QUEUE_CAPACITY);
631 int i = 1;
632 bool result = qi.PushNoWait(i);
633 AssertTrue(result, "PushNoWait returned false, expected true.", state);
634 }
635 BENCHMARK_LOGD("SafeBlockQueue testPushNoWait001 end.");
636 }
637
638 /*
639 * @tc.name: testPopNoWait001
640 * @tc.desc: Single-threaded call PopNoWait and check the performance
641 */
BENCHMARK_F(BenchmarkSafeBlockQueue,testPopNoWait001)642 BENCHMARK_F(BenchmarkSafeBlockQueue, testPopNoWait001)(benchmark::State& state)
643 {
644 BENCHMARK_LOGD("SafeBlockQueue testPopNoWait001 start.");
645 const int pushCount = 10;
646 while (state.KeepRunning()) {
647 SafeBlockQueue<int> qi(QUEUE_CAPACITY);
648 for (int i = 0; i < pushCount; i++) {
649 qi.Push(i); // Fill the queue
650 }
651 int out;
652 bool result = qi.PopNotWait(out);
653 AssertTrue(result, "PopNoWait returned false, expected true.", state);
654 }
655 BENCHMARK_LOGD("SafeBlockQueue testPopNoWait001 end.");
656 }
657 } // namespace
658 } // namespace OHOS
659 // Run the benchmark
660 BENCHMARK_MAIN();