From 6192f458f4fd2ca4e6f01515547034f89325e73c Mon Sep 17 00:00:00 2001 From: Petr Hosek Date: Tue, 16 Jul 2024 21:58:13 -0700 Subject: [PATCH] [libc++] Make `std::lock_guard` available with `_LIBCPP_HAS_NO_THREADS` (#98717) This change makes `std::lock_guard` available when `_LIBCPP_HAS_NO_THREADS` is set. This class is generic and doesn't require threading support, and is regularly used even in environments where threading isn't available like embedded. fixes #89891 --------- Co-authored-by: Louis Dionne --- libcxx/include/__mutex/lock_guard.h | 4 -- libcxx/include/__mutex/tag_types.h | 10 ++-- ...mpile.fail.cpp => assign.compile.pass.cpp} | 11 +---- ...compile.fail.cpp => copy.compile.pass.cpp} | 9 +--- ...lock.pass.cpp => ctor.adopt_lock.pass.cpp} | 23 +++------ .../{mutex.verify.cpp => ctor.mutex.pass.cpp} | 17 ++++--- .../thread.lock.guard/implicit_ctad.pass.cpp | 10 ++-- .../thread.lock.guard/mutex.pass.cpp | 49 ------------------- .../thread.lock.guard/std.mutex.pass.cpp | 49 +++++++++++++++++++ ...{types.pass.cpp => types.compile.pass.cpp} | 12 +---- .../thread.lock/thread.lock.guard/types.h | 33 +++++++++++++ 11 files changed, 113 insertions(+), 114 deletions(-) rename libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/{assign.compile.fail.cpp => assign.compile.pass.cpp} (74%) rename libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/{copy.compile.fail.cpp => copy.compile.pass.cpp} (78%) rename libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/{adopt_lock.pass.cpp => ctor.adopt_lock.pass.cpp} (64%) rename libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/{mutex.verify.cpp => ctor.mutex.pass.cpp} (63%) delete mode 100644 libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/mutex.pass.cpp create mode 100644 libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/std.mutex.pass.cpp rename libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/{types.pass.cpp => types.compile.pass.cpp} (71%) create mode 100644 libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/types.h diff --git a/libcxx/include/__mutex/lock_guard.h b/libcxx/include/__mutex/lock_guard.h index 8340b9bbd445..ef56896be9f6 100644 --- a/libcxx/include/__mutex/lock_guard.h +++ b/libcxx/include/__mutex/lock_guard.h @@ -16,8 +16,6 @@ # pragma GCC system_header #endif -#ifndef _LIBCPP_HAS_NO_THREADS - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -47,6 +45,4 @@ _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(lock_guard); _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_HAS_NO_THREADS - #endif // _LIBCPP___MUTEX_LOCK_GUARD_H diff --git a/libcxx/include/__mutex/tag_types.h b/libcxx/include/__mutex/tag_types.h index 05ccb8b23a6f..2b2dd58ee4e8 100644 --- a/libcxx/include/__mutex/tag_types.h +++ b/libcxx/include/__mutex/tag_types.h @@ -15,8 +15,6 @@ # pragma GCC system_header #endif -#ifndef _LIBCPP_HAS_NO_THREADS - _LIBCPP_BEGIN_NAMESPACE_STD struct _LIBCPP_EXPORTED_FROM_ABI defer_lock_t { @@ -31,18 +29,16 @@ struct _LIBCPP_EXPORTED_FROM_ABI adopt_lock_t { explicit adopt_lock_t() = default; }; -# if _LIBCPP_STD_VER >= 17 +#if _LIBCPP_STD_VER >= 17 inline constexpr defer_lock_t defer_lock = defer_lock_t(); inline constexpr try_to_lock_t try_to_lock = try_to_lock_t(); inline constexpr adopt_lock_t adopt_lock = adopt_lock_t(); -# elif !defined(_LIBCPP_CXX03_LANG) +#elif !defined(_LIBCPP_CXX03_LANG) constexpr defer_lock_t defer_lock = defer_lock_t(); constexpr try_to_lock_t try_to_lock = try_to_lock_t(); constexpr adopt_lock_t adopt_lock = adopt_lock_t(); -# endif +#endif _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_HAS_NO_THREADS - #endif // _LIBCPP___MUTEX_TAG_TYPES_H diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/assign.compile.fail.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/assign.compile.pass.cpp similarity index 74% rename from libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/assign.compile.fail.cpp rename to libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/assign.compile.pass.cpp index 2d0f438ed039..abd37ea0d55d 100644 --- a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/assign.compile.fail.cpp +++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/assign.compile.pass.cpp @@ -14,13 +14,6 @@ #include -int main(int, char**) -{ - std::mutex m0; - std::mutex m1; - std::lock_guard lg0(m0); - std::lock_guard lg(m1); - lg = lg0; +#include "types.h" - return 0; -} +static_assert(!std::is_copy_assignable >::value, ""); diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/copy.compile.fail.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/copy.compile.pass.cpp similarity index 78% rename from libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/copy.compile.fail.cpp rename to libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/copy.compile.pass.cpp index e99517e47e8c..2a5973726ff1 100644 --- a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/copy.compile.fail.cpp +++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/copy.compile.pass.cpp @@ -14,11 +14,6 @@ #include -int main(int, char**) -{ - std::mutex m; - std::lock_guard lg0(m); - std::lock_guard lg(lg0); +#include "types.h" - return 0; -} +static_assert(!std::is_copy_constructible >::value, ""); diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/adopt_lock.pass.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/ctor.adopt_lock.pass.cpp similarity index 64% rename from libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/adopt_lock.pass.cpp rename to libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/ctor.adopt_lock.pass.cpp index 4d11674f1e83..d674b9a93fc6 100644 --- a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/adopt_lock.pass.cpp +++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/ctor.adopt_lock.pass.cpp @@ -5,8 +5,7 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// -// -// UNSUPPORTED: no-threads + // UNSUPPORTED: c++03 // @@ -16,28 +15,18 @@ // lock_guard(mutex_type& m, adopt_lock_t); #include -#include #include -#include "make_test_thread.h" -#include "test_macros.h" - -std::mutex m; - -void do_try_lock() { - assert(m.try_lock() == false); -} +#include "types.h" int main(int, char**) { + MyMutex m; { m.lock(); - std::lock_guard lg(m, std::adopt_lock); - std::thread t = support::make_test_thread(do_try_lock); - t.join(); + std::lock_guard lg(m, std::adopt_lock); + assert(m.locked); } - - m.lock(); - m.unlock(); + assert(!m.locked); return 0; } diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/mutex.verify.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/ctor.mutex.pass.cpp similarity index 63% rename from libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/mutex.verify.cpp rename to libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/ctor.mutex.pass.cpp index 82f672891c45..9fcffd2f9957 100644 --- a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/mutex.verify.cpp +++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/ctor.mutex.pass.cpp @@ -6,20 +6,25 @@ // //===----------------------------------------------------------------------===// -// UNSUPPORTED: no-threads - // // template class lock_guard; // explicit lock_guard(mutex_type& m); +#include #include +#include -int main(int, char**) -{ - std::mutex m; - std::lock_guard lg = m; // expected-error{{no viable conversion}} +#include "types.h" + +int main(int, char**) { + MyMutex m; + assert(!m.locked); + std::lock_guard lg(m); + assert(m.locked); + + static_assert(!std::is_convertible >::value, "constructor must be explicit"); return 0; } diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/implicit_ctad.pass.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/implicit_ctad.pass.cpp index 9319ec0dba04..cd5e6692731f 100644 --- a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/implicit_ctad.pass.cpp +++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/implicit_ctad.pass.cpp @@ -6,24 +6,24 @@ // //===----------------------------------------------------------------------===// -// UNSUPPORTED: no-threads // UNSUPPORTED: c++03, c++11, c++14 // -// lock_guard +// template class lock_guard; // Make sure that the implicitly-generated CTAD works. #include #include "test_macros.h" +#include "types.h" int main(int, char**) { - std::mutex mutex; + MyMutex m; { - std::lock_guard lock(mutex); - ASSERT_SAME_TYPE(decltype(lock), std::lock_guard); + std::lock_guard lg(m); + ASSERT_SAME_TYPE(decltype(lg), std::lock_guard); } return 0; diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/mutex.pass.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/mutex.pass.cpp deleted file mode 100644 index 6025b0c3b465..000000000000 --- a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/mutex.pass.cpp +++ /dev/null @@ -1,49 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// 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 - -// - -// template class lock_guard; - -// explicit lock_guard(mutex_type& m); - -// template lock_guard(lock_guard<_Mutex>) -// -> lock_guard<_Mutex>; // C++17 - -#include -#include -#include - -#include "make_test_thread.h" -#include "test_macros.h" - -std::mutex m; - -void do_try_lock() { - assert(m.try_lock() == false); -} - -int main(int, char**) { - { - std::lock_guard lg(m); - std::thread t = support::make_test_thread(do_try_lock); - t.join(); - } - - m.lock(); - m.unlock(); - -#if TEST_STD_VER >= 17 - std::lock_guard lg(m); - static_assert((std::is_same>::value), "" ); -#endif - - return 0; -} diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/std.mutex.pass.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/std.mutex.pass.cpp new file mode 100644 index 000000000000..5453db49d4e3 --- /dev/null +++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/std.mutex.pass.cpp @@ -0,0 +1,49 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// Test the interoperation of std::lock_guard with std::mutex, since that is such +// a common use case. + +#include +#include +#include +#include + +#include "make_test_thread.h" +#include "test_macros.h" + +void do_try_lock(std::mutex& m) { assert(m.try_lock() == false); } + +int main(int, char**) { + { + std::mutex m; + { + std::lock_guard lg(m); + std::thread t = support::make_test_thread(do_try_lock, std::ref(m)); + t.join(); + } + + // This should work because the lock_guard unlocked the mutex when it was destroyed above. + m.lock(); + m.unlock(); + } + + // Test CTAD +#if TEST_STD_VER >= 17 + { + std::mutex m; + std::lock_guard lg(m); + static_assert(std::is_same>::value, ""); + } +#endif + + return 0; +} diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/types.pass.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/types.compile.pass.cpp similarity index 71% rename from libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/types.pass.cpp rename to libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/types.compile.pass.cpp index 8b10d9dab8f2..015dbfe3c46a 100644 --- a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/types.pass.cpp +++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/types.compile.pass.cpp @@ -5,8 +5,6 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// -// -// UNSUPPORTED: no-threads // @@ -21,12 +19,6 @@ #include #include -#include "test_macros.h" +#include "types.h" -int main(int, char**) -{ - static_assert((std::is_same::mutex_type, - std::mutex>::value), ""); - - return 0; -} +static_assert(std::is_same::mutex_type, MyMutex>::value, ""); diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/types.h b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/types.h new file mode 100644 index 000000000000..5aeed2154788 --- /dev/null +++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/types.h @@ -0,0 +1,33 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef TEST_STD_THREAD_THREAD_MUTEX_THREAD_LOCK_THREAD_LOCK_GUARD_TYPES_H +#define TEST_STD_THREAD_THREAD_MUTEX_THREAD_LOCK_THREAD_LOCK_GUARD_TYPES_H + +#include + +struct MyMutex { + bool locked = false; + + MyMutex() = default; + ~MyMutex() { assert(!locked); } + + void lock() { + assert(!locked); + locked = true; + } + void unlock() { + assert(locked); + locked = false; + } + + MyMutex(MyMutex const&) = delete; + MyMutex& operator=(MyMutex const&) = delete; +}; + +#endif // TEST_STD_THREAD_THREAD_MUTEX_THREAD_LOCK_THREAD_LOCK_GUARD_TYPES_H