[libcxx-commits] [libcxx] 6192f45 - [libc++] Make `std::lock_guard` available with `_LIBCPP_HAS_NO_THREADS` (#98717)

via libcxx-commits libcxx-commits at lists.llvm.org
Tue Jul 16 21:58:17 PDT 2024


Author: Petr Hosek
Date: 2024-07-16T21:58:13-07:00
New Revision: 6192f458f4fd2ca4e6f01515547034f89325e73c

URL: https://github.com/llvm/llvm-project/commit/6192f458f4fd2ca4e6f01515547034f89325e73c
DIFF: https://github.com/llvm/llvm-project/commit/6192f458f4fd2ca4e6f01515547034f89325e73c.diff

LOG: [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 <ldionne.2 at gmail.com>

Added: 
    libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/assign.compile.pass.cpp
    libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/copy.compile.pass.cpp
    libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/ctor.adopt_lock.pass.cpp
    libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/ctor.mutex.pass.cpp
    libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/std.mutex.pass.cpp
    libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/types.compile.pass.cpp
    libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/types.h

Modified: 
    libcxx/include/__mutex/lock_guard.h
    libcxx/include/__mutex/tag_types.h
    libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/implicit_ctad.pass.cpp

Removed: 
    libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/adopt_lock.pass.cpp
    libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/assign.compile.fail.cpp
    libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/copy.compile.fail.cpp
    libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/mutex.pass.cpp
    libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/mutex.verify.cpp
    libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/types.pass.cpp


################################################################################
diff  --git a/libcxx/include/__mutex/lock_guard.h b/libcxx/include/__mutex/lock_guard.h
index 8340b9bbd4453..ef56896be9f68 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 <class _Mutex>
@@ -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 05ccb8b23a6f4..2b2dd58ee4e80 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 2d0f438ed0391..abd37ea0d55dd 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 <mutex>
 
-int main(int, char**)
-{
-    std::mutex m0;
-    std::mutex m1;
-    std::lock_guard<std::mutex> lg0(m0);
-    std::lock_guard<std::mutex> lg(m1);
-    lg = lg0;
+#include "types.h"
 
-  return 0;
-}
+static_assert(!std::is_copy_assignable<std::lock_guard<MyMutex> >::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 e99517e47e8c6..2a5973726ff1d 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 <mutex>
 
-int main(int, char**)
-{
-    std::mutex m;
-    std::lock_guard<std::mutex> lg0(m);
-    std::lock_guard<std::mutex> lg(lg0);
+#include "types.h"
 
-  return 0;
-}
+static_assert(!std::is_copy_constructible<std::lock_guard<MyMutex> >::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 4d11674f1e83c..d674b9a93fc64 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
 
 // <mutex>
@@ -16,28 +15,18 @@
 // lock_guard(mutex_type& m, adopt_lock_t);
 
 #include <mutex>
-#include <cstdlib>
 #include <cassert>
 
-#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<std::mutex> lg(m, std::adopt_lock);
-    std::thread t = support::make_test_thread(do_try_lock);
-    t.join();
+    std::lock_guard<MyMutex> 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 82f672891c452..9fcffd2f9957d 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
-
 // <mutex>
 
 // template <class Mutex> class lock_guard;
 
 // explicit lock_guard(mutex_type& m);
 
+#include <cassert>
 #include <mutex>
+#include <type_traits>
+
+#include "types.h"
+
+int main(int, char**) {
+  MyMutex m;
+  assert(!m.locked);
+  std::lock_guard<MyMutex> lg(m);
+  assert(m.locked);
 
-int main(int, char**)
-{
-    std::mutex m;
-    std::lock_guard<std::mutex> lg = m; // expected-error{{no viable conversion}}
+  static_assert(!std::is_convertible<MyMutex, std::lock_guard<MyMutex> >::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 9319ec0dba04e..cd5e6692731fe 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
 
 // <mutex>
 
-// lock_guard
+// template <class Mutex> class lock_guard;
 
 // Make sure that the implicitly-generated CTAD works.
 
 #include <mutex>
 
 #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::mutex>);
+    std::lock_guard lg(m);
+    ASSERT_SAME_TYPE(decltype(lg), std::lock_guard<MyMutex>);
   }
 
   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 6025b0c3b465b..0000000000000
--- 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
-
-// <mutex>
-
-// template <class Mutex> class lock_guard;
-
-// explicit lock_guard(mutex_type& m);
-
-// template<class _Mutex> lock_guard(lock_guard<_Mutex>)
-//     -> lock_guard<_Mutex>;  // C++17
-
-#include <mutex>
-#include <cstdlib>
-#include <cassert>
-
-#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<std::mutex> 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<decltype(lg), std::lock_guard<decltype(m)>>::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 0000000000000..5453db49d4e34
--- /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 <cassert>
+#include <mutex>
+#include <type_traits>
+#include <functional>
+
+#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<std::mutex> 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<decltype(lg), std::lock_guard<std::mutex>>::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 8b10d9dab8f2a..015dbfe3c46ae 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
 
 // <mutex>
 
@@ -21,12 +19,6 @@
 #include <mutex>
 #include <type_traits>
 
-#include "test_macros.h"
-
-int main(int, char**)
-{
-    static_assert((std::is_same<std::lock_guard<std::mutex>::mutex_type,
-                   std::mutex>::value), "");
+#include "types.h"
 
-  return 0;
-}
+static_assert(std::is_same<std::lock_guard<MyMutex>::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 0000000000000..5aeed21547880
--- /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 <cassert>
+
+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


        


More information about the libcxx-commits mailing list