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