https://gcc.gnu.org/g:fb558b78108ff2974248190bb64b4c19215535bc

commit r16-4427-gfb558b78108ff2974248190bb64b4c19215535bc
Author: Jonathan Wakely <[email protected]>
Date:   Thu Oct 9 11:11:44 2025 +0100

    libstdc++: Add std::shared_timed_mutex tests for negative timeouts 
[PR116586]
    
    Add tests to show that std::shared_timed_mutex correctly handles
    negative timeouts.
    
    libstdc++-v3/ChangeLog:
    
            PR libstdc++/116586
            * testsuite/30_threads/shared_timed_mutex/try_lock_until/116586.cc:
            New test.
    
    Signed-off-by: Mike Crowe <[email protected]>

Diff:
---
 .../shared_timed_mutex/try_lock_until/116586.cc    | 97 ++++++++++++++++++++++
 1 file changed, 97 insertions(+)

diff --git 
a/libstdc++-v3/testsuite/30_threads/shared_timed_mutex/try_lock_until/116586.cc 
b/libstdc++-v3/testsuite/30_threads/shared_timed_mutex/try_lock_until/116586.cc
new file mode 100644
index 000000000000..cebbb3a258d9
--- /dev/null
+++ 
b/libstdc++-v3/testsuite/30_threads/shared_timed_mutex/try_lock_until/116586.cc
@@ -0,0 +1,97 @@
+// { dg-do run { target c++14 } }
+
+#include <shared_mutex>
+#include <chrono>
+#include <future>
+#include <initializer_list>
+#include <testsuite_hooks.h>
+
+namespace chrono = std::chrono;
+
+// thread.timedmutex.requirements.general:
+//   If abs_time has already passed, the function attempts to obtain
+//   ownership without blocking (as if by calling try_lock()).
+
+template <typename Clock>
+void
+test_exclusive_absolute(chrono::nanoseconds offset)
+{
+  std::shared_timed_mutex stm;
+  chrono::time_point<Clock> tp(offset);
+  VERIFY(stm.try_lock_until(tp));
+  VERIFY(!stm.try_lock_until(tp));
+}
+
+template <typename Clock>
+void
+test_shared_absolute(chrono::nanoseconds offset)
+{
+  std::shared_timed_mutex stm;
+  chrono::time_point<Clock> tp(offset);
+  VERIFY(stm.try_lock_shared_until(tp));
+  stm.unlock_shared();
+
+  VERIFY(stm.try_lock_for(chrono::seconds{10}));
+
+  {
+    // NPTL will give us EDEADLK if pthread_rwlock_timedrdlock() is called on
+    // the same thread that already holds the exclusive (write) lock, so let's
+    // arrange for a different thread to try to acquire the shared lock.
+    auto t = std::async(std::launch::async, [&stm, tp]() {
+       VERIFY(!stm.try_lock_shared_until(tp));
+      });
+  }
+}
+
+// The type of clock used for the actual wait depends on whether
+// _GLIBCXX_USE_PTHREAD_RWLOCK_CLOCKLOCK is defined. We might as well just test
+// both steady_clock and system_clock.
+template <typename Clock>
+void
+test_exclusive_relative(chrono::nanoseconds offset)
+{
+  std::shared_timed_mutex stm;
+  const auto d = -Clock::now().time_since_epoch() + offset;
+  VERIFY(stm.try_lock_for(d));
+  VERIFY(!stm.try_lock_for(d));
+}
+
+template <typename Clock>
+void
+test_shared_relative(chrono::nanoseconds offset)
+{
+  std::shared_timed_mutex stm;
+  const auto d = -Clock::now().time_since_epoch() + offset;
+  VERIFY(stm.try_lock_shared_for(d));
+  stm.unlock_shared();
+  // Should complete immediately
+  VERIFY(stm.try_lock_for(chrono::seconds{10}));
+  VERIFY(!stm.try_lock_shared_for(d));
+}
+
+int main()
+{
+  // Try once with an offset that ought to result in tv_sec == 0, tv_nsec < 0
+  // and one with an offset that ought to result in tv_sec < 0, tv_nsec == 0
+  // for the absolute calls at least.  It's not really possible to arrange for
+  // the relative calls to have tv_nsec == 0 due to time advancing.
+  using namespace std::chrono_literals;
+  for (const chrono::nanoseconds offset : {
+      // tv_sec == 0, tv_nsec == 0
+      chrono::nanoseconds{0},
+      // tv_sec == 0, tv_nsec < 0
+      chrono::nanoseconds{-10ms},
+      // tv_sec < 0
+      chrono::nanoseconds{-10s}
+    }) {
+    test_exclusive_absolute<chrono::system_clock>(offset);
+    test_shared_absolute<chrono::system_clock>(offset);
+    test_exclusive_relative<chrono::system_clock>(offset);
+    test_shared_relative<chrono::system_clock>(offset);
+
+    test_exclusive_absolute<chrono::steady_clock>(offset);
+    test_shared_absolute<chrono::steady_clock>(offset);
+    test_exclusive_relative<chrono::steady_clock>(offset);
+    test_shared_relative<chrono::steady_clock>(offset);
+  }
+}

Reply via email to