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 <mutex>
17 #include <future>
18 #include <chrono>
19 #include <random>
20 #include <gtest/gtest.h>
21 #include "sync/sync.h"
22 #include "ffrt_inner.h"
23 #include "dfx/log/ffrt_log_api.h"
24 #include "c/thread.h"
25 #include "../common.h"
26
27 extern "C" int ffrt_mutexattr_init(ffrt_mutexattr_t* attr);
28 extern "C" int ffrt_mutexattr_settype(ffrt_mutexattr_t* attr, int type);
29 extern "C" int ffrt_mutexattr_gettype(ffrt_mutexattr_t* attr, int* type);
30 extern "C" int ffrt_mutexattr_destroy(ffrt_mutexattr_t* attr);
31 extern "C" int ffrt_mutex_init(ffrt_mutex_t *mutex, const ffrt_mutexattr_t* attr);
32 extern "C" int ffrt_mutex_lock(ffrt_mutex_t *mutex);
33 extern "C" int ffrt_mutex_unlock(ffrt_mutex_t *mutex);
34 extern "C" int ffrt_mutex_trylock(ffrt_mutex_t *mutex);
35 extern "C" int ffrt_mutex_destroy(ffrt_mutex_t *mutex);
36 using namespace std;
37 using namespace testing;
38 #ifdef HWTEST_TESTING_EXT_ENABLE
39 using namespace testing::ext;
40 #endif
41
42 class SyncTest : public testing::Test {
43 protected:
SetUpTestCase()44 static void SetUpTestCase()
45 {
46 }
47
TearDownTestCase()48 static void TearDownTestCase()
49 {
50 }
51
SetUp()52 virtual void SetUp()
53 {
54 }
55
TearDown()56 virtual void TearDown()
57 {
58 }
59 };
60
61 HWTEST_F(SyncTest, mutexattr_nullptr_fail, TestSize.Level1)
62 {
63 int ret = ffrt_mutexattr_init(nullptr);
64 EXPECT_EQ(ret, ffrt_error_inval);
65 ret = ffrt_mutexattr_settype(nullptr, 0);
66 EXPECT_EQ(ret, ffrt_error_inval);
67 ret = ffrt_mutexattr_gettype(nullptr, nullptr);
68 EXPECT_EQ(ret, ffrt_error_inval);
69 ret = ffrt_mutexattr_destroy(nullptr);
70 EXPECT_EQ(ret, ffrt_error_inval);
71 }
72
73 HWTEST_F(SyncTest, mutex_nullptr_fail, TestSize.Level1)
74 {
75 int ret = ffrt_mutex_init(nullptr, nullptr);
76 EXPECT_EQ(ret, ffrt_error_inval);
77 ret = ffrt_mutex_lock(nullptr);
78 EXPECT_EQ(ret, ffrt_error_inval);
79 ret = ffrt_mutex_unlock(nullptr);
80 EXPECT_EQ(ret, ffrt_error_inval);
81 ret = ffrt_mutex_trylock(nullptr);
82 EXPECT_EQ(ret, ffrt_error_inval);
83 ffrt_mutex_destroy(nullptr);
84 }
85
86 HWTEST_F(SyncTest, recursive_mutex_try_lock, TestSize.Level1)
87 {
88 int val = -1;
89 ffrt::recursive_mutex lock;
90 lock.lock();
91 val = lock.try_lock();
92 EXPECT_EQ(val, 1);
93 lock.unlock();
94 val = lock.try_lock();
95 EXPECT_EQ(val, 1);
96 lock.unlock();
97 lock.unlock();
98 }
99
100 HWTEST_F(SyncTest, class_data_align, TestSize.Level1)
101 {
102 struct memTest {
103 bool isFlag; // Construct an unaligned address
104 ffrt::mutex mtx;
105 ffrt::task_attr taskAttr;
106 ffrt::task_handle taskHandle;
107 ffrt::condition_variable cv;
108 ffrt::thread t;
109 };
110 memTest m;
111 {
112 ffrt::mutex* mtxAddr = &m.mtx;
113 uintptr_t addr_int = reinterpret_cast<uintptr_t>(mtxAddr);
114 EXPECT_EQ((addr_int % 4), 0);
115
116 ffrt::task_attr* attrAddr = &m.taskAttr;
117 addr_int = reinterpret_cast<uintptr_t>(attrAddr);
118 EXPECT_EQ((addr_int % 4), 0);
119
120 ffrt::task_handle* handleAddr = &m.taskHandle;
121 addr_int = reinterpret_cast<uintptr_t>(handleAddr);
122 EXPECT_EQ((addr_int % 4), 0);
123
124 ffrt::condition_variable* cvAddr = &m.cv;
125 addr_int = reinterpret_cast<uintptr_t>(cvAddr);
126 EXPECT_EQ((addr_int % 4), 0);
127
128 ffrt::thread* tAddr = &m.t;
129 addr_int = reinterpret_cast<uintptr_t>(tAddr);
130 EXPECT_EQ((addr_int % 4), 0);
131 }
132 }
133
134 HWTEST_F(SyncTest, lock_stress, TestSize.Level1)
135 {
136 // trigger lazy init
__anonc91b23f70102() 137 ffrt::submit([&]() {}, {}, {});
138 ffrt::wait();
139
140 const int N = 10;
141 const int M = 1000;
142 const int J = 10000;
143 ffrt::mutex lock;
144 // std::mutex lock;
145 int acc = 0;
146 for (int i = 0; i < N; ++i) {
147 ffrt::submit(
__anonc91b23f70402() 148 [&]() {
149 for (int j = 0; j < M; ++j) {
150 lock.lock();
151 acc++;
152 lock.unlock();
153 }
154 },
__anonc91b23f70502() 155 {}, {});
156 }
157
158 for (int j = 0; j < J; ++j) {
159 lock.lock();
160 acc++;
161 lock.unlock();
162 }
163
164 ffrt::wait();
165 EXPECT_EQ(acc, (M * N + J));
166 }
167
168 HWTEST_F(SyncTest, lock_stress_c_api, TestSize.Level1)
169 {
170 // trigger lazy init
__anonc91b23f70902() 171 ffrt::submit([&]() {}, {}, {});
172 ffrt::wait();
173
174 const int N = 10;
175 const int M = 1000;
176 const int J = 10000;
177 ffrt::mutex* lock = new ffrt::mutex;
178 int acc = 0;
179 for (int i = 0; i < N; ++i) {
180 ffrt::submit(
__anonc91b23f70a02() 181 [&]() {
182 for (int j = 0; j < M; ++j) {
183 lock->lock();
184 acc++;
185 lock->unlock();
186 }
187 },
__anonc91b23f70b02() 188 {}, {});
189 }
190
191 for (int j = 0; j < J; ++j) {
192 lock->lock();
193 acc++;
194 lock->unlock();
195 }
196
197 ffrt::wait();
198 EXPECT_EQ(acc, (M * N + J));
199 delete lock;
200 }
201
202 HWTEST_F(SyncTest, conditionTestNotifyOne, TestSize.Level1)
203 {
204 ffrt::condition_variable cond;
205 int a = 0;
206 ffrt::mutex lock_;
207
208 ffrt::submit(
__anonc91b23f70d02() 209 [&]() {
210 std::unique_lock lck(lock_);
211 cond.wait(lck, [&] { return a == 1; });
212 },
__anonc91b23f71002() 213 {}, {});
214
215 ffrt::submit(
__anonc91b23f71102() 216 [&]() {
217 std::unique_lock lck(lock_);
218 a = 1;
219 cond.notify_one();
220 },
__anonc91b23f71302() 221 {}, {});
222 ffrt::wait();
223 }
224
225 HWTEST_F(SyncTest, conditionTestNotifyAll, TestSize.Level1)
226 {
227 ffrt::condition_variable cond;
228 int a = 0;
229 ffrt::mutex lock_;
230
231 ffrt::submit(
__anonc91b23f71402() 232 [&]() {
233 std::unique_lock lck(lock_);
234 cond.wait(lck, [&] { return a == 1; });
235 },
__anonc91b23f71702() 236 {}, {});
237 ffrt::submit(
__anonc91b23f71802() 238 [&]() {
239 std::unique_lock lck(lock_);
240 cond.wait(lck, [&] { return a == 1; });
241 },
__anonc91b23f71a02() 242 {}, {});
243 ffrt::submit(
__anonc91b23f71c02() 244 [&]() {
245 std::unique_lock lck(lock_);
246 cond.wait(lck, [&] { return a == 1; });
247 },
__anonc91b23f71f02() 248 {}, {});
249
250 ffrt::submit(
__anonc91b23f72002() 251 [&]() {
252 std::unique_lock lck(lock_);
253 a = 1;
254 cond.notify_all();
255 },
__anonc91b23f72202() 256 {}, {});
257 ffrt::wait();
258 }
259
260 HWTEST_F(SyncTest, conditionTestWaitfor, TestSize.Level1)
261 {
262 ffrt::condition_variable cond;
263 std::atomic_int a = 0;
264 ffrt::mutex lock_;
265
266 ffrt::submit(
__anonc91b23f72302() 267 [&]() {
268 std::unique_lock lck(lock_);
269 cond.wait_for(lck, 100ms, [&] { return a == 1; });
270 EXPECT_EQ(a, 2);
271 },
__anonc91b23f72602() 272 {}, {});
273 ffrt::submit(
__anonc91b23f72702() 274 [&]() {
275 std::unique_lock lck(lock_);
276 cond.wait_for(lck, 150ms, [&] { return a == 2; });
277 EXPECT_EQ(a, 2);
278 },
__anonc91b23f72a02() 279 {}, {});
280 ffrt::submit(
__anonc91b23f72b02() 281 [&]() {
282 std::unique_lock lck(lock_);
283 a = 2;
284 cond.notify_all();
285 },
__anonc91b23f72c02() 286 {}, {});
287 ffrt::wait();
288 }
289
290 HWTEST_F(SyncTest, conditionTestDataRace, TestSize.Level1)
291 {
292 std::atomic_bool exit {false};
293 ffrt::mutex mtx;
294 ffrt::condition_variable cv;
295 std::atomic_bool start {false};
296
__anonc91b23f72e02null297 ffrt::thread th {[&] {
298 while (!exit) {
299 if (start) {
300 cv.notify_one();
301 ffrt::this_task::sleep_for(1us);
302 }
303 }
304 }};
305
306 start = true;
307 for (int i = 0; i < 2000; ++i) {
308 std::unique_lock lk(mtx);
309 cv.wait_for(lk, 1us);
310 }
311 exit = true;
312 th.join();
313 exit = false;
314 start = true;
__anonc91b23f72f02null315 ffrt::thread th1 {[&] {
316 for (int i = 0; i < 2000; ++i) {
317 std::unique_lock lk(mtx);
318 cv.wait_for(lk, 1us);
319 }
320 exit = true;
321 }};
322
323 while (!exit) {
324 if (start) {
325 cv.notify_one();
326 ffrt::this_task::sleep_for(1us);
327 }
328 }
329
330 th1.join();
331 }
332
NotifyOneTest(ffrt::mutex & mtx,ffrt::condition_variable & cv)333 static void NotifyOneTest(ffrt::mutex& mtx, ffrt::condition_variable& cv)
334 {
335 FFRT_LOGE("[RUN ] notifyone");
336 int value = 0;
337 bool flag {false};
338 ffrt::submit(
339 [&]() {
340 std::unique_lock lk(mtx);
341 cv.wait(lk, [&] { return flag; });
342 EXPECT_TRUE(lk.owns_lock());
343 value = 123;
344 },
345 {}, {});
346
347 EXPECT_EQ(value, 0);
348
349 ffrt::submit(
350 [&]() {
351 {
352 std::unique_lock lk(mtx);
353 flag = true;
354 }
355 cv.notify_one();
356 },
357 {}, {});
358
359 ffrt::wait();
360
361 EXPECT_EQ(value, 123);
362 }
363
WaitUntilTimeoutTest(ffrt::mutex & mtx,ffrt::condition_variable & cv)364 static void WaitUntilTimeoutTest(ffrt::mutex& mtx, ffrt::condition_variable& cv)
365 {
366 constexpr auto eps = 3ms;
367
368 FFRT_LOGE("[RUN ] WaitUntil timeout¬ifyone");
369 int value = 0;
370 ffrt::submit(
371 [&]() {
372 std::unique_lock lk(mtx);
373 EXPECT_EQ(static_cast<int>(cv.wait_until(lk, std::chrono::steady_clock::now() + 30ms)),
374 static_cast<int>(ffrt::cv_status::timeout));
375 EXPECT_TRUE(lk.owns_lock());
376 value = 123;
377 },
378 {}, {});
379
380 EXPECT_EQ(value, 0);
381
382 ffrt::submit(
383 [&]() {
384 ffrt::this_task::sleep_for(30ms + eps);
385 cv.notify_one();
386 },
387 {}, {});
388
389 ffrt::wait();
390
391 EXPECT_EQ(value, 123);
392 }
393
WaitUtilFlagTest_1(ffrt::mutex & mtx,ffrt::condition_variable & cv)394 static void WaitUtilFlagTest_1(ffrt::mutex& mtx, ffrt::condition_variable& cv)
395 {
396 constexpr auto eps = 3ms;
397
398 FFRT_LOGE("[RUN ] WaitUntil flag¬ifyone");
399 int value = 0;
400 bool flag {false};
401
402 ffrt::submit(
403 [&]() {
404 std::unique_lock lk(mtx);
405 EXPECT_TRUE(!cv.wait_until(lk, std::chrono::steady_clock::now() + 30ms, [&] { return flag; }));
406 value = 123;
407 },
408 {}, {});
409
410 EXPECT_EQ(value, 0);
411
412 ffrt::submit(
413 [&]() {
414 ffrt::this_task::sleep_for(30ms + eps);
415 cv.notify_one();
416 },
417 {}, {});
418
419 ffrt::wait();
420
421 EXPECT_EQ(value, 123);
422 }
423
WaitUtilFlagTest_2(ffrt::mutex & mtx,ffrt::condition_variable & cv)424 static void WaitUtilFlagTest_2(ffrt::mutex& mtx, ffrt::condition_variable& cv)
425 {
426 int value = 0;
427 bool flag {false};
428
429 ffrt::submit(
430 [&]() {
431 std::unique_lock lk(mtx);
432 EXPECT_TRUE(cv.wait_until(lk, std::chrono::steady_clock::now() + 30ms, [&] { return flag; }));
433 value = 123;
434 },
435 {}, {});
436
437 EXPECT_EQ(value, 0);
438
439 ffrt::submit(
440 [&]() {
441 std::unique_lock lk(mtx);
442 flag = true;
443 cv.notify_one();
444 },
445 {}, {});
446
447 ffrt::wait();
448
449 EXPECT_EQ(value, 123);
450 }
451
WaitForTest_1(ffrt::mutex & mtx,ffrt::condition_variable & cv)452 static void WaitForTest_1(ffrt::mutex& mtx, ffrt::condition_variable& cv)
453 {
454 constexpr auto eps = 3ms;
455
456 int value = 0;
457 ffrt::submit(
458 [&]() {
459 std::unique_lock lk(mtx);
460 EXPECT_EQ(static_cast<int>(cv.wait_for(lk, 30ms)), static_cast<int>(ffrt::cv_status::timeout));
461 EXPECT_TRUE(lk.owns_lock());
462 value = 123;
463 },
464 {}, {});
465
466 EXPECT_EQ(value, 0);
467
468 ffrt::submit(
469 [&]() {
470 ffrt::this_task::sleep_for(30ms + eps);
471 cv.notify_one();
472 },
473 {}, {});
474
475 ffrt::wait();
476
477 EXPECT_EQ(value, 123);
478 }
479
WaitForTest_2(ffrt::mutex & mtx,ffrt::condition_variable & cv)480 static void WaitForTest_2(ffrt::mutex& mtx, ffrt::condition_variable& cv)
481 {
482 int value = 0;
483 ffrt::submit(
484 [&]() {
485 std::unique_lock lk(mtx);
486 ffrt::submit(
487 [&]() {
488 std::unique_lock lk(mtx);
489 cv.notify_one();
490 },
491 {}, {});
492 EXPECT_EQ(static_cast<int>(cv.wait_for(lk, 30ms)), static_cast<int>(ffrt::cv_status::no_timeout));
493 EXPECT_EQ(value, 0);
494 EXPECT_TRUE(lk.owns_lock());
495 value = 123;
496 },
497 {}, {});
498
499 ffrt::wait();
500
501 EXPECT_EQ(value, 123);
502 }
503
WaitForTest_3(ffrt::mutex & mtx,ffrt::condition_variable & cv)504 static void WaitForTest_3(ffrt::mutex& mtx, ffrt::condition_variable& cv)
505 {
506 constexpr auto eps = 3ms;
507
508 int value = 0;
509 bool flag {false};
510
511 ffrt::submit(
512 [&]() {
513 std::unique_lock lk(mtx);
514 EXPECT_TRUE(!cv.wait_for(lk, 30ms, [&] { return flag; }));
515 value = 123;
516 },
517 {}, {});
518
519 EXPECT_EQ(value, 0);
520
521 ffrt::submit(
522 [&]() {
523 ffrt::this_task::sleep_for(30ms + eps);
524 cv.notify_one();
525 },
526 {}, {});
527
528 ffrt::wait();
529
530 EXPECT_EQ(value, 123);
531 }
532
WaitForTest_4(ffrt::mutex & mtx,ffrt::condition_variable & cv)533 static void WaitForTest_4(ffrt::mutex& mtx, ffrt::condition_variable& cv)
534 {
535 int value = 0;
536 bool flag {false};
537
538 ffrt::submit(
539 [&]() {
540 std::unique_lock lk(mtx);
541 EXPECT_TRUE(cv.wait_for(lk, 30ms, [&] { return flag; }));
542 value = 123;
543 },
544 {}, {});
545
546 EXPECT_EQ(value, 0);
547
548 ffrt::submit(
549 [&]() {
550 std::unique_lock lk(mtx);
551 flag = true;
552 cv.notify_one();
553 },
554 {}, {});
555
556 ffrt::wait();
557
558 EXPECT_EQ(value, 123);
559 }
560
561 HWTEST_F(SyncTest, conditionTest, TestSize.Level1)
562 {
563 ffrt::mutex mtx;
564 ffrt::condition_variable cv;
565
566 NotifyOneTest(mtx, cv);
567 WaitUntilTimeoutTest(mtx, cv);
568 WaitUtilFlagTest_1(mtx, cv);
569 WaitUtilFlagTest_2(mtx, cv);
570 WaitForTest_1(mtx, cv);
571 WaitForTest_2(mtx, cv);
572 WaitForTest_3(mtx, cv);
573 WaitForTest_4(mtx, cv);
574 }
575
LockTest(ffrt::shared_mutex & smtx)576 static void LockTest(ffrt::shared_mutex& smtx)
577 {
578 int x = 0;
579 const int N = 100;
580 const int R = 200;
581
582 ffrt::submit(
583 [&]() {
584 for (int i = 0; i < N; i++) {
585 smtx.lock();
586 x++;
587 smtx.unlock();
588 }
589 },
590 {}, {});
591
592 for (int j = 0; j < N; ++j) {
593 smtx.lock();
594 x++;
595 smtx.unlock();
596 }
597
598 ffrt::wait();
599 EXPECT_EQ(x, R);
600 }
601
TryLockTest(ffrt::shared_mutex & smtx)602 static void TryLockTest(ffrt::shared_mutex& smtx)
603 {
604 int x = 0;
605 const int N = 100;
606 ffrt::submit(
607 [&]() {
608 smtx.lock();
609 ffrt::this_task::sleep_for(20ms);
610 smtx.unlock();
611 },
612 {}, {});
613
614 ffrt::this_task::sleep_for(2ms);
615
616 bool ret = smtx.try_lock();
617 EXPECT_EQ(ret, false);
618 if (ret) {
619 smtx.unlock();
620 }
621 ffrt::wait();
622
623 ret = smtx.try_lock();
624 EXPECT_EQ(ret, true);
625 if (ret) {
626 smtx.unlock();
627 }
628 }
629
LockSharedTest(ffrt::shared_mutex & smtx)630 static void LockSharedTest(ffrt::shared_mutex& smtx)
631 {
632 int x = 0;
633 const int N = 100;
634
635 ffrt::submit(
636 [&]() {
637 smtx.lock_shared();
638 ffrt::this_task::sleep_for(20ms);
639 x = N;
640 smtx.unlock_shared();
641 },
642 {}, {});
643 ffrt::this_task::sleep_for(2ms);
644
645 smtx.lock_shared();
646 EXPECT_EQ(x, 0);
647 smtx.unlock_shared();
648
649 smtx.lock();
650 EXPECT_EQ(x, N);
651 smtx.unlock();
652
653 ffrt::wait();
654
655 smtx.lock_shared();
656 EXPECT_EQ(x, N);
657 smtx.unlock_shared();
658 }
659
TryLockSharedTest(ffrt::shared_mutex & smtx)660 static void TryLockSharedTest(ffrt::shared_mutex& smtx)
661 {
662 int x = 0;
663 const int N = 100;
664
665 ffrt::submit(
666 [&]() {
667 smtx.lock_shared();
668 ffrt::this_task::sleep_for(20ms);
669 x = N;
670 smtx.unlock_shared();
671 },
672 {}, {});
673 ffrt::this_task::sleep_for(2ms);
674
675 bool ret = smtx.try_lock_shared();
676 EXPECT_EQ(ret, true);
677 EXPECT_EQ(x, 0);
678 if (ret) {
679 smtx.unlock_shared();
680 }
681 ffrt::wait();
682
683 ret = smtx.try_lock_shared();
684 EXPECT_EQ(ret, true);
685 EXPECT_EQ(x, N);
686 if (ret) {
687 smtx.unlock_shared();
688 }
689
690 ffrt::submit(
691 [&]() {
692 smtx.lock();
693 ffrt::this_task::sleep_for(20ms);
694 x = 0;
695 smtx.unlock();
696 },
697 {}, {});
698 ffrt::this_task::sleep_for(2ms);
699
700 ret = smtx.try_lock_shared();
701 EXPECT_EQ(ret, false);
702 EXPECT_EQ(x, N);
703 if (ret) {
704 smtx.unlock_shared();
705 }
706 ffrt::wait();
707
708 ret = smtx.try_lock_shared();
709 EXPECT_EQ(ret, true);
710 EXPECT_EQ(x, 0);
711 if (ret) {
712 smtx.unlock_shared();
713 }
714 }
715
716 HWTEST_F(SyncTest, sharedMutexTest, TestSize.Level1)
717 {
718 ffrt::shared_mutex smtx;
719 LockTest(smtx);
720 TryLockTest(smtx);
721 LockSharedTest(smtx);
722 TryLockSharedTest(smtx);
723 }
724
725 HWTEST_F(SyncTest, thread1, TestSize.Level1)
726 {
__anonc91b23f77402(int a, const int& b) 727 auto ThreadFunc1 = [](int a, const int& b) {
728 FFRT_LOGW("a = %d, b = %d", a, b);
729 return 0;
730 };
731
__anonc91b23f77502(const char* a, const char* b) 732 auto ThreadFunc2 = [](const char* a, const char* b) {
733 FFRT_LOGW("%s %s", a, b);
734 return 0;
735 };
736
737 {
738 int value = 0;
__anonc91b23f77602null739 std::thread th0 {[&value, &ThreadFunc1, &ThreadFunc2] {
740 std::thread th1 {ThreadFunc1, 10, 20};
741 std::thread th2 {ThreadFunc2, "hello", "ffrt"};
742 th1.join();
743 th2.join();
744
745 value = 123;
746 FFRT_LOGW("value = %d", value);
747 }};
748 th0.join();
749 assert(!th0.joinable());
750 EXPECT_EQ(value, 123);
751 }
752 {
753 int value = 0;
__anonc91b23f77702null754 ffrt::thread th0 {[&value, &ThreadFunc1, &ThreadFunc2] {
755 ffrt::thread th1 {ThreadFunc1, 10, 20};
756 ffrt::thread th2 {ThreadFunc2, "hello", "ffrt"};
757 th1.join();
758 th2.join();
759
760 value = 123;
761 FFRT_LOGW("value = %d", value);
762 }};
763 th0.join();
764 assert(!th0.joinable());
765 EXPECT_EQ(value, 123);
766 }
767 }
768
f1(int n)769 void f1(int n)
770 {
771 for (int i = 0; i < 5; ++i) {
772 std::cout << "Thread 1 executing\n";
773 ++n;
774 std::this_thread::sleep_for(std::chrono::milliseconds(10));
775 }
776 }
777
f2(int & n)778 void f2(int& n)
779 {
780 for (int i = 0; i < 5; ++i) {
781 std::cout << "Thread 2 executing\n";
782 ++n;
783 std::this_thread::sleep_for(std::chrono::milliseconds(10));
784 }
785 }
786
787 class foo {
788 public:
bar()789 void bar()
790 {
791 for (int i = 0; i < 5; ++i) {
792 std::cout << "Thread 3 executing\n";
793 ++n;
794 std::this_thread::sleep_for(std::chrono::milliseconds(10));
795 }
796 }
797 int n = 0;
798 };
799
800 class baz {
801 public:
operator ()()802 void operator()()
803 {
804 for (int i = 0; i < 5; ++i) {
805 std::cout << "Thread 4 executing\n";
806 ++n;
807 std::this_thread::sleep_for(std::chrono::milliseconds(10));
808 }
809 }
810 int n = 0;
811 };
812
813 HWTEST_F(SyncTest, thread2, TestSize.Level1)
814 {
815 {
816 int n = 0;
817 foo f;
818 baz b;
819 {
820 std::thread t2(f1, n + 1);
821 t2.detach(); // test detach
822 }
823 std::thread t1; // t1 is not a thread
824 std::thread t2(f1, n + 1); // pass by value
825 std::thread t3(f2, std::ref(n)); // pass by reference
826 std::thread t4(std::move(t3)); // t4 is now running f2(). t3 is no longer a thread
827 std::thread t5(&foo::bar, &f); // t5 runs foo::bar() on object f
828 std::thread t6(b); // t6 runs baz::operator() on a copy of object b
829 EXPECT_EQ(t1.joinable(), false);
830 EXPECT_EQ(t2.joinable(), true);
831 t2.join();
832 EXPECT_EQ(t2.joinable(), false);
833 t4.join();
834 t5.join();
835 t6.join();
836 EXPECT_EQ(n, 5);
837 EXPECT_EQ(f.n, 5);
838 EXPECT_EQ(b.n, 0);
839 }
840 FFRT_LOGW("ffrt version");
841 {
842 int n = 0;
843 foo f;
844 baz b;
845 {
846 ffrt::thread t2(f1, n + 1);
847 t2.detach(); // test detach
848 }
849 ffrt::thread t1; // t1 is not a thread
850 ffrt::thread t2(f1, n + 1); // pass by value
851 ffrt::thread t3(f2, std::ref(n)); // pass by reference
852 ffrt::thread t4(std::move(t3)); // t4 is now running f2(). t3 is no longer a thread
853 ffrt::thread t5(&foo::bar, &f); // t5 runs foo::bar() on object f
854 ffrt::thread t6(b); // t6 runs baz::operator() on a copy of object b
855 EXPECT_EQ(t1.joinable(), false);
856 EXPECT_EQ(t2.joinable(), true);
857 t2.join();
858 EXPECT_EQ(t2.joinable(), false);
859 EXPECT_EQ(t3.joinable(), false);
860 EXPECT_EQ(t4.joinable(), true);
861 t4.join();
862 EXPECT_EQ(t4.joinable(), false);
863 t5.join();
864 t6.join();
865 EXPECT_EQ(n, 5);
866 EXPECT_EQ(f.n, 5);
867 EXPECT_EQ(b.n, 0);
868 }
869 }
870
871 HWTEST_F(SyncTest, thread_with_qos, TestSize.Level1)
872 {
873 int a = 0;
__anonc91b23f77802null874 auto task = [&] {
875 a++;
876 };
877 ffrt::thread(static_cast<int>(ffrt::qos_user_initiated), task).join();
878 EXPECT_EQ(1, a);
879 }
880
881 HWTEST_F(SyncTest, thread_with_name, TestSize.Level1)
882 {
883 int a = 0;
__anonc91b23f77902null884 auto task = [&] {
885 a++;
886 };
887 std::string name = "thread_test";
888 ffrt::thread(name.c_str(), static_cast<int>(ffrt::qos_user_initiated), task).join();
889 EXPECT_EQ(1, a);
890 }
891
892 struct F {
893 template<typename T, typename U>
operator ()F894 void operator()(T, U, int& a)
895 {
896 using std::is_same;
897 using std::reference_wrapper;
898 static_assert(is_same<T, reference_wrapper<int>>::value, "");
899 static_assert(is_same<U, reference_wrapper<const int>>::value, "");
900 a++;
901 }
902 };
903
904 HWTEST_F(SyncTest, thread_with_ref_check, TestSize.Level1)
905 {
906 int a = 0;
907 ffrt::thread t(F{}, std::ref(a), std::cref(a), std::ref(a));
908 t.join();
909 EXPECT_EQ(1, a);
910 }
911
912 struct A {
913 A() = default;
914 explicit A(const A&) = default;
915 };
916
func(const A &)917 void func(const A&) { }
918
919 HWTEST_F(SyncTest, thread_with_ref, TestSize.Level1)
920 {
921 ffrt::thread t(func, A{});
922 t.join();
923 }
924
925 HWTEST_F(SyncTest, future_wait, TestSize.Level1)
926 {
__anonc91b23f77a02null927 ffrt::packaged_task<int()> task([] { return 7; });
928 ffrt::future<int> f1 = task.get_future();
929 ffrt::thread t(std::move(task));
930
__anonc91b23f77b02null931 ffrt::future<int> f2 = ffrt::async([] { return 8; });
932
933 ffrt::promise<int> p;
934 ffrt::future<int> f3 = p.get_future();
__anonc91b23f77c02null935 ffrt::thread([&p] { p.set_value(9); }).detach();
936
937 std::cout << "Waiting..." << std::flush;
938 f1.wait();
939 f2.wait();
940 f3.wait();
941 std::cout << "Done!\nResults are: "
942 << f1.get() << ' ' << f2.get() << ' ' << f3.get() << '\n';
943 t.join();
944 }
945