This is the last PR that's needed (for now) to get libc++'s tests working with MSVC's STL. The ADDITIONAL_COMPILE_FLAGS machinery is very useful, but also very problematic for MSVC, as it doesn't understand most of Clang's compiler options. We've been dealing with this by simply marking anything that uses ADDITIONAL_COMPILE_FLAGS as FAIL or SKIPPED, but that creates significant gaps in test coverage. Fortunately, ADDITIONAL_COMPILE_FLAGS also supports "features", which can be slightly enhanced to send Clang-compatible and MSVC-compatible options to the right compilers. This patch adds the gcc-style-warnings and cl-style-warnings Lit features, and uses that to pass the appropriate warning flags to tests. It also uses TEST_MEOW_DIAGNOSTIC_IGNORED for a few local suppressions of MSVC warnings.
118 lines
3.5 KiB
C++
118 lines
3.5 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: libcpp-has-no-experimental-stop_token
|
|
// UNSUPPORTED: c++03, c++11, c++14, c++17
|
|
// XFAIL: availability-synchronization_library-missing
|
|
// ADDITIONAL_COMPILE_FLAGS(gcc-style-warnings): -Wno-self-move
|
|
|
|
// jthread& operator=(jthread&&) noexcept;
|
|
|
|
#include <atomic>
|
|
#include <cassert>
|
|
#include <concepts>
|
|
#include <stop_token>
|
|
#include <thread>
|
|
#include <type_traits>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
#include "make_test_thread.h"
|
|
#include "test_macros.h"
|
|
|
|
static_assert(std::is_nothrow_move_assignable_v<std::jthread>);
|
|
|
|
int main(int, char**) {
|
|
// If &x == this is true, there are no effects.
|
|
{
|
|
std::jthread j = support::make_test_jthread([] {});
|
|
auto id = j.get_id();
|
|
auto ssource = j.get_stop_source();
|
|
j = std::move(j);
|
|
assert(j.get_id() == id);
|
|
assert(j.get_stop_source() == ssource);
|
|
}
|
|
|
|
// if joinable() is true, calls request_stop() and then join()
|
|
// request_stop is called
|
|
{
|
|
std::jthread j1 = support::make_test_jthread([] {});
|
|
bool called = false;
|
|
std::stop_callback cb(j1.get_stop_token(), [&called] { called = true; });
|
|
|
|
std::jthread j2 = support::make_test_jthread([] {});
|
|
j1 = std::move(j2);
|
|
assert(called);
|
|
}
|
|
|
|
// if joinable() is true, calls request_stop() and then join()
|
|
// join is called
|
|
{
|
|
std::atomic_int calledTimes = 0;
|
|
std::vector<std::jthread> jts;
|
|
constexpr auto numberOfThreads = 10u;
|
|
jts.reserve(numberOfThreads);
|
|
for (auto i = 0u; i < numberOfThreads; ++i) {
|
|
jts.emplace_back(support::make_test_jthread([&] {
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(2));
|
|
calledTimes.fetch_add(1, std::memory_order_relaxed);
|
|
}));
|
|
}
|
|
|
|
for (auto i = 0u; i < numberOfThreads; ++i) {
|
|
jts[i] = std::jthread{};
|
|
}
|
|
|
|
// If join was called as expected, calledTimes must equal to numberOfThreads
|
|
// If join was not called, there is a chance that the check below happened
|
|
// before test threads incrementing the counter, thus calledTimed would
|
|
// be less than numberOfThreads.
|
|
// This is not going to catch issues 100%. Creating more threads to increase
|
|
// the probability of catching the issue
|
|
assert(calledTimes.load(std::memory_order_relaxed) == numberOfThreads);
|
|
}
|
|
|
|
// then assigns the state of x to *this
|
|
{
|
|
std::jthread j1 = support::make_test_jthread([] {});
|
|
std::jthread j2 = support::make_test_jthread([] {});
|
|
auto id2 = j2.get_id();
|
|
auto ssource2 = j2.get_stop_source();
|
|
|
|
j1 = std::move(j2);
|
|
|
|
assert(j1.get_id() == id2);
|
|
assert(j1.get_stop_source() == ssource2);
|
|
}
|
|
|
|
// sets x to a default constructed state
|
|
{
|
|
std::jthread j1 = support::make_test_jthread([] {});
|
|
std::jthread j2 = support::make_test_jthread([] {});
|
|
j1 = std::move(j2);
|
|
|
|
assert(j2.get_id() == std::jthread::id());
|
|
assert(!j2.get_stop_source().stop_possible());
|
|
}
|
|
|
|
// joinable is false
|
|
{
|
|
std::jthread j1;
|
|
std::jthread j2 = support::make_test_jthread([] {});
|
|
|
|
auto j2Id = j2.get_id();
|
|
|
|
j1 = std::move(j2);
|
|
|
|
assert(j1.get_id() == j2Id);
|
|
}
|
|
|
|
return 0;
|
|
}
|