mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-27 14:58:30 +00:00
Release Cosmopolitan v3.6.0
This release is an atomic upgrade to GCC 14.1.0 with C23 and C++23
This commit is contained in:
parent
62ace3623a
commit
5660ec4741
1585 changed files with 117353 additions and 271644 deletions
80
third_party/libcxx/__thread/formatter.h
vendored
Normal file
80
third_party/libcxx/__thread/formatter.h
vendored
Normal file
|
@ -0,0 +1,80 @@
|
|||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _LIBCPP___THREAD_FORMATTER_H
|
||||
#define _LIBCPP___THREAD_FORMATTER_H
|
||||
|
||||
#include <__concepts/arithmetic.h>
|
||||
#include <__config>
|
||||
#include <__format/concepts.h>
|
||||
#include <__format/format_parse_context.h>
|
||||
#include <__format/formatter.h>
|
||||
#include <__format/formatter_integral.h>
|
||||
#include <__format/parser_std_format_spec.h>
|
||||
#include <__thread/id.h>
|
||||
#include <__type_traits/conditional.h>
|
||||
#include <__type_traits/is_pointer.h>
|
||||
#include <__type_traits/is_same.h>
|
||||
#include <cstdint>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
# pragma GCC system_header
|
||||
#endif
|
||||
|
||||
#if _LIBCPP_STD_VER >= 23
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
# ifndef _LIBCPP_HAS_NO_THREADS
|
||||
|
||||
template <__fmt_char_type _CharT>
|
||||
struct _LIBCPP_TEMPLATE_VIS formatter<__thread_id, _CharT> {
|
||||
public:
|
||||
template <class _ParseContext>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) {
|
||||
return __parser_.__parse(__ctx, __format_spec::__fields_fill_align_width);
|
||||
}
|
||||
|
||||
template <class _FormatContext>
|
||||
_LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator format(__thread_id __id, _FormatContext& __ctx) const {
|
||||
// In __thread/support/pthread.h, __libcpp_thread_id is either a
|
||||
// unsigned long long or a pthread_t.
|
||||
//
|
||||
// The type of pthread_t is left unspecified in POSIX so it can be any
|
||||
// type. The most logical types are an integral or pointer.
|
||||
// On Linux systems pthread_t is an unsigned long long.
|
||||
// On Apple systems pthread_t is a pointer type.
|
||||
//
|
||||
// Note the output should match what the stream operator does. Since
|
||||
// the ostream operator has been shipped years before this formatter
|
||||
// was added to the Standard, this formatter does what the stream
|
||||
// operator does. This may require platform specific changes.
|
||||
|
||||
using _Tp = decltype(__get_underlying_id(__id));
|
||||
using _Cp = conditional_t<integral<_Tp>, _Tp, conditional_t<is_pointer_v<_Tp>, uintptr_t, void>>;
|
||||
static_assert(!is_same_v<_Cp, void>, "unsupported thread::id type, please file a bug report");
|
||||
|
||||
__format_spec::__parsed_specifications<_CharT> __specs = __parser_.__get_parsed_std_specifications(__ctx);
|
||||
if constexpr (is_pointer_v<_Tp>) {
|
||||
__specs.__std_.__alternate_form_ = true;
|
||||
__specs.__std_.__type_ = __format_spec::__type::__hexadecimal_lower_case;
|
||||
}
|
||||
return __formatter::__format_integer(reinterpret_cast<_Cp>(__get_underlying_id(__id)), __ctx, __specs);
|
||||
}
|
||||
|
||||
__format_spec::__parser<_CharT> __parser_{.__alignment_ = __format_spec::__alignment::__right};
|
||||
};
|
||||
|
||||
# endif // !_LIBCPP_HAS_NO_THREADS
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCPP_STD_VER >= 23
|
||||
|
||||
#endif // _LIBCPP___THREAD_FORMATTER_H
|
121
third_party/libcxx/__thread/id.h
vendored
Normal file
121
third_party/libcxx/__thread/id.h
vendored
Normal file
|
@ -0,0 +1,121 @@
|
|||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _LIBCPP___THREAD_ID_H
|
||||
#define _LIBCPP___THREAD_ID_H
|
||||
|
||||
#include <__compare/ordering.h>
|
||||
#include <__config>
|
||||
#include <__fwd/functional.h>
|
||||
#include <__fwd/ostream.h>
|
||||
#include <__thread/support.h>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
# pragma GCC system_header
|
||||
#endif
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_THREADS
|
||||
class _LIBCPP_EXPORTED_FROM_ABI __thread_id;
|
||||
|
||||
namespace this_thread {
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI __thread_id get_id() _NOEXCEPT;
|
||||
|
||||
} // namespace this_thread
|
||||
|
||||
template <>
|
||||
struct hash<__thread_id>;
|
||||
|
||||
class _LIBCPP_TEMPLATE_VIS __thread_id {
|
||||
// FIXME: pthread_t is a pointer on Darwin but a long on Linux.
|
||||
// NULL is the no-thread value on Darwin. Someone needs to check
|
||||
// on other platforms. We assume 0 works everywhere for now.
|
||||
__libcpp_thread_id __id_;
|
||||
|
||||
static _LIBCPP_HIDE_FROM_ABI bool
|
||||
__lt_impl(__thread_id __x, __thread_id __y) _NOEXCEPT { // id==0 is always less than any other thread_id
|
||||
if (__x.__id_ == 0)
|
||||
return __y.__id_ != 0;
|
||||
if (__y.__id_ == 0)
|
||||
return false;
|
||||
return __libcpp_thread_id_less(__x.__id_, __y.__id_);
|
||||
}
|
||||
|
||||
public:
|
||||
_LIBCPP_HIDE_FROM_ABI __thread_id() _NOEXCEPT : __id_(0) {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI void __reset() { __id_ = 0; }
|
||||
|
||||
friend _LIBCPP_HIDE_FROM_ABI bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT;
|
||||
# if _LIBCPP_STD_VER <= 17
|
||||
friend _LIBCPP_HIDE_FROM_ABI bool operator<(__thread_id __x, __thread_id __y) _NOEXCEPT;
|
||||
# else // _LIBCPP_STD_VER <= 17
|
||||
friend _LIBCPP_HIDE_FROM_ABI strong_ordering operator<=>(__thread_id __x, __thread_id __y) noexcept;
|
||||
# endif // _LIBCPP_STD_VER <= 17
|
||||
|
||||
template <class _CharT, class _Traits>
|
||||
friend _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>&
|
||||
operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id);
|
||||
|
||||
private:
|
||||
_LIBCPP_HIDE_FROM_ABI __thread_id(__libcpp_thread_id __id) : __id_(__id) {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI friend __libcpp_thread_id __get_underlying_id(const __thread_id __id) { return __id.__id_; }
|
||||
|
||||
friend __thread_id this_thread::get_id() _NOEXCEPT;
|
||||
friend class _LIBCPP_EXPORTED_FROM_ABI thread;
|
||||
friend struct _LIBCPP_TEMPLATE_VIS hash<__thread_id>;
|
||||
};
|
||||
|
||||
inline _LIBCPP_HIDE_FROM_ABI bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT {
|
||||
// Don't pass id==0 to underlying routines
|
||||
if (__x.__id_ == 0)
|
||||
return __y.__id_ == 0;
|
||||
if (__y.__id_ == 0)
|
||||
return false;
|
||||
return __libcpp_thread_id_equal(__x.__id_, __y.__id_);
|
||||
}
|
||||
|
||||
# if _LIBCPP_STD_VER <= 17
|
||||
|
||||
inline _LIBCPP_HIDE_FROM_ABI bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT { return !(__x == __y); }
|
||||
|
||||
inline _LIBCPP_HIDE_FROM_ABI bool operator<(__thread_id __x, __thread_id __y) _NOEXCEPT {
|
||||
return __thread_id::__lt_impl(__x.__id_, __y.__id_);
|
||||
}
|
||||
|
||||
inline _LIBCPP_HIDE_FROM_ABI bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT { return !(__y < __x); }
|
||||
inline _LIBCPP_HIDE_FROM_ABI bool operator>(__thread_id __x, __thread_id __y) _NOEXCEPT { return __y < __x; }
|
||||
inline _LIBCPP_HIDE_FROM_ABI bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT { return !(__x < __y); }
|
||||
|
||||
# else // _LIBCPP_STD_VER <= 17
|
||||
|
||||
inline _LIBCPP_HIDE_FROM_ABI strong_ordering operator<=>(__thread_id __x, __thread_id __y) noexcept {
|
||||
if (__x == __y)
|
||||
return strong_ordering::equal;
|
||||
if (__thread_id::__lt_impl(__x, __y))
|
||||
return strong_ordering::less;
|
||||
return strong_ordering::greater;
|
||||
}
|
||||
|
||||
# endif // _LIBCPP_STD_VER <= 17
|
||||
|
||||
namespace this_thread {
|
||||
|
||||
inline _LIBCPP_HIDE_FROM_ABI __thread_id get_id() _NOEXCEPT { return __libcpp_thread_get_current_id(); }
|
||||
|
||||
} // namespace this_thread
|
||||
|
||||
#endif // !_LIBCPP_HAS_NO_THREADS
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCPP___THREAD_ID_H
|
134
third_party/libcxx/__thread/jthread.h
vendored
Normal file
134
third_party/libcxx/__thread/jthread.h
vendored
Normal file
|
@ -0,0 +1,134 @@
|
|||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _LIBCPP___THREAD_JTHREAD_H
|
||||
#define _LIBCPP___THREAD_JTHREAD_H
|
||||
|
||||
#include <__config>
|
||||
#include <__functional/invoke.h>
|
||||
#include <__stop_token/stop_source.h>
|
||||
#include <__stop_token/stop_token.h>
|
||||
#include <__thread/support.h>
|
||||
#include <__thread/thread.h>
|
||||
#include <__type_traits/decay.h>
|
||||
#include <__type_traits/is_constructible.h>
|
||||
#include <__type_traits/is_same.h>
|
||||
#include <__type_traits/remove_cvref.h>
|
||||
#include <__utility/forward.h>
|
||||
#include <__utility/move.h>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
# pragma GCC system_header
|
||||
#endif
|
||||
|
||||
_LIBCPP_PUSH_MACROS
|
||||
#include <__undef_macros>
|
||||
|
||||
#if _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN)
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
class _LIBCPP_AVAILABILITY_SYNC jthread {
|
||||
public:
|
||||
// types
|
||||
using id = thread::id;
|
||||
using native_handle_type = thread::native_handle_type;
|
||||
|
||||
// [thread.jthread.cons], constructors, move, and assignment
|
||||
_LIBCPP_HIDE_FROM_ABI jthread() noexcept : __stop_source_(std::nostopstate) {}
|
||||
|
||||
template <class _Fun, class... _Args>
|
||||
_LIBCPP_HIDE_FROM_ABI explicit jthread(_Fun&& __fun, _Args&&... __args)
|
||||
requires(!std::is_same_v<remove_cvref_t<_Fun>, jthread>)
|
||||
: __stop_source_(),
|
||||
__thread_(__init_thread(__stop_source_, std::forward<_Fun>(__fun), std::forward<_Args>(__args)...)) {
|
||||
static_assert(is_constructible_v<decay_t<_Fun>, _Fun>);
|
||||
static_assert((is_constructible_v<decay_t<_Args>, _Args> && ...));
|
||||
static_assert(is_invocable_v<decay_t<_Fun>, decay_t<_Args>...> ||
|
||||
is_invocable_v<decay_t<_Fun>, stop_token, decay_t<_Args>...>);
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI ~jthread() {
|
||||
if (joinable()) {
|
||||
request_stop();
|
||||
join();
|
||||
}
|
||||
}
|
||||
|
||||
jthread(const jthread&) = delete;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI jthread(jthread&&) noexcept = default;
|
||||
|
||||
jthread& operator=(const jthread&) = delete;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI jthread& operator=(jthread&& __other) noexcept {
|
||||
if (this != &__other) {
|
||||
if (joinable()) {
|
||||
request_stop();
|
||||
join();
|
||||
}
|
||||
__stop_source_ = std::move(__other.__stop_source_);
|
||||
__thread_ = std::move(__other.__thread_);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// [thread.jthread.mem], members
|
||||
_LIBCPP_HIDE_FROM_ABI void swap(jthread& __other) noexcept {
|
||||
std::swap(__stop_source_, __other.__stop_source_);
|
||||
std::swap(__thread_, __other.__thread_);
|
||||
}
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool joinable() const noexcept { return get_id() != id(); }
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI void join() { __thread_.join(); }
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI void detach() { __thread_.detach(); }
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI id get_id() const noexcept { return __thread_.get_id(); }
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() { return __thread_.native_handle(); }
|
||||
|
||||
// [thread.jthread.stop], stop token handling
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI stop_source get_stop_source() noexcept { return __stop_source_; }
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI stop_token get_stop_token() const noexcept { return __stop_source_.get_token(); }
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI bool request_stop() noexcept { return __stop_source_.request_stop(); }
|
||||
|
||||
// [thread.jthread.special], specialized algorithms
|
||||
_LIBCPP_HIDE_FROM_ABI friend void swap(jthread& __lhs, jthread& __rhs) noexcept { __lhs.swap(__rhs); }
|
||||
|
||||
// [thread.jthread.static], static members
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI static unsigned int hardware_concurrency() noexcept {
|
||||
return thread::hardware_concurrency();
|
||||
}
|
||||
|
||||
private:
|
||||
template <class _Fun, class... _Args>
|
||||
_LIBCPP_HIDE_FROM_ABI static thread __init_thread(const stop_source& __ss, _Fun&& __fun, _Args&&... __args) {
|
||||
if constexpr (is_invocable_v<decay_t<_Fun>, stop_token, decay_t<_Args>...>) {
|
||||
return thread(std::forward<_Fun>(__fun), __ss.get_token(), std::forward<_Args>(__args)...);
|
||||
} else {
|
||||
return thread(std::forward<_Fun>(__fun), std::forward<_Args>(__args)...);
|
||||
}
|
||||
}
|
||||
|
||||
stop_source __stop_source_;
|
||||
thread __thread_;
|
||||
};
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN)
|
||||
|
||||
_LIBCPP_POP_MACROS
|
||||
|
||||
#endif // _LIBCPP___THREAD_JTHREAD_H
|
42
third_party/libcxx/__thread/poll_with_backoff.h
vendored
42
third_party/libcxx/__thread/poll_with_backoff.h
vendored
|
@ -10,7 +10,6 @@
|
|||
#ifndef _LIBCPP___THREAD_POLL_WITH_BACKOFF_H
|
||||
#define _LIBCPP___THREAD_POLL_WITH_BACKOFF_H
|
||||
|
||||
#include <__availability>
|
||||
#include <__chrono/duration.h>
|
||||
#include <__chrono/high_resolution_clock.h>
|
||||
#include <__config>
|
||||
|
@ -26,31 +25,31 @@ static _LIBCPP_CONSTEXPR const int __libcpp_polling_count = 64;
|
|||
// Polls a thread for a condition given by a predicate, and backs off based on a backoff policy
|
||||
// before polling again.
|
||||
//
|
||||
// - __f is the "test function" that should return true if polling succeeded, and false if it failed.
|
||||
// - __poll is the "test function" that should return true if polling succeeded, and false if it failed.
|
||||
//
|
||||
// - __bf is the "backoff policy", which is called with the duration since we started polling. It should
|
||||
// - __backoff is the "backoff policy", which is called with the duration since we started polling. It should
|
||||
// return false in order to resume polling, and true if polling should stop entirely for some reason.
|
||||
// In general, backoff policies sleep for some time before returning control to the polling loop.
|
||||
//
|
||||
// - __max_elapsed is the maximum duration to try polling for. If the maximum duration is exceeded,
|
||||
// the polling loop will return false to report a timeout.
|
||||
template<class _Fn, class _BFn>
|
||||
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI
|
||||
bool __libcpp_thread_poll_with_backoff(_Fn&& __f, _BFn&& __bf, chrono::nanoseconds __max_elapsed = chrono::nanoseconds::zero()) {
|
||||
auto const __start = chrono::high_resolution_clock::now();
|
||||
for (int __count = 0;;) {
|
||||
if (__f())
|
||||
return true; // _Fn completion means success
|
||||
if (__count < __libcpp_polling_count) {
|
||||
__count += 1;
|
||||
continue;
|
||||
}
|
||||
chrono::nanoseconds const __elapsed = chrono::high_resolution_clock::now() - __start;
|
||||
if (__max_elapsed != chrono::nanoseconds::zero() && __max_elapsed < __elapsed)
|
||||
return false; // timeout failure
|
||||
if (__bf(__elapsed))
|
||||
return false; // _BFn completion means failure
|
||||
template <class _Poll, class _Backoff>
|
||||
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI bool __libcpp_thread_poll_with_backoff(
|
||||
_Poll&& __poll, _Backoff&& __backoff, chrono::nanoseconds __max_elapsed = chrono::nanoseconds::zero()) {
|
||||
auto const __start = chrono::high_resolution_clock::now();
|
||||
for (int __count = 0;;) {
|
||||
if (__poll())
|
||||
return true; // __poll completion means success
|
||||
if (__count < __libcpp_polling_count) {
|
||||
__count += 1;
|
||||
continue;
|
||||
}
|
||||
chrono::nanoseconds const __elapsed = chrono::high_resolution_clock::now() - __start;
|
||||
if (__max_elapsed != chrono::nanoseconds::zero() && __max_elapsed < __elapsed)
|
||||
return false; // timeout failure
|
||||
if (__backoff(__elapsed))
|
||||
return false; // __backoff completion means failure
|
||||
}
|
||||
}
|
||||
|
||||
// A trivial backoff policy that always immediately returns the control to
|
||||
|
@ -60,10 +59,7 @@ bool __libcpp_thread_poll_with_backoff(_Fn&& __f, _BFn&& __bf, chrono::nanosecon
|
|||
// so this should most likely only be used on single-threaded systems where there
|
||||
// are no other threads to compete with.
|
||||
struct __spinning_backoff_policy {
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR
|
||||
bool operator()(chrono::nanoseconds const&) const {
|
||||
return false;
|
||||
}
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool operator()(chrono::nanoseconds const&) const { return false; }
|
||||
};
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
|
123
third_party/libcxx/__thread/support.h
vendored
Normal file
123
third_party/libcxx/__thread/support.h
vendored
Normal file
|
@ -0,0 +1,123 @@
|
|||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _LIBCPP___THREAD_SUPPORT_H
|
||||
#define _LIBCPP___THREAD_SUPPORT_H
|
||||
|
||||
#include <__config>
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
|
||||
# pragma GCC system_header
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
||||
//
|
||||
// The library supports multiple implementations of the basic threading functionality.
|
||||
// The following functionality must be provided by any implementation:
|
||||
//
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
using __libcpp_timespec_t = ...;
|
||||
|
||||
//
|
||||
// Mutex
|
||||
//
|
||||
using __libcpp_mutex_t = ...;
|
||||
#define _LIBCPP_MUTEX_INITIALIZER ...
|
||||
|
||||
using __libcpp_recursive_mutex_t = ...;
|
||||
|
||||
int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t*);
|
||||
_LIBCPP_NO_THREAD_SAFETY_ANALYSIS int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t*);
|
||||
_LIBCPP_NO_THREAD_SAFETY_ANALYSIS bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t*);
|
||||
_LIBCPP_NO_THREAD_SAFETY_ANALYSIS int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t*);
|
||||
int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t*);
|
||||
|
||||
_LIBCPP_NO_THREAD_SAFETY_ANALYSIS int __libcpp_mutex_lock(__libcpp_mutex_t*);
|
||||
_LIBCPP_NO_THREAD_SAFETY_ANALYSIS bool __libcpp_mutex_trylock(__libcpp_mutex_t*);
|
||||
_LIBCPP_NO_THREAD_SAFETY_ANALYSIS int __libcpp_mutex_unlock(__libcpp_mutex_t*);
|
||||
int __libcpp_mutex_destroy(__libcpp_mutex_t*);
|
||||
|
||||
//
|
||||
// Condition Variable
|
||||
//
|
||||
using __libcpp_condvar_t = ...;
|
||||
#define _LIBCPP_CONDVAR_INITIALIZER ...
|
||||
|
||||
int __libcpp_condvar_signal(__libcpp_condvar_t*);
|
||||
int __libcpp_condvar_broadcast(__libcpp_condvar_t*);
|
||||
_LIBCPP_NO_THREAD_SAFETY_ANALYSIS int __libcpp_condvar_wait(__libcpp_condvar_t*, __libcpp_mutex_t*);
|
||||
_LIBCPP_NO_THREAD_SAFETY_ANALYSIS
|
||||
int __libcpp_condvar_timedwait(__libcpp_condvar_t*, __libcpp_mutex_t*, __libcpp_timespec_t*);
|
||||
int __libcpp_condvar_destroy(__libcpp_condvar_t*);
|
||||
|
||||
//
|
||||
// Execute once
|
||||
//
|
||||
using __libcpp_exec_once_flag = ...;
|
||||
#define _LIBCPP_EXEC_ONCE_INITIALIZER ...
|
||||
|
||||
int __libcpp_execute_once(__libcpp_exec_once_flag*, void (*__init_routine)());
|
||||
|
||||
//
|
||||
// Thread id
|
||||
//
|
||||
using __libcpp_thread_id = ...;
|
||||
|
||||
bool __libcpp_thread_id_equal(__libcpp_thread_id, __libcpp_thread_id);
|
||||
bool __libcpp_thread_id_less(__libcpp_thread_id, __libcpp_thread_id);
|
||||
|
||||
//
|
||||
// Thread
|
||||
//
|
||||
#define _LIBCPP_NULL_THREAD ...
|
||||
using __libcpp_thread_t = ...;
|
||||
|
||||
bool __libcpp_thread_isnull(const __libcpp_thread_t*);
|
||||
int __libcpp_thread_create(__libcpp_thread_t*, void* (*__func)(void*), void* __arg);
|
||||
__libcpp_thread_id __libcpp_thread_get_current_id();
|
||||
__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t*);
|
||||
int __libcpp_thread_join(__libcpp_thread_t*);
|
||||
int __libcpp_thread_detach(__libcpp_thread_t*);
|
||||
void __libcpp_thread_yield();
|
||||
void __libcpp_thread_sleep_for(const chrono::nanoseconds&);
|
||||
|
||||
//
|
||||
// Thread local storage
|
||||
//
|
||||
#define _LIBCPP_TLS_DESTRUCTOR_CC ...
|
||||
using __libcpp_tls_key = ...;
|
||||
|
||||
int __libcpp_tls_create(__libcpp_tls_key*, void (*__at_exit)(void*));
|
||||
void* __libcpp_tls_get(__libcpp_tls_key);
|
||||
int __libcpp_tls_set(__libcpp_tls_key, void*);
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
*/
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_THREADS)
|
||||
|
||||
# if defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
|
||||
// # include <__thread/support/external.h>
|
||||
# elif defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
|
||||
# include <__thread/support/pthread.h>
|
||||
# elif defined(_LIBCPP_HAS_THREAD_API_C11)
|
||||
// # include <__thread/support/c11.h>
|
||||
# elif defined(_LIBCPP_HAS_THREAD_API_WIN32)
|
||||
// # include <__thread/support/windows.h>
|
||||
# else
|
||||
# error "No threading API was selected"
|
||||
# endif
|
||||
|
||||
#endif // !_LIBCPP_HAS_NO_THREADS
|
||||
|
||||
#endif // _LIBCPP___THREAD_SUPPORT_H
|
217
third_party/libcxx/__thread/support/pthread.h
vendored
Normal file
217
third_party/libcxx/__thread/support/pthread.h
vendored
Normal file
|
@ -0,0 +1,217 @@
|
|||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _LIBCPP___THREAD_SUPPORT_PTHREAD_H
|
||||
#define _LIBCPP___THREAD_SUPPORT_PTHREAD_H
|
||||
|
||||
#include <__chrono/convert_to_timespec.h>
|
||||
#include <__chrono/duration.h>
|
||||
#include <__config>
|
||||
#include <ctime>
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <sched.h>
|
||||
|
||||
// Some platforms require <bits/atomic_wide_counter.h> in order for
|
||||
// PTHREAD_COND_INITIALIZER to be expanded. Normally that would come
|
||||
// in via <pthread.h>, but it's a non-modular header on those platforms,
|
||||
// so libc++'s <math.h> usually absorbs atomic_wide_counter.h into the
|
||||
// module with <math.h> and makes atomic_wide_counter.h invisible.
|
||||
// Include <math.h> here to work around that.
|
||||
// This checks wheter a Clang module is built
|
||||
#if __building_module(std)
|
||||
# include <math.h>
|
||||
#endif
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
|
||||
# pragma GCC system_header
|
||||
#endif
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
using __libcpp_timespec_t = ::timespec;
|
||||
|
||||
//
|
||||
// Mutex
|
||||
//
|
||||
typedef pthread_mutex_t __libcpp_mutex_t;
|
||||
#define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
|
||||
|
||||
typedef pthread_mutex_t __libcpp_recursive_mutex_t;
|
||||
|
||||
inline _LIBCPP_HIDE_FROM_ABI int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t* __m) {
|
||||
pthread_mutexattr_t __attr;
|
||||
int __ec = pthread_mutexattr_init(&__attr);
|
||||
if (__ec)
|
||||
return __ec;
|
||||
__ec = pthread_mutexattr_settype(&__attr, PTHREAD_MUTEX_RECURSIVE);
|
||||
if (__ec) {
|
||||
pthread_mutexattr_destroy(&__attr);
|
||||
return __ec;
|
||||
}
|
||||
__ec = pthread_mutex_init(__m, &__attr);
|
||||
if (__ec) {
|
||||
pthread_mutexattr_destroy(&__attr);
|
||||
return __ec;
|
||||
}
|
||||
__ec = pthread_mutexattr_destroy(&__attr);
|
||||
if (__ec) {
|
||||
pthread_mutex_destroy(__m);
|
||||
return __ec;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int
|
||||
__libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t* __m) {
|
||||
return pthread_mutex_lock(__m);
|
||||
}
|
||||
|
||||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS bool
|
||||
__libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t* __m) {
|
||||
return pthread_mutex_trylock(__m) == 0;
|
||||
}
|
||||
|
||||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int
|
||||
__libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t* __m) {
|
||||
return pthread_mutex_unlock(__m);
|
||||
}
|
||||
|
||||
inline _LIBCPP_HIDE_FROM_ABI int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t* __m) {
|
||||
return pthread_mutex_destroy(__m);
|
||||
}
|
||||
|
||||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int __libcpp_mutex_lock(__libcpp_mutex_t* __m) {
|
||||
return pthread_mutex_lock(__m);
|
||||
}
|
||||
|
||||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS bool __libcpp_mutex_trylock(__libcpp_mutex_t* __m) {
|
||||
return pthread_mutex_trylock(__m) == 0;
|
||||
}
|
||||
|
||||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int __libcpp_mutex_unlock(__libcpp_mutex_t* __m) {
|
||||
return pthread_mutex_unlock(__m);
|
||||
}
|
||||
|
||||
inline _LIBCPP_HIDE_FROM_ABI int __libcpp_mutex_destroy(__libcpp_mutex_t* __m) { return pthread_mutex_destroy(__m); }
|
||||
|
||||
//
|
||||
// Condition Variable
|
||||
//
|
||||
typedef pthread_cond_t __libcpp_condvar_t;
|
||||
#define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER
|
||||
|
||||
inline _LIBCPP_HIDE_FROM_ABI int __libcpp_condvar_signal(__libcpp_condvar_t* __cv) { return pthread_cond_signal(__cv); }
|
||||
|
||||
inline _LIBCPP_HIDE_FROM_ABI int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv) {
|
||||
return pthread_cond_broadcast(__cv);
|
||||
}
|
||||
|
||||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int
|
||||
__libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m) {
|
||||
return pthread_cond_wait(__cv, __m);
|
||||
}
|
||||
|
||||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_THREAD_SAFETY_ANALYSIS int
|
||||
__libcpp_condvar_timedwait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m, __libcpp_timespec_t* __ts) {
|
||||
return pthread_cond_timedwait(__cv, __m, __ts);
|
||||
}
|
||||
|
||||
inline _LIBCPP_HIDE_FROM_ABI int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv) {
|
||||
return pthread_cond_destroy(__cv);
|
||||
}
|
||||
|
||||
//
|
||||
// Execute once
|
||||
//
|
||||
typedef pthread_once_t __libcpp_exec_once_flag;
|
||||
#define _LIBCPP_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT
|
||||
|
||||
inline _LIBCPP_HIDE_FROM_ABI int __libcpp_execute_once(__libcpp_exec_once_flag* __flag, void (*__init_routine)()) {
|
||||
return pthread_once(__flag, __init_routine);
|
||||
}
|
||||
|
||||
//
|
||||
// Thread id
|
||||
//
|
||||
#if defined(__MVS__)
|
||||
typedef unsigned long long __libcpp_thread_id;
|
||||
#else
|
||||
typedef pthread_t __libcpp_thread_id;
|
||||
#endif
|
||||
|
||||
// Returns non-zero if the thread ids are equal, otherwise 0
|
||||
inline _LIBCPP_HIDE_FROM_ABI bool __libcpp_thread_id_equal(__libcpp_thread_id __t1, __libcpp_thread_id __t2) {
|
||||
return __t1 == __t2;
|
||||
}
|
||||
|
||||
// Returns non-zero if t1 < t2, otherwise 0
|
||||
inline _LIBCPP_HIDE_FROM_ABI bool __libcpp_thread_id_less(__libcpp_thread_id __t1, __libcpp_thread_id __t2) {
|
||||
return __t1 < __t2;
|
||||
}
|
||||
|
||||
//
|
||||
// Thread
|
||||
//
|
||||
#define _LIBCPP_NULL_THREAD ((__libcpp_thread_t()))
|
||||
typedef pthread_t __libcpp_thread_t;
|
||||
|
||||
inline _LIBCPP_HIDE_FROM_ABI __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t* __t) {
|
||||
#if defined(__MVS__)
|
||||
return __t->__;
|
||||
#else
|
||||
return *__t;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline _LIBCPP_HIDE_FROM_ABI bool __libcpp_thread_isnull(const __libcpp_thread_t* __t) {
|
||||
return __libcpp_thread_get_id(__t) == 0;
|
||||
}
|
||||
|
||||
inline _LIBCPP_HIDE_FROM_ABI int __libcpp_thread_create(__libcpp_thread_t* __t, void* (*__func)(void*), void* __arg) {
|
||||
return pthread_create(__t, nullptr, __func, __arg);
|
||||
}
|
||||
|
||||
inline _LIBCPP_HIDE_FROM_ABI __libcpp_thread_id __libcpp_thread_get_current_id() {
|
||||
const __libcpp_thread_t __current_thread = pthread_self();
|
||||
return __libcpp_thread_get_id(&__current_thread);
|
||||
}
|
||||
|
||||
inline _LIBCPP_HIDE_FROM_ABI int __libcpp_thread_join(__libcpp_thread_t* __t) { return pthread_join(*__t, nullptr); }
|
||||
|
||||
inline _LIBCPP_HIDE_FROM_ABI int __libcpp_thread_detach(__libcpp_thread_t* __t) { return pthread_detach(*__t); }
|
||||
|
||||
inline _LIBCPP_HIDE_FROM_ABI void __libcpp_thread_yield() { sched_yield(); }
|
||||
|
||||
inline _LIBCPP_HIDE_FROM_ABI void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns) {
|
||||
__libcpp_timespec_t __ts = std::__convert_to_timespec<__libcpp_timespec_t>(__ns);
|
||||
while (nanosleep(&__ts, &__ts) == -1 && errno == EINTR)
|
||||
;
|
||||
}
|
||||
|
||||
//
|
||||
// Thread local storage
|
||||
//
|
||||
#define _LIBCPP_TLS_DESTRUCTOR_CC /* nothing */
|
||||
|
||||
typedef pthread_key_t __libcpp_tls_key;
|
||||
|
||||
inline _LIBCPP_HIDE_FROM_ABI int __libcpp_tls_create(__libcpp_tls_key* __key, void (*__at_exit)(void*)) {
|
||||
return pthread_key_create(__key, __at_exit);
|
||||
}
|
||||
|
||||
inline _LIBCPP_HIDE_FROM_ABI void* __libcpp_tls_get(__libcpp_tls_key __key) { return pthread_getspecific(__key); }
|
||||
|
||||
inline _LIBCPP_HIDE_FROM_ABI int __libcpp_tls_set(__libcpp_tls_key __key, void* __p) {
|
||||
return pthread_setspecific(__key, __p);
|
||||
}
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCPP___THREAD_SUPPORT_PTHREAD_H
|
74
third_party/libcxx/__thread/this_thread.h
vendored
Normal file
74
third_party/libcxx/__thread/this_thread.h
vendored
Normal file
|
@ -0,0 +1,74 @@
|
|||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _LIBCPP___THREAD_THIS_THREAD_H
|
||||
#define _LIBCPP___THREAD_THIS_THREAD_H
|
||||
|
||||
#include <__chrono/steady_clock.h>
|
||||
#include <__chrono/time_point.h>
|
||||
#include <__condition_variable/condition_variable.h>
|
||||
#include <__config>
|
||||
#include <__mutex/mutex.h>
|
||||
#include <__mutex/unique_lock.h>
|
||||
#include <__thread/support.h>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
# pragma GCC system_header
|
||||
#endif
|
||||
|
||||
_LIBCPP_PUSH_MACROS
|
||||
#include <__undef_macros>
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
namespace this_thread {
|
||||
|
||||
_LIBCPP_EXPORTED_FROM_ABI void sleep_for(const chrono::nanoseconds& __ns);
|
||||
|
||||
template <class _Rep, class _Period>
|
||||
_LIBCPP_HIDE_FROM_ABI void sleep_for(const chrono::duration<_Rep, _Period>& __d) {
|
||||
if (__d > chrono::duration<_Rep, _Period>::zero()) {
|
||||
// The standard guarantees a 64bit signed integer resolution for nanoseconds,
|
||||
// so use INT64_MAX / 1e9 as cut-off point. Use a constant to avoid <climits>
|
||||
// and issues with long double folding on PowerPC with GCC.
|
||||
_LIBCPP_CONSTEXPR chrono::duration<long double> __max = chrono::duration<long double>(9223372036.0L);
|
||||
chrono::nanoseconds __ns;
|
||||
if (__d < __max) {
|
||||
__ns = chrono::duration_cast<chrono::nanoseconds>(__d);
|
||||
if (__ns < __d)
|
||||
++__ns;
|
||||
} else
|
||||
__ns = chrono::nanoseconds::max();
|
||||
this_thread::sleep_for(__ns);
|
||||
}
|
||||
}
|
||||
|
||||
template <class _Clock, class _Duration>
|
||||
_LIBCPP_HIDE_FROM_ABI void sleep_until(const chrono::time_point<_Clock, _Duration>& __t) {
|
||||
mutex __mut;
|
||||
condition_variable __cv;
|
||||
unique_lock<mutex> __lk(__mut);
|
||||
while (_Clock::now() < __t)
|
||||
__cv.wait_until(__lk, __t);
|
||||
}
|
||||
|
||||
template <class _Duration>
|
||||
inline _LIBCPP_HIDE_FROM_ABI void sleep_until(const chrono::time_point<chrono::steady_clock, _Duration>& __t) {
|
||||
this_thread::sleep_for(__t - chrono::steady_clock::now());
|
||||
}
|
||||
|
||||
inline _LIBCPP_HIDE_FROM_ABI void yield() _NOEXCEPT { __libcpp_thread_yield(); }
|
||||
|
||||
} // namespace this_thread
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
_LIBCPP_POP_MACROS
|
||||
|
||||
#endif // _LIBCPP___THREAD_THIS_THREAD_H
|
258
third_party/libcxx/__thread/thread.h
vendored
Normal file
258
third_party/libcxx/__thread/thread.h
vendored
Normal file
|
@ -0,0 +1,258 @@
|
|||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _LIBCPP___THREAD_THREAD_H
|
||||
#define _LIBCPP___THREAD_THREAD_H
|
||||
|
||||
#include <__condition_variable/condition_variable.h>
|
||||
#include <__config>
|
||||
#include <__exception/terminate.h>
|
||||
#include <__functional/hash.h>
|
||||
#include <__functional/unary_function.h>
|
||||
#include <__memory/unique_ptr.h>
|
||||
#include <__mutex/mutex.h>
|
||||
#include <__system_error/system_error.h>
|
||||
#include <__thread/id.h>
|
||||
#include <__thread/support.h>
|
||||
#include <__utility/forward.h>
|
||||
#include <tuple>
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_LOCALIZATION
|
||||
# include <locale>
|
||||
# include <sstream>
|
||||
#endif
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
# pragma GCC system_header
|
||||
#endif
|
||||
|
||||
_LIBCPP_PUSH_MACROS
|
||||
#include <__undef_macros>
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
template <class _Tp>
|
||||
class __thread_specific_ptr;
|
||||
class _LIBCPP_EXPORTED_FROM_ABI __thread_struct;
|
||||
class _LIBCPP_HIDDEN __thread_struct_imp;
|
||||
class __assoc_sub_state;
|
||||
|
||||
_LIBCPP_EXPORTED_FROM_ABI __thread_specific_ptr<__thread_struct>& __thread_local_data();
|
||||
|
||||
class _LIBCPP_EXPORTED_FROM_ABI __thread_struct {
|
||||
__thread_struct_imp* __p_;
|
||||
|
||||
__thread_struct(const __thread_struct&);
|
||||
__thread_struct& operator=(const __thread_struct&);
|
||||
|
||||
public:
|
||||
__thread_struct();
|
||||
~__thread_struct();
|
||||
|
||||
void notify_all_at_thread_exit(condition_variable*, mutex*);
|
||||
void __make_ready_at_thread_exit(__assoc_sub_state*);
|
||||
};
|
||||
|
||||
template <class _Tp>
|
||||
class __thread_specific_ptr {
|
||||
__libcpp_tls_key __key_;
|
||||
|
||||
// Only __thread_local_data() may construct a __thread_specific_ptr
|
||||
// and only with _Tp == __thread_struct.
|
||||
static_assert(is_same<_Tp, __thread_struct>::value, "");
|
||||
__thread_specific_ptr();
|
||||
friend _LIBCPP_EXPORTED_FROM_ABI __thread_specific_ptr<__thread_struct>& __thread_local_data();
|
||||
|
||||
_LIBCPP_HIDDEN static void _LIBCPP_TLS_DESTRUCTOR_CC __at_thread_exit(void*);
|
||||
|
||||
public:
|
||||
typedef _Tp* pointer;
|
||||
|
||||
__thread_specific_ptr(const __thread_specific_ptr&) = delete;
|
||||
__thread_specific_ptr& operator=(const __thread_specific_ptr&) = delete;
|
||||
~__thread_specific_ptr();
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI pointer get() const { return static_cast<_Tp*>(__libcpp_tls_get(__key_)); }
|
||||
_LIBCPP_HIDE_FROM_ABI pointer operator*() const { return *get(); }
|
||||
_LIBCPP_HIDE_FROM_ABI pointer operator->() const { return get(); }
|
||||
void set_pointer(pointer __p);
|
||||
};
|
||||
|
||||
template <class _Tp>
|
||||
void _LIBCPP_TLS_DESTRUCTOR_CC __thread_specific_ptr<_Tp>::__at_thread_exit(void* __p) {
|
||||
delete static_cast<pointer>(__p);
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
__thread_specific_ptr<_Tp>::__thread_specific_ptr() {
|
||||
int __ec = __libcpp_tls_create(&__key_, &__thread_specific_ptr::__at_thread_exit);
|
||||
if (__ec)
|
||||
__throw_system_error(__ec, "__thread_specific_ptr construction failed");
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
__thread_specific_ptr<_Tp>::~__thread_specific_ptr() {
|
||||
// __thread_specific_ptr is only created with a static storage duration
|
||||
// so this destructor is only invoked during program termination. Invoking
|
||||
// pthread_key_delete(__key_) may prevent other threads from deleting their
|
||||
// thread local data. For this reason we leak the key.
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
void __thread_specific_ptr<_Tp>::set_pointer(pointer __p) {
|
||||
_LIBCPP_ASSERT_INTERNAL(get() == nullptr, "Attempting to overwrite thread local data");
|
||||
std::__libcpp_tls_set(__key_, __p);
|
||||
}
|
||||
|
||||
template <>
|
||||
struct _LIBCPP_TEMPLATE_VIS hash<__thread_id> : public __unary_function<__thread_id, size_t> {
|
||||
_LIBCPP_HIDE_FROM_ABI size_t operator()(__thread_id __v) const _NOEXCEPT {
|
||||
return hash<__libcpp_thread_id>()(__v.__id_);
|
||||
}
|
||||
};
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_LOCALIZATION
|
||||
template <class _CharT, class _Traits>
|
||||
_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>&
|
||||
operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id) {
|
||||
// [thread.thread.id]/9
|
||||
// Effects: Inserts the text representation for charT of id into out.
|
||||
//
|
||||
// [thread.thread.id]/2
|
||||
// The text representation for the character type charT of an
|
||||
// object of type thread::id is an unspecified sequence of charT
|
||||
// such that, for two objects of type thread::id x and y, if
|
||||
// x == y is true, the thread::id objects have the same text
|
||||
// representation, and if x != y is true, the thread::id objects
|
||||
// have distinct text representations.
|
||||
//
|
||||
// Since various flags in the output stream can affect how the
|
||||
// thread id is represented (e.g. numpunct or showbase), we
|
||||
// use a temporary stream instead and just output the thread
|
||||
// id representation as a string.
|
||||
|
||||
basic_ostringstream<_CharT, _Traits> __sstr;
|
||||
__sstr.imbue(locale::classic());
|
||||
__sstr << __id.__id_;
|
||||
return __os << __sstr.str();
|
||||
}
|
||||
#endif // _LIBCPP_HAS_NO_LOCALIZATION
|
||||
|
||||
class _LIBCPP_EXPORTED_FROM_ABI thread {
|
||||
__libcpp_thread_t __t_;
|
||||
|
||||
thread(const thread&);
|
||||
thread& operator=(const thread&);
|
||||
|
||||
public:
|
||||
typedef __thread_id id;
|
||||
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);
|
||||
#else // _LIBCPP_CXX03_LANG
|
||||
template <class _Fp>
|
||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS explicit thread(_Fp __f);
|
||||
#endif
|
||||
~thread();
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI thread(thread&& __t) _NOEXCEPT : __t_(__t.__t_) { __t.__t_ = _LIBCPP_NULL_THREAD; }
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI thread& operator=(thread&& __t) _NOEXCEPT {
|
||||
if (!__libcpp_thread_isnull(&__t_))
|
||||
terminate();
|
||||
__t_ = __t.__t_;
|
||||
__t.__t_ = _LIBCPP_NULL_THREAD;
|
||||
return *this;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI void swap(thread& __t) _NOEXCEPT { std::swap(__t_, __t.__t_); }
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI bool joinable() const _NOEXCEPT { return !__libcpp_thread_isnull(&__t_); }
|
||||
void join();
|
||||
void detach();
|
||||
_LIBCPP_HIDE_FROM_ABI id get_id() const _NOEXCEPT { return __libcpp_thread_get_id(&__t_); }
|
||||
_LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() _NOEXCEPT { return __t_; }
|
||||
|
||||
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_, &__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>
|
||||
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
|
||||
__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); }
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
_LIBCPP_POP_MACROS
|
||||
|
||||
#endif // _LIBCPP___THREAD_THREAD_H
|
|
@ -15,27 +15,25 @@
|
|||
#ifndef _LIBCPP_HAS_NO_THREADS
|
||||
|
||||
# include <__chrono/duration.h>
|
||||
# include <__threading_support>
|
||||
# include <__thread/support.h>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
# pragma GCC system_header
|
||||
#endif
|
||||
# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
# pragma GCC system_header
|
||||
# endif
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
struct __libcpp_timed_backoff_policy {
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
bool operator()(chrono::nanoseconds __elapsed) const
|
||||
{
|
||||
if(__elapsed > chrono::milliseconds(128))
|
||||
__libcpp_thread_sleep_for(chrono::milliseconds(8));
|
||||
else if(__elapsed > chrono::microseconds(64))
|
||||
__libcpp_thread_sleep_for(__elapsed / 2);
|
||||
else if(__elapsed > chrono::microseconds(4))
|
||||
__libcpp_thread_yield();
|
||||
else
|
||||
{} // poll
|
||||
return false;
|
||||
_LIBCPP_HIDE_FROM_ABI bool operator()(chrono::nanoseconds __elapsed) const {
|
||||
if (__elapsed > chrono::milliseconds(128))
|
||||
__libcpp_thread_sleep_for(chrono::milliseconds(8));
|
||||
else if (__elapsed > chrono::microseconds(64))
|
||||
__libcpp_thread_sleep_for(__elapsed / 2);
|
||||
else if (__elapsed > chrono::microseconds(4))
|
||||
__libcpp_thread_yield();
|
||||
else {
|
||||
} // poll
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue