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