From c2a965083bd2f0b88ce8242db629efc034acfded Mon Sep 17 00:00:00 2001
From: Timo Heister <timo.heister@gmail.com>
Date: Wed, 27 May 2020 21:49:36 -0400
Subject: [PATCH] initialize cpp-taskflow

- introduce get_taskflow_executor
- initialize executor
---
 include/deal.II/base/multithread_info.h | 29 +++++++++++++++++++++++++
 source/base/multithread_info.cc         | 27 +++++++++++++++++++++++
 2 files changed, 56 insertions(+)

diff --git a/include/deal.II/base/multithread_info.h b/include/deal.II/base/multithread_info.h
index 1b618a90c7..8476510c80 100644
--- a/include/deal.II/base/multithread_info.h
+++ b/include/deal.II/base/multithread_info.h
@@ -23,6 +23,14 @@
 #  include <deal.II/base/exceptions.h>
 #  include <deal.II/base/types.h>
 
+#  include <memory>
+
+// forward declaration from <taskflow/taskflow.hpp>
+namespace tf
+{
+  class Executor;
+}
+
 DEAL_II_NAMESPACE_OPEN
 
 /**
@@ -113,11 +121,32 @@ public:
   static void
   initialize_multithreading();
 
+
+#  ifdef DEAL_II_WITH_CPP_TASKFLOW
+  /**
+   * Return a reference to the global Executor from cpp-taskflow.
+   *
+   * The Executor is set to use n_threads() worker threads that you can
+   * control using set_thread_limit() and the DEAL_II_NUM_THREADS environment
+   * variable.
+   */
+  static tf::Executor &
+  get_taskflow_executor();
+#  endif
+
 private:
   /**
    * Variable representing the maximum number of threads.
    */
   static unsigned int n_max_threads;
+
+#  ifdef DEAL_II_WITH_CPP_TASKFLOW
+  /**
+   * Store a cpp-taskflow Executor that is constructed with N workers (from
+   * set_thread_limit).
+   */
+  static std::unique_ptr<tf::Executor> executor;
+#  endif
 };
 
 
diff --git a/source/base/multithread_info.cc b/source/base/multithread_info.cc
index 6da31b9853..c4de3074a8 100644
--- a/source/base/multithread_info.cc
+++ b/source/base/multithread_info.cc
@@ -26,6 +26,13 @@
 #  undef TBB_SUPPRESS_DEPRECATED_MESSAGES
 #endif
 
+
+#ifdef DEAL_II_WITH_CPP_TASKFLOW
+DEAL_II_DISABLE_EXTRA_DIAGNOSTICS
+#  include <taskflow/taskflow.hpp>
+DEAL_II_ENABLE_EXTRA_DIAGNOSTICS
+#endif
+
 DEAL_II_NAMESPACE_OPEN
 
 
@@ -93,6 +100,10 @@ MultithreadInfo::set_thread_limit(const unsigned int max_threads)
     dummy.terminate();
   dummy.initialize(n_max_threads);
 #endif
+
+#ifdef DEAL_II_WITH_CPP_TASKFLOW
+  executor = std::make_unique<tf::Executor>(n_max_threads);
+#endif
 }
 
 
@@ -134,6 +145,22 @@ MultithreadInfo::initialize_multithreading()
   done = true;
 }
 
+#ifdef DEAL_II_WITH_CPP_TASKFLOW
+tf::Executor &
+MultithreadInfo::get_taskflow_executor()
+{
+  // This should not trigger in normal user code, because we initialize the
+  // Executor in the static DoOnce struct at the end of this file unless you
+  // ask for the Executor before this static object gets constructed.
+  Assert(
+    executor.get() != nullptr,
+    ExcMessage(
+      "Please initialize multithreading using MultithreadInfo::set_thread_limit() first."));
+  return *(executor.get());
+}
+
+std::unique_ptr<tf::Executor> MultithreadInfo::executor = nullptr;
+#endif
 
 unsigned int MultithreadInfo::n_max_threads = numbers::invalid_unsigned_int;
 
-- 
2.39.5