Fix --disable-threading build
authorTom Tromey <tromey@adacore.com>
Mon, 9 May 2022 17:48:40 +0000 (11:48 -0600)
committerTom Tromey <tromey@adacore.com>
Tue, 10 May 2022 14:15:40 +0000 (08:15 -0600)
PR build/29110 points out that GDB fails to build on mingw when the
"win32" thread model is in use.  It turns out that the Fedora cross
tools using the "posix" thread model, which somehow manages to support
std::future, whereas the win32 model does not.

While looking into this, I found that the configuring with
--disable-threading will also cause a build failure.

This patch fixes this build by introducing a compatibility wrapper for
std::future.

I am not able to test the win32 thread model build, but I'm going to
ask the reporter to try this patch.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=29110

gdb/dwarf2/cooked-index.h
gdbsupport/parallel-for.h
gdbsupport/thread-pool.cc
gdbsupport/thread-pool.h

index a460351612f52ba5e44fc0b2f3853cad3c381bc3..1d229586948ffc5a3b0a3437f83d9cef67e591e6 100644 (file)
@@ -330,7 +330,7 @@ private:
   /* A future that tracks when the 'finalize' method is done.  Note
      that the 'get' method is never called on this future, only
      'wait'.  */
-  std::future<void> m_future;
+  gdb::future<void> m_future;
 };
 
 #endif /* GDB_DWARF2_COOKED_INDEX_H */
index 713ec660306e8fb2dbd8d95b2db1c88d0cb9a78d..7b6891a0dcba9230eb4cba8a0850bda72cffc1ca 100644 (file)
@@ -72,7 +72,7 @@ private:
   
   /* A vector of futures coming from the tasks run in the
      background.  */
-  std::vector<std::future<T>> m_futures;
+  std::vector<gdb::future<T>> m_futures;
 };
 
 /* See the generic template.  */
@@ -108,7 +108,7 @@ public:
 
 private:
 
-  std::vector<std::future<void>> m_futures;
+  std::vector<gdb::future<void>> m_futures;
 };
 
 }
index 3674e910f1db24c07dfffbd274f1caa3a7ecd2ef..ddb76b691c1bc9cc01773b6bff7f9637f5016fd7 100644 (file)
@@ -192,12 +192,13 @@ thread_pool::set_thread_count (size_t num_threads)
 #endif /* CXX_STD_THREAD */
 }
 
+#if CXX_STD_THREAD
+
 void
 thread_pool::do_post_task (std::packaged_task<void ()> &&func)
 {
   std::packaged_task<void ()> t (std::move (func));
 
-#if CXX_STD_THREAD
   if (m_thread_count != 0)
     {
       std::lock_guard<std::mutex> guard (m_tasks_mutex);
@@ -205,15 +206,12 @@ thread_pool::do_post_task (std::packaged_task<void ()> &&func)
       m_tasks_cv.notify_one ();
     }
   else
-#endif
     {
       /* Just execute it now.  */
       t ();
     }
 }
 
-#if CXX_STD_THREAD
-
 void
 thread_pool::thread_function ()
 {
index 5e203fd896c189d5a561f6fdc79e25ce43a05bf7..4db35bab957b332e7817417b6290ff0521c6df6c 100644 (file)
 #include <thread>
 #include <mutex>
 #include <condition_variable>
-#endif
 #include <future>
+#endif
 #include "gdbsupport/gdb_optional.h"
 
 namespace gdb
 {
 
+#if CXX_STD_THREAD
+
+/* Simply use the standard future.  */
+template<typename T>
+using future = std::future<T>;
+
+#else /* CXX_STD_THREAD */
+
+/* A compatibility wrapper for std::future.  Once <thread> and
+   <future> are available in all GCC builds -- should that ever happen
+   -- this can be removed.  GCC does not implement threading for
+   MinGW, see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93687.
+
+   Meanwhile, in this mode, there are no threads.  Tasks submitted to
+   the thread pool are invoked immediately and their result is stored
+   here.  The base template here simply wraps a T and provides some
+   std::future compatibility methods.  The provided methods are chosen
+   based on what GDB needs presently.  */
+
+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 { }
+
+  T get () { return std::move (m_value); }
+
+private:
+
+  T m_value;
+};
+
+/* A specialization for void.  */
+
+template<>
+class future<void>
+{
+public:
+  void wait () const { }
+  void get () { }
+};
+
+#endif /* CXX_STD_THREAD */
+
+
 /* A thread pool.
 
    There is a single global thread pool, see g_thread_pool.  Tasks can
@@ -64,23 +121,32 @@ public:
 
   /* Post a task to the thread pool.  A future is returned, which can
      be used to wait for the result.  */
-  std::future<void> post_task (std::function<void ()> &&func)
+  future<void> post_task (std::function<void ()> &&func)
   {
+#if CXX_STD_THREAD
     std::packaged_task<void ()> task (std::move (func));
-    std::future<void> result = task.get_future ();
+    future<void> result = task.get_future ();
     do_post_task (std::packaged_task<void ()> (std::move (task)));
     return result;
+#else
+    func ();
+    return {};
+#endif /* CXX_STD_THREAD */
   }
 
   /* Post a task to the thread pool.  A future is returned, which can
      be used to wait for the result.  */
   template<typename T>
-  std::future<T> post_task (std::function<T ()> &&func)
+  future<T> post_task (std::function<T ()> &&func)
   {
+#if CXX_STD_THREAD
     std::packaged_task<T ()> task (std::move (func));
-    std::future<T> result = task.get_future ();
+    future<T> result = task.get_future ();
     do_post_task (std::packaged_task<void ()> (std::move (task)));
     return result;
+#else
+    return future<T> (func ());
+#endif /* CXX_STD_THREAD */
   }
 
 private: