xref: /llvm-project/libcxx/test/std/thread/thread.jthread/dtor.pass.cpp (revision 121ed5c1985356436d0040dbe81bca26992b1fae)
1695138caSHui //===----------------------------------------------------------------------===//
2695138caSHui //
3695138caSHui // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4695138caSHui // See https://llvm.org/LICENSE.txt for license information.
5695138caSHui // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6695138caSHui //
7695138caSHui //===----------------------------------------------------------------------===//
8695138caSHui //
9695138caSHui // UNSUPPORTED: no-threads
10695138caSHui // UNSUPPORTED: c++03, c++11, c++14, c++17
11695138caSHui // XFAIL: availability-synchronization_library-missing
12695138caSHui 
13695138caSHui // ~jthread();
14695138caSHui 
15695138caSHui #include <atomic>
16695138caSHui #include <cassert>
17695138caSHui #include <optional>
18695138caSHui #include <stop_token>
19695138caSHui #include <thread>
20695138caSHui #include <type_traits>
21695138caSHui #include <vector>
22*475e1543SLouis Dionne 
23*475e1543SLouis Dionne #include "make_test_thread.h"
24695138caSHui #include "test_macros.h"
25695138caSHui 
26695138caSHui int main(int, char**) {
27695138caSHui   // !joinable()
28695138caSHui   {
29695138caSHui     std::jthread jt;
30695138caSHui     assert(!jt.joinable());
31695138caSHui   }
32695138caSHui 
33695138caSHui   // If joinable() is true, calls request_stop() and then join().
34695138caSHui   // request_stop is called
35695138caSHui   {
36*475e1543SLouis Dionne     std::optional<std::jthread> jt = support::make_test_jthread([] {});
37695138caSHui     bool called                    = false;
38695138caSHui     std::stop_callback cb(jt->get_stop_token(), [&called] { called = true; });
39695138caSHui     jt.reset();
40695138caSHui     assert(called);
41695138caSHui   }
42695138caSHui 
43695138caSHui   // If joinable() is true, calls request_stop() and then join().
44695138caSHui   // join is called
45695138caSHui   {
46695138caSHui     std::atomic_int calledTimes = 0;
47695138caSHui     std::vector<std::jthread> jts;
48695138caSHui 
49695138caSHui     constexpr auto numberOfThreads = 10u;
50695138caSHui     jts.reserve(numberOfThreads);
51695138caSHui     for (auto i = 0u; i < numberOfThreads; ++i) {
52*475e1543SLouis Dionne       jts.emplace_back(support::make_test_jthread([&calledTimes] {
53695138caSHui         std::this_thread::sleep_for(std::chrono::milliseconds{2});
54695138caSHui         calledTimes.fetch_add(1, std::memory_order_relaxed);
55*475e1543SLouis Dionne       }));
56695138caSHui     }
57695138caSHui     jts.clear();
58695138caSHui 
59695138caSHui     // If join was called as expected, calledTimes must equal to numberOfThreads
60695138caSHui     // If join was not called, there is a chance that the check below happened
61695138caSHui     // before test threads incrementing the counter, thus calledTimed would
62695138caSHui     // be less than numberOfThreads.
63695138caSHui     // This is not going to catch issues 100%. Creating more threads would increase
64695138caSHui     // the probability of catching the issue
65695138caSHui     assert(calledTimes.load(std::memory_order_relaxed) == numberOfThreads);
66695138caSHui   }
67695138caSHui 
68695138caSHui   return 0;
69695138caSHui }
70