1 //===----------------------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // UNSUPPORTED: no-threads 10 // UNSUPPORTED: c++03, c++11, c++14, c++17 11 // XFAIL: availability-synchronization_library-missing 12 13 // void join(); 14 15 #include <atomic> 16 #include <cassert> 17 #include <chrono> 18 #include <concepts> 19 #include <functional> 20 #include <system_error> 21 #include <thread> 22 #include <type_traits> 23 #include <vector> 24 25 #include "make_test_thread.h" 26 #include "test_macros.h" 27 28 int main(int, char**) { 29 // Effects: Blocks until the thread represented by *this has completed. 30 { 31 std::atomic_int calledTimes = 0; 32 std::vector<std::jthread> jts; 33 constexpr auto numberOfThreads = 10u; 34 jts.reserve(numberOfThreads); 35 for (auto i = 0u; i < numberOfThreads; ++i) { 36 jts.emplace_back(support::make_test_jthread([&] { 37 std::this_thread::sleep_for(std::chrono::milliseconds(2)); 38 calledTimes.fetch_add(1, std::memory_order_relaxed); 39 })); 40 } 41 42 for (auto i = 0u; i < numberOfThreads; ++i) { 43 jts[i].join(); 44 } 45 46 // If join did block, calledTimes must equal to numberOfThreads 47 // If join did not block, there is a chance that the check below happened 48 // before test threads incrementing the counter, thus calledTimed would 49 // be less than numberOfThreads. 50 // This is not going to catch issues 100%. Creating more threads to increase 51 // the probability of catching the issue 52 assert(calledTimes.load(std::memory_order_relaxed) == numberOfThreads); 53 } 54 55 // Synchronization: The completion of the thread represented by *this synchronizes with 56 // ([intro.multithread]) the corresponding successful join() return. 57 { 58 bool flag = false; 59 std::jthread jt = support::make_test_jthread([&] { flag = true; }); 60 jt.join(); 61 assert(flag); // non atomic write is visible to the current thread 62 } 63 64 // Postconditions: The thread represented by *this has completed. get_id() == id(). 65 { 66 std::jthread jt = support::make_test_jthread([] {}); 67 assert(jt.get_id() != std::jthread::id()); 68 jt.join(); 69 assert(jt.get_id() == std::jthread::id()); 70 } 71 72 #if !defined(TEST_HAS_NO_EXCEPTIONS) 73 // Throws: system_error when an exception is required ([thread.req.exception]). 74 // invalid_argument - if the thread is not joinable. 75 { 76 std::jthread jt; 77 try { 78 jt.join(); 79 assert(false); 80 } catch (const std::system_error& err) { 81 assert(err.code() == std::errc::invalid_argument); 82 } 83 } 84 85 #endif 86 87 return 0; 88 } 89