16 #ifndef dealii_thread_management_h 17 # define dealii_thread_management_h 20 # include <deal.II/base/config.h> 22 # include <deal.II/base/exceptions.h> 23 # include <deal.II/base/multithread_info.h> 24 # include <deal.II/base/template_constraints.h> 26 # include <condition_variable> 27 # include <functional> 35 DEAL_II_DISABLE_EXTRA_DIAGNOSTICS
36 # ifdef DEAL_II_WITH_THREADS 38 # ifdef DEAL_II_USE_MT_POSIX 41 # include <tbb/task.h> 42 # include <tbb/tbb_stddef.h> 44 DEAL_II_ENABLE_EXTRA_DIAGNOSTICS
48 DEAL_II_NAMESPACE_OPEN
111 using ScopedLock DEAL_II_DEPRECATED = std::lock_guard<std::mutex>;
184 condition_variable.notify_one();
194 condition_variable.notify_all();
209 std::unique_lock<std::mutex> lock(mutex, std::adopt_lock);
210 condition_variable.wait(lock);
220 # ifdef DEAL_II_USE_MT_POSIX 246 const char * name =
nullptr,
247 void * arg =
nullptr);
268 # ifndef DEAL_II_USE_MT_POSIX_NO_BARRIERS 363 template <
typename ForwardIterator>
364 std::vector<std::pair<ForwardIterator, ForwardIterator>>
366 const ForwardIterator &end,
367 const unsigned int n_intervals);
377 std::vector<std::pair<unsigned int, unsigned int>>
379 const unsigned int end,
380 const unsigned int n_intervals);
411 handle_std_exception(
const std::exception &exc);
421 handle_unknown_exception();
454 template <
typename ForwardIterator>
455 std::vector<std::pair<ForwardIterator, ForwardIterator>>
457 const ForwardIterator &end,
458 const unsigned int n_intervals)
460 using IteratorPair = std::pair<ForwardIterator, ForwardIterator>;
466 if (n_intervals == 1)
467 return (std::vector<IteratorPair>(1, IteratorPair(begin, end)));
470 const unsigned int n_elements = std::distance(begin, end);
471 const unsigned int n_elements_per_interval = n_elements / n_intervals;
472 const unsigned int residual = n_elements % n_intervals;
474 std::vector<IteratorPair> return_values(n_intervals);
476 return_values[0].first = begin;
477 for (
unsigned int i = 0; i < n_intervals; ++i)
479 if (i != n_intervals - 1)
481 return_values[i].second = return_values[i].first;
486 std::advance(return_values[i].second,
487 static_cast<signed int>(n_elements_per_interval));
491 ++return_values[i].second;
493 return_values[i + 1].first = return_values[i].second;
496 return_values[i].second = end;
498 return return_values;
516 template <
typename RT>
523 using reference_type = RT &;
525 inline return_value()
529 inline reference_type
538 value = std::move(v);
552 template <
typename RT>
553 struct return_value<RT &>
559 using reference_type = RT &;
561 inline return_value()
565 inline reference_type
588 struct return_value<void>
590 using reference_type = void;
602 template <
typename RT>
604 call(
const std::function<RT()> &
function,
605 internal::return_value<RT> &ret_val)
607 ret_val.set(
function());
612 call(
const std::function<
void()> &
function, internal::return_value<void> &)
622 # ifdef DEAL_II_WITH_THREADS 634 template <
typename RT>
710 start(
const std::function<RT()> &
function)
713 ret_val = std::make_shared<return_value<RT>>();
745 std::shared_ptr<return_value<RT>>
ret_val)
752 internal::register_thread();
757 catch (
const std::exception &exc)
759 internal::handle_std_exception(exc);
763 internal::handle_unknown_exception();
765 internal::deregister_thread();
778 template <
typename RT>
779 struct ThreadDescriptor
785 std::shared_ptr<return_value<RT>>
ret_val;
792 start(
const std::function<RT()> &
function)
794 ret_val = std::make_shared<return_value<RT>>();
832 template <
typename RT =
void>
839 Thread(
const std::function<RT()> &
function)
915 typename internal::return_value<RT>::reference_type
963 template <
typename T>
982 template <
typename T>
985 static std::reference_wrapper<T>
1005 template <
typename RT>
1078 template <
typename FunctionObjectType>
1083 using return_type = decltype(function_object());
1095 template <
typename RT,
typename... Args>
1097 new_thread(RT (*fun_ptr)(Args...),
typename identity<Args>::type... args)
1110 template <
typename RT,
typename C,
typename... Args>
1113 typename identity<C>::type &c,
1114 typename identity<Args>::type... args)
1116 return new_thread(std::function<RT()>(std::bind(
1120 # ifndef DEAL_II_CONST_MEMBER_DEDUCTION_BUG 1126 template <
typename RT,
typename C,
typename... Args>
1129 typename identity<const C>::type &c,
1130 typename identity<Args>::type... args)
1132 return new_thread(std::function<RT()>(std::bind(
1147 template <
typename RT =
void>
1190 # ifdef DEAL_II_WITH_THREADS 1193 struct TaskDescriptor;
1198 template <
typename RT>
1214 catch (
const std::exception &exc)
1216 internal::handle_std_exception(exc);
1220 internal::handle_unknown_exception();
1252 template <
typename RT>
1253 struct TaskDescriptor
1259 std::function<RT()>
function;
1274 return_value<RT> ret_val;
1285 TaskDescriptor(
const std::function<RT()> &
function);
1298 TaskDescriptor(
const TaskDescriptor &);
1310 operator=(
const TaskDescriptor &);
1332 friend class ::Threads::Task<RT>;
1337 template <
typename RT>
1338 inline TaskDescriptor<RT>::TaskDescriptor(
1339 const std::function<RT()> &
function)
1340 : function(function)
1342 , task_is_done(false)
1346 template <
typename RT>
1348 TaskDescriptor<RT>::queue_task()
1352 task =
new (tbb::task::allocate_root()) tbb::empty_task;
1353 task->set_ref_count(2);
1356 new (task->allocate_child()) TaskEntryPoint<RT>(*
this);
1358 tbb::task::spawn(*worker);
1363 template <
typename RT>
1364 TaskDescriptor<RT>::TaskDescriptor()
1365 : task_is_done(false)
1372 template <
typename RT>
1373 TaskDescriptor<RT>::TaskDescriptor(
const TaskDescriptor &)
1374 : task_is_done(false)
1383 template <
typename RT>
1384 inline TaskDescriptor<RT>::~TaskDescriptor()
1401 task->destroy(*task);
1405 template <
typename RT>
1406 TaskDescriptor<RT> &
1407 TaskDescriptor<RT>::operator=(
const TaskDescriptor &)
1416 template <
typename RT>
1418 TaskDescriptor<RT>::join()
1429 if (task_is_done ==
true)
1433 task_is_done =
true;
1434 task->wait_for_all();
1439 # else // no threading enabled 1445 template <
typename RT>
1446 struct TaskDescriptor
1451 return_value<RT> ret_val;
1457 TaskDescriptor(
const std::function<RT()> &
function)
1459 call(
function, ret_val);
1495 template <
typename RT =
void>
1506 Task(
const std::function<RT()> &function_object)
1511 std::make_shared<internal::TaskDescriptor<RT>>(function_object);
1563 std::shared_ptr<internal::TaskDescriptor<RT>>());
1610 typename internal::return_value<RT>::reference_type
1639 "The current object is not associated with a task that " 1640 "can be joined. It may have been detached, or you " 1641 "may have already joined it in the past.");
1661 template <
typename RT>
1734 template <
typename FunctionObjectType>
1739 using return_type = decltype(function_object());
1752 template <
typename RT,
typename... Args>
1754 new_task(RT (*fun_ptr)(Args...),
typename identity<Args>::type... args)
1756 return new_task(std::function<RT()>(
1767 template <
typename RT,
typename C,
typename... Args>
1770 typename identity<C>::type &c,
1771 typename identity<Args>::type... args)
1773 return new_task(std::function<RT()>(std::bind(
1777 # ifndef DEAL_II_CONST_MEMBER_DEDUCTION_BUG 1783 template <
typename RT,
typename C,
typename... Args>
1786 typename identity<const C>::type &c,
1787 typename identity<Args>::type... args)
1789 return new_task(std::function<RT()>(std::bind(
1810 template <
typename RT =
void>
1833 for (
typename std::list<
Task<RT>>::const_iterator t =
tasks.begin();
1854 DEAL_II_NAMESPACE_CLOSE
std::shared_ptr< internal::ThreadDescriptor< RT > > thread_descriptor
#define AssertNothrow(cond, exc)
unsigned int this_thread_id()
Task< RT > new_task(const std::function< RT()> &function)
Thread(const Thread< RT > &t)
TaskDescriptor< RT > & task_descriptor
std::list< Task< RT > > tasks
internal::return_value< RT >::reference_type return_value()
std::shared_ptr< return_value< RT > > ret_val
#define AssertThrow(cond, exc)
bool operator==(const Task &t) const
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 &)
static ::ExceptionBase & ExcNoTask()
std::condition_variable condition_variable
#define Assert(cond, exc)
static void initialize_multithreading()
std::shared_ptr< internal::TaskDescriptor< RT > > task_descriptor
#define DeclExceptionMsg(Exception, defaulttext)
unsigned int n_existing_threads()
Thread(const std::function< RT()> &function)
std::lock_guard< std::mutex > ScopedLock
internal::return_value< RT >::reference_type return_value()
bool operator==(const Thread &t) const
TaskGroup & operator+=(const Task< RT > &t)
void start(const std::function< RT()> &function)
ThreadGroup & operator+=(const Thread< RT > &t)
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
pthread_barrier_t barrier
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()