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 constexpr ptrdiff_t _S_max
177 = _Binary ? 1 : __gnu_cxx::__int_traits<__count_type>::__max;
180 __platform_semaphore_impl(__count_type __count) noexcept
181 : _M_counter(__count)
184 __platform_semaphore_impl(__platform_semaphore_impl&) =
delete;
185 __platform_semaphore_impl& operator=(
const __platform_semaphore_impl&) =
delete;
188 _GLIBCXX_ALWAYS_INLINE __count_type
189 _M_get_current() const noexcept
191 if constexpr (_Binary)
194 return __atomic_impl::load(&_M_counter, memory_order::acquire);
201 _GLIBCXX_ALWAYS_INLINE
bool
202 _M_do_try_acquire(__count_type& __cur)
noexcept
207 return __atomic_impl::compare_exchange_strong(&_M_counter,
209 memory_order::acquire,
210 memory_order::relaxed);
215 _M_acquire() noexcept
217 auto __val = _M_get_current();
218 while (!_M_do_try_acquire(__val))
221 std::__atomic_wait_address_v(&_M_counter, __val, __ATOMIC_ACQUIRE,
223 __val = _M_get_current();
229 _M_try_acquire() noexcept
231 if constexpr (_Binary)
233 __count_type __val = 1;
235 return _M_do_try_acquire(__val);
241 return _M_try_acquire_for(__detail::__wait_clock_t::duration{});
244 template<
typename _Clock,
typename _Duration>
246 _M_try_acquire_until(
const chrono::time_point<_Clock, _Duration>& __atime)
noexcept
248 auto __val = _M_get_current();
249 while (!_M_do_try_acquire(__val))
252 if (!std::__atomic_wait_address_until_v(&_M_counter, 0,
256 __val = _M_get_current();
261 template<
typename _Rep,
typename _Period>
263 _M_try_acquire_for(
const chrono::duration<_Rep, _Period>& __rtime)
noexcept
265 auto __val = _M_get_current();
266 while (!_M_do_try_acquire(__val))
269 if (!std::__atomic_wait_address_for_v(&_M_counter, 0,
273 __val = _M_get_current();
278 _GLIBCXX_ALWAYS_INLINE ptrdiff_t
279 _M_release(ptrdiff_t __update)
noexcept
281 auto __old = __atomic_impl::fetch_add(&_M_counter, __update,
282 memory_order::release);
283 if (__old == 0 && __update > 0)
284 __atomic_notify_address(&_M_counter,
true,
true);
289 alignas(__detail::__platform_wait_alignment) __count_type _M_counter;
292 template<ptrdiff_t _Max,
typename _Tp = __detail::__platform_wait_t>
293 using _Semaphore_impl
294 = __conditional_t<__platform_wait_uses_type<_Tp>
295 && _Max <= __gnu_cxx::__int_traits<_Tp>::__max,
296 __platform_semaphore_impl<(_Max <= 1)>,
299_GLIBCXX_END_NAMESPACE_VERSION
ISO C++ entities toplevel namespace is std.