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 12*64addd65SStephan T. Lavavej // ADDITIONAL_COMPILE_FLAGS(gcc-style-warnings): -Wno-self-move 13695138caSHui 14695138caSHui // jthread& operator=(jthread&&) noexcept; 15695138caSHui 16695138caSHui #include <atomic> 17695138caSHui #include <cassert> 18695138caSHui #include <concepts> 19695138caSHui #include <stop_token> 20695138caSHui #include <thread> 21695138caSHui #include <type_traits> 22695138caSHui #include <utility> 23695138caSHui #include <vector> 24695138caSHui 25475e1543SLouis Dionne #include "make_test_thread.h" 26695138caSHui #include "test_macros.h" 27695138caSHui 28695138caSHui static_assert(std::is_nothrow_move_assignable_v<std::jthread>); 29695138caSHui 30695138caSHui int main(int, char**) { 31695138caSHui // If &x == this is true, there are no effects. 32695138caSHui { 33475e1543SLouis Dionne std::jthread j = support::make_test_jthread([] {}); 34695138caSHui auto id = j.get_id(); 35695138caSHui auto ssource = j.get_stop_source(); 36695138caSHui j = std::move(j); 37695138caSHui assert(j.get_id() == id); 38695138caSHui assert(j.get_stop_source() == ssource); 39695138caSHui } 40695138caSHui 41695138caSHui // if joinable() is true, calls request_stop() and then join() 42695138caSHui // request_stop is called 43695138caSHui { 44475e1543SLouis Dionne std::jthread j1 = support::make_test_jthread([] {}); 45695138caSHui bool called = false; 46695138caSHui std::stop_callback cb(j1.get_stop_token(), [&called] { called = true; }); 47695138caSHui 48475e1543SLouis Dionne std::jthread j2 = support::make_test_jthread([] {}); 49695138caSHui j1 = std::move(j2); 50695138caSHui assert(called); 51695138caSHui } 52695138caSHui 53695138caSHui // if joinable() is true, calls request_stop() and then join() 54695138caSHui // join is called 55695138caSHui { 56695138caSHui std::atomic_int calledTimes = 0; 57695138caSHui std::vector<std::jthread> jts; 58695138caSHui constexpr auto numberOfThreads = 10u; 59695138caSHui jts.reserve(numberOfThreads); 60695138caSHui for (auto i = 0u; i < numberOfThreads; ++i) { 61475e1543SLouis Dionne jts.emplace_back(support::make_test_jthread([&] { 62695138caSHui std::this_thread::sleep_for(std::chrono::milliseconds(2)); 63695138caSHui calledTimes.fetch_add(1, std::memory_order_relaxed); 64475e1543SLouis Dionne })); 65695138caSHui } 66695138caSHui 67695138caSHui for (auto i = 0u; i < numberOfThreads; ++i) { 68695138caSHui jts[i] = std::jthread{}; 69695138caSHui } 70695138caSHui 71695138caSHui // If join was called as expected, calledTimes must equal to numberOfThreads 72695138caSHui // If join was not called, there is a chance that the check below happened 73695138caSHui // before test threads incrementing the counter, thus calledTimed would 74695138caSHui // be less than numberOfThreads. 75695138caSHui // This is not going to catch issues 100%. Creating more threads to increase 76695138caSHui // the probability of catching the issue 77695138caSHui assert(calledTimes.load(std::memory_order_relaxed) == numberOfThreads); 78695138caSHui } 79695138caSHui 80695138caSHui // then assigns the state of x to *this 81695138caSHui { 82475e1543SLouis Dionne std::jthread j1 = support::make_test_jthread([] {}); 83475e1543SLouis Dionne std::jthread j2 = support::make_test_jthread([] {}); 84695138caSHui auto id2 = j2.get_id(); 85695138caSHui auto ssource2 = j2.get_stop_source(); 86695138caSHui 87695138caSHui j1 = std::move(j2); 88695138caSHui 89695138caSHui assert(j1.get_id() == id2); 90695138caSHui assert(j1.get_stop_source() == ssource2); 91695138caSHui } 92695138caSHui 93695138caSHui // sets x to a default constructed state 94695138caSHui { 95475e1543SLouis Dionne std::jthread j1 = support::make_test_jthread([] {}); 96475e1543SLouis Dionne std::jthread j2 = support::make_test_jthread([] {}); 97695138caSHui j1 = std::move(j2); 98695138caSHui 99695138caSHui assert(j2.get_id() == std::jthread::id()); 100695138caSHui assert(!j2.get_stop_source().stop_possible()); 101695138caSHui } 102695138caSHui 103695138caSHui // joinable is false 104695138caSHui { 105695138caSHui std::jthread j1; 106475e1543SLouis Dionne std::jthread j2 = support::make_test_jthread([] {}); 107695138caSHui 108695138caSHui auto j2Id = j2.get_id(); 109695138caSHui 110695138caSHui j1 = std::move(j2); 111695138caSHui 112695138caSHui assert(j1.get_id() == j2Id); 113695138caSHui } 114695138caSHui 115695138caSHui return 0; 116695138caSHui } 117