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 return _M_try_acquire_for(__detail::__wait_clock_t::duration{});
107 template<
typename _Clock,
typename _Duration>
109 _M_try_acquire_until(
const chrono::time_point<_Clock, _Duration>& __atime)
noexcept
111 auto __vfn = [
this]{
return _M_get_current(); };
112 _Available __is_available{__vfn()};
113 while (!_M_do_try_acquire(__is_available._M_val))
114 if (!__is_available())
115 if (!std::__atomic_wait_address_until(&_M_counter, __is_available,
116 __vfn, __atime,
true))
121 template<
typename _Rep,
typename _Period>
123 _M_try_acquire_for(
const chrono::duration<_Rep, _Period>& __rtime)
noexcept
125 auto __vfn = [
this]{
return _M_get_current(); };
126 _Available __is_available{__vfn()};
127 while (!_M_do_try_acquire(__is_available._M_val))
128 if (!__is_available())
129 if (!std::__atomic_wait_address_for(&_M_counter, __is_available,
130 __vfn, __rtime,
true))
135 _GLIBCXX_ALWAYS_INLINE ptrdiff_t
136 _M_release(ptrdiff_t __update)
noexcept
138 auto __old = __atomic_impl::fetch_add(&_M_counter, __update,
139 memory_order::release);
140 if (__old == 0 && __update > 0)
141 __atomic_notify_address(&_M_counter,
true,
true);
152 bool operator()() const noexcept {
return _M_val > 0; }
157 bool operator()(__count_type __cur)
noexcept
166 alignas(__atomic_ref<__count_type>::required_alignment)
167 __count_type _M_counter;
171 template<
bool _Binary>
172 struct __platform_semaphore_impl
174 using __count_type = __detail::__platform_wait_t;
176 static consteval ptrdiff_t
181 else if ((ptrdiff_t)__gnu_cxx::__int_traits<__count_type>::__max < 0)
182 return __gnu_cxx::__int_traits<ptrdiff_t>::__max;
184 return __gnu_cxx::__int_traits<__count_type>::__max;
187 static constexpr ptrdiff_t _S_max = _S_calc_max();
190 __platform_semaphore_impl(__count_type __count) noexcept
191 : _M_counter(__count)
194 __platform_semaphore_impl(__platform_semaphore_impl&) =
delete;
195 __platform_semaphore_impl& operator=(
const __platform_semaphore_impl&) =
delete;
198 _GLIBCXX_ALWAYS_INLINE __count_type
199 _M_get_current() const noexcept
201 if constexpr (_Binary)
204 return __atomic_impl::load(&_M_counter, memory_order::acquire);
211 _GLIBCXX_ALWAYS_INLINE
bool
212 _M_do_try_acquire(__count_type& __cur)
noexcept
217 return __atomic_impl::compare_exchange_strong(&_M_counter,
219 memory_order::acquire,
220 memory_order::relaxed);
225 _M_acquire() noexcept
227 auto __val = _M_get_current();
228 while (!_M_do_try_acquire(__val))
231 std::__atomic_wait_address_v(&_M_counter, __val, __ATOMIC_ACQUIRE,
233 __val = _M_get_current();
239 _M_try_acquire() noexcept
241 if constexpr (_Binary)
243 __count_type __val = 1;
245 return _M_do_try_acquire(__val);
251 return _M_try_acquire_for(__detail::__wait_clock_t::duration{});
254 template<
typename _Clock,
typename _Duration>
256 _M_try_acquire_until(
const chrono::time_point<_Clock, _Duration>& __atime)
noexcept
258 auto __val = _M_get_current();
259 while (!_M_do_try_acquire(__val))
262 if (!std::__atomic_wait_address_until_v(&_M_counter, 0,
266 __val = _M_get_current();
271 template<
typename _Rep,
typename _Period>
273 _M_try_acquire_for(
const chrono::duration<_Rep, _Period>& __rtime)
noexcept
275 auto __val = _M_get_current();
276 while (!_M_do_try_acquire(__val))
279 if (!std::__atomic_wait_address_for_v(&_M_counter, 0,
283 __val = _M_get_current();
288 _GLIBCXX_ALWAYS_INLINE ptrdiff_t
289 _M_release(ptrdiff_t __update)
noexcept
291 auto __old = __atomic_impl::fetch_add(&_M_counter, __update,
292 memory_order::release);
293 if (__old == 0 && __update > 0)
294 __atomic_notify_address(&_M_counter,
true,
true);
299 alignas(__detail::__platform_wait_alignment) __count_type _M_counter;
302 template<ptrdiff_t _Max,
typename _Tp = __detail::__platform_wait_t>
303 using _Semaphore_impl
304 = __conditional_t<__platform_wait_uses_type<_Tp>
305 && _Max <= __gnu_cxx::__int_traits<_Tp>::__max,
306 __platform_semaphore_impl<(_Max <= 1)>,
309_GLIBCXX_END_NAMESPACE_VERSION
ISO C++ entities toplevel namespace is std.