30#ifndef _GLIBCXX_SEMAPHORE_BASE_H
31#define _GLIBCXX_SEMAPHORE_BASE_H 1
33#pragma GCC system_header
37#if __cpp_lib_atomic_wait
42#ifdef _GLIBCXX_HAVE_POSIX_SEMAPHORE
45# include <semaphore.h>
48namespace std _GLIBCXX_VISIBILITY(default)
50_GLIBCXX_BEGIN_NAMESPACE_VERSION
52#ifdef _GLIBCXX_HAVE_POSIX_SEMAPHORE
53 struct __platform_semaphore
55 using __clock_t = chrono::system_clock;
57 static constexpr ptrdiff_t _S_max = SEM_VALUE_MAX;
59 static constexpr ptrdiff_t _S_max = _POSIX_SEM_VALUE_MAX;
62 explicit __platform_semaphore(ptrdiff_t __count)
noexcept
64 sem_init(&_M_semaphore, 0, __count);
67 __platform_semaphore(
const __platform_semaphore&) =
delete;
68 __platform_semaphore& operator=(
const __platform_semaphore&) =
delete;
70 ~__platform_semaphore()
71 { sem_destroy(&_M_semaphore); }
73 _GLIBCXX_ALWAYS_INLINE
void
78 auto __err = sem_wait(&_M_semaphore);
79 if (__err && (errno == EINTR))
88 _GLIBCXX_ALWAYS_INLINE
bool
89 _M_try_acquire() noexcept
93 auto __err = sem_trywait(&_M_semaphore);
94 if (__err && (errno == EINTR))
96 else if (__err && (errno == EAGAIN))
106 _GLIBCXX_ALWAYS_INLINE
void
107 _M_release(std::ptrdiff_t __update)
noexcept
109 for(; __update != 0; --__update)
111 auto __err = sem_post(&_M_semaphore);
118 _M_try_acquire_until_impl(
const chrono::time_point<__clock_t>& __atime)
122 auto __s = chrono::time_point_cast<chrono::seconds>(__atime);
123 auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
125 struct timespec __ts =
127 static_cast<std::time_t
>(__s.time_since_epoch().count()),
128 static_cast<long>(__ns.count())
133 if (
auto __err = sem_timedwait(&_M_semaphore, &__ts))
137 else if (errno == ETIMEDOUT || errno == EINVAL)
148 template<
typename _Clock,
typename _Duration>
150 _M_try_acquire_until(
const chrono::time_point<_Clock,
151 _Duration>& __atime)
noexcept
153 if constexpr (std::is_same_v<__clock_t, _Clock>)
155 return _M_try_acquire_until_impl(__atime);
159 const typename _Clock::time_point __c_entry = _Clock::now();
160 const auto __s_entry = __clock_t::now();
161 const auto __delta = __atime - __c_entry;
162 const auto __s_atime = __s_entry + __delta;
163 if (_M_try_acquire_until_impl(__s_atime))
169 return (_Clock::now() < __atime);
173 template<
typename _Rep,
typename _Period>
174 _GLIBCXX_ALWAYS_INLINE
bool
175 _M_try_acquire_for(
const chrono::duration<_Rep, _Period>& __rtime)
177 {
return _M_try_acquire_until(__clock_t::now() + __rtime); }
184#if __cpp_lib_atomic_wait
185 struct __atomic_semaphore
188 explicit __atomic_semaphore(__detail::__platform_wait_t __count) noexcept
189 : _M_counter(__count)
191 __glibcxx_assert(__count >= 0 && __count <= _S_max);
194 __atomic_semaphore(
const __atomic_semaphore&) =
delete;
195 __atomic_semaphore& operator=(
const __atomic_semaphore&) =
delete;
197 static _GLIBCXX_ALWAYS_INLINE
bool
198 _S_do_try_acquire(__detail::__platform_wait_t* __counter)
noexcept
200 auto __old = __atomic_impl::load(__counter, memory_order::acquire);
204 return __atomic_impl::compare_exchange_strong(__counter,
206 memory_order::acquire,
207 memory_order::relaxed);
210 _GLIBCXX_ALWAYS_INLINE
void
211 _M_acquire() noexcept
214 [
this] {
return _S_do_try_acquire(&this->_M_counter); };
215 std::__atomic_wait_address_bare(&_M_counter, __pred);
219 _M_try_acquire() noexcept
222 [
this] {
return _S_do_try_acquire(&this->_M_counter); };
223 return std::__detail::__atomic_spin(__pred);
226 template<
typename _Clock,
typename _Duration>
227 _GLIBCXX_ALWAYS_INLINE
bool
228 _M_try_acquire_until(
const chrono::time_point<_Clock,
229 _Duration>& __atime)
noexcept
232 [
this] {
return _S_do_try_acquire(&this->_M_counter); };
234 return __atomic_wait_address_until_bare(&_M_counter, __pred, __atime);
237 template<
typename _Rep,
typename _Period>
238 _GLIBCXX_ALWAYS_INLINE
bool
239 _M_try_acquire_for(
const chrono::duration<_Rep, _Period>& __rtime)
243 [
this] {
return _S_do_try_acquire(&this->_M_counter); };
245 return __atomic_wait_address_for_bare(&_M_counter, __pred, __rtime);
248 _GLIBCXX_ALWAYS_INLINE
void
249 _M_release(ptrdiff_t __update)
noexcept
251 if (0 < __atomic_impl::fetch_add(&_M_counter, __update, memory_order_release))
254 __atomic_notify_address_bare(&_M_counter,
true);
256 __atomic_notify_address_bare(&_M_counter,
true);
262 alignas(__detail::__platform_wait_alignment)
263 __detail::__platform_wait_t _M_counter;
269#if defined __cpp_lib_atomic_wait && !_GLIBCXX_USE_POSIX_SEMAPHORE
270 using __semaphore_impl = __atomic_semaphore;
271#elif _GLIBCXX_HAVE_POSIX_SEMAPHORE
272 using __semaphore_impl = __platform_semaphore;
275_GLIBCXX_END_NAMESPACE_VERSION
ISO C++ entities toplevel namespace is std.
__numeric_traits_integer< _Tp > __int_traits
Convenience alias for __numeric_traits<integer-type>.