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