Files
TheRock/rocm-libraries/projects/hipthreads/test/std/thread/thread.jthread/cons.func.token.pass.cpp
T
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

161 lines
5.3 KiB
C++

//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// UNSUPPORTED: no-threads
// UNSUPPORTED: c++03, c++11, c++14, c++17
// XFAIL: availability-synchronization_library-missing
// template<class F, class... Args>
// explicit jthread(F&& f, Args&&... args);
#include <cassert>
#include <stop_token>
#include <hip/thread>
#include <type_traits>
#include <utility>
#include "test_macros.h"
template <class... Args>
struct Func {
void operator()(Args...) const;
};
// Constraints: remove_cvref_t<F> is not the same type as jthread.
static_assert(::std::is_constructible_v<::std::jthread, Func<>>);
static_assert(::std::is_constructible_v<::std::jthread, Func<int>, int>);
static_assert(!::std::is_constructible_v<::std::jthread, ::std::jthread const&>);
// explicit
template <class T>
void conversion_test(T);
template <class T, class... Args>
concept ImplicitlyConstructible = requires(Args&&... args) { conversion_test<T>({::std::forward<Args>(args)...}); };
static_assert(!ImplicitlyConstructible<::std::jthread, Func<>>);
static_assert(!ImplicitlyConstructible<::std::jthread, Func<int>, int>);
int main(int, char**) {
// Effects: Initializes ssource
// Postconditions: get_id() != id() is true and ssource.stop_possible() is true
// and *this represents the newly started thread.
{
::std::jthread jt{[] {}};
assert(jt.get_stop_source().stop_possible());
assert(jt.get_id() != ::std::jthread::id());
}
// The new thread of execution executes
// invoke(auto(::std::forward<F>(f)), get_stop_token(), auto(::std::forward<Args>(args))...)
// if that expression is well-formed,
{
int result = 0;
::std::jthread jt{[&result](::std::stop_token st, int i) {
assert(st.stop_possible());
assert(!st.stop_requested());
result += i;
},
5};
jt.join();
assert(result == 5);
}
// otherwise
// invoke(auto(::std::forward<F>(f)), auto(::std::forward<Args>(args))...)
{
int result = 0;
::std::jthread jt{[&result](int i) { result += i; }, 5};
jt.join();
assert(result == 5);
}
// with the values produced by auto being materialized ([conv.rval]) in the constructing thread.
{
struct TrackThread {
::std::jthread::id threadId;
bool copyConstructed = false;
bool moveConstructed = false;
TrackThread() : threadId(hip::this_thread::get_id()) {}
TrackThread(const TrackThread&) : threadId(hip::this_thread::get_id()), copyConstructed(true) {}
TrackThread(TrackThread&&) : threadId(hip::this_thread::get_id()), moveConstructed(true) {}
};
auto mainThread = hip::this_thread::get_id();
TrackThread arg1;
::std::jthread jt1{[mainThread](const TrackThread& arg) {
assert(arg.threadId == mainThread);
assert(arg.threadId != hip::this_thread::get_id());
assert(arg.copyConstructed);
},
arg1};
TrackThread arg2;
::std::jthread jt2{[mainThread](const TrackThread& arg) {
assert(arg.threadId == mainThread);
assert(arg.threadId != hip::this_thread::get_id());
assert(arg.moveConstructed);
},
::std::move(arg2)};
}
#if !defined(TEST_HAS_NO_EXCEPTIONS)
// [Note 1: This implies that any exceptions not thrown from the invocation of the copy
// of f will be thrown in the constructing thread, not the new thread. - end note]
{
struct Exception {
::std::jthread::id threadId;
};
struct ThrowOnCopyFunc {
ThrowOnCopyFunc() = default;
ThrowOnCopyFunc(const ThrowOnCopyFunc&) { throw Exception{hip::this_thread::get_id()}; }
void operator()() const {}
};
ThrowOnCopyFunc f1;
try {
::std::jthread jt{f1};
assert(false);
} catch (const Exception& e) {
assert(e.threadId == hip::this_thread::get_id());
}
}
#endif // !defined(TEST_HAS_NO_EXCEPTIONS)
// Synchronization: The completion of the invocation of the constructor
// synchronizes with the beginning of the invocation of the copy of f.
{
int flag = 0;
struct Arg {
int& flag_;
Arg(int& f) : flag_(f) {}
Arg(const Arg& other) : flag_(other.flag_) { flag_ = 5; }
};
Arg arg(flag);
::std::jthread jt(
[&flag](const auto&) {
assert(flag == 5); // happens-after the copy-construction of arg
},
arg);
}
// Per https://eel.is/c++draft/thread.jthread.class#thread.jthread.cons-8:
//
// Throws: system_error if unable to start the new thread.
// Error conditions:
// resource_unavailable_try_again - the system lacked the necessary resources to create another thread,
// or the system-imposed limit on the number of threads in a process would be exceeded.
//
// Unfortunately, this is extremely hard to test portably so we don't have a test for this error condition right now.
return 0;
}