aboutsummaryrefslogtreecommitdiff
path: root/gdbsupport/cxx-thread.h
diff options
context:
space:
mode:
Diffstat (limited to 'gdbsupport/cxx-thread.h')
-rw-r--r--gdbsupport/cxx-thread.h243
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 */