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