# 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
/**
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
};
# 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
dummy.terminate();
dummy.initialize(n_max_threads);
#endif
+
+#ifdef DEAL_II_WITH_CPP_TASKFLOW
+ executor = std::make_unique<tf::Executor>(n_max_threads);
+#endif
}
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;