30#ifndef _GLIBCXX_SEMAPHORE_BASE_H
31#define _GLIBCXX_SEMAPHORE_BASE_H 1
34#pragma GCC system_header
39#ifdef __glibcxx_semaphore
45namespace std _GLIBCXX_VISIBILITY(default)
47_GLIBCXX_BEGIN_NAMESPACE_VERSION
49 struct __semaphore_impl
51 using __count_type = ptrdiff_t;
53 static constexpr ptrdiff_t _S_max
54 = __gnu_cxx::__int_traits<__count_type>::__max;
57 __semaphore_impl(__count_type __count) noexcept
61 __semaphore_impl(
const __semaphore_impl&) =
delete;
62 __semaphore_impl& operator=(
const __semaphore_impl&) =
delete;
65 _GLIBCXX_ALWAYS_INLINE __count_type
66 _M_get_current() const noexcept
67 {
return __atomic_impl::load(&_M_counter, memory_order::acquire); }
73 _GLIBCXX_ALWAYS_INLINE
bool
74 _M_do_try_acquire(__count_type& __cur)
noexcept
79 return __atomic_impl::compare_exchange_strong(&_M_counter,
81 memory_order::acquire,
82 memory_order::relaxed);
89 auto __vfn = [
this]{
return _M_get_current(); };
90 _Available __is_available{__vfn()};
91 while (!_M_do_try_acquire(__is_available._M_val))
92 if (!__is_available())
93 std::__atomic_wait_address(&_M_counter, __is_available, __vfn,
true);
99 _M_try_acquire() noexcept
104 auto __vfn = [
this]{
return _M_get_current(); };
105 _Available __is_available{__vfn()};
108 for (
int __i = 0; __i < 10 && __is_available(); ++__i)
109 if (_M_do_try_acquire(__is_available._M_val))
113 constexpr auto __zero = __detail::__wait_clock_t::duration{};
114 if (std::__atomic_wait_address_for(&_M_counter, __is_available,
115 __vfn, __zero,
true))
119 return _M_do_try_acquire(__is_available._M_val);
122 template<
typename _Clock,
typename _Duration>
124 _M_try_acquire_until(
const chrono::time_point<_Clock, _Duration>& __atime)
noexcept
126 auto __vfn = [
this]{
return _M_get_current(); };
127 _Available __is_available{__vfn()};
128 while (!_M_do_try_acquire(__is_available._M_val))
129 if (!__is_available())
130 if (!std::__atomic_wait_address_until(&_M_counter, __is_available,
131 __vfn, __atime,
true))
136 template<
typename _Rep,
typename _Period>
138 _M_try_acquire_for(
const chrono::duration<_Rep, _Period>& __rtime)
noexcept
140 return _M_try_acquire_until(__detail::__wait_clock_t::now() + __rtime);
143 _GLIBCXX_ALWAYS_INLINE ptrdiff_t
144 _M_release(ptrdiff_t __update)
noexcept
146 auto __old = __atomic_impl::fetch_add(&_M_counter, __update,
147 memory_order::release);
148 if (__old == 0 && __update > 0)
149 __atomic_notify_address(&_M_counter,
true,
true);
160 bool operator()() const noexcept {
return _M_val > 0; }
165 bool operator()(__count_type __cur)
noexcept
174 alignas(__atomic_ref<__count_type>::required_alignment)
175 __count_type _M_counter;
179 template<
bool _Binary>
180 struct __platform_semaphore_impl
182 using __count_type = __detail::__platform_wait_t;
184 static consteval ptrdiff_t
189 else if ((ptrdiff_t)__gnu_cxx::__int_traits<__count_type>::__max < 0)
190 return __gnu_cxx::__int_traits<ptrdiff_t>::__max;
192 return __gnu_cxx::__int_traits<__count_type>::__max;
195 static constexpr ptrdiff_t _S_max = _S_calc_max();
198 __platform_semaphore_impl(__count_type __count) noexcept
199 : _M_counter(__count)
202 __platform_semaphore_impl(__platform_semaphore_impl&) =
delete;
203 __platform_semaphore_impl& operator=(
const __platform_semaphore_impl&) =
delete;
206 _GLIBCXX_ALWAYS_INLINE __count_type
207 _M_get_current() const noexcept
209 if constexpr (_Binary)
212 return __atomic_impl::load(&_M_counter, memory_order::acquire);
219 _GLIBCXX_ALWAYS_INLINE
bool
220 _M_do_try_acquire(__count_type& __cur)
noexcept
225 return __atomic_impl::compare_exchange_strong(&_M_counter,
227 memory_order::acquire,
228 memory_order::relaxed);
233 _M_acquire() noexcept
235 auto __val = _M_get_current();
236 while (!_M_do_try_acquire(__val))
239 std::__atomic_wait_address_v(&_M_counter, __val, __ATOMIC_ACQUIRE,
241 __val = _M_get_current();
247 _M_try_acquire() noexcept
249 if constexpr (_Binary)
251 __count_type __val = 1;
253 return _M_do_try_acquire(__val);
259 return _M_try_acquire_for(__detail::__wait_clock_t::duration{});
262 template<
typename _Clock,
typename _Duration>
264 _M_try_acquire_until(
const chrono::time_point<_Clock, _Duration>& __atime)
noexcept
266 auto __val = _M_get_current();
267 while (!_M_do_try_acquire(__val))
270 if (!std::__atomic_wait_address_until_v(&_M_counter, 0,
274 __val = _M_get_current();
279 template<
typename _Rep,
typename _Period>
281 _M_try_acquire_for(
const chrono::duration<_Rep, _Period>& __rtime)
noexcept
283 auto __val = _M_get_current();
284 while (!_M_do_try_acquire(__val))
287 if (!std::__atomic_wait_address_for_v(&_M_counter, 0,
291 __val = _M_get_current();
296 _GLIBCXX_ALWAYS_INLINE ptrdiff_t
297 _M_release(ptrdiff_t __update)
noexcept
299 auto __old = __atomic_impl::fetch_add(&_M_counter, __update,
300 memory_order::release);
301 if (__old == 0 && __update > 0)
302 __atomic_notify_address(&_M_counter,
true,
true);
307 alignas(__detail::__platform_wait_alignment) __count_type _M_counter;
310 template<ptrdiff_t _Max,
typename _Tp = __detail::__platform_wait_t>
311 using _Semaphore_impl
312 = __conditional_t<__platform_wait_uses_type<_Tp>
313 && _Max <= __gnu_cxx::__int_traits<_Tp>::__max,
314 __platform_semaphore_impl<(_Max <= 1)>,
317_GLIBCXX_END_NAMESPACE_VERSION
ISO C++ entities toplevel namespace is std.