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();