123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262 |
- #pragma once
- #ifdef __GNUC__
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wunused-parameter"
- #endif
- //===-- llvm/Support/thread.h - Wrapper for <thread> ------------*- 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
- //
- //===----------------------------------------------------------------------===//
- //
- // This header is a wrapper for <thread> that works around problems with the
- // MSVC headers when exceptions are disabled. It also provides llvm::thread,
- // which is either a typedef of std::thread or a replacement that calls the
- // function synchronously depending on the value of LLVM_ENABLE_THREADS.
- //
- //===----------------------------------------------------------------------===//
- #ifndef LLVM_SUPPORT_THREAD_H
- #define LLVM_SUPPORT_THREAD_H
- #include "llvm/ADT/Optional.h"
- #include "llvm/Config/llvm-config.h"
- #ifdef _WIN32
- typedef unsigned long DWORD;
- typedef void *PVOID;
- typedef PVOID HANDLE;
- #endif
- #if LLVM_ENABLE_THREADS
- #include <thread>
- namespace llvm {
- #if LLVM_ON_UNIX || _WIN32
- /// LLVM thread following std::thread interface with added constructor to
- /// specify stack size.
- class thread {
- template <typename FPtr, typename... Args, size_t... Indices>
- static void Apply(std::tuple<FPtr, Args...> &Callee,
- std::index_sequence<Indices...>) {
- std::move(std::get<0>(Callee))(std::move(std::get<Indices + 1>(Callee))...);
- }
- template <typename CalleeTuple> static void GenericThreadProxy(void *Ptr) {
- std::unique_ptr<CalleeTuple> Callee(static_cast<CalleeTuple *>(Ptr));
- // FIXME: use std::apply when C++17 is allowed.
- std::make_index_sequence<std::tuple_size<CalleeTuple>() - 1> Indices{};
- Apply(*Callee.get(), Indices);
- }
- public:
- #if LLVM_ON_UNIX
- using native_handle_type = pthread_t;
- using id = pthread_t;
- using start_routine_type = void *(*)(void *);
- template <typename CalleeTuple> static void *ThreadProxy(void *Ptr) {
- GenericThreadProxy<CalleeTuple>(Ptr);
- return nullptr;
- }
- #elif _WIN32
- using native_handle_type = HANDLE;
- using id = DWORD;
- using start_routine_type = unsigned(__stdcall *)(void *);
- template <typename CalleeTuple>
- static unsigned __stdcall ThreadProxy(void *Ptr) {
- GenericThreadProxy<CalleeTuple>(Ptr);
- return 0;
- }
- #endif
- static const llvm::Optional<unsigned> DefaultStackSize;
- thread() : Thread(native_handle_type()) {}
- thread(thread &&Other) noexcept
- : Thread(std::exchange(Other.Thread, native_handle_type())) {}
- template <class Function, class... Args>
- explicit thread(Function &&f, Args &&...args)
- : thread(DefaultStackSize, f, args...) {}
- template <class Function, class... Args>
- explicit thread(llvm::Optional<unsigned> StackSizeInBytes, Function &&f,
- Args &&...args);
- thread(const thread &) = delete;
- ~thread() {
- if (joinable())
- std::terminate();
- }
- thread &operator=(thread &&Other) noexcept {
- if (joinable())
- std::terminate();
- Thread = std::exchange(Other.Thread, native_handle_type());
- return *this;
- }
- bool joinable() const noexcept { return Thread != native_handle_type(); }
- inline id get_id() const noexcept;
- native_handle_type native_handle() const noexcept { return Thread; }
- static unsigned hardware_concurrency() {
- return std::thread::hardware_concurrency();
- };
- inline void join();
- inline void detach();
- void swap(llvm::thread &Other) noexcept { std::swap(Thread, Other.Thread); }
- private:
- native_handle_type Thread;
- };
- thread::native_handle_type
- llvm_execute_on_thread_impl(thread::start_routine_type ThreadFunc, void *Arg,
- llvm::Optional<unsigned> StackSizeInBytes);
- void llvm_thread_join_impl(thread::native_handle_type Thread);
- void llvm_thread_detach_impl(thread::native_handle_type Thread);
- thread::id llvm_thread_get_id_impl(thread::native_handle_type Thread);
- thread::id llvm_thread_get_current_id_impl();
- template <class Function, class... Args>
- thread::thread(llvm::Optional<unsigned> StackSizeInBytes, Function &&f,
- Args &&...args) {
- typedef std::tuple<typename std::decay<Function>::type,
- typename std::decay<Args>::type...>
- CalleeTuple;
- std::unique_ptr<CalleeTuple> Callee(
- new CalleeTuple(std::forward<Function>(f), std::forward<Args>(args)...));
- Thread = llvm_execute_on_thread_impl(ThreadProxy<CalleeTuple>, Callee.get(),
- StackSizeInBytes);
- if (Thread != native_handle_type())
- Callee.release();
- }
- thread::id thread::get_id() const noexcept {
- return llvm_thread_get_id_impl(Thread);
- }
- void thread::join() {
- llvm_thread_join_impl(Thread);
- Thread = native_handle_type();
- }
- void thread::detach() {
- llvm_thread_detach_impl(Thread);
- Thread = native_handle_type();
- }
- namespace this_thread {
- inline thread::id get_id() { return llvm_thread_get_current_id_impl(); }
- } // namespace this_thread
- #else // !LLVM_ON_UNIX && !_WIN32
- /// std::thread backed implementation of llvm::thread interface that ignores the
- /// stack size request.
- class thread {
- public:
- using native_handle_type = std::thread::native_handle_type;
- using id = std::thread::id;
- thread() : Thread(std::thread()) {}
- thread(thread &&Other) noexcept
- : Thread(std::exchange(Other.Thread, std::thread())) {}
- template <class Function, class... Args>
- explicit thread(llvm::Optional<unsigned> StackSizeInBytes, Function &&f,
- Args &&...args)
- : Thread(std::forward<Function>(f), std::forward<Args>(args)...) {}
- template <class Function, class... Args>
- explicit thread(Function &&f, Args &&...args) : Thread(f, args...) {}
- thread(const thread &) = delete;
- ~thread() {}
- thread &operator=(thread &&Other) noexcept {
- Thread = std::exchange(Other.Thread, std::thread());
- return *this;
- }
- bool joinable() const noexcept { return Thread.joinable(); }
- id get_id() const noexcept { return Thread.get_id(); }
- native_handle_type native_handle() noexcept { return Thread.native_handle(); }
- static unsigned hardware_concurrency() {
- return std::thread::hardware_concurrency();
- };
- inline void join() { Thread.join(); }
- inline void detach() { Thread.detach(); }
- void swap(llvm::thread &Other) noexcept { std::swap(Thread, Other.Thread); }
- private:
- std::thread Thread;
- };
- namespace this_thread {
- inline thread::id get_id() { return std::this_thread::get_id(); }
- }
- #endif // LLVM_ON_UNIX || _WIN32
- } // namespace llvm
- #else // !LLVM_ENABLE_THREADS
- #include <utility>
- namespace llvm {
- struct thread {
- thread() {}
- thread(thread &&other) {}
- template <class Function, class... Args>
- explicit thread(llvm::Optional<unsigned> StackSizeInBytes, Function &&f,
- Args &&...args) {
- f(std::forward<Args>(args)...);
- }
- template <class Function, class... Args>
- explicit thread(Function &&f, Args &&...args) {
- f(std::forward<Args>(args)...);
- }
- thread(const thread &) = delete;
- void detach() {
- report_fatal_error("Detaching from a thread does not make sense with no "
- "threading support");
- }
- void join() {}
- static unsigned hardware_concurrency() { return 1; };
- };
- } // namespace llvm
- #endif // LLVM_ENABLE_THREADS
- #endif // LLVM_SUPPORT_THREAD_H
- #ifdef __GNUC__
- #pragma GCC diagnostic pop
- #endif
|