libstdc++: make atomic waiting depend on gthreads or futexes
libstdc++-v3/ChangeLog: * include/bits/atomic_wait.h: Do not define anything unless gthreads or futexes are available. * include/bits/atomic_timed_wait.h: Likewise. * include/bits/semaphore_base.h: Likewise. * include/std/semaphore: Likewise. * include/bits/atomic_base.h (atomic_flag::wait) (atomic_flag::notify_one, atomic_flag::notify_all) (__atomic_base<I>::wait, __atomic_base<I>::notify_one) (__atomic_base<I>::notify_all, __atomic_base<P*>::wait) (__atomic_base<P*>::notify_one, __atomic_base<P*>::notify_all) (__atomic_impl::wait, __atomic_impl::notify_one) (__atomic_impl::notify_all, __atomic_float::wait) (__atomic_float::notify_one, __atomic_float::notify_all) (__atomic_ref::wait, __atomic_ref::notify_one) (__atomic_ref::notify_all): Only define if gthreads or futexes are available. * include/std/atomic (atomic::wait, atomic::notify_one) (atomic::notify_all): Likewise. * include/std/version (__cpp_lib_semaphore): Define conditionally.
This commit is contained in:
parent
bcbde431aa
commit
183ae52b22
7 changed files with 111 additions and 74 deletions
|
@ -230,6 +230,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
return __v == __GCC_ATOMIC_TEST_AND_SET_TRUEVAL;
|
||||
}
|
||||
|
||||
#if defined _GLIBCXX_HAS_GTHREADS || _GLIBCXX_HAVE_LINUX_FUTEX
|
||||
_GLIBCXX_ALWAYS_INLINE void
|
||||
wait(bool __old,
|
||||
memory_order __m = memory_order_seq_cst) const noexcept
|
||||
|
@ -252,6 +253,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
{ std::__atomic_notify(&_M_i, true); }
|
||||
|
||||
// TODO add const volatile overload
|
||||
#endif // GTHREADS || LINUX_FUTEX
|
||||
#endif // C++20
|
||||
|
||||
_GLIBCXX_ALWAYS_INLINE void
|
||||
|
@ -603,6 +605,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
}
|
||||
|
||||
#if __cplusplus > 201703L
|
||||
#if defined _GLIBCXX_HAS_GTHREADS || _GLIBCXX_HAVE_LINUX_FUTEX
|
||||
_GLIBCXX_ALWAYS_INLINE void
|
||||
wait(__int_type __old,
|
||||
memory_order __m = memory_order_seq_cst) const noexcept
|
||||
|
@ -625,6 +628,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
{ std::__atomic_notify(&_M_i, true); }
|
||||
|
||||
// TODO add const volatile overload
|
||||
#endif // GTHREADS || LINUX_FUTEX
|
||||
#endif // C++2a
|
||||
|
||||
_GLIBCXX_ALWAYS_INLINE __int_type
|
||||
|
@ -897,6 +901,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
}
|
||||
|
||||
#if __cplusplus > 201703L
|
||||
#if defined _GLIBCXX_HAS_GTHREADS || _GLIBCXX_HAVE_LINUX_FUTEX
|
||||
_GLIBCXX_ALWAYS_INLINE void
|
||||
wait(__pointer_type __old,
|
||||
memory_order __m = memory_order_seq_cst) noexcept
|
||||
|
@ -919,6 +924,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
{ std::__atomic_notify(&_M_p, true); }
|
||||
|
||||
// TODO add const volatile overload
|
||||
#endif // GTHREADS || LINUX_FUTEX
|
||||
#endif // C++2a
|
||||
|
||||
_GLIBCXX_ALWAYS_INLINE __pointer_type
|
||||
|
@ -1010,6 +1016,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
}
|
||||
|
||||
#if __cplusplus > 201703L
|
||||
#if defined _GLIBCXX_HAS_GTHREADS || _GLIBCXX_HAVE_LINUX_FUTEX
|
||||
template<typename _Tp>
|
||||
_GLIBCXX_ALWAYS_INLINE void
|
||||
wait(const _Tp* __ptr, _Val<_Tp> __old,
|
||||
|
@ -1034,6 +1041,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
{ std::__atomic_notify(__ptr, true); }
|
||||
|
||||
// TODO add const volatile overload
|
||||
#endif // GTHREADS || LINUX_FUTEX
|
||||
#endif // C++2a
|
||||
|
||||
template<typename _Tp>
|
||||
|
@ -1289,6 +1297,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
__cmpexch_failure_order(__order));
|
||||
}
|
||||
|
||||
#if defined _GLIBCXX_HAS_GTHREADS || _GLIBCXX_HAVE_LINUX_FUTEX
|
||||
_GLIBCXX_ALWAYS_INLINE void
|
||||
wait(_Fp __old, memory_order __m = memory_order_seq_cst) const noexcept
|
||||
{ __atomic_impl::wait(&_M_fp, __old, __m); }
|
||||
|
@ -1306,6 +1315,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
{ __atomic_impl::notify_all(&_M_fp); }
|
||||
|
||||
// TODO add const volatile overload
|
||||
#endif // GTHREADS || LINUX_FUTEX
|
||||
|
||||
value_type
|
||||
fetch_add(value_type __i,
|
||||
|
@ -1444,6 +1454,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
__cmpexch_failure_order(__order));
|
||||
}
|
||||
|
||||
#if defined _GLIBCXX_HAS_GTHREADS || _GLIBCXX_HAVE_LINUX_FUTEX
|
||||
_GLIBCXX_ALWAYS_INLINE void
|
||||
wait(_Tp __old, memory_order __m = memory_order_seq_cst) const noexcept
|
||||
{ __atomic_impl::wait(_M_ptr, __old, __m); }
|
||||
|
@ -1461,6 +1472,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
{ __atomic_impl::notify_all(_M_ptr); }
|
||||
|
||||
// TODO add const volatile overload
|
||||
#endif // GTHREADS || LINUX_FUTEX
|
||||
|
||||
private:
|
||||
_Tp* _M_ptr;
|
||||
|
@ -1557,6 +1569,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
__cmpexch_failure_order(__order));
|
||||
}
|
||||
|
||||
#if defined _GLIBCXX_HAS_GTHREADS || _GLIBCXX_HAVE_LINUX_FUTEX
|
||||
_GLIBCXX_ALWAYS_INLINE void
|
||||
wait(_Tp __old, memory_order __m = memory_order_seq_cst) const noexcept
|
||||
{ __atomic_impl::wait(_M_ptr, __old, __m); }
|
||||
|
@ -1574,6 +1587,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
{ __atomic_impl::notify_all(_M_ptr); }
|
||||
|
||||
// TODO add const volatile overload
|
||||
#endif // GTHREADS || LINUX_FUTEX
|
||||
|
||||
value_type
|
||||
fetch_add(value_type __i,
|
||||
|
@ -1730,6 +1744,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
__cmpexch_failure_order(__order));
|
||||
}
|
||||
|
||||
#if defined _GLIBCXX_HAS_GTHREADS || _GLIBCXX_HAVE_LINUX_FUTEX
|
||||
_GLIBCXX_ALWAYS_INLINE void
|
||||
wait(_Fp __old, memory_order __m = memory_order_seq_cst) const noexcept
|
||||
{ __atomic_impl::wait(_M_ptr, __old, __m); }
|
||||
|
@ -1747,6 +1762,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
{ __atomic_impl::notify_all(_M_ptr); }
|
||||
|
||||
// TODO add const volatile overload
|
||||
#endif // GTHREADS || LINUX_FUTEX
|
||||
|
||||
value_type
|
||||
fetch_add(value_type __i,
|
||||
|
@ -1857,6 +1873,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
__cmpexch_failure_order(__order));
|
||||
}
|
||||
|
||||
#if defined _GLIBCXX_HAS_GTHREADS || _GLIBCXX_HAVE_LINUX_FUTEX
|
||||
_GLIBCXX_ALWAYS_INLINE void
|
||||
wait(_Tp __old, memory_order __m = memory_order_seq_cst) const noexcept
|
||||
{ __atomic_impl::wait(_M_ptr, __old, __m); }
|
||||
|
@ -1874,6 +1891,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
{ __atomic_impl::notify_all(_M_ptr); }
|
||||
|
||||
// TODO add const volatile overload
|
||||
#endif // GTHREADS || LINUX_FUTEX
|
||||
|
||||
_GLIBCXX_ALWAYS_INLINE value_type
|
||||
fetch_add(difference_type __d,
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#pragma GCC system_header
|
||||
|
||||
#include <bits/c++config.h>
|
||||
#if defined _GLIBCXX_HAS_GTHREADS || _GLIBCXX_HAVE_LINUX_FUTEX
|
||||
#include <bits/functional_hash.h>
|
||||
#include <bits/atomic_wait.h>
|
||||
|
||||
|
@ -286,4 +287,5 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
}
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace std
|
||||
#endif
|
||||
#endif // GTHREADS || LINUX_FUTEX
|
||||
#endif // _GLIBCXX_ATOMIC_TIMED_WAIT_H
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#pragma GCC system_header
|
||||
|
||||
#include <bits/c++config.h>
|
||||
#if defined _GLIBCXX_HAS_GTHREADS || _GLIBCXX_HAVE_LINUX_FUTEX
|
||||
#include <bits/functional_hash.h>
|
||||
#include <bits/gthr.h>
|
||||
#include <bits/std_mutex.h>
|
||||
|
@ -106,7 +107,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
}
|
||||
}
|
||||
|
||||
template<typename _Tp>
|
||||
template<typename _Tp>
|
||||
void
|
||||
__platform_notify(const _Tp* __addr, bool __all) noexcept
|
||||
{
|
||||
|
@ -175,11 +176,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
|
||||
bool
|
||||
_M_waiting() const noexcept
|
||||
{
|
||||
__platform_wait_t __res;
|
||||
__atomic_load(&_M_wait, &__res, __ATOMIC_ACQUIRE);
|
||||
return __res;
|
||||
}
|
||||
{
|
||||
__platform_wait_t __res;
|
||||
__atomic_load(&_M_wait, &__res, __ATOMIC_ACQUIRE);
|
||||
return __res;
|
||||
}
|
||||
|
||||
void
|
||||
_M_notify(bool __all) noexcept
|
||||
|
@ -305,4 +306,5 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
}
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace std
|
||||
#endif
|
||||
#endif // GTHREADS || LINUX_FUTEX
|
||||
#endif // _GLIBCXX_ATOMIC_WAIT_H
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#pragma GCC system_header
|
||||
|
||||
#include <bits/c++config.h>
|
||||
#if defined _GLIBCXX_HAS_GTHREADS || _GLIBCXX_HAVE_LINUX_FUTEX
|
||||
#include <bits/atomic_base.h>
|
||||
#include <bits/atomic_timed_wait.h>
|
||||
|
||||
|
@ -161,30 +162,68 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
noexcept
|
||||
{ return _M_try_acquire_until(__clock_t::now() + __rtime); }
|
||||
|
||||
private:
|
||||
sem_t _M_semaphore;
|
||||
};
|
||||
private:
|
||||
sem_t _M_semaphore;
|
||||
};
|
||||
#endif // _GLIBCXX_HAVE_POSIX_SEMAPHORE
|
||||
|
||||
template<typename _Tp>
|
||||
struct __atomic_semaphore
|
||||
template<typename _Tp>
|
||||
struct __atomic_semaphore
|
||||
{
|
||||
static_assert(std::is_integral_v<_Tp>);
|
||||
static_assert(__gnu_cxx::__int_traits<_Tp>::__max
|
||||
<= __gnu_cxx::__int_traits<ptrdiff_t>::__max);
|
||||
static constexpr ptrdiff_t _S_max = __gnu_cxx::__int_traits<_Tp>::__max;
|
||||
|
||||
explicit __atomic_semaphore(_Tp __count) noexcept
|
||||
: _M_counter(__count)
|
||||
{
|
||||
static_assert(std::is_integral_v<_Tp>);
|
||||
static_assert(__gnu_cxx::__int_traits<_Tp>::__max
|
||||
<= __gnu_cxx::__int_traits<ptrdiff_t>::__max);
|
||||
static constexpr ptrdiff_t _S_max = __gnu_cxx::__int_traits<_Tp>::__max;
|
||||
__glibcxx_assert(__count >= 0 && __count <= _S_max);
|
||||
}
|
||||
|
||||
explicit __atomic_semaphore(_Tp __count) noexcept
|
||||
: _M_counter(__count)
|
||||
{
|
||||
__glibcxx_assert(__count >= 0 && __count <= _S_max);
|
||||
}
|
||||
__atomic_semaphore(const __atomic_semaphore&) = delete;
|
||||
__atomic_semaphore& operator=(const __atomic_semaphore&) = delete;
|
||||
|
||||
__atomic_semaphore(const __atomic_semaphore&) = delete;
|
||||
__atomic_semaphore& operator=(const __atomic_semaphore&) = delete;
|
||||
_GLIBCXX_ALWAYS_INLINE void
|
||||
_M_acquire() noexcept
|
||||
{
|
||||
auto const __pred = [this]
|
||||
{
|
||||
auto __old = __atomic_impl::load(&this->_M_counter,
|
||||
memory_order::acquire);
|
||||
if (__old == 0)
|
||||
return false;
|
||||
return __atomic_impl::compare_exchange_strong(&this->_M_counter,
|
||||
__old, __old - 1,
|
||||
memory_order::acquire,
|
||||
memory_order::release);
|
||||
};
|
||||
auto __old = __atomic_impl::load(&_M_counter, memory_order_relaxed);
|
||||
std::__atomic_wait(&_M_counter, __old, __pred);
|
||||
}
|
||||
|
||||
_GLIBCXX_ALWAYS_INLINE void
|
||||
_M_acquire() noexcept
|
||||
bool
|
||||
_M_try_acquire() noexcept
|
||||
{
|
||||
auto __old = __atomic_impl::load(&_M_counter, memory_order::acquire);
|
||||
auto const __pred = [this, __old]
|
||||
{
|
||||
if (__old == 0)
|
||||
return false;
|
||||
|
||||
auto __prev = __old;
|
||||
return __atomic_impl::compare_exchange_weak(&this->_M_counter,
|
||||
__prev, __prev - 1,
|
||||
memory_order::acquire,
|
||||
memory_order::release);
|
||||
};
|
||||
return std::__atomic_spin(__pred);
|
||||
}
|
||||
|
||||
template<typename _Clock, typename _Duration>
|
||||
_GLIBCXX_ALWAYS_INLINE bool
|
||||
_M_try_acquire_until(const chrono::time_point<_Clock,
|
||||
_Duration>& __atime) noexcept
|
||||
{
|
||||
auto const __pred = [this]
|
||||
{
|
||||
|
@ -193,51 +232,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
if (__old == 0)
|
||||
return false;
|
||||
return __atomic_impl::compare_exchange_strong(&this->_M_counter,
|
||||
__old, __old - 1,
|
||||
memory_order::acquire,
|
||||
memory_order::release);
|
||||
__old, __old - 1,
|
||||
memory_order::acquire,
|
||||
memory_order::release);
|
||||
};
|
||||
|
||||
auto __old = __atomic_impl::load(&_M_counter, memory_order_relaxed);
|
||||
std::__atomic_wait(&_M_counter, __old, __pred);
|
||||
}
|
||||
|
||||
bool
|
||||
_M_try_acquire() noexcept
|
||||
{
|
||||
auto __old = __atomic_impl::load(&_M_counter, memory_order::acquire);
|
||||
auto const __pred = [this, __old]
|
||||
{
|
||||
if (__old == 0)
|
||||
return false;
|
||||
|
||||
auto __prev = __old;
|
||||
return __atomic_impl::compare_exchange_weak(&this->_M_counter,
|
||||
__prev, __prev - 1,
|
||||
memory_order::acquire,
|
||||
memory_order::release);
|
||||
};
|
||||
return std::__atomic_spin(__pred);
|
||||
}
|
||||
|
||||
template<typename _Clock, typename _Duration>
|
||||
_GLIBCXX_ALWAYS_INLINE bool
|
||||
_M_try_acquire_until(const chrono::time_point<_Clock,
|
||||
_Duration>& __atime) noexcept
|
||||
{
|
||||
auto const __pred = [this]
|
||||
{
|
||||
auto __old = __atomic_impl::load(&this->_M_counter,
|
||||
memory_order::acquire);
|
||||
if (__old == 0)
|
||||
return false;
|
||||
return __atomic_impl::compare_exchange_strong(&this->_M_counter,
|
||||
__old, __old - 1,
|
||||
memory_order::acquire,
|
||||
memory_order::release);
|
||||
};
|
||||
|
||||
auto __old = __atomic_impl::load(&_M_counter, memory_order_relaxed);
|
||||
return __atomic_wait_until(&_M_counter, __old, __pred, __atime);
|
||||
return __atomic_wait_until(&_M_counter, __old, __pred, __atime);
|
||||
}
|
||||
|
||||
template<typename _Rep, typename _Period>
|
||||
|
@ -299,4 +300,5 @@ template<ptrdiff_t __least_max_value>
|
|||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace std
|
||||
|
||||
#endif
|
||||
#endif // GTHREADS || LINUX_FUTEX
|
||||
#endif // _GLIBCXX_SEMAPHORE_BASE_H
|
||||
|
|
|
@ -165,6 +165,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
{ return _M_base.compare_exchange_strong(__i1, __i2, __m); }
|
||||
|
||||
#if __cplusplus > 201703L
|
||||
#if defined _GLIBCXX_HAS_GTHREADS || _GLIBCXX_HAVE_LINUX_FUTEX
|
||||
void wait(bool __old, memory_order __m = memory_order_seq_cst) const
|
||||
noexcept
|
||||
{ _M_base.wait(__old, __m); }
|
||||
|
@ -176,6 +177,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
|
||||
void notify_all() const noexcept
|
||||
{ _M_base.notify_all(); }
|
||||
#endif // GTHREADS || LINUX_FUTEX
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -379,6 +381,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
__cmpexch_failure_order(__m)); }
|
||||
|
||||
#if __cplusplus > 201703L
|
||||
#if defined _GLIBCXX_HAS_GTHREADS || _GLIBCXX_HAVE_LINUX_FUTEX
|
||||
void wait(_Tp __old, memory_order __m = memory_order_seq_cst) const noexcept
|
||||
{
|
||||
std::__atomic_wait(&_M_i, __old,
|
||||
|
@ -399,7 +402,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
|
||||
void notify_all() const noexcept
|
||||
{ std::__atomic_notify(&_M_i, true); }
|
||||
#endif
|
||||
#endif // GTHREADS || LINUX_FUTEX
|
||||
#endif // C++20
|
||||
|
||||
};
|
||||
#undef _GLIBCXX20_INIT
|
||||
|
@ -640,6 +644,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
}
|
||||
|
||||
#if __cplusplus > 201703L
|
||||
#if defined _GLIBCXX_HAS_GTHREADS || _GLIBCXX_HAVE_LINUX_FUTEX
|
||||
void wait(__pointer_type __old,
|
||||
memory_order __m = memory_order_seq_cst) noexcept
|
||||
{ _M_b.wait(__old, __m); }
|
||||
|
@ -651,6 +656,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
|
||||
void notify_all() const noexcept
|
||||
{ _M_b.notify_all(); }
|
||||
#endif // GTHREADS || LINUX_FUTEX
|
||||
#endif
|
||||
__pointer_type
|
||||
fetch_add(ptrdiff_t __d,
|
||||
|
@ -1406,6 +1412,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
|
||||
|
||||
#if __cplusplus > 201703L
|
||||
#if defined _GLIBCXX_HAS_GTHREADS || _GLIBCXX_HAVE_LINUX_FUTEX
|
||||
template<typename _Tp>
|
||||
inline void
|
||||
atomic_wait(const atomic<_Tp>* __a,
|
||||
|
@ -1429,6 +1436,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
atomic_notify_all(atomic<_Tp>* __a) noexcept
|
||||
{ __a->notify_all(); }
|
||||
|
||||
#endif // GTHREADS || LINUX_FUTEX
|
||||
#endif // C++2a
|
||||
|
||||
// Function templates for atomic_integral and atomic_pointer operations only.
|
||||
|
|
|
@ -32,14 +32,16 @@
|
|||
#pragma GCC system_header
|
||||
|
||||
#if __cplusplus > 201703L
|
||||
#define __cpp_lib_semaphore 201907L
|
||||
#include <bits/semaphore_base.h>
|
||||
#if defined _GLIBCXX_HAS_GTHREADS || _GLIBCXX_HAVE_LINUX_FUTEX
|
||||
#include <ext/numeric_traits.h>
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
#define __cpp_lib_semaphore 201907L
|
||||
|
||||
template<ptrdiff_t __least_max_value =
|
||||
__gnu_cxx::__int_traits<ptrdiff_t>::__max>
|
||||
class counting_semaphore
|
||||
|
@ -88,5 +90,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
using binary_semaphore = std::counting_semaphore<1>;
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace
|
||||
#endif // __cplusplus > 201703L
|
||||
#endif // GTHREADS || LINUX_FUTEX
|
||||
#endif // C++20
|
||||
#endif // _GLIBCXX_SEMAPHORE
|
||||
|
|
|
@ -226,7 +226,9 @@
|
|||
#if __cpp_lib_concepts
|
||||
# define __cpp_lib_ranges 201911L
|
||||
#endif
|
||||
#define __cpp_lib_semaphore 201907L
|
||||
#if defined _GLIBCXX_HAS_GTHREADS || _GLIBCXX_HAVE_LINUX_FUTEX
|
||||
# define __cpp_lib_semaphore 201907L
|
||||
#endif
|
||||
#define __cpp_lib_shift 201806L
|
||||
#if __cpp_lib_concepts
|
||||
# define __cpp_lib_span 202002L
|
||||
|
|
Loading…
Add table
Reference in a new issue