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&notifyone");
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&notifyone");
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