[gcc r16-994] libstdc++: Rename __waiter_pool_impl to __waitable_state
Jonathan Wakely
redi@gcc.gnu.org
Fri May 30 09:08:33 GMT 2025
https://gcc.gnu.org/g:5b110bbb70f75d034228d83086b9a49a208a1520
commit r16-994-g5b110bbb70f75d034228d83086b9a49a208a1520
Author: Jonathan Wakely <jwakely@redhat.com>
Date: Sat Jan 18 21:11:26 2025 +0000
libstdc++: Rename __waiter_pool_impl to __waitable_state
The name __waiter_pool_impl is misleading. An object of that type is a
member of the pool, not the pool itself, and it's not an "impl" of
any abstract base class or generic concept. Just call it
__waitable_state since it maintains the state used for waiting/notifying
a waitable atomic object.
Similarly, rename _S_impl_for to _S_state_for.
Once these functions move into the shared library they won't be exported
and so the naming won't matter much anyway.
libstdc++-v3/ChangeLog:
* include/bits/atomic_timed_wait.h (__wait_until_impl): Adjust
to use new naming.
* include/bits/atomic_wait.h (__waiter_pool_impl): Rename to
__waitable_state.
(__waiter_pool_impl::_S_wait): Rename to _M_waiters.
(__waiter_pool_impl::_S_impl_for): Rename to _S_state_for.
(__waiter_pool_impl::_S_track): Adjust to use new naming.
(__wait_impl, __notify_impl): Likewise.
* testsuite/29_atomics/atomic/wait_notify/100334.cc: Adjust to
use new naming.
Diff:
---
libstdc++-v3/include/bits/atomic_timed_wait.h | 16 ++---
libstdc++-v3/include/bits/atomic_wait.h | 81 ++++++++++++----------
.../29_atomics/atomic/wait_notify/100334.cc | 5 +-
3 files changed, 53 insertions(+), 49 deletions(-)
diff --git a/libstdc++-v3/include/bits/atomic_timed_wait.h b/libstdc++-v3/include/bits/atomic_timed_wait.h
index 800f461e9e48..19a0225c63b2 100644
--- a/libstdc++-v3/include/bits/atomic_timed_wait.h
+++ b/libstdc++-v3/include/bits/atomic_timed_wait.h
@@ -174,12 +174,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
const __wait_clock_t::time_point& __atime)
{
__wait_args_base __args = __a;
- __waiter_pool_impl* __pool = nullptr;
+ __waitable_state* __state = nullptr;
const __platform_wait_t* __wait_addr;
if (__args & __wait_flags::__proxy_wait)
{
- __pool = &__waiter_pool_impl::_S_impl_for(__addr);
- __wait_addr = &__pool->_M_ver;
+ __state = &__waitable_state::_S_state_for(__addr);
+ __wait_addr = &__state->_M_ver;
__atomic_load(__wait_addr, &__args._M_old, __args._M_order);
}
else
@@ -194,7 +194,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return __res;
}
- auto __tracker = __waiter_pool_impl::_S_track(__pool, __args, __addr);
+ auto __tracker = __waitable_state::_S_track(__state, __args, __addr);
#ifdef _GLIBCXX_HAVE_PLATFORM_TIMED_WAIT
if (__platform_wait_until(__wait_addr, __args._M_old, __atime))
@@ -206,12 +206,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__atomic_load(__wait_addr, &__val, __args._M_order);
if (__val == __args._M_old)
{
- if (!__pool)
- __pool = &__waiter_pool_impl::_S_impl_for(__addr);
- lock_guard<mutex> __l{ __pool->_M_mtx };
+ if (!__state)
+ __state = &__waitable_state::_S_state_for(__addr);
+ lock_guard<mutex> __l{ __state->_M_mtx };
__atomic_load(__wait_addr, &__val, __args._M_order);
if (__val == __args._M_old
- && __cond_wait_until(__pool->_M_cv, __pool->_M_mtx, __atime))
+ && __cond_wait_until(__state->_M_cv, __state->_M_mtx, __atime))
return { true, __val };
}
return { false, __val };
diff --git a/libstdc++-v3/include/bits/atomic_wait.h b/libstdc++-v3/include/bits/atomic_wait.h
index 40d8471413a2..bdc8677e9ea9 100644
--- a/libstdc++-v3/include/bits/atomic_wait.h
+++ b/libstdc++-v3/include/bits/atomic_wait.h
@@ -163,47 +163,52 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
struct __wait_args_base;
- struct __waiter_pool_impl
+ // The state used by atomic waiting and notifying functions.
+ struct __waitable_state
{
// Don't use std::hardware_destructive_interference_size here because we
// don't want the layout of library types to depend on compiler options.
static constexpr auto _S_align = 64;
- alignas(_S_align) __platform_wait_t _M_wait = 0;
+ // Count of threads blocked waiting on this state.
+ alignas(_S_align) __platform_wait_t _M_waiters = 0;
#ifndef _GLIBCXX_HAVE_PLATFORM_WAIT
mutex _M_mtx;
#endif
+ // If we can't do a platform wait on the atomic variable itself,
+ // we use this member as a proxy for the atomic variable and we
+ // use this for waiting and notifying functions instead.
alignas(_S_align) __platform_wait_t _M_ver = 0;
#ifndef _GLIBCXX_HAVE_PLATFORM_WAIT
__condvar _M_cv;
#endif
- __waiter_pool_impl() = default;
+ __waitable_state() = default;
void
_M_enter_wait() noexcept
- { __atomic_fetch_add(&_M_wait, 1, __ATOMIC_SEQ_CST); }
+ { __atomic_fetch_add(&_M_waiters, 1, __ATOMIC_SEQ_CST); }
void
_M_leave_wait() noexcept
- { __atomic_fetch_sub(&_M_wait, 1, __ATOMIC_RELEASE); }
+ { __atomic_fetch_sub(&_M_waiters, 1, __ATOMIC_RELEASE); }
bool
_M_waiting() const noexcept
{
__platform_wait_t __res;
- __atomic_load(&_M_wait, &__res, __ATOMIC_SEQ_CST);
+ __atomic_load(&_M_waiters, &__res, __ATOMIC_SEQ_CST);
return __res != 0;
}
- static __waiter_pool_impl&
- _S_impl_for(const void* __addr) noexcept
+ static __waitable_state&
+ _S_state_for(const void* __addr) noexcept
{
constexpr __UINTPTR_TYPE__ __ct = 16;
- static __waiter_pool_impl __w[__ct];
+ static __waitable_state __w[__ct];
auto __key = ((__UINTPTR_TYPE__)__addr >> 2) % __ct;
return __w[__key];
}
@@ -211,7 +216,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Return an RAII type that calls _M_enter_wait() on construction
// and _M_leave_wait() on destruction.
static auto
- _S_track(__waiter_pool_impl*& __pool, const __wait_args_base& __args,
+ _S_track(__waitable_state*& __state, const __wait_args_base& __args,
const void* __addr) noexcept;
};
@@ -298,9 +303,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
};
inline auto
- __waiter_pool_impl::_S_track(__waiter_pool_impl*& __pool,
- const __wait_args_base& __args,
- const void* __addr) noexcept
+ __waitable_state::_S_track(__waitable_state*& __state,
+ const __wait_args_base& __args,
+ const void* __addr) noexcept
{
struct _Tracker
{
@@ -308,7 +313,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
[[__gnu__::__nonnull__]]
explicit
- _Tracker(__waiter_pool_impl* __st) noexcept
+ _Tracker(__waitable_state* __st) noexcept
: _M_st(__st)
{ __st->_M_enter_wait(); }
@@ -317,21 +322,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
~_Tracker() { if (_M_st) _M_st->_M_leave_wait(); }
- __waiter_pool_impl* _M_st;
+ __waitable_state* _M_st;
};
if (__args & __wait_flags::__track_contention)
{
// Caller does not externally track contention,
- // so we want to increment+decrement __pool->_M_waiters
+ // so we want to increment+decrement __state->_M_waiters
// First make sure we have a waitable state for the address.
- if (!__pool)
- __pool = &__waiter_pool_impl::_S_impl_for(__addr);
+ if (!__state)
+ __state = &__waitable_state::_S_state_for(__addr);
// This object will increment the number of waiters and
// decrement it again on destruction.
- return _Tracker{__pool};
+ return _Tracker{__state};
}
return _Tracker{}; // For bare waits caller tracks waiters.
}
@@ -359,13 +364,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__wait_impl(const void* __addr, const __wait_args_base& __a)
{
__wait_args_base __args = __a;
- __waiter_pool_impl* __pool = nullptr;
+ __waitable_state* __state = nullptr;
const __platform_wait_t* __wait_addr;
if (__args & __wait_flags::__proxy_wait)
{
- __pool = &__waiter_pool_impl::_S_impl_for(__addr);
- __wait_addr = &__pool->_M_ver;
+ __state = &__waitable_state::_S_state_for(__addr);
+ __wait_addr = &__state->_M_ver;
__atomic_load(__wait_addr, &__args._M_old, __args._M_order);
}
else
@@ -380,7 +385,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return __res;
}
- auto __tracker = __waiter_pool_impl::_S_track(__pool, __args, __addr);
+ auto __tracker = __waitable_state::_S_track(__state, __args, __addr);
#ifdef _GLIBCXX_HAVE_PLATFORM_WAIT
__platform_wait(__wait_addr, __args._M_old);
@@ -390,12 +395,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__atomic_load(__wait_addr, &__val, __args._M_order);
if (__val == __args._M_old)
{
- if (!__pool)
- __pool = &__waiter_pool_impl::_S_impl_for(__addr);
- lock_guard<mutex> __l{ __pool->_M_mtx };
+ if (!__state)
+ __state = &__waitable_state::_S_state_for(__addr);
+ lock_guard<mutex> __l{ __state->_M_mtx };
__atomic_load(__wait_addr, &__val, __args._M_order);
if (__val == __args._M_old)
- __pool->_M_cv.wait(__pool->_M_mtx);
+ __state->_M_cv.wait(__state->_M_mtx);
}
return { false, __val };
#endif
@@ -405,15 +410,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__notify_impl(const void* __addr, [[maybe_unused]] bool __all,
const __wait_args_base& __args)
{
- __waiter_pool_impl* __pool = nullptr;
+ __waitable_state* __state = nullptr;
const __platform_wait_t* __wait_addr;
if (__args & __wait_flags::__proxy_wait)
{
- __pool = &__waiter_pool_impl::_S_impl_for(__addr);
+ __state = &__waitable_state::_S_state_for(__addr);
// Waiting for *__addr is actually done on the proxy's _M_ver.
- __wait_addr = &__pool->_M_ver;
- __atomic_fetch_add(&__pool->_M_ver, 1, __ATOMIC_RELAXED);
+ __wait_addr = &__state->_M_ver;
+ __atomic_fetch_add(&__state->_M_ver, 1, __ATOMIC_RELAXED);
// Because the proxy might be shared by several waiters waiting
// on different atomic variables, we need to wake them all so
// they can re-evaluate their conditions to see if they should
@@ -425,19 +430,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
if (__args & __wait_flags::__track_contention)
{
- if (!__pool)
- __pool = &__waiter_pool_impl::_S_impl_for(__addr);
- if (!__pool->_M_waiting())
+ if (!__state)
+ __state = &__waitable_state::_S_state_for(__addr);
+ if (!__state->_M_waiting())
return;
}
#ifdef _GLIBCXX_HAVE_PLATFORM_WAIT
__platform_notify(__wait_addr, __all);
#else
- if (!__pool)
- __pool = &__waiter_pool_impl::_S_impl_for(__addr);
- lock_guard<mutex> __l{ __pool->_M_mtx };
- __pool->_M_cv.notify_all();
+ if (!__state)
+ __state = &__waitable_state::_S_state_for(__addr);
+ lock_guard<mutex> __l{ __state->_M_mtx };
+ __state->_M_cv.notify_all();
#endif
}
} // namespace __detail
diff --git a/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/100334.cc b/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/100334.cc
index ec596e316500..58a0da6e6def 100644
--- a/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/100334.cc
+++ b/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/100334.cc
@@ -47,15 +47,14 @@ int
main()
{
// all atomic share the same waiter
-// atomics_sharing_same_waiter<char> atomics;
atomics_sharing_same_waiter<char> atomics;
for (auto& atom : atomics.a)
{
atom->store(0);
}
- auto a = &std::__detail::__waiter_pool_impl::_S_impl_for(reinterpret_cast<char *>(atomics.a[0]));
- auto b = &std::__detail::__waiter_pool_impl::_S_impl_for(reinterpret_cast<char *>(atomics.a[1]));
+ auto a = &std::__detail::__waitable_state::_S_state_for((void*)(atomics.a[0]));
+ auto b = &std::__detail::__waitable_state::_S_state_for((void*)(atomics.a[1]));
VERIFY( a == b );
auto fut0 = std::async(std::launch::async, [&] { atomics.a[0]->wait(0); });
More information about the Libstdc++-cvs
mailing list