https://gcc.gnu.org/g:88e41d761e02f77345ad88b42500e2ef3861c245

commit r16-996-g88e41d761e02f77345ad88b42500e2ef3861c245
Author: Jonathan Wakely <jwak...@redhat.com>
Date:   Thu Jan 9 22:03:15 2025 +0000

    libstdc++: Optimise std::latch::arrive_and_wait
    
    We don't need to wait if we know the counter has reached zero.
    
    libstdc++-v3/ChangeLog:
    
            * include/std/latch (latch::arrive_and_wait): Optimise.

Diff:
---
 libstdc++-v3/include/std/latch | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/libstdc++-v3/include/std/latch b/libstdc++-v3/include/std/latch
index 52a2b1489f6a..9504df0a7224 100644
--- a/libstdc++-v3/include/std/latch
+++ b/libstdc++-v3/include/std/latch
@@ -101,8 +101,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     _GLIBCXX_ALWAYS_INLINE void
     arrive_and_wait(ptrdiff_t __update = 1) noexcept
     {
-      count_down(__update);
-      wait();
+      // The standard specifies this functions as count_down(update); wait();
+      // but we combine those two calls into one and avoid the wait() if we
+      // know the counter reached zero.
+
+      __glibcxx_assert(__update >= 0 && __update <= max());
+      // Use acq_rel here because an omitted wait() would have used acquire:
+      auto const __old = __atomic_impl::fetch_sub(&_M_counter, __update,
+                                                 memory_order::acq_rel);
+      if (std::cmp_equal(__old, __update))
+       __atomic_impl::notify_all(&_M_counter);
+      else
+       {
+         __glibcxx_assert(std::cmp_less(__update, __old));
+         wait();
+       }
     }
 
   private:

Reply via email to