16 #ifndef dealii_thread_management_h 17 # define dealii_thread_management_h 28 # include <condition_variable> 29 # include <functional> 120 template <
typename ForwardIterator>
121 std::vector<std::pair<ForwardIterator, ForwardIterator>>
123 const ForwardIterator &
end,
124 const unsigned int n_intervals);
134 std::vector<std::pair<unsigned int, unsigned int>>
136 const unsigned int end,
137 const unsigned int n_intervals);
189 template <
typename ForwardIterator>
190 std::vector<std::pair<ForwardIterator, ForwardIterator>>
192 const ForwardIterator &
end,
193 const unsigned int n_intervals)
195 using IteratorPair = std::pair<ForwardIterator, ForwardIterator>;
201 if (n_intervals == 1)
202 return (std::vector<IteratorPair>(1, IteratorPair(begin, end)));
205 const unsigned int n_elements = std::distance(begin, end);
206 const unsigned int n_elements_per_interval = n_elements / n_intervals;
207 const unsigned int residual = n_elements % n_intervals;
209 std::vector<IteratorPair> return_values(n_intervals);
211 return_values[0].first =
begin;
212 for (
unsigned int i = 0; i < n_intervals; ++i)
214 if (i != n_intervals - 1)
216 return_values[i].second = return_values[i].first;
222 static_cast<signed int>(n_elements_per_interval));
226 ++return_values[i].second;
228 return_values[i + 1].first = return_values[i].second;
231 return_values[i].second =
end;
233 return return_values;
261 template <
typename RT>
283 value = std::move(v);
289 value = std::move(v.get());
313 template <
typename RT>
384 template <
typename RT>
386 call(
const std::function<RT()> &
function,
389 ret_val.
set(
function());
414 template <
typename RT>
478 : thread_is_active(false)
483 if (!thread_is_active)
486 thread_is_active =
false;
494 start(
const std::function<RT()> &
function)
496 thread_is_active =
true;
497 ret_val = std::make_shared<return_value<RT>>();
498 thread = std::thread(thread_entry_point,
function, ret_val);
511 if (thread_is_active ==
false)
514 std::lock_guard<std::mutex> lock(thread_is_active_mutex);
515 if (thread_is_active ==
true)
519 thread_is_active =
false;
538 call(
function, *ret_val);
540 catch (
const std::exception &exc)
574 template <
typename RT =
void>
581 Thread(
const std::function<RT()> &
function)
582 : thread_descriptor(new
internal::ThreadDescriptor<RT>())
585 thread_descriptor->start(
function);
599 : thread_descriptor(t.thread_descriptor)
610 if (thread_descriptor)
611 thread_descriptor->join();
661 return thread_descriptor->ret_val->get();
671 return static_cast<bool>(thread_descriptor);
705 template <
typename T>
724 template <
typename T>
727 static std::reference_wrapper<T>
747 template <
typename RT>
820 template <
typename FunctionObjectType>
825 using return_type = decltype(function_object());
837 template <
typename RT,
typename... Args>
853 template <
typename RT,
typename C,
typename... Args>
860 return new_thread(std::function<RT()>(std::bind(
869 template <
typename RT,
typename C,
typename... Args>
876 return new_thread(std::function<RT()>(std::bind(
889 template <
typename RT =
void>
899 threads.push_back(t);
912 for (
typename std::list<
Thread<RT>>::const_iterator t = threads.begin();
931 template <
typename RT,
typename Function>
935 promise.set_value(
function());
946 template <
typename Function>
983 template <
typename RT =
void>
998 Task(
const std::function<RT()> &function_object)
1001 task_data = std::make_shared<TaskData>(
1002 std::async(std::launch::async, function_object));
1015 std::promise<RT> promise;
1016 task_data = std::make_shared<TaskData>(promise.get_future());
1026 promise.set_exception(std::current_exception());
1100 return (task_data !=
nullptr);
1161 return task_data->get();
1174 "The current object is not associated with a task that " 1175 "can be joined. It may have been detached, or you " 1176 "may have already joined it in the past.");
1195 : future(
std::move(future))
1196 , task_has_finished(false)
1209 if (task_has_finished)
1215 std::lock_guard<std::mutex> lock(mutex);
1216 if (task_has_finished)
1232 returned_object.set_from(future);
1235 task_has_finished =
true;
1245 return returned_object.get();
1322 template <
typename RT>
1412 template <
typename FunctionObjectType>
1417 using return_type = decltype(function_object());
1419 return new_task(std::function<return_type()>(function_object));
1430 template <
typename RT,
typename... Args>
1447 template <
typename RT,
typename C,
typename... Args>
1454 return new_task(std::function<RT()>(std::bind(
1464 template <
typename RT,
typename C,
typename... Args>
1471 return new_task(std::function<RT()>(std::bind(
1490 template <
typename RT =
void>
1515 return tasks.size();
1528 for (
auto &t : tasks)
void evaluate_and_set_promise(Function &function, std::promise< void > &promise)
std::shared_ptr< internal::ThreadDescriptor< RT > > thread_descriptor
Task< RT > new_task(const std::function< RT()> &function)
Thread(const Thread< RT > &t)
void evaluate_and_set_promise(Function &function, std::promise< RT > &promise)
std::list< Task< RT > > tasks
internal::return_value< RT >::reference_type return_value()
std::atomic< bool > thread_is_active
void call(const std::function< void()> &function, internal::return_value< void > &)
std::shared_ptr< return_value< RT > > ret_val
#define AssertThrow(cond, exc)
std::shared_ptr< TaskData > task_data
SymmetricTensor< 2, dim, Number > C(const Tensor< 2, dim, Number > &F)
std::vector< std::pair< unsigned int, unsigned int > > split_interval(const unsigned int begin, const unsigned int end, const unsigned int n_intervals)
Task(const std::function< RT()> &function_object)
Mutex & operator=(const Mutex &)
void set_from(std::future< void > &)
void set_from(std::future< RT &> &v)
#define Assert(cond, exc)
static void initialize_multithreading()
auto apply(F &&fn, Tuple &&t) -> decltype(apply_impl(std::forward< F >(fn), std::forward< Tuple >(t), std::make_index_sequence< std::tuple_size< typename std::remove_reference< Tuple >::type >::value >()))
#define DeclExceptionMsg(Exception, defaulttext)
std::atomic< bool > task_has_finished
#define DEAL_II_NAMESPACE_CLOSE
VectorType::value_type * end(VectorType &V)
void set_from(std::future< RT > &v)
Thread(const std::function< RT()> &function)
static std::reference_wrapper< T > act(T &t)
internal::return_value< RT >::reference_type return_value()
void advance(std::tuple< I1, I2 > &t, const unsigned int n)
bool operator==(const Thread &t) const
#define DEAL_II_NAMESPACE_OPEN
VectorType::value_type * begin(VectorType &V)
TaskGroup & operator+=(const Task< RT > &t)
void start(const std::function< RT()> &function)
ThreadGroup & operator+=(const Thread< RT > &t)
TaskData(std::future< RT > &&future)
Thread< RT > new_thread(const std::function< RT()> &function)
static void thread_entry_point(const std::function< RT()> &function, std::shared_ptr< return_value< RT >> ret_val)
Mutex thread_is_active_mutex
static unsigned int n_threads()
void handle_std_exception(const std::exception &exc)
internal::return_value< RT > returned_object
void handle_unknown_exception()
std::vector< std::pair< ForwardIterator, ForwardIterator > > split_range(const ForwardIterator &begin, const ForwardIterator &end, const unsigned int n_intervals)
std::list< Thread< RT > > threads
static ::ExceptionBase & ExcInternalError()