16#ifndef dealii_thread_management_h
17#define dealii_thread_management_h
37#ifdef DEAL_II_HAVE_CXX20
42#ifdef DEAL_II_WITH_TBB
43# include <tbb/task_group.h>
76 template <
typename ForwardIterator>
77 std::vector<std::pair<ForwardIterator, ForwardIterator>>
79 const ForwardIterator &end,
80 const unsigned int n_intervals);
90 std::vector<std::pair<unsigned int, unsigned int>>
92 const unsigned int end,
93 const unsigned int n_intervals);
145 template <
typename ForwardIterator>
146 std::vector<std::pair<ForwardIterator, ForwardIterator>>
148 const ForwardIterator &end,
149 const unsigned int n_intervals)
151 using IteratorPair = std::pair<ForwardIterator, ForwardIterator>;
157 if (n_intervals == 1)
158 return (std::vector<IteratorPair>(1, IteratorPair(begin, end)));
161 const unsigned int n_elements = std::distance(begin, end);
162 const unsigned int n_elements_per_interval = n_elements / n_intervals;
163 const unsigned int residual = n_elements % n_intervals;
165 std::vector<IteratorPair> return_values(n_intervals);
167 return_values[0].first =
begin;
168 for (
unsigned int i = 0; i < n_intervals; ++i)
170 if (i != n_intervals - 1)
172 return_values[i].second = return_values[i].first;
177 std::advance(return_values[i].
second,
178 static_cast<signed int>(n_elements_per_interval));
182 ++return_values[i].second;
184 return_values[i + 1].first = return_values[i].second;
187 return_values[i].second =
end;
189 return return_values;
217 template <
typename RT>
239 value = std::move(v);
250 value = std::move(v.get());
274 template <
typename RT>
287 inline reference_type
356 template <
typename RT>
358 call(
const std::function<RT()> & function,
361 ret_val.
set(function());
386 template <
typename RT>
466 start(
const std::function<RT()> &function)
469 ret_val = std::make_shared<return_value<RT>>();
512 catch (
const std::exception &exc)
551 template <
typename RT =
void>
559 Thread(
const std::function<RT()> &function)
685 template <
typename T>
704 template <
typename T>
707 static std::reference_wrapper<T>
729 template <
typename RT>
812 template <
typename FunctionObjectType>
815 ->
Thread<decltype(function_object())>
819 using return_type =
decltype(function_object());
834 template <
typename RT,
typename... Args>
842 [dummy, fun_ptr]() -> RT {
return std_cxx17::apply(fun_ptr, dummy); });
855 template <
typename RT,
typename C,
typename... Args>
859 std_cxx20::type_identity_t<Args>... args)
862 return new_thread(std::function<RT()>(std::bind(
873 template <
typename RT,
typename C,
typename... Args>
877 std_cxx20::type_identity_t<Args>... args)
882 return new_thread(std::function<RT()>(std::bind(
898 template <
typename RT =
void>
908 threads.push_back(t);
921 for (
auto &t : threads)
941 template <
typename RT,
typename Function>
943 (std::invocable<Function> &&
944 std::convertible_to<std::invoke_result_t<Function>, RT>))
947 promise.set_value(function());
960 template <
typename Function>
963 std::promise<
void> &promise)
998 template <
typename RT =
void>
1013 Task(
const std::function<RT()> &function_object)
1017#ifdef DEAL_II_WITH_TBB
1022 std::unique_ptr<std::promise<RT>> promise =
1023 std::make_unique<std::promise<RT>>();
1025 std::make_shared<TaskData>(std::move(promise->get_future()));
1065 std::shared_ptr<std::promise<RT>>(std::move(promise))]() {
1075 promise->set_exception(std::current_exception());
1104 std::async(std::launch::async | std::launch::deferred,
1120 std::promise<RT> promise;
1121 task_data = std::make_shared<TaskData>(promise.get_future());
1131 promise.set_exception(std::current_exception());
1281 "The current object is not associated with a task that "
1282 "can be joined. It may have been detached, or you "
1283 "may have already joined it in the past.");
1388 std::lock_guard<std::mutex> lock(
mutex);
1393#ifdef DEAL_II_WITH_TBB
1488#ifdef DEAL_II_WITH_TBB
1494 friend class Task<RT>;
1526 template <
typename RT>
1612 template <
typename FunctionObjectType>
1614 inline auto
new_task(FunctionObjectType function_object)
1615 ->
Task<decltype(function_object())>
1617 using return_type =
decltype(function_object());
1619 return new_task(std::function<return_type()>(function_object));
1630 template <
typename RT,
typename... Args>
1636 [dummy, fun_ptr]() -> RT {
return std_cxx17::apply(fun_ptr, dummy); });
1647 template <
typename RT,
typename C,
typename... Args>
1651 std_cxx20::type_identity_t<Args>... args)
1654 return new_task(std::function<RT()>(std::bind(
1664 template <
typename RT,
typename C,
typename... Args>
1668 std_cxx20::type_identity_t<Args>... args)
1671 return new_task(std::function<RT()>(std::bind(
1690 template <
typename RT =
void>
1715 return tasks.size();
1735 std::vector<RT> results;
1736 results.reserve(
size());
1737 for (
auto &t :
tasks)
1738 results.emplace_back(std::move(t.return_value()));
1752 for (
auto &t :
tasks)
static void initialize_multithreading()
static unsigned int n_threads()
TaskGroup & operator+=(const Task< RT > &t)
std::vector< RT > return_values()
std::list< Task< RT > > tasks
TaskData(std::future< RT > &&future) noexcept
TaskData(const TaskData &)=delete
TaskData & operator=(const TaskData &)=delete
std::atomic< bool > task_has_finished
internal::return_value< RT > returned_object
TaskData & operator=(TaskData &&)=delete
TaskData(TaskData &&)=delete
internal::return_value< RT >::reference_type get()
tbb::task_group task_group
std::shared_ptr< TaskData > task_data
internal::return_value< RT >::reference_type return_value()
Task(const std::function< RT()> &function_object)
std::list< Thread< RT > > threads
ThreadGroup & operator+=(const Thread< RT > &t)
Thread(const std::function< RT()> &function)
internal::return_value< RT >::reference_type return_value()
std::shared_ptr< internal::ThreadDescriptor< RT > > thread_descriptor
bool operator==(const Thread &t) const
Thread(const Thread< RT > &t)
#define DEAL_II_DEPRECATED
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_DISABLE_EXTRA_DIAGNOSTICS
#define DEAL_II_CXX20_REQUIRES(condition)
#define DEAL_II_NAMESPACE_CLOSE
#define DEAL_II_ENABLE_EXTRA_DIAGNOSTICS
static ::ExceptionBase & ExcNoTask()
#define Assert(cond, exc)
#define DeclExceptionMsg(Exception, defaulttext)
static ::ExceptionBase & ExcInternalError()
#define AssertThrow(cond, exc)
std::vector< std::pair< ForwardIterator, ForwardIterator > > split_range(const ForwardIterator &begin, const ForwardIterator &end, const unsigned int n_intervals)
Thread< RT > new_thread(const std::function< RT()> &function)
Task< RT > new_task(const std::function< RT()> &function)
std::vector< std::pair< unsigned int, unsigned int > > split_interval(const unsigned int begin, const unsigned int end, const unsigned int n_intervals)
void handle_unknown_exception()
void evaluate_and_set_promise(Function &function, std::promise< RT > &promise)
void call(const std::function< RT()> &function, internal::return_value< RT > &ret_val)
void handle_std_exception(const std::exception &exc)
VectorType::value_type * end(VectorType &V)
VectorType::value_type * begin(VectorType &V)
typename type_identity< T >::type type_identity_t
Mutex thread_is_active_mutex
std::shared_ptr< return_value< RT > > ret_val
std::atomic< bool > thread_is_active
void start(const std::function< RT()> &function)
static void thread_entry_point(const std::function< RT()> &function, std::shared_ptr< return_value< RT > > ret_val)
static std::reference_wrapper< T > act(T &t)
reference_type get() const
void set_from(std::future< RT & > &v)
void set_from(std::future< void > &)
void set_from(std::future< RT > &v)