Skip to content

Commit f07d572

Browse files
committed
[libc++] Refactor atomic_wait using lambdas
Now that we've dropped support for older C++ dialects in the synchronization library, we can use lambdas to clarify some of the code used to implement atomic_wait.
1 parent 3ce544e commit f07d572

File tree

3 files changed

+19
-34
lines changed

3 files changed

+19
-34
lines changed

libcxx/include/__atomic/atomic_sync.h

Lines changed: 13 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -57,18 +57,6 @@ struct __atomic_waitable< _Tp,
5757
decltype(__atomic_waitable_traits<__decay_t<_Tp> >::__atomic_contention_address(
5858
std::declval<const _Tp&>()))> > : true_type {};
5959

60-
template <class _AtomicWaitable, class _Poll>
61-
struct __atomic_wait_poll_impl {
62-
const _AtomicWaitable& __a_;
63-
_Poll __poll_;
64-
memory_order __order_;
65-
66-
_LIBCPP_HIDE_FROM_ABI bool operator()() const {
67-
auto __current_val = __atomic_waitable_traits<__decay_t<_AtomicWaitable> >::__atomic_load(__a_, __order_);
68-
return __poll_(__current_val);
69-
}
70-
};
71-
7260
#if _LIBCPP_HAS_THREADS
7361

7462
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void __cxx_atomic_notify_one(void const volatile*) _NOEXCEPT;
@@ -144,11 +132,12 @@ struct __atomic_wait_backoff_impl {
144132
// value. The predicate function must not return `false` spuriously.
145133
template <class _AtomicWaitable, class _Poll>
146134
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void
147-
__atomic_wait_unless(const _AtomicWaitable& __a, _Poll&& __poll, memory_order __order) {
135+
__atomic_wait_unless(const _AtomicWaitable& __a, memory_order __order, _Poll&& __poll) {
148136
static_assert(__atomic_waitable<_AtomicWaitable>::value, "");
149-
__atomic_wait_poll_impl<_AtomicWaitable, __decay_t<_Poll> > __poll_impl = {__a, __poll, __order};
150137
__atomic_wait_backoff_impl<_AtomicWaitable, __decay_t<_Poll> > __backoff_fn = {__a, __poll, __order};
151-
std::__libcpp_thread_poll_with_backoff(__poll_impl, __backoff_fn);
138+
std::__libcpp_thread_poll_with_backoff(
139+
/* poll */ [&]() { return __poll(__atomic_waitable_traits<_AtomicWaitable>::__atomic_load(__a, __order)); },
140+
/* backoff */ __backoff_fn);
152141
}
153142

154143
template <class _AtomicWaitable>
@@ -166,9 +155,10 @@ _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void __atomic_notify_all(const _
166155
#else // _LIBCPP_HAS_THREADS
167156

168157
template <class _AtomicWaitable, class _Poll>
169-
_LIBCPP_HIDE_FROM_ABI void __atomic_wait_unless(const _AtomicWaitable& __a, _Poll&& __poll, memory_order __order) {
170-
__atomic_wait_poll_impl<_AtomicWaitable, __decay_t<_Poll> > __poll_fn = {__a, __poll, __order};
171-
std::__libcpp_thread_poll_with_backoff(__poll_fn, __spinning_backoff_policy());
158+
_LIBCPP_HIDE_FROM_ABI void __atomic_wait_unless(const _AtomicWaitable& __a, memory_order __order, _Poll&& __poll) {
159+
std::__libcpp_thread_poll_with_backoff(
160+
/* poll */ [&]() { return __poll(__atomic_waitable_traits<_AtomicWaitable>::__atomic_load(__a, __order)); },
161+
/* backoff */ __spinning_backoff_policy());
172162
}
173163

174164
template <class _AtomicWaitable>
@@ -184,20 +174,13 @@ _LIBCPP_HIDE_FROM_ABI bool __cxx_nonatomic_compare_equal(_Tp const& __lhs, _Tp c
184174
return std::memcmp(std::addressof(__lhs), std::addressof(__rhs), sizeof(_Tp)) == 0;
185175
}
186176

187-
template <class _Tp>
188-
struct __atomic_compare_unequal_to {
189-
_Tp __val_;
190-
_LIBCPP_HIDE_FROM_ABI bool operator()(const _Tp& __arg) const {
191-
return !std::__cxx_nonatomic_compare_equal(__arg, __val_);
192-
}
193-
};
194-
195-
template <class _AtomicWaitable, class _Up>
177+
template <class _AtomicWaitable, class _Tp>
196178
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void
197-
__atomic_wait(_AtomicWaitable& __a, _Up __val, memory_order __order) {
179+
__atomic_wait(_AtomicWaitable& __a, _Tp __val, memory_order __order) {
198180
static_assert(__atomic_waitable<_AtomicWaitable>::value, "");
199-
__atomic_compare_unequal_to<_Up> __nonatomic_equal = {__val};
200-
std::__atomic_wait_unless(__a, __nonatomic_equal, __order);
181+
std::__atomic_wait_unless(__a, __order, [&](_Tp const& __current) {
182+
return !std::__cxx_nonatomic_compare_equal(__current, __val)
183+
});
201184
}
202185

203186
_LIBCPP_END_NAMESPACE_STD

libcxx/include/latch

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,9 @@ public:
9999
return try_wait_impl(__value);
100100
}
101101
inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void wait() const {
102-
std::__atomic_wait_unless(
103-
__a_, [this](ptrdiff_t& __value) -> bool { return try_wait_impl(__value); }, memory_order_acquire);
102+
std::__atomic_wait_unless(__a_, memory_order_acquire, [this](ptrdiff_t& __value) -> bool {
103+
return try_wait_impl(__value);
104+
});
104105
}
105106
inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void arrive_and_wait(ptrdiff_t __update = 1) {
106107
_LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(__update >= 0, "latch::arrive_and_wait called with a negative value");

libcxx/include/semaphore

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,9 @@ public:
9696
}
9797
}
9898
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void acquire() {
99-
std::__atomic_wait_unless(
100-
__a_, [this](ptrdiff_t& __old) { return __try_acquire_impl(__old); }, memory_order_relaxed);
99+
std::__atomic_wait_unless(__a_, memory_order_relaxed, [this](ptrdiff_t& __old) {
100+
return __try_acquire_impl(__old);
101+
});
101102
}
102103
template <class _Rep, class _Period>
103104
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI bool

0 commit comments

Comments
 (0)