-
Notifications
You must be signed in to change notification settings - Fork 11.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[libc++] Make std::lock_guard
available with _LIBCPP_HAS_NO_THREADS
#98717
Conversation
This change makes std::lock_guard, std::unique_lock, std::scoped_lock, and std::shared_lock available when _LIBCPP_HAS_NO_THREADS is set. These classes are generic and don't require threading support, and are regularly used even in environments where threading isn't available like embedded. fixes llvm#89891
@llvm/pr-subscribers-libcxx Author: Petr Hosek (petrhosek) ChangesThis change makes std::lock_guard, std::unique_lock, std::scoped_lock, and std::shared_lock available when _LIBCPP_HAS_NO_THREADS is set. These classes are generic and don't require threading support, and are regularly used even in environments where threading isn't available like embedded. fixes #89891 Full diff: https://github.com/llvm/llvm-project/pull/98717.diff 4 Files Affected:
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/unique_lock.h b/libcxx/include/__mutex/unique_lock.h
index 4a616ba51ee1c..5df791de4c742 100644
--- a/libcxx/include/__mutex/unique_lock.h
+++ b/libcxx/include/__mutex/unique_lock.h
@@ -22,8 +22,6 @@
# pragma GCC system_header
#endif
-#ifndef _LIBCPP_HAS_NO_THREADS
-
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _Mutex>
@@ -172,6 +170,4 @@ inline _LIBCPP_HIDE_FROM_ABI void swap(unique_lock<_Mutex>& __x, unique_lock<_Mu
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_HAS_NO_THREADS
-
#endif // _LIBCPP___MUTEX_UNIQUE_LOCK_H
diff --git a/libcxx/include/mutex b/libcxx/include/mutex
index 02c52dd72f02b..d4d7539240094 100644
--- a/libcxx/include/mutex
+++ b/libcxx/include/mutex
@@ -419,8 +419,9 @@ inline _LIBCPP_HIDE_FROM_ABI void lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&...
}
# endif // _LIBCPP_CXX03_LANG
+#endif // !_LIBCPP_HAS_NO_THREADS
-# if _LIBCPP_STD_VER >= 17
+#if _LIBCPP_STD_VER >= 17
template <class... _Mutexes>
class _LIBCPP_TEMPLATE_VIS scoped_lock;
@@ -491,8 +492,7 @@ private:
};
_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(scoped_lock);
-# endif // _LIBCPP_STD_VER >= 17
-#endif // !_LIBCPP_HAS_NO_THREADS
+#endif // _LIBCPP_STD_VER >= 17
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/shared_mutex b/libcxx/include/shared_mutex
index 397ac290d9b2e..5918af4a214c1 100644
--- a/libcxx/include/shared_mutex
+++ b/libcxx/include/shared_mutex
@@ -122,16 +122,11 @@ template <class Mutex>
*/
-#include <__config>
-
-#ifdef _LIBCPP_HAS_NO_THREADS
-# error "<shared_mutex> is not supported since libc++ has been configured without support for threads."
-#endif
-
#include <__chrono/duration.h>
#include <__chrono/steady_clock.h>
#include <__chrono/time_point.h>
#include <__condition_variable/condition_variable.h>
+#include <__config>
#include <__memory/addressof.h>
#include <__mutex/mutex.h>
#include <__mutex/tag_types.h>
@@ -152,6 +147,8 @@ _LIBCPP_PUSH_MACROS
_LIBCPP_BEGIN_NAMESPACE_STD
+# ifndef _LIBCPP_HAS_NO_THREADS
+
struct _LIBCPP_EXPORTED_FROM_ABI __shared_mutex_base {
mutex __mut_;
condition_variable __gate1_;
@@ -181,7 +178,7 @@ struct _LIBCPP_EXPORTED_FROM_ABI __shared_mutex_base {
// native_handle_type native_handle(); // See 30.2.3
};
-# if _LIBCPP_STD_VER >= 17
+# if _LIBCPP_STD_VER >= 17
class _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_THREAD_SAFETY_ANNOTATION(__capability__("shared_mutex")) shared_mutex {
__shared_mutex_base __base_;
@@ -218,7 +215,7 @@ public:
// typedef __shared_mutex_base::native_handle_type native_handle_type;
// _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() { return __base::unlock_shared(); }
};
-# endif
+# endif
class _LIBCPP_EXPORTED_FROM_ABI
_LIBCPP_THREAD_SAFETY_ANNOTATION(__capability__("shared_timed_mutex")) shared_timed_mutex {
@@ -308,6 +305,8 @@ bool shared_timed_mutex::try_lock_shared_until(const chrono::time_point<_Clock,
return true;
}
+# endif // !_LIBCPP_HAS_NO_THREADS
+
template <class _Mutex>
class shared_lock {
public:
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There should be at least some test that this works with threading disabled. I don't know whether we have any tests currently that could now be enabled. If not, let's add at least a simple one for all the classes.
There are several tests that should now pass even with threading disabled, I removed |
std::lock_guard
available with _LIBCPP_HAS_NO_THREADS
After doing more testing, I decide to exclude |
@@ -6,6 +6,8 @@ | |||
// | |||
//===----------------------------------------------------------------------===// | |||
|
|||
// UNSUPPORTED: no-threads |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can lift this UNSUPPORTED
by defining our own mutex-like class. Also, while we're at it this test should be a .compile.pass.cpp
and it should test static_assert(!std::is_copy_assignable<std::lock_guard<MyMutexType>>::value, "");
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
@@ -6,6 +6,8 @@ | |||
// | |||
//===----------------------------------------------------------------------===// | |||
|
|||
// UNSUPPORTED: no-threads |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar comment here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
@@ -18,31 +18,44 @@ | |||
// -> lock_guard<_Mutex>; // C++17 | |||
|
|||
#include <mutex> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would suggest that we formulate the tests in terms of the TestMutex
only, that way they would all become enabled when threading is disabled.
And then we can have a single test (probably in this test file) where we test basic interoperation between std::lock_guard
and std::mutex
, and that one would be the only one with UNSUPPORTED: no-threads
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few more comments but this LGTM once they are applied.
int main(int, char**) { | ||
static_assert(!std::is_copy_assignable<std::lock_guard<MyMutex> >::value, ""); | ||
return 0; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
int main(int, char**) { | |
static_assert(!std::is_copy_assignable<std::lock_guard<MyMutex> >::value, ""); | |
return 0; | |
} | |
static_assert(!std::is_copy_assignable<std::lock_guard<MyMutex> >::value, ""); |
Just as a matter of style, we don't use main
function in these compile-only tests when they are not needed to avoid any confusion about the test running.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
|
||
int main(int, char**) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
@@ -16,10 +14,12 @@ | |||
|
|||
#include <mutex> | |||
|
|||
struct MyMutex {}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you need to use a valid BasicLockable
all the time, otherwise the code is ill-formed. I suggest you define MyMutex
in a local header like types.h
and include it from all the tests in this directory that use MyMutex
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
std::mutex>::value), ""); | ||
struct MyMutex {}; | ||
|
||
int main(int, char**) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No main
needed, and this can be a .compile.pass.cpp
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
@@ -6,8 +6,6 @@ | |||
// |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe rename to ctor.mutex.pass.cpp
and test the constructor as a whole instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
std::mutex m; | ||
std::lock_guard<std::mutex> lg = m; // expected-error{{no viable conversion}} | ||
MyMutex m; | ||
std::lock_guard<MyMutex> lg = m; // expected-error{{no viable conversion}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead, we should do something like
std::lock_guard<MyMutex> lg(m); // make sure this compiles and runs
static_assert(!std::is_convertible_v<MyMutex, std::lock_guard<MyMutex>>, "constructor must be explicit");
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
Thanks, I believe it should be all addressed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM if CI is green.
libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/ctor.adopt_lock.pass.cpp
Show resolved
Hide resolved
…S` (llvm#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 llvm#89891 --------- Co-authored-by: Louis Dionne <[email protected]>
…S` (#98717) Summary: 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 <[email protected]> Test Plan: Reviewers: Subscribers: Tasks: Tags: Differential Revision: https://phabricator.intern.facebook.com/D60251575
…99562) This is a follow up to #98717, which made lock_guard available under _LIBCPP_HAS_NO_THREADS. We can make unique_lock available under similar circumstances. This patch follows the example in #98717, by: - Removing the preprocessor guards for _LIBCPP_HAS_NO_THREADS in the unique_lock header. - providing a set of custom mutex implementations in a local header. - using custom locks in tests that can be made to work under `no-threads`.
…lvm#99562) This is a follow up to llvm#98717, which made lock_guard available under _LIBCPP_HAS_NO_THREADS. We can make unique_lock available under similar circumstances. This patch follows the example in llvm#98717, by: - Removing the preprocessor guards for _LIBCPP_HAS_NO_THREADS in the unique_lock header. - providing a set of custom mutex implementations in a local header. - using custom locks in tests that can be made to work under `no-threads`.
…lvm#99562) This is a follow up to llvm#98717, which made lock_guard available under _LIBCPP_HAS_NO_THREADS. We can make unique_lock available under similar circumstances. This patch follows the example in llvm#98717, by: - Removing the preprocessor guards for _LIBCPP_HAS_NO_THREADS in the unique_lock header. - providing a set of custom mutex implementations in a local header. - using custom locks in tests that can be made to work under `no-threads`.
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