[libcxx-commits] [libcxx] [libc++] Refactor the std::unique_lock tests (PR #102151)

Nikolas Klauser via libcxx-commits libcxx-commits at lists.llvm.org
Tue Aug 6 07:19:17 PDT 2024


https://github.com/philnik777 created https://github.com/llvm/llvm-project/pull/102151

This makes some of the tests not flaky anymore, updates some tests to also work in C++03 and modernizes them in general.


>From b442c41c4d16d341caec71f2c50ccdcc13222799 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Tue, 6 Aug 2024 16:18:01 +0200
Subject: [PATCH] [libc++] Refactor the std::unique_lock tests

---
 libcxx/include/__bit_reference                |  8 +-
 libcxx/include/__tree                         | 14 +--
 libcxx/include/deque                          |  8 +-
 ...ass.cpp => implicit_ctad.compile.pass.cpp} | 14 +--
 .../copy_assign.compile.pass.cpp              |  4 +-
 .../copy_ctor.compile.pass.cpp                |  4 +-
 .../thread.lock.unique.cons/default.pass.cpp  |  5 +-
 .../move_assign.pass.cpp                      | 39 +++-----
 .../move_ctor.pass.cpp                        | 34 ++-----
 .../thread.lock.unique.cons/mutex.pass.cpp    | 44 ++--------
 .../mutex_adopt_lock.pass.cpp                 | 29 ++----
 .../mutex_defer_lock.pass.cpp                 | 25 ++----
 .../mutex_duration.pass.cpp                   | 79 +++++------------
 .../mutex_time_point.pass.cpp                 | 80 +++++------------
 .../mutex_try_to_lock.pass.cpp                | 72 +++++----------
 .../thread.lock.unique.locking/lock.pass.cpp  | 81 ++++++-----------
 .../try_lock.pass.cpp                         | 41 +++++----
 .../try_lock_for.pass.cpp                     | 43 +++++----
 .../try_lock_until.pass.cpp                   | 39 ++++----
 .../unlock.pass.cpp                           | 26 ++++--
 .../member_swap.pass.cpp                      | 22 ++---
 .../nonmember_swap.pass.cpp                   | 22 ++---
 .../thread.lock.unique.mod/release.pass.cpp   | 31 +++----
 .../thread.lock.unique.obs/mutex.pass.cpp     | 18 ++--
 .../thread.lock.unique.obs/op_bool.pass.cpp   | 22 ++---
 .../thread.lock.unique.obs/owns_lock.pass.cpp | 17 ++--
 .../thread.lock.unique/types.compile.pass.cpp |  5 +-
 .../thread.lock/thread.lock.unique/types.h    | 88 -------------------
 libcxx/test/support/checking_mutex.h          | 80 +++++++++++++++++
 29 files changed, 388 insertions(+), 606 deletions(-)
 rename libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/{implicit_ctad.pass.cpp => implicit_ctad.compile.pass.cpp} (71%)
 delete mode 100644 libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/types.h
 create mode 100644 libcxx/test/support/checking_mutex.h

diff --git a/libcxx/include/__bit_reference b/libcxx/include/__bit_reference
index 22637d4397412..849ca104a80b1 100644
--- a/libcxx/include/__bit_reference
+++ b/libcxx/include/__bit_reference
@@ -802,13 +802,7 @@ private:
   unsigned __ctz_;
 
 public:
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator() _NOEXCEPT
-#if _LIBCPP_STD_VER >= 14
-      : __seg_(nullptr),
-        __ctz_(0)
-#endif
-  {
-  }
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator() _NOEXCEPT : __seg_(nullptr), __ctz_(0) {}
 
   // When _IsConst=false, this is the copy constructor.
   // It is non-trivial. Making it trivial would break ABI.
diff --git a/libcxx/include/__tree b/libcxx/include/__tree
index 1990fa602d39c..e091352c1b636 100644
--- a/libcxx/include/__tree
+++ b/libcxx/include/__tree
@@ -730,12 +730,7 @@ public:
   typedef value_type& reference;
   typedef typename _NodeTypes::__node_value_type_pointer pointer;
 
-  _LIBCPP_HIDE_FROM_ABI __tree_iterator() _NOEXCEPT
-#if _LIBCPP_STD_VER >= 14
-      : __ptr_(nullptr)
-#endif
-  {
-  }
+  _LIBCPP_HIDE_FROM_ABI __tree_iterator() _NOEXCEPT : __ptr_(nullptr) {}
 
   _LIBCPP_HIDE_FROM_ABI reference operator*() const { return __get_np()->__value_; }
   _LIBCPP_HIDE_FROM_ABI pointer operator->() const { return pointer_traits<pointer>::pointer_to(__get_np()->__value_); }
@@ -807,12 +802,7 @@ public:
   typedef const value_type& reference;
   typedef typename _NodeTypes::__const_node_value_type_pointer pointer;
 
-  _LIBCPP_HIDE_FROM_ABI __tree_const_iterator() _NOEXCEPT
-#if _LIBCPP_STD_VER >= 14
-      : __ptr_(nullptr)
-#endif
-  {
-  }
+  _LIBCPP_HIDE_FROM_ABI __tree_const_iterator() _NOEXCEPT : __ptr_(nullptr) {}
 
 private:
   typedef __tree_iterator<value_type, __node_pointer, difference_type> __non_const_iterator;
diff --git a/libcxx/include/deque b/libcxx/include/deque
index 759de5d3a030a..8db1b7042e4f9 100644
--- a/libcxx/include/deque
+++ b/libcxx/include/deque
@@ -283,13 +283,7 @@ public:
   typedef random_access_iterator_tag iterator_category;
   typedef _Reference reference;
 
-  _LIBCPP_HIDE_FROM_ABI __deque_iterator() _NOEXCEPT
-#if _LIBCPP_STD_VER >= 14
-      : __m_iter_(nullptr),
-        __ptr_(nullptr)
-#endif
-  {
-  }
+  _LIBCPP_HIDE_FROM_ABI __deque_iterator() _NOEXCEPT : __m_iter_(nullptr), __ptr_(nullptr) {}
 
   template <class _Pp, class _Rp, class _MP, __enable_if_t<is_convertible<_Pp, pointer>::value, int> = 0>
   _LIBCPP_HIDE_FROM_ABI
diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/implicit_ctad.pass.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/implicit_ctad.compile.pass.cpp
similarity index 71%
rename from libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/implicit_ctad.pass.cpp
rename to libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/implicit_ctad.compile.pass.cpp
index 8c7ca4279eead..cc94c5704327f 100644
--- a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/implicit_ctad.pass.cpp
+++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/implicit_ctad.compile.pass.cpp
@@ -16,15 +16,7 @@
 
 #include <mutex>
 
-#include "test_macros.h"
-#include "types.h"
+#include "checking_mutex.h"
 
-int main(int, char**) {
-  MyMutex mutex;
-  {
-    std::unique_lock lock(mutex);
-    ASSERT_SAME_TYPE(decltype(lock), std::unique_lock<MyMutex>);
-  }
-
-  return 0;
-}
+checking_mutex mux;
+static_assert(std::is_same_v<std::unique_lock<checking_mutex>, decltype(std::unique_lock{mux})>);
diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/copy_assign.compile.pass.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/copy_assign.compile.pass.cpp
index 9ab8369637cdc..c0cb7d4ddd27a 100644
--- a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/copy_assign.compile.pass.cpp
+++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/copy_assign.compile.pass.cpp
@@ -14,6 +14,6 @@
 
 #include <mutex>
 
-#include "../types.h"
+#include "checking_mutex.h"
 
-static_assert(!std::is_copy_assignable<std::lock_guard<MyMutex> >::value, "");
+static_assert(!std::is_copy_assignable<std::lock_guard<checking_mutex> >::value, "");
diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/copy_ctor.compile.pass.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/copy_ctor.compile.pass.cpp
index e846061f5fbd0..2846b24125e78 100644
--- a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/copy_ctor.compile.pass.cpp
+++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/copy_ctor.compile.pass.cpp
@@ -14,6 +14,6 @@
 
 #include <mutex>
 
-#include "../types.h"
+#include "checking_mutex.h"
 
-static_assert(!std::is_copy_constructible<std::lock_guard<MyMutex> >::value, "");
+static_assert(!std::is_copy_constructible<std::lock_guard<checking_mutex> >::value, "");
diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/default.pass.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/default.pass.cpp
index 6fc4f7f23ced3..f203acf5f07dd 100644
--- a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/default.pass.cpp
+++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/default.pass.cpp
@@ -15,11 +15,10 @@
 #include <cassert>
 #include <mutex>
 
-#include "test_macros.h"
-#include "../types.h"
+#include "checking_mutex.h"
 
 int main(int, char**) {
-  std::unique_lock<MyMutex> ul;
+  std::unique_lock<checking_mutex> ul;
   assert(!ul.owns_lock());
   assert(ul.mutex() == nullptr);
 
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 9563fdebd3e06..c7ff4b9f24f7b 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
@@ -15,35 +15,20 @@
 #include <cassert>
 #include <mutex>
 
-#include "nasty_containers.h"
-#include "../types.h"
-#include "test_macros.h"
+#include "checking_mutex.h"
 
 int main(int, char**) {
-  {
-    typedef MyMutex M;
-    M m0;
-    M m1;
-    std::unique_lock<M> lk0(m0);
-    std::unique_lock<M> lk1(m1);
-    lk1 = std::move(lk0);
-    assert(lk1.mutex() == std::addressof(m0));
-    assert(lk1.owns_lock() == true);
-    assert(lk0.mutex() == nullptr);
-    assert(lk0.owns_lock() == false);
-  }
-  {
-    typedef nasty_mutex M;
-    M m0;
-    M m1;
-    std::unique_lock<M> lk0(m0);
-    std::unique_lock<M> lk1(m1);
-    lk1 = std::move(lk0);
-    assert(lk1.mutex() == std::addressof(m0));
-    assert(lk1.owns_lock() == true);
-    assert(lk0.mutex() == nullptr);
-    assert(lk0.owns_lock() == false);
-  }
+  checking_mutex m0;
+  checking_mutex m1;
+  std::unique_lock<checking_mutex> lk0(m0);
+  std::unique_lock<checking_mutex> lk1(m1);
+
+  lk1 = std::move(lk0);
+
+  assert(lk1.mutex() == std::addressof(m0));
+  assert(lk1.owns_lock());
+  assert(lk0.mutex() == nullptr);
+  assert(!lk0.owns_lock());
 
   return 0;
 }
diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/move_ctor.pass.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/move_ctor.pass.cpp
index 08f6fc8410e25..62fdbde9c2c29 100644
--- a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/move_ctor.pass.cpp
+++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/move_ctor.pass.cpp
@@ -5,8 +5,6 @@
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
-//
-// UNSUPPORTED: c++03
 
 // <mutex>
 
@@ -17,31 +15,17 @@
 #include <cassert>
 #include <mutex>
 
-#include "nasty_containers.h"
-#include "../types.h"
-#include "test_macros.h"
+#include "checking_mutex.h"
 
 int main(int, char**) {
-  {
-    typedef MyMutex M;
-    M m;
-    std::unique_lock<M> lk0(m);
-    std::unique_lock<M> lk = std::move(lk0);
-    assert(lk.mutex() == std::addressof(m));
-    assert(lk.owns_lock() == true);
-    assert(lk0.mutex() == nullptr);
-    assert(lk0.owns_lock() == false);
-  }
-  {
-    typedef nasty_mutex M;
-    M m;
-    std::unique_lock<M> lk0(m);
-    std::unique_lock<M> lk = std::move(lk0);
-    assert(lk.mutex() == std::addressof(m));
-    assert(lk.owns_lock() == true);
-    assert(lk0.mutex() == nullptr);
-    assert(lk0.owns_lock() == false);
-  }
+  checking_mutex m;
+  std::unique_lock<checking_mutex> lk0(m);
+  std::unique_lock<checking_mutex> lk = std::move(lk0);
+
+  assert(lk.mutex() == std::addressof(m));
+  assert(lk.owns_lock());
+  assert(lk0.mutex() == nullptr);
+  assert(!lk0.owns_lock());
 
   return 0;
 }
diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/mutex.pass.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/mutex.pass.cpp
index 2be25748e903b..31f15deec0cfa 100644
--- a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/mutex.pass.cpp
+++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/mutex.pass.cpp
@@ -5,9 +5,6 @@
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
-//
-// UNSUPPORTED: no-threads
-// ALLOW_RETRIES: 2
 
 // <mutex>
 
@@ -19,45 +16,22 @@
 //     -> unique_lock<_Mutex>;  // C++17
 
 #include <cassert>
-#include <chrono>
-#include <cstdlib>
 #include <mutex>
-#include <thread>
 
-#include "make_test_thread.h"
+#include "checking_mutex.h"
 #include "test_macros.h"
 
-std::mutex m;
-
-typedef std::chrono::system_clock Clock;
-typedef Clock::time_point time_point;
-typedef Clock::duration duration;
-typedef std::chrono::milliseconds ms;
-typedef std::chrono::nanoseconds ns;
-
-void f()
-{
-    time_point t0 = Clock::now();
-    time_point t1;
-    {
-    std::unique_lock<std::mutex> ul(m);
-    t1 = Clock::now();
-    }
-    ns d = t1 - t0 - ms(250);
-    assert(d < ms(50));  // within 50ms
-}
+int main(int, char**) {
+  checking_mutex mux;
 
-int main(int, char**)
-{
-    m.lock();
-    std::thread t = support::make_test_thread(f);
-    std::this_thread::sleep_for(ms(250));
-    m.unlock();
-    t.join();
+  {
+    std::unique_lock<checking_mutex> lock(mux);
+    assert(mux.current_state == checking_mutex::locked_via_lock);
+  }
+  assert(mux.current_state == checking_mutex::unlocked);
 
 #if TEST_STD_VER >= 17
-    std::unique_lock ul(m);
-    static_assert((std::is_same<decltype(ul), std::unique_lock<decltype(m)>>::value), "" );
+  static_assert(std::is_same_v<std::unique_lock<checking_mutex>, decltype(std::unique_lock{mux})>, "");
 #endif
 
   return 0;
diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/mutex_adopt_lock.pass.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/mutex_adopt_lock.pass.cpp
index 28cc43853180e..1ffe8a9ce771b 100644
--- a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/mutex_adopt_lock.pass.cpp
+++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/mutex_adopt_lock.pass.cpp
@@ -5,8 +5,6 @@
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
-//
-// UNSUPPORTED: c++03
 
 // <mutex>
 
@@ -17,27 +15,16 @@
 #include <cassert>
 #include <mutex>
 
-#include "nasty_containers.h"
-#include "../types.h"
-#include "test_macros.h"
+#include "checking_mutex.h"
 
 int main(int, char**) {
-  {
-    typedef MyMutex M;
-    M m;
-    m.lock();
-    std::unique_lock<M> lk(m, std::adopt_lock);
-    assert(lk.mutex() == std::addressof(m));
-    assert(lk.owns_lock() == true);
-  }
-  {
-    typedef nasty_mutex M;
-    M m;
-    m.lock();
-    std::unique_lock<M> lk(m, std::adopt_lock);
-    assert(lk.mutex() == std::addressof(m));
-    assert(lk.owns_lock() == true);
-  }
+  checking_mutex m;
+  m.lock();
+  m.last_try = checking_mutex::none;
+  std::unique_lock<checking_mutex> lk(m, std::adopt_lock_t());
+  assert(m.last_try == checking_mutex::none);
+  assert(lk.mutex() == std::addressof(m));
+  assert(lk.owns_lock());
 
   return 0;
 }
diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/mutex_defer_lock.pass.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/mutex_defer_lock.pass.cpp
index 96a9afbc9438c..8b48a5144d6ec 100644
--- a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/mutex_defer_lock.pass.cpp
+++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/mutex_defer_lock.pass.cpp
@@ -5,8 +5,6 @@
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
-//
-// UNSUPPORTED: c++03
 
 // <mutex>
 
@@ -17,25 +15,14 @@
 #include <cassert>
 #include <mutex>
 
-#include "nasty_containers.h"
-#include "../types.h"
-#include "test_macros.h"
+#include "checking_mutex.h"
 
 int main(int, char**) {
-  {
-    typedef MyMutex M;
-    M m;
-    std::unique_lock<M> lk(m, std::defer_lock);
-    assert(lk.mutex() == std::addressof(m));
-    assert(lk.owns_lock() == false);
-  }
-  {
-    typedef nasty_mutex M;
-    M m;
-    std::unique_lock<M> lk(m, std::defer_lock);
-    assert(lk.mutex() == std::addressof(m));
-    assert(lk.owns_lock() == false);
-  }
+  checking_mutex m;
+  std::unique_lock<checking_mutex> lk(m, std::defer_lock_t());
+  assert(m.last_try == checking_mutex::none);
+  assert(lk.mutex() == std::addressof(m));
+  assert(lk.owns_lock() == false);
 
   return 0;
 }
diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/mutex_duration.pass.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/mutex_duration.pass.cpp
index 4bfabab919f17..624b99623d6be 100644
--- a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/mutex_duration.pass.cpp
+++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/mutex_duration.pass.cpp
@@ -5,69 +5,36 @@
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
-//
-// UNSUPPORTED: no-threads
-// ALLOW_RETRIES: 2
 
 // <mutex>
 
-// class timed_mutex;
-
 // template <class Rep, class Period>
-//   unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time);
+// unique_lock::unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time);
 
-#include <mutex>
-#include <thread>
-#include <cstdlib>
 #include <cassert>
+#include <chrono>
+#include <mutex>
 
-#include "make_test_thread.h"
-#include "test_macros.h"
-
-std::timed_mutex m;
-
-typedef std::chrono::steady_clock Clock;
-typedef Clock::time_point time_point;
-typedef Clock::duration duration;
-typedef std::chrono::milliseconds ms;
-typedef std::chrono::nanoseconds ns;
-
-void f1()
-{
-    time_point t0 = Clock::now();
-    std::unique_lock<std::timed_mutex> lk(m, ms(300));
-    assert(lk.owns_lock() == true);
-    time_point t1 = Clock::now();
-    ns d = t1 - t0 - ms(250);
-    assert(d < ms(50));  // within 50ms
-}
-
-void f2()
-{
-    time_point t0 = Clock::now();
-    std::unique_lock<std::timed_mutex> lk(m, ms(250));
-    assert(lk.owns_lock() == false);
-    time_point t1 = Clock::now();
-    ns d = t1 - t0 - ms(250);
-    assert(d < ms(50));  // within 50ms
-}
-
-int main(int, char**)
-{
-    {
-        m.lock();
-        std::thread t = support::make_test_thread(f1);
-        std::this_thread::sleep_for(ms(250));
-        m.unlock();
-        t.join();
-    }
-    {
-        m.lock();
-        std::thread t = support::make_test_thread(f2);
-        std::this_thread::sleep_for(ms(300));
-        m.unlock();
-        t.join();
-    }
+#include "checking_mutex.h"
+
+int main(int, char**) {
+  checking_mutex mux;
+  { // check successful lock
+    mux.reject = false;
+    std::unique_lock<checking_mutex> lock(mux, std::chrono::seconds());
+    assert(mux.current_state == checking_mutex::locked_via_try_lock_for);
+    assert(lock.owns_lock());
+  }
+  assert(mux.current_state == checking_mutex::unlocked);
+
+  { // check unsuccessful lock
+    mux.reject = true;
+    std::unique_lock<checking_mutex> lock(mux, std::chrono::seconds());
+    assert(mux.current_state == checking_mutex::unlocked);
+    assert(mux.last_try == checking_mutex::locked_via_try_lock_for);
+    assert(!lock.owns_lock());
+  }
+  assert(mux.current_state == checking_mutex::unlocked);
 
   return 0;
 }
diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/mutex_time_point.pass.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/mutex_time_point.pass.cpp
index b85bbace3233c..3b344b9616c3d 100644
--- a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/mutex_time_point.pass.cpp
+++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/mutex_time_point.pass.cpp
@@ -5,69 +5,37 @@
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
-//
-// UNSUPPORTED: no-threads
-// ALLOW_RETRIES: 2
 
 // <mutex>
 
-// class timed_mutex;
-
 // template <class Clock, class Duration>
-//   unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time);
+// unique_lock::unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time);
 
-#include <mutex>
-#include <thread>
-#include <cstdlib>
 #include <cassert>
+#include <chrono>
+#include <mutex>
 
-#include "make_test_thread.h"
-#include "test_macros.h"
-
-std::timed_mutex m;
-
-typedef std::chrono::steady_clock Clock;
-typedef Clock::time_point time_point;
-typedef Clock::duration duration;
-typedef std::chrono::milliseconds ms;
-typedef std::chrono::nanoseconds ns;
-
-void f1()
-{
-    time_point t0 = Clock::now();
-    std::unique_lock<std::timed_mutex> lk(m, Clock::now() + ms(300));
-    assert(lk.owns_lock() == true);
-    time_point t1 = Clock::now();
-    ns d = t1 - t0 - ms(250);
-    assert(d < ns(50000000));  // within 50ms
-}
-
-void f2()
-{
-    time_point t0 = Clock::now();
-    std::unique_lock<std::timed_mutex> lk(m, Clock::now() + ms(250));
-    assert(lk.owns_lock() == false);
-    time_point t1 = Clock::now();
-    ns d = t1 - t0 - ms(250);
-    assert(d < ms(50));  // within 50ms
-}
-
-int main(int, char**)
-{
-    {
-        m.lock();
-        std::thread t = support::make_test_thread(f1);
-        std::this_thread::sleep_for(ms(250));
-        m.unlock();
-        t.join();
-    }
-    {
-        m.lock();
-        std::thread t = support::make_test_thread(f2);
-        std::this_thread::sleep_for(ms(300));
-        m.unlock();
-        t.join();
-    }
+#include "checking_mutex.h"
+
+int main(int, char**) {
+  checking_mutex mux;
+
+  { // check successful lock
+    mux.reject = false;
+    std::unique_lock<checking_mutex> lock(mux, std::chrono::time_point<std::chrono::steady_clock>());
+    assert(mux.current_state == checking_mutex::locked_via_try_lock_until);
+    assert(lock.owns_lock());
+  }
+  assert(mux.current_state == checking_mutex::unlocked);
+
+  { // check unsuccessful lock
+    mux.reject = true;
+    std::unique_lock<checking_mutex> lock(mux, std::chrono::time_point<std::chrono::steady_clock>());
+    assert(mux.current_state == checking_mutex::unlocked);
+    assert(mux.last_try == checking_mutex::locked_via_try_lock_until);
+    assert(!lock.owns_lock());
+  }
+  assert(mux.current_state == checking_mutex::unlocked);
 
   return 0;
 }
diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/mutex_try_to_lock.pass.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/mutex_try_to_lock.pass.cpp
index 992d383dfa780..e7af0fc34e750 100644
--- a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/mutex_try_to_lock.pass.cpp
+++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.cons/mutex_try_to_lock.pass.cpp
@@ -6,10 +6,6 @@
 //
 //===----------------------------------------------------------------------===//
 
-// UNSUPPORTED: no-threads
-// UNSUPPORTED: c++03
-// ALLOW_RETRIES: 2
-
 // <mutex>
 
 // template <class Mutex> class unique_lock;
@@ -17,55 +13,29 @@
 // unique_lock(mutex_type& m, try_to_lock_t);
 
 #include <cassert>
-#include <chrono>
-#include <cstdlib>
 #include <mutex>
-#include <thread>
-
-#include "make_test_thread.h"
-#include "test_macros.h"
-
-std::mutex m;
-
-typedef std::chrono::system_clock Clock;
-typedef Clock::time_point time_point;
-typedef Clock::duration duration;
-typedef std::chrono::milliseconds ms;
-typedef std::chrono::nanoseconds ns;
-
-void f()
-{
-    time_point t0 = Clock::now();
-    {
-        std::unique_lock<std::mutex> lk(m, std::try_to_lock);
-        assert(lk.owns_lock() == false);
-    }
-    {
-        std::unique_lock<std::mutex> lk(m, std::try_to_lock);
-        assert(lk.owns_lock() == false);
-    }
-    {
-        std::unique_lock<std::mutex> lk(m, std::try_to_lock);
-        assert(lk.owns_lock() == false);
-    }
-    while (true)
-    {
-        std::unique_lock<std::mutex> lk(m, std::try_to_lock);
-        if (lk.owns_lock())
-            break;
-    }
-    time_point t1 = Clock::now();
-    ns d = t1 - t0 - ms(250);
-    assert(d < ms(200));  // within 200ms
-}
 
-int main(int, char**)
-{
-    m.lock();
-    std::thread t = support::make_test_thread(f);
-    std::this_thread::sleep_for(ms(250));
-    m.unlock();
-    t.join();
+#include "checking_mutex.h"
+
+int main(int, char**) {
+  checking_mutex mux;
+
+  { // check successful lock
+    mux.reject = false;
+    std::unique_lock<checking_mutex> lock(mux, std::try_to_lock_t());
+    assert(mux.current_state == checking_mutex::locked_via_try_lock);
+    assert(lock.owns_lock());
+  }
+  assert(mux.current_state == checking_mutex::unlocked);
+
+  { // check successful lock
+    mux.reject = true;
+    std::unique_lock<checking_mutex> lock(mux, std::try_to_lock_t());
+    assert(mux.last_try == checking_mutex::locked_via_try_lock);
+    assert(mux.current_state == checking_mutex::unlocked);
+    assert(!lock.owns_lock());
+  }
+  assert(mux.current_state == checking_mutex::unlocked);
 
   return 0;
 }
diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.locking/lock.pass.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.locking/lock.pass.cpp
index 6767e11a1f8b4..4be1eaa5e1b95 100644
--- a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.locking/lock.pass.cpp
+++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.locking/lock.pass.cpp
@@ -5,10 +5,6 @@
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
-//
-// UNSUPPORTED: no-threads
-// UNSUPPORTED: c++03
-// ALLOW_RETRIES: 2
 
 // <mutex>
 
@@ -17,65 +13,42 @@
 // void lock();
 
 #include <cassert>
-#include <chrono>
-#include <cstdlib>
 #include <mutex>
 #include <system_error>
-#include <thread>
 
-#include "make_test_thread.h"
+#include "checking_mutex.h"
 #include "test_macros.h"
 
-std::mutex m;
+int main(int, char**) {
+  checking_mutex mux;
+  std::unique_lock<checking_mutex> lk(mux, std::defer_lock_t());
+  assert(mux.last_try == checking_mutex::none);
+  lk.lock();
+  assert(mux.current_state == checking_mutex::locked_via_lock);
+  mux.last_try = checking_mutex::none;
 
-typedef std::chrono::system_clock Clock;
-typedef Clock::time_point time_point;
-typedef Clock::duration duration;
-typedef std::chrono::milliseconds ms;
-typedef std::chrono::nanoseconds ns;
+#ifndef TEST_HAS_NO_EXCEPTIONS
+  try {
+    mux.last_try = checking_mutex::none;
+    lk.lock();
+    assert(false);
+  } catch (std::system_error& e) {
+    assert(mux.last_try == checking_mutex::none);
+    assert(e.code() == std::errc::resource_deadlock_would_occur);
+  }
 
-void f()
-{
-    std::unique_lock<std::mutex> lk(m, std::defer_lock);
-    time_point t0 = Clock::now();
+  lk.unlock();
+  lk.release();
+
+  try {
+    mux.last_try = checking_mutex::none;
     lk.lock();
-    time_point t1 = Clock::now();
-    assert(lk.owns_lock() == true);
-    ns d = t1 - t0 - ms(250);
-    assert(d < ms(25));  // within 25ms
-#ifndef TEST_HAS_NO_EXCEPTIONS
-    try
-    {
-        lk.lock();
-        assert(false);
-    }
-    catch (std::system_error& e)
-    {
-      assert(e.code() == std::errc::resource_deadlock_would_occur);
-    }
+    assert(false);
+  } catch (std::system_error& e) {
+    assert(mux.last_try == checking_mutex::none);
+    assert(e.code() == std::errc::operation_not_permitted);
+  }
 #endif
-    lk.unlock();
-    lk.release();
-#ifndef TEST_HAS_NO_EXCEPTIONS
-    try
-    {
-        lk.lock();
-        assert(false);
-    }
-    catch (std::system_error& e)
-    {
-      assert(e.code() == std::errc::operation_not_permitted);
-    }
-#endif
-}
-
-int main(int, char**)
-{
-    m.lock();
-    std::thread t = support::make_test_thread(f);
-    std::this_thread::sleep_for(ms(250));
-    m.unlock();
-    t.join();
 
   return 0;
 }
diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.locking/try_lock.pass.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.locking/try_lock.pass.cpp
index 2ee5d3766eb18..41a5957480556 100644
--- a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.locking/try_lock.pass.cpp
+++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.locking/try_lock.pass.cpp
@@ -5,9 +5,6 @@
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
-//
-// UNSUPPORTED: c++03
-// ALLOW_RETRIES: 2
 
 // <mutex>
 
@@ -20,33 +17,43 @@
 #include <system_error>
 
 #include "test_macros.h"
-#include "../types.h"
-
-MyTimedMutex m;
+#include "checking_mutex.h"
 
 int main(int, char**) {
-  std::unique_lock<MyTimedMutex> lk(m, std::defer_lock);
-  assert(lk.try_lock() == true);
-  assert(m.try_lock_called == true);
-  assert(lk.owns_lock() == true);
+  checking_mutex mux;
+
+  std::unique_lock<checking_mutex> lock(mux, std::defer_lock_t());
+  assert(lock.try_lock());
+  assert(mux.current_state == checking_mutex::locked_via_try_lock);
+  assert(lock.owns_lock());
+
 #ifndef TEST_HAS_NO_EXCEPTIONS
   try {
-    TEST_IGNORE_NODISCARD lk.try_lock();
+    mux.last_try = checking_mutex::none;
+    TEST_IGNORE_NODISCARD lock.try_lock();
     assert(false);
   } catch (std::system_error& e) {
+    assert(mux.last_try == checking_mutex::none);
     assert(e.code() == std::errc::resource_deadlock_would_occur);
   }
 #endif
-  lk.unlock();
-  assert(lk.try_lock() == false);
-  assert(m.try_lock_called == false);
-  assert(lk.owns_lock() == false);
-  lk.release();
+
+  lock.unlock();
+  mux.reject = true;
+
+  assert(!lock.try_lock());
+  assert(mux.last_try == checking_mutex::locked_via_try_lock);
+
+  assert(!lock.owns_lock());
+  lock.release();
+
 #ifndef TEST_HAS_NO_EXCEPTIONS
   try {
-    TEST_IGNORE_NODISCARD lk.try_lock();
+    mux.last_try = checking_mutex::none;
+    (void)lock.try_lock();
     assert(false);
   } catch (std::system_error& e) {
+    assert(mux.last_try == checking_mutex::none);
     assert(e.code() == std::errc::operation_not_permitted);
   }
 #endif
diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.locking/try_lock_for.pass.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.locking/try_lock_for.pass.cpp
index 603cc7b185620..cfe81a8faf338 100644
--- a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.locking/try_lock_for.pass.cpp
+++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.locking/try_lock_for.pass.cpp
@@ -5,8 +5,6 @@
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
-//
-// UNSUPPORTED: c++03
 
 // <mutex>
 
@@ -20,34 +18,47 @@
 #include <system_error>
 
 #include "test_macros.h"
-#include "../types.h"
-
-MyTimedMutex m;
+#include "checking_mutex.h"
 
 int main(int, char**) {
   using ms = std::chrono::milliseconds;
-  std::unique_lock<MyTimedMutex> lk(m, std::defer_lock);
-  assert(lk.try_lock_for(ms(5)) == true);
-  assert(m.try_lock_for_called == true);
-  assert(lk.owns_lock() == true);
+
+  checking_mutex mux;
+
+  std::unique_lock<checking_mutex> lock(mux, std::defer_lock_t());
+
+  assert(lock.try_lock_for(ms(5)));
+  assert(mux.current_state == checking_mutex::locked_via_try_lock_for);
+  assert(lock.owns_lock());
+
 #ifndef TEST_HAS_NO_EXCEPTIONS
   try {
-    TEST_IGNORE_NODISCARD lk.try_lock_for(ms(5));
+    mux.last_try = checking_mutex::none;
+    (void)lock.try_lock_for(ms(5));
+
     assert(false);
   } catch (std::system_error& e) {
+    assert(mux.last_try == checking_mutex::none);
     assert(e.code() == std::errc::resource_deadlock_would_occur);
   }
 #endif
-  lk.unlock();
-  assert(lk.try_lock_for(ms(5)) == false);
-  assert(m.try_lock_for_called == false);
-  assert(lk.owns_lock() == false);
-  lk.release();
+
+  lock.unlock();
+  mux.reject = true;
+  assert(!lock.try_lock_for(ms(5)));
+  assert(mux.last_try == checking_mutex::locked_via_try_lock_for);
+  assert(!lock.owns_lock());
+
+  lock.release();
+
 #ifndef TEST_HAS_NO_EXCEPTIONS
   try {
-    TEST_IGNORE_NODISCARD lk.try_lock_for(ms(5));
+    mux.last_try = checking_mutex::none;
+    (void)lock.try_lock_for(ms(5));
+
     assert(false);
   } catch (std::system_error& e) {
+    assert(mux.last_try == checking_mutex::none);
     assert(e.code() == std::errc::operation_not_permitted);
   }
 #endif
diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.locking/try_lock_until.pass.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.locking/try_lock_until.pass.cpp
index 46ab95197311c..bc261f681020f 100644
--- a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.locking/try_lock_until.pass.cpp
+++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.locking/try_lock_until.pass.cpp
@@ -5,8 +5,6 @@
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
-//
-// UNSUPPORTED: c++03
 
 // <mutex>
 
@@ -20,35 +18,44 @@
 #include <mutex>
 #include <system_error>
 
+#include "checking_mutex.h"
 #include "test_macros.h"
-#include "../types.h"
-
-MyTimedMutex m;
 
 int main(int, char**) {
   typedef std::chrono::system_clock Clock;
-  std::unique_lock<MyTimedMutex> lk(m, std::defer_lock);
-  assert(lk.try_lock_until(Clock::now()) == true);
-  assert(m.try_lock_until_called == true);
-  assert(lk.owns_lock() == true);
+  checking_mutex mux;
+
+  std::unique_lock<checking_mutex> lock(mux, std::defer_lock_t());
+
+  assert(lock.try_lock_until(Clock::now()));
+  assert(mux.current_state == checking_mutex::locked_via_try_lock_until);
+  assert(lock.owns_lock());
+
 #ifndef TEST_HAS_NO_EXCEPTIONS
   try {
-    TEST_IGNORE_NODISCARD lk.try_lock_until(Clock::now());
+    mux.last_try = checking_mutex::none;
+    (void)lock.try_lock_until(Clock::now());
     assert(false);
   } catch (std::system_error& e) {
+    assert(mux.last_try == checking_mutex::none);
     assert(e.code() == std::errc::resource_deadlock_would_occur);
   }
 #endif
-  lk.unlock();
-  assert(lk.try_lock_until(Clock::now()) == false);
-  assert(m.try_lock_until_called == false);
-  assert(lk.owns_lock() == false);
-  lk.release();
+
+  lock.unlock();
+  mux.reject = true;
+  assert(!lock.try_lock_until(Clock::now()));
+  assert(mux.last_try == checking_mutex::locked_via_try_lock_until);
+  assert(lock.owns_lock() == false);
+  lock.release();
+
 #ifndef TEST_HAS_NO_EXCEPTIONS
   try {
-    TEST_IGNORE_NODISCARD lk.try_lock_until(Clock::now());
+    mux.last_try = checking_mutex::none;
+    (void)lock.try_lock_until(Clock::now());
     assert(false);
   } catch (std::system_error& e) {
+    assert(mux.last_try == checking_mutex::none);
     assert(e.code() == std::errc::operation_not_permitted);
   }
 #endif
diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.locking/unlock.pass.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.locking/unlock.pass.cpp
index 97808f60f2e55..cfc44a6cd5d25 100644
--- a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.locking/unlock.pass.cpp
+++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.locking/unlock.pass.cpp
@@ -17,28 +17,36 @@
 #include <system_error>
 
 #include "test_macros.h"
-#include "../types.h"
-
-MyMutex m;
+#include "checking_mutex.h"
 
 int main(int, char**) {
-  std::unique_lock<MyMutex> lk(m);
-  lk.unlock();
-  assert(lk.owns_lock() == false);
+  checking_mutex mux;
+  std::unique_lock<checking_mutex> lock(mux);
+  assert(mux.current_state == checking_mutex::locked_via_lock);
+  lock.unlock();
+  assert(mux.current_state == checking_mutex::unlocked);
+  assert(!lock.owns_lock());
+
 #ifndef TEST_HAS_NO_EXCEPTIONS
   try {
-    lk.unlock();
+    mux.last_try = checking_mutex::none;
+    lock.unlock();
     assert(false);
   } catch (std::system_error& e) {
+    assert(mux.last_try == checking_mutex::none);
     assert(e.code() == std::errc::operation_not_permitted);
   }
 #endif
-  lk.release();
+
+  lock.release();
+
 #ifndef TEST_HAS_NO_EXCEPTIONS
   try {
-    lk.unlock();
+    mux.last_try = checking_mutex::none;
+    lock.unlock();
     assert(false);
   } catch (std::system_error& e) {
+    assert(mux.last_try == checking_mutex::none);
     assert(e.code() == std::errc::operation_not_permitted);
   }
 #endif
diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.mod/member_swap.pass.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.mod/member_swap.pass.cpp
index 361c85e015059..a249b451125de 100644
--- a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.mod/member_swap.pass.cpp
+++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.mod/member_swap.pass.cpp
@@ -15,19 +15,19 @@
 #include <cassert>
 #include <mutex>
 
-#include "test_macros.h"
-#include "../types.h"
-
-MyMutex m;
+#include "checking_mutex.h"
 
 int main(int, char**) {
-  std::unique_lock<MyMutex> lk1(m);
-  std::unique_lock<MyMutex> lk2;
-  lk1.swap(lk2);
-  assert(lk1.mutex() == nullptr);
-  assert(lk1.owns_lock() == false);
-  assert(lk2.mutex() == &m);
-  assert(lk2.owns_lock() == true);
+  checking_mutex mux;
+  std::unique_lock<checking_mutex> lock1(mux);
+  std::unique_lock<checking_mutex> lock2;
+
+  lock1.swap(lock2);
+
+  assert(lock1.mutex() == nullptr);
+  assert(!lock1.owns_lock());
+  assert(lock2.mutex() == std::addressof(mux));
+  assert(lock2.owns_lock() == true);
 
   return 0;
 }
diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.mod/nonmember_swap.pass.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.mod/nonmember_swap.pass.cpp
index 5133032f6ae39..49afc73c48f1e 100644
--- a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.mod/nonmember_swap.pass.cpp
+++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.mod/nonmember_swap.pass.cpp
@@ -16,19 +16,19 @@
 #include <cassert>
 #include <mutex>
 
-#include "test_macros.h"
-#include "../types.h"
-
-MyMutex m;
+#include "checking_mutex.h"
 
 int main(int, char**) {
-  std::unique_lock<MyMutex> lk1(m);
-  std::unique_lock<MyMutex> lk2;
-  swap(lk1, lk2);
-  assert(lk1.mutex() == nullptr);
-  assert(lk1.owns_lock() == false);
-  assert(lk2.mutex() == &m);
-  assert(lk2.owns_lock() == true);
+  checking_mutex mux;
+  std::unique_lock<checking_mutex> lock1(mux);
+  std::unique_lock<checking_mutex> lock2;
+
+  swap(lock1, lock2);
+
+  assert(lock1.mutex() == nullptr);
+  assert(!lock1.owns_lock());
+  assert(lock2.mutex() == std::addressof(mux));
+  assert(lock2.owns_lock() == true);
 
   return 0;
 }
diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.mod/release.pass.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.mod/release.pass.cpp
index a726c8ccc060a..8d659bb3b42d3 100644
--- a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.mod/release.pass.cpp
+++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.mod/release.pass.cpp
@@ -15,25 +15,22 @@
 #include <cassert>
 #include <mutex>
 
-#include "test_macros.h"
-#include "../types.h"
-
-int MyCountingMutex::lock_count   = 0;
-int MyCountingMutex::unlock_count = 0;
-
-MyCountingMutex m;
+#include "checking_mutex.h"
 
 int main(int, char**) {
-  std::unique_lock<MyCountingMutex> lk(m);
-  assert(lk.mutex() == &m);
-  assert(lk.owns_lock() == true);
-  assert(MyCountingMutex::lock_count == 1);
-  assert(MyCountingMutex::unlock_count == 0);
-  assert(lk.release() == &m);
-  assert(lk.mutex() == nullptr);
-  assert(lk.owns_lock() == false);
-  assert(MyCountingMutex::lock_count == 1);
-  assert(MyCountingMutex::unlock_count == 0);
+  checking_mutex mux;
+  std::unique_lock<checking_mutex> lock(mux);
+  assert(lock.mutex() == std::addressof(mux));
+  assert(lock.owns_lock());
+
+  assert(mux.current_state == checking_mutex::locked_via_lock);
+
+  assert(lock.release() == std::addressof(mux));
+  assert(lock.mutex() == nullptr);
+  assert(!lock.owns_lock());
+  assert(mux.last_try == checking_mutex::locked_via_lock);
+  assert(mux.current_state == checking_mutex::locked_via_lock);
+  mux.unlock();
 
   return 0;
 }
diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.obs/mutex.pass.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.obs/mutex.pass.cpp
index 72346e8c67e25..bb7a91773e35f 100644
--- a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.obs/mutex.pass.cpp
+++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.obs/mutex.pass.cpp
@@ -15,18 +15,16 @@
 #include <cassert>
 #include <mutex>
 
-#include "test_macros.h"
-#include "../types.h"
-
-MyMutex m;
+#include "checking_mutex.h"
 
 int main(int, char**) {
-  std::unique_lock<MyMutex> lk0;
-  assert(lk0.mutex() == nullptr);
-  std::unique_lock<MyMutex> lk1(m);
-  assert(lk1.mutex() == &m);
-  lk1.unlock();
-  assert(lk1.mutex() == &m);
+  checking_mutex mux;
+  std::unique_lock<checking_mutex> lock0;
+  assert(lock0.mutex() == nullptr);
+  std::unique_lock<checking_mutex> lock1(mux);
+  assert(lock1.mutex() == std::addressof(mux));
+  lock1.unlock();
+  assert(lock1.mutex() == std::addressof(mux));
 
   return 0;
 }
diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.obs/op_bool.pass.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.obs/op_bool.pass.cpp
index 3759302a483eb..65f853e71af40 100644
--- a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.obs/op_bool.pass.cpp
+++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.obs/op_bool.pass.cpp
@@ -16,21 +16,21 @@
 #include <mutex>
 #include <type_traits>
 
+#include "checking_mutex.h"
 #include "test_macros.h"
-#include "../types.h"
-
-MyMutex m;
 
 int main(int, char**) {
-  static_assert(std::is_constructible<bool, std::unique_lock<MyMutex> >::value, "");
-  static_assert(!std::is_convertible<std::unique_lock<MyMutex>, bool>::value, "");
-
-  std::unique_lock<MyMutex> lk0;
-  assert(static_cast<bool>(lk0) == false);
-  std::unique_lock<MyMutex> lk1(m);
-  assert(static_cast<bool>(lk1) == true);
+  static_assert(std::is_constructible<bool, std::unique_lock<checking_mutex> >::value, "");
+  static_assert(!std::is_convertible<std::unique_lock<checking_mutex>, bool>::value, "");
+
+  checking_mutex mux;
+  std::unique_lock<checking_mutex> lk0;
+  assert(!static_cast<bool>(lk0));
+  std::unique_lock<checking_mutex> lk1(mux);
+  assert(static_cast<bool>(lk1));
   lk1.unlock();
-  assert(static_cast<bool>(lk1) == false);
+  assert(!static_cast<bool>(lk1));
+
   ASSERT_NOEXCEPT(static_cast<bool>(lk0));
 
   return 0;
diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.obs/owns_lock.pass.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.obs/owns_lock.pass.cpp
index 163942786323a..264e6b3622eb9 100644
--- a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.obs/owns_lock.pass.cpp
+++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/thread.lock.unique.obs/owns_lock.pass.cpp
@@ -16,17 +16,16 @@
 #include <mutex>
 
 #include "test_macros.h"
-#include "../types.h"
-
-MyMutex m;
+#include "checking_mutex.h"
 
 int main(int, char**) {
-  std::unique_lock<MyMutex> lk0;
-  assert(lk0.owns_lock() == false);
-  std::unique_lock<MyMutex> lk1(m);
-  assert(lk1.owns_lock() == true);
-  lk1.unlock();
-  assert(lk1.owns_lock() == false);
+  checking_mutex mux;
+  std::unique_lock<checking_mutex> lock0;
+  assert(!lock0.owns_lock());
+  std::unique_lock<checking_mutex> lock1(mux);
+  assert(lock1.owns_lock());
+  lock1.unlock();
+  assert(!lock1.owns_lock());
 
   return 0;
 }
diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/types.compile.pass.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/types.compile.pass.cpp
index 312863ae8e743..56055788965d5 100644
--- a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/types.compile.pass.cpp
+++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/types.compile.pass.cpp
@@ -19,7 +19,6 @@
 #include <mutex>
 #include <type_traits>
 
-#include "test_macros.h"
-#include "types.h"
+#include "checking_mutex.h"
 
-static_assert((std::is_same<std::unique_lock<MyMutex>::mutex_type, MyMutex>::value), "");
+static_assert(std::is_same<std::unique_lock<checking_mutex>::mutex_type, checking_mutex>::value, "");
diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/types.h b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/types.h
deleted file mode 100644
index 15a1a531487f5..0000000000000
--- a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/types.h
+++ /dev/null
@@ -1,88 +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
-//
-//===----------------------------------------------------------------------===//
-
-#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>
-#include <chrono>
-
-struct MyMutex {
-  bool locked = false;
-
-  MyMutex() = default;
-  ~MyMutex() { assert(!locked); }
-
-  void lock() {
-    assert(!locked);
-    locked = true;
-  }
-
-  void unlock() {
-    assert(locked);
-    locked = false;
-  }
-
-  bool try_lock() {
-    if (locked)
-      return false;
-    lock();
-    return true;
-  }
-
-  template <class Rep, class Period>
-  bool try_lock_for(const std::chrono::duration<Rep, Period>& rel_time) {
-    using ms = std::chrono::milliseconds;
-    assert(rel_time == ms(5));
-    if (locked)
-      return false;
-    lock();
-    return true;
-  }
-
-  MyMutex(MyMutex const&)            = delete;
-  MyMutex& operator=(MyMutex const&) = delete;
-};
-
-struct MyTimedMutex {
-  using ms = std::chrono::milliseconds;
-
-  bool try_lock_called       = false;
-  bool try_lock_for_called   = false;
-  bool try_lock_until_called = false;
-
-  bool try_lock() {
-    try_lock_called = !try_lock_called;
-    return try_lock_called;
-  }
-
-  template <class Rep, class Period>
-  bool try_lock_for(const std::chrono::duration<Rep, Period>& rel_time) {
-    assert(rel_time == ms(5));
-    try_lock_for_called = !try_lock_for_called;
-    return try_lock_for_called;
-  }
-
-  template <class Clock, class Duration>
-  bool try_lock_until(const std::chrono::time_point<Clock, Duration>& abs_time) {
-    assert(Clock::now() - abs_time < ms(5));
-    try_lock_until_called = !try_lock_until_called;
-    return try_lock_until_called;
-  }
-
-  void unlock() {}
-};
-
-struct MyCountingMutex {
-  static int lock_count;
-  static int unlock_count;
-  void lock() { ++lock_count; }
-  void unlock() { ++unlock_count; }
-};
-
-#endif // TEST_STD_THREAD_THREAD_MUTEX_THREAD_LOCK_THREAD_LOCK_GUARD_TYPES_H
diff --git a/libcxx/test/support/checking_mutex.h b/libcxx/test/support/checking_mutex.h
new file mode 100644
index 0000000000000..1a635c32f29a6
--- /dev/null
+++ b/libcxx/test/support/checking_mutex.h
@@ -0,0 +1,80 @@
+//===----------------------------------------------------------------------===//
+//
+// 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_SUPPORT_CHECKING_MUTEX_H
+#define TEST_SUPPORT_CHECKING_MUTEX_H
+
+#include <cassert>
+#include <chrono>
+
+struct checking_mutex {
+  enum state {
+    locked_via_lock,
+    locked_via_try_lock,
+    locked_via_try_lock_for,
+    locked_via_try_lock_until,
+    unlocked,
+    none,
+  };
+
+  state current_state = unlocked;
+  state last_try      = none;
+  bool reject         = false;
+
+  checking_mutex()                      = default;
+  checking_mutex(const checking_mutex&) = delete;
+  ~checking_mutex() { assert(current_state == unlocked); }
+
+  void lock() {
+    assert(current_state == unlocked);
+    assert(!reject);
+    current_state = locked_via_lock;
+    last_try      = locked_via_lock;
+    reject        = true;
+  }
+
+  void unlock() {
+    assert(current_state != unlocked && current_state != none);
+    last_try      = unlocked;
+    current_state = unlocked;
+    reject        = false;
+  }
+
+  bool try_lock() {
+    last_try = locked_via_try_lock;
+    if (reject)
+      return false;
+    current_state = locked_via_try_lock;
+    return true;
+  }
+
+  template <class Rep, class Period>
+  bool try_lock_for(const std::chrono::duration<Rep, Period>&) {
+    last_try = locked_via_try_lock_for;
+    if (reject)
+      return false;
+    current_state = locked_via_try_lock_for;
+    return true;
+  }
+
+  template <class Clock, class Duration>
+  bool try_lock_until(const std::chrono::time_point<Clock, Duration>&) {
+    last_try = locked_via_try_lock_until;
+    if (reject)
+      return false;
+    current_state = locked_via_try_lock_until;
+    return true;
+  }
+
+  checking_mutex* operator&() = delete;
+
+  template <class T>
+  void operator,(const T&) = delete;
+};
+
+#endif // TEST_SUPPORT_CHECKING_MUTEX_H



More information about the libcxx-commits mailing list