diff --git a/libcxx/include/__mutex/unique_lock.h b/libcxx/include/__mutex/unique_lock.h index aea93eb9b8c9b..1dc7f94612eca 100644 --- a/libcxx/include/__mutex/unique_lock.h +++ b/libcxx/include/__mutex/unique_lock.h @@ -15,6 +15,7 @@ #include <__memory/addressof.h> #include <__mutex/tag_types.h> #include <__system_error/throw_system_error.h> +#include <__utility/move.h> #include <__utility/swap.h> #include @@ -22,6 +23,8 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> _LIBCPP_BEGIN_NAMESPACE_STD template @@ -74,13 +77,7 @@ class unique_lock { } _LIBCPP_HIDE_FROM_ABI unique_lock& operator=(unique_lock&& __u) _NOEXCEPT { - if (__owns_) - __m_->unlock(); - - __m_ = __u.__m_; - __owns_ = __u.__owns_; - __u.__m_ = nullptr; - __u.__owns_ = false; + unique_lock{std::move(__u)}.swap(*this); return *this; } @@ -169,5 +166,6 @@ inline _LIBCPP_HIDE_FROM_ABI void swap(unique_lock<_Mutex>& __x, unique_lock<_Mu } _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS #endif // _LIBCPP___MUTEX_UNIQUE_LOCK_H diff --git a/libcxx/include/shared_mutex b/libcxx/include/shared_mutex index 8c02e348e4de7..6841a6d7d1887 100644 --- a/libcxx/include/shared_mutex +++ b/libcxx/include/shared_mutex @@ -138,6 +138,7 @@ template # include <__mutex/tag_types.h> # include <__mutex/unique_lock.h> # include <__system_error/throw_system_error.h> +# include <__utility/move.h> # include <__utility/swap.h> # include # include @@ -340,14 +341,7 @@ public: } _LIBCPP_HIDE_FROM_ABI shared_lock& operator=(shared_lock&& __u) _NOEXCEPT { - if (__owns_) - __m_->unlock_shared(); - __m_ = nullptr; - __owns_ = false; - __m_ = __u.__m_; - __owns_ = __u.__owns_; - __u.__m_ = nullptr; - __u.__owns_ = false; + shared_lock{std::move(__u)}.swap(*this); return *this; } diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/move_assign.pass.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/move_assign.pass.cpp index 6d7838e8c6c95..b0647f06e4c43 100644 --- a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/move_assign.pass.cpp +++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/move_assign.pass.cpp @@ -21,22 +21,31 @@ #include "test_macros.h" - -int main(int, char**) -{ - { +int main(int, char**) { + { typedef std::shared_timed_mutex M; M m0; M m1; std::shared_lock lk0(m0); std::shared_lock lk1(m1); + + // Test self move assignment for lk0. + lk0 = std::move(lk0); + assert(lk0.mutex() == std::addressof(m0)); + assert(lk0.owns_lock() == true); + lk1 = std::move(lk0); assert(lk1.mutex() == std::addressof(m0)); assert(lk1.owns_lock() == true); assert(lk0.mutex() == nullptr); assert(lk0.owns_lock() == false); - } - { + + // Test self move assignment for lk1. + lk1 = std::move(lk1); + assert(lk1.mutex() == std::addressof(m0)); + assert(lk1.owns_lock() == true); + } + { typedef nasty_mutex M; M m0; M m1; @@ -47,7 +56,7 @@ int main(int, char**) assert(lk1.owns_lock() == true); assert(lk0.mutex() == nullptr); assert(lk0.owns_lock() == false); - } + } return 0; } diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/move_assign.pass.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/move_assign.pass.cpp index 588d8332c4164..5b25cb6d5940d 100644 --- a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/move_assign.pass.cpp +++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/move_assign.pass.cpp @@ -24,13 +24,22 @@ int main(int, char**) { std::unique_lock lk0(m0); std::unique_lock lk1(m1); + // Test self move assignment for lk0. + lk0 = std::move(lk0); + assert(lk0.mutex() == std::addressof(m0)); + assert(lk0.owns_lock() == true); + auto& result = (lk1 = std::move(lk0)); assert(&result == &lk1); assert(lk1.mutex() == std::addressof(m0)); assert(lk1.owns_lock()); assert(lk0.mutex() == nullptr); - assert(!lk0.owns_lock()); + assert(lk0.owns_lock() == false); + // Test self move assignment for lk1 + lk1 = std::move(lk1); + assert(lk1.mutex() == std::addressof(m0)); + assert(lk1.owns_lock() == true); return 0; }