mirror of
https://github.com/intel/llvm.git
synced 2026-01-25 01:07:04 +08:00
[libc++] Remove _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS (#111964)
This macro isn't required if we define all the functions inline. In fact, quite a few of the marked functions have already been inlined. This patch basically only moves code around and adds `_LIBCPP_HIDE_FROM_ABI` to the places where it's been missing so far. This also removes inlining hints, since it dropps `inline` in some places, but that shouldn't make much of a difference. The functions tend to be either really small, so should be inlined anyways, or are big enough that they shouldn't be inlined even with an inlinehint.
This commit is contained in:
@@ -37,7 +37,6 @@ AttributeMacros: [
|
||||
'_LIBCPP_HIDDEN',
|
||||
'_LIBCPP_HIDE_FROM_ABI_AFTER_V1',
|
||||
'_LIBCPP_HIDE_FROM_ABI',
|
||||
'_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS',
|
||||
'_LIBCPP_NO_SANITIZE',
|
||||
'_LIBCPP_NO_UNIQUE_ADDRESS',
|
||||
'_LIBCPP_NOALIAS',
|
||||
|
||||
@@ -105,35 +105,6 @@ Visibility Macros
|
||||
the extern template declaration) as exported on Windows, as discussed above.
|
||||
On all other platforms, this macro has an empty definition.
|
||||
|
||||
**_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS**
|
||||
Mark a symbol as hidden so it will not be exported from shared libraries. This
|
||||
is intended specifically for method templates of either classes marked with
|
||||
`_LIBCPP_TYPE_VIS` or classes with an extern template instantiation
|
||||
declaration marked with `_LIBCPP_EXTERN_TEMPLATE_TYPE_VIS`.
|
||||
|
||||
When building libc++ with hidden visibility, we want explicit template
|
||||
instantiations to export members, which is consistent with existing Windows
|
||||
behavior. We also want classes annotated with `_LIBCPP_TYPE_VIS` to export
|
||||
their members, which is again consistent with existing Windows behavior.
|
||||
Both these changes are necessary for clients to be able to link against a
|
||||
libc++ DSO built with hidden visibility without encountering missing symbols.
|
||||
|
||||
An unfortunate side effect, however, is that method templates of classes
|
||||
either marked `_LIBCPP_TYPE_VIS` or with extern template instantiation
|
||||
declarations marked with `_LIBCPP_EXTERN_TEMPLATE_TYPE_VIS` also get default
|
||||
visibility when instantiated. These methods are often implicitly instantiated
|
||||
inside other libraries which use the libc++ headers, and will therefore end up
|
||||
being exported from those libraries, since those implicit instantiations will
|
||||
receive default visibility. This is not acceptable for libraries that wish to
|
||||
control their visibility, and led to PR30642.
|
||||
|
||||
Consequently, all such problematic method templates are explicitly marked
|
||||
either hidden (via this macro) or inline, so that they don't leak into client
|
||||
libraries. The problematic methods were found by running
|
||||
`bad-visibility-finder <https://github.com/smeenai/bad-visibility-finder>`_
|
||||
against the libc++ headers after making `_LIBCPP_TYPE_VIS` and
|
||||
`_LIBCPP_EXTERN_TEMPLATE_TYPE_VIS` expand to default visibility.
|
||||
|
||||
Links
|
||||
=====
|
||||
|
||||
|
||||
@@ -39,60 +39,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD
|
||||
_LIBCPP_DECLARE_STRONG_ENUM(cv_status){no_timeout, timeout};
|
||||
_LIBCPP_DECLARE_STRONG_ENUM_EPILOG(cv_status)
|
||||
|
||||
class _LIBCPP_EXPORTED_FROM_ABI condition_variable {
|
||||
__libcpp_condvar_t __cv_ = _LIBCPP_CONDVAR_INITIALIZER;
|
||||
|
||||
public:
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR condition_variable() _NOEXCEPT = default;
|
||||
|
||||
# if _LIBCPP_HAS_TRIVIAL_CONDVAR_DESTRUCTION
|
||||
~condition_variable() = default;
|
||||
# else
|
||||
~condition_variable();
|
||||
# endif
|
||||
|
||||
condition_variable(const condition_variable&) = delete;
|
||||
condition_variable& operator=(const condition_variable&) = delete;
|
||||
|
||||
void notify_one() _NOEXCEPT;
|
||||
void notify_all() _NOEXCEPT;
|
||||
|
||||
void wait(unique_lock<mutex>& __lk) _NOEXCEPT;
|
||||
template <class _Predicate>
|
||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS void wait(unique_lock<mutex>& __lk, _Predicate __pred);
|
||||
|
||||
template <class _Clock, class _Duration>
|
||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS cv_status
|
||||
wait_until(unique_lock<mutex>& __lk, const chrono::time_point<_Clock, _Duration>& __t);
|
||||
|
||||
template <class _Clock, class _Duration, class _Predicate>
|
||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS bool
|
||||
wait_until(unique_lock<mutex>& __lk, const chrono::time_point<_Clock, _Duration>& __t, _Predicate __pred);
|
||||
|
||||
template <class _Rep, class _Period>
|
||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS cv_status
|
||||
wait_for(unique_lock<mutex>& __lk, const chrono::duration<_Rep, _Period>& __d);
|
||||
|
||||
template <class _Rep, class _Period, class _Predicate>
|
||||
bool _LIBCPP_HIDE_FROM_ABI
|
||||
wait_for(unique_lock<mutex>& __lk, const chrono::duration<_Rep, _Period>& __d, _Predicate __pred);
|
||||
|
||||
typedef __libcpp_condvar_t* native_handle_type;
|
||||
_LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() { return &__cv_; }
|
||||
|
||||
private:
|
||||
void
|
||||
__do_timed_wait(unique_lock<mutex>& __lk, chrono::time_point<chrono::system_clock, chrono::nanoseconds>) _NOEXCEPT;
|
||||
# if _LIBCPP_HAS_COND_CLOCKWAIT
|
||||
_LIBCPP_HIDE_FROM_ABI void
|
||||
__do_timed_wait(unique_lock<mutex>& __lk, chrono::time_point<chrono::steady_clock, chrono::nanoseconds>) _NOEXCEPT;
|
||||
# endif
|
||||
template <class _Clock>
|
||||
_LIBCPP_HIDE_FROM_ABI void
|
||||
__do_timed_wait(unique_lock<mutex>& __lk, chrono::time_point<_Clock, chrono::nanoseconds>) _NOEXCEPT;
|
||||
};
|
||||
#endif // _LIBCPP_HAS_THREADS
|
||||
|
||||
template <class _Rep, class _Period, __enable_if_t<is_floating_point<_Rep>::value, int> = 0>
|
||||
inline _LIBCPP_HIDE_FROM_ABI chrono::nanoseconds __safe_nanosecond_cast(chrono::duration<_Rep, _Period> __d) {
|
||||
using namespace chrono;
|
||||
@@ -140,64 +86,106 @@ inline _LIBCPP_HIDE_FROM_ABI chrono::nanoseconds __safe_nanosecond_cast(chrono::
|
||||
return nanoseconds(__result);
|
||||
}
|
||||
|
||||
#if _LIBCPP_HAS_THREADS
|
||||
template <class _Predicate>
|
||||
void condition_variable::wait(unique_lock<mutex>& __lk, _Predicate __pred) {
|
||||
while (!__pred())
|
||||
wait(__lk);
|
||||
}
|
||||
class _LIBCPP_EXPORTED_FROM_ABI condition_variable {
|
||||
__libcpp_condvar_t __cv_ = _LIBCPP_CONDVAR_INITIALIZER;
|
||||
|
||||
template <class _Clock, class _Duration>
|
||||
cv_status condition_variable::wait_until(unique_lock<mutex>& __lk, const chrono::time_point<_Clock, _Duration>& __t) {
|
||||
using namespace chrono;
|
||||
using __clock_tp_ns = time_point<_Clock, nanoseconds>;
|
||||
public:
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR condition_variable() _NOEXCEPT = default;
|
||||
|
||||
typename _Clock::time_point __now = _Clock::now();
|
||||
if (__t <= __now)
|
||||
return cv_status::timeout;
|
||||
|
||||
__clock_tp_ns __t_ns = __clock_tp_ns(std::__safe_nanosecond_cast(__t.time_since_epoch()));
|
||||
|
||||
__do_timed_wait(__lk, __t_ns);
|
||||
return _Clock::now() < __t ? cv_status::no_timeout : cv_status::timeout;
|
||||
}
|
||||
|
||||
template <class _Clock, class _Duration, class _Predicate>
|
||||
bool condition_variable::wait_until(
|
||||
unique_lock<mutex>& __lk, const chrono::time_point<_Clock, _Duration>& __t, _Predicate __pred) {
|
||||
while (!__pred()) {
|
||||
if (wait_until(__lk, __t) == cv_status::timeout)
|
||||
return __pred();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class _Rep, class _Period>
|
||||
cv_status condition_variable::wait_for(unique_lock<mutex>& __lk, const chrono::duration<_Rep, _Period>& __d) {
|
||||
using namespace chrono;
|
||||
if (__d <= __d.zero())
|
||||
return cv_status::timeout;
|
||||
using __ns_rep = nanoseconds::rep;
|
||||
steady_clock::time_point __c_now = steady_clock::now();
|
||||
|
||||
# if _LIBCPP_HAS_COND_CLOCKWAIT
|
||||
using __clock_tp_ns = time_point<steady_clock, nanoseconds>;
|
||||
__ns_rep __now_count_ns = std::__safe_nanosecond_cast(__c_now.time_since_epoch()).count();
|
||||
# if _LIBCPP_HAS_TRIVIAL_CONDVAR_DESTRUCTION
|
||||
~condition_variable() = default;
|
||||
# else
|
||||
using __clock_tp_ns = time_point<system_clock, nanoseconds>;
|
||||
__ns_rep __now_count_ns = std::__safe_nanosecond_cast(system_clock::now().time_since_epoch()).count();
|
||||
~condition_variable();
|
||||
# endif
|
||||
|
||||
__ns_rep __d_ns_count = std::__safe_nanosecond_cast(__d).count();
|
||||
condition_variable(const condition_variable&) = delete;
|
||||
condition_variable& operator=(const condition_variable&) = delete;
|
||||
|
||||
if (__now_count_ns > numeric_limits<__ns_rep>::max() - __d_ns_count) {
|
||||
__do_timed_wait(__lk, __clock_tp_ns::max());
|
||||
} else {
|
||||
__do_timed_wait(__lk, __clock_tp_ns(nanoseconds(__now_count_ns + __d_ns_count)));
|
||||
void notify_one() _NOEXCEPT;
|
||||
void notify_all() _NOEXCEPT;
|
||||
|
||||
void wait(unique_lock<mutex>& __lk) _NOEXCEPT;
|
||||
|
||||
template <class _Predicate>
|
||||
_LIBCPP_HIDE_FROM_ABI void wait(unique_lock<mutex>& __lk, _Predicate __pred) {
|
||||
while (!__pred())
|
||||
wait(__lk);
|
||||
}
|
||||
|
||||
return steady_clock::now() - __c_now < __d ? cv_status::no_timeout : cv_status::timeout;
|
||||
}
|
||||
template <class _Clock, class _Duration>
|
||||
_LIBCPP_HIDE_FROM_ABI cv_status
|
||||
wait_until(unique_lock<mutex>& __lk, const chrono::time_point<_Clock, _Duration>& __t) {
|
||||
using namespace chrono;
|
||||
using __clock_tp_ns = time_point<_Clock, nanoseconds>;
|
||||
|
||||
typename _Clock::time_point __now = _Clock::now();
|
||||
if (__t <= __now)
|
||||
return cv_status::timeout;
|
||||
|
||||
__clock_tp_ns __t_ns = __clock_tp_ns(std::__safe_nanosecond_cast(__t.time_since_epoch()));
|
||||
|
||||
__do_timed_wait(__lk, __t_ns);
|
||||
return _Clock::now() < __t ? cv_status::no_timeout : cv_status::timeout;
|
||||
}
|
||||
|
||||
template <class _Clock, class _Duration, class _Predicate>
|
||||
_LIBCPP_HIDE_FROM_ABI bool
|
||||
wait_until(unique_lock<mutex>& __lk, const chrono::time_point<_Clock, _Duration>& __t, _Predicate __pred) {
|
||||
while (!__pred()) {
|
||||
if (wait_until(__lk, __t) == cv_status::timeout)
|
||||
return __pred();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class _Rep, class _Period>
|
||||
_LIBCPP_HIDE_FROM_ABI cv_status wait_for(unique_lock<mutex>& __lk, const chrono::duration<_Rep, _Period>& __d) {
|
||||
using namespace chrono;
|
||||
if (__d <= __d.zero())
|
||||
return cv_status::timeout;
|
||||
using __ns_rep = nanoseconds::rep;
|
||||
steady_clock::time_point __c_now = steady_clock::now();
|
||||
|
||||
# if _LIBCPP_HAS_COND_CLOCKWAIT
|
||||
using __clock_tp_ns = time_point<steady_clock, nanoseconds>;
|
||||
__ns_rep __now_count_ns = std::__safe_nanosecond_cast(__c_now.time_since_epoch()).count();
|
||||
# else
|
||||
using __clock_tp_ns = time_point<system_clock, nanoseconds>;
|
||||
__ns_rep __now_count_ns = std::__safe_nanosecond_cast(system_clock::now().time_since_epoch()).count();
|
||||
# endif
|
||||
|
||||
__ns_rep __d_ns_count = std::__safe_nanosecond_cast(__d).count();
|
||||
|
||||
if (__now_count_ns > numeric_limits<__ns_rep>::max() - __d_ns_count) {
|
||||
__do_timed_wait(__lk, __clock_tp_ns::max());
|
||||
} else {
|
||||
__do_timed_wait(__lk, __clock_tp_ns(nanoseconds(__now_count_ns + __d_ns_count)));
|
||||
}
|
||||
|
||||
return steady_clock::now() - __c_now < __d ? cv_status::no_timeout : cv_status::timeout;
|
||||
}
|
||||
|
||||
template <class _Rep, class _Period, class _Predicate>
|
||||
bool _LIBCPP_HIDE_FROM_ABI
|
||||
wait_for(unique_lock<mutex>& __lk, const chrono::duration<_Rep, _Period>& __d, _Predicate __pred);
|
||||
|
||||
typedef __libcpp_condvar_t* native_handle_type;
|
||||
_LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() { return &__cv_; }
|
||||
|
||||
private:
|
||||
void
|
||||
__do_timed_wait(unique_lock<mutex>& __lk, chrono::time_point<chrono::system_clock, chrono::nanoseconds>) _NOEXCEPT;
|
||||
# if _LIBCPP_HAS_COND_CLOCKWAIT
|
||||
_LIBCPP_HIDE_FROM_ABI void
|
||||
__do_timed_wait(unique_lock<mutex>& __lk, chrono::time_point<chrono::steady_clock, chrono::nanoseconds>) _NOEXCEPT;
|
||||
# endif
|
||||
template <class _Clock>
|
||||
_LIBCPP_HIDE_FROM_ABI void
|
||||
__do_timed_wait(unique_lock<mutex>& __lk, chrono::time_point<_Clock, chrono::nanoseconds>) _NOEXCEPT;
|
||||
};
|
||||
#endif // _LIBCPP_HAS_THREADS
|
||||
|
||||
#if _LIBCPP_HAS_THREADS
|
||||
|
||||
template <class _Rep, class _Period, class _Predicate>
|
||||
inline bool
|
||||
|
||||
@@ -383,7 +383,6 @@ typedef __char32_t char32_t;
|
||||
# endif
|
||||
|
||||
# define _LIBCPP_HIDDEN
|
||||
# define _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
|
||||
# define _LIBCPP_TEMPLATE_VIS
|
||||
# define _LIBCPP_TEMPLATE_DATA_VIS
|
||||
# define _LIBCPP_NAMESPACE_VISIBILITY
|
||||
@@ -407,13 +406,6 @@ typedef __char32_t char32_t;
|
||||
# define _LIBCPP_OVERRIDABLE_FUNC_VIS _LIBCPP_VISIBILITY("default")
|
||||
# endif
|
||||
|
||||
# if !defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS)
|
||||
// The inline should be removed once PR32114 is resolved
|
||||
# define _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS inline _LIBCPP_HIDDEN
|
||||
# else
|
||||
# define _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
|
||||
# endif
|
||||
|
||||
// This is kept to avoid a huge library-wide diff in the first step.
|
||||
// TODO: Remove this in a follow-up patch
|
||||
# define _LIBCPP_TEMPLATE_VIS
|
||||
|
||||
@@ -45,6 +45,9 @@ _LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
class _LIBCPP_EXPORTED_FROM_ABI locale;
|
||||
|
||||
template <class _CharT>
|
||||
class collate;
|
||||
|
||||
template <class _Facet>
|
||||
_LIBCPP_HIDE_FROM_ABI bool has_facet(const locale&) _NOEXCEPT;
|
||||
|
||||
@@ -84,7 +87,12 @@ public:
|
||||
const locale& operator=(const locale&) _NOEXCEPT;
|
||||
|
||||
template <class _Facet>
|
||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS locale combine(const locale&) const;
|
||||
_LIBCPP_HIDE_FROM_ABI locale combine(const locale& __other) const {
|
||||
if (!std::has_facet<_Facet>(__other))
|
||||
__throw_runtime_error("locale::combine: locale missing facet");
|
||||
|
||||
return locale(*this, std::addressof(const_cast<_Facet&>(std::use_facet<_Facet>(__other))));
|
||||
}
|
||||
|
||||
// locale operations:
|
||||
string name() const;
|
||||
@@ -93,8 +101,11 @@ public:
|
||||
_LIBCPP_HIDE_FROM_ABI bool operator!=(const locale& __y) const { return !(*this == __y); }
|
||||
# endif
|
||||
template <class _CharT, class _Traits, class _Allocator>
|
||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS bool
|
||||
operator()(const basic_string<_CharT, _Traits, _Allocator>&, const basic_string<_CharT, _Traits, _Allocator>&) const;
|
||||
_LIBCPP_HIDE_FROM_ABI bool operator()(const basic_string<_CharT, _Traits, _Allocator>& __x,
|
||||
const basic_string<_CharT, _Traits, _Allocator>& __y) const {
|
||||
return std::use_facet<std::collate<_CharT> >(*this).compare(
|
||||
__x.data(), __x.data() + __x.size(), __y.data(), __y.data() + __y.size()) < 0;
|
||||
}
|
||||
|
||||
// global locale objects:
|
||||
static locale global(const locale&);
|
||||
@@ -155,14 +166,6 @@ inline _LIBCPP_HIDE_FROM_ABI locale::locale(const locale& __other, _Facet* __f)
|
||||
__install_ctor(__other, __f, __f ? __f->id.__get() : 0);
|
||||
}
|
||||
|
||||
template <class _Facet>
|
||||
locale locale::combine(const locale& __other) const {
|
||||
if (!std::has_facet<_Facet>(__other))
|
||||
std::__throw_runtime_error("locale::combine: locale missing facet");
|
||||
|
||||
return locale(*this, std::addressof(const_cast<_Facet&>(std::use_facet<_Facet>(__other))));
|
||||
}
|
||||
|
||||
template <class _Facet>
|
||||
inline _LIBCPP_HIDE_FROM_ABI bool has_facet(const locale& __l) _NOEXCEPT {
|
||||
return __l.has_facet(_Facet::id);
|
||||
@@ -289,13 +292,6 @@ protected:
|
||||
};
|
||||
# endif
|
||||
|
||||
template <class _CharT, class _Traits, class _Allocator>
|
||||
bool locale::operator()(const basic_string<_CharT, _Traits, _Allocator>& __x,
|
||||
const basic_string<_CharT, _Traits, _Allocator>& __y) const {
|
||||
return std::use_facet<std::collate<_CharT> >(*this).compare(
|
||||
__x.data(), __x.data() + __x.size(), __y.data(), __y.data() + __y.size()) < 0;
|
||||
}
|
||||
|
||||
// template <class charT> class ctype
|
||||
|
||||
class _LIBCPP_EXPORTED_FROM_ABI ctype_base {
|
||||
|
||||
@@ -152,6 +152,45 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id) {
|
||||
}
|
||||
# endif // _LIBCPP_HAS_LOCALIZATION
|
||||
|
||||
# ifndef _LIBCPP_CXX03_LANG
|
||||
|
||||
template <class _TSp, class _Fp, class... _Args, size_t... _Indices>
|
||||
inline _LIBCPP_HIDE_FROM_ABI void __thread_execute(tuple<_TSp, _Fp, _Args...>& __t, __tuple_indices<_Indices...>) {
|
||||
std::__invoke(std::move(std::get<1>(__t)), std::move(std::get<_Indices>(__t))...);
|
||||
}
|
||||
|
||||
template <class _Fp>
|
||||
_LIBCPP_HIDE_FROM_ABI void* __thread_proxy(void* __vp) {
|
||||
// _Fp = tuple< unique_ptr<__thread_struct>, Functor, Args...>
|
||||
unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp));
|
||||
__thread_local_data().set_pointer(std::get<0>(*__p.get()).release());
|
||||
typedef typename __make_tuple_indices<tuple_size<_Fp>::value, 2>::type _Index;
|
||||
std::__thread_execute(*__p.get(), _Index());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
# else // _LIBCPP_CXX03_LANG
|
||||
|
||||
template <class _Fp>
|
||||
struct __thread_invoke_pair {
|
||||
// This type is used to pass memory for thread local storage and a functor
|
||||
// to a newly created thread because std::pair doesn't work with
|
||||
// std::unique_ptr in C++03.
|
||||
_LIBCPP_HIDE_FROM_ABI __thread_invoke_pair(_Fp& __f) : __tsp_(new __thread_struct), __fn_(__f) {}
|
||||
unique_ptr<__thread_struct> __tsp_;
|
||||
_Fp __fn_;
|
||||
};
|
||||
|
||||
template <class _Fp>
|
||||
_LIBCPP_HIDE_FROM_ABI void* __thread_proxy_cxx03(void* __vp) {
|
||||
unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp));
|
||||
__thread_local_data().set_pointer(__p->__tsp_.release());
|
||||
(__p->__fn_)();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
# endif // _LIBCPP_CXX03_LANG
|
||||
|
||||
class _LIBCPP_EXPORTED_FROM_ABI thread {
|
||||
__libcpp_thread_t __t_;
|
||||
|
||||
@@ -163,12 +202,32 @@ public:
|
||||
typedef __libcpp_thread_t native_handle_type;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI thread() _NOEXCEPT : __t_(_LIBCPP_NULL_THREAD) {}
|
||||
|
||||
# ifndef _LIBCPP_CXX03_LANG
|
||||
template <class _Fp, class... _Args, __enable_if_t<!is_same<__remove_cvref_t<_Fp>, thread>::value, int> = 0>
|
||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS explicit thread(_Fp&& __f, _Args&&... __args);
|
||||
_LIBCPP_HIDE_FROM_ABI explicit thread(_Fp&& __f, _Args&&... __args) {
|
||||
typedef unique_ptr<__thread_struct> _TSPtr;
|
||||
_TSPtr __tsp(new __thread_struct);
|
||||
typedef tuple<_TSPtr, __decay_t<_Fp>, __decay_t<_Args>...> _Gp;
|
||||
unique_ptr<_Gp> __p(new _Gp(std::move(__tsp), std::forward<_Fp>(__f), std::forward<_Args>(__args)...));
|
||||
int __ec = std::__libcpp_thread_create(&__t_, std::addressof(__thread_proxy<_Gp>), __p.get());
|
||||
if (__ec == 0)
|
||||
__p.release();
|
||||
else
|
||||
__throw_system_error(__ec, "thread constructor failed");
|
||||
}
|
||||
# else // _LIBCPP_CXX03_LANG
|
||||
template <class _Fp>
|
||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS explicit thread(_Fp __f);
|
||||
_LIBCPP_HIDE_FROM_ABI explicit thread(_Fp __f) {
|
||||
typedef __thread_invoke_pair<_Fp> _InvokePair;
|
||||
typedef unique_ptr<_InvokePair> _PairPtr;
|
||||
_PairPtr __pp(new _InvokePair(__f));
|
||||
int __ec = std::__libcpp_thread_create(&__t_, &__thread_proxy_cxx03<_InvokePair>, __pp.get());
|
||||
if (__ec == 0)
|
||||
__pp.release();
|
||||
else
|
||||
__throw_system_error(__ec, "thread constructor failed");
|
||||
}
|
||||
# endif
|
||||
~thread();
|
||||
|
||||
@@ -193,70 +252,6 @@ public:
|
||||
static unsigned hardware_concurrency() _NOEXCEPT;
|
||||
};
|
||||
|
||||
# ifndef _LIBCPP_CXX03_LANG
|
||||
|
||||
template <class _TSp, class _Fp, class... _Args, size_t... _Indices>
|
||||
inline _LIBCPP_HIDE_FROM_ABI void __thread_execute(tuple<_TSp, _Fp, _Args...>& __t, __tuple_indices<_Indices...>) {
|
||||
std::__invoke(std::move(std::get<1>(__t)), std::move(std::get<_Indices>(__t))...);
|
||||
}
|
||||
|
||||
template <class _Fp>
|
||||
_LIBCPP_HIDE_FROM_ABI void* __thread_proxy(void* __vp) {
|
||||
// _Fp = tuple< unique_ptr<__thread_struct>, Functor, Args...>
|
||||
unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp));
|
||||
__thread_local_data().set_pointer(std::get<0>(*__p.get()).release());
|
||||
typedef typename __make_tuple_indices<tuple_size<_Fp>::value, 2>::type _Index;
|
||||
std::__thread_execute(*__p.get(), _Index());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <class _Fp, class... _Args, __enable_if_t<!is_same<__remove_cvref_t<_Fp>, thread>::value, int> >
|
||||
thread::thread(_Fp&& __f, _Args&&... __args) {
|
||||
typedef unique_ptr<__thread_struct> _TSPtr;
|
||||
_TSPtr __tsp(new __thread_struct);
|
||||
typedef tuple<_TSPtr, __decay_t<_Fp>, __decay_t<_Args>...> _Gp;
|
||||
unique_ptr<_Gp> __p(new _Gp(std::move(__tsp), std::forward<_Fp>(__f), std::forward<_Args>(__args)...));
|
||||
int __ec = std::__libcpp_thread_create(&__t_, std::addressof(__thread_proxy<_Gp>), __p.get());
|
||||
if (__ec == 0)
|
||||
__p.release();
|
||||
else
|
||||
std::__throw_system_error(__ec, "thread constructor failed");
|
||||
}
|
||||
|
||||
# else // _LIBCPP_CXX03_LANG
|
||||
|
||||
template <class _Fp>
|
||||
struct __thread_invoke_pair {
|
||||
// This type is used to pass memory for thread local storage and a functor
|
||||
// to a newly created thread because std::pair doesn't work with
|
||||
// std::unique_ptr in C++03.
|
||||
_LIBCPP_HIDE_FROM_ABI __thread_invoke_pair(_Fp& __f) : __tsp_(new __thread_struct), __fn_(__f) {}
|
||||
unique_ptr<__thread_struct> __tsp_;
|
||||
_Fp __fn_;
|
||||
};
|
||||
|
||||
template <class _Fp>
|
||||
_LIBCPP_HIDE_FROM_ABI void* __thread_proxy_cxx03(void* __vp) {
|
||||
unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp));
|
||||
__thread_local_data().set_pointer(__p->__tsp_.release());
|
||||
(__p->__fn_)();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <class _Fp>
|
||||
thread::thread(_Fp __f) {
|
||||
typedef __thread_invoke_pair<_Fp> _InvokePair;
|
||||
typedef unique_ptr<_InvokePair> _PairPtr;
|
||||
_PairPtr __pp(new _InvokePair(__f));
|
||||
int __ec = std::__libcpp_thread_create(&__t_, &__thread_proxy_cxx03<_InvokePair>, __pp.get());
|
||||
if (__ec == 0)
|
||||
__pp.release();
|
||||
else
|
||||
std::__throw_system_error(__ec, "thread constructor failed");
|
||||
}
|
||||
|
||||
# endif // _LIBCPP_CXX03_LANG
|
||||
|
||||
inline _LIBCPP_HIDE_FROM_ABI void swap(thread& __x, thread& __y) _NOEXCEPT { __x.swap(__y); }
|
||||
|
||||
#endif // _LIBCPP_HAS_THREADS
|
||||
|
||||
@@ -147,6 +147,21 @@ _LIBCPP_PUSH_MACROS
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
template <class _Lock>
|
||||
struct __unlock_guard {
|
||||
_Lock& __lock_;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI __unlock_guard(_Lock& __lock) : __lock_(__lock) { __lock_.unlock(); }
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI ~__unlock_guard() _NOEXCEPT // turns exception to std::terminate
|
||||
{
|
||||
__lock_.lock();
|
||||
}
|
||||
|
||||
__unlock_guard(const __unlock_guard&) = delete;
|
||||
__unlock_guard& operator=(const __unlock_guard&) = delete;
|
||||
};
|
||||
|
||||
class _LIBCPP_EXPORTED_FROM_ABI condition_variable_any {
|
||||
condition_variable __cv_;
|
||||
shared_ptr<mutex> __mut_;
|
||||
@@ -158,13 +173,25 @@ public:
|
||||
_LIBCPP_HIDE_FROM_ABI void notify_all() _NOEXCEPT;
|
||||
|
||||
template <class _Lock>
|
||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS void wait(_Lock& __lock);
|
||||
_LIBCPP_HIDE_FROM_ABI void wait(_Lock& __lock) {
|
||||
shared_ptr<mutex> __mut = __mut_;
|
||||
unique_lock<mutex> __lk(*__mut);
|
||||
__unlock_guard<_Lock> __unlock(__lock);
|
||||
lock_guard<unique_lock<mutex> > __lx(__lk, adopt_lock_t());
|
||||
__cv_.wait(__lk);
|
||||
} // __mut_.unlock(), __lock.lock()
|
||||
|
||||
template <class _Lock, class _Predicate>
|
||||
_LIBCPP_HIDE_FROM_ABI void wait(_Lock& __lock, _Predicate __pred);
|
||||
|
||||
template <class _Lock, class _Clock, class _Duration>
|
||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS cv_status
|
||||
wait_until(_Lock& __lock, const chrono::time_point<_Clock, _Duration>& __t);
|
||||
_LIBCPP_HIDE_FROM_ABI cv_status wait_until(_Lock& __lock, const chrono::time_point<_Clock, _Duration>& __t) {
|
||||
shared_ptr<mutex> __mut = __mut_;
|
||||
unique_lock<mutex> __lk(*__mut);
|
||||
__unlock_guard<_Lock> __unlock(__lock);
|
||||
lock_guard<unique_lock<mutex> > __lx(__lk, adopt_lock_t());
|
||||
return __cv_.wait_until(__lk, __t);
|
||||
} // __mut_.unlock(), __lock.lock()
|
||||
|
||||
template <class _Lock, class _Clock, class _Duration, class _Predicate>
|
||||
bool _LIBCPP_HIDE_FROM_ABI
|
||||
@@ -204,45 +231,12 @@ inline void condition_variable_any::notify_all() _NOEXCEPT {
|
||||
__cv_.notify_all();
|
||||
}
|
||||
|
||||
template <class _Lock>
|
||||
struct __unlock_guard {
|
||||
_Lock& __lock_;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI __unlock_guard(_Lock& __lock) : __lock_(__lock) { __lock_.unlock(); }
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI ~__unlock_guard() _NOEXCEPT // turns exception to std::terminate
|
||||
{
|
||||
__lock_.lock();
|
||||
}
|
||||
|
||||
__unlock_guard(const __unlock_guard&) = delete;
|
||||
__unlock_guard& operator=(const __unlock_guard&) = delete;
|
||||
};
|
||||
|
||||
template <class _Lock>
|
||||
void condition_variable_any::wait(_Lock& __lock) {
|
||||
shared_ptr<mutex> __mut = __mut_;
|
||||
unique_lock<mutex> __lk(*__mut);
|
||||
__unlock_guard<_Lock> __unlock(__lock);
|
||||
lock_guard<unique_lock<mutex> > __lx(__lk, adopt_lock_t());
|
||||
__cv_.wait(__lk);
|
||||
} // __mut_.unlock(), __lock.lock()
|
||||
|
||||
template <class _Lock, class _Predicate>
|
||||
inline void condition_variable_any::wait(_Lock& __lock, _Predicate __pred) {
|
||||
while (!__pred())
|
||||
wait(__lock);
|
||||
}
|
||||
|
||||
template <class _Lock, class _Clock, class _Duration>
|
||||
cv_status condition_variable_any::wait_until(_Lock& __lock, const chrono::time_point<_Clock, _Duration>& __t) {
|
||||
shared_ptr<mutex> __mut = __mut_;
|
||||
unique_lock<mutex> __lk(*__mut);
|
||||
__unlock_guard<_Lock> __unlock(__lock);
|
||||
lock_guard<unique_lock<mutex> > __lx(__lk, adopt_lock_t());
|
||||
return __cv_.wait_until(__lk, __t);
|
||||
} // __mut_.unlock(), __lock.lock()
|
||||
|
||||
template <class _Lock, class _Clock, class _Duration, class _Predicate>
|
||||
inline bool
|
||||
condition_variable_any::wait_until(_Lock& __lock, const chrono::time_point<_Clock, _Duration>& __t, _Predicate __pred) {
|
||||
|
||||
@@ -563,24 +563,20 @@ public:
|
||||
template <class _Rep, class _Period>
|
||||
future_status _LIBCPP_HIDE_FROM_ABI wait_for(const chrono::duration<_Rep, _Period>& __rel_time) const;
|
||||
template <class _Clock, class _Duration>
|
||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS future_status
|
||||
wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const;
|
||||
_LIBCPP_HIDE_FROM_ABI future_status wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const {
|
||||
unique_lock<mutex> __lk(__mut_);
|
||||
if (__state_ & deferred)
|
||||
return future_status::deferred;
|
||||
while (!(__state_ & ready) && _Clock::now() < __abs_time)
|
||||
__cv_.wait_until(__lk, __abs_time);
|
||||
if (__state_ & ready)
|
||||
return future_status::ready;
|
||||
return future_status::timeout;
|
||||
}
|
||||
|
||||
virtual void __execute();
|
||||
};
|
||||
|
||||
template <class _Clock, class _Duration>
|
||||
future_status __assoc_sub_state::wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const {
|
||||
unique_lock<mutex> __lk(__mut_);
|
||||
if (__state_ & deferred)
|
||||
return future_status::deferred;
|
||||
while (!(__state_ & ready) && _Clock::now() < __abs_time)
|
||||
__cv_.wait_until(__lk, __abs_time);
|
||||
if (__state_ & ready)
|
||||
return future_status::ready;
|
||||
return future_status::timeout;
|
||||
}
|
||||
|
||||
template <class _Rep, class _Period>
|
||||
inline future_status __assoc_sub_state::wait_for(const chrono::duration<_Rep, _Period>& __rel_time) const {
|
||||
return wait_until(chrono::steady_clock::now() + __rel_time);
|
||||
@@ -1347,8 +1343,17 @@ class _LIBCPP_EXPORTED_FROM_ABI promise<void> {
|
||||
|
||||
public:
|
||||
promise();
|
||||
template <class _Allocator>
|
||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS promise(allocator_arg_t, const _Allocator& __a);
|
||||
template <class _Alloc>
|
||||
_LIBCPP_HIDE_FROM_ABI promise(allocator_arg_t, const _Alloc& __a0) {
|
||||
typedef __assoc_sub_state_alloc<_Alloc> _State;
|
||||
typedef typename __allocator_traits_rebind<_Alloc, _State>::type _A2;
|
||||
typedef __allocator_destructor<_A2> _D2;
|
||||
_A2 __a(__a0);
|
||||
unique_ptr<_State, _D2> __hold(__a.allocate(1), _D2(__a, 1));
|
||||
::new ((void*)std::addressof(*__hold.get())) _State(__a0);
|
||||
__state_ = std::addressof(*__hold.release());
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI promise(promise&& __rhs) _NOEXCEPT : __state_(__rhs.__state_) { __rhs.__state_ = nullptr; }
|
||||
promise(const promise& __rhs) = delete;
|
||||
~promise();
|
||||
@@ -1374,17 +1379,6 @@ public:
|
||||
void set_exception_at_thread_exit(exception_ptr __p);
|
||||
};
|
||||
|
||||
template <class _Alloc>
|
||||
promise<void>::promise(allocator_arg_t, const _Alloc& __a0) {
|
||||
typedef __assoc_sub_state_alloc<_Alloc> _State;
|
||||
typedef typename __allocator_traits_rebind<_Alloc, _State>::type _A2;
|
||||
typedef __allocator_destructor<_A2> _D2;
|
||||
_A2 __a(__a0);
|
||||
unique_ptr<_State, _D2> __hold(__a.allocate(1), _D2(__a, 1));
|
||||
::new ((void*)std::addressof(*__hold.get())) _State(__a0);
|
||||
__state_ = std::addressof(*__hold.release());
|
||||
}
|
||||
|
||||
template <class _Rp>
|
||||
inline _LIBCPP_HIDE_FROM_ABI void swap(promise<_Rp>& __x, promise<_Rp>& __y) _NOEXCEPT {
|
||||
__x.swap(__y);
|
||||
|
||||
@@ -566,6 +566,104 @@ extern template struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_get<char>;
|
||||
extern template struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_get<wchar_t>;
|
||||
# endif
|
||||
|
||||
template <class _Tp>
|
||||
_LIBCPP_HIDE_FROM_ABI _Tp __do_strtod(const char* __a, char** __p2);
|
||||
|
||||
template <>
|
||||
inline _LIBCPP_HIDE_FROM_ABI float __do_strtod<float>(const char* __a, char** __p2) {
|
||||
return __locale::__strtof(__a, __p2, _LIBCPP_GET_C_LOCALE);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline _LIBCPP_HIDE_FROM_ABI double __do_strtod<double>(const char* __a, char** __p2) {
|
||||
return __locale::__strtod(__a, __p2, _LIBCPP_GET_C_LOCALE);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline _LIBCPP_HIDE_FROM_ABI long double __do_strtod<long double>(const char* __a, char** __p2) {
|
||||
return __locale::__strtold(__a, __p2, _LIBCPP_GET_C_LOCALE);
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
_LIBCPP_HIDE_FROM_ABI _Tp __num_get_float(const char* __a, const char* __a_end, ios_base::iostate& __err) {
|
||||
if (__a != __a_end) {
|
||||
__libcpp_remove_reference_t<decltype(errno)> __save_errno = errno;
|
||||
errno = 0;
|
||||
char* __p2;
|
||||
_Tp __ld = std::__do_strtod<_Tp>(__a, &__p2);
|
||||
__libcpp_remove_reference_t<decltype(errno)> __current_errno = errno;
|
||||
if (__current_errno == 0)
|
||||
errno = __save_errno;
|
||||
if (__p2 != __a_end) {
|
||||
__err = ios_base::failbit;
|
||||
return 0;
|
||||
} else if (__current_errno == ERANGE)
|
||||
__err = ios_base::failbit;
|
||||
return __ld;
|
||||
}
|
||||
__err = ios_base::failbit;
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
_LIBCPP_HIDE_FROM_ABI _Tp
|
||||
__num_get_signed_integral(const char* __a, const char* __a_end, ios_base::iostate& __err, int __base) {
|
||||
if (__a != __a_end) {
|
||||
__libcpp_remove_reference_t<decltype(errno)> __save_errno = errno;
|
||||
errno = 0;
|
||||
char* __p2;
|
||||
long long __ll = __locale::__strtoll(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE);
|
||||
__libcpp_remove_reference_t<decltype(errno)> __current_errno = errno;
|
||||
if (__current_errno == 0)
|
||||
errno = __save_errno;
|
||||
if (__p2 != __a_end) {
|
||||
__err = ios_base::failbit;
|
||||
return 0;
|
||||
} else if (__current_errno == ERANGE || __ll < numeric_limits<_Tp>::min() || numeric_limits<_Tp>::max() < __ll) {
|
||||
__err = ios_base::failbit;
|
||||
if (__ll > 0)
|
||||
return numeric_limits<_Tp>::max();
|
||||
else
|
||||
return numeric_limits<_Tp>::min();
|
||||
}
|
||||
return static_cast<_Tp>(__ll);
|
||||
}
|
||||
__err = ios_base::failbit;
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
_LIBCPP_HIDE_FROM_ABI _Tp
|
||||
__num_get_unsigned_integral(const char* __a, const char* __a_end, ios_base::iostate& __err, int __base) {
|
||||
if (__a != __a_end) {
|
||||
const bool __negate = *__a == '-';
|
||||
if (__negate && ++__a == __a_end) {
|
||||
__err = ios_base::failbit;
|
||||
return 0;
|
||||
}
|
||||
__libcpp_remove_reference_t<decltype(errno)> __save_errno = errno;
|
||||
errno = 0;
|
||||
char* __p2;
|
||||
unsigned long long __ll = __locale::__strtoull(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE);
|
||||
__libcpp_remove_reference_t<decltype(errno)> __current_errno = errno;
|
||||
if (__current_errno == 0)
|
||||
errno = __save_errno;
|
||||
if (__p2 != __a_end) {
|
||||
__err = ios_base::failbit;
|
||||
return 0;
|
||||
} else if (__current_errno == ERANGE || numeric_limits<_Tp>::max() < __ll) {
|
||||
__err = ios_base::failbit;
|
||||
return numeric_limits<_Tp>::max();
|
||||
}
|
||||
_Tp __res = static_cast<_Tp>(__ll);
|
||||
if (__negate)
|
||||
__res = -__res;
|
||||
return __res;
|
||||
}
|
||||
__err = ios_base::failbit;
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
|
||||
class _LIBCPP_TEMPLATE_VIS num_get : public locale::facet, private __num_get<_CharT> {
|
||||
public:
|
||||
@@ -635,16 +733,175 @@ protected:
|
||||
_LIBCPP_HIDE_FROM_ABI_VIRTUAL ~num_get() override {}
|
||||
|
||||
template <class _Fp>
|
||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS iter_type
|
||||
__do_get_floating_point(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, _Fp& __v) const;
|
||||
_LIBCPP_HIDE_FROM_ABI iter_type
|
||||
__do_get_floating_point(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, _Fp& __v) const {
|
||||
// Stage 1, nothing to do
|
||||
// Stage 2
|
||||
char_type __atoms[__num_get_base::__fp_chr_cnt];
|
||||
char_type __decimal_point;
|
||||
char_type __thousands_sep;
|
||||
string __grouping = this->__stage2_float_prep(__iob, __atoms, __decimal_point, __thousands_sep);
|
||||
string __buf;
|
||||
__buf.resize(__buf.capacity());
|
||||
char* __a = &__buf[0];
|
||||
char* __a_end = __a;
|
||||
unsigned __g[__num_get_base::__num_get_buf_sz];
|
||||
unsigned* __g_end = __g;
|
||||
unsigned __dc = 0;
|
||||
bool __in_units = true;
|
||||
char __exp = 'E';
|
||||
bool __is_leading_parsed = false;
|
||||
for (; __b != __e; ++__b) {
|
||||
if (__a_end == __a + __buf.size()) {
|
||||
size_t __tmp = __buf.size();
|
||||
__buf.resize(2 * __buf.size());
|
||||
__buf.resize(__buf.capacity());
|
||||
__a = &__buf[0];
|
||||
__a_end = __a + __tmp;
|
||||
}
|
||||
if (this->__stage2_float_loop(
|
||||
*__b,
|
||||
__in_units,
|
||||
__exp,
|
||||
__a,
|
||||
__a_end,
|
||||
__decimal_point,
|
||||
__thousands_sep,
|
||||
__grouping,
|
||||
__g,
|
||||
__g_end,
|
||||
__dc,
|
||||
__atoms))
|
||||
break;
|
||||
|
||||
// the leading character excluding the sign must be a decimal digit
|
||||
if (!__is_leading_parsed) {
|
||||
if (__a_end - __a >= 1 && __a[0] != '-' && __a[0] != '+') {
|
||||
if (('0' <= __a[0] && __a[0] <= '9') || __a[0] == '.')
|
||||
__is_leading_parsed = true;
|
||||
else
|
||||
break;
|
||||
} else if (__a_end - __a >= 2 && (__a[0] == '-' || __a[0] == '+')) {
|
||||
if (('0' <= __a[1] && __a[1] <= '9') || __a[1] == '.')
|
||||
__is_leading_parsed = true;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (__grouping.size() != 0 && __in_units && __g_end - __g < __num_get_base::__num_get_buf_sz)
|
||||
*__g_end++ = __dc;
|
||||
// Stage 3
|
||||
__v = std::__num_get_float<_Fp>(__a, __a_end, __err);
|
||||
// Digit grouping checked
|
||||
__check_grouping(__grouping, __g, __g_end, __err);
|
||||
// EOF checked
|
||||
if (__b == __e)
|
||||
__err |= ios_base::eofbit;
|
||||
return __b;
|
||||
}
|
||||
|
||||
template <class _Signed>
|
||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS iter_type
|
||||
__do_get_signed(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, _Signed& __v) const;
|
||||
_LIBCPP_HIDE_FROM_ABI iter_type
|
||||
__do_get_signed(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, _Signed& __v) const {
|
||||
// Stage 1
|
||||
int __base = this->__get_base(__iob);
|
||||
// Stage 2
|
||||
char_type __thousands_sep;
|
||||
const int __atoms_size = __num_get_base::__int_chr_cnt;
|
||||
char_type __atoms1[__atoms_size];
|
||||
const char_type* __atoms = this->__do_widen(__iob, __atoms1);
|
||||
string __grouping = this->__stage2_int_prep(__iob, __thousands_sep);
|
||||
string __buf;
|
||||
__buf.resize(__buf.capacity());
|
||||
char* __a = &__buf[0];
|
||||
char* __a_end = __a;
|
||||
unsigned __g[__num_get_base::__num_get_buf_sz];
|
||||
unsigned* __g_end = __g;
|
||||
unsigned __dc = 0;
|
||||
for (; __b != __e; ++__b) {
|
||||
if (__a_end == __a + __buf.size()) {
|
||||
size_t __tmp = __buf.size();
|
||||
__buf.resize(2 * __buf.size());
|
||||
__buf.resize(__buf.capacity());
|
||||
__a = &__buf[0];
|
||||
__a_end = __a + __tmp;
|
||||
}
|
||||
if (this->__stage2_int_loop(
|
||||
*__b,
|
||||
__base,
|
||||
__a,
|
||||
__a_end,
|
||||
__dc,
|
||||
__thousands_sep,
|
||||
__grouping,
|
||||
__g,
|
||||
__g_end,
|
||||
const_cast<char_type*>(__atoms)))
|
||||
break;
|
||||
}
|
||||
if (__grouping.size() != 0 && __g_end - __g < __num_get_base::__num_get_buf_sz)
|
||||
*__g_end++ = __dc;
|
||||
// Stage 3
|
||||
__v = std::__num_get_signed_integral<_Signed>(__a, __a_end, __err, __base);
|
||||
// Digit grouping checked
|
||||
__check_grouping(__grouping, __g, __g_end, __err);
|
||||
// EOF checked
|
||||
if (__b == __e)
|
||||
__err |= ios_base::eofbit;
|
||||
return __b;
|
||||
}
|
||||
|
||||
template <class _Unsigned>
|
||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS iter_type
|
||||
__do_get_unsigned(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, _Unsigned& __v) const;
|
||||
_LIBCPP_HIDE_FROM_ABI iter_type
|
||||
__do_get_unsigned(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, _Unsigned& __v) const {
|
||||
// Stage 1
|
||||
int __base = this->__get_base(__iob);
|
||||
// Stage 2
|
||||
char_type __thousands_sep;
|
||||
const int __atoms_size = __num_get_base::__int_chr_cnt;
|
||||
char_type __atoms1[__atoms_size];
|
||||
const char_type* __atoms = this->__do_widen(__iob, __atoms1);
|
||||
string __grouping = this->__stage2_int_prep(__iob, __thousands_sep);
|
||||
string __buf;
|
||||
__buf.resize(__buf.capacity());
|
||||
char* __a = &__buf[0];
|
||||
char* __a_end = __a;
|
||||
unsigned __g[__num_get_base::__num_get_buf_sz];
|
||||
unsigned* __g_end = __g;
|
||||
unsigned __dc = 0;
|
||||
for (; __b != __e; ++__b) {
|
||||
if (__a_end == __a + __buf.size()) {
|
||||
size_t __tmp = __buf.size();
|
||||
__buf.resize(2 * __buf.size());
|
||||
__buf.resize(__buf.capacity());
|
||||
__a = &__buf[0];
|
||||
__a_end = __a + __tmp;
|
||||
}
|
||||
if (this->__stage2_int_loop(
|
||||
*__b,
|
||||
__base,
|
||||
__a,
|
||||
__a_end,
|
||||
__dc,
|
||||
__thousands_sep,
|
||||
__grouping,
|
||||
__g,
|
||||
__g_end,
|
||||
const_cast<char_type*>(__atoms)))
|
||||
break;
|
||||
}
|
||||
if (__grouping.size() != 0 && __g_end - __g < __num_get_base::__num_get_buf_sz)
|
||||
*__g_end++ = __dc;
|
||||
// Stage 3
|
||||
__v = std::__num_get_unsigned_integral<_Unsigned>(__a, __a_end, __err, __base);
|
||||
// Digit grouping checked
|
||||
__check_grouping(__grouping, __g, __g_end, __err);
|
||||
// EOF checked
|
||||
if (__b == __e)
|
||||
__err |= ios_base::eofbit;
|
||||
return __b;
|
||||
}
|
||||
|
||||
virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, bool& __v) const;
|
||||
|
||||
@@ -696,104 +953,6 @@ protected:
|
||||
template <class _CharT, class _InputIterator>
|
||||
locale::id num_get<_CharT, _InputIterator>::id;
|
||||
|
||||
template <class _Tp>
|
||||
_LIBCPP_HIDE_FROM_ABI _Tp
|
||||
__num_get_signed_integral(const char* __a, const char* __a_end, ios_base::iostate& __err, int __base) {
|
||||
if (__a != __a_end) {
|
||||
__libcpp_remove_reference_t<decltype(errno)> __save_errno = errno;
|
||||
errno = 0;
|
||||
char* __p2;
|
||||
long long __ll = __locale::__strtoll(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE);
|
||||
__libcpp_remove_reference_t<decltype(errno)> __current_errno = errno;
|
||||
if (__current_errno == 0)
|
||||
errno = __save_errno;
|
||||
if (__p2 != __a_end) {
|
||||
__err = ios_base::failbit;
|
||||
return 0;
|
||||
} else if (__current_errno == ERANGE || __ll < numeric_limits<_Tp>::min() || numeric_limits<_Tp>::max() < __ll) {
|
||||
__err = ios_base::failbit;
|
||||
if (__ll > 0)
|
||||
return numeric_limits<_Tp>::max();
|
||||
else
|
||||
return numeric_limits<_Tp>::min();
|
||||
}
|
||||
return static_cast<_Tp>(__ll);
|
||||
}
|
||||
__err = ios_base::failbit;
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
_LIBCPP_HIDE_FROM_ABI _Tp
|
||||
__num_get_unsigned_integral(const char* __a, const char* __a_end, ios_base::iostate& __err, int __base) {
|
||||
if (__a != __a_end) {
|
||||
const bool __negate = *__a == '-';
|
||||
if (__negate && ++__a == __a_end) {
|
||||
__err = ios_base::failbit;
|
||||
return 0;
|
||||
}
|
||||
__libcpp_remove_reference_t<decltype(errno)> __save_errno = errno;
|
||||
errno = 0;
|
||||
char* __p2;
|
||||
unsigned long long __ll = __locale::__strtoull(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE);
|
||||
__libcpp_remove_reference_t<decltype(errno)> __current_errno = errno;
|
||||
if (__current_errno == 0)
|
||||
errno = __save_errno;
|
||||
if (__p2 != __a_end) {
|
||||
__err = ios_base::failbit;
|
||||
return 0;
|
||||
} else if (__current_errno == ERANGE || numeric_limits<_Tp>::max() < __ll) {
|
||||
__err = ios_base::failbit;
|
||||
return numeric_limits<_Tp>::max();
|
||||
}
|
||||
_Tp __res = static_cast<_Tp>(__ll);
|
||||
if (__negate)
|
||||
__res = -__res;
|
||||
return __res;
|
||||
}
|
||||
__err = ios_base::failbit;
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
_LIBCPP_HIDE_FROM_ABI _Tp __do_strtod(const char* __a, char** __p2);
|
||||
|
||||
template <>
|
||||
inline _LIBCPP_HIDE_FROM_ABI float __do_strtod<float>(const char* __a, char** __p2) {
|
||||
return __locale::__strtof(__a, __p2, _LIBCPP_GET_C_LOCALE);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline _LIBCPP_HIDE_FROM_ABI double __do_strtod<double>(const char* __a, char** __p2) {
|
||||
return __locale::__strtod(__a, __p2, _LIBCPP_GET_C_LOCALE);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline _LIBCPP_HIDE_FROM_ABI long double __do_strtod<long double>(const char* __a, char** __p2) {
|
||||
return __locale::__strtold(__a, __p2, _LIBCPP_GET_C_LOCALE);
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
_LIBCPP_HIDE_FROM_ABI _Tp __num_get_float(const char* __a, const char* __a_end, ios_base::iostate& __err) {
|
||||
if (__a != __a_end) {
|
||||
__libcpp_remove_reference_t<decltype(errno)> __save_errno = errno;
|
||||
errno = 0;
|
||||
char* __p2;
|
||||
_Tp __ld = std::__do_strtod<_Tp>(__a, &__p2);
|
||||
__libcpp_remove_reference_t<decltype(errno)> __current_errno = errno;
|
||||
if (__current_errno == 0)
|
||||
errno = __save_errno;
|
||||
if (__p2 != __a_end) {
|
||||
__err = ios_base::failbit;
|
||||
return 0;
|
||||
} else if (__current_errno == ERANGE)
|
||||
__err = ios_base::failbit;
|
||||
return __ld;
|
||||
}
|
||||
__err = ios_base::failbit;
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class _CharT, class _InputIterator>
|
||||
_InputIterator num_get<_CharT, _InputIterator>::do_get(
|
||||
iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, bool& __v) const {
|
||||
@@ -823,186 +982,6 @@ _InputIterator num_get<_CharT, _InputIterator>::do_get(
|
||||
return __b;
|
||||
}
|
||||
|
||||
// signed
|
||||
|
||||
template <class _CharT, class _InputIterator>
|
||||
template <class _Signed>
|
||||
_InputIterator num_get<_CharT, _InputIterator>::__do_get_signed(
|
||||
iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, _Signed& __v) const {
|
||||
// Stage 1
|
||||
int __base = this->__get_base(__iob);
|
||||
// Stage 2
|
||||
char_type __thousands_sep;
|
||||
const int __atoms_size = __num_get_base::__int_chr_cnt;
|
||||
char_type __atoms1[__atoms_size];
|
||||
const char_type* __atoms = this->__do_widen(__iob, __atoms1);
|
||||
string __grouping = this->__stage2_int_prep(__iob, __thousands_sep);
|
||||
string __buf;
|
||||
__buf.resize(__buf.capacity());
|
||||
char* __a = &__buf[0];
|
||||
char* __a_end = __a;
|
||||
unsigned __g[__num_get_base::__num_get_buf_sz];
|
||||
unsigned* __g_end = __g;
|
||||
unsigned __dc = 0;
|
||||
for (; __b != __e; ++__b) {
|
||||
if (__a_end == __a + __buf.size()) {
|
||||
size_t __tmp = __buf.size();
|
||||
__buf.resize(2 * __buf.size());
|
||||
__buf.resize(__buf.capacity());
|
||||
__a = &__buf[0];
|
||||
__a_end = __a + __tmp;
|
||||
}
|
||||
if (this->__stage2_int_loop(
|
||||
*__b,
|
||||
__base,
|
||||
__a,
|
||||
__a_end,
|
||||
__dc,
|
||||
__thousands_sep,
|
||||
__grouping,
|
||||
__g,
|
||||
__g_end,
|
||||
const_cast<char_type*>(__atoms)))
|
||||
break;
|
||||
}
|
||||
if (__grouping.size() != 0 && __g_end - __g < __num_get_base::__num_get_buf_sz)
|
||||
*__g_end++ = __dc;
|
||||
// Stage 3
|
||||
__v = std::__num_get_signed_integral<_Signed>(__a, __a_end, __err, __base);
|
||||
// Digit grouping checked
|
||||
__check_grouping(__grouping, __g, __g_end, __err);
|
||||
// EOF checked
|
||||
if (__b == __e)
|
||||
__err |= ios_base::eofbit;
|
||||
return __b;
|
||||
}
|
||||
|
||||
// unsigned
|
||||
|
||||
template <class _CharT, class _InputIterator>
|
||||
template <class _Unsigned>
|
||||
_InputIterator num_get<_CharT, _InputIterator>::__do_get_unsigned(
|
||||
iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, _Unsigned& __v) const {
|
||||
// Stage 1
|
||||
int __base = this->__get_base(__iob);
|
||||
// Stage 2
|
||||
char_type __thousands_sep;
|
||||
const int __atoms_size = __num_get_base::__int_chr_cnt;
|
||||
char_type __atoms1[__atoms_size];
|
||||
const char_type* __atoms = this->__do_widen(__iob, __atoms1);
|
||||
string __grouping = this->__stage2_int_prep(__iob, __thousands_sep);
|
||||
string __buf;
|
||||
__buf.resize(__buf.capacity());
|
||||
char* __a = &__buf[0];
|
||||
char* __a_end = __a;
|
||||
unsigned __g[__num_get_base::__num_get_buf_sz];
|
||||
unsigned* __g_end = __g;
|
||||
unsigned __dc = 0;
|
||||
for (; __b != __e; ++__b) {
|
||||
if (__a_end == __a + __buf.size()) {
|
||||
size_t __tmp = __buf.size();
|
||||
__buf.resize(2 * __buf.size());
|
||||
__buf.resize(__buf.capacity());
|
||||
__a = &__buf[0];
|
||||
__a_end = __a + __tmp;
|
||||
}
|
||||
if (this->__stage2_int_loop(
|
||||
*__b,
|
||||
__base,
|
||||
__a,
|
||||
__a_end,
|
||||
__dc,
|
||||
__thousands_sep,
|
||||
__grouping,
|
||||
__g,
|
||||
__g_end,
|
||||
const_cast<char_type*>(__atoms)))
|
||||
break;
|
||||
}
|
||||
if (__grouping.size() != 0 && __g_end - __g < __num_get_base::__num_get_buf_sz)
|
||||
*__g_end++ = __dc;
|
||||
// Stage 3
|
||||
__v = std::__num_get_unsigned_integral<_Unsigned>(__a, __a_end, __err, __base);
|
||||
// Digit grouping checked
|
||||
__check_grouping(__grouping, __g, __g_end, __err);
|
||||
// EOF checked
|
||||
if (__b == __e)
|
||||
__err |= ios_base::eofbit;
|
||||
return __b;
|
||||
}
|
||||
|
||||
// floating point
|
||||
|
||||
template <class _CharT, class _InputIterator>
|
||||
template <class _Fp>
|
||||
_InputIterator num_get<_CharT, _InputIterator>::__do_get_floating_point(
|
||||
iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, _Fp& __v) const {
|
||||
// Stage 1, nothing to do
|
||||
// Stage 2
|
||||
char_type __atoms[__num_get_base::__fp_chr_cnt];
|
||||
char_type __decimal_point;
|
||||
char_type __thousands_sep;
|
||||
string __grouping = this->__stage2_float_prep(__iob, __atoms, __decimal_point, __thousands_sep);
|
||||
string __buf;
|
||||
__buf.resize(__buf.capacity());
|
||||
char* __a = &__buf[0];
|
||||
char* __a_end = __a;
|
||||
unsigned __g[__num_get_base::__num_get_buf_sz];
|
||||
unsigned* __g_end = __g;
|
||||
unsigned __dc = 0;
|
||||
bool __in_units = true;
|
||||
char __exp = 'E';
|
||||
bool __is_leading_parsed = false;
|
||||
for (; __b != __e; ++__b) {
|
||||
if (__a_end == __a + __buf.size()) {
|
||||
size_t __tmp = __buf.size();
|
||||
__buf.resize(2 * __buf.size());
|
||||
__buf.resize(__buf.capacity());
|
||||
__a = &__buf[0];
|
||||
__a_end = __a + __tmp;
|
||||
}
|
||||
if (this->__stage2_float_loop(
|
||||
*__b,
|
||||
__in_units,
|
||||
__exp,
|
||||
__a,
|
||||
__a_end,
|
||||
__decimal_point,
|
||||
__thousands_sep,
|
||||
__grouping,
|
||||
__g,
|
||||
__g_end,
|
||||
__dc,
|
||||
__atoms))
|
||||
break;
|
||||
|
||||
// the leading character excluding the sign must be a decimal digit
|
||||
if (!__is_leading_parsed) {
|
||||
if (__a_end - __a >= 1 && __a[0] != '-' && __a[0] != '+') {
|
||||
if (('0' <= __a[0] && __a[0] <= '9') || __a[0] == '.')
|
||||
__is_leading_parsed = true;
|
||||
else
|
||||
break;
|
||||
} else if (__a_end - __a >= 2 && (__a[0] == '-' || __a[0] == '+')) {
|
||||
if (('0' <= __a[1] && __a[1] <= '9') || __a[1] == '.')
|
||||
__is_leading_parsed = true;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (__grouping.size() != 0 && __in_units && __g_end - __g < __num_get_base::__num_get_buf_sz)
|
||||
*__g_end++ = __dc;
|
||||
// Stage 3
|
||||
__v = std::__num_get_float<_Fp>(__a, __a_end, __err);
|
||||
// Digit grouping checked
|
||||
__check_grouping(__grouping, __g, __g_end, __err);
|
||||
// EOF checked
|
||||
if (__b == __e)
|
||||
__err |= ios_base::eofbit;
|
||||
return __b;
|
||||
}
|
||||
|
||||
template <class _CharT, class _InputIterator>
|
||||
_InputIterator num_get<_CharT, _InputIterator>::do_get(
|
||||
iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, void*& __v) const {
|
||||
|
||||
@@ -256,26 +256,24 @@ public:
|
||||
_LIBCPP_HIDE_FROM_ABI bool try_lock_for(const chrono::duration<_Rep, _Period>& __d) {
|
||||
return try_lock_until(chrono::steady_clock::now() + __d);
|
||||
}
|
||||
|
||||
template <class _Clock, class _Duration>
|
||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS bool
|
||||
try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
|
||||
_LIBCPP_HIDE_FROM_ABI bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) {
|
||||
using namespace chrono;
|
||||
unique_lock<mutex> __lk(__m_);
|
||||
bool __no_timeout = _Clock::now() < __t;
|
||||
while (__no_timeout && __locked_)
|
||||
__no_timeout = __cv_.wait_until(__lk, __t) == cv_status::no_timeout;
|
||||
if (!__locked_) {
|
||||
__locked_ = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void unlock() _NOEXCEPT;
|
||||
};
|
||||
|
||||
template <class _Clock, class _Duration>
|
||||
bool timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) {
|
||||
using namespace chrono;
|
||||
unique_lock<mutex> __lk(__m_);
|
||||
bool __no_timeout = _Clock::now() < __t;
|
||||
while (__no_timeout && __locked_)
|
||||
__no_timeout = __cv_.wait_until(__lk, __t) == cv_status::no_timeout;
|
||||
if (!__locked_) {
|
||||
__locked_ = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
class _LIBCPP_EXPORTED_FROM_ABI recursive_timed_mutex {
|
||||
mutex __m_;
|
||||
condition_variable __cv_;
|
||||
@@ -295,34 +293,32 @@ public:
|
||||
_LIBCPP_HIDE_FROM_ABI bool try_lock_for(const chrono::duration<_Rep, _Period>& __d) {
|
||||
return try_lock_until(chrono::steady_clock::now() + __d);
|
||||
}
|
||||
|
||||
template <class _Clock, class _Duration>
|
||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS bool
|
||||
try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
|
||||
_LIBCPP_HIDE_FROM_ABI bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) {
|
||||
using namespace chrono;
|
||||
__thread_id __id = this_thread::get_id();
|
||||
unique_lock<mutex> __lk(__m_);
|
||||
if (__id == __id_) {
|
||||
if (__count_ == numeric_limits<size_t>::max())
|
||||
return false;
|
||||
++__count_;
|
||||
return true;
|
||||
}
|
||||
bool __no_timeout = _Clock::now() < __t;
|
||||
while (__no_timeout && __count_ != 0)
|
||||
__no_timeout = __cv_.wait_until(__lk, __t) == cv_status::no_timeout;
|
||||
if (__count_ == 0) {
|
||||
__count_ = 1;
|
||||
__id_ = __id;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void unlock() _NOEXCEPT;
|
||||
};
|
||||
|
||||
template <class _Clock, class _Duration>
|
||||
bool recursive_timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) {
|
||||
using namespace chrono;
|
||||
__thread_id __id = this_thread::get_id();
|
||||
unique_lock<mutex> __lk(__m_);
|
||||
if (__id == __id_) {
|
||||
if (__count_ == numeric_limits<size_t>::max())
|
||||
return false;
|
||||
++__count_;
|
||||
return true;
|
||||
}
|
||||
bool __no_timeout = _Clock::now() < __t;
|
||||
while (__no_timeout && __count_ != 0)
|
||||
__no_timeout = __cv_.wait_until(__lk, __t) == cv_status::no_timeout;
|
||||
if (__count_ == 0) {
|
||||
__count_ = 1;
|
||||
__id_ = __id;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class _L0, class _L1>
|
||||
_LIBCPP_HIDE_FROM_ABI int try_lock(_L0& __l0, _L1& __l1) {
|
||||
unique_lock<_L0> __u0(__l0, try_to_lock_t());
|
||||
|
||||
@@ -240,10 +240,36 @@ public:
|
||||
_LIBCPP_THREAD_SAFETY_ANNOTATION(__try_acquire_capability__(true)) {
|
||||
return try_lock_until(chrono::steady_clock::now() + __rel_time);
|
||||
}
|
||||
|
||||
template <class _Clock, class _Duration>
|
||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS bool
|
||||
try_lock_until(const chrono::time_point<_Clock, _Duration>& __abs_time)
|
||||
_LIBCPP_THREAD_SAFETY_ANNOTATION(__try_acquire_capability__(true));
|
||||
_LIBCPP_HIDE_FROM_ABI bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __abs_time)
|
||||
_LIBCPP_THREAD_SAFETY_ANNOTATION(__try_acquire_capability__(true)) {
|
||||
unique_lock<mutex> __lk(__base_.__mut_);
|
||||
if (__base_.__state_ & __base_.__write_entered_) {
|
||||
while (true) {
|
||||
cv_status __status = __base_.__gate1_.wait_until(__lk, __abs_time);
|
||||
if ((__base_.__state_ & __base_.__write_entered_) == 0)
|
||||
break;
|
||||
if (__status == cv_status::timeout)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
__base_.__state_ |= __base_.__write_entered_;
|
||||
if (__base_.__state_ & __base_.__n_readers_) {
|
||||
while (true) {
|
||||
cv_status __status = __base_.__gate2_.wait_until(__lk, __abs_time);
|
||||
if ((__base_.__state_ & __base_.__n_readers_) == 0)
|
||||
break;
|
||||
if (__status == cv_status::timeout) {
|
||||
__base_.__state_ &= ~__base_.__write_entered_;
|
||||
__base_.__gate1_.notify_all();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void unlock() _LIBCPP_THREAD_SAFETY_ANNOTATION(__release_capability__());
|
||||
|
||||
// Shared ownership
|
||||
@@ -254,60 +280,30 @@ public:
|
||||
_LIBCPP_THREAD_SAFETY_ANNOTATION(__try_acquire_shared_capability__(true)) {
|
||||
return try_lock_shared_until(chrono::steady_clock::now() + __rel_time);
|
||||
}
|
||||
template <class _Clock, class _Duration>
|
||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS bool
|
||||
try_lock_shared_until(const chrono::time_point<_Clock, _Duration>& __abs_time)
|
||||
_LIBCPP_THREAD_SAFETY_ANNOTATION(__try_acquire_shared_capability__(true));
|
||||
void unlock_shared() _LIBCPP_THREAD_SAFETY_ANNOTATION(__release_shared_capability__());
|
||||
};
|
||||
|
||||
template <class _Clock, class _Duration>
|
||||
bool shared_timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __abs_time) {
|
||||
unique_lock<mutex> __lk(__base_.__mut_);
|
||||
if (__base_.__state_ & __base_.__write_entered_) {
|
||||
while (true) {
|
||||
cv_status __status = __base_.__gate1_.wait_until(__lk, __abs_time);
|
||||
if ((__base_.__state_ & __base_.__write_entered_) == 0)
|
||||
break;
|
||||
if (__status == cv_status::timeout)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
__base_.__state_ |= __base_.__write_entered_;
|
||||
if (__base_.__state_ & __base_.__n_readers_) {
|
||||
while (true) {
|
||||
cv_status __status = __base_.__gate2_.wait_until(__lk, __abs_time);
|
||||
if ((__base_.__state_ & __base_.__n_readers_) == 0)
|
||||
break;
|
||||
if (__status == cv_status::timeout) {
|
||||
__base_.__state_ &= ~__base_.__write_entered_;
|
||||
__base_.__gate1_.notify_all();
|
||||
return false;
|
||||
template <class _Clock, class _Duration>
|
||||
_LIBCPP_HIDE_FROM_ABI bool try_lock_shared_until(const chrono::time_point<_Clock, _Duration>& __abs_time)
|
||||
_LIBCPP_THREAD_SAFETY_ANNOTATION(__try_acquire_shared_capability__(true)) {
|
||||
unique_lock<mutex> __lk(__base_.__mut_);
|
||||
if ((__base_.__state_ & __base_.__write_entered_) ||
|
||||
(__base_.__state_ & __base_.__n_readers_) == __base_.__n_readers_) {
|
||||
while (true) {
|
||||
cv_status __status = __base_.__gate1_.wait_until(__lk, __abs_time);
|
||||
if ((__base_.__state_ & __base_.__write_entered_) == 0 &&
|
||||
(__base_.__state_ & __base_.__n_readers_) < __base_.__n_readers_)
|
||||
break;
|
||||
if (__status == cv_status::timeout)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
unsigned __num_readers = (__base_.__state_ & __base_.__n_readers_) + 1;
|
||||
__base_.__state_ &= ~__base_.__n_readers_;
|
||||
__base_.__state_ |= __num_readers;
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class _Clock, class _Duration>
|
||||
bool shared_timed_mutex::try_lock_shared_until(const chrono::time_point<_Clock, _Duration>& __abs_time) {
|
||||
unique_lock<mutex> __lk(__base_.__mut_);
|
||||
if ((__base_.__state_ & __base_.__write_entered_) ||
|
||||
(__base_.__state_ & __base_.__n_readers_) == __base_.__n_readers_) {
|
||||
while (true) {
|
||||
cv_status __status = __base_.__gate1_.wait_until(__lk, __abs_time);
|
||||
if ((__base_.__state_ & __base_.__write_entered_) == 0 &&
|
||||
(__base_.__state_ & __base_.__n_readers_) < __base_.__n_readers_)
|
||||
break;
|
||||
if (__status == cv_status::timeout)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
unsigned __num_readers = (__base_.__state_ & __base_.__n_readers_) + 1;
|
||||
__base_.__state_ &= ~__base_.__n_readers_;
|
||||
__base_.__state_ |= __num_readers;
|
||||
return true;
|
||||
}
|
||||
void unlock_shared() _LIBCPP_THREAD_SAFETY_ANNOTATION(__release_shared_capability__());
|
||||
};
|
||||
|
||||
template <class _Mutex>
|
||||
class shared_lock {
|
||||
|
||||
@@ -1117,7 +1117,7 @@ public:
|
||||
__enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value &&
|
||||
!__is_same_uncvref<_Tp, basic_string>::value,
|
||||
int> = 0>
|
||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
|
||||
basic_string(const _Tp& __t, size_type __pos, size_type __n, const allocator_type& __a = allocator_type())
|
||||
: __alloc_(__a) {
|
||||
__self_view __sv0 = __t;
|
||||
@@ -1129,8 +1129,7 @@ public:
|
||||
__enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value &&
|
||||
!__is_same_uncvref<_Tp, basic_string>::value,
|
||||
int> = 0>
|
||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 explicit basic_string(const _Tp& __t) {
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit basic_string(const _Tp& __t) {
|
||||
__self_view __sv = __t;
|
||||
__init(__sv.data(), __sv.size());
|
||||
}
|
||||
@@ -1139,8 +1138,7 @@ public:
|
||||
__enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value &&
|
||||
!__is_same_uncvref<_Tp, basic_string>::value,
|
||||
int> = 0>
|
||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 explicit basic_string(const _Tp& __t, const allocator_type& __a)
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit basic_string(const _Tp& __t, const allocator_type& __a)
|
||||
: __alloc_(__a) {
|
||||
__self_view __sv = __t;
|
||||
__init(__sv.data(), __sv.size());
|
||||
@@ -1336,8 +1334,7 @@ public:
|
||||
__enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value &&
|
||||
!__is_same_uncvref<_Tp, basic_string >::value,
|
||||
int> = 0>
|
||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
|
||||
operator+=(const _Tp& __t) {
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& operator+=(const _Tp& __t) {
|
||||
__self_view __sv = __t;
|
||||
return append(__sv);
|
||||
}
|
||||
@@ -1366,8 +1363,7 @@ public:
|
||||
__enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value &&
|
||||
!__is_same_uncvref<_Tp, basic_string>::value,
|
||||
int> = 0>
|
||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
|
||||
append(const _Tp& __t) {
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(const _Tp& __t) {
|
||||
__self_view __sv = __t;
|
||||
return append(__sv.data(), __sv.size());
|
||||
}
|
||||
@@ -1378,10 +1374,14 @@ public:
|
||||
__enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value &&
|
||||
!__is_same_uncvref<_Tp, basic_string>::value,
|
||||
int> = 0>
|
||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20
|
||||
|
||||
basic_string&
|
||||
append(const _Tp& __t, size_type __pos, size_type __n = npos);
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
|
||||
append(const _Tp& __t, size_type __pos, size_type __n = npos) {
|
||||
__self_view __sv = __t;
|
||||
size_type __sz = __sv.size();
|
||||
if (__pos > __sz)
|
||||
__throw_out_of_range();
|
||||
return append(__sv.data() + __pos, std::min(__n, __sz - __pos));
|
||||
}
|
||||
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(const value_type* __s, size_type __n);
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(const value_type* _LIBCPP_DIAGNOSE_NULLPTR __s);
|
||||
@@ -1390,7 +1390,7 @@ public:
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __append_default_init(size_type __n);
|
||||
|
||||
template <class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> = 0>
|
||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
|
||||
append(_InputIterator __first, _InputIterator __last) {
|
||||
const basic_string __temp(__first, __last, __alloc_);
|
||||
append(__temp.data(), __temp.size());
|
||||
@@ -1398,8 +1398,26 @@ public:
|
||||
}
|
||||
|
||||
template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> = 0>
|
||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
|
||||
append(_ForwardIterator __first, _ForwardIterator __last);
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
|
||||
append(_ForwardIterator __first, _ForwardIterator __last) {
|
||||
size_type __sz = size();
|
||||
size_type __cap = capacity();
|
||||
size_type __n = static_cast<size_type>(std::distance(__first, __last));
|
||||
if (__n) {
|
||||
if (__string_is_trivial_iterator<_ForwardIterator>::value && !__addr_in_range(*__first)) {
|
||||
if (__cap - __sz < __n)
|
||||
__grow_by_without_replace(__cap, __sz + __n - __cap, __sz, __sz, 0);
|
||||
__annotate_increase(__n);
|
||||
auto __end = __copy_non_overlapping_range(__first, __last, std::__to_address(__get_pointer() + __sz));
|
||||
traits_type::assign(*__end, value_type());
|
||||
__set_size(__sz + __n);
|
||||
} else {
|
||||
const basic_string __temp(__first, __last, __alloc_);
|
||||
append(__temp.data(), __temp.size());
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
# if _LIBCPP_STD_VER >= 23
|
||||
template <_ContainerCompatibleRange<_CharT> _Range>
|
||||
@@ -1439,8 +1457,7 @@ public:
|
||||
}
|
||||
|
||||
template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0>
|
||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
|
||||
assign(const _Tp& __t) {
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(const _Tp& __t) {
|
||||
__self_view __sv = __t;
|
||||
return assign(__sv.data(), __sv.size());
|
||||
}
|
||||
@@ -1484,19 +1501,38 @@ public:
|
||||
__enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value &&
|
||||
!__is_same_uncvref<_Tp, basic_string>::value,
|
||||
int> = 0>
|
||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
|
||||
assign(const _Tp& __t, size_type __pos, size_type __n = npos);
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
|
||||
assign(const _Tp& __t, size_type __pos, size_type __n = npos) {
|
||||
__self_view __sv = __t;
|
||||
size_type __sz = __sv.size();
|
||||
if (__pos > __sz)
|
||||
__throw_out_of_range();
|
||||
return assign(__sv.data() + __pos, std::min(__n, __sz - __pos));
|
||||
}
|
||||
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(const value_type* __s, size_type __n);
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(const value_type* __s);
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(size_type __n, value_type __c);
|
||||
|
||||
template <class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> = 0>
|
||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
|
||||
assign(_InputIterator __first, _InputIterator __last);
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
|
||||
assign(_InputIterator __first, _InputIterator __last) {
|
||||
__assign_with_sentinel(__first, __last);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> = 0>
|
||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
|
||||
assign(_ForwardIterator __first, _ForwardIterator __last);
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
|
||||
assign(_ForwardIterator __first, _ForwardIterator __last) {
|
||||
if (__string_is_trivial_iterator<_ForwardIterator>::value) {
|
||||
size_type __n = static_cast<size_type>(std::distance(__first, __last));
|
||||
__assign_trivial(__first, __last, __n);
|
||||
} else {
|
||||
__assign_with_sentinel(__first, __last);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
# if _LIBCPP_STD_VER >= 23
|
||||
template <_ContainerCompatibleRange<_CharT> _Range>
|
||||
@@ -1526,8 +1562,7 @@ public:
|
||||
}
|
||||
|
||||
template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0>
|
||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
|
||||
insert(size_type __pos1, const _Tp& __t) {
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& insert(size_type __pos1, const _Tp& __t) {
|
||||
__self_view __sv = __t;
|
||||
return insert(__pos1, __sv.data(), __sv.size());
|
||||
}
|
||||
@@ -1536,8 +1571,14 @@ public:
|
||||
__enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value &&
|
||||
!__is_same_uncvref<_Tp, basic_string>::value,
|
||||
int> = 0>
|
||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
|
||||
insert(size_type __pos1, const _Tp& __t, size_type __pos2, size_type __n = npos);
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
|
||||
insert(size_type __pos1, const _Tp& __t, size_type __pos2, size_type __n = npos) {
|
||||
__self_view __sv = __t;
|
||||
size_type __str_sz = __sv.size();
|
||||
if (__pos2 > __str_sz)
|
||||
__throw_out_of_range();
|
||||
return insert(__pos1, __sv.data() + __pos2, std::min(__n, __str_sz - __pos2));
|
||||
}
|
||||
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
|
||||
insert(size_type __pos1, const basic_string& __str, size_type __pos2, size_type __n = npos);
|
||||
@@ -1568,12 +1609,18 @@ public:
|
||||
}
|
||||
|
||||
template <class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> = 0>
|
||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator
|
||||
insert(const_iterator __pos, _InputIterator __first, _InputIterator __last);
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator
|
||||
insert(const_iterator __pos, _InputIterator __first, _InputIterator __last) {
|
||||
const basic_string __temp(__first, __last, __alloc_);
|
||||
return insert(__pos, __temp.data(), __temp.data() + __temp.size());
|
||||
}
|
||||
|
||||
template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> = 0>
|
||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator
|
||||
insert(const_iterator __pos, _ForwardIterator __first, _ForwardIterator __last);
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator
|
||||
insert(const_iterator __pos, _ForwardIterator __first, _ForwardIterator __last) {
|
||||
auto __n = static_cast<size_type>(std::distance(__first, __last));
|
||||
return __insert_with_size(__pos, __first, __last, __n);
|
||||
}
|
||||
|
||||
# ifndef _LIBCPP_CXX03_LANG
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator
|
||||
@@ -1592,7 +1639,7 @@ public:
|
||||
}
|
||||
|
||||
template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0>
|
||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
|
||||
replace(size_type __pos1, size_type __n1, const _Tp& __t) {
|
||||
__self_view __sv = __t;
|
||||
return replace(__pos1, __n1, __sv.data(), __sv.size());
|
||||
@@ -1605,8 +1652,14 @@ public:
|
||||
__enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value &&
|
||||
!__is_same_uncvref<_Tp, basic_string>::value,
|
||||
int> = 0>
|
||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
|
||||
replace(size_type __pos1, size_type __n1, const _Tp& __t, size_type __pos2, size_type __n2 = npos);
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
|
||||
replace(size_type __pos1, size_type __n1, const _Tp& __t, size_type __pos2, size_type __n2 = npos) {
|
||||
__self_view __sv = __t;
|
||||
size_type __str_sz = __sv.size();
|
||||
if (__pos2 > __str_sz)
|
||||
__throw_out_of_range();
|
||||
return replace(__pos1, __n1, __sv.data() + __pos2, std::min(__n2, __str_sz - __pos2));
|
||||
}
|
||||
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
|
||||
replace(size_type __pos, size_type __n1, const value_type* __s, size_type __n2);
|
||||
@@ -1620,7 +1673,7 @@ public:
|
||||
}
|
||||
|
||||
template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0>
|
||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
|
||||
replace(const_iterator __i1, const_iterator __i2, const _Tp& __t) {
|
||||
__self_view __sv = __t;
|
||||
return replace(__i1 - begin(), __i2 - __i1, __sv);
|
||||
@@ -1642,8 +1695,11 @@ public:
|
||||
}
|
||||
|
||||
template <class _InputIterator, __enable_if_t<__has_input_iterator_category<_InputIterator>::value, int> = 0>
|
||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
|
||||
replace(const_iterator __i1, const_iterator __i2, _InputIterator __j1, _InputIterator __j2);
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
|
||||
replace(const_iterator __i1, const_iterator __i2, _InputIterator __j1, _InputIterator __j2) {
|
||||
const basic_string __temp(__j1, __j2, __alloc_);
|
||||
return replace(__i1, __i2, __temp);
|
||||
}
|
||||
|
||||
# if _LIBCPP_STD_VER >= 23
|
||||
template <_ContainerCompatibleRange<_CharT> _Range>
|
||||
@@ -1710,7 +1766,7 @@ public:
|
||||
}
|
||||
|
||||
template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0>
|
||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type
|
||||
find(const _Tp& __t, size_type __pos = 0) const _NOEXCEPT {
|
||||
__self_view __sv = __t;
|
||||
return std::__str_find<value_type, size_type, traits_type, npos>(data(), size(), __sv.data(), __pos, __sv.size());
|
||||
@@ -1741,7 +1797,7 @@ public:
|
||||
}
|
||||
|
||||
template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0>
|
||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type
|
||||
rfind(const _Tp& __t, size_type __pos = npos) const _NOEXCEPT {
|
||||
__self_view __sv = __t;
|
||||
return std::__str_rfind<value_type, size_type, traits_type, npos>(data(), size(), __sv.data(), __pos, __sv.size());
|
||||
@@ -1772,7 +1828,7 @@ public:
|
||||
}
|
||||
|
||||
template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0>
|
||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type
|
||||
find_first_of(const _Tp& __t, size_type __pos = 0) const _NOEXCEPT {
|
||||
__self_view __sv = __t;
|
||||
return std::__str_find_first_of<value_type, size_type, traits_type, npos>(
|
||||
@@ -1806,7 +1862,7 @@ public:
|
||||
}
|
||||
|
||||
template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0>
|
||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type
|
||||
find_last_of(const _Tp& __t, size_type __pos = npos) const _NOEXCEPT {
|
||||
__self_view __sv = __t;
|
||||
return std::__str_find_last_of<value_type, size_type, traits_type, npos>(
|
||||
@@ -1840,7 +1896,7 @@ public:
|
||||
}
|
||||
|
||||
template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0>
|
||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type
|
||||
find_first_not_of(const _Tp& __t, size_type __pos = 0) const _NOEXCEPT {
|
||||
__self_view __sv = __t;
|
||||
return std::__str_find_first_not_of<value_type, size_type, traits_type, npos>(
|
||||
@@ -1874,7 +1930,7 @@ public:
|
||||
}
|
||||
|
||||
template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0>
|
||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type
|
||||
find_last_not_of(const _Tp& __t, size_type __pos = npos) const _NOEXCEPT {
|
||||
__self_view __sv = __t;
|
||||
return std::__str_find_last_not_of<value_type, size_type, traits_type, npos>(
|
||||
@@ -1906,11 +1962,22 @@ public:
|
||||
}
|
||||
|
||||
template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0>
|
||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 int
|
||||
compare(const _Tp& __t) const _NOEXCEPT;
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 int compare(const _Tp& __t) const _NOEXCEPT {
|
||||
__self_view __sv = __t;
|
||||
size_t __lhs_sz = size();
|
||||
size_t __rhs_sz = __sv.size();
|
||||
int __result = traits_type::compare(data(), __sv.data(), std::min(__lhs_sz, __rhs_sz));
|
||||
if (__result != 0)
|
||||
return __result;
|
||||
if (__lhs_sz < __rhs_sz)
|
||||
return -1;
|
||||
if (__lhs_sz > __rhs_sz)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0>
|
||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 int
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 int
|
||||
compare(size_type __pos1, size_type __n1, const _Tp& __t) const {
|
||||
__self_view __sv = __t;
|
||||
return compare(__pos1, __n1, __sv.data(), __sv.size());
|
||||
@@ -2877,14 +2944,6 @@ basic_string<_CharT, _Traits, _Allocator>::__move_assign(basic_string& __str, tr
|
||||
|
||||
# endif
|
||||
|
||||
template <class _CharT, class _Traits, class _Allocator>
|
||||
template <class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> >
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>&
|
||||
basic_string<_CharT, _Traits, _Allocator>::assign(_InputIterator __first, _InputIterator __last) {
|
||||
__assign_with_sentinel(__first, __last);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class _CharT, class _Traits, class _Allocator>
|
||||
template <class _InputIterator, class _Sentinel>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
|
||||
@@ -2893,20 +2952,6 @@ basic_string<_CharT, _Traits, _Allocator>::__assign_with_sentinel(_InputIterator
|
||||
assign(__temp.data(), __temp.size());
|
||||
}
|
||||
|
||||
template <class _CharT, class _Traits, class _Allocator>
|
||||
template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> >
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>&
|
||||
basic_string<_CharT, _Traits, _Allocator>::assign(_ForwardIterator __first, _ForwardIterator __last) {
|
||||
if (__string_is_trivial_iterator<_ForwardIterator>::value) {
|
||||
size_type __n = static_cast<size_type>(std::distance(__first, __last));
|
||||
__assign_trivial(__first, __last, __n);
|
||||
} else {
|
||||
__assign_with_sentinel(__first, __last);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class _CharT, class _Traits, class _Allocator>
|
||||
template <class _Iterator, class _Sentinel>
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
|
||||
@@ -2946,20 +2991,6 @@ basic_string<_CharT, _Traits, _Allocator>::assign(const basic_string& __str, siz
|
||||
return assign(__str.data() + __pos, std::min(__n, __sz - __pos));
|
||||
}
|
||||
|
||||
template <class _CharT, class _Traits, class _Allocator>
|
||||
template <class _Tp,
|
||||
__enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value &&
|
||||
!__is_same_uncvref<_Tp, basic_string<_CharT, _Traits, _Allocator> >::value,
|
||||
int> >
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>&
|
||||
basic_string<_CharT, _Traits, _Allocator>::assign(const _Tp& __t, size_type __pos, size_type __n) {
|
||||
__self_view __sv = __t;
|
||||
size_type __sz = __sv.size();
|
||||
if (__pos > __sz)
|
||||
this->__throw_out_of_range();
|
||||
return assign(__sv.data() + __pos, std::min(__n, __sz - __pos));
|
||||
}
|
||||
|
||||
template <class _CharT, class _Traits, class _Allocator>
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE basic_string<_CharT, _Traits, _Allocator>&
|
||||
basic_string<_CharT, _Traits, _Allocator>::__assign_external(const value_type* __s) {
|
||||
@@ -3059,29 +3090,6 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::pu
|
||||
traits_type::assign(*++__p, value_type());
|
||||
}
|
||||
|
||||
template <class _CharT, class _Traits, class _Allocator>
|
||||
template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> >
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>&
|
||||
basic_string<_CharT, _Traits, _Allocator>::append(_ForwardIterator __first, _ForwardIterator __last) {
|
||||
size_type __sz = size();
|
||||
size_type __cap = capacity();
|
||||
size_type __n = static_cast<size_type>(std::distance(__first, __last));
|
||||
if (__n) {
|
||||
if (__string_is_trivial_iterator<_ForwardIterator>::value && !__addr_in_range(*__first)) {
|
||||
if (__cap - __sz < __n)
|
||||
__grow_by_without_replace(__cap, __sz + __n - __cap, __sz, __sz, 0);
|
||||
__annotate_increase(__n);
|
||||
auto __end = __copy_non_overlapping_range(__first, __last, std::__to_address(__get_pointer() + __sz));
|
||||
traits_type::assign(*__end, value_type());
|
||||
__set_size(__sz + __n);
|
||||
} else {
|
||||
const basic_string __temp(__first, __last, __alloc_);
|
||||
append(__temp.data(), __temp.size());
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class _CharT, class _Traits, class _Allocator>
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>&
|
||||
basic_string<_CharT, _Traits, _Allocator>::append(const basic_string& __str, size_type __pos, size_type __n) {
|
||||
@@ -3091,20 +3099,6 @@ basic_string<_CharT, _Traits, _Allocator>::append(const basic_string& __str, siz
|
||||
return append(__str.data() + __pos, std::min(__n, __sz - __pos));
|
||||
}
|
||||
|
||||
template <class _CharT, class _Traits, class _Allocator>
|
||||
template <class _Tp,
|
||||
__enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value &&
|
||||
!__is_same_uncvref<_Tp, basic_string<_CharT, _Traits, _Allocator> >::value,
|
||||
int> >
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>&
|
||||
basic_string<_CharT, _Traits, _Allocator>::append(const _Tp& __t, size_type __pos, size_type __n) {
|
||||
__self_view __sv = __t;
|
||||
size_type __sz = __sv.size();
|
||||
if (__pos > __sz)
|
||||
this->__throw_out_of_range();
|
||||
return append(__sv.data() + __pos, std::min(__n, __sz - __pos));
|
||||
}
|
||||
|
||||
template <class _CharT, class _Traits, class _Allocator>
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>&
|
||||
basic_string<_CharT, _Traits, _Allocator>::append(const value_type* __s) {
|
||||
@@ -3169,23 +3163,6 @@ basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos, size_type __n
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class _CharT, class _Traits, class _Allocator>
|
||||
template <class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> >
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::iterator
|
||||
basic_string<_CharT, _Traits, _Allocator>::insert(const_iterator __pos, _InputIterator __first, _InputIterator __last) {
|
||||
const basic_string __temp(__first, __last, __alloc_);
|
||||
return insert(__pos, __temp.data(), __temp.data() + __temp.size());
|
||||
}
|
||||
|
||||
template <class _CharT, class _Traits, class _Allocator>
|
||||
template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> >
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::iterator
|
||||
basic_string<_CharT, _Traits, _Allocator>::insert(
|
||||
const_iterator __pos, _ForwardIterator __first, _ForwardIterator __last) {
|
||||
auto __n = static_cast<size_type>(std::distance(__first, __last));
|
||||
return __insert_with_size(__pos, __first, __last, __n);
|
||||
}
|
||||
|
||||
template <class _CharT, class _Traits, class _Allocator>
|
||||
template <class _Iterator, class _Sentinel>
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::iterator
|
||||
@@ -3213,20 +3190,6 @@ basic_string<_CharT, _Traits, _Allocator>::insert(
|
||||
return insert(__pos1, __str.data() + __pos2, std::min(__n, __str_sz - __pos2));
|
||||
}
|
||||
|
||||
template <class _CharT, class _Traits, class _Allocator>
|
||||
template <class _Tp,
|
||||
__enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value &&
|
||||
!__is_same_uncvref<_Tp, basic_string<_CharT, _Traits, _Allocator> >::value,
|
||||
int> >
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>&
|
||||
basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos1, const _Tp& __t, size_type __pos2, size_type __n) {
|
||||
__self_view __sv = __t;
|
||||
size_type __str_sz = __sv.size();
|
||||
if (__pos2 > __str_sz)
|
||||
this->__throw_out_of_range();
|
||||
return insert(__pos1, __sv.data() + __pos2, std::min(__n, __str_sz - __pos2));
|
||||
}
|
||||
|
||||
template <class _CharT, class _Traits, class _Allocator>
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>&
|
||||
basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos, const value_type* __s) {
|
||||
@@ -3330,15 +3293,6 @@ basic_string<_CharT, _Traits, _Allocator>::replace(size_type __pos, size_type __
|
||||
return __null_terminate_at(__p, __sz - (__n1 - __n2));
|
||||
}
|
||||
|
||||
template <class _CharT, class _Traits, class _Allocator>
|
||||
template <class _InputIterator, __enable_if_t<__has_input_iterator_category<_InputIterator>::value, int> >
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>&
|
||||
basic_string<_CharT, _Traits, _Allocator>::replace(
|
||||
const_iterator __i1, const_iterator __i2, _InputIterator __j1, _InputIterator __j2) {
|
||||
const basic_string __temp(__j1, __j2, __alloc_);
|
||||
return replace(__i1, __i2, __temp);
|
||||
}
|
||||
|
||||
template <class _CharT, class _Traits, class _Allocator>
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>&
|
||||
basic_string<_CharT, _Traits, _Allocator>::replace(
|
||||
@@ -3349,21 +3303,6 @@ basic_string<_CharT, _Traits, _Allocator>::replace(
|
||||
return replace(__pos1, __n1, __str.data() + __pos2, std::min(__n2, __str_sz - __pos2));
|
||||
}
|
||||
|
||||
template <class _CharT, class _Traits, class _Allocator>
|
||||
template <class _Tp,
|
||||
__enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value &&
|
||||
!__is_same_uncvref<_Tp, basic_string<_CharT, _Traits, _Allocator> >::value,
|
||||
int> >
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>&
|
||||
basic_string<_CharT, _Traits, _Allocator>::replace(
|
||||
size_type __pos1, size_type __n1, const _Tp& __t, size_type __pos2, size_type __n2) {
|
||||
__self_view __sv = __t;
|
||||
size_type __str_sz = __sv.size();
|
||||
if (__pos2 > __str_sz)
|
||||
this->__throw_out_of_range();
|
||||
return replace(__pos1, __n1, __sv.data() + __pos2, std::min(__n2, __str_sz - __pos2));
|
||||
}
|
||||
|
||||
template <class _CharT, class _Traits, class _Allocator>
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>&
|
||||
basic_string<_CharT, _Traits, _Allocator>::replace(size_type __pos, size_type __n1, const value_type* __s) {
|
||||
@@ -3586,22 +3525,6 @@ inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocat
|
||||
|
||||
// compare
|
||||
|
||||
template <class _CharT, class _Traits, class _Allocator>
|
||||
template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> >
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 int basic_string<_CharT, _Traits, _Allocator>::compare(const _Tp& __t) const _NOEXCEPT {
|
||||
__self_view __sv = __t;
|
||||
size_t __lhs_sz = size();
|
||||
size_t __rhs_sz = __sv.size();
|
||||
int __result = traits_type::compare(data(), __sv.data(), std::min(__lhs_sz, __rhs_sz));
|
||||
if (__result != 0)
|
||||
return __result;
|
||||
if (__lhs_sz < __rhs_sz)
|
||||
return -1;
|
||||
if (__lhs_sz > __rhs_sz)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class _CharT, class _Traits, class _Allocator>
|
||||
inline _LIBCPP_CONSTEXPR_SINCE_CXX20 int basic_string<_CharT, _Traits, _Allocator>::compare(
|
||||
size_type __pos1, size_type __n1, const value_type* __s, size_type __n2) const {
|
||||
|
||||
Reference in New Issue
Block a user