16 #ifndef dealii_thread_management_h 17 #define dealii_thread_management_h 20 #include <deal.II/base/config.h> 21 #include <deal.II/base/exceptions.h> 22 #include <deal.II/base/template_constraints.h> 23 #include <deal.II/base/multithread_info.h> 25 #ifdef DEAL_II_WITH_THREADS 28 # include <condition_variable> 40 #ifdef DEAL_II_WITH_THREADS 41 # ifdef DEAL_II_USE_MT_POSIX 44 # include <tbb/task.h> 45 # include <tbb/tbb_stddef.h> 50 DEAL_II_NAMESPACE_OPEN
197 const char *name =
nullptr,
198 void *arg =
nullptr);
224 <<
"In single-thread mode, barrier sizes other than 1 are not " 225 <<
"useful. You gave " << arg1 <<
".");
231 #ifdef DEAL_II_WITH_THREADS 386 std::unique_lock<std::mutex> lock(mutex.
mutex, std::adopt_lock);
420 const char *name =
nullptr,
421 void *arg =
nullptr);
441 #ifndef DEAL_II_USE_MT_POSIX_NO_BARRIERS 542 template <
typename ForwardIterator>
543 std::vector<std::pair<ForwardIterator,ForwardIterator> >
545 const ForwardIterator &end,
546 const unsigned int n_intervals);
556 std::vector<std::pair<unsigned int,unsigned int> >
558 const unsigned int end,
559 const unsigned int n_intervals);
590 void handle_std_exception (
const std::exception &exc);
600 void handle_unknown_exception ();
609 void register_thread ();
618 void deregister_thread ();
631 template <
typename ForwardIterator>
632 std::vector<std::pair<ForwardIterator,ForwardIterator> >
634 const ForwardIterator &end,
635 const unsigned int n_intervals)
637 typedef std::pair<ForwardIterator,ForwardIterator> IteratorPair;
644 return (std::vector<IteratorPair>
645 (1, IteratorPair(begin, end)));
648 const unsigned int n_elements = std::distance (begin, end);
649 const unsigned int n_elements_per_interval = n_elements / n_intervals;
650 const unsigned int residual = n_elements % n_intervals;
652 std::vector<IteratorPair> return_values (n_intervals);
654 return_values[0].first = begin;
655 for (
unsigned int i=0; i<n_intervals; ++i)
657 if (i != n_intervals-1)
659 return_values[i].second = return_values[i].first;
664 std::advance (return_values[i].second,
665 static_cast<signed int>(n_elements_per_interval));
669 ++return_values[i].second;
671 return_values[i+1].first = return_values[i].second;
674 return_values[i].second = end;
676 return return_values;
694 template <
typename RT>
struct return_value
699 typedef RT &reference_type;
701 inline return_value () : value() {}
703 inline reference_type
get ()
708 inline void set (RT &&v)
710 value = std::move(v);
724 template <
typename RT>
struct return_value<RT &>
729 typedef RT &reference_type;
731 inline return_value ()
735 inline reference_type
get ()
const 740 inline void set (RT &v)
755 template <>
struct return_value<void>
757 typedef void reference_type;
759 static inline void get () {}
767 template <
typename RT>
768 inline void call (
const std::function<RT ()> &
function,
769 internal::return_value<RT> &ret_val)
771 ret_val.set (
function());
775 inline void call (
const std::function<
void ()> &
function,
776 internal::return_value<void> &)
786 #ifdef DEAL_II_WITH_THREADS 798 template <
typename RT>
874 void start (
const std::function<RT ()> &
function)
877 ret_val = std::make_shared<return_value<RT>>();
909 std::shared_ptr<return_value<RT> >
ret_val)
916 internal::register_thread ();
921 catch (
const std::exception &exc)
923 internal::handle_std_exception (exc);
927 internal::handle_unknown_exception ();
929 internal::deregister_thread ();
942 template <
typename RT>
943 struct ThreadDescriptor
949 std::shared_ptr<return_value<RT> >
ret_val;
955 void start (
const std::function<RT ()> &
function)
957 ret_val = std::make_shared<return_value<RT>>();
994 template <
typename RT =
void>
1001 Thread (
const std::function<RT ()> &
function)
1074 typename internal::return_value<RT>::reference_type
1120 template <
typename T>
1138 template <
typename T>
1141 static std::reference_wrapper<T> act (T &t)
1160 template <
typename RT>
1233 template <
typename FunctionObjectType>
1239 typedef decltype(function_object()) return_type;
1251 template <
typename RT,
typename... Args>
1255 typename identity<Args>::type... args)
1270 template <
typename RT,
typename C,
typename... Args>
1274 typename identity<C>::type &c,
1275 typename identity<Args>::type... args)
1279 (std::bind(fun_ptr, std::ref(c),
1283 #ifndef DEAL_II_CONST_MEMBER_DEDUCTION_BUG 1289 template <
typename RT,
typename C,
typename... Args>
1293 typename identity<const C>::type &c,
1294 typename identity<Args>::type... args)
1298 (std::bind(fun_ptr, std::cref(c),
1313 template <
typename RT =
void>
1334 for (
typename std::list<
Thread<RT> >::const_iterator
1352 #ifdef DEAL_II_WITH_THREADS 1354 template <
typename>
struct TaskDescriptor;
1359 template <
typename RT>
1367 virtual tbb::task *execute ()
1375 catch (
const std::exception &exc)
1377 internal::handle_std_exception (exc);
1381 internal::handle_unknown_exception ();
1413 template <
typename RT>
1414 struct TaskDescriptor
1420 std::function<RT ()>
function;
1435 return_value<RT> ret_val;
1447 TaskDescriptor (
const std::function<RT ()> &
function);
1460 TaskDescriptor (
const TaskDescriptor &);
1472 operator = (
const TaskDescriptor &);
1491 friend class ::Threads::Task<RT>;
1496 template <
typename RT>
1498 TaskDescriptor<RT>::TaskDescriptor (
const std::function<RT ()> &
function)
1500 function (function),
1502 task_is_done (false)
1506 template <
typename RT>
1509 TaskDescriptor<RT>::queue_task ()
1513 task =
new (tbb::task::allocate_root()) tbb::empty_task;
1514 task->set_ref_count (2);
1516 tbb::task *worker =
new (task->allocate_child()) TaskEntryPoint<RT>(*
this);
1523 #if TBB_VERSION_MAJOR >= 4 1524 tbb::task::spawn (*worker);
1526 task->spawn (*worker);
1532 template <
typename RT>
1533 TaskDescriptor<RT>::TaskDescriptor ()
1535 task_is_done (false)
1542 template <
typename RT>
1543 TaskDescriptor<RT>::TaskDescriptor (
const TaskDescriptor &)
1545 task_is_done (false)
1554 template <
typename RT>
1556 TaskDescriptor<RT>::~TaskDescriptor ()
1573 task->destroy (*task);
1577 template <
typename RT>
1578 TaskDescriptor<RT> &
1579 TaskDescriptor<RT>::operator = (
const TaskDescriptor &)
1588 template <
typename RT>
1591 TaskDescriptor<RT>::join ()
1602 if (task_is_done ==
true)
1606 task_is_done =
true;
1607 task->wait_for_all();
1612 #else // no threading enabled 1618 template <
typename RT>
1619 struct TaskDescriptor
1624 return_value<RT> ret_val;
1630 TaskDescriptor (
const std::function<RT ()> &
function)
1632 call (
function, ret_val);
1639 static void join () {}
1645 static void queue_task () {}
1664 template <
typename RT =
void>
1675 Task (
const std::function<RT ()> &function_object)
1679 task_descriptor = std::make_shared<internal::TaskDescriptor<RT>>(function_object);
1738 std::shared_ptr<internal::TaskDescriptor<RT> >());
1785 typename internal::return_value<RT>::reference_type
1813 "The current object is not associated with a task that " 1814 "can be joined. It may have been detached, or you " 1815 "may have already joined it in the past.");
1835 template <
typename RT>
1908 template <
typename FunctionObjectType>
1914 typedef decltype(function_object()) return_type;
1927 template <
typename RT,
typename... Args>
1931 typename identity<Args>::type... args)
1946 template <
typename RT,
typename C,
typename... Args>
1950 typename identity<C>::type &c,
1951 typename identity<Args>::type... args)
1955 (std::bind(fun_ptr, std::ref(c),
1959 #ifndef DEAL_II_CONST_MEMBER_DEDUCTION_BUG 1965 template <
typename RT,
typename C,
typename... Args>
1969 typename identity<const C>::type &c,
1970 typename identity<Args>::type... args)
1974 (std::bind(fun_ptr, std::cref(c),
1995 template <
typename RT =
void>
2004 tasks.push_back (t);
2016 for (
typename std::list<
Task<RT> >::const_iterator
2036 DEAL_II_NAMESPACE_CLOSE
std::shared_ptr< internal::ThreadDescriptor< RT > > thread_descriptor
#define AssertNothrow(cond, exc)
std::vector< std::pair< ForwardIterator, ForwardIterator > > split_range(const ForwardIterator &begin, const ForwardIterator &end, const unsigned int n_intervals)
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()
ScopedLock(DummyThreadMutex &)
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 &)
DummyBarrier(const unsigned int count, const char *name=nullptr, void *arg=nullptr)
static ::ExceptionBase & ExcNoTask()
#define DeclException1(Exception1, type1, outsequence)
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()
static void thread_entry_point(const std::function< RT()> &function, std::shared_ptr< return_value< RT > > ret_val)
Thread(const std::function< RT()> &function)
void wait(DummyThreadMutex &) const
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)
PosixThreadBarrier Barrier
Task(const Task< RT > &t)
Thread< RT > new_thread(const std::function< RT()> &function)
Mutex thread_is_active_mutex
PosixThreadBarrier(const unsigned int count, const char *name=nullptr, void *arg=nullptr)
pthread_barrier_t barrier
std::list< Thread< RT > > threads
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcBarrierSizeNotUseful(int arg1)