diff options
Diffstat (limited to 'gdbsupport/cxx-thread.h')
-rw-r--r-- | gdbsupport/cxx-thread.h | 243 |
1 files changed, 243 insertions, 0 deletions
diff --git a/gdbsupport/cxx-thread.h b/gdbsupport/cxx-thread.h new file mode 100644 index 0000000..e4061eb --- /dev/null +++ b/gdbsupport/cxx-thread.h @@ -0,0 +1,243 @@ +/* Wrappers for C++ threading + + Copyright (C) 2025 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef GDBSUPPORT_CXX_THREAD_H +#define GDBSUPPORT_CXX_THREAD_H + +/* This header implements shims for the parts of the C++ threading + library that are needed by gdb. + + The reason this exists is that some versions of libstdc++ do not + supply a working C++ thread implementation. In particular this was + true for several versions of the Windows compiler. See + https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93687. + + For systems where this works, this header just supplies aliases of + the standard functionality, in the "gdb" namespace. For example, + "gdb::mutex" is an alias for "std::mutex". + + For non-working ports, shims are provided. These are just the + subset needed by gdb, and they generally do nothing, or as little + as possible. In particular they all simply assume single-threaded + operation. */ + +#if CXX_STD_THREAD + +#include <thread> +#include <mutex> +#include <condition_variable> +#include <future> + +namespace gdb +{ + +using condition_variable = std::condition_variable; +using cv_status = std::cv_status; +using future_status = std::future_status; +using mutex = std::mutex; +using recursive_mutex = std::recursive_mutex; +using thread = std::thread; + +namespace this_thread = std::this_thread; + +template<typename T> +using lock_guard = std::lock_guard<T>; + +template<typename T> +using unique_lock = std::unique_lock<T>; + +template<typename T> +using future = std::future<T>; + +} /* namespace gdb*/ + +#else + +#include <chrono> + +namespace gdb +{ + +/* A do-nothing replacement for std::mutex. */ +struct mutex +{ + mutex () = default; + + DISABLE_COPY_AND_ASSIGN (mutex); + + void lock () + { + } + + void unlock () + { + } +}; + +/* A do-nothing replacement for std::recursive_mutex. */ +struct recursive_mutex +{ + recursive_mutex () = default; + + DISABLE_COPY_AND_ASSIGN (recursive_mutex); + + void lock () + { + } + + void unlock () + { + } +}; + +/* A do-nothing replacement for std::lock_guard. */ +template<typename T> +struct lock_guard +{ + explicit lock_guard (T &m) + { + } + + DISABLE_COPY_AND_ASSIGN (lock_guard); +}; + +/* A do-nothing replacement for std::unique_lock. */ +template<typename T> +struct unique_lock +{ + explicit unique_lock (T &m) + { + } + + DISABLE_COPY_AND_ASSIGN (unique_lock); +}; + +/* A compatibility enum for std::cv_status. */ +enum class cv_status +{ + no_timeout, + timeout, +}; + +/* A do-nothing replacement for std::condition_variable. */ +struct condition_variable +{ + condition_variable () = default; + + DISABLE_COPY_AND_ASSIGN (condition_variable); + + void notify_one () noexcept + { + } + + void wait (unique_lock<mutex> &lock) + { + } + + template<class Rep, class Period> + cv_status wait_for (unique_lock<mutex> &lock, + const std::chrono::duration<Rep, Period> &rel_time) + { + return cv_status::no_timeout; + } +}; + +/* A compatibility enum for std::future_status. This is just the + subset needed by gdb. */ +enum class future_status +{ + ready, + timeout, +}; + +/* A compatibility implementation of std::future. */ +template<typename T> +class future +{ +public: + + explicit future (T value) + : m_value (std::move (value)) + { + } + + future () = default; + future (future &&other) = default; + future (const future &other) = delete; + future &operator= (future &&other) = default; + future &operator= (const future &other) = delete; + + void wait () const { } + + template<class Rep, class Period> + future_status wait_for (const std::chrono::duration<Rep,Period> &duration) + const + { + return future_status::ready; + } + + T get () { return std::move (m_value); } + +private: + + T m_value; +}; + +/* A specialization for void. */ + +template<> +class future<void> +{ +public: + void wait () const { } + + template<class Rep, class Period> + future_status wait_for (const std::chrono::duration<Rep,Period> &duration) + const + { + return future_status::ready; + } + + void get () { } +}; + +/* Rather than try to write a gdb::thread class, we just use a + namespace since only the 'id' type is needed. Code manipulating + actual std::thread objects has to be wrapped in a check anyway. */ +namespace thread +{ +/* Replacement for std::thread::id. */ +using id = int; +} + +/* Replacement for std::this_thread. */ +namespace this_thread +{ +static inline thread::id +get_id () +{ + return 0; +} +} + +} /* namespace gdb */ + +#endif /* CXX_STD_THREAD */ + +#endif /* GDBSUPPORT_CXX_THREAD_H */ |