30 #ifndef _GLIBCXX_SEMAPHORE_BASE_H 31 #define _GLIBCXX_SEMAPHORE_BASE_H 1 33 #pragma GCC system_header 36 #if __cpp_lib_atomic_wait 39 #endif // __cpp_lib_atomic_wait 41 #ifdef _GLIBCXX_HAVE_POSIX_SEMAPHORE 43 # include <semaphore.h> 49 namespace std _GLIBCXX_VISIBILITY(default)
51 _GLIBCXX_BEGIN_NAMESPACE_VERSION
53 #ifdef _GLIBCXX_HAVE_POSIX_SEMAPHORE 54 struct __platform_semaphore
56 using __clock_t = chrono::system_clock;
58 static constexpr ptrdiff_t _S_max = SEM_VALUE_MAX;
60 static constexpr ptrdiff_t _S_max = _POSIX_SEM_VALUE_MAX;
63 explicit __platform_semaphore(ptrdiff_t __count) noexcept
65 sem_init(&_M_semaphore, 0, __count);
68 __platform_semaphore(
const __platform_semaphore&) =
delete;
69 __platform_semaphore&
operator=(
const __platform_semaphore&) =
delete;
71 ~__platform_semaphore()
72 { sem_destroy(&_M_semaphore); }
74 _GLIBCXX_ALWAYS_INLINE
void 79 auto __err = sem_wait(&_M_semaphore);
80 if (__err && (errno == EINTR))
89 _GLIBCXX_ALWAYS_INLINE
bool 90 _M_try_acquire() noexcept
94 auto __err = sem_trywait(&_M_semaphore);
95 if (__err && (errno == EINTR))
97 else if (__err && (errno == EAGAIN))
107 _GLIBCXX_ALWAYS_INLINE
void 108 _M_release(std::ptrdiff_t __update) noexcept
110 for(; __update != 0; --__update)
112 auto __err = sem_post(&_M_semaphore);
119 _M_try_acquire_until_impl(
const chrono::time_point<__clock_t>& __atime)
126 struct timespec __ts =
128 static_cast<std::time_t
>(__s.time_since_epoch().count()),
129 static_cast<long>(__ns.count())
134 if (
auto __err = sem_timedwait(&_M_semaphore, &__ts))
138 else if (errno == ETIMEDOUT || errno == EINVAL)
149 template<
typename _Clock,
typename _Duration>
151 _M_try_acquire_until(
const chrono::time_point<_Clock,
152 _Duration>& __atime) noexcept
154 if constexpr (std::is_same_v<__clock_t, _Clock>)
156 return _M_try_acquire_until_impl(__atime);
160 const typename _Clock::time_point __c_entry = _Clock::now();
161 const auto __s_entry = __clock_t::now();
162 const auto __delta = __atime - __c_entry;
163 const auto __s_atime = __s_entry + __delta;
164 if (_M_try_acquire_until_impl(__s_atime))
170 return (_Clock::now() < __atime);
174 template<
typename _Rep,
typename _Period>
175 _GLIBCXX_ALWAYS_INLINE
bool 176 _M_try_acquire_for(
const chrono::duration<_Rep, _Period>& __rtime)
178 {
return _M_try_acquire_until(__clock_t::now() + __rtime); }
183 #endif // _GLIBCXX_HAVE_POSIX_SEMAPHORE 185 #if __cpp_lib_atomic_wait 186 struct __atomic_semaphore
189 explicit __atomic_semaphore(__detail::__platform_wait_t __count) noexcept
190 : _M_counter(__count)
192 __glibcxx_assert(__count >= 0 && __count <= _S_max);
195 __atomic_semaphore(
const __atomic_semaphore&) =
delete;
196 __atomic_semaphore&
operator=(
const __atomic_semaphore&) =
delete;
198 static _GLIBCXX_ALWAYS_INLINE
bool 199 _S_do_try_acquire(__detail::__platform_wait_t* __counter) noexcept
201 auto __old = __atomic_impl::load(__counter, memory_order::acquire);
205 return __atomic_impl::compare_exchange_strong(__counter,
207 memory_order::acquire,
208 memory_order::relaxed);
211 _GLIBCXX_ALWAYS_INLINE
void 212 _M_acquire() noexcept
215 [
this] {
return _S_do_try_acquire(&this->_M_counter); };
216 std::__atomic_wait_address_bare(&_M_counter, __pred);
220 _M_try_acquire() noexcept
223 [
this] {
return _S_do_try_acquire(&this->_M_counter); };
224 return std::__detail::__atomic_spin(__pred);
227 template<
typename _Clock,
typename _Duration>
228 _GLIBCXX_ALWAYS_INLINE
bool 229 _M_try_acquire_until(
const chrono::time_point<_Clock,
230 _Duration>& __atime) noexcept
233 [
this] {
return _S_do_try_acquire(&this->_M_counter); };
235 return __atomic_wait_address_until_bare(&_M_counter, __pred, __atime);
238 template<
typename _Rep,
typename _Period>
239 _GLIBCXX_ALWAYS_INLINE
bool 240 _M_try_acquire_for(
const chrono::duration<_Rep, _Period>& __rtime)
244 [
this] {
return _S_do_try_acquire(&this->_M_counter); };
246 return __atomic_wait_address_for_bare(&_M_counter, __pred, __rtime);
249 _GLIBCXX_ALWAYS_INLINE
void 250 _M_release(ptrdiff_t __update) noexcept
252 if (0 < __atomic_impl::fetch_add(&_M_counter, __update, memory_order_release))
255 __atomic_notify_address_bare(&_M_counter,
true);
257 __atomic_notify_address_bare(&_M_counter,
true);
263 alignas(__detail::__platform_wait_alignment)
264 __detail::__platform_wait_t _M_counter;
266 #endif // __cpp_lib_atomic_wait 270 #if defined __cpp_lib_atomic_wait && !_GLIBCXX_USE_POSIX_SEMAPHORE 271 using __semaphore_impl = __atomic_semaphore;
272 #elif _GLIBCXX_HAVE_POSIX_SEMAPHORE 273 using __semaphore_impl = __platform_semaphore;
276 _GLIBCXX_END_NAMESPACE_VERSION
278 #endif // _GLIBCXX_SEMAPHORE_BASE_H __numeric_traits_integer< _Tp > __int_traits
Convenience alias for __numeric_traits<integer-type>.
constexpr enable_if< __is_duration< _ToDur >::value, time_point< _Clock, _ToDur > >::type time_point_cast(const time_point< _Clock, _Dur > &__t)
time_point_cast
duration< int64_t > seconds
seconds
duration< int64_t, nano > nanoseconds
nanoseconds
ISO C++ entities toplevel namespace is std.
auto_ptr & operator=(auto_ptr &__a)
auto_ptr assignment operator.
constexpr __enable_if_is_duration< _ToDur > duration_cast(const duration< _Rep, _Period > &__d)
duration_cast
void terminate() noexcept