From: bangerth Date: Fri, 10 Oct 2008 23:55:13 +0000 (+0000) Subject: Completely rewrite passing back and forth function descriptors from the Threads:... X-Git-Url: https://gitweb.dealii.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a994b4cb4ef515c02b6d5ad9d2df0fe9d4a5b38d;p=dealii-svn.git Completely rewrite passing back and forth function descriptors from the Threads::spawn functions to the place where threads are created and then where the function is called on the new thread. Previously, this was done using function pointers and boost::tuple for argument lists. Now, we use the boost::bind and boost::function libraries that encapsulate all these things nicely. The end result is a reducting in the size of base/include/base/thread_management.h of 4,050 lines, finally making the file readable again. git-svn-id: https://svn.dealii.org/trunk@17179 0785d39b-7218-0410-832d-ea1e28bc413d --- diff --git a/deal.II/base/include/base/thread_management.h b/deal.II/base/include/base/thread_management.h index 7c85191db4..861ae9fd54 100644 --- a/deal.II/base/include/base/thread_management.h +++ b/deal.II/base/include/base/thread_management.h @@ -25,6 +25,8 @@ #include #include #include +#include +#include #if DEAL_II_USE_MT == 1 # if defined(DEAL_II_USE_MT_POSIX) @@ -247,8 +249,8 @@ namespace Threads */ void dump () {} - /** @addtogroup Exceptions - * @{ */ + /** @addtogroup Exceptions + * @{ */ /** * Exception. @@ -848,20 +850,6 @@ namespace Threads namespace Threads { - namespace internal - { - /** - * @internal - * A type that is used to - * distinguish argument lists of - * functions by enumeration. - */ - template struct int2type - { - }; - } - - namespace internal { /** @@ -923,7 +911,8 @@ namespace Threads * a function get() that returns * void. */ - template <> struct return_value { + template <> struct return_value + { static inline void get () {} }; } @@ -932,4117 +921,725 @@ namespace Threads namespace internal { - /** - * @internal - * Call arbitrary functions with - * return type RT. For each number - * of arguments to these functions, - * there is an instance of the - * do_call function in this class - * that unpacks the argument list - * (which is passed by reference) - * and calls the function. The - * number of arguments is - * distinguished by the last - * argument. The return value - * object is the second last. A - * second version of the do_call - * function is used to call member - * function pointers, in which case - * there is an additional argument - * at second position holding a - * reference to the object with - * which the member function - * pointer is to be called. - * - * There is a specialization of - * this class for the case that the - * return type is void, in which - * case there is no return value to - * be set. - */ template - struct Caller + inline void call (boost::function &function, + internal::return_value &ret_val) { - /** - * Call a function with 0 - * arguments, and set the - * return value. - */ - template - static inline void do_call (PFun fun_ptr, - ArgList &, - internal::return_value &ret_val, - const int2type<0> &) - { - ret_val.set ((*fun_ptr) ()); - } - - /** - * Call a member function with - * 0 arguments, and set the - * return value. - */ - template - static inline void do_call (PFun fun_ptr, - C &obj, - ArgList &, - internal::return_value &ret_val, - const int2type<0> &) - { - ret_val.set ((obj.*fun_ptr) ()); - } - - - /** - * Call a function with 1 - * argument, and set the - * return value. - */ - template - static inline void do_call (PFun fun_ptr, - ArgList &arg_list, - internal::return_value &ret_val, - const int2type<1> &) - { - ret_val.set ((*fun_ptr) (arg_list.template get<0>())); - } - - /** - * Call a member function with - * 1 argument, and set the - * return value. - */ - template - static inline void do_call (PFun fun_ptr, - C &obj, - ArgList &arg_list, - internal::return_value &ret_val, - const int2type<1> &) - { - ret_val.set ((obj.*fun_ptr) (arg_list.template get<0>())); - } - - - - - /** - * Call a function with 2 - * arguments, and set the - * return value. - */ - template - static inline void do_call (PFun fun_ptr, - ArgList &arg_list, - internal::return_value &ret_val, - const int2type<2> &) - { - ret_val.set ((*fun_ptr) (arg_list.template get<0>(), - arg_list.template get<1>())); - } - - /** - * Call a member function with - * 2 arguments, and set the - * return value. - */ - template - static inline void do_call (PFun fun_ptr, - C &obj, - ArgList &arg_list, - internal::return_value &ret_val, - const int2type<2> &) - { - ret_val.set ((obj.*fun_ptr) (arg_list.template get<0>(), - arg_list.template get<1>())); - } - - - /** - * Call a function with 3 - * arguments, and set the - * return value. - */ - template - static inline void do_call (PFun fun_ptr, - ArgList &arg_list, - internal::return_value &ret_val, - const int2type<3> &) - { - ret_val.set ((*fun_ptr) (arg_list.template get<0>(), - arg_list.template get<1>(), - arg_list.template get<2>())); - } + ret_val.set (function()); + } - /** - * Call a member function with - * 3 arguments, and set the - * return value. - */ - template - static inline void do_call (PFun fun_ptr, - C &obj, - ArgList &arg_list, - internal::return_value &ret_val, - const int2type<3> &) - { - ret_val.set ((obj.*fun_ptr) (arg_list.template get<0>(), - arg_list.template get<1>(), - arg_list.template get<2>())); - } + inline void call (boost::function &function, + internal::return_value &) + { + function(); + } + } - /** - * Call a function with 4 - * arguments, and set the - * return value. - */ - template - static inline void do_call (PFun fun_ptr, - ArgList &arg_list, - internal::return_value &ret_val, - const int2type<4> &) - { - ret_val.set ((*fun_ptr) (arg_list.template get<0>(), - arg_list.template get<1>(), - arg_list.template get<2>(), - arg_list.template get<3>())); - } - /** - * Call a member function with - * 4 arguments, and set the - * return value. - */ - template - static inline void do_call (PFun fun_ptr, - C &obj, - ArgList &arg_list, - internal::return_value &ret_val, - const int2type<4> &) - { - ret_val.set ((obj.*fun_ptr) (arg_list.template get<0>(), - arg_list.template get<1>(), - arg_list.template get<2>(), - arg_list.template get<3>())); - } + namespace internal + { + /** + * @internal + * Construct a pointer to non-member + * function based on the template + * arguments, and whether the + * second argument is a const or + * non-const class, dependening on + * which the member function will + * also me const or + * non-const. There are + * specializations of this class + * for each number of arguments. + */ + template ::value> + struct fun_ptr_helper; + - /** - * Call a function with 5 - * arguments, and set the - * return value. - */ - template - static inline void do_call (PFun fun_ptr, - ArgList &arg_list, - internal::return_value &ret_val, - const int2type<5> &) - { - ret_val.set ((*fun_ptr) (arg_list.template get<0>(), - arg_list.template get<1>(), - arg_list.template get<2>(), - arg_list.template get<3>(), - arg_list.template get<4>())); - } + /** + * @internal + * Construct a pointer to non-member + * function based on the template + * arguments. This is the + * specialization for 0 arguments. + */ + template + struct fun_ptr_helper + { + typedef RT (type) (); + }; - /** - * Call a member function with - * 5 arguments, and set the - * return value. - */ - template - static inline void do_call (PFun fun_ptr, - C &obj, - ArgList &arg_list, - internal::return_value &ret_val, - const int2type<5> &) - { - ret_val.set ((obj.*fun_ptr) (arg_list.template get<0>(), - arg_list.template get<1>(), - arg_list.template get<2>(), - arg_list.template get<3>(), - arg_list.template get<4>())); - } + /** + * @internal + * Construct a pointer to non-member + * function based on the template + * arguments. This is the + * specialization for 1 argument. + */ + template + struct fun_ptr_helper + { + typedef RT (type) (typename boost::tuples::element<0,ArgList>::type); + }; - /** - * Call a function with 6 - * arguments, and set the - * return value. - */ - template - static inline void do_call (PFun fun_ptr, - ArgList &arg_list, - internal::return_value &ret_val, - const int2type<6> &) - { - ret_val.set ((*fun_ptr) (arg_list.template get<0>(), - arg_list.template get<1>(), - arg_list.template get<2>(), - arg_list.template get<3>(), - arg_list.template get<4>(), - arg_list.template get<5>())); - } - /** - * Call a member function with - * 6 arguments, and set the - * return value. - */ - template - static inline void do_call (PFun fun_ptr, - C &obj, - ArgList &arg_list, - internal::return_value &ret_val, - const int2type<6> &) - { - ret_val.set ((obj.*fun_ptr) (arg_list.template get<0>(), - arg_list.template get<1>(), - arg_list.template get<2>(), - arg_list.template get<3>(), - arg_list.template get<4>(), - arg_list.template get<5>())); - } + /** + * @internal + * Construct a pointer to non-member + * function based on the template + * arguments. This is the + * specialization for 2 arguments. + */ + template + struct fun_ptr_helper + { + typedef RT (type) (typename boost::tuples::element<0,ArgList>::type, + typename boost::tuples::element<1,ArgList>::type); + }; - /** - * Call a function with 7 - * arguments, and set the - * return value. - */ - template - static inline void do_call (PFun fun_ptr, - ArgList &arg_list, - internal::return_value &ret_val, - const int2type<7> &) - { - ret_val.set ((*fun_ptr) (arg_list.template get<0>(), - arg_list.template get<1>(), - arg_list.template get<2>(), - arg_list.template get<3>(), - arg_list.template get<4>(), - arg_list.template get<5>(), - arg_list.template get<6>())); - } + /** + * @internal + * Construct a pointer to non-member + * function based on the template + * arguments. This is the + * specialization for 3 arguments. + */ + template + struct fun_ptr_helper + { + typedef RT (type) (typename boost::tuples::element<0,ArgList>::type, + typename boost::tuples::element<1,ArgList>::type, + typename boost::tuples::element<2,ArgList>::type); + }; - /** - * Call a member function with - * 7 arguments, and set the - * return value. - */ - template - static inline void do_call (PFun fun_ptr, - C &obj, - ArgList &arg_list, - internal::return_value &ret_val, - const int2type<7> &) - { - ret_val.set ((obj.*fun_ptr) (arg_list.template get<0>(), - arg_list.template get<1>(), - arg_list.template get<2>(), - arg_list.template get<3>(), - arg_list.template get<4>(), - arg_list.template get<5>(), - arg_list.template get<6>())); - } + /** + * @internal + * Construct a pointer to non-member + * function based on the template + * arguments. This is the + * specialization for 4 arguments. + */ + template + struct fun_ptr_helper + { + typedef RT (type) (typename boost::tuples::element<0,ArgList>::type, + typename boost::tuples::element<1,ArgList>::type, + typename boost::tuples::element<2,ArgList>::type, + typename boost::tuples::element<3,ArgList>::type); + }; - /** - * Call a function with 8 - * arguments, and set the - * return value. - */ - template - static inline void do_call (PFun fun_ptr, - ArgList &arg_list, - internal::return_value &ret_val, - const int2type<8> &) - { - ret_val.set ((*fun_ptr) (arg_list.template get<0>(), - arg_list.template get<1>(), - arg_list.template get<2>(), - arg_list.template get<3>(), - arg_list.template get<4>(), - arg_list.template get<5>(), - arg_list.template get<6>(), - arg_list.template get<7>())); - } - /** - * Call a member function with - * 8 arguments, and set the - * return value. - */ - template - static inline void do_call (PFun fun_ptr, - C &obj, - ArgList &arg_list, - internal::return_value &ret_val, - const int2type<8> &) - { - ret_val.set ((obj.*fun_ptr) (arg_list.template get<0>(), - arg_list.template get<1>(), - arg_list.template get<2>(), - arg_list.template get<3>(), - arg_list.template get<4>(), - arg_list.template get<5>(), - arg_list.template get<6>(), - arg_list.template get<7>())); - } + /** + * @internal + * Construct a pointer to non-member + * function based on the template + * arguments. This is the + * specialization for 5 arguments. + */ + template + struct fun_ptr_helper + { + typedef RT (type) (typename boost::tuples::element<0,ArgList>::type, + typename boost::tuples::element<1,ArgList>::type, + typename boost::tuples::element<2,ArgList>::type, + typename boost::tuples::element<3,ArgList>::type, + typename boost::tuples::element<4,ArgList>::type); + }; - /** - * Call a function with 9 - * arguments, and set the - * return value. - */ - template - static inline void do_call (PFun fun_ptr, - ArgList &arg_list, - internal::return_value &ret_val, - const int2type<9> &) - { - ret_val.set ((*fun_ptr) (arg_list.template get<0>(), - arg_list.template get<1>(), - arg_list.template get<2>(), - arg_list.template get<3>(), - arg_list.template get<4>(), - arg_list.template get<5>(), - arg_list.template get<6>(), - arg_list.template get<7>(), - arg_list.template get<8>())); - } + /** + * @internal + * Construct a pointer to non-member + * function based on the template + * arguments. This is the + * specialization for 6 arguments. + */ + template + struct fun_ptr_helper + { + typedef RT (type) (typename boost::tuples::element<0,ArgList>::type, + typename boost::tuples::element<1,ArgList>::type, + typename boost::tuples::element<2,ArgList>::type, + typename boost::tuples::element<3,ArgList>::type, + typename boost::tuples::element<4,ArgList>::type, + typename boost::tuples::element<5,ArgList>::type); + }; - /** - * Call a member function with - * 9 arguments, and set the - * return value. - */ - template - static inline void do_call (PFun fun_ptr, - C &obj, - ArgList &arg_list, - internal::return_value &ret_val, - const int2type<9> &) - { - ret_val.set ((obj.*fun_ptr) (arg_list.template get<0>(), - arg_list.template get<1>(), - arg_list.template get<2>(), - arg_list.template get<3>(), - arg_list.template get<4>(), - arg_list.template get<5>(), - arg_list.template get<6>(), - arg_list.template get<7>(), - arg_list.template get<8>())); - } + /** + * @internal + * Construct a pointer to non-member + * function based on the template + * arguments. This is the + * specialization for 7 arguments. + */ + template + struct fun_ptr_helper + { + typedef RT (type) (typename boost::tuples::element<0,ArgList>::type, + typename boost::tuples::element<1,ArgList>::type, + typename boost::tuples::element<2,ArgList>::type, + typename boost::tuples::element<3,ArgList>::type, + typename boost::tuples::element<4,ArgList>::type, + typename boost::tuples::element<5,ArgList>::type, + typename boost::tuples::element<6,ArgList>::type); + }; - /** - * Call a function with 10 - * arguments, and set the - * return value. - */ - template - static inline void do_call (PFun fun_ptr, - ArgList &arg_list, - internal::return_value &ret_val, - const int2type<10> &) - { - ret_val.set ((*fun_ptr) (arg_list.template get<0>(), - arg_list.template get<1>(), - arg_list.template get<2>(), - arg_list.template get<3>(), - arg_list.template get<4>(), - arg_list.template get<5>(), - arg_list.template get<6>(), - arg_list.template get<7>(), - arg_list.template get<8>(), - arg_list.template get<9>())); - } - /** - * Call a member function with - * 10 arguments, and set the - * return value. - */ - template - static inline void do_call (PFun fun_ptr, - C &obj, - ArgList &arg_list, - internal::return_value &ret_val, - const int2type<10> &) - { - ret_val.set ((obj.*fun_ptr) (arg_list.template get<0>(), - arg_list.template get<1>(), - arg_list.template get<2>(), - arg_list.template get<3>(), - arg_list.template get<4>(), - arg_list.template get<5>(), - arg_list.template get<6>(), - arg_list.template get<7>(), - arg_list.template get<8>(), - arg_list.template get<9>())); - } + /** + * @internal + * Construct a pointer to non-member + * function based on the template + * arguments. This is the + * specialization for 8 arguments. + */ + template + struct fun_ptr_helper + { + typedef RT (type) (typename boost::tuples::element<0,ArgList>::type, + typename boost::tuples::element<1,ArgList>::type, + typename boost::tuples::element<2,ArgList>::type, + typename boost::tuples::element<3,ArgList>::type, + typename boost::tuples::element<4,ArgList>::type, + typename boost::tuples::element<5,ArgList>::type, + typename boost::tuples::element<6,ArgList>::type, + typename boost::tuples::element<7,ArgList>::type); }; - - /** * @internal - * Call arbitrary functions with - * void return type. For each - * number of arguments to these - * functions, there is an instance - * of the do_call function in this - * class that unpacks the argument - * list (which is passed by - * reference) and calls the - * function. The number of - * arguments is distinguished by - * the last argument. The return - * value object is the second last, - * but since the return type is - * void, this is of course simply - * ignored. A second version of the - * do_call function is used to call - * member function pointers, in - * which case there is an - * additional argument at second - * position holding a reference to - * the object with which the member - * function pointer is to be - * called. + * Construct a pointer to non-member + * function based on the template + * arguments. This is the + * specialization for 9 arguments. */ - template <> - struct Caller + template + struct fun_ptr_helper { - /** - * Call a void function with 0 - * arguments. - */ - template - static inline void do_call (PFun fun_ptr, - ArgList &, - internal::return_value &, - const int2type<0> &) - { - (*fun_ptr) (); - } + typedef RT (type) (typename boost::tuples::element<0,ArgList>::type, + typename boost::tuples::element<1,ArgList>::type, + typename boost::tuples::element<2,ArgList>::type, + typename boost::tuples::element<3,ArgList>::type, + typename boost::tuples::element<4,ArgList>::type, + typename boost::tuples::element<5,ArgList>::type, + typename boost::tuples::element<6,ArgList>::type, + typename boost::tuples::element<7,ArgList>::type, + typename boost::tuples::element<8,ArgList>::type); + }; - /** - * Call a void member function - * with 0 arguments. - */ - template - static inline void do_call (PFun fun_ptr, - C &obj, - ArgList &, - internal::return_value &, - const int2type<0> &) - { - (obj.*fun_ptr) (); - } - /** - * Call a void function with 1 - * argument. - */ - template - static inline void do_call (PFun fun_ptr, - ArgList &arg_list, - internal::return_value &, - const int2type<1> &) - { - (*fun_ptr) (arg_list.template get<0>()); - } - - /** - * Call a void member function - * with 1 argument. - */ - template - static inline void do_call (PFun fun_ptr, - C &obj, - ArgList &arg_list, - internal::return_value &, - const int2type<1> &) - { - (obj.*fun_ptr) (arg_list.template get<0>()); - } - - - - - /** - * Call a void function with 2 - * arguments. - */ - template - static inline void do_call (PFun fun_ptr, - ArgList &arg_list, - internal::return_value &, - const int2type<2> &) - { - (*fun_ptr) (arg_list.template get<0>(), - arg_list.template get<1>()); - } - - /** - * Call a void member function - * with 2 arguments. - */ - template - static inline void do_call (PFun fun_ptr, - C &obj, - ArgList &arg_list, - internal::return_value &, - const int2type<2> &) - { - (obj.*fun_ptr) (arg_list.template get<0>(), - arg_list.template get<1>()); - } - - - /** - * Call a void function with 3 - * arguments. - */ - template - static inline void do_call (PFun fun_ptr, - ArgList &arg_list, - internal::return_value &, - const int2type<3> &) - { - (*fun_ptr) (arg_list.template get<0>(), - arg_list.template get<1>(), - arg_list.template get<2>()); - } - - /** - * Call a void member function - * with 3 arguments. - */ - template - static inline void do_call (PFun fun_ptr, - C &obj, - ArgList &arg_list, - internal::return_value &, - const int2type<3> &) - { - (obj.*fun_ptr) (arg_list.template get<0>(), - arg_list.template get<1>(), - arg_list.template get<2>()); - } - - - /** - * Call a void function with 4 - * arguments. - */ - template - static inline void do_call (PFun fun_ptr, - ArgList &arg_list, - internal::return_value &, - const int2type<4> &) - { - (*fun_ptr) (arg_list.template get<0>(), - arg_list.template get<1>(), - arg_list.template get<2>(), - arg_list.template get<3>()); - } - - /** - * Call a void member function - * with 4 arguments. - */ - template - static inline void do_call (PFun fun_ptr, - C &obj, - ArgList &arg_list, - internal::return_value &, - const int2type<4> &) - { - (obj.*fun_ptr) (arg_list.template get<0>(), - arg_list.template get<1>(), - arg_list.template get<2>(), - arg_list.template get<3>()); - } + /** + * @internal + * Construct a pointer to non-member + * function based on the template + * arguments. This is the + * specialization for 10 arguments. + */ + template + struct fun_ptr_helper + { + typedef RT (type) (typename boost::tuples::element<0,ArgList>::type, + typename boost::tuples::element<1,ArgList>::type, + typename boost::tuples::element<2,ArgList>::type, + typename boost::tuples::element<3,ArgList>::type, + typename boost::tuples::element<4,ArgList>::type, + typename boost::tuples::element<5,ArgList>::type, + typename boost::tuples::element<6,ArgList>::type, + typename boost::tuples::element<7,ArgList>::type, + typename boost::tuples::element<8,ArgList>::type, + typename boost::tuples::element<9,ArgList>::type); + }; + - /** - * Call a void function with 5 - * arguments. - */ - template - static inline void do_call (PFun fun_ptr, - ArgList &arg_list, - internal::return_value &, - const int2type<5> &) - { - (*fun_ptr) (arg_list.template get<0>(), - arg_list.template get<1>(), - arg_list.template get<2>(), - arg_list.template get<3>(), - arg_list.template get<4>()); - } + /** + * @internal + * Construct a pointer to + * non-member function based on the + * template arguments. We do this + * by dispatching to the + * fun_ptr_helper classes that are + * overloaded on the number of + * elements. + * + * Note that the last template + * argument for the + * fun_ptr_helper class is + * automatically computed in the + * default argument to the general + * template. + */ + template + struct fun_ptr + { + typedef typename fun_ptr_helper::type type; + }; + } - /** - * Call a void member function - * with 5 arguments. - */ - template - static inline void do_call (PFun fun_ptr, - C &obj, - ArgList &arg_list, - internal::return_value &, - const int2type<5> &) - { - (obj.*fun_ptr) (arg_list.template get<0>(), - arg_list.template get<1>(), - arg_list.template get<2>(), - arg_list.template get<3>(), - arg_list.template get<4>()); - } - /** - * Call a void function with 6 - * arguments. - */ - template - static inline void do_call (PFun fun_ptr, - ArgList &arg_list, - internal::return_value &, - const int2type<6> &) - { - (*fun_ptr) (arg_list.template get<0>(), - arg_list.template get<1>(), - arg_list.template get<2>(), - arg_list.template get<3>(), - arg_list.template get<4>(), - arg_list.template get<5>()); - } + namespace internal + { +#if (DEAL_II_USE_MT == 1) +# if defined(DEAL_II_USE_MT_POSIX) + /** + * @internal + * Base class describing a + * thread. This is the basic + * class abstracting the + * operating system's POSIX + * implementation into a C++ + * class. It provides a mechanism + * to start a new thread, as well + * as for joining it. + * + * @author Wolfgang Bangerth, 2003 + */ + struct thread_description_base + { + private: /** - * Call a void member function - * with 6 arguments. + * Variable holding the data + * the operating system needs + * to work with a thread. */ - template - static inline void do_call (PFun fun_ptr, - C &obj, - ArgList &arg_list, - internal::return_value &, - const int2type<6> &) - { - (obj.*fun_ptr) (arg_list.template get<0>(), - arg_list.template get<1>(), - arg_list.template get<2>(), - arg_list.template get<3>(), - arg_list.template get<4>(), - arg_list.template get<5>()); - } - + pthread_t thread; /** - * Call a void function with 7 - * arguments. + * Store whether the + * join() member function + * as already been called. If + * true, then join + * will return immediately, + * otherwise it needs to go + * through a call to the + * operating system. + * + * This class is generated + * exactly once per thread, + * but is kept in the + * background: user's should + * not directly access this + * class. Access to it is + * performed through counted + * pointers, both from + * Thread<> objects as + * well as from the thread + * entry point function on + * the new thread. It is only + * deleted when all users + * have freed it, which means + * that also the new thread + * has ended. */ - template - static inline void do_call (PFun fun_ptr, - ArgList &arg_list, - internal::return_value &, - const int2type<7> &) - { - (*fun_ptr) (arg_list.template get<0>(), - arg_list.template get<1>(), - arg_list.template get<2>(), - arg_list.template get<3>(), - arg_list.template get<4>(), - arg_list.template get<5>(), - arg_list.template get<6>()); - } + mutable volatile bool was_joined; /** - * Call a void member function - * with 7 arguments. + * Mutex used to synchronise + * calls to the join() + * function. */ - template - static inline void do_call (PFun fun_ptr, - C &obj, - ArgList &arg_list, - internal::return_value &, - const int2type<7> &) - { - (obj.*fun_ptr) (arg_list.template get<0>(), - arg_list.template get<1>(), - arg_list.template get<2>(), - arg_list.template get<3>(), - arg_list.template get<4>(), - arg_list.template get<5>(), - arg_list.template get<6>()); - } + mutable ThreadMutex join_mutex; + public: /** - * Call a void function with 8 - * arguments. + * Constructor. */ - template - static inline void do_call (PFun fun_ptr, - ArgList &arg_list, - internal::return_value &, - const int2type<8> &) - { - (*fun_ptr) (arg_list.template get<0>(), - arg_list.template get<1>(), - arg_list.template get<2>(), - arg_list.template get<3>(), - arg_list.template get<4>(), - arg_list.template get<5>(), - arg_list.template get<6>(), - arg_list.template get<7>()); - } + thread_description_base (); /** - * Call a void member function - * with 8 arguments. + * Destructor. */ - template - static inline void do_call (PFun fun_ptr, - C &obj, - ArgList &arg_list, - internal::return_value &, - const int2type<8> &) - { - (obj.*fun_ptr) (arg_list.template get<0>(), - arg_list.template get<1>(), - arg_list.template get<2>(), - arg_list.template get<3>(), - arg_list.template get<4>(), - arg_list.template get<5>(), - arg_list.template get<6>(), - arg_list.template get<7>()); - } - + virtual ~thread_description_base (); /** - * Call a void function with 9 - * arguments. + * Create a new thread with + * the given thread entry + * point and arguments. Store + * the result of the + * operation in the + * thread member variable + * for further use. */ - template - static inline void do_call (PFun fun_ptr, - ArgList &arg_list, - internal::return_value &, - const int2type<9> &) - { - (*fun_ptr) (arg_list.template get<0>(), - arg_list.template get<1>(), - arg_list.template get<2>(), - arg_list.template get<3>(), - arg_list.template get<4>(), - arg_list.template get<5>(), - arg_list.template get<6>(), - arg_list.template get<7>(), - arg_list.template get<8>()); - } + void create (void * (*p) (void *), void *d); /** - * Call a void member function - * with 9 arguments. + * Join a thread, i.e. wait + * for it to finish. This + * function can safely be + * called from different + * threads at the same time, + * and can also be called + * more than once. */ - template - static inline void do_call (PFun fun_ptr, - C &obj, - ArgList &arg_list, - internal::return_value &, - const int2type<9> &) - { - (obj.*fun_ptr) (arg_list.template get<0>(), - arg_list.template get<1>(), - arg_list.template get<2>(), - arg_list.template get<3>(), - arg_list.template get<4>(), - arg_list.template get<5>(), - arg_list.template get<6>(), - arg_list.template get<7>(), - arg_list.template get<8>()); - } + void join () const; + /** + * Exception + */ + DeclException1 (ExcThreadCreationError, + int, + << "pthread_create return code is " << arg1); + }; - /** - * Call a void function with 10 - * arguments. - */ - template - static inline void do_call (PFun fun_ptr, - ArgList &arg_list, - internal::return_value &, - const int2type<10> &) - { - (*fun_ptr) (arg_list.template get<0>(), - arg_list.template get<1>(), - arg_list.template get<2>(), - arg_list.template get<3>(), - arg_list.template get<4>(), - arg_list.template get<5>(), - arg_list.template get<6>(), - arg_list.template get<7>(), - arg_list.template get<8>(), - arg_list.template get<9>()); - } +# else // some other threading model +# error Not Implemented +# endif // defined(DEAL_II_USE_MT_POSIX) - /** - * Call a void member function - * with 10 arguments. - */ - template - static inline void do_call (PFun fun_ptr, - C &obj, - ArgList &arg_list, - internal::return_value &, - const int2type<10> &) - { - (obj.*fun_ptr) (arg_list.template get<0>(), - arg_list.template get<1>(), - arg_list.template get<2>(), - arg_list.template get<3>(), - arg_list.template get<4>(), - arg_list.template get<5>(), - arg_list.template get<6>(), - arg_list.template get<7>(), - arg_list.template get<8>(), - arg_list.template get<9>()); - } - }; - - +#else // no threading enabled - /** - * @internal - * Call an arbitrary function by - * dispatching to the functions in - * the Caller class based on the - * number of elements in the - * argument list and the return - * type. - */ - template - inline void call (PFun fun_ptr, - ArgList &arg_list, - internal::return_value &ret_val) + struct thread_description_base { - Caller::do_call (fun_ptr, arg_list, ret_val, - int2type::value>()); - } - + static void join () {} + }; + +#endif - /** * @internal - * Call an arbitrary member - * function by dispatching to the - * functions in the Caller class - * based on the number of elements - * in the argument list and the - * return type. + * Class derived from + * thread_description_base() + * that also provides the + * possibility to store a return + * value. + * + * @author Wolfgang Bangerth, 2003 */ - template - inline void call (PFun fun_ptr, - C &obj, - ArgList &arg_list, - internal::return_value &ret_val) + template + struct thread_description : public thread_description_base { - Caller::do_call (fun_ptr, obj, arg_list, ret_val, - int2type::value>()); - } + return_value ret_val; + }; + + // forward declare another class + template struct fun_wrapper; } - namespace internal + /** + * User visible class describing a + * thread. Relays all real calls to + * the internal thread object + * abstracting the operating + * system's functions, to which it + * keeps a shared pointer. This + * object can be freely copied + * around in user space. + * + * The default value of the + * template argument is void, + * so if the function you are + * calling on a new thread has no + * return value, you can omit the + * template argument. + * + * @author Wolfgang Bangerth, 2003 + */ + template + class Thread { - /** - * @internal - * Construct a pointer to member - * function based on the template - * arguments, and whether the - * second argument is a const or - * non-const class, dependening on - * which the member function will - * also me const or - * non-const. There are - * specializations of this class - * for each number of arguments, - * and the const and non-const - * versions. - */ - template ::value> - struct mem_fun_ptr_helper; - - - /** - * @internal - * Construct a pointer to member - * function based on the template - * arguments. This is the - * specialization for 0 arguments - * and non-const member functions. - */ - template - struct mem_fun_ptr_helper - { - typedef RT (C::*type) (); - }; - - /** - * @internal - * Construct a pointer to member - * function based on the template - * arguments. This is the - * specialization for 0 arguments - * and const member functions. - */ - template - struct mem_fun_ptr_helper - { - typedef RT (C::*type) () const; - }; - - - /** - * @internal - * Construct a pointer to member - * function based on the template - * arguments. This is the - * specialization for 1 argument - * and non-const member functions. - */ - template - struct mem_fun_ptr_helper - { - typedef RT (C::*type) (typename boost::tuples::element<0,ArgList>::type); - }; - - /** - * @internal - * Construct a pointer to member - * function based on the template - * arguments. This is the - * specialization for 1 argument - * and const member functions. - */ - template - struct mem_fun_ptr_helper - { - typedef RT (C::*type) (typename boost::tuples::element<0,ArgList>::type) const; - }; - - - /** - * @internal - * Construct a pointer to member - * function based on the template - * arguments. This is the - * specialization for 2 arguments - * and non-const member functions. - */ - template - struct mem_fun_ptr_helper - { - typedef RT (C::*type) (typename boost::tuples::element<0,ArgList>::type, - typename boost::tuples::element<1,ArgList>::type); - }; - - /** - * @internal - * Construct a pointer to member - * function based on the template - * arguments. This is the - * specialization for 2 arguments - * and const member functions. - */ - template - struct mem_fun_ptr_helper - { - typedef RT (C::*type) (typename boost::tuples::element<0,ArgList>::type, - typename boost::tuples::element<1,ArgList>::type) const; - }; - - - /** - * @internal - * Construct a pointer to member - * function based on the template - * arguments. This is the - * specialization for 3 arguments - * and non-const member functions. - */ - template - struct mem_fun_ptr_helper - { - typedef RT (C::*type) (typename boost::tuples::element<0,ArgList>::type, - typename boost::tuples::element<1,ArgList>::type, - typename boost::tuples::element<2,ArgList>::type); - }; - - /** - * @internal - * Construct a pointer to member - * function based on the template - * arguments. This is the - * specialization for 3 arguments - * and const member functions. - */ - template - struct mem_fun_ptr_helper - { - typedef RT (C::*type) (typename boost::tuples::element<0,ArgList>::type, - typename boost::tuples::element<1,ArgList>::type, - typename boost::tuples::element<2,ArgList>::type) const; - }; - - - /** - * @internal - * Construct a pointer to member - * function based on the template - * arguments. This is the - * specialization for 4 arguments - * and non-const member functions. - */ - template - struct mem_fun_ptr_helper - { - typedef RT (C::*type) (typename boost::tuples::element<0,ArgList>::type, - typename boost::tuples::element<1,ArgList>::type, - typename boost::tuples::element<2,ArgList>::type, - typename boost::tuples::element<3,ArgList>::type); - }; - - /** - * @internal - * Construct a pointer to member - * function based on the template - * arguments. This is the - * specialization for 4 arguments - * and const member functions. - */ - template - struct mem_fun_ptr_helper - { - typedef RT (C::*type) (typename boost::tuples::element<0,ArgList>::type, - typename boost::tuples::element<1,ArgList>::type, - typename boost::tuples::element<2,ArgList>::type, - typename boost::tuples::element<3,ArgList>::type) const; - }; - - - /** - * @internal - * Construct a pointer to member - * function based on the template - * arguments. This is the - * specialization for 5 arguments - * and non-const member functions. - */ - template - struct mem_fun_ptr_helper - { - typedef RT (C::*type) (typename boost::tuples::element<0,ArgList>::type, - typename boost::tuples::element<1,ArgList>::type, - typename boost::tuples::element<2,ArgList>::type, - typename boost::tuples::element<3,ArgList>::type, - typename boost::tuples::element<4,ArgList>::type); - }; - - /** - * @internal - * Construct a pointer to member - * function based on the template - * arguments. This is the - * specialization for 5 arguments - * and const member functions. - */ - template - struct mem_fun_ptr_helper - { - typedef RT (C::*type) (typename boost::tuples::element<0,ArgList>::type, - typename boost::tuples::element<1,ArgList>::type, - typename boost::tuples::element<2,ArgList>::type, - typename boost::tuples::element<3,ArgList>::type, - typename boost::tuples::element<4,ArgList>::type) const; - }; - - - /** - * @internal - * Construct a pointer to member - * function based on the template - * arguments. This is the - * specialization for 6 arguments - * and non-const member functions. - */ - template - struct mem_fun_ptr_helper - { - typedef RT (C::*type) (typename boost::tuples::element<0,ArgList>::type, - typename boost::tuples::element<1,ArgList>::type, - typename boost::tuples::element<2,ArgList>::type, - typename boost::tuples::element<3,ArgList>::type, - typename boost::tuples::element<4,ArgList>::type, - typename boost::tuples::element<5,ArgList>::type); - }; - - /** - * @internal - * Construct a pointer to member - * function based on the template - * arguments. This is the - * specialization for 6 arguments - * and const member functions. - */ - template - struct mem_fun_ptr_helper - { - typedef RT (C::*type) (typename boost::tuples::element<0,ArgList>::type, - typename boost::tuples::element<1,ArgList>::type, - typename boost::tuples::element<2,ArgList>::type, - typename boost::tuples::element<3,ArgList>::type, - typename boost::tuples::element<4,ArgList>::type, - typename boost::tuples::element<5,ArgList>::type) const; - }; - - - /** - * @internal - * Construct a pointer to member - * function based on the template - * arguments. This is the - * specialization for 7 arguments - * and non-const member functions. - */ - template - struct mem_fun_ptr_helper - { - typedef RT (C::*type) (typename boost::tuples::element<0,ArgList>::type, - typename boost::tuples::element<1,ArgList>::type, - typename boost::tuples::element<2,ArgList>::type, - typename boost::tuples::element<3,ArgList>::type, - typename boost::tuples::element<4,ArgList>::type, - typename boost::tuples::element<5,ArgList>::type, - typename boost::tuples::element<6,ArgList>::type); - }; - - /** - * @internal - * Construct a pointer to member - * function based on the template - * arguments. This is the - * specialization for 7 arguments - * and const member functions. - */ - template - struct mem_fun_ptr_helper - { - typedef RT (C::*type) (typename boost::tuples::element<0,ArgList>::type, - typename boost::tuples::element<1,ArgList>::type, - typename boost::tuples::element<2,ArgList>::type, - typename boost::tuples::element<3,ArgList>::type, - typename boost::tuples::element<4,ArgList>::type, - typename boost::tuples::element<5,ArgList>::type, - typename boost::tuples::element<6,ArgList>::type) const; - }; - - - /** - * @internal - * Construct a pointer to member - * function based on the template - * arguments. This is the - * specialization for 8 arguments - * and non-const member functions. - */ - template - struct mem_fun_ptr_helper - { - typedef RT (C::*type) (typename boost::tuples::element<0,ArgList>::type, - typename boost::tuples::element<1,ArgList>::type, - typename boost::tuples::element<2,ArgList>::type, - typename boost::tuples::element<3,ArgList>::type, - typename boost::tuples::element<4,ArgList>::type, - typename boost::tuples::element<5,ArgList>::type, - typename boost::tuples::element<6,ArgList>::type, - typename boost::tuples::element<7,ArgList>::type); - }; - - /** - * @internal - * Construct a pointer to member - * function based on the template - * arguments. This is the - * specialization for 8 arguments - * and const member functions. - */ - template - struct mem_fun_ptr_helper - { - typedef RT (C::*type) (typename boost::tuples::element<0,ArgList>::type, - typename boost::tuples::element<1,ArgList>::type, - typename boost::tuples::element<2,ArgList>::type, - typename boost::tuples::element<3,ArgList>::type, - typename boost::tuples::element<4,ArgList>::type, - typename boost::tuples::element<5,ArgList>::type, - typename boost::tuples::element<6,ArgList>::type, - typename boost::tuples::element<7,ArgList>::type) const; - }; - - - /** - * @internal - * Construct a pointer to member - * function based on the template - * arguments. This is the - * specialization for 9 arguments - * and non-const member functions. - */ - template - struct mem_fun_ptr_helper - { - typedef RT (C::*type) (typename boost::tuples::element<0,ArgList>::type, - typename boost::tuples::element<1,ArgList>::type, - typename boost::tuples::element<2,ArgList>::type, - typename boost::tuples::element<3,ArgList>::type, - typename boost::tuples::element<4,ArgList>::type, - typename boost::tuples::element<5,ArgList>::type, - typename boost::tuples::element<6,ArgList>::type, - typename boost::tuples::element<7,ArgList>::type, - typename boost::tuples::element<8,ArgList>::type); - }; - - /** - * @internal - * Construct a pointer to member - * function based on the template - * arguments. This is the - * specialization for 9 arguments - * and const member functions. - */ - template - struct mem_fun_ptr_helper - { - typedef RT (C::*type) (typename boost::tuples::element<0,ArgList>::type, - typename boost::tuples::element<1,ArgList>::type, - typename boost::tuples::element<2,ArgList>::type, - typename boost::tuples::element<3,ArgList>::type, - typename boost::tuples::element<4,ArgList>::type, - typename boost::tuples::element<5,ArgList>::type, - typename boost::tuples::element<6,ArgList>::type, - typename boost::tuples::element<7,ArgList>::type, - typename boost::tuples::element<8,ArgList>::type) const; - }; - - - - /** - * @internal - * Construct a pointer to member - * function based on the template - * arguments. This is the - * specialization for 10 arguments - * and non-const member functions. - */ - template - struct mem_fun_ptr_helper - { - typedef RT (C::*type) (typename boost::tuples::element<0,ArgList>::type, - typename boost::tuples::element<1,ArgList>::type, - typename boost::tuples::element<2,ArgList>::type, - typename boost::tuples::element<3,ArgList>::type, - typename boost::tuples::element<4,ArgList>::type, - typename boost::tuples::element<5,ArgList>::type, - typename boost::tuples::element<6,ArgList>::type, - typename boost::tuples::element<7,ArgList>::type, - typename boost::tuples::element<8,ArgList>::type, - typename boost::tuples::element<9,ArgList>::type); - }; - - /** - * @internal - * Construct a pointer to member - * function based on the template - * arguments. This is the - * specialization for 10 arguments - * and const member functions. - */ - template - struct mem_fun_ptr_helper - { - typedef RT (C::*type) (typename boost::tuples::element<0,ArgList>::type, - typename boost::tuples::element<1,ArgList>::type, - typename boost::tuples::element<2,ArgList>::type, - typename boost::tuples::element<3,ArgList>::type, - typename boost::tuples::element<4,ArgList>::type, - typename boost::tuples::element<5,ArgList>::type, - typename boost::tuples::element<6,ArgList>::type, - typename boost::tuples::element<7,ArgList>::type, - typename boost::tuples::element<8,ArgList>::type, - typename boost::tuples::element<9,ArgList>::type) const; - }; - - - - /** - * @internal - * Construct a pointer to member - * function based on the template - * arguments, and whether the - * second argument is a const or - * non-const class, dependening on - * which the member function will - * also me const or non-const. We - * do this by dispatching to the - * mem_fun_ptr_helper classes that - * are overloaded on the number of - * elements and the const/non-const - * decision. - * - * Note that the last template - * argument for the - * mem_fun_ptr_helper class is - * automatically computed in the - * default argument to the general - * template. - */ - template - struct mem_fun_ptr - { - typedef typename mem_fun_ptr_helper::type type; - }; - } - - - namespace internal - { - /** - * @internal - * Construct a pointer to non-member - * function based on the template - * arguments, and whether the - * second argument is a const or - * non-const class, dependening on - * which the member function will - * also me const or - * non-const. There are - * specializations of this class - * for each number of arguments. - */ - template ::value> - struct fun_ptr_helper; - - - /** - * @internal - * Construct a pointer to non-member - * function based on the template - * arguments. This is the - * specialization for 0 arguments. - */ - template - struct fun_ptr_helper - { - typedef RT (*type) (); - }; - - - /** - * @internal - * Construct a pointer to non-member - * function based on the template - * arguments. This is the - * specialization for 1 argument. - */ - template - struct fun_ptr_helper - { - typedef RT (*type) (typename boost::tuples::element<0,ArgList>::type); - }; - - - /** - * @internal - * Construct a pointer to non-member - * function based on the template - * arguments. This is the - * specialization for 2 arguments. - */ - template - struct fun_ptr_helper - { - typedef RT (*type) (typename boost::tuples::element<0,ArgList>::type, - typename boost::tuples::element<1,ArgList>::type); - }; - - - /** - * @internal - * Construct a pointer to non-member - * function based on the template - * arguments. This is the - * specialization for 3 arguments. - */ - template - struct fun_ptr_helper - { - typedef RT (*type) (typename boost::tuples::element<0,ArgList>::type, - typename boost::tuples::element<1,ArgList>::type, - typename boost::tuples::element<2,ArgList>::type); - }; - - - /** - * @internal - * Construct a pointer to non-member - * function based on the template - * arguments. This is the - * specialization for 4 arguments. - */ - template - struct fun_ptr_helper - { - typedef RT (*type) (typename boost::tuples::element<0,ArgList>::type, - typename boost::tuples::element<1,ArgList>::type, - typename boost::tuples::element<2,ArgList>::type, - typename boost::tuples::element<3,ArgList>::type); - }; - - - /** - * @internal - * Construct a pointer to non-member - * function based on the template - * arguments. This is the - * specialization for 5 arguments. - */ - template - struct fun_ptr_helper - { - typedef RT (*type) (typename boost::tuples::element<0,ArgList>::type, - typename boost::tuples::element<1,ArgList>::type, - typename boost::tuples::element<2,ArgList>::type, - typename boost::tuples::element<3,ArgList>::type, - typename boost::tuples::element<4,ArgList>::type); - }; - - - /** - * @internal - * Construct a pointer to non-member - * function based on the template - * arguments. This is the - * specialization for 6 arguments. - */ - template - struct fun_ptr_helper - { - typedef RT (*type) (typename boost::tuples::element<0,ArgList>::type, - typename boost::tuples::element<1,ArgList>::type, - typename boost::tuples::element<2,ArgList>::type, - typename boost::tuples::element<3,ArgList>::type, - typename boost::tuples::element<4,ArgList>::type, - typename boost::tuples::element<5,ArgList>::type); - }; - - - /** - * @internal - * Construct a pointer to non-member - * function based on the template - * arguments. This is the - * specialization for 7 arguments. - */ - template - struct fun_ptr_helper - { - typedef RT (*type) (typename boost::tuples::element<0,ArgList>::type, - typename boost::tuples::element<1,ArgList>::type, - typename boost::tuples::element<2,ArgList>::type, - typename boost::tuples::element<3,ArgList>::type, - typename boost::tuples::element<4,ArgList>::type, - typename boost::tuples::element<5,ArgList>::type, - typename boost::tuples::element<6,ArgList>::type); - }; - - - /** - * @internal - * Construct a pointer to non-member - * function based on the template - * arguments. This is the - * specialization for 8 arguments. - */ - template - struct fun_ptr_helper - { - typedef RT (*type) (typename boost::tuples::element<0,ArgList>::type, - typename boost::tuples::element<1,ArgList>::type, - typename boost::tuples::element<2,ArgList>::type, - typename boost::tuples::element<3,ArgList>::type, - typename boost::tuples::element<4,ArgList>::type, - typename boost::tuples::element<5,ArgList>::type, - typename boost::tuples::element<6,ArgList>::type, - typename boost::tuples::element<7,ArgList>::type); - }; - - - /** - * @internal - * Construct a pointer to non-member - * function based on the template - * arguments. This is the - * specialization for 9 arguments. - */ - template - struct fun_ptr_helper - { - typedef RT (*type) (typename boost::tuples::element<0,ArgList>::type, - typename boost::tuples::element<1,ArgList>::type, - typename boost::tuples::element<2,ArgList>::type, - typename boost::tuples::element<3,ArgList>::type, - typename boost::tuples::element<4,ArgList>::type, - typename boost::tuples::element<5,ArgList>::type, - typename boost::tuples::element<6,ArgList>::type, - typename boost::tuples::element<7,ArgList>::type, - typename boost::tuples::element<8,ArgList>::type); - }; - - - - /** - * @internal - * Construct a pointer to non-member - * function based on the template - * arguments. This is the - * specialization for 10 arguments. - */ - template - struct fun_ptr_helper - { - typedef RT (*type) (typename boost::tuples::element<0,ArgList>::type, - typename boost::tuples::element<1,ArgList>::type, - typename boost::tuples::element<2,ArgList>::type, - typename boost::tuples::element<3,ArgList>::type, - typename boost::tuples::element<4,ArgList>::type, - typename boost::tuples::element<5,ArgList>::type, - typename boost::tuples::element<6,ArgList>::type, - typename boost::tuples::element<7,ArgList>::type, - typename boost::tuples::element<8,ArgList>::type, - typename boost::tuples::element<9,ArgList>::type); - }; - - - - /** - * @internal - * Construct a pointer to - * non-member function based on the - * template arguments. We do this - * by dispatching to the - * fun_ptr_helper classes that are - * overloaded on the number of - * elements. - * - * Note that the last template - * argument for the - * fun_ptr_helper class is - * automatically computed in the - * default argument to the general - * template. - */ - template - struct fun_ptr - { - typedef typename fun_ptr_helper::type type; - }; - } - - - namespace internal - { - /** - * @internal - * Extract the Nth element of the - * type list and make it a - * reference. - */ - template - struct add_reference_to_Nth - { - typedef typename boost::tuples::element::type ArgType; - typedef typename boost::add_reference::type type; - }; - - /** - * @internal - * Specializations of this template - * declare a typedef to a tuple - * type that has the same basic - * types as the first template - * argument, but all references - * instead of values. The second - * argument is used to distinguish - * between the lengths of argument - * lists. The default argument - * makes it possible to omit this - * length argument. - */ - template ::value> - struct tie_args_helper; - - - /** - * @internal - * Make a tuple type of all - * references out of the given - * tuple. Specialization for tuple - * of length 0. - */ - template - struct tie_args_helper - { - typedef Tuple type; - }; - - - /** - * @internal - * Make a tuple type of all - * references out of the given - * tuple. Specialization for tuple - * of length 1. - */ - template - struct tie_args_helper - { - typedef - boost::tuple::type> - type; - }; - - - /** - * @internal - * Make a tuple type of all - * references out of the given - * tuple. Specialization for tuple - * of length 2. - */ - template - struct tie_args_helper - { - typedef - boost::tuple::type, - typename add_reference_to_Nth<1,Tuple>::type> - type; - }; - - - /** - * @internal - * Make a tuple type of all - * references out of the given - * tuple. Specialization for tuple - * of length 3. - */ - template - struct tie_args_helper - { - typedef - boost::tuple::type, - typename add_reference_to_Nth<1,Tuple>::type, - typename add_reference_to_Nth<2,Tuple>::type> - type; - }; - - - /** - * @internal - * Make a tuple type of all - * references out of the given - * tuple. Specialization for tuple - * of length 4. - */ - template - struct tie_args_helper - { - typedef - boost::tuple::type, - typename add_reference_to_Nth<1,Tuple>::type, - typename add_reference_to_Nth<2,Tuple>::type, - typename add_reference_to_Nth<3,Tuple>::type> - type; - }; - - - /** - * @internal - * Make a tuple type of all - * references out of the given - * tuple. Specialization for tuple - * of length 5. - */ - template - struct tie_args_helper - { - typedef - boost::tuple::type, - typename add_reference_to_Nth<1,Tuple>::type, - typename add_reference_to_Nth<2,Tuple>::type, - typename add_reference_to_Nth<3,Tuple>::type, - typename add_reference_to_Nth<4,Tuple>::type> - type; - }; - - - /** - * @internal - * Make a tuple type of all - * references out of the given - * tuple. Specialization for tuple - * of length 6. - */ - template - struct tie_args_helper - { - typedef - boost::tuple::type, - typename add_reference_to_Nth<1,Tuple>::type, - typename add_reference_to_Nth<2,Tuple>::type, - typename add_reference_to_Nth<3,Tuple>::type, - typename add_reference_to_Nth<4,Tuple>::type, - typename add_reference_to_Nth<5,Tuple>::type> - type; - }; - - - - /** - * @internal - * Make a tuple type of all - * references out of the given - * tuple. Specialization for tuple - * of length 7. - */ - template - struct tie_args_helper - { - typedef - boost::tuple::type, - typename add_reference_to_Nth<1,Tuple>::type, - typename add_reference_to_Nth<2,Tuple>::type, - typename add_reference_to_Nth<3,Tuple>::type, - typename add_reference_to_Nth<4,Tuple>::type, - typename add_reference_to_Nth<5,Tuple>::type, - typename add_reference_to_Nth<6,Tuple>::type> - type; - }; - - - /** - * @internal - * Make a tuple type of all - * references out of the given - * tuple. Specialization for tuple - * of length 8. - */ - template - struct tie_args_helper - { - typedef - boost::tuple::type, - typename add_reference_to_Nth<1,Tuple>::type, - typename add_reference_to_Nth<2,Tuple>::type, - typename add_reference_to_Nth<3,Tuple>::type, - typename add_reference_to_Nth<4,Tuple>::type, - typename add_reference_to_Nth<5,Tuple>::type, - typename add_reference_to_Nth<6,Tuple>::type, - typename add_reference_to_Nth<7,Tuple>::type> - type; - }; - - - /** - * @internal - * Make a tuple type of all - * references out of the given - * tuple. Specialization for tuple - * of length 9. - */ - template - struct tie_args_helper - { - typedef - boost::tuple::type, - typename add_reference_to_Nth<1,Tuple>::type, - typename add_reference_to_Nth<2,Tuple>::type, - typename add_reference_to_Nth<3,Tuple>::type, - typename add_reference_to_Nth<4,Tuple>::type, - typename add_reference_to_Nth<5,Tuple>::type, - typename add_reference_to_Nth<6,Tuple>::type, - typename add_reference_to_Nth<7,Tuple>::type, - typename add_reference_to_Nth<8,Tuple>::type> - type; - }; - - - /** - * @internal - * Make a tuple type of all - * references out of the given - * tuple. Specialization for tuple - * of length 10. - */ - template - struct tie_args_helper - { - typedef - boost::tuple::type, - typename add_reference_to_Nth<1,Tuple>::type, - typename add_reference_to_Nth<2,Tuple>::type, - typename add_reference_to_Nth<3,Tuple>::type, - typename add_reference_to_Nth<4,Tuple>::type, - typename add_reference_to_Nth<5,Tuple>::type, - typename add_reference_to_Nth<6,Tuple>::type, - typename add_reference_to_Nth<7,Tuple>::type, - typename add_reference_to_Nth<8,Tuple>::type, - typename add_reference_to_Nth<9,Tuple>::type> - type; - }; - - - - /** - * @internal - * Declare a typedef to a tuple - * type that has the same basic - * types as the template - * argument, but all references - * instead of values. - * - * Do so by redirecting to the - * tie_args_helper specializations; - * note that the second argument of - * these templates is computed - * automatically by the default - * argument specification. - */ - template - struct tie_args - { - typedef typename tie_args_helper::type type; - }; - } - - -#if (DEAL_II_USE_MT == 1) -# if defined(DEAL_II_USE_MT_POSIX) - - namespace internal - { - /** - * @internal - * Base class describing a - * thread. This is the basic - * class abstracting the - * operating system's POSIX - * implementation into a C++ - * class. It provides a mechanism - * to start a new thread, as well - * as for joining it. - * - * @author Wolfgang Bangerth, 2003 - */ - struct thread_description_base - { - private: - /** - * Variable holding the data - * the operating system needs - * to work with a thread. - */ - pthread_t thread; - - /** - * Store whether the - * join() member function - * as already been called. If - * true, then join - * will return immediately, - * otherwise it needs to go - * through a call to the - * operating system. - * - * This class is generated - * exactly once per thread, - * but is kept in the - * background: user's should - * not directly access this - * class. Access to it is - * performed through counted - * pointers, both from - * Thread<> objects as - * well as from the thread - * entry point function on - * the new thread. It is only - * deleted when all users - * have freed it, which means - * that also the new thread - * has ended. - */ - mutable volatile bool was_joined; - - /** - * Mutex used to synchronise - * calls to the join() - * function. - */ - mutable ThreadMutex join_mutex; - - public: - - /** - * Constructor. - */ - thread_description_base (); - - /** - * Destructor. - */ - virtual ~thread_description_base (); - - /** - * Create a new thread with - * the given thread entry - * point and arguments. Store - * the result of the - * operation in the - * thread member variable - * for further use. - */ - void create (void * (*p) (void *), void *d); - - /** - * Join a thread, i.e. wait - * for it to finish. This - * function can safely be - * called from different - * threads at the same time, - * and can also be called - * more than once. - */ - void join () const; - - /** - * Exception - */ - DeclException1 (ExcThreadCreationError, - int, - << "pthread_create return code is " << arg1); - }; - -# else // some other threading model -# error Not Implemented -# endif // defined(DEAL_II_USE_MT_POSIX) - - /** - * @internal - * Class derived from - * thread_description_base() - * that also provides the - * possibility to store a return - * value. - * - * @author Wolfgang Bangerth, 2003 - */ - template - struct thread_description : public thread_description_base - { - return_value ret_val; - }; - - // forward declare another class - template struct wrapper_base; - } - - - - /** - * User visible class describing a - * thread. Relays all real calls to - * the internal thread object - * abstracting the operating - * system's functions, to which it - * keeps a shared pointer. This - * object can be freely copied - * around in user space. - * - * The default value of the - * template argument is void, - * so if the function you are - * calling on a new thread has no - * return value, you can omit the - * template argument. - * - * @author Wolfgang Bangerth, 2003 - */ - template - class Thread - { - /** - * Construct a thread object - * with a pointer to an - * internal thread object. This - * is the constructor used to - * the spawn family of - * functions. - * - * We would like to make this - * constructor private and only - * grant the - * wrapper_base::fire_up - * function friendship, but - * granting friendship to - * functions in other - * namespaces doesn't work with - * some compilers, so only do - * so if the configure script - * decided that this is safe. - */ -#if defined(DEAL_II_NAMESP_TEMPL_FRIEND_BUG2) || defined(DEAL_II_NAMESP_TEMPL_FRIEND_BUG) - public: -#endif - Thread (const boost::shared_ptr > &td) - : thread_descriptor (td) {} - - public: - - /** - * Default constructor. You - * can't do much with a thread - * object constructed this way, - * except for assigning it a - * thread object that holds - * data created by the - * spawn functions. - */ - Thread () {} - - /** - * Join the thread represented - * by this object, i.e. wait - * for it to finish. You can't - * call this function if you - * have used the default - * constructor of this class - * and have not assigned a - * thread object to it. - */ - void join () const { - AssertThrow (thread_descriptor, ExcNoThread()); - thread_descriptor->join (); - } - - /** - * Get the return value of the - * function of the - * thread. Since this is only - * available once the thread - * finishes, this implicitely - * also calls join(). - */ - RT return_value () { - join (); - return thread_descriptor->ret_val.get(); - } - - - /** - * Check for equality of thread - * objects. Since objects of - * this class store an implicit - * pointer to an object that - * exists exactly once for each - * thread, the check is simply - * to compare these pointers. - */ - bool operator == (const Thread &t) { - return thread_descriptor == t.thread_descriptor; - } - - /** @addtogroup Exceptions - * @{ */ - - /** - * Exception - */ - DeclException0 (ExcNoThread); - //@} - private: - /** - * Shared pointer to the object - * representing the thread, and - * abstracting operating system - * functions to work on - * it. Boost's shared pointer - * implementation will make - * sure that that object lives - * as long as there is at least - * one subscriber to it. - */ - boost::shared_ptr > thread_descriptor; - -#if !defined(DEAL_II_NAMESP_TEMPL_FRIEND_BUG2) && !defined(DEAL_II_NAMESP_TEMPL_FRIEND_BUG) - template friend struct internal::wrapper_base; -#endif - }; - - - - namespace internal - { - - /** - * @internal - * Base class for the classes - * wrapping function pointers and - * arguments for non-member and - * member functions. The first - * template class denotes the - * return type of the function - * being called. The second one - * is a class that provides a - * function entry_point, - * which will be used as an entry - * point for the new thread. In - * the classes derived from this - * one, the second template - * argument is actually the - * derived class itself, using - * something like the - * Barton-Nackman trick. - * - * @author Wolfgang Bangerth, 2003 - */ - template - struct wrapper_base - { - - /** - * Start a new thread, wait - * until it has copied the - * data out of this object, - * and return the thread - * descriptor. - */ - Thread fire_up () { - thread_descriptor = - DescriptionPointer(new internal::thread_description()); - - ThreadMutex::ScopedLock lock (mutex); - thread_descriptor->create (&EntryPointClass::entry_point, - (void *)this); - condition.wait (mutex); - - return thread_descriptor; - } - - protected: - /** - * Typedef for shared - * pointers to the objects - * describing threads on the - * OS level. - */ - typedef - boost::shared_ptr > - DescriptionPointer; - - /** - * Shared pointer to the - * unique object describing a - * thread on the OS level. - */ - DescriptionPointer thread_descriptor; - - /** - * Mutex and condition - * variable used to - * synchronise calling and - * called thread. - */ - mutable ThreadMutex mutex; - mutable ThreadCondition condition; - }; - - - /** - * @internal - * Wrap the arguments to a - * non-member or static member - * function and provide an entry - * point for a new thread that - * unwraps this data and calls - * the function with them. - * - * @author Wolfgang Bangerth, 2003 - */ - template - struct fun_wrapper : public wrapper_base > - { - /** - * Typedef for the type of - * the function to be called - * on the new thread. - */ - typedef typename internal::fun_ptr::type FunPtr; - - /** - * Typedef for a typelist of - * reference arguments to the - * function to be called. - */ - typedef typename internal::tie_args::type ArgReferences; - - /** - * Constructor. Store the - * necessary information - * about the function to be - * called and with which - * arguments. - * - * Pass down the address of - * this class's thread entry - * point function. This way, - * we can ensure that object - * and thread entry point - * function always are in - * synch with respect to - * their knowledge of the - * types involved. - */ - fun_wrapper (FunPtr fun_ptr, - const ArgReferences &args) - : fun_ptr (fun_ptr), - args (args) {} - private: - /** - * Default constructor. Made - * private and not - * implemented to prevent - * calling. - */ - fun_wrapper (); - - /** - * Copy constructor. Made - * private and not - * implemented to prevent - * calling. - */ - fun_wrapper (const fun_wrapper &); - - /** - * Pointer to the function to - * be called on the new - * thread. - */ - FunPtr fun_ptr; - - /** - * References to the - * arguments with which the - * function is to be called. - */ - ArgReferences args; - - - /** - * Entry point for the new - * thread. - */ - static void * entry_point (void *arg) - { - const wrapper_base *w - = reinterpret_cast*> (arg); - const fun_wrapper *wrapper - = static_cast (w); - - // copy information from - // the stack of the - // calling thread - FunPtr fun_ptr = wrapper->fun_ptr; - ArgList args = wrapper->args; - - boost::shared_ptr > - thread_descriptor = wrapper->thread_descriptor; - - // signal the fact that - // we have copied all the - // information that is - // needed - { - ThreadMutex::ScopedLock lock (wrapper->mutex); - wrapper->condition.signal (); - } - - // call the - // function. since an - // exception that is - // thrown from one of the - // called functions will - // not propagate to the - // main thread, it will - // kill the program if - // not treated here - // before we return to - // the operating system's - // thread library - internal::register_thread (); - try - { - internal::call (fun_ptr, args, - thread_descriptor->ret_val); - } - catch (const std::exception &exc) - { - internal::handle_std_exception (exc); - } - catch (...) - { - internal::handle_unknown_exception (); - } - internal::deregister_thread (); - - return 0; - } - - - /** - * Make the base class a - * friend, so that it can - * access the thread entry - * point function. - */ - template friend class wrapper_base; - }; - - - - /** - * @internal - * Wrap the arguments to a member - * function and provide an entry - * point for a new thread that - * unwraps this data and calls - * the function with them. - * - * @author Wolfgang Bangerth, 2003 - */ - template - struct mem_fun_wrapper : public wrapper_base > - { - /** - * Typedef for the type of - * the function to be called - * on the new thread. - */ - typedef typename internal::mem_fun_ptr::type MemFunPtr; - - /** - * Typedef for a typelist of - * reference arguments to the - * function to be called. - */ - typedef typename internal::tie_args::type ArgReferences; - - /** - * Constructor. Store the - * necessary information - * about the function to be - * called and with which - * arguments. - * - * Pass down the address of - * this class's thread entry - * point function. This way, - * we can ensure that object - * and thread entry point - * function always are in - * synch with respect to - * their knowledge of the - * types involved. - */ - mem_fun_wrapper (MemFunPtr mem_fun_ptr, - C &c, - const ArgReferences &args) - : - c (c), - mem_fun_ptr (mem_fun_ptr), - args (args) {} - private: - /** - * Default constructor. Made - * private and not - * implemented to prevent - * calling. - */ - mem_fun_wrapper (); - - /** - * Copy constructor. Made - * private and not - * implemented to prevent - * calling. - */ - mem_fun_wrapper (const mem_fun_wrapper &); - - /** - * Pointer to the function to - * be called on the new - * thread, as well as the - * object with which this has - * to happen. - */ - C &c; - MemFunPtr mem_fun_ptr; - - /** - * References to the - * arguments with which the - * function is to be called. - */ - ArgReferences args; - - /** - * Entry point for the new - * thread. - */ - static void * entry_point (void *arg) - { - const wrapper_base *w - = reinterpret_cast*> (arg); - const mem_fun_wrapper *wrapper - = static_cast (w); - - // copy information from - // the stack of the - // calling thread - MemFunPtr mem_fun_ptr = wrapper->mem_fun_ptr; - C &c = wrapper->c; - ArgList args = wrapper->args; - - boost::shared_ptr > - thread_descriptor = wrapper->thread_descriptor; - - // signal the fact that - // we have copied all the - // information that is - // needed - { - ThreadMutex::ScopedLock lock (wrapper->mutex); - wrapper->condition.signal (); - } - - // call the - // function. since an - // exception that is - // thrown from one of the - // called functions will - // not propagate to the - // main thread, it will - // kill the program if - // not treated here - // before we return to - // the operating system's - // thread library - internal::register_thread (); - try - { - internal::call (mem_fun_ptr, c, args, - thread_descriptor->ret_val); - } - catch (const std::exception &exc) - { - internal::handle_std_exception (exc); - } - catch (...) - { - internal::handle_unknown_exception (); - } - internal::deregister_thread (); - - return 0; - } - - /** - * Make the base class a - * friend, so that it can - * access the thread entry - * point function. - */ - template friend class wrapper_base; - }; - } - - - namespace internal - { - /** - * @internal - * General template declaration - * of a class that is used to - * encapsulate arguments to - * global and static member - * functions, make sure a new - * thread is created and that - * function being run on that - * thread. - * - * Although this general template - * is not implemented at all, the - * default template argument - * makes sure that whenever using - * the name of this class, the - * last template argument will be - * computed correctly from the - * previous arguments, and the - * correct specialization for - * this last template argument be - * used, even though we need to - * specify it. - */ - template - class fun_encapsulator; - - - /** - * @internal - * General template declaration - * of a class that is used to - * encapsulate arguments to - * non-static member functions, - * make sure a new thread is - * created and that function - * being run on that thread. - * - * Although this general template - * is not implemented at all, the - * default template argument - * makes sure that whenever using - * the name of this class, the - * last template argument will be - * computed correctly from the - * previous arguments, and the - * correct specialization for - * this last template argument be - * used, even though we need to - * specify it. - */ - template - class mem_fun_encapsulator; - } - - -// ----------- encapsulators for member functions not taking any parameters - - namespace internal - { - /** - * @internal - * Encapsulator class for member - * functions with no arguments. - */ - template - class mem_fun_encapsulator - { - typedef typename internal::mem_fun_ptr::type MemFunPtr; - - public: - inline mem_fun_encapsulator (C &c, MemFunPtr mem_fun_ptr) - : c (c), mem_fun_ptr(mem_fun_ptr) {} - - inline - Thread - operator() () { - return mem_fun_wrapper (mem_fun_ptr, c, - ArgList()).fire_up (); - } - - private: - C &c; - MemFunPtr mem_fun_ptr; - }; - - } - - /** - * Overload of the non-const spawn - * function for member functions with - * no arguments. - */ - template - inline - internal::mem_fun_encapsulator,0> - spawn (C &c, RT (C::*fun_ptr)()) { - return internal::mem_fun_encapsulator,0> (c,fun_ptr); - } - - /** - * Overload of the spawn function for - * const member functions with no - * arguments. - */ - template - inline - internal::mem_fun_encapsulator,0> - spawn (const C &c, RT (C::*fun_ptr)() const) { - return internal::mem_fun_encapsulator,0> (c,fun_ptr); - } - - - - -// ----------- encapsulators for unary member functions - - namespace internal - { - /** - * @internal - * Encapsulator class for member - * functions with 1 argument. - */ - template - class mem_fun_encapsulator - { - typedef typename internal::mem_fun_ptr::type MemFunPtr; - - public: - inline mem_fun_encapsulator (C &c, MemFunPtr mem_fun_ptr) - : c (c), mem_fun_ptr(mem_fun_ptr) {} - - inline - Thread - operator() (typename boost::tuples::element<0,ArgList>::type arg1) { - return mem_fun_wrapper (mem_fun_ptr, c, - boost::tie(arg1)).fire_up (); - } - - private: - C &c; - MemFunPtr mem_fun_ptr; - }; - - } - - - /** - * Overload of the non-const spawn - * function for member functions with - * 1 argument. - */ - template - inline - internal::mem_fun_encapsulator,1> - spawn (C &c, RT (C::*fun_ptr)(Arg1)) { - return internal::mem_fun_encapsulator,1> (c,fun_ptr); - } - - /** - * Overload of the spawn function for - * const member functions with 1 - * argument. - */ - template - inline - internal::mem_fun_encapsulator,1> - spawn (const C &c, RT (C::*fun_ptr)(Arg1) const) { - return internal::mem_fun_encapsulator,1> (c,fun_ptr); - } - - - - -// ----------- encapsulators for binary member functions - - namespace internal - { - /** - * @internal - * Encapsulator class for member - * functions with 2 arguments. - */ - template - class mem_fun_encapsulator - { - typedef typename internal::mem_fun_ptr::type MemFunPtr; - - public: - inline mem_fun_encapsulator (C &c, MemFunPtr mem_fun_ptr) - : c (c), mem_fun_ptr(mem_fun_ptr) {} - - inline - Thread - operator() (typename boost::tuples::element<0,ArgList>::type arg1, - typename boost::tuples::element<1,ArgList>::type arg2) { - return mem_fun_wrapper (mem_fun_ptr, c, - boost::tie(arg1, - arg2)).fire_up (); - } - - private: - C &c; - MemFunPtr mem_fun_ptr; - }; - - } - - /** - * Overload of the non-const spawn - * function for member functions with - * 2 arguments. - */ - template - inline - internal::mem_fun_encapsulator,2> - spawn (C &c, RT (C::*fun_ptr)(Arg1,Arg2)) { - return internal::mem_fun_encapsulator,2> (c,fun_ptr); - } - - /** - * Overload of the spawn function for - * const member functions with 2 - * arguments. - */ - template - inline - internal::mem_fun_encapsulator,2> - spawn (const C &c, RT (C::*fun_ptr)(Arg1,Arg2) const) { - return internal::mem_fun_encapsulator,2> (c,fun_ptr); - } - - - -// ----------- encapsulators for ternary member functions - - namespace internal - { - /** - * @internal - * Encapsulator class for member - * functions with 3 arguments. - */ - template - class mem_fun_encapsulator - { - typedef typename internal::mem_fun_ptr::type MemFunPtr; - - public: - inline mem_fun_encapsulator (C &c, MemFunPtr mem_fun_ptr) - : c (c), mem_fun_ptr(mem_fun_ptr) {} - - inline - Thread - operator() (typename boost::tuples::element<0,ArgList>::type arg1, - typename boost::tuples::element<1,ArgList>::type arg2, - typename boost::tuples::element<2,ArgList>::type arg3) { - return mem_fun_wrapper (mem_fun_ptr, c, - boost::tie(arg1, - arg2, - arg3)).fire_up (); - } - - private: - C &c; - MemFunPtr mem_fun_ptr; - }; - - } - - /** - * Overload of the non-const spawn - * function for member functions with - * 3 arguments. - */ - template - inline - internal::mem_fun_encapsulator,3> - spawn (C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3)) { - return internal::mem_fun_encapsulator,3> (c,fun_ptr); - } - - /** - * Overload of the spawn function for - * const member functions with 3 - * arguments. - */ - template - inline - internal::mem_fun_encapsulator,3> - spawn (const C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3) const) { - return internal::mem_fun_encapsulator,3> (c,fun_ptr); - } - - - - -// ----------- encapsulators for member functions with 4 arguments - - namespace internal - { - /** - * @internal - * Encapsulator class for member - * functions with 4 arguments. - */ - template - class mem_fun_encapsulator - { - typedef typename internal::mem_fun_ptr::type MemFunPtr; - - public: - inline mem_fun_encapsulator (C &c, MemFunPtr mem_fun_ptr) - : c (c), mem_fun_ptr(mem_fun_ptr) {} - - inline - Thread - operator() (typename boost::tuples::element<0,ArgList>::type arg1, - typename boost::tuples::element<1,ArgList>::type arg2, - typename boost::tuples::element<2,ArgList>::type arg3, - typename boost::tuples::element<3,ArgList>::type arg4) { - return mem_fun_wrapper (mem_fun_ptr, c, - boost::tie(arg1,arg2, - arg3,arg4)).fire_up (); - } - - private: - C &c; - MemFunPtr mem_fun_ptr; - }; - - } - - /** - * Overload of the non-const spawn - * function for member functions with - * 4 arguments. - */ - template - inline - internal::mem_fun_encapsulator,4> - spawn (C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4)) { - return internal::mem_fun_encapsulator,4> (c,fun_ptr); - } - - /** - * Overload of the spawn function for - * const member functions with 4 - * arguments. - */ - template - inline - internal::mem_fun_encapsulator,4> - spawn (const C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4) const) { - return internal::mem_fun_encapsulator,4> (c,fun_ptr); - } - - - - -// ----------- encapsulators for member functions with 5 arguments - - namespace internal - { - /** - * @internal - * Encapsulator class for member - * functions with 5 arguments. - */ - template - class mem_fun_encapsulator - { - typedef typename internal::mem_fun_ptr::type MemFunPtr; - - public: - inline mem_fun_encapsulator (C &c, MemFunPtr mem_fun_ptr) - : c (c), mem_fun_ptr(mem_fun_ptr) {} - - inline - Thread - operator() (typename boost::tuples::element<0,ArgList>::type arg1, - typename boost::tuples::element<1,ArgList>::type arg2, - typename boost::tuples::element<2,ArgList>::type arg3, - typename boost::tuples::element<3,ArgList>::type arg4, - typename boost::tuples::element<4,ArgList>::type arg5) { - return mem_fun_wrapper (mem_fun_ptr, c, - boost::tie(arg1,arg2, - arg3,arg4, - arg5)).fire_up (); - } - - private: - C &c; - MemFunPtr mem_fun_ptr; - }; - - } - - /** - * Overload of the non-const spawn - * function for member functions with - * 5 arguments. - */ - template - inline - internal::mem_fun_encapsulator,5> - spawn (C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5)) { - return internal::mem_fun_encapsulator,5> (c,fun_ptr); - } - - /** - * Overload of the spawn function for - * const member functions with 5 - * arguments. - */ - template - inline - internal::mem_fun_encapsulator,5> - spawn (const C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5) const) { - return internal::mem_fun_encapsulator,5> (c,fun_ptr); - } - - -// ----------- encapsulators for member functions with 6 arguments - - namespace internal - { - /** - * @internal - * Encapsulator class for member - * functions with 6 arguments. - */ - template - class mem_fun_encapsulator - { - typedef typename internal::mem_fun_ptr::type MemFunPtr; - - public: - inline mem_fun_encapsulator (C &c, MemFunPtr mem_fun_ptr) - : c (c), mem_fun_ptr(mem_fun_ptr) {} - - inline - Thread - operator() (typename boost::tuples::element<0,ArgList>::type arg1, - typename boost::tuples::element<1,ArgList>::type arg2, - typename boost::tuples::element<2,ArgList>::type arg3, - typename boost::tuples::element<3,ArgList>::type arg4, - typename boost::tuples::element<4,ArgList>::type arg5, - typename boost::tuples::element<5,ArgList>::type arg6) { - return mem_fun_wrapper (mem_fun_ptr, c, - boost::tie(arg1,arg2, - arg3,arg4, - arg5,arg6)).fire_up (); - } - - private: - C &c; - MemFunPtr mem_fun_ptr; - }; - - } - - /** - * Overload of the non-const spawn - * function for member functions with - * 6 arguments. - */ - template - inline - internal::mem_fun_encapsulator,6> - spawn (C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5,Arg6)) { - return internal::mem_fun_encapsulator,6> (c,fun_ptr); - } - - /** - * Overload of the spawn function for - * const member functions with 6 - * arguments. - */ - template - inline - internal::mem_fun_encapsulator,6> - spawn (const C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5,Arg6) const) { - return internal::mem_fun_encapsulator,6> (c,fun_ptr); - } - - -// ----------- encapsulators for member functions with 7 arguments - - namespace internal - { - /** - * @internal - * Encapsulator class for member - * functions with 7 arguments. - */ - template - class mem_fun_encapsulator - { - typedef typename internal::mem_fun_ptr::type MemFunPtr; - - public: - inline mem_fun_encapsulator (C &c, MemFunPtr mem_fun_ptr) - : c (c), mem_fun_ptr(mem_fun_ptr) {} - - inline - Thread - operator() (typename boost::tuples::element<0,ArgList>::type arg1, - typename boost::tuples::element<1,ArgList>::type arg2, - typename boost::tuples::element<2,ArgList>::type arg3, - typename boost::tuples::element<3,ArgList>::type arg4, - typename boost::tuples::element<4,ArgList>::type arg5, - typename boost::tuples::element<5,ArgList>::type arg6, - typename boost::tuples::element<6,ArgList>::type arg7) { - return mem_fun_wrapper (mem_fun_ptr, c, - boost::tie(arg1,arg2, - arg3,arg4, - arg5,arg6, - arg7)).fire_up (); - } - - private: - C &c; - MemFunPtr mem_fun_ptr; - }; - - } - - /** - * Overload of the non-const spawn - * function for member functions with - * 7 arguments. - */ - template - inline - internal::mem_fun_encapsulator,7> - spawn (C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5,Arg6,Arg7)) { - return internal::mem_fun_encapsulator,7> (c,fun_ptr); - } - - /** - * Overload of the spawn function for - * const member functions with 7 - * arguments. - */ - template - inline - internal::mem_fun_encapsulator,7> - spawn (const C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5,Arg6,Arg7) const) { - return internal::mem_fun_encapsulator,7> (c,fun_ptr); - } - - -// ----------- encapsulators for member functions with 8 arguments - - namespace internal - { - /** - * @internal - * Encapsulator class for member - * functions with 8 arguments. - */ - template - class mem_fun_encapsulator - { - typedef typename internal::mem_fun_ptr::type MemFunPtr; - - public: - inline mem_fun_encapsulator (C &c, MemFunPtr mem_fun_ptr) - : c (c), mem_fun_ptr(mem_fun_ptr) {} - - inline - Thread - operator() (typename boost::tuples::element<0,ArgList>::type arg1, - typename boost::tuples::element<1,ArgList>::type arg2, - typename boost::tuples::element<2,ArgList>::type arg3, - typename boost::tuples::element<3,ArgList>::type arg4, - typename boost::tuples::element<4,ArgList>::type arg5, - typename boost::tuples::element<5,ArgList>::type arg6, - typename boost::tuples::element<6,ArgList>::type arg7, - typename boost::tuples::element<7,ArgList>::type arg8) { - return mem_fun_wrapper (mem_fun_ptr, c, - boost::tie(arg1,arg2, - arg3,arg4, - arg5,arg6, - arg7,arg8)).fire_up (); - } - - private: - C &c; - MemFunPtr mem_fun_ptr; - }; - - } - - /** - * Overload of the non-const spawn - * function for member functions with - * 8 arguments. - */ - template - inline - internal::mem_fun_encapsulator,8> - spawn (C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5, - Arg6,Arg7,Arg8)) { - return internal::mem_fun_encapsulator,8> (c,fun_ptr); - } - - /** - * Overload of the spawn function for - * const member functions with 8 - * arguments. - */ - template - inline - internal::mem_fun_encapsulator,8> - spawn (const C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5, - Arg6,Arg7,Arg8) const) { - return internal::mem_fun_encapsulator,8> (c,fun_ptr); - } - - -// ----------- encapsulators for member functions with 9 arguments - - namespace internal - { - /** - * @internal - * Encapsulator class for member - * functions with 9 arguments. - */ - template - class mem_fun_encapsulator - { - typedef typename internal::mem_fun_ptr::type MemFunPtr; - - public: - inline mem_fun_encapsulator (C &c, MemFunPtr mem_fun_ptr) - : c (c), mem_fun_ptr(mem_fun_ptr) {} - - inline - Thread - operator() (typename boost::tuples::element<0,ArgList>::type arg1, - typename boost::tuples::element<1,ArgList>::type arg2, - typename boost::tuples::element<2,ArgList>::type arg3, - typename boost::tuples::element<3,ArgList>::type arg4, - typename boost::tuples::element<4,ArgList>::type arg5, - typename boost::tuples::element<5,ArgList>::type arg6, - typename boost::tuples::element<6,ArgList>::type arg7, - typename boost::tuples::element<7,ArgList>::type arg8, - typename boost::tuples::element<8,ArgList>::type arg9) { - return mem_fun_wrapper (mem_fun_ptr, c, - boost::tie(arg1,arg2, - arg3,arg4, - arg5,arg6, - arg7,arg8, - arg9)).fire_up (); - } - - private: - C &c; - MemFunPtr mem_fun_ptr; - }; - - } - - /** - * Overload of the non-const spawn - * function for member functions with - * 9 arguments. - */ - template - inline - internal::mem_fun_encapsulator,9> - spawn (C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5, - Arg6,Arg7,Arg8,Arg9)) { - return internal::mem_fun_encapsulator,9> (c,fun_ptr); - } - - /** - * Overload of the spawn function for - * const member functions with 9 - * arguments. - */ - template - inline - internal::mem_fun_encapsulator,9> - spawn (const C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5, - Arg6,Arg7,Arg8,Arg9) const) { - return internal::mem_fun_encapsulator,9> (c,fun_ptr); - } - - -// ----------- encapsulators for member functions with 10 arguments - - namespace internal - { - /** - * @internal - * Encapsulator class for member - * functions with 10 arguments. - */ - template - class mem_fun_encapsulator - { - typedef typename internal::mem_fun_ptr::type MemFunPtr; - - public: - inline mem_fun_encapsulator (C &c, MemFunPtr mem_fun_ptr) - : c (c), mem_fun_ptr(mem_fun_ptr) {} - - inline - Thread - operator() (typename boost::tuples::element<0,ArgList>::type arg1, - typename boost::tuples::element<1,ArgList>::type arg2, - typename boost::tuples::element<2,ArgList>::type arg3, - typename boost::tuples::element<3,ArgList>::type arg4, - typename boost::tuples::element<4,ArgList>::type arg5, - typename boost::tuples::element<5,ArgList>::type arg6, - typename boost::tuples::element<6,ArgList>::type arg7, - typename boost::tuples::element<7,ArgList>::type arg8, - typename boost::tuples::element<8,ArgList>::type arg9, - typename boost::tuples::element<9,ArgList>::type arg10) { - return mem_fun_wrapper (mem_fun_ptr, c, - boost::tie(arg1,arg2, - arg3,arg4, - arg5,arg6, - arg7,arg8, - arg9, arg10)).fire_up (); - } - - private: - C &c; - MemFunPtr mem_fun_ptr; - }; - - } - - /** - * Overload of the non-const spawn - * function for member functions with - * 10 arguments. - */ - template - inline - internal::mem_fun_encapsulator,10> - spawn (C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5, - Arg6,Arg7,Arg8,Arg9,Arg10)) { - return internal::mem_fun_encapsulator,10> (c,fun_ptr); - } - - /** - * Overload of the spawn function for - * const member functions with 10 - * arguments. - */ - template - inline - internal::mem_fun_encapsulator,10> - spawn (const C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5, - Arg6,Arg7,Arg8,Arg9,Arg10) const) { - return internal::mem_fun_encapsulator,10> (c,fun_ptr); - } - - - -// ----------- encapsulators for functions not taking any parameters - - namespace internal - { - /** - * @internal - * Encapsulator class for - * functions with no arguments. - */ - template - class fun_encapsulator - { - typedef typename internal::fun_ptr::type FunPtr; - - public: - inline fun_encapsulator (FunPtr fun_ptr) - : fun_ptr(fun_ptr) {} - - inline - Thread - operator() () { - return fun_wrapper (fun_ptr, - ArgList()).fire_up (); - } - - private: - FunPtr fun_ptr; - }; - - } - - /** - * Overload of the spawn function for - * non-member or static member - * functions with no arguments. - */ - template - inline - internal::fun_encapsulator,0> - spawn (RT (*fun_ptr)()) { - return internal::fun_encapsulator,0> (fun_ptr); - } - - - - -// ----------- encapsulators for unary functions - - namespace internal - { - /** - * @internal - * Encapsulator class for - * functions with 1 argument. - */ - template - class fun_encapsulator - { - typedef typename internal::fun_ptr::type FunPtr; - - public: - inline fun_encapsulator (FunPtr fun_ptr) - : fun_ptr(fun_ptr) {} - - inline - Thread - operator() (typename boost::tuples::element<0,ArgList>::type arg1) { - return fun_wrapper (fun_ptr, - boost::tie(arg1)).fire_up (); - } - - private: - FunPtr fun_ptr; - }; - - } - - /** - * Overload of the spawn function for - * non-member or static member - * functions with 1 argument. - */ - template - inline - internal::fun_encapsulator,1> - spawn (RT (*fun_ptr)(Arg1)) { - return internal::fun_encapsulator,1> (fun_ptr); - } - - - - -// ----------- encapsulators for binary functions - - namespace internal - { - /** - * Encapsulator class for - * functions with 2 arguments. - */ - template - class fun_encapsulator - { - typedef typename internal::fun_ptr::type FunPtr; - - public: - inline fun_encapsulator (FunPtr fun_ptr) - : fun_ptr(fun_ptr) {} - - inline - Thread - operator() (typename boost::tuples::element<0,ArgList>::type arg1, - typename boost::tuples::element<1,ArgList>::type arg2) { - return fun_wrapper (fun_ptr, - boost::tie(arg1, - arg2)).fire_up (); - } - - private: - FunPtr fun_ptr; - }; - - } - - /** - * Overload of the spawn function for - * non-member or static member - * functions with 2 arguments. - */ - template - inline - internal::fun_encapsulator,2> - spawn (RT (*fun_ptr)(Arg1,Arg2)) { - return internal::fun_encapsulator,2> (fun_ptr); - } - - - -// ----------- encapsulators for ternary functions - - namespace internal - { - /** - * Encapsulator class for - * functions with 3 arguments. - */ - template - class fun_encapsulator - { - typedef typename internal::fun_ptr::type FunPtr; - - public: - inline fun_encapsulator (FunPtr fun_ptr) - : fun_ptr(fun_ptr) {} - - inline - Thread - operator() (typename boost::tuples::element<0,ArgList>::type arg1, - typename boost::tuples::element<1,ArgList>::type arg2, - typename boost::tuples::element<2,ArgList>::type arg3) { - return fun_wrapper (fun_ptr, - boost::tie(arg1, - arg2, - arg3)).fire_up (); - } - - private: - FunPtr fun_ptr; - }; - - } - - /** - * Overload of the spawn function for - * non-member or static member - * functions with 3 arguments. - */ - template - inline - internal::fun_encapsulator,3> - spawn (RT (*fun_ptr)(Arg1,Arg2,Arg3)) { - return internal::fun_encapsulator,3> (fun_ptr); - } - - - - -// ----------- encapsulators for functions with 4 arguments - - namespace internal - { - /** - * Encapsulator class for - * functions with 4 arguments. - */ - template - class fun_encapsulator - { - typedef typename internal::fun_ptr::type FunPtr; - - public: - inline fun_encapsulator (FunPtr fun_ptr) - : fun_ptr(fun_ptr) {} - - inline - Thread - operator() (typename boost::tuples::element<0,ArgList>::type arg1, - typename boost::tuples::element<1,ArgList>::type arg2, - typename boost::tuples::element<2,ArgList>::type arg3, - typename boost::tuples::element<3,ArgList>::type arg4) { - return fun_wrapper (fun_ptr, - boost::tie(arg1,arg2, - arg3,arg4)).fire_up (); - } - - private: - FunPtr fun_ptr; - }; - - } - - /** - * Overload of the spawn function for - * non-member or static member - * functions with 4 arguments. - */ - template - inline - internal::fun_encapsulator,4> - spawn (RT (*fun_ptr)(Arg1,Arg2,Arg3,Arg4)) { - return internal::fun_encapsulator,4> (fun_ptr); - } - - - - -// ----------- encapsulators for functions with 5 arguments - - namespace internal - { - /** - * Encapsulator class for - * functions with 5 arguments. - */ - template - class fun_encapsulator - { - typedef typename internal::fun_ptr::type FunPtr; - - public: - inline fun_encapsulator (FunPtr fun_ptr) - : fun_ptr(fun_ptr) {} - - inline - Thread - operator() (typename boost::tuples::element<0,ArgList>::type arg1, - typename boost::tuples::element<1,ArgList>::type arg2, - typename boost::tuples::element<2,ArgList>::type arg3, - typename boost::tuples::element<3,ArgList>::type arg4, - typename boost::tuples::element<4,ArgList>::type arg5) { - return fun_wrapper (fun_ptr, - boost::tie(arg1,arg2, - arg3,arg4, - arg5)).fire_up (); - } - - private: - FunPtr fun_ptr; - }; - - } - - /** - * Overload of the spawn function for - * non-member or static member - * functions with 5 arguments. - */ - template - inline - internal::fun_encapsulator,5> - spawn (RT (*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5)) { - return internal::fun_encapsulator,5> (fun_ptr); - } - - -// ----------- encapsulators for functions with 6 arguments - - namespace internal - { - /** - * Encapsulator class for - * functions with 6 arguments. - */ - template - class fun_encapsulator - { - typedef typename internal::fun_ptr::type FunPtr; - - public: - inline fun_encapsulator (FunPtr fun_ptr) - : fun_ptr(fun_ptr) {} - - inline - Thread - operator() (typename boost::tuples::element<0,ArgList>::type arg1, - typename boost::tuples::element<1,ArgList>::type arg2, - typename boost::tuples::element<2,ArgList>::type arg3, - typename boost::tuples::element<3,ArgList>::type arg4, - typename boost::tuples::element<4,ArgList>::type arg5, - typename boost::tuples::element<5,ArgList>::type arg6) { - return fun_wrapper (fun_ptr, - boost::tie(arg1,arg2, - arg3,arg4, - arg5,arg6)).fire_up (); - } - - private: - FunPtr fun_ptr; - }; - - } - - /** - * Overload of the spawn function for - * non-member or static member - * functions with 6 arguments. - */ - template - inline - internal::fun_encapsulator,6> - spawn (RT (*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5,Arg6)) { - return internal::fun_encapsulator,6> (fun_ptr); - } - - -// ----------- encapsulators for functions with 7 arguments - - namespace internal - { - /** - * Encapsulator class for - * functions with 7 arguments. - */ - template - class fun_encapsulator - { - typedef typename internal::fun_ptr::type FunPtr; - - public: - inline fun_encapsulator (FunPtr fun_ptr) - : fun_ptr(fun_ptr) {} - - inline - Thread - operator() (typename boost::tuples::element<0,ArgList>::type arg1, - typename boost::tuples::element<1,ArgList>::type arg2, - typename boost::tuples::element<2,ArgList>::type arg3, - typename boost::tuples::element<3,ArgList>::type arg4, - typename boost::tuples::element<4,ArgList>::type arg5, - typename boost::tuples::element<5,ArgList>::type arg6, - typename boost::tuples::element<6,ArgList>::type arg7) { - return fun_wrapper (fun_ptr, - boost::tie(arg1,arg2, - arg3,arg4, - arg5,arg6, - arg7)).fire_up (); - } - - private: - FunPtr fun_ptr; - }; - - } - - /** - * Overload of the spawn function for - * non-member or static member - * functions with 7 arguments. - */ - template - inline - internal::fun_encapsulator,7> - spawn (RT (*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5,Arg6,Arg7)) { - return internal::fun_encapsulator,7> (fun_ptr); - } - - -// ----------- encapsulators for functions with 8 arguments - - namespace internal - { - /** - * Encapsulator class for - * functions with 8 arguments. - */ - template - class fun_encapsulator - { - typedef typename internal::fun_ptr::type FunPtr; - - public: - inline fun_encapsulator (FunPtr fun_ptr) - : fun_ptr(fun_ptr) {} - - inline - Thread - operator() (typename boost::tuples::element<0,ArgList>::type arg1, - typename boost::tuples::element<1,ArgList>::type arg2, - typename boost::tuples::element<2,ArgList>::type arg3, - typename boost::tuples::element<3,ArgList>::type arg4, - typename boost::tuples::element<4,ArgList>::type arg5, - typename boost::tuples::element<5,ArgList>::type arg6, - typename boost::tuples::element<6,ArgList>::type arg7, - typename boost::tuples::element<7,ArgList>::type arg8) { - return fun_wrapper (fun_ptr, - boost::tie(arg1,arg2, - arg3,arg4, - arg5,arg6, - arg7,arg8)).fire_up (); - } - - private: - FunPtr fun_ptr; - }; - - } + /** + * Construct a thread object + * with a pointer to an + * internal thread object. This + * is the constructor used to + * the spawn family of + * functions. + * + * We would like to make this + * constructor private and only + * grant the + * fun_wrapper::fire_up + * function friendship, but + * granting friendship to + * functions in other + * namespaces doesn't work with + * some compilers, so only do + * so if the configure script + * decided that this is safe. + */ +#if defined(DEAL_II_NAMESP_TEMPL_FRIEND_BUG2) || defined(DEAL_II_NAMESP_TEMPL_FRIEND_BUG) + public: +#endif + Thread (const boost::shared_ptr > &td) + : thread_descriptor (td) {} - /** - * Overload of the spawn function for - * non-member or static member - * functions with 8 arguments. - */ - template - inline - internal::fun_encapsulator,8> - spawn (RT (*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5, - Arg6,Arg7,Arg8)) { - return internal::fun_encapsulator,8> (fun_ptr); - } + public: + + /** + * Default constructor. You + * can't do much with a thread + * object constructed this way, + * except for assigning it a + * thread object that holds + * data created by the + * spawn functions. + */ + Thread () {} + /** + * Join the thread represented + * by this object, i.e. wait + * for it to finish. You can't + * call this function if you + * have used the default + * constructor of this class + * and have not assigned a + * thread object to it. + */ + void join () const + { + AssertThrow (thread_descriptor, ExcNoThread()); + thread_descriptor->join (); + } -// ----------- encapsulators for functions with 9 arguments + /** + * Get the return value of the + * function of the + * thread. Since this is only + * available once the thread + * finishes, this implicitely + * also calls join(). + */ + RT return_value () + { + join (); + return thread_descriptor->ret_val.get(); + } - namespace internal - { - /** - * Encapsulator class for - * functions with 9 arguments. - */ - template - class fun_encapsulator - { - typedef typename internal::fun_ptr::type FunPtr; - public: - inline fun_encapsulator (FunPtr fun_ptr) - : fun_ptr(fun_ptr) {} + /** + * Check for equality of thread + * objects. Since objects of + * this class store an implicit + * pointer to an object that + * exists exactly once for each + * thread, the check is simply + * to compare these pointers. + */ + bool operator == (const Thread &t) + { + return thread_descriptor == t.thread_descriptor; + } - inline - Thread - operator() (typename boost::tuples::element<0,ArgList>::type arg1, - typename boost::tuples::element<1,ArgList>::type arg2, - typename boost::tuples::element<2,ArgList>::type arg3, - typename boost::tuples::element<3,ArgList>::type arg4, - typename boost::tuples::element<4,ArgList>::type arg5, - typename boost::tuples::element<5,ArgList>::type arg6, - typename boost::tuples::element<6,ArgList>::type arg7, - typename boost::tuples::element<7,ArgList>::type arg8, - typename boost::tuples::element<8,ArgList>::type arg9) { - return fun_wrapper (fun_ptr, - boost::tie(arg1,arg2, - arg3,arg4, - arg5,arg6, - arg7,arg8, - arg9)).fire_up (); - } - - private: - FunPtr fun_ptr; - }; - - } + /** @addtogroup Exceptions + * @{ */ + + /** + * Exception + */ + DeclException0 (ExcNoThread); + //@} + private: + /** + * Shared pointer to the object + * representing the thread, and + * abstracting operating system + * functions to work on + * it. Boost's shared pointer + * implementation will make + * sure that that object lives + * as long as there is at least + * one subscriber to it. + */ + boost::shared_ptr > thread_descriptor; - /** - * Overload of the spawn function for - * non-member or static member - * functions with 9 arguments. - */ - template - inline - internal::fun_encapsulator,9> - spawn (RT (*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5, - Arg6,Arg7,Arg8,Arg9)) { - return internal::fun_encapsulator,9> (fun_ptr); - } +#if !defined(DEAL_II_NAMESP_TEMPL_FRIEND_BUG2) && !defined(DEAL_II_NAMESP_TEMPL_FRIEND_BUG) + template friend struct internal::fun_wrapper; +#endif + }; -// ----------- encapsulators for functions with 10 arguments namespace internal { /** - * Encapsulator class for - * functions with 10 arguments. + * @internal + * Wrap the arguments to a + * non-member or static member + * function and provide an entry + * point for a new thread that + * unwraps this data and calls + * the function with them. + * + * @author Wolfgang Bangerth, 2003 */ - template - class fun_encapsulator + template + struct fun_wrapper { - typedef typename internal::fun_ptr::type FunPtr; + /** + * Constructor. Store the + * necessary information + * about the function to be + * called and with which + * arguments. + * + * Pass down the address of + * this class's thread entry + * point function. This way, + * we can ensure that object + * and thread entry point + * function always are in + * synch with respect to + * their knowledge of the + * types involved. + */ + fun_wrapper (const boost::function &function) + : function (function) {} - public: - inline fun_encapsulator (FunPtr fun_ptr) - : fun_ptr(fun_ptr) {} - inline - Thread - operator() (typename boost::tuples::element<0,ArgList>::type arg1, - typename boost::tuples::element<1,ArgList>::type arg2, - typename boost::tuples::element<2,ArgList>::type arg3, - typename boost::tuples::element<3,ArgList>::type arg4, - typename boost::tuples::element<4,ArgList>::type arg5, - typename boost::tuples::element<5,ArgList>::type arg6, - typename boost::tuples::element<6,ArgList>::type arg7, - typename boost::tuples::element<7,ArgList>::type arg8, - typename boost::tuples::element<8,ArgList>::type arg9, - typename boost::tuples::element<9,ArgList>::type arg10) { - return fun_wrapper (fun_ptr, - boost::tie(arg1,arg2, - arg3,arg4, - arg5,arg6, - arg7,arg8, - arg9, arg10)).fire_up (); - } - + /** + * Start a new thread, wait + * until it has copied the + * data out of this object, + * and return the thread + * descriptor. + * + * In the non-multithreaded case, + * simply call the function. + */ + Thread fire_up () + { + thread_descriptor = + DescriptionPointer(new internal::thread_description()); + +#if (DEAL_II_USE_MT == 1) + ThreadMutex::ScopedLock lock (mutex); + thread_descriptor->create (&entry_point, (void *)this); + condition.wait (mutex); +#else + call (function, thread_descriptor->ret_val); +#endif + return thread_descriptor; + } + private: - FunPtr fun_ptr; - }; - - } + /** + * Default constructor. Made + * private and not + * implemented to prevent + * calling. + */ + fun_wrapper (); - /** - * Overload of the spawn function for - * non-member or static member - * functions with 10 arguments. - */ - template - inline - internal::fun_encapsulator,10> - spawn (RT (*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5, - Arg6,Arg7,Arg8,Arg9,Arg10)) { - return internal::fun_encapsulator,10> (fun_ptr); - } + /** + * Copy constructor. Made + * private and not + * implemented to prevent + * calling. + */ + fun_wrapper (const fun_wrapper &); -#else // #if (DEAL_II_USE_MT == 1) + /** + * Typedef for shared + * pointers to the objects + * describing threads on the + * OS level. + */ + typedef + boost::shared_ptr > + DescriptionPointer; - template - class Thread - { - public: - /** - * Default constructor. - */ - Thread () {} + /** + * Shared pointer to the + * unique object describing a + * thread on the OS level. + */ + DescriptionPointer thread_descriptor; - /** - * Initialize the return value - * of this object using the - * given member-function - * pointer, object, and - * argument list. - */ - template - Thread (PFun fun_ptr, - C &obj, - ArgRefs arg_refs) - { - internal::call (fun_ptr, obj, arg_refs, rv); - } + /** + * Mutex and condition + * variable used to + * synchronise calling and + * called thread. + */ + mutable ThreadMutex mutex; + mutable ThreadCondition condition; - /** - * Initialize the return value - * of this object using the - * given function pointer, and - * argument list. - */ - template - Thread (PFun fun_ptr, - ArgRefs arg_refs) - { - internal::call (fun_ptr, arg_refs, rv); - } + /** + * Pointer to the function to + * be called on the new + * thread. + */ + boost::function function; - /** - * Get the return value of the - * function of the - * thread. - */ - RT return_value () const - { - return rv.get(); - } + /** + * Entry point for the new + * thread. + */ + static void * entry_point (void *arg) + { + const fun_wrapper *wrapper + = reinterpret_cast*> (arg); - /** - * Join this thread. Is of - * course a no-op in this of no - * thread support. - */ - void join () const {} + // copy information from + // the stack of the + // calling thread + boost::function function = wrapper->function; + + boost::shared_ptr > + thread_descriptor = wrapper->thread_descriptor; + + // signal the fact that + // we have copied all the + // information that is + // needed + { + ThreadMutex::ScopedLock lock (wrapper->mutex); + wrapper->condition.signal (); + } + + // call the + // function. since an + // exception that is + // thrown from one of the + // called functions will + // not propagate to the + // main thread, it will + // kill the program if + // not treated here + // before we return to + // the operating system's + // thread library + internal::register_thread (); + try + { + internal::call (function, thread_descriptor->ret_val); + } + catch (const std::exception &exc) + { + internal::handle_std_exception (exc); + } + catch (...) + { + internal::handle_unknown_exception (); + } + internal::deregister_thread (); + + return 0; + } + + + /** + * Make the base class a + * friend, so that it can + * access the thread entry + * point function. + */ + template friend class wrapper_base; + }; + } - /** - * Compare for equality of - * threads. Since thrheads are - * not supported, there can - * only be exactly one thread, - * and the result is - * true. This function - * doesn't make much sense, - * though, when threads are not - * supported. - */ - bool operator == (const Thread &) - { - return true; - } - - private: - /** - * Store the return value of - * the thread function. - */ - internal::return_value rv; - }; - namespace internal { @@ -5050,9 +1647,12 @@ namespace Threads * @internal * General template declaration * of a class that is used to - * forward arguments to + * encapsulate arguments to * global and static member - * functions. + * functions, make sure a new + * thread is created and that + * function being run on that + * thread. * * Although this general template * is not implemented at all, the @@ -5067,1595 +1667,929 @@ namespace Threads * used, even though we need to * specify it. */ - template - class fun_forwarder; + template + class fun_encapsulator; - /** - * @internal - * General template declaration - * of a class that is used to - * forward arguments to - * non-static member functions. - * - * Although this general template - * is not implemented at all, the - * default template argument - * makes sure that whenever using - * the name of this class, the - * last template argument will be - * computed correctly from the - * previous arguments, and the - * correct specialization for - * this last template argument be - * used, even though we need to - * specify it. - */ - template - class mem_fun_forwarder; - } +// ----------- encapsulators for member functions not taking any parameters - namespace internal - { /** * @internal - * Forwarder class for member + * Encapsulator class for * functions with no arguments. */ - template - class mem_fun_forwarder + template + class fun_encapsulator { - typedef typename internal::mem_fun_ptr::type MemFunPtr; - public: - inline mem_fun_forwarder (C &c, MemFunPtr mem_fun_ptr) - : c (c), mem_fun_ptr(mem_fun_ptr) {} + fun_encapsulator (typename internal::fun_ptr::type *function) + : function (*function) + {} + + fun_encapsulator (const boost::function::type> &function) + : function (function) + {} inline Thread - operator() () { - return Thread (mem_fun_ptr, c, - ArgList()); - } + operator() () + { + return fun_wrapper (function).fire_up (); + } private: - C &c; - MemFunPtr mem_fun_ptr; + boost::function::type> function; }; - } - - /** - * Overload of the non-const spawn - * function for member functions - * with no arguments. This version of the - * function is only visible if - * multithreading is not enabled, but - * it has the exact same interface as - * if multithreading was enabled. - */ - template - inline - internal::mem_fun_forwarder,0> - spawn (C &c, RT (C::*fun_ptr)()) { - return internal::mem_fun_forwarder,0> (c,fun_ptr); - } - - /** - * Overload of the spawn function - * for const member functions with - * no arguments. This version of the - * function is only visible if - * multithreading is not enabled, but - * it has the exact same interface as - * if multithreading was enabled. - */ - template - inline - internal::mem_fun_forwarder,0> - spawn (const C &c, RT (C::*fun_ptr)() const) { - return internal::mem_fun_forwarder,0> (c,fun_ptr); - } - - - - -// ----------- forwarders for unary member functions - - namespace internal - { /** * @internal - * Forwarder class for member + * Encapsulator class for * functions with 1 argument. */ - template - class mem_fun_forwarder + template + class fun_encapsulator { - typedef typename internal::mem_fun_ptr::type MemFunPtr; - public: - inline mem_fun_forwarder (C &c, MemFunPtr mem_fun_ptr) - : c (c), mem_fun_ptr(mem_fun_ptr) {} - - inline - Thread - operator() (typename boost::tuples::element<0,ArgList>::type arg1) { - return Thread (mem_fun_ptr, c, - boost::tie(arg1)); - } - - private: - C &c; - MemFunPtr mem_fun_ptr; - }; - - } - - /** - * Overload of the non-const spawn - * function for member functions with - * 1 argument. This version of the - * function is only visible if - * multithreading is not enabled, but - * it has the exact same interface as - * if multithreading was enabled. - */ - template - inline - internal::mem_fun_forwarder,1> - spawn (C &c, RT (C::*fun_ptr)(Arg1)) { - return internal::mem_fun_forwarder,1> (c,fun_ptr); - } - - /** - * Overload of the spawn function for - * const member functions with 1 - * argument. This version of the - * function is only visible if - * multithreading is not enabled, but - * it has the exact same interface as - * if multithreading was enabled. - */ - template - inline - internal::mem_fun_forwarder,1> - spawn (const C &c, RT (C::*fun_ptr)(Arg1) const) { - return internal::mem_fun_forwarder,1> (c,fun_ptr); - } - - - - -// ----------- forwarders for binary member functions - - namespace internal - { - /** - * @internal - * Forwarder class for member - * functions with 2 - * arguments. - */ - template - class mem_fun_forwarder - { - typedef typename internal::mem_fun_ptr::type MemFunPtr; + fun_encapsulator (typename internal::fun_ptr::type *function) + : function (*function) + {} - public: - inline mem_fun_forwarder (C &c, MemFunPtr mem_fun_ptr) - : c (c), mem_fun_ptr(mem_fun_ptr) {} + fun_encapsulator (const boost::function::type> &function) + : function (function) + {} inline Thread - operator() (typename boost::tuples::element<0,ArgList>::type arg1, - typename boost::tuples::element<1,ArgList>::type arg2) { - return Thread (mem_fun_ptr, c, - boost::tie(arg1, - arg2)); - } + operator() (typename boost::tuples::element<0,ArgList>::type arg1) + { + return fun_wrapper (boost::bind (function, + boost::ref(arg1))).fire_up (); + } private: - C &c; - MemFunPtr mem_fun_ptr; + boost::function::type> function; }; - - } - - /** - * Overload of the non-const spawn - * function for member functions - * with 2 arguments. This version of the - * function is only visible if - * multithreading is not enabled, but - * it has the exact same interface as - * if multithreading was enabled. - */ - template - inline - internal::mem_fun_forwarder,2> - spawn (C &c, RT (C::*fun_ptr)(Arg1,Arg2)) { - return internal::mem_fun_forwarder,2> (c,fun_ptr); - } - - /** - * Overload of the spawn function - * for const member functions with - * 2 arguments. This version of the - * function is only visible if - * multithreading is not enabled, but - * it has the exact same interface as - * if multithreading was enabled. - */ - template - inline - internal::mem_fun_forwarder,2> - spawn (const C &c, RT (C::*fun_ptr)(Arg1,Arg2) const) { - return internal::mem_fun_forwarder,2> (c,fun_ptr); - } - - -// ----------- forwarders for ternary member functions - - namespace internal - { - /** + /** * @internal - * Forwarder class for member - * functions with 3 - * arguments. - */ - template - class mem_fun_forwarder + * Encapsulator class for + * functions with 2 arguments. + */ + template + class fun_encapsulator { - typedef typename internal::mem_fun_ptr::type MemFunPtr; - public: - inline mem_fun_forwarder (C &c, MemFunPtr mem_fun_ptr) - : c (c), mem_fun_ptr(mem_fun_ptr) {} - - inline - Thread - operator() (typename boost::tuples::element<0,ArgList>::type arg1, - typename boost::tuples::element<1,ArgList>::type arg2, - typename boost::tuples::element<2,ArgList>::type arg3) { - return Thread (mem_fun_ptr, c, - boost::tie(arg1, - arg2, - arg3)); - } + fun_encapsulator (typename internal::fun_ptr::type *function) + : function (*function) + {} + + fun_encapsulator (const boost::function::type> &function) + : function (function) + {} + + inline + Thread + operator() (typename boost::tuples::element<0,ArgList>::type arg1, + typename boost::tuples::element<1,ArgList>::type arg2) + { + return fun_wrapper (boost::bind (function, + boost::ref(arg1), + boost::ref(arg2))).fire_up (); + } private: - C &c; - MemFunPtr mem_fun_ptr; + boost::function::type> function; }; - } - - /** - * Overload of the non-const spawn - * function for member functions - * with 3 arguments. This version of the - * function is only visible if - * multithreading is not enabled, but - * it has the exact same interface as - * if multithreading was enabled. - */ - template - inline - internal::mem_fun_forwarder,3> - spawn (C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3)) { - return internal::mem_fun_forwarder,3> (c,fun_ptr); - } - - /** - * Overload of the spawn function - * for const member functions with - * 3 arguments. This version of the - * function is only visible if - * multithreading is not enabled, but - * it has the exact same interface as - * if multithreading was enabled. - */ - template - inline - internal::mem_fun_forwarder,3> - spawn (const C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3) const) { - return internal::mem_fun_forwarder,3> (c,fun_ptr); - } - - - - -// ----------- forwarders for member functions with 4 arguments - - namespace internal - { - /** + /** * @internal - * Forwarder class for member - * functions with 4 - * arguments. - */ - template - class mem_fun_forwarder + * Encapsulator class for + * functions with 3 arguments. + */ + template + class fun_encapsulator { - typedef typename internal::mem_fun_ptr::type MemFunPtr; - public: - inline mem_fun_forwarder (C &c, MemFunPtr mem_fun_ptr) - : c (c), mem_fun_ptr(mem_fun_ptr) {} - - inline - Thread - operator() (typename boost::tuples::element<0,ArgList>::type arg1, - typename boost::tuples::element<1,ArgList>::type arg2, - typename boost::tuples::element<2,ArgList>::type arg3, - typename boost::tuples::element<3,ArgList>::type arg4) { - return Thread (mem_fun_ptr, c, - boost::tie(arg1,arg2, - arg3,arg4)); - } + fun_encapsulator (typename internal::fun_ptr::type *function) + : function (*function) + {} + + fun_encapsulator (const boost::function::type> &function) + : function (function) + {} + + inline + Thread + operator() (typename boost::tuples::element<0,ArgList>::type arg1, + typename boost::tuples::element<1,ArgList>::type arg2, + typename boost::tuples::element<2,ArgList>::type arg3) + { + return fun_wrapper (boost::bind (function, + boost::ref(arg1), + boost::ref(arg2), + boost::ref(arg3))).fire_up (); + } private: - C &c; - MemFunPtr mem_fun_ptr; + boost::function::type> function; }; - } - - /** - * Overload of the non-const spawn - * function for member functions - * with 4 arguments. This version of the - * function is only visible if - * multithreading is not enabled, but - * it has the exact same interface as - * if multithreading was enabled. - */ - template - inline - internal::mem_fun_forwarder,4> - spawn (C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4)) { - return internal::mem_fun_forwarder,4> (c,fun_ptr); - } - - /** - * Overload of the spawn function - * for const member functions with - * 4 arguments. This version of the - * function is only visible if - * multithreading is not enabled, but - * it has the exact same interface as - * if multithreading was enabled. - */ - template - inline - internal::mem_fun_forwarder,4> - spawn (const C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4) const) { - return internal::mem_fun_forwarder,4> (c,fun_ptr); - } - - - - -// ----------- forwarders for member functions with 5 arguments - - namespace internal - { - /** + /** * @internal - * Forwarder class for member - * functions with 5 - * arguments. - */ - template - class mem_fun_forwarder + * Encapsulator class for + * functions with 4 arguments. + */ + template + class fun_encapsulator { - typedef typename internal::mem_fun_ptr::type MemFunPtr; - public: - inline mem_fun_forwarder (C &c, MemFunPtr mem_fun_ptr) - : c (c), mem_fun_ptr(mem_fun_ptr) {} - - inline - Thread - operator() (typename boost::tuples::element<0,ArgList>::type arg1, - typename boost::tuples::element<1,ArgList>::type arg2, - typename boost::tuples::element<2,ArgList>::type arg3, - typename boost::tuples::element<3,ArgList>::type arg4, - typename boost::tuples::element<4,ArgList>::type arg5) { - return Thread (mem_fun_ptr, c, - boost::tie(arg1,arg2, - arg3,arg4, - arg5)); - } + fun_encapsulator (typename internal::fun_ptr::type *function) + : function (*function) + {} + + fun_encapsulator (const boost::function::type> &function) + : function (function) + {} + + inline + Thread + operator() (typename boost::tuples::element<0,ArgList>::type arg1, + typename boost::tuples::element<1,ArgList>::type arg2, + typename boost::tuples::element<2,ArgList>::type arg3, + typename boost::tuples::element<3,ArgList>::type arg4) + { + return fun_wrapper (boost::bind (function, + boost::ref(arg1), + boost::ref(arg2), + boost::ref(arg3), + boost::ref(arg4))).fire_up (); + } private: - C &c; - MemFunPtr mem_fun_ptr; + boost::function::type> function; }; - } - - /** - * Overload of the non-const spawn - * function for member functions - * with 5 arguments. This version of the - * function is only visible if - * multithreading is not enabled, but - * it has the exact same interface as - * if multithreading was enabled. - */ - template - inline - internal::mem_fun_forwarder,5> - spawn (C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5)) { - return internal::mem_fun_forwarder,5> (c,fun_ptr); - } - - /** - * Overload of the spawn function - * for const member functions with - * 5 arguments. This version of the - * function is only visible if - * multithreading is not enabled, but - * it has the exact same interface as - * if multithreading was enabled. - */ - template - inline - internal::mem_fun_forwarder,5> - spawn (const C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5) const) { - return internal::mem_fun_forwarder,5> (c,fun_ptr); - } - - -// ----------- forwarders for member functions with 6 arguments - - namespace internal - { - /** + /** * @internal - * Forwarder class for member - * functions with 6 - * arguments. - */ - template - class mem_fun_forwarder + * Encapsulator class for + * functions with 5 arguments. + */ + template + class fun_encapsulator { - typedef typename internal::mem_fun_ptr::type MemFunPtr; - public: - inline mem_fun_forwarder (C &c, MemFunPtr mem_fun_ptr) - : c (c), mem_fun_ptr(mem_fun_ptr) {} - - inline - Thread - operator() (typename boost::tuples::element<0,ArgList>::type arg1, - typename boost::tuples::element<1,ArgList>::type arg2, - typename boost::tuples::element<2,ArgList>::type arg3, - typename boost::tuples::element<3,ArgList>::type arg4, - typename boost::tuples::element<4,ArgList>::type arg5, - typename boost::tuples::element<5,ArgList>::type arg6) { - return Thread (mem_fun_ptr, c, - boost::tie(arg1,arg2, - arg3,arg4, - arg5,arg6)); - } + fun_encapsulator (typename internal::fun_ptr::type *function) + : function (*function) + {} + + fun_encapsulator (const boost::function::type> &function) + : function (function) + {} + + inline + Thread + operator() (typename boost::tuples::element<0,ArgList>::type arg1, + typename boost::tuples::element<1,ArgList>::type arg2, + typename boost::tuples::element<2,ArgList>::type arg3, + typename boost::tuples::element<3,ArgList>::type arg4, + typename boost::tuples::element<4,ArgList>::type arg5) + { + return fun_wrapper (boost::bind (function, + boost::ref(arg1), + boost::ref(arg2), + boost::ref(arg3), + boost::ref(arg4), + boost::ref(arg5))).fire_up (); + } - private: - C &c; - MemFunPtr mem_fun_ptr; - }; - - } - - /** - * Overload of the non-const spawn - * function for member functions - * with 6 arguments. This version of the - * function is only visible if - * multithreading is not enabled, but - * it has the exact same interface as - * if multithreading was enabled. - */ - template - inline - internal::mem_fun_forwarder,6> - spawn (C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5,Arg6)) { - return internal::mem_fun_forwarder,6> (c,fun_ptr); - } - - /** - * Overload of the spawn function - * for const member functions with - * 6 arguments. This version of the - * function is only visible if - * multithreading is not enabled, but - * it has the exact same interface as - * if multithreading was enabled. - */ - template - inline - internal::mem_fun_forwarder,6> - spawn (const C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5,Arg6) const) { - return internal::mem_fun_forwarder,6> (c,fun_ptr); - } - - -// ----------- forwarders for member functions with 7 arguments - - namespace internal - { - /** + private: + boost::function::type> function; + }; + + /** * @internal - * Forwarder class for member - * functions with 7 - * arguments. - */ - template - class mem_fun_forwarder + * Encapsulator class for + * functions with 6 arguments. + */ + template + class fun_encapsulator { - typedef typename internal::mem_fun_ptr::type MemFunPtr; - public: - inline mem_fun_forwarder (C &c, MemFunPtr mem_fun_ptr) - : c (c), mem_fun_ptr(mem_fun_ptr) {} - - inline - Thread - operator() (typename boost::tuples::element<0,ArgList>::type arg1, - typename boost::tuples::element<1,ArgList>::type arg2, - typename boost::tuples::element<2,ArgList>::type arg3, - typename boost::tuples::element<3,ArgList>::type arg4, - typename boost::tuples::element<4,ArgList>::type arg5, - typename boost::tuples::element<5,ArgList>::type arg6, - typename boost::tuples::element<6,ArgList>::type arg7) { - return Thread (mem_fun_ptr, c, - boost::tie(arg1,arg2, - arg3,arg4, - arg5,arg6, - arg7)); - } + fun_encapsulator (typename internal::fun_ptr::type *function) + : function (*function) + {} + + fun_encapsulator (const boost::function::type> &function) + : function (function) + {} + + inline + Thread + operator() (typename boost::tuples::element<0,ArgList>::type arg1, + typename boost::tuples::element<1,ArgList>::type arg2, + typename boost::tuples::element<2,ArgList>::type arg3, + typename boost::tuples::element<3,ArgList>::type arg4, + typename boost::tuples::element<4,ArgList>::type arg5, + typename boost::tuples::element<5,ArgList>::type arg6) + { + return fun_wrapper (boost::bind (function, + boost::ref(arg1), + boost::ref(arg2), + boost::ref(arg3), + boost::ref(arg4), + boost::ref(arg5), + boost::ref(arg6))).fire_up (); + } private: - C &c; - MemFunPtr mem_fun_ptr; + boost::function::type> function; }; - } - - /** - * Overload of the non-const spawn - * function for member functions - * with 7 arguments. This version of the - * function is only visible if - * multithreading is not enabled, but - * it has the exact same interface as - * if multithreading was enabled. - */ - template - inline - internal::mem_fun_forwarder,7> - spawn (C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5,Arg6,Arg7)) { - return internal::mem_fun_forwarder,7> (c,fun_ptr); - } - - /** - * Overload of the spawn function - * for const member functions with - * 7 arguments. This version of the - * function is only visible if - * multithreading is not enabled, but - * it has the exact same interface as - * if multithreading was enabled. - */ - template - inline - internal::mem_fun_forwarder,7> - spawn (const C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5,Arg6,Arg7) const) { - return internal::mem_fun_forwarder,7> (c,fun_ptr); - } - - -// ----------- forwarders for member functions with 8 arguments - - namespace internal - { - /** + /** * @internal - * Forwarder class for member - * functions with 8 - * arguments. - */ - template - class mem_fun_forwarder + * Encapsulator class for + * functions with 7 arguments. + */ + template + class fun_encapsulator { - typedef typename internal::mem_fun_ptr::type MemFunPtr; - public: - inline mem_fun_forwarder (C &c, MemFunPtr mem_fun_ptr) - : c (c), mem_fun_ptr(mem_fun_ptr) {} - - inline - Thread - operator() (typename boost::tuples::element<0,ArgList>::type arg1, - typename boost::tuples::element<1,ArgList>::type arg2, - typename boost::tuples::element<2,ArgList>::type arg3, - typename boost::tuples::element<3,ArgList>::type arg4, - typename boost::tuples::element<4,ArgList>::type arg5, - typename boost::tuples::element<5,ArgList>::type arg6, - typename boost::tuples::element<6,ArgList>::type arg7, - typename boost::tuples::element<7,ArgList>::type arg8) { - return Thread (mem_fun_ptr, c, - boost::tie(arg1,arg2, - arg3,arg4, - arg5,arg6, - arg7,arg8)); - } + fun_encapsulator (typename internal::fun_ptr::type *function) + : function (*function) + {} + + fun_encapsulator (const boost::function::type> &function) + : function (function) + {} + + inline + Thread + operator() (typename boost::tuples::element<0,ArgList>::type arg1, + typename boost::tuples::element<1,ArgList>::type arg2, + typename boost::tuples::element<2,ArgList>::type arg3, + typename boost::tuples::element<3,ArgList>::type arg4, + typename boost::tuples::element<4,ArgList>::type arg5, + typename boost::tuples::element<5,ArgList>::type arg6, + typename boost::tuples::element<6,ArgList>::type arg7) + { + return fun_wrapper (boost::bind (function, + boost::ref(arg1), + boost::ref(arg2), + boost::ref(arg3), + boost::ref(arg4), + boost::ref(arg5), + boost::ref(arg6), + boost::ref(arg7))).fire_up (); + } private: - C &c; - MemFunPtr mem_fun_ptr; + boost::function::type> function; }; - - } - - /** - * Overload of the non-const spawn - * function for member functions - * with 8 arguments. This version of the - * function is only visible if - * multithreading is not enabled, but - * it has the exact same interface as - * if multithreading was enabled. - */ - template - inline - internal::mem_fun_forwarder,8> - spawn (C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5, - Arg6,Arg7,Arg8)) { - return internal::mem_fun_forwarder,8> (c,fun_ptr); - } - - /** - * Overload of the spawn function - * for const member functions with - * 8 arguments. This version of the - * function is only visible if - * multithreading is not enabled, but - * it has the exact same interface as - * if multithreading was enabled. - */ - template - inline - internal::mem_fun_forwarder,8> - spawn (const C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5, - Arg6,Arg7,Arg8) const) { - return internal::mem_fun_forwarder,8> (c,fun_ptr); - } - - -// ----------- forwarders for member functions with 9 arguments - namespace internal - { - /** + /** * @internal - * Forwarder class for member - * functions with 9 - * arguments. - */ - template - class mem_fun_forwarder + * Encapsulator class for + * functions with 8 arguments. + */ + template + class fun_encapsulator { - typedef typename internal::mem_fun_ptr::type MemFunPtr; - public: - inline mem_fun_forwarder (C &c, MemFunPtr mem_fun_ptr) - : c (c), mem_fun_ptr(mem_fun_ptr) {} - - inline - Thread - operator() (typename boost::tuples::element<0,ArgList>::type arg1, - typename boost::tuples::element<1,ArgList>::type arg2, - typename boost::tuples::element<2,ArgList>::type arg3, - typename boost::tuples::element<3,ArgList>::type arg4, - typename boost::tuples::element<4,ArgList>::type arg5, - typename boost::tuples::element<5,ArgList>::type arg6, - typename boost::tuples::element<6,ArgList>::type arg7, - typename boost::tuples::element<7,ArgList>::type arg8, - typename boost::tuples::element<8,ArgList>::type arg9) { - return Thread (mem_fun_ptr, c, - boost::tie(arg1,arg2, - arg3,arg4, - arg5,arg6, - arg7,arg8, - arg9)); - } + fun_encapsulator (typename internal::fun_ptr::type *function) + : function (*function) + {} + + fun_encapsulator (const boost::function::type> &function) + : function (function) + {} + + inline + Thread + operator() (typename boost::tuples::element<0,ArgList>::type arg1, + typename boost::tuples::element<1,ArgList>::type arg2, + typename boost::tuples::element<2,ArgList>::type arg3, + typename boost::tuples::element<3,ArgList>::type arg4, + typename boost::tuples::element<4,ArgList>::type arg5, + typename boost::tuples::element<5,ArgList>::type arg6, + typename boost::tuples::element<6,ArgList>::type arg7, + typename boost::tuples::element<7,ArgList>::type arg8) + { + return fun_wrapper (boost::bind (function, + boost::ref(arg1), + boost::ref(arg2), + boost::ref(arg3), + boost::ref(arg4), + boost::ref(arg5), + boost::ref(arg6), + boost::ref(arg7), + boost::ref(arg8))).fire_up (); + } private: - C &c; - MemFunPtr mem_fun_ptr; + boost::function::type> function; }; - } - - /** - * Overload of the non-const spawn - * function for member functions - * with 9 arguments. This version of the - * function is only visible if - * multithreading is not enabled, but - * it has the exact same interface as - * if multithreading was enabled. - */ - template - inline - internal::mem_fun_forwarder,9> - spawn (C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5, - Arg6,Arg7,Arg8,Arg9)) { - return internal::mem_fun_forwarder,9> (c,fun_ptr); - } - - /** - * Overload of the spawn function - * for const member functions with - * 9 arguments. This version of the - * function is only visible if - * multithreading is not enabled, but - * it has the exact same interface as - * if multithreading was enabled. - */ - template - inline - internal::mem_fun_forwarder,9> - spawn (const C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5, - Arg6,Arg7,Arg8,Arg9) const) { - return internal::mem_fun_forwarder,9> (c,fun_ptr); - } - - -// ----------- forwarders for member functions with 10 arguments - - namespace internal - { - /** + /** * @internal - * Forwarder class for member - * functions with 10 - * arguments. - */ - template - class mem_fun_forwarder + * Encapsulator class for + * functions with 9 arguments. + */ + template + class fun_encapsulator { - typedef typename internal::mem_fun_ptr::type MemFunPtr; - public: - inline mem_fun_forwarder (C &c, MemFunPtr mem_fun_ptr) - : c (c), mem_fun_ptr(mem_fun_ptr) {} - - inline - Thread - operator() (typename boost::tuples::element<0,ArgList>::type arg1, - typename boost::tuples::element<1,ArgList>::type arg2, - typename boost::tuples::element<2,ArgList>::type arg3, - typename boost::tuples::element<3,ArgList>::type arg4, - typename boost::tuples::element<4,ArgList>::type arg5, - typename boost::tuples::element<5,ArgList>::type arg6, - typename boost::tuples::element<6,ArgList>::type arg7, - typename boost::tuples::element<7,ArgList>::type arg8, - typename boost::tuples::element<8,ArgList>::type arg9, - typename boost::tuples::element<9,ArgList>::type arg10) { - return Thread (mem_fun_ptr, c, - boost::tie(arg1,arg2, - arg3,arg4, - arg5,arg6, - arg7,arg8, - arg9, arg10)); - } + fun_encapsulator (typename internal::fun_ptr::type *function) + : function (*function) + {} + + fun_encapsulator (const boost::function::type> &function) + : function (function) + {} + + inline + Thread + operator() (typename boost::tuples::element<0,ArgList>::type arg1, + typename boost::tuples::element<1,ArgList>::type arg2, + typename boost::tuples::element<2,ArgList>::type arg3, + typename boost::tuples::element<3,ArgList>::type arg4, + typename boost::tuples::element<4,ArgList>::type arg5, + typename boost::tuples::element<5,ArgList>::type arg6, + typename boost::tuples::element<6,ArgList>::type arg7, + typename boost::tuples::element<7,ArgList>::type arg8, + typename boost::tuples::element<8,ArgList>::type arg9) + { + return fun_wrapper (boost::bind (function, + boost::ref(arg1), + boost::ref(arg2), + boost::ref(arg3), + boost::ref(arg4), + boost::ref(arg5), + boost::ref(arg6), + boost::ref(arg7), + boost::ref(arg8), + boost::ref(arg9))).fire_up (); + } private: - C &c; - MemFunPtr mem_fun_ptr; + boost::function::type> function; }; - } + + + +// ----------- encapsulators for functions not taking any parameters + /** - * Overload of the non-const spawn - * function for member functions - * with 10 arguments. This version of the - * function is only visible if - * multithreading is not enabled, but - * it has the exact same interface as - * if multithreading was enabled. + * Overload of the spawn function for + * non-member or static member + * functions with no arguments. */ - template + template inline - internal::mem_fun_forwarder,10> - spawn (C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5, - Arg6,Arg7,Arg8,Arg9,Arg10)) { - return internal::mem_fun_forwarder,10> (c,fun_ptr); + internal::fun_encapsulator,0> + spawn (RT (*fun_ptr)()) + { + return fun_ptr; } + /** - * Overload of the spawn function - * for const member functions with - * 10 arguments. This version of the - * function is only visible if - * multithreading is not enabled, but - * it has the exact same interface as - * if multithreading was enabled. + * Overload of the non-const spawn + * function for member functions with + * no arguments. */ - template + template inline - internal::mem_fun_forwarder,10> - spawn (const C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5, - Arg6,Arg7,Arg8,Arg9,Arg10) const) { - return internal::mem_fun_forwarder,10> (c,fun_ptr); - } - - - -// ----------- forwarders for functions not taking any parameters - - namespace internal + internal::fun_encapsulator,0> + spawn (C &c, RT (C::*fun_ptr)()) { - /** - * @internal - * Forwarder class for functions - * with no arguments. - */ - template - class fun_forwarder - { - typedef typename internal::fun_ptr::type FunPtr; - - public: - inline fun_forwarder (FunPtr fun_ptr) - : fun_ptr(fun_ptr) {} - - inline - Thread - operator() () { - return Thread (fun_ptr, - ArgList()); - } - - private: - FunPtr fun_ptr; - }; - + return + boost::function >::type> + (boost::bind(fun_ptr, boost::ref(c))); } - + /** - * Overload of the spawn function - * for non-member or static member - * functions with no - * arguments. This version of the - * function is only visible if * - * multithreading is not enabled, - * but * it has the exact same - * interface as * if multithreading - * was enabled. + * Overload of the spawn function for + * const member functions with no + * arguments. */ - template + template inline - internal::fun_forwarder,0> - spawn (RT (*fun_ptr)()) { - return internal::fun_forwarder,0> (fun_ptr); + internal::fun_encapsulator,0> + spawn (const C &c, RT (C::*fun_ptr)() const) + { + return + boost::function >::type> + (boost::bind(fun_ptr, boost::cref(c))); } + +// ----------- encapsulators for unary functions -// ----------- forwarders for unary functions - - namespace internal - { - /** - * @internal - * Forwarder class for functions - * with 1 argument. - */ - template - class fun_forwarder - { - typedef typename internal::fun_ptr::type FunPtr; - - public: - inline fun_forwarder (FunPtr fun_ptr) - : fun_ptr(fun_ptr) {} - - inline - Thread - operator() (typename boost::tuples::element<0,ArgList>::type arg1) { - return Thread (fun_ptr, - boost::tie(arg1)); - } - - private: - FunPtr fun_ptr; - }; - - } - /** - * Overload of the spawn function - * for non-member or static member - * functions with 1 argument. This version of the - * function is only visible if - * multithreading is not enabled, but - * it has the exact same interface as - * if multithreading was enabled. + * Overload of the spawn function for + * non-member or static member + * functions with 1 argument. */ template inline - internal::fun_forwarder,1> - spawn (RT (*fun_ptr)(Arg1)) { - return internal::fun_forwarder,1> (fun_ptr); + internal::fun_encapsulator,1> + spawn (RT (*fun_ptr)(Arg1)) + { + return fun_ptr; } + /** + * Overload of the non-const spawn + * function for member functions with + * 1 argument. + */ + template + inline + internal::fun_encapsulator,1> + spawn (C &c, RT (C::*fun_ptr)(Arg1)) + { + return + boost::function >::type> + (boost::bind(fun_ptr, boost::ref(c), _1)); + } -// ----------- forwarders for binary functions - - namespace internal + /** + * Overload of the spawn function for + * const member functions with 1 + * argument. + */ + template + inline + internal::fun_encapsulator,1> + spawn (const C &c, RT (C::*fun_ptr)(Arg1) const) { - /** - * @internal - * Forwarder class for functions - * with 2 arguments. - */ - template - class fun_forwarder - { - typedef typename internal::fun_ptr::type FunPtr; + return + boost::function >::type> + (boost::bind(fun_ptr, boost::cref(c), _1)); + } - public: - inline fun_forwarder (FunPtr fun_ptr) - : fun_ptr(fun_ptr) {} - inline - Thread - operator() (typename boost::tuples::element<0,ArgList>::type arg1, - typename boost::tuples::element<1,ArgList>::type arg2) { - return Thread (fun_ptr, - boost::tie(arg1, - arg2)); - } - - private: - FunPtr fun_ptr; - }; - - } +// ----------- encapsulators for binary functions /** - * Overload of the spawn function - * for non-member or static member - * functions with 2 arguments. This version of the - * function is only visible if - * multithreading is not enabled, but - * it has the exact same interface as - * if multithreading was enabled. + * Overload of the spawn function for + * non-member or static member + * functions with 2 arguments. */ template inline - internal::fun_forwarder,2> - spawn (RT (*fun_ptr)(Arg1,Arg2)) { - return internal::fun_forwarder,2> (fun_ptr); + internal::fun_encapsulator,2> + spawn (RT (*fun_ptr)(Arg1,Arg2)) + { + return fun_ptr; } -// ----------- forwarders for ternary functions - - namespace internal + /** + * Overload of the non-const spawn + * function for member functions with + * 2 arguments. + */ + template + inline + internal::fun_encapsulator,2> + spawn (C &c, RT (C::*fun_ptr)(Arg1,Arg2)) { - /** - * @internal - * Forwarder class for functions - * with 3 arguments. - */ - template - class fun_forwarder - { - typedef typename internal::fun_ptr::type FunPtr; + return + boost::function >::type> + (boost::bind(fun_ptr, boost::ref(c), _1, _2)); + } + + /** + * Overload of the spawn function for + * const member functions with 2 + * arguments. + */ + template + inline + internal::fun_encapsulator,2> + spawn (const C &c, RT (C::*fun_ptr)(Arg1,Arg2) const) + { + return + boost::function >::type> + (boost::bind(fun_ptr, boost::cref(c), _1, _2)); + } - public: - inline fun_forwarder (FunPtr fun_ptr) - : fun_ptr(fun_ptr) {} - inline - Thread - operator() (typename boost::tuples::element<0,ArgList>::type arg1, - typename boost::tuples::element<1,ArgList>::type arg2, - typename boost::tuples::element<2,ArgList>::type arg3) { - return Thread (fun_ptr, - boost::tie(arg1, - arg2, - arg3)); - } - - private: - FunPtr fun_ptr; - }; - - } +// ----------- encapsulators for ternary functions /** - * Overload of the spawn function - * for non-member or static member - * functions with 3 arguments. This version of the - * function is only visible if - * multithreading is not enabled, but - * it has the exact same interface as - * if multithreading was enabled. + * Overload of the spawn function for + * non-member or static member + * functions with 3 arguments. */ template inline - internal::fun_forwarder,3> - spawn (RT (*fun_ptr)(Arg1,Arg2,Arg3)) { - return internal::fun_forwarder,3> (fun_ptr); + internal::fun_encapsulator,3> + spawn (RT (*fun_ptr)(Arg1,Arg2,Arg3)) + { + return fun_ptr; } + /** + * Overload of the non-const spawn + * function for member functions with + * 3 arguments. + */ + template + inline + internal::fun_encapsulator,3> + spawn (C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3)) + { + return + boost::function >::type> + (boost::bind(fun_ptr, boost::ref(c), _1, _2, _3)); + } -// ----------- forwarders for functions with 4 arguments - - namespace internal + /** + * Overload of the spawn function for + * const member functions with 3 + * arguments. + */ + template + inline + internal::fun_encapsulator,3> + spawn (const C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3) const) { - /** - * @internal - * Forwarder class for functions - * with 4 arguments. - */ - template - class fun_forwarder - { - typedef typename internal::fun_ptr::type FunPtr; + return + boost::function >::type> + (boost::bind(fun_ptr, boost::cref(c), _1, _2, _3)); + } - public: - inline fun_forwarder (FunPtr fun_ptr) - : fun_ptr(fun_ptr) {} - inline - Thread - operator() (typename boost::tuples::element<0,ArgList>::type arg1, - typename boost::tuples::element<1,ArgList>::type arg2, - typename boost::tuples::element<2,ArgList>::type arg3, - typename boost::tuples::element<3,ArgList>::type arg4) { - return Thread (fun_ptr, - boost::tie(arg1,arg2, - arg3,arg4)); - } - - private: - FunPtr fun_ptr; - }; - - } + +// ----------- encapsulators for functions with 4 arguments /** - * Overload of the spawn function - * for non-member or static member - * functions with 4 arguments. This version of the - * function is only visible if - * multithreading is not enabled, but - * it has the exact same interface as - * if multithreading was enabled. + * Overload of the spawn function for + * non-member or static member + * functions with 4 arguments. */ template inline - internal::fun_forwarder,4> - spawn (RT (*fun_ptr)(Arg1,Arg2,Arg3,Arg4)) { - return internal::fun_forwarder,4> (fun_ptr); + internal::fun_encapsulator,4> + spawn (RT (*fun_ptr)(Arg1,Arg2,Arg3,Arg4)) + { + return fun_ptr; } + /** + * Overload of the non-const spawn + * function for member functions with + * 4 arguments. + */ + template + inline + internal::fun_encapsulator,4> + spawn (C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4)) + { + return + boost::function >::type> + (boost::bind(fun_ptr, boost::ref(c), _1, _2, _3, _4)); + } -// ----------- forwarders for functions with 5 arguments - - namespace internal + /** + * Overload of the spawn function for + * const member functions with 4 + * arguments. + */ + template + inline + internal::fun_encapsulator,4> + spawn (const C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4) const) { - /** - * @internal - * Forwarder class for functions - * with 5 arguments. - */ - template - class fun_forwarder - { - typedef typename internal::fun_ptr::type FunPtr; + return + boost::function >::type> + (boost::bind(fun_ptr, boost::cref(c), _1, _2, _3, _4)); + } - public: - inline fun_forwarder (FunPtr fun_ptr) - : fun_ptr(fun_ptr) {} - inline - Thread - operator() (typename boost::tuples::element<0,ArgList>::type arg1, - typename boost::tuples::element<1,ArgList>::type arg2, - typename boost::tuples::element<2,ArgList>::type arg3, - typename boost::tuples::element<3,ArgList>::type arg4, - typename boost::tuples::element<4,ArgList>::type arg5) { - return Thread (fun_ptr, - boost::tie(arg1,arg2, - arg3,arg4, - arg5)); - } - - private: - FunPtr fun_ptr; - }; - - } +// ----------- encapsulators for functions with 5 arguments /** - * Overload of the spawn function - * for non-member or static member - * functions with 5 arguments. This version of the - * function is only visible if - * multithreading is not enabled, but - * it has the exact same interface as - * if multithreading was enabled. + * Overload of the spawn function for + * non-member or static member + * functions with 5 arguments. */ template inline - internal::fun_forwarder,5> - spawn (RT (*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5)) { - return internal::fun_forwarder,5> (fun_ptr); + internal::fun_encapsulator,5> + spawn (RT (*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5)) + { + return fun_ptr; } -// ----------- forwarders for functions with 6 arguments - namespace internal + /** + * Overload of the non-const spawn + * function for member functions with + * 5 arguments. + */ + template + inline + internal::fun_encapsulator,5> + spawn (C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5)) { - /** - * @internal - * Forwarder class for functions - * with 6 arguments. - */ - template - class fun_forwarder - { - typedef typename internal::fun_ptr::type FunPtr; - - public: - inline fun_forwarder (FunPtr fun_ptr) - : fun_ptr(fun_ptr) {} + return + boost::function >::type> + (boost::bind(fun_ptr, boost::ref(c), _1, _2, _3, _4, _5)); + } - inline - Thread - operator() (typename boost::tuples::element<0,ArgList>::type arg1, - typename boost::tuples::element<1,ArgList>::type arg2, - typename boost::tuples::element<2,ArgList>::type arg3, - typename boost::tuples::element<3,ArgList>::type arg4, - typename boost::tuples::element<4,ArgList>::type arg5, - typename boost::tuples::element<5,ArgList>::type arg6) { - return Thread (fun_ptr, - boost::tie(arg1,arg2, - arg3,arg4, - arg5,arg6)); - } - - private: - FunPtr fun_ptr; - }; - + /** + * Overload of the spawn function for + * const member functions with 5 + * arguments. + */ + template + inline + internal::fun_encapsulator,5> + spawn (const C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5) const) + { + return + boost::function >::type> + (boost::bind(fun_ptr, boost::cref(c), _1, _2, _3, _4, _5)); } + + +// ----------- encapsulators for functions with 6 arguments /** - * Overload of the spawn function - * for non-member or static member - * functions with 6 arguments. This version of the - * function is only visible if - * multithreading is not enabled, but - * it has the exact same interface as - * if multithreading was enabled. + * Overload of the spawn function for + * non-member or static member + * functions with 6 arguments. */ template inline - internal::fun_forwarder,6> - spawn (RT (*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5,Arg6)) { - return internal::fun_forwarder,6> (fun_ptr); + internal::fun_encapsulator,6> + spawn (RT (*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5,Arg6)) + { + return fun_ptr; } -// ----------- forwarders for functions with 7 arguments - namespace internal + /** + * Overload of the non-const spawn + * function for member functions with + * 6 arguments. + */ + template + inline + internal::fun_encapsulator,6> + spawn (C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5,Arg6)) { - /** - * @internal - * Forwarder class for functions - * with 7 arguments. - */ - template - class fun_forwarder - { - typedef typename internal::fun_ptr::type FunPtr; - - public: - inline fun_forwarder (FunPtr fun_ptr) - : fun_ptr(fun_ptr) {} + return + boost::function >::type> + (boost::bind(fun_ptr, boost::ref(c), _1, _2, _3, _4, _5, _6)); + } - inline - Thread - operator() (typename boost::tuples::element<0,ArgList>::type arg1, - typename boost::tuples::element<1,ArgList>::type arg2, - typename boost::tuples::element<2,ArgList>::type arg3, - typename boost::tuples::element<3,ArgList>::type arg4, - typename boost::tuples::element<4,ArgList>::type arg5, - typename boost::tuples::element<5,ArgList>::type arg6, - typename boost::tuples::element<6,ArgList>::type arg7) { - return Thread (fun_ptr, - boost::tie(arg1,arg2, - arg3,arg4, - arg5,arg6, - arg7)); - } - - private: - FunPtr fun_ptr; - }; - + /** + * Overload of the spawn function for + * const member functions with 6 + * arguments. + */ + template + inline + internal::fun_encapsulator,6> + spawn (const C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5,Arg6) const) + { + return + boost::function >::type> + (boost::bind(fun_ptr, boost::cref(c), _1, _2, _3, _4, _5, _6)); } + + +// ----------- encapsulators for functions with 7 arguments /** - * Overload of the spawn function - * for non-member or static member - * functions with 7 arguments. This version of the - * function is only visible if - * multithreading is not enabled, but - * it has the exact same interface as - * if multithreading was enabled. + * Overload of the spawn function for + * non-member or static member + * functions with 7 arguments. */ template inline - internal::fun_forwarder,7> - spawn (RT (*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5,Arg6,Arg7)) { - return internal::fun_forwarder,7> (fun_ptr); + internal::fun_encapsulator,7> + spawn (RT (*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5,Arg6,Arg7)) + { + return fun_ptr; } -// ----------- forwarders for functions with 8 arguments - namespace internal + /** + * Overload of the non-const spawn + * function for member functions with + * 7 arguments. + */ + template + inline + internal::fun_encapsulator,7> + spawn (C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5,Arg6,Arg7)) { - /** - * @internal - * Forwarder class for functions - * with 8 arguments. - */ - template - class fun_forwarder - { - typedef typename internal::fun_ptr::type FunPtr; - - public: - inline fun_forwarder (FunPtr fun_ptr) - : fun_ptr(fun_ptr) {} + return + boost::function >::type> + (boost::bind(fun_ptr, boost::ref(c), _1, _2, _3, _4, _5, _6, _7)); + } - inline - Thread - operator() (typename boost::tuples::element<0,ArgList>::type arg1, - typename boost::tuples::element<1,ArgList>::type arg2, - typename boost::tuples::element<2,ArgList>::type arg3, - typename boost::tuples::element<3,ArgList>::type arg4, - typename boost::tuples::element<4,ArgList>::type arg5, - typename boost::tuples::element<5,ArgList>::type arg6, - typename boost::tuples::element<6,ArgList>::type arg7, - typename boost::tuples::element<7,ArgList>::type arg8) { - return Thread (fun_ptr, - boost::tie(arg1,arg2, - arg3,arg4, - arg5,arg6, - arg7,arg8)); - } - - private: - FunPtr fun_ptr; - }; - + /** + * Overload of the spawn function for + * const member functions with 7 + * arguments. + */ + template + inline + internal::fun_encapsulator,7> + spawn (const C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5,Arg6,Arg7) const) + { + return + boost::function >::type> + (boost::bind(fun_ptr, boost::cref(c), _1, _2, _3, _4, _5, _6, _7)); } + + +// ----------- encapsulators for functions with 8 arguments /** - * Overload of the spawn function - * for non-member or static member - * functions with 8 arguments. This version of the - * function is only visible if - * multithreading is not enabled, but - * it has the exact same interface as - * if multithreading was enabled. + * Overload of the spawn function for + * non-member or static member + * functions with 8 arguments. */ template inline - internal::fun_forwarder,8> + internal::fun_encapsulator,8> spawn (RT (*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5, - Arg6,Arg7,Arg8)) { - return internal::fun_forwarder,8> (fun_ptr); + Arg6,Arg7,Arg8)) + { + return fun_ptr; } -// ----------- forwarders for functions with 9 arguments - namespace internal + /** + * Overload of the non-const spawn + * function for member functions with + * 8 arguments. + */ + template + inline + internal::fun_encapsulator,8> + spawn (C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5, + Arg6,Arg7,Arg8)) { - /** - * @internal - * Forwarder class for functions - * with 9 arguments. - */ - template - class fun_forwarder - { - typedef typename internal::fun_ptr::type FunPtr; - - public: - inline fun_forwarder (FunPtr fun_ptr) - : fun_ptr(fun_ptr) {} + return + boost::function >::type> + (boost::bind(fun_ptr, boost::ref(c), _1, _2, _3, _4, _5, _6, _7, _8)); + } - inline - Thread - operator() (typename boost::tuples::element<0,ArgList>::type arg1, - typename boost::tuples::element<1,ArgList>::type arg2, - typename boost::tuples::element<2,ArgList>::type arg3, - typename boost::tuples::element<3,ArgList>::type arg4, - typename boost::tuples::element<4,ArgList>::type arg5, - typename boost::tuples::element<5,ArgList>::type arg6, - typename boost::tuples::element<6,ArgList>::type arg7, - typename boost::tuples::element<7,ArgList>::type arg8, - typename boost::tuples::element<8,ArgList>::type arg9) { - return Thread (fun_ptr, - boost::tie(arg1,arg2, - arg3,arg4, - arg5,arg6, - arg7,arg8, - arg9)); - } - - private: - FunPtr fun_ptr; - }; - + /** + * Overload of the spawn function for + * const member functions with 8 + * arguments. + */ + template + inline + internal::fun_encapsulator,8> + spawn (const C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5, + Arg6,Arg7,Arg8) const) + { + return + boost::function >::type> + (boost::bind(fun_ptr, boost::cref(c), _1, _2, _3, _4, _5, _6, _7, _8)); } + + +// ----------- encapsulators for functions with 9 arguments /** - * Overload of the spawn function - * for non-member or static member - * functions with 9 arguments. This version of the - * function is only visible if - * multithreading is not enabled, but - * it has the exact same interface as - * if multithreading was enabled. + * Overload of the spawn function for + * non-member or static member + * functions with 9 arguments. */ template inline - internal::fun_forwarder,9> + internal::fun_encapsulator,9> spawn (RT (*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5, - Arg6,Arg7,Arg8,Arg9)) { - return internal::fun_forwarder,9> (fun_ptr); + Arg6,Arg7,Arg8,Arg9)) + { + return fun_ptr; } -// ----------- forwarders for functions with 10 arguments - namespace internal + /** + * Overload of the non-const spawn + * function for member functions with + * 9 arguments. + */ + template + inline + internal::fun_encapsulator,9> + spawn (C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5, + Arg6,Arg7,Arg8,Arg9)) { - /** - * @internal - * Forwarder class for functions - * with 10 arguments. - */ - template - class fun_forwarder - { - typedef typename internal::fun_ptr::type FunPtr; - - public: - inline fun_forwarder (FunPtr fun_ptr) - : fun_ptr(fun_ptr) {} - - inline - Thread - operator() (typename boost::tuples::element<0,ArgList>::type arg1, - typename boost::tuples::element<1,ArgList>::type arg2, - typename boost::tuples::element<2,ArgList>::type arg3, - typename boost::tuples::element<3,ArgList>::type arg4, - typename boost::tuples::element<4,ArgList>::type arg5, - typename boost::tuples::element<5,ArgList>::type arg6, - typename boost::tuples::element<6,ArgList>::type arg7, - typename boost::tuples::element<7,ArgList>::type arg8, - typename boost::tuples::element<8,ArgList>::type arg9, - typename boost::tuples::element<9,ArgList>::type arg10) { - return Thread (fun_ptr, - boost::tie(arg1,arg2, - arg3,arg4, - arg5,arg6, - arg7,arg8, - arg9, arg10)); - } - - private: - FunPtr fun_ptr; - }; - + return + boost::function >::type> + (boost::bind(fun_ptr, boost::ref(c), _1, _2, _3, _4, _5, _6, _7, _8, _9)); } - /** - * Overload of the spawn function - * for non-member or static member - * functions with 10 - * arguments. This version of the - * function is only visible if - * multithreading is not enabled, but - * it has the exact same interface as - * if multithreading was enabled. - */ - template - inline - internal::fun_forwarder,10> - spawn (RT (*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5, - Arg6,Arg7,Arg8,Arg9,Arg10)) { - return internal::fun_forwarder,10> (fun_ptr); + /** + * Overload of the spawn function for + * const member functions with 9 + * arguments. + */ + template + inline + internal::fun_encapsulator,9> + spawn (const C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5, + Arg6,Arg7,Arg8,Arg9) const) + { + return + boost::function >::type> + (boost::bind(fun_ptr, boost::cref(c), _1, _2, _3, _4, _5, _6, _7, _8, _9)); } - -#endif // #if (DEAL_II_USE_MT == 1) - - /** * A container for thread @@ -6675,10 +2609,11 @@ namespace Threads * Add another thread object to * the collection. */ - ThreadGroup & operator += (const Thread &t) { - threads.push_back (t); - return *this; - } + ThreadGroup & operator += (const Thread &t) + { + threads.push_back (t); + return *this; + } /** * Wait for all threads in the diff --git a/deal.II/doc/news/changes.h b/deal.II/doc/news/changes.h index 4021a05e9f..41fc331162 100644 --- a/deal.II/doc/news/changes.h +++ b/deal.II/doc/news/changes.h @@ -30,6 +30,21 @@ inconvenience this causes.

    +
  1. +

    + Changed: The way we set up threads in the Threads::spawn functions + and friends has been completely written, using the boost::bind and + boost::function libraries. This has made things significantly simpler + and allowed us to remove some 4,100 lines of code. The only + user-visible side effect is that you can now no longer spawn + functions with 10 arguments (this was the maximum before) whereas 9 + arguments continues to work; the reason for this is a limitation in + the boost::bind library. This limit will be lifted with the next + C++ standard, however, using variadic templates. +
    + (WB 2008/08/28) +

    +
  2. Changed: The SolutionTransfer class used to take a type as second