30#ifndef _GLIBCXX_SEMAPHORE_BASE_H
31#define _GLIBCXX_SEMAPHORE_BASE_H 1
34#pragma GCC system_header
39#if __glibcxx_atomic_wait
44#ifdef _GLIBCXX_HAVE_POSIX_SEMAPHORE
47# include <semaphore.h>
48#elif defined(_GLIBCXX_USE_POSIX_SEMAPHORE)
49# warning "POSIX semaphore not available, ignoring _GLIBCXX_USE_POSIX_SEMAPHORE"
50# undef _GLIBCXX_USE_POSIX_SEMAPHORE
53namespace std _GLIBCXX_VISIBILITY(default)
55_GLIBCXX_BEGIN_NAMESPACE_VERSION
57#ifdef _GLIBCXX_HAVE_POSIX_SEMAPHORE
58 struct __platform_semaphore
60 using __clock_t = chrono::system_clock;
62 static constexpr ptrdiff_t _S_max = SEM_VALUE_MAX;
64 static constexpr ptrdiff_t _S_max = _POSIX_SEM_VALUE_MAX;
67 explicit __platform_semaphore(ptrdiff_t __count)
noexcept
69 sem_init(&_M_semaphore, 0, __count);
72 __platform_semaphore(
const __platform_semaphore&) =
delete;
73 __platform_semaphore& operator=(
const __platform_semaphore&) =
delete;
75 ~__platform_semaphore()
76 { sem_destroy(&_M_semaphore); }
78 _GLIBCXX_ALWAYS_INLINE
void
81 while (sem_wait(&_M_semaphore))
86 _GLIBCXX_ALWAYS_INLINE
bool
87 _M_try_acquire() noexcept
89 while (sem_trywait(&_M_semaphore))
93 else if (errno != EINTR)
100 _GLIBCXX_ALWAYS_INLINE
void
101 _M_release(ptrdiff_t __update)
noexcept
103 for(; __update != 0; --__update)
104 if (sem_post(&_M_semaphore))
109 _M_try_acquire_until_impl(
const chrono::time_point<__clock_t>& __atime)
115 struct timespec __ts =
117 static_cast<std::time_t
>(__s.time_since_epoch().count()),
118 static_cast<long>(__ns.count())
121 while (sem_timedwait(&_M_semaphore, &__ts))
123 if (errno == ETIMEDOUT)
125 else if (errno != EINTR)
131 template<
typename _Clock,
typename _Duration>
133 _M_try_acquire_until(
const chrono::time_point<_Clock,
134 _Duration>& __atime)
noexcept
136 if constexpr (std::is_same_v<__clock_t, _Clock>)
138 using _Dur = __clock_t::duration;
146 const typename _Clock::time_point __c_entry = _Clock::now();
147 const auto __s_entry = __clock_t::now();
148 const auto __delta = __atime - __c_entry;
149 const auto __s_atime = __s_entry + __delta;
150 if (_M_try_acquire_until_impl(__s_atime))
156 return (_Clock::now() < __atime);
160 template<
typename _Rep,
typename _Period>
161 _GLIBCXX_ALWAYS_INLINE
bool
162 _M_try_acquire_for(
const chrono::duration<_Rep, _Period>& __rtime)
164 {
return _M_try_acquire_until(__clock_t::now() + __rtime); }
171#if __glibcxx_atomic_wait
172 struct __atomic_semaphore
174 static constexpr ptrdiff_t _S_max = __gnu_cxx::__int_traits<int>::__max;
175 explicit __atomic_semaphore(__detail::__platform_wait_t __count) noexcept
176 : _M_counter(__count)
178 __glibcxx_assert(__count >= 0 && __count <= _S_max);
181 __atomic_semaphore(
const __atomic_semaphore&) =
delete;
182 __atomic_semaphore& operator=(
const __atomic_semaphore&) =
delete;
184 static _GLIBCXX_ALWAYS_INLINE
bool
185 _S_do_try_acquire(__detail::__platform_wait_t* __counter)
noexcept
187 auto __old = __atomic_impl::load(__counter, memory_order::acquire);
191 return __atomic_impl::compare_exchange_strong(__counter,
193 memory_order::acquire,
194 memory_order::relaxed);
197 _GLIBCXX_ALWAYS_INLINE
void
198 _M_acquire() noexcept
201 [
this] {
return _S_do_try_acquire(&this->_M_counter); };
202 std::__atomic_wait_address_bare(&_M_counter, __pred);
206 _M_try_acquire() noexcept
209 [
this] {
return _S_do_try_acquire(&this->_M_counter); };
210 return std::__detail::__atomic_spin(__pred);
213 template<
typename _Clock,
typename _Duration>
214 _GLIBCXX_ALWAYS_INLINE
bool
215 _M_try_acquire_until(
const chrono::time_point<_Clock,
216 _Duration>& __atime)
noexcept
219 [
this] {
return _S_do_try_acquire(&this->_M_counter); };
221 return __atomic_wait_address_until_bare(&_M_counter, __pred, __atime);
224 template<
typename _Rep,
typename _Period>
225 _GLIBCXX_ALWAYS_INLINE
bool
226 _M_try_acquire_for(
const chrono::duration<_Rep, _Period>& __rtime)
230 [
this] {
return _S_do_try_acquire(&this->_M_counter); };
232 return __atomic_wait_address_for_bare(&_M_counter, __pred, __rtime);
235 _GLIBCXX_ALWAYS_INLINE
void
236 _M_release(ptrdiff_t __update)
noexcept
238 if (0 < __atomic_impl::fetch_add(&_M_counter, __update, memory_order_release))
241 __atomic_notify_address_bare(&_M_counter,
true);
243 __atomic_notify_address_bare(&_M_counter,
true);
249 alignas(__detail::__platform_wait_alignment)
250 __detail::__platform_wait_t _M_counter;
256#if defined __glibcxx_atomic_wait && !_GLIBCXX_USE_POSIX_SEMAPHORE
257 using __semaphore_impl = __atomic_semaphore;
258#elif _GLIBCXX_HAVE_POSIX_SEMAPHORE
259 using __semaphore_impl = __platform_semaphore;
262_GLIBCXX_END_NAMESPACE_VERSION
constexpr __enable_if_t< __is_duration< _ToDur >::value, time_point< _Clock, _ToDur > > time_point_cast(const time_point< _Clock, _Dur > &__t)
constexpr __enable_if_is_duration< _ToDur > ceil(const duration< _Rep, _Period > &__d)
constexpr __enable_if_is_duration< _ToDur > duration_cast(const duration< _Rep, _Period > &__d)
ISO C++ entities toplevel namespace is std.