summaryrefslogtreecommitdiff
path: root/third_party/libcxx/include/c++/v1/__thread
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/libcxx/include/c++/v1/__thread')
-rw-r--r--third_party/libcxx/include/c++/v1/__thread/formatter.h80
-rw-r--r--third_party/libcxx/include/c++/v1/__thread/id.h121
-rw-r--r--third_party/libcxx/include/c++/v1/__thread/jthread.h136
-rw-r--r--third_party/libcxx/include/c++/v1/__thread/poll_with_backoff.h86
-rw-r--r--third_party/libcxx/include/c++/v1/__thread/support.h123
-rw-r--r--third_party/libcxx/include/c++/v1/__thread/support/c11.h191
-rw-r--r--third_party/libcxx/include/c++/v1/__thread/support/external.h21
-rw-r--r--third_party/libcxx/include/c++/v1/__thread/support/pthread.h221
-rw-r--r--third_party/libcxx/include/c++/v1/__thread/support/windows.h131
-rw-r--r--third_party/libcxx/include/c++/v1/__thread/this_thread.h79
-rw-r--r--third_party/libcxx/include/c++/v1/__thread/thread.h268
-rw-r--r--third_party/libcxx/include/c++/v1/__thread/timed_backoff_policy.h45
12 files changed, 1502 insertions, 0 deletions
diff --git a/third_party/libcxx/include/c++/v1/__thread/formatter.h b/third_party/libcxx/include/c++/v1/__thread/formatter.h
new file mode 100644
index 0000000..826607d
--- /dev/null
+++ b/third_party/libcxx/include/c++/v1/__thread/formatter.h
@@ -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
+
+# if _LIBCPP_HAS_THREADS
+
+template <__fmt_char_type _CharT>
+struct 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_THREADS
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP_STD_VER >= 23
+
+#endif // _LIBCPP___THREAD_FORMATTER_H
diff --git a/third_party/libcxx/include/c++/v1/__thread/id.h b/third_party/libcxx/include/c++/v1/__thread/id.h
new file mode 100644
index 0000000..14a51fc
--- /dev/null
+++ b/third_party/libcxx/include/c++/v1/__thread/id.h
@@ -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
+
+#if _LIBCPP_HAS_THREADS
+class __thread_id;
+
+namespace this_thread {
+
+_LIBCPP_HIDE_FROM_ABI __thread_id get_id() _NOEXCEPT;
+
+} // namespace this_thread
+
+template <>
+struct hash<__thread_id>;
+
+class __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 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_THREADS
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP___THREAD_ID_H
diff --git a/third_party/libcxx/include/c++/v1/__thread/jthread.h b/third_party/libcxx/include/c++/v1/__thread/jthread.h
new file mode 100644
index 0000000..481ffe2
--- /dev/null
+++ b/third_party/libcxx/include/c++/v1/__thread/jthread.h
@@ -0,0 +1,136 @@
+// -*- 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 <__stop_token/stop_source.h>
+#include <__stop_token/stop_token.h>
+#include <__thread/id.h>
+#include <__thread/support.h>
+#include <__thread/thread.h>
+#include <__type_traits/decay.h>
+#include <__type_traits/invoke.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>
+#include <__utility/swap.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 && _LIBCPP_HAS_THREADS
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+class 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 && _LIBCPP_HAS_THREADS
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___THREAD_JTHREAD_H
diff --git a/third_party/libcxx/include/c++/v1/__thread/poll_with_backoff.h b/third_party/libcxx/include/c++/v1/__thread/poll_with_backoff.h
new file mode 100644
index 0000000..e007e77
--- /dev/null
+++ b/third_party/libcxx/include/c++/v1/__thread/poll_with_backoff.h
@@ -0,0 +1,86 @@
+// -*- 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_POLL_WITH_BACKOFF_H
+#define _LIBCPP___THREAD_POLL_WITH_BACKOFF_H
+
+#include <__chrono/duration.h>
+#include <__chrono/high_resolution_clock.h>
+#include <__config>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+static _LIBCPP_CONSTEXPR const int __libcpp_polling_count = 64;
+
+enum class __backoff_results : unsigned char {
+ __continue_poll = 1,
+ __poll_success = 2,
+ __timeout = 3,
+ __backoff_failure = 4,
+};
+
+enum class __poll_with_backoff_results : unsigned char {
+ __poll_success = static_cast<unsigned char>(__backoff_results::__poll_success),
+ __timeout = static_cast<unsigned char>(__backoff_results::__timeout),
+ __backoff_failure = static_cast<unsigned char>(__backoff_results::__backoff_failure),
+};
+
+// Polls a thread for a condition given by a predicate, and backs off based on a backoff policy
+// before polling again.
+//
+// - __poll is the "test function" that should return true if polling succeeded, and false if it failed.
+//
+// - __backoff is the "backoff policy", which is called with the duration since we started polling. It should
+// return __backoff_results::__continue_poll in order to resume polling, and other appropriate __backoff_results
+// 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 __poll_with_backoff_results::__timeout to report a timeout.
+
+template <class _Poll, class _Backoff>
+_LIBCPP_HIDE_FROM_ABI __poll_with_backoff_results __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 __poll_with_backoff_results::__poll_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 __poll_with_backoff_results::__timeout;
+ if (auto __backoff_res = __backoff(__elapsed); __backoff_res == __backoff_results::__continue_poll)
+ continue;
+ else
+ return static_cast<__poll_with_backoff_results>(__backoff_res);
+ }
+}
+
+// A trivial backoff policy that always immediately returns the control to
+// the polling loop.
+//
+// This is not very well-behaved since it will cause the polling loop to spin,
+// 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 __backoff_results operator()(chrono::nanoseconds const&) const {
+ return __backoff_results::__continue_poll;
+ }
+};
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP___THREAD_POLL_WITH_BACKOFF_H
diff --git a/third_party/libcxx/include/c++/v1/__thread/support.h b/third_party/libcxx/include/c++/v1/__thread/support.h
new file mode 100644
index 0000000..50a18da
--- /dev/null
+++ b/third_party/libcxx/include/c++/v1/__thread/support.h
@@ -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 _LIBCPP_HAS_THREADS
+
+# if _LIBCPP_HAS_THREAD_API_EXTERNAL
+# include <__thread/support/external.h>
+# elif _LIBCPP_HAS_THREAD_API_PTHREAD
+# include <__thread/support/pthread.h>
+# elif _LIBCPP_HAS_THREAD_API_C11
+# include <__thread/support/c11.h>
+# elif _LIBCPP_HAS_THREAD_API_WIN32
+# include <__thread/support/windows.h>
+# else
+# error "No threading API was selected"
+# endif
+
+#endif // _LIBCPP_HAS_THREADS
+
+#endif // _LIBCPP___THREAD_SUPPORT_H
diff --git a/third_party/libcxx/include/c++/v1/__thread/support/c11.h b/third_party/libcxx/include/c++/v1/__thread/support/c11.h
new file mode 100644
index 0000000..463c849
--- /dev/null
+++ b/third_party/libcxx/include/c++/v1/__thread/support/c11.h
@@ -0,0 +1,191 @@
+// -*- 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_C11_H
+#define _LIBCPP___THREAD_SUPPORT_C11_H
+
+#include <__chrono/convert_to_timespec.h>
+#include <__chrono/duration.h>
+#include <__config>
+#include <ctime>
+#include <errno.h>
+#include <threads.h>
+
+#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
+# pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+using __libcpp_timespec_t = ::timespec;
+
+//
+// Mutex
+//
+typedef mtx_t __libcpp_mutex_t;
+// mtx_t is a struct so using {} for initialization is valid.
+#define _LIBCPP_MUTEX_INITIALIZER \
+ {}
+
+typedef mtx_t __libcpp_recursive_mutex_t;
+
+inline _LIBCPP_HIDE_FROM_ABI int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t* __m) {
+ return mtx_init(__m, mtx_plain | mtx_recursive) == thrd_success ? 0 : EINVAL;
+}
+
+_LIBCPP_NO_THREAD_SAFETY_ANALYSIS inline _LIBCPP_HIDE_FROM_ABI int
+__libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t* __m) {
+ return mtx_lock(__m) == thrd_success ? 0 : EINVAL;
+}
+
+_LIBCPP_NO_THREAD_SAFETY_ANALYSIS inline _LIBCPP_HIDE_FROM_ABI bool
+__libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t* __m) {
+ return mtx_trylock(__m) == thrd_success;
+}
+
+_LIBCPP_NO_THREAD_SAFETY_ANALYSIS inline _LIBCPP_HIDE_FROM_ABI int
+__libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t* __m) {
+ return mtx_unlock(__m) == thrd_success ? 0 : EINVAL;
+}
+
+inline _LIBCPP_HIDE_FROM_ABI int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t* __m) {
+ mtx_destroy(__m);
+ return 0;
+}
+
+_LIBCPP_NO_THREAD_SAFETY_ANALYSIS inline _LIBCPP_HIDE_FROM_ABI int __libcpp_mutex_lock(__libcpp_mutex_t* __m) {
+ return mtx_lock(__m) == thrd_success ? 0 : EINVAL;
+}
+
+_LIBCPP_NO_THREAD_SAFETY_ANALYSIS inline _LIBCPP_HIDE_FROM_ABI bool __libcpp_mutex_trylock(__libcpp_mutex_t* __m) {
+ return mtx_trylock(__m) == thrd_success;
+}
+
+_LIBCPP_NO_THREAD_SAFETY_ANALYSIS inline _LIBCPP_HIDE_FROM_ABI int __libcpp_mutex_unlock(__libcpp_mutex_t* __m) {
+ return mtx_unlock(__m) == thrd_success ? 0 : EINVAL;
+}
+
+inline _LIBCPP_HIDE_FROM_ABI int __libcpp_mutex_destroy(__libcpp_mutex_t* __m) {
+ mtx_destroy(__m);
+ return 0;
+}
+
+//
+// Condition Variable
+//
+typedef cnd_t __libcpp_condvar_t;
+// cnd_t is a struct so using {} for initialization is valid.
+#define _LIBCPP_CONDVAR_INITIALIZER \
+ {}
+
+inline _LIBCPP_HIDE_FROM_ABI int __libcpp_condvar_signal(__libcpp_condvar_t* __cv) {
+ return cnd_signal(__cv) == thrd_success ? 0 : EINVAL;
+}
+
+inline _LIBCPP_HIDE_FROM_ABI int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv) {
+ return cnd_broadcast(__cv) == thrd_success ? 0 : EINVAL;
+}
+
+_LIBCPP_NO_THREAD_SAFETY_ANALYSIS inline _LIBCPP_HIDE_FROM_ABI int
+__libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m) {
+ return cnd_wait(__cv, __m) == thrd_success ? 0 : EINVAL;
+}
+
+_LIBCPP_NO_THREAD_SAFETY_ANALYSIS inline _LIBCPP_HIDE_FROM_ABI int
+__libcpp_condvar_timedwait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m, timespec* __ts) {
+ int __ec = cnd_timedwait(__cv, __m, __ts);
+ return __ec == thrd_timedout ? ETIMEDOUT : __ec;
+}
+
+inline _LIBCPP_HIDE_FROM_ABI int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv) {
+ cnd_destroy(__cv);
+ return 0;
+}
+
+//
+// Execute once
+//
+typedef ::once_flag __libcpp_exec_once_flag;
+#define _LIBCPP_EXEC_ONCE_INITIALIZER ONCE_FLAG_INIT
+
+inline _LIBCPP_HIDE_FROM_ABI int __libcpp_execute_once(__libcpp_exec_once_flag* flag, void (*init_routine)(void)) {
+ ::call_once(flag, init_routine);
+ return 0;
+}
+
+//
+// Thread id
+//
+typedef thrd_t __libcpp_thread_id;
+
+// 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 thrd_equal(t1, t2) != 0;
+}
+
+// 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 0U
+
+typedef thrd_t __libcpp_thread_t;
+
+inline _LIBCPP_HIDE_FROM_ABI __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t* __t) { return *__t; }
+
+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) {
+ int __ec = thrd_create(__t, reinterpret_cast<thrd_start_t>(__func), __arg);
+ return __ec == thrd_nomem ? ENOMEM : __ec;
+}
+
+inline _LIBCPP_HIDE_FROM_ABI __libcpp_thread_id __libcpp_thread_get_current_id() { return thrd_current(); }
+
+inline _LIBCPP_HIDE_FROM_ABI int __libcpp_thread_join(__libcpp_thread_t* __t) {
+ return thrd_join(*__t, nullptr) == thrd_success ? 0 : EINVAL;
+}
+
+inline _LIBCPP_HIDE_FROM_ABI int __libcpp_thread_detach(__libcpp_thread_t* __t) {
+ return thrd_detach(*__t) == thrd_success ? 0 : EINVAL;
+}
+
+inline _LIBCPP_HIDE_FROM_ABI void __libcpp_thread_yield() { thrd_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);
+ thrd_sleep(&__ts, nullptr);
+}
+
+//
+// Thread local storage
+//
+#define _LIBCPP_TLS_DESTRUCTOR_CC /* nothing */
+
+typedef tss_t __libcpp_tls_key;
+
+inline _LIBCPP_HIDE_FROM_ABI int __libcpp_tls_create(__libcpp_tls_key* __key, void (*__at_exit)(void*)) {
+ return tss_create(__key, __at_exit) == thrd_success ? 0 : EINVAL;
+}
+
+inline _LIBCPP_HIDE_FROM_ABI void* __libcpp_tls_get(__libcpp_tls_key __key) { return tss_get(__key); }
+
+inline _LIBCPP_HIDE_FROM_ABI int __libcpp_tls_set(__libcpp_tls_key __key, void* __p) {
+ return tss_set(__key, __p) == thrd_success ? 0 : EINVAL;
+}
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP___THREAD_SUPPORT_C11_H
diff --git a/third_party/libcxx/include/c++/v1/__thread/support/external.h b/third_party/libcxx/include/c++/v1/__thread/support/external.h
new file mode 100644
index 0000000..d5e2124
--- /dev/null
+++ b/third_party/libcxx/include/c++/v1/__thread/support/external.h
@@ -0,0 +1,21 @@
+// -*- 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_EXTERNAL_H
+#define _LIBCPP___THREAD_SUPPORT_EXTERNAL_H
+
+#include <__config>
+
+#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
+# pragma GCC system_header
+#endif
+
+#include <__external_threading>
+
+#endif // _LIBCPP___THREAD_SUPPORT_EXTERNAL_H
diff --git a/third_party/libcxx/include/c++/v1/__thread/support/pthread.h b/third_party/libcxx/include/c++/v1/__thread/support/pthread.h
new file mode 100644
index 0000000..4cf5c03
--- /dev/null
+++ b/third_party/libcxx/include/c++/v1/__thread/support/pthread.h
@@ -0,0 +1,221 @@
+// -*- 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>
+
+#ifdef __MVS__
+# include <__support/ibm/nanosleep.h>
+#endif
+
+// 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 _LIBCPP_NODEBUG = ::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;
+}
+
+_LIBCPP_NO_THREAD_SAFETY_ANALYSIS inline _LIBCPP_HIDE_FROM_ABI int
+__libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t* __m) {
+ return pthread_mutex_lock(__m);
+}
+
+_LIBCPP_NO_THREAD_SAFETY_ANALYSIS inline _LIBCPP_HIDE_FROM_ABI bool
+__libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t* __m) {
+ return pthread_mutex_trylock(__m) == 0;
+}
+
+_LIBCPP_NO_THREAD_SAFETY_ANALYSIS inline _LIBCPP_HIDE_FROM_ABI 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);
+}
+
+_LIBCPP_NO_THREAD_SAFETY_ANALYSIS inline _LIBCPP_HIDE_FROM_ABI int __libcpp_mutex_lock(__libcpp_mutex_t* __m) {
+ return pthread_mutex_lock(__m);
+}
+
+_LIBCPP_NO_THREAD_SAFETY_ANALYSIS inline _LIBCPP_HIDE_FROM_ABI bool __libcpp_mutex_trylock(__libcpp_mutex_t* __m) {
+ return pthread_mutex_trylock(__m) == 0;
+}
+
+_LIBCPP_NO_THREAD_SAFETY_ANALYSIS inline _LIBCPP_HIDE_FROM_ABI 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);
+}
+
+_LIBCPP_NO_THREAD_SAFETY_ANALYSIS inline _LIBCPP_HIDE_FROM_ABI int
+__libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m) {
+ return pthread_cond_wait(__cv, __m);
+}
+
+_LIBCPP_NO_THREAD_SAFETY_ANALYSIS inline _LIBCPP_HIDE_FROM_ABI 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
diff --git a/third_party/libcxx/include/c++/v1/__thread/support/windows.h b/third_party/libcxx/include/c++/v1/__thread/support/windows.h
new file mode 100644
index 0000000..558b5c8
--- /dev/null
+++ b/third_party/libcxx/include/c++/v1/__thread/support/windows.h
@@ -0,0 +1,131 @@
+// -*- 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_WINDOWS_H
+#define _LIBCPP___THREAD_SUPPORT_WINDOWS_H
+
+#include <__chrono/duration.h>
+#include <__config>
+#include <ctime>
+
+#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
+# pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+using __libcpp_timespec_t = ::timespec;
+
+//
+// Mutex
+//
+typedef void* __libcpp_mutex_t;
+#define _LIBCPP_MUTEX_INITIALIZER 0
+
+#if defined(_WIN64)
+typedef void* __libcpp_recursive_mutex_t[5];
+#else
+typedef void* __libcpp_recursive_mutex_t[6];
+#endif
+
+_LIBCPP_EXPORTED_FROM_ABI int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t* __m);
+
+_LIBCPP_NO_THREAD_SAFETY_ANALYSIS _LIBCPP_EXPORTED_FROM_ABI int
+__libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t* __m);
+
+_LIBCPP_NO_THREAD_SAFETY_ANALYSIS _LIBCPP_EXPORTED_FROM_ABI bool
+__libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t* __m);
+
+_LIBCPP_NO_THREAD_SAFETY_ANALYSIS _LIBCPP_EXPORTED_FROM_ABI int
+__libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t* __m);
+
+_LIBCPP_EXPORTED_FROM_ABI int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t* __m);
+
+_LIBCPP_NO_THREAD_SAFETY_ANALYSIS _LIBCPP_EXPORTED_FROM_ABI int __libcpp_mutex_lock(__libcpp_mutex_t* __m);
+
+_LIBCPP_NO_THREAD_SAFETY_ANALYSIS _LIBCPP_EXPORTED_FROM_ABI bool __libcpp_mutex_trylock(__libcpp_mutex_t* __m);
+
+_LIBCPP_NO_THREAD_SAFETY_ANALYSIS _LIBCPP_EXPORTED_FROM_ABI int __libcpp_mutex_unlock(__libcpp_mutex_t* __m);
+
+_LIBCPP_EXPORTED_FROM_ABI int __libcpp_mutex_destroy(__libcpp_mutex_t* __m);
+
+//
+// Condition variable
+//
+typedef void* __libcpp_condvar_t;
+#define _LIBCPP_CONDVAR_INITIALIZER 0
+
+_LIBCPP_EXPORTED_FROM_ABI int __libcpp_condvar_signal(__libcpp_condvar_t* __cv);
+
+_LIBCPP_EXPORTED_FROM_ABI int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv);
+
+_LIBCPP_NO_THREAD_SAFETY_ANALYSIS _LIBCPP_EXPORTED_FROM_ABI int
+__libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m);
+
+_LIBCPP_NO_THREAD_SAFETY_ANALYSIS _LIBCPP_EXPORTED_FROM_ABI int
+__libcpp_condvar_timedwait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m, __libcpp_timespec_t* __ts);
+
+_LIBCPP_EXPORTED_FROM_ABI int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv);
+
+//
+// Execute once
+//
+typedef void* __libcpp_exec_once_flag;
+#define _LIBCPP_EXEC_ONCE_INITIALIZER 0
+
+_LIBCPP_EXPORTED_FROM_ABI int __libcpp_execute_once(__libcpp_exec_once_flag* __flag, void (*__init_routine)());
+
+//
+// Thread id
+//
+typedef long __libcpp_thread_id;
+
+_LIBCPP_EXPORTED_FROM_ABI bool __libcpp_thread_id_equal(__libcpp_thread_id __t1, __libcpp_thread_id __t2);
+
+_LIBCPP_EXPORTED_FROM_ABI bool __libcpp_thread_id_less(__libcpp_thread_id __t1, __libcpp_thread_id __t2);
+
+//
+// Thread
+//
+#define _LIBCPP_NULL_THREAD 0U
+typedef void* __libcpp_thread_t;
+
+_LIBCPP_EXPORTED_FROM_ABI bool __libcpp_thread_isnull(const __libcpp_thread_t* __t);
+
+_LIBCPP_EXPORTED_FROM_ABI int __libcpp_thread_create(__libcpp_thread_t* __t, void* (*__func)(void*), void* __arg);
+
+_LIBCPP_EXPORTED_FROM_ABI __libcpp_thread_id __libcpp_thread_get_current_id();
+
+_LIBCPP_EXPORTED_FROM_ABI __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t* __t);
+
+_LIBCPP_EXPORTED_FROM_ABI int __libcpp_thread_join(__libcpp_thread_t* __t);
+
+_LIBCPP_EXPORTED_FROM_ABI int __libcpp_thread_detach(__libcpp_thread_t* __t);
+
+_LIBCPP_EXPORTED_FROM_ABI void __libcpp_thread_yield();
+
+_LIBCPP_EXPORTED_FROM_ABI void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns);
+
+//
+// Thread local storage
+//
+typedef long __libcpp_tls_key;
+
+#define _LIBCPP_TLS_DESTRUCTOR_CC __stdcall
+
+_LIBCPP_EXPORTED_FROM_ABI int
+__libcpp_tls_create(__libcpp_tls_key* __key, void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*));
+
+_LIBCPP_EXPORTED_FROM_ABI void* __libcpp_tls_get(__libcpp_tls_key __key);
+
+_LIBCPP_EXPORTED_FROM_ABI int __libcpp_tls_set(__libcpp_tls_key __key, void* __p);
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP___THREAD_SUPPORT_WINDOWS_H
diff --git a/third_party/libcxx/include/c++/v1/__thread/this_thread.h b/third_party/libcxx/include/c++/v1/__thread/this_thread.h
new file mode 100644
index 0000000..4df1377
--- /dev/null
+++ b/third_party/libcxx/include/c++/v1/__thread/this_thread.h
@@ -0,0 +1,79 @@
+// -*- 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/duration.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 {
+
+#if _LIBCPP_HAS_THREADS
+
+_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(); }
+
+#endif // _LIBCPP_HAS_THREADS
+
+} // namespace this_thread
+
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___THREAD_THIS_THREAD_H
diff --git a/third_party/libcxx/include/c++/v1/__thread/thread.h b/third_party/libcxx/include/c++/v1/__thread/thread.h
new file mode 100644
index 0000000..b2f51aa
--- /dev/null
+++ b/third_party/libcxx/include/c++/v1/__thread/thread.h
@@ -0,0 +1,268 @@
+// -*- 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 <__assert>
+#include <__condition_variable/condition_variable.h>
+#include <__config>
+#include <__exception/terminate.h>
+#include <__functional/hash.h>
+#include <__functional/unary_function.h>
+#include <__locale>
+#include <__memory/addressof.h>
+#include <__memory/unique_ptr.h>
+#include <__mutex/mutex.h>
+#include <__system_error/throw_system_error.h>
+#include <__thread/id.h>
+#include <__thread/support.h>
+#include <__type_traits/decay.h>
+#include <__type_traits/enable_if.h>
+#include <__type_traits/invoke.h>
+#include <__type_traits/is_constructible.h>
+#include <__type_traits/is_same.h>
+#include <__type_traits/remove_cvref.h>
+#include <__utility/forward.h>
+#include <tuple>
+
+#if _LIBCPP_HAS_LOCALIZATION
+# 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
+
+#if _LIBCPP_HAS_THREADS
+
+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)
+ std::__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 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_);
+ }
+};
+
+# if _LIBCPP_HAS_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_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, __index_sequence<_Indices...>) {
+ std::__invoke(std::move(std::get<_Indices + 1>(__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());
+ std::__thread_execute(*__p.get(), __make_index_sequence<tuple_size<_Fp>::value - 1>());
+ 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_;
+
+ 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_HIDE_FROM_ABI explicit thread(_Fp&& __f, _Args&&... __args) {
+ static_assert(is_constructible<__decay_t<_Fp>, _Fp>::value, "");
+ static_assert(_And<is_constructible<__decay_t<_Args>, _Args>...>::value, "");
+ static_assert(__is_invocable_v<__decay_t<_Fp>, __decay_t<_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_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();
+
+ _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_); }
+
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool joinable() const _NOEXCEPT { return !__libcpp_thread_isnull(&__t_); }
+ void join();
+ void detach();
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI id get_id() const _NOEXCEPT { return __libcpp_thread_get_id(&__t_); }
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() _NOEXCEPT { return __t_; }
+
+ [[__nodiscard__]] static unsigned hardware_concurrency() _NOEXCEPT;
+};
+
+inline _LIBCPP_HIDE_FROM_ABI void swap(thread& __x, thread& __y) _NOEXCEPT { __x.swap(__y); }
+
+#endif // _LIBCPP_HAS_THREADS
+
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___THREAD_THREAD_H
diff --git a/third_party/libcxx/include/c++/v1/__thread/timed_backoff_policy.h b/third_party/libcxx/include/c++/v1/__thread/timed_backoff_policy.h
new file mode 100644
index 0000000..01fe2dd
--- /dev/null
+++ b/third_party/libcxx/include/c++/v1/__thread/timed_backoff_policy.h
@@ -0,0 +1,45 @@
+// -*- 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_TIMED_BACKOFF_POLICY_H
+#define _LIBCPP___THREAD_TIMED_BACKOFF_POLICY_H
+
+#include <__config>
+#include <__thread/poll_with_backoff.h>
+
+#if _LIBCPP_HAS_THREADS
+
+# include <__chrono/duration.h>
+# include <__thread/support.h>
+
+# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+# endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+struct __libcpp_timed_backoff_policy {
+ _LIBCPP_HIDE_FROM_ABI __backoff_results 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 __backoff_results::__continue_poll;
+ }
+};
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP_HAS_THREADS
+
+#endif // _LIBCPP___THREAD_TIMED_BACKOFF_POLICY_H