From a76503d470ac66a2d543ad843cd6f3ae6391414f Mon Sep 17 00:00:00 2001 From: wolf Date: Thu, 6 Feb 2003 18:14:39 +0000 Subject: [PATCH] Merge the new threading scheme. git-svn-id: https://svn.dealii.org/trunk@7060 0785d39b-7218-0410-832d-ea1e28bc413d --- deal.II/aclocal.m4 | 157 +- deal.II/base/include/base/config.h.in | 6 + deal.II/base/include/base/thread_management.h | 13171 +++++++--------- deal.II/base/source/data_out_base.cc | 36 +- deal.II/base/source/thread_management.cc | 537 +- deal.II/common/Make.global_options.in | 12 +- deal.II/configure | 263 +- deal.II/configure.in | 2 + deal.II/contrib/hsl/source/detached_ma27.cc | 20 +- deal.II/deal.II/source/dofs/dof_tools.cc | 26 +- deal.II/deal.II/source/grid/grid_generator.cc | 8 +- .../deal.II/source/multigrid/mg_dof_tools.cc | 10 +- deal.II/deal.II/source/numerics/data_out.cc | 8 +- .../deal.II/source/numerics/data_out_faces.cc | 8 +- .../source/numerics/data_out_rotation.cc | 9 +- .../numerics/derivative_approximation.cc | 12 +- .../source/numerics/error_estimator.cc | 19 +- deal.II/deal.II/source/numerics/matrices.cc | 58 +- .../deal.II/source/numerics/time_dependent.cc | 14 +- deal.II/examples/step-13/step-13.cc | 36 +- deal.II/examples/step-14/step-14.cc | 59 +- deal.II/examples/step-9/step-9.cc | 175 +- .../lac/include/lac/sparse_matrix.templates.h | 58 +- .../lac/include/lac/sparse_vanka.templates.h | 22 +- deal.II/lac/include/lac/swappable_vector.h | 12 - .../include/lac/swappable_vector.templates.h | 14 +- tests/base/Makefile | 8 +- 27 files changed, 6460 insertions(+), 8300 deletions(-) diff --git a/deal.II/aclocal.m4 b/deal.II/aclocal.m4 index fae35f911a..37b378a1b7 100644 --- a/deal.II/aclocal.m4 +++ b/deal.II/aclocal.m4 @@ -228,6 +228,9 @@ AC_DEFUN(DEAL_II_SET_CXX_FLAGS, dnl CXXFLAGSO="$CXXFLAGS -O2 -Wuninitialized -felide-constructors -ftemplate-depth-32" CXXFLAGSG="$CXXFLAGS -DDEBUG -pedantic -Wall -W -Wpointer-arith -Wwrite-strings -Wmissing-prototypes -Winline -Woverloaded-virtual -Wstrict-prototypes -Wsynth -Wsign-compare -Wconversion -Wswitch -ftemplate-depth-32" + dnl BOOST uses long long, so don't warn about this + CXXFLAGSG="$CXXFLAGSG -Wno-long-long" + dnl Set PIC flags. On some systems, -fpic/PIC is implied, so don't set dnl anything to avoid a warning case "$target" in @@ -297,12 +300,36 @@ AC_DEFUN(DEAL_II_SET_CXX_FLAGS, dnl CXXFLAGSG="`echo $CXXFLAGSG | perl -pi -e 's/-W //g;'`" fi - dnl Use -Wno-long-long on Apple Darwin to avoid some unnecessary warning + dnl Some system specific things case "$target" in + dnl Use -Wno-long-long on Apple Darwin to avoid some unnecessary warning *apple-darwin*) CXXFLAGSG="$CXXFLAGSG -Wno-long-double" CXXFLAGSO="$CXXFLAGSO -Wno-long-double" ;; + + dnl On DEC OSF, including both stdio.h and unistd.h causes a warning + dnl from the preprocessor that cuserid is redefined as a preprocessor + dnl variable. Suppress this if necessary by switching off warnings + dnl from the preprocessor + *dec-osf*) + AC_MSG_CHECKING(for preprocessor warning with cuserid) + CXXFLAGS="$CXXFLAGSG -Werror" + AC_TRY_COMPILE( + [ +# include +# include + ], + [;], + [ + AC_MSG_RESULT(no) + ], + [ + AC_MSG_RESULT(yes) + CXXFLAGSG="$CXXFLAGSG -Wp,-w" + CXXFLAGSO="$CXXFLAGSO -Wp,-w" + ]) + ;; esac dnl In order to link shared libraries, almost all versions of gcc can @@ -405,6 +432,8 @@ AC_DEFUN(DEAL_II_SET_CXX_FLAGS, dnl dnl #1182:`statement either is unreachable or causes unreachable code' dnl (happens in switch(dim) clauses for other dimensions than dnl the present one) + dnl #450:`the type "long long" is nonstandard' + dnl BOOST uses long long, unfortunately dnl dnl Also disable the following error: dnl #265: `class "..." is inaccessible' (happens when we try to @@ -423,11 +452,12 @@ AC_DEFUN(DEAL_II_SET_CXX_FLAGS, dnl CXXFLAGSG="$CXXFLAGS -model ansi -std strict_ansi -w1 -msg_display_number -timplicit_local -DDEBUG" CXXFLAGSO="$CXXFLAGS -model ansi -std strict_ansi -w2 -msg_display_number -timplicit_local -fast" - for i in 175 236 237 381 487 1136 1156 111 1182 265 ; do + for i in 175 236 237 381 487 1136 1156 111 1182 265 450 ; do CXXFLAGSG="$CXXFLAGSG -msg_disable $i" CXXFLAGSO="$CXXFLAGSO -msg_disable $i" done + dnl If we use -model ansi to compile the files, we also have to dnl specify it for linking LDFLAGS="$LDFLAGS -model ansi" @@ -481,7 +511,7 @@ AC_DEFUN(DEAL_II_SET_CXX_FLAGS, dnl ;; borland_bcc) - CXXFLAGSG="$CXXFLAGS -q -DDEBUG -w -w-use -w-amp" + CXXFLAGSG="$CXXFLAGS -q -DDEBUG -w -w-use -w-amp -w-prc" CXXFLAGSO="$CXXFLAGS -q -O2" CXXFLAGSPIC="" LDFLAGSPIC="" @@ -792,6 +822,7 @@ AC_DEFUN(DEAL_II_THREAD_CPPFLAGS, dnl [ AC_MSG_CHECKING(for platform specific multi-threading defines) AC_LANG(C++) + CXXFLAGS="$CXXFLAGSG" AC_TRY_COMPILE( [ # if !defined (_REENTRANT) && !defined (_THREAD_SAFE) @@ -958,8 +989,8 @@ AC_DEFUN(DEAL_II_CHECK_PARTLY_BRACKETED_INITIALIZER, dnl case "$GXX_VERSION" in gcc*) AC_MSG_CHECKING(for only partly bracketed mutex initializer) - CXXFLAGS="$CXXFLAGSG -Werror" AC_LANG(C++) + CXXFLAGS="$CXXFLAGSG -Werror" AC_TRY_COMPILE( [ # include @@ -1041,6 +1072,7 @@ AC_DEFUN(DEAL_II_CHECK_POSIX_THREAD_FUNCTIONS, dnl [ AC_MSG_CHECKING(for posix thread functions) AC_LANG(C++) + CXXFLAGS="$CXXFLAGSG" AC_TRY_COMPILE( [ # include @@ -1245,6 +1277,7 @@ AC_DEFUN(DEAL_II_CHECK_GETRUSAGE, dnl [ AC_MSG_CHECKING(whether getrusage is properly declared) AC_LANG(C++) + CXXFLAGS="$CXXFLAGSG" AC_TRY_COMPILE( [ #include @@ -1412,9 +1445,9 @@ dnl dnl ------------------------------------------------------------- AC_DEFUN(DEAL_II_CHECK_RAND_R, dnl [ + AC_MSG_CHECKING(for rand_r) AC_LANG(C++) CXXFLAGS=$CXXFLAGSG - AC_MSG_CHECKING(for rand_r) AC_TRY_COMPILE( [ #include @@ -1811,7 +1844,7 @@ dnl dnl ------------------------------------------------------------- AC_DEFUN(DEAL_II_CHECK_NAMESP_TEMPL_FRIEND_BUG, dnl [ - AC_MSG_CHECKING(for template friend in namespace bug) + AC_MSG_CHECKING(for 1st template friend in namespace bug) AC_LANG(C++) CXXFLAGS="$CXXFLAGSG" AC_TRY_COMPILE( @@ -1856,6 +1889,70 @@ AC_DEFUN(DEAL_II_CHECK_NAMESP_TEMPL_FRIEND_BUG, dnl +dnl ------------------------------------------------------------- +dnl Another bug in gcc with template and namespaces (fixed since 3.2, +dnl but present in 3.0): +dnl +dnl /* ----------------------------------------------- */ +dnl namespace NS { +dnl template struct Foo; +dnl } +dnl +dnl class Bar { +dnl template friend struct NS::Foo; +dnl }; +dnl +dnl namespace NS { +dnl template struct Foo { Foo (); }; +dnl } +dnl +dnl template struct NS::Foo; +dnl /* ----------------------------------------------- */ +dnl +dnl gcc2.95 provides a really unhelpful error message, 3.0 gets an +dnl internal compiler error. +dnl +dnl Usage: DEAL_II_CHECK_NAMESP_TEMPL_FRIEND_BUG2 +dnl +dnl ------------------------------------------------------------- +AC_DEFUN(DEAL_II_CHECK_NAMESP_TEMPL_FRIEND_BUG2, dnl +[ + AC_MSG_CHECKING(for 2nd template friend in namespace bug) + AC_LANG(C++) + CXXFLAGS="$CXXFLAGSG -Werror" + AC_TRY_COMPILE( + [ + namespace NS { + template struct Foo; + } + + class Bar { + template friend struct NS::Foo; + }; + + namespace NS { + template struct Foo { Foo (); }; + } + + template struct NS::Foo; + ], + [], + [ + AC_MSG_RESULT(no) + ], + [ + AC_MSG_RESULT(yes. using workaround) + AC_DEFINE_UNQUOTED(DEAL_II_NAMESP_TEMPL_FRIEND_BUG2, 1, + [Define if we have to work around another bug in gcc with + marking all instances of a template class as friends + to this class if the class is inside a namespace. + See the aclocal.m4 file in the top-level directory + for a description of this bug.]) + ]) +]) + + + dnl ------------------------------------------------------------- dnl In some cases, we would like to name partial specializations dnl as friends. However, the standard forbids us to do so. But @@ -2304,6 +2401,48 @@ AC_DEFUN(DEAL_II_CHECK_LONG_DOUBLE_LOOP_BUG, dnl +dnl ------------------------------------------------------------- +dnl The boost::shared_ptr class has a templated assignment operator +dnl but no assignment operator matching the default operator +dnl signature (this if for boost 1.29 at least). So when using +dnl using a normal assignment between identical types, the +dnl compiler synthesizes teh default operator, rather than using +dnl the template. It doesn't matter here, but is probably an +dnl oversight on behalf of the operators. +dnl +dnl With -Wsynth in gcc we then get a warning. So if we find that +dnl this is still the case, disable -Wsynth, i.e. remove it from +dnl the list of warning flags. +dnl +dnl Usage: DEAL_II_CHECK_BOOST_SHARED_PTR_ASSIGNMENT +dnl +dnl ------------------------------------------------------------- +AC_DEFUN(DEAL_II_CHECK_BOOST_SHARED_PTR_ASSIGNMENT, dnl +[ + if test "x$GXX_VERSION" != "x" ; then + AC_MSG_CHECKING(for boost::shared_ptr assignment operator= template buglet) + AC_LANG(C++) + CXXFLAGS="-Wsynth -Werror -I `pwd`/contrib/boost/include" + AC_TRY_COMPILE( + [ +# include + ], + [ + boost::shared_ptr a,b; + a = b; + ], + [ + AC_MSG_RESULT(no) + ], + [ + AC_MSG_RESULT(yes) + CXXFLAGSG="`echo $CXXFLAGSG | perl -pi -e 's/-Wsynth\s*//g;'`" + ]) + fi +]) + + + dnl ------------------------------------------------------------- dnl gcc2.95 doesn't have the std::iterator class, but the standard dnl requires it, so check whether we have to work around it @@ -2472,9 +2611,9 @@ dnl Usage: DEAL_II_CHECK_ADVANCE_WARNING dnl ------------------------------------------------------------- AC_DEFUN(DEAL_II_CHECK_ADVANCE_WARNING, dnl [ + AC_MSG_CHECKING(for std::advance warning) AC_LANG(C++) CXXFLAGS="$CXXFLAGSG -Werror" - AC_MSG_CHECKING(for std::advance warning) AC_TRY_COMPILE( [ #include @@ -2760,9 +2899,9 @@ dnl dnl ------------------------------------------------------------- AC_DEFUN(DEAL_II_CHECK_CXXFLAGS_CONSISTENCY, dnl [ + AC_MSG_CHECKING(for consistency of CXXFLAGSG flags) AC_LANG(C++) CXXFLAGS="$CXXFLAGSG" - AC_MSG_CHECKING(for consistency of CXXFLAGSG flags) AC_TRY_COMPILE( [], [;], @@ -2774,8 +2913,8 @@ AC_DEFUN(DEAL_II_CHECK_CXXFLAGS_CONSISTENCY, dnl exit 1; ]) - CXXFLAGS="$CXXFLAGSO" AC_MSG_CHECKING(for consistency of CXXFLAGSO flags) + CXXFLAGS="$CXXFLAGSO" AC_TRY_COMPILE( [], [;], diff --git a/deal.II/base/include/base/config.h.in b/deal.II/base/include/base/config.h.in index fffe90e452..5402fdd106 100644 --- a/deal.II/base/include/base/config.h.in +++ b/deal.II/base/include/base/config.h.in @@ -82,6 +82,12 @@ description of this bug. */ #undef DEAL_II_NAMESP_TEMPL_FRIEND_BUG +/* Define if we have to work around another bug in gcc with marking all + instances of a template class as friends to this class if the class is + inside a namespace. See the aclocal.m4 file in the top-level directory for + a description of this bug. */ +#undef DEAL_II_NAMESP_TEMPL_FRIEND_BUG2 + /* Defined if the compiler does not properly implement the resolution of defect report #45 to the C++ standard, which makes nested types implicit friends of the enclosing class. */ diff --git a/deal.II/base/include/base/thread_management.h b/deal.II/base/include/base/thread_management.h index 5d9eb31fd6..541c3cf7b0 100644 --- a/deal.II/base/include/base/thread_management.h +++ b/deal.II/base/include/base/thread_management.h @@ -17,9 +17,14 @@ #include #include -#include -#include #include +#include +#include + +#include +#include +#include +#include #if DEAL_II_USE_MT == 1 # if defined(DEAL_II_USE_MT_POSIX) @@ -32,9 +37,6 @@ namespace Threads { - // forward declarations - class FunDataBase; - /** * This class is used instead of a true lock class when not using * multithreading. It allows to write programs such that they start @@ -184,54 +186,6 @@ namespace Threads */ inline void wait (DummyThreadMutex &) {}; }; - -/** - * This class is used instead of a true thread manager class when not - * using multithreading. It allows to write programs such that they - * start new threads and/or lock objects in multithreading mode, and - * use dummy thread management and synchronisation classes instead - * when running in single-thread mode. Specifically, the @p{spawn} - * functions only call the function but wait for it to return instead - * of running in on another thread, and the mutices do nothing - * really. The only reason to provide such a function is that the - * program can be compiled both in MT and non-MT mode without - * difference. - * - * @author Wolfgang Bangerth, 2000 - */ - class DummyThreadManager - { - public: - /** - * Typedef for a global - * function that might be - * called on a new thread. - */ - typedef void * (*FunPtr) (void *); - - /** - * Emulate spawning a new - * thread and calling the - * passed function - * thereon. Actually only call - * that function with the given - * parameters, and wait for it - * to return. - */ - void spawn (const FunPtr fun_ptr, - void * fun_data, - int flags) const; - - /** - * Emulate that we wait for - * other threads to - * return. Since no other - * threads have been started, - * the right thing, of course, - * is to return immediately. - */ - inline void wait () const {}; - }; @@ -546,85 +500,14 @@ namespace Threads }; - class PosixThreadManager - { - public: - /** - * Typedef for a global - * function that might be - * called on a new thread. - */ - typedef void * (*FunPtr) (void *); - - /** - * Constructor. Initialize data - * structures. - */ - PosixThreadManager (); - - /** - * Destructor. Wait for all - * spawned threads if they have - * not yet finished, and - * release the resources of - * this object. - */ - ~PosixThreadManager (); - - /** - * Spawn a new thread and - * calling the passed function - * thereon. Store the - * identifier of the thread for - * later operations as waiting - * for that thread. - * - * The @p{flags} argument is - * currently ignored. - */ - void spawn (const FunPtr fun_ptr, - void * fun_data, - int flags); - - /** - * Wait for all spawned threads - * to return. - */ - void wait () const; - - private: - /** - * Copy constructor. Made - * private since copying these - * kinds of objects is a no-go. - */ - PosixThreadManager (const PosixThreadManager &) {}; - - /** - * List of thread ids. This - * variable actually points to - * an object of type - * @p{std::list}, - * but to avoid including - * @p{} into this central - * header file and all other - * files including it, we use a - * void pointer instead. - */ - void * const thread_id_list; - - /** - * Mutex by which we guard all - * accesses to the thread list. - */ - mutable PosixThreadMutex list_mutex; - }; - - - + /** + * If using POSIX functions, then + * alias the POSIX wrapper classes + * to the names we use throughout + * the library. + */ typedef PosixThreadMutex ThreadMutex; typedef PosixThreadCondition ThreadCondition; - typedef PosixThreadManager ThreadManager; typedef PosixThreadBarrier Barrier; # else @@ -637,7952 +520,6006 @@ namespace Threads * classes are aliased to dummy * classes that actually do * nothing, in particular not lock - * objects or start new - * threads. Likewise for the + * objects. Likewise for the * barrier class. */ typedef DummyThreadMutex ThreadMutex; typedef DummyThreadCondition ThreadCondition; - typedef DummyThreadManager ThreadManager; typedef DummyBarrier Barrier; #endif + +} +namespace Threads +{ - /** - * Given a class, argument type, - * and the return type, generate a - * local typedef denoting a pointer - * to such a member function. - */ - template - struct MemFunPtr0 - { - typedef RetType (Class::*type) (); - }; + /** + * Return the number of presently + * existing threads. This function + * may be useful in a situation + * where a large number of threads + * are concurrently, and you want + * to decide whether creation of + * another thread is reasonable or + * whether running the respective + * operation sequentially is more + * useful since already many more + * threads than processors are + * running. + * + * Note that the function returns + * the total number of threads, not + * those actually running. Some of + * the threads may be waiting for + * locks and mutexes, or may be + * sleeping until they are + * delivered with data to work on. + * + * Upon program start, this number + * is one. It is increased each + * time a thread is created using + * the @ref{Threads::spawn} or + * @ref{Threads::spawn_n} + * functions. It is decreased once + * a thread terminates by returning + * from the function that was + * spawned. + * + * Note that this means that only + * threads created and terminated + * through the interfaces of this + * namespace are taken care of. If + * threads are created by directly + * calling the respective functions + * of the operating system + * (e.g. @p{pthread_create} for the + * POSIX thread interface), or if + * they are killed (e.g. either + * through @p{pthread_exit} from + * the spawned thread, or + * @p{pthread_kill} from another + * thread), then these events are + * not registered and counted for + * the result of this function. + */ + unsigned int n_existing_threads (); -#ifdef DEAL_II_CONST_MEM_FUN_PTR_BUG - /** - * Same as above, but for the case - * of a member function marked - * @p{const}. This should not - * really be necessary, but Intel's - * compiler has a bug here so we - * have to work around. - */ - template - struct MemFunPtr0 - { - typedef RetType (Class::*type) () const; - }; -#endif /** - * Given a class, argument types, - * and the return type, generate a - * local typedef denoting a pointer - * to such a member function. + * Split the range @p{[begin,end)} + * into @p{n_intervals} subintervals + * of equal size. The last interval + * will be a little bit larger, if + * the number of elements in the + * whole range is not exactly + * divisible by @p{n_intervals}. The + * type of the iterators has to + * fulfill the requirements of a + * forward iterator, + * i.e. @p{operator++} must be + * available, and of course it must + * be assignable. + * + * A list of subintervals is + * returned as a vector of pairs of + * iterators, where each pair + * denotes the range + * @p{[begin[i],end[i])}. */ - template - struct MemFunPtr1 - { - typedef RetType (Class::*type) (Arg1); - }; + template + std::vector > + split_range (const ForwardIterator &begin, + const ForwardIterator &end, + const unsigned int n_intervals); -#ifdef DEAL_II_CONST_MEM_FUN_PTR_BUG - /** - * Same as above, but for the case - * of a member function marked - * @p{const}. This should not - * really be necessary, but Intel's - * compiler has a bug here so we - * have to work around. - */ - template - struct MemFunPtr1 - { - typedef RetType (Class::*type) (Arg1) const; - }; -#endif /** - * Given a class, argument types, - * and the return type, generate a - * local typedef denoting a pointer - * to such a member function. + * Split the interval @p{[begin,end)} + * into subintervals of (almost) + * equal size. This function works + * mostly as the one before, with + * the difference that instead of + * iterators, now values are taken + * that define the whole interval. */ - template - struct MemFunPtr2 - { - typedef RetType (Class::*type) (Arg1, Arg2); - }; + std::vector > + split_interval (const unsigned int begin, + const unsigned int end, + const unsigned int n_intervals); -#ifdef DEAL_II_CONST_MEM_FUN_PTR_BUG - /** - * Same as above, but for the case - * of a member function marked - * @p{const}. This should not - * really be necessary, but Intel's - * compiler has a bug here so we - * have to work around. - */ - template - struct MemFunPtr2 - { - typedef RetType (Class::*type) (Arg1, Arg2) const; - }; -#endif + /** + * A namespace in which helper + * functions and the like for the + * threading subsystem are + * implemented. The members of this + * namespace are not meant for + * public use. + * + * The classes inside this + * namespace are suppressed by the + * documentation script in the + * class overview table, to keep it + * short. + * + * @author Wolfgang Bangerth, 2003 + */ + namespace internal + { + /** + * If in a sub-thread an + * exception is thrown, it is not + * propagated to the main + * thread. Therefore, the + * exception handler that is + * provided by the applications + * main function or some of its + * other parts will not be able + * to catch these + * exceptions. Therefore, we have + * to provide an exception + * handler in the top function of + * each sub-thread that at least + * catches the exception and + * prints some information, + * rather than letting the + * operating system to just kill + * the program without a + * message. In each of the + * functions we use as entry + * points to new threads, we + * therefore install a try-catch + * block, and if an exception of + * type @p{std::exception} is + * caught, it passes over control + * to this function, which will + * then provide some output. + */ + void handle_std_exception (const std::exception &exc); + + /** + * Same as above, but the type of + * the exception is not derived + * from @p{std::exception}, so + * there is little way to provide + * something more useful. + */ + void handle_unknown_exception (); + + /** + * The following function is used + * for internal bookkeeping of the + * number of existing threads. It + * is not thought for use in + * application programs, but only + * for use in the template + * functions below. + */ + void register_thread (); + + /** + * The following function is used + * for internal bookkeeping of the + * number of existing threads. It + * is not thought for use in + * application programs, but only + * for use in the template + * functions below. + */ + void deregister_thread (); + } + +} // end declarations of namespace Threads - /** - * Given a class, argument types, - * and the return type, generate a - * local typedef denoting a pointer - * to such a member function. - */ - template - struct MemFunPtr3 - { - typedef RetType (Class::*type) (Arg1, Arg2, Arg3); - }; -#ifdef DEAL_II_CONST_MEM_FUN_PTR_BUG - /** - * Same as above, but for the case - * of a member function marked - * @p{const}. This should not - * really be necessary, but Intel's - * compiler has a bug here so we - * have to work around. - */ - template - struct MemFunPtr3 +/* ----------- implementation of functions in namespace Threads ---------- */ +namespace Threads +{ + template + std::vector > + split_range (const ForwardIterator &begin, + const ForwardIterator &end, + const unsigned int n_intervals) { - typedef RetType (Class::*type) (Arg1, Arg2, Arg3) const; - }; -#endif + typedef std::pair IteratorPair; - /** - * Given a class, argument types, - * and the return type, generate a - * local typedef denoting a pointer - * to such a member function. - */ - template - struct MemFunPtr4 - { - typedef RetType (Class::*type) (Arg1, Arg2, Arg3, Arg4); - }; + // in non-multithreaded mode, we + // often have the case that this + // function is called with + // n_intervals==1, so have a + // shortcut here to handle that + // case efficiently + + if (n_intervals==1) + return (std::vector + (1, IteratorPair(begin, end))); + + // if more than one interval + // requested, do the full work + const unsigned int n_elements = distance (begin, end); + const unsigned int n_elements_per_interval = n_elements / n_intervals; + const unsigned int residual = n_elements % n_intervals; + + std::vector return_values (n_intervals); -#ifdef DEAL_II_CONST_MEM_FUN_PTR_BUG - /** - * Same as above, but for the case - * of a member function marked - * @p{const}. This should not - * really be necessary, but Intel's - * compiler has a bug here so we - * have to work around. - */ - template - struct MemFunPtr4 - { - typedef RetType (Class::*type) (Arg1, Arg2, Arg3, Arg4) const; - }; -#endif + return_values[0].first = begin; + for (unsigned int i=0; i=0' + // is checked (dist has a + // template type, which + // here is unsigned if no + // cast is performed) + std::advance (return_values[i].second, + static_cast(n_elements_per_interval)); + // distribute residual in + // division equally among + // the first few + // subintervals + if (i < residual) + ++return_values[i].second; + + return_values[i+1].first = return_values[i].second; + } + else + return_values[i].second = end; + } + return return_values; + } - /** - * Given a class, argument types, - * and the return type, generate a - * local typedef denoting a pointer - * to such a member function. - */ - template - struct MemFunPtr5 - { - typedef RetType (Class::*type) (Arg1, Arg2, Arg3, Arg4, Arg5); - }; -#ifdef DEAL_II_CONST_MEM_FUN_PTR_BUG - /** - * Same as above, but for the case - * of a member function marked - * @p{const}. This should not - * really be necessary, but Intel's - * compiler has a bug here so we - * have to work around. - */ - template - struct MemFunPtr5 - { - typedef RetType (Class::*type) (Arg1, Arg2, Arg3, Arg4, Arg5) const; - }; -#endif + namespace internal + { + /** + * A type that is used to + * distinguish argument lists of + * functions by enumeration. + */ + template struct int2type + { + }; + } + + + namespace internal + { + /** + * Given an arbitrary type RT, + * store an element of it and grant + * access to it through functions + * get() and set(). There are + * specializations for reference + * types (which cannot be set), and + * for type void. + */ + template struct return_value + { + private: + RT value; + public: + inline return_value () : value() {} + + inline RT get () const { return value; } + inline void set (RT v) { value = v; } + }; + + + /** + * Given an arbitrary type RT, + * store an element of it and grant + * access to it through functions + * get() and set(). This is the + * specialization for reference + * types: since they cannot be set + * after construction time, we + * store a pointer instead, that + * holds the address of the object + * being referenced. + */ + template struct return_value + { + private: + RT * value; + public: + inline return_value () : value(0) {} + + inline RT & get () const { return *value; } + inline void set (RT & v) { value = &v; } + }; + + + /** + * Given an arbitrary type RT, + * store an element of it and grant + * access to it through functions + * get() and set(). This is the + * specialization for type void: + * there is obviously nothing to + * store, so no function set(), and + * a function get() that returns + * void. + */ + template <> struct return_value { + static inline void get () {} + }; + } - /** - * Given a class, argument types, - * and the return type, generate a - * local typedef denoting a pointer - * to such a member function. - */ - template - struct MemFunPtr6 - { - typedef RetType (Class::*type) (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6); - }; + -#ifdef DEAL_II_CONST_MEM_FUN_PTR_BUG - /** - * Same as above, but for the case - * of a member function marked - * @p{const}. This should not - * really be necessary, but Intel's - * compiler has a bug here so we - * have to work around. - */ - template - struct MemFunPtr6 - { - typedef RetType (Class::*type) (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6) const; - }; -#endif + namespace 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 + { + /** + * 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>())); + } + + /** + * 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>())); + } + + + /** + * 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>())); + } + + + /** + * 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>())); + } + + /** + * 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>())); + } + + + /** + * 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>())); + } + + + /** + * 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>())); + } + + /** + * 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>())); + } + + + /** + * 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>())); + } + + + /** + * 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>())); + } + + /** + * 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>())); + } + + + /** + * 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>())); + } + }; + + + + + /** + * 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. + */ + template <> + struct Caller + { + /** + * 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) (); + } + + /** + * 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>()); + } + + + /** + * 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>()); + } + + /** + * 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>()); + } + + /** + * Call a void member function + * with 6 arguments. + */ + 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>()); + } + + + /** + * Call a void function with 7 + * arguments. + */ + 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>()); + } + + /** + * Call a void member function + * with 7 arguments. + */ + 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>()); + } + + + /** + * Call a void function with 8 + * arguments. + */ + 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>()); + } + + /** + * Call a void member function + * with 8 arguments. + */ + 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>()); + } + + + /** + * Call a void function with 9 + * arguments. + */ + 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>()); + } + + /** + * Call a void member function + * with 9 arguments. + */ + 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>()); + } + + + /** + * 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>()); + } + + /** + * 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>()); + } + }; + + + + /** + * 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 + static inline void call (PFun fun_ptr, + ArgList &arg_list, + internal::return_value &ret_val) + { + Caller::do_call (fun_ptr, arg_list, ret_val, + int2type::value>()); + } + + + + /** + * 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. + */ + template + static inline void call (PFun fun_ptr, + C &obj, + ArgList &arg_list, + internal::return_value &ret_val) + { + Caller::do_call (fun_ptr, obj, arg_list, ret_val, + int2type::value>()); + } + } - /** - * Given a class, argument types, - * and the return type, generate a - * local typedef denoting a pointer - * to such a member function. - */ - template - struct MemFunPtr7 - { - typedef RetType (Class::*type) (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7); - }; - -#ifdef DEAL_II_CONST_MEM_FUN_PTR_BUG - /** - * Same as above, but for the case - * of a member function marked - * @p{const}. This should not - * really be necessary, but Intel's - * compiler has a bug here so we - * have to work around. - */ - template - struct MemFunPtr7 - { - typedef RetType (Class::*type) (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7) const; - }; -#endif - /** - * Given a class, argument types, - * and the return type, generate a - * local typedef denoting a pointer - * to such a member function. - */ - template - struct MemFunPtr8 - { - typedef RetType (Class::*type) (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8); - }; - -#ifdef DEAL_II_CONST_MEM_FUN_PTR_BUG - /** - * Same as above, but for the case - * of a member function marked - * @p{const}. This should not - * really be necessary, but Intel's - * compiler has a bug here so we - * have to work around. - */ - template - struct MemFunPtr8 - { - typedef RetType (Class::*type) (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8) const; - }; -#endif + namespace 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; + + + /** + * 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) (); + }; + + /** + * 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; + }; + + + /** + * 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); + }; + + /** + * 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; + }; + + + /** + * 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); + }; + + /** + * 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; + }; + + + /** + * 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); + }; + + /** + * 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; + }; + + + /** + * 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); + }; + + /** + * 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; + }; + + + /** + * 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); + }; + + /** + * 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; + }; + + + /** + * 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); + }; + + /** + * 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; + }; + + + /** + * 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); + }; + + /** + * 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; + }; + + + /** + * 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); + }; + + /** + * 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; + }; + + + /** + * 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); + }; + + /** + * 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; + }; + + + + /** + * 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); + }; + + /** + * 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; + }; + + + + /** + * 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 + { + /** + * 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; + + + /** + * 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) (); + }; + + + /** + * 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); + }; + + + /** + * 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); + }; + + + /** + * 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); + }; + + + /** + * 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); + }; + + + /** + * 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); + }; + + + /** + * 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); + }; + + + /** + * 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); + }; + + + /** + * 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); + }; + + + /** + * 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); + }; + + + + /** + * 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); + }; + + + + /** + * 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; + }; + } - /** - * Given a class, argument types, - * and the return type, generate a - * local typedef denoting a pointer - * to such a member function. - */ - template - struct MemFunPtr9 - { - typedef RetType (Class::*type) (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9); - }; -#ifdef DEAL_II_CONST_MEM_FUN_PTR_BUG - /** - * Same as above, but for the case - * of a member function marked - * @p{const}. This should not - * really be necessary, but Intel's - * compiler has a bug here so we - * have to work around. - */ - template - struct MemFunPtr9 - { - typedef RetType (Class::*type) (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9) const; - }; -#endif + namespace 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; + }; + + /** + * 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; + + + /** + * 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; + }; + + + /** + * 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; + }; + + + /** + * 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; + }; + + + /** + * 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; + }; + + + /** + * 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; + }; + + + /** + * 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; + }; + + + /** + * 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; + }; + + + + /** + * 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; + }; + + + /** + * 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; + }; + + + /** + * 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; + }; + + + /** + * 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; + }; + + + + /** + * 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 + { + /** + * 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 + * @p{join()} member function + * as already been called. If + * @p{true}, then @p{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 + * @p{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 @p{join()} + * function. + */ + mutable ThreadMutex join_mutex; + + public: + + /** + * Constructor. + */ + thread_description_base () : was_joined (false) {}; + + /** + * 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 + * @p{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; + }; + +# else // some other threading model +# error Not Implemented +# endif // defined(DEAL_II_USE_MT_POSIX) + + /** + * Class derived from + * @ref{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; + } - /** - * Given a class, argument types, - * and the return type, generate a - * local typedef denoting a pointer - * to such a member function. - */ - template - struct MemFunPtr10 - { - typedef RetType (Class::*type) (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9, Arg10); - }; - -#ifdef DEAL_II_CONST_MEM_FUN_PTR_BUG - /** - * Same as above, but for the case - * of a member function marked - * @p{const}. This should not - * really be necessary, but Intel's - * compiler has a bug here so we - * have to work around. - */ - template - struct MemFunPtr10 - { - typedef RetType (Class::*type) (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9, Arg10) const; - }; -#endif - - -/** - * Class used to store a pointer temporarily and delete the object - * pointed to upon destruction of this object. For more information on - * use and internals of this class see the report on multithreading. - * - * @author Wolfgang Bangerth, 2000 - */ - class FunEncapsulation + /** + * 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 @p{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 { - private: - /** - * Default constructor. Construct - * the object empty, i.e. set - * @p{data==0}. Since this is not - * very useful, disallow it by - * declaring this constructor - * @p{private}. - */ - FunEncapsulation (); - + /** + * Construct a thread object + * with a pointer to an + * internal thread object. This + * is the constructor used to + * the @p{spawn} family of + * functions. + * + * We would like to make this + * constructor private and only + * grant the + * @p{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. + */ +#ifdef DEAL_II_NAMESP_TEMPL_FRIEND_BUG2 public: - /** - * Copy constructor. Clone the - * object pointed to by - * @p{fun_data.fun_data_base}. - */ - FunEncapsulation (const FunEncapsulation &fun_encapsulation); - - /** - * This is the usual - * constructor. Set @p{fun_data_base} to - * @p{fun_data_base}. This is what - * the @p{fun_data_*} functions - * use. - */ - FunEncapsulation (FunDataBase *fun_data_base); - - /** - * Destructor. Delete the object - * pointed to by @p{fun_data_base}. - */ - ~FunEncapsulation (); - - /** - * Copy another object of this - * type by cloning its @p{fun_data_base} - * object. - */ - const FunEncapsulation & operator = (const FunEncapsulation &fun_encapsulation); - - /** - * Pointer to the object which - * contains all the parameters. - */ - const FunDataBase * fun_data_base; - }; - - +#endif + Thread (const boost::shared_ptr > &td) + : thread_descriptor (td) {}; -/** - * Abstract base class for those classes that actually store - * parameters of functions. For more information on use and internals - * of this class see the report on multithreading. - * - * @author Wolfgang Bangerth, 2000 - */ - class FunDataBase - { public: - /** - * Typedef a pointer to a - * function that satifies the - * requirements of thread entry - * points. - */ - typedef void * (*ThreadEntryPoint) (void *); - - /** - * Default constructor. Store the - * pointer to the function which - * we will use as thread entry - * point for the derived class. - */ - FunDataBase (const ThreadEntryPoint thread_entry_point); - - /** - * Copy constructor. - */ - FunDataBase (const FunDataBase &); - - /** - * Destructor. Needs to be - * virtual to make destruction of - * derived classes through base - * class pointers. - */ - virtual ~FunDataBase (); - - /** - * Virtual constructor. Needed to - * copy an object of which we - * only have a pointer to the - * base class. Copying such - * objects is necessary to - * guarantee memory consistency. - */ - virtual FunDataBase * clone () const = 0; - - /** - * Lock to be used when starting - * a thread and which is released - * after the data of this object - * is copied and therefore no - * more needed. This ensures that - * no data is deleted when it is - * still in use. - */ - mutable ThreadMutex lock; - + /** - * A condition variable that is - * used for the same purpose. + * 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 + * @p{spawn} functions. */ - mutable ThreadCondition condition; - - private: - /** - * Pointer to the thread entry - * point function. The address of - * that function is passed from - * the derived classes to the - * constructor of this class. - */ - ThreadEntryPoint thread_entry_point; - - /** - * Make the thread starter - * function a friend, since it - * needs to have access to the - * @p{thread_entry_point} variable. - */ - friend void spawn (ThreadManager &thread_manager, - const FunEncapsulation &fun_data); - }; - - - -/** - * Class to store the parameters of a void function. For more - * information on use and internals of this class see the report on - * multithreading. - * - * @author Wolfgang Bangerth, 2000 - */ - template - class FunData0 : public FunDataBase - { - public: - /** - * Typedef a pointer to a global - * function which we will call - * from this class. - */ - typedef RetType (*FunPtr) (); - - /** - * Constructor. Store pointer to - * the function and the values of - * the arguments. - */ - FunData0 (FunPtr fun_ptr); + Thread () {}; - /** - * Copy constructor. - */ - FunData0 (const FunData0 &fun_data0); - - /** - * Virtual constructor. - */ - virtual FunDataBase * clone () const; - - private: - - /** - * Pointer to the function to be - * called and values of the - * arguments to be passed. - */ - FunPtr fun_ptr; - - /** - * Static function used as entry - * point for the new thread. - */ - static void * thread_entry_point (void *arg); - - -//TODO:[WB] (compiler) with some compilers we get into trouble if the following class is not public, since we can't somehow declare the encapsulate function as friend. change this when compilers accept the friend declaration - public: - /** - * Helper class, used to collect - * the values of the parameters - * which we will pass to the - * function, once we know its - * type. - */ - class ArgCollector - { - public: - /** - * Typedef the function - * pointer type of the - * underlying class to a - * local type. - */ - typedef typename FunData0::FunPtr FunPtr; - - /** - * Constructor. Take and store a - * pointer to the function which - * is to be called. - */ - ArgCollector (FunPtr fun_ptr); - - /** - * Take the arguments with - * which we want to call the - * function and produce and - * object of the desired type - * from that. - * - * Since the function in - * question here does not - * take parameters, this - * function also does - * nothing. It is only - * present for - * orthogonality of thread - * creation. - */ - FunEncapsulation collect_args (); - - private: - /** - * Space to temporarily store - * the function pointer. - */ - FunPtr fun_ptr; + /** + * 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 (); }; -// we should be declaring the following function friend, but gcc2.95 -// does not allow us to do that at present... -// /** -// * Declare a function that uses -// * the @ref{ArgCollector} as -// * friend. -// */ -// friend -// FunData0::ArgCollector -// encapsulate (void (*fun_ptr)()); - }; - - - -/** - * Class to store the parameters of a unary function. For more - * information on use and internals of this class see the report on - * multithreading. - * - * @author Wolfgang Bangerth, 2000 - */ - template - class FunData1 : public FunDataBase - { - public: - /** - * Typedef a pointer to a global - * function which we will call - * from this class. - */ - typedef RetType (*FunPtr) (Arg1); - - /** - * Constructor. Store pointer to - * the function and the values of - * the arguments. - */ - FunData1 (FunPtr fun_ptr, - Arg1 arg1); - - /** - * Copy constructor. - */ - FunData1 (const FunData1 &fun_data1); - - /** - * Virtual constructor. - */ - virtual FunDataBase * clone () const; - - private: - - /** - * Pointer to the function to be - * called and values of the - * arguments to be passed. - */ - FunPtr fun_ptr; - - /** - * Values of the arguments of the - * function to be called. - */ - Arg1 arg1; - - /** - * Static function used as entry - * point for the new thread. - */ - static void * thread_entry_point (void *arg); - - /** - * Helper class, used to collect - * the values of the parameters - * which we will pass to the - * function, once we know its - * type. - */ - class ArgCollector - { - public: - /** - * Typedef the function - * pointer type of the - * underlying class to a - * local type. - */ - typedef typename FunData1::FunPtr FunPtr; - - /** - * Constructor. Take and store a - * pointer to the function which - * is to be called. - */ - ArgCollector (FunPtr fun_ptr); - - /** - * Take the arguments with - * which we want to call the - * function and produce and - * object of the desired type - * from that. - */ - FunEncapsulation collect_args (Arg1 arg1); - - private: - /** - * Space to temporarily store - * the function pointer. - */ - FunPtr fun_ptr; + /** + * Get the return value of the + * function of the + * thread. Since this is only + * available once the thread + * finishes, this implicitely + * also calls @p{join()}. + */ + RT return_value () { + join (); + return thread_descriptor->ret_val.get(); }; - /** - * Declare a function that uses - * the @ref{ArgCollector} as - * friend. - */ - template - friend - typename FunData1::ArgCollector - encapsulate (void (*fun_ptr)(Arg1_)); - }; - - - -/** - * Class to store the parameters of a binary function. For more - * information on use and internals of this class see the report on - * multithreading. - * - * @author Wolfgang Bangerth, 2000 - */ - template - class FunData2 : public FunDataBase - { - public: - /** - * Typedef a pointer to a global - * function which we will call - * from this class. - */ - typedef RetType (*FunPtr) (Arg1, Arg2); - - /** - * Constructor. Store pointer to - * the function and the values of - * the arguments. - */ - FunData2 (FunPtr fun_ptr, - Arg1 arg1, - Arg2 arg2); - - /** - * Copy constructor. - */ - FunData2 (const FunData2 &fun_data2); - - /** - * Virtual constructor. - */ - virtual FunDataBase * clone () const; - - private: - /** - * Pointer to the function to be - * called and values of the - * arguments to be passed. - */ - FunPtr 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; + }; - /** - * Values of the arguments of the - * function to be called. - */ - Arg1 arg1; - Arg2 arg2; + /** + * Exception + */ + DeclException0 (ExcNoThread); - /** - * Static function used as entry - * point for the new thread. - */ - static void * thread_entry_point (void *arg); - - /** - * Helper class, used to collect - * the values of the parameters - * which we will pass to the - * function, once we know its - * type. - */ - class ArgCollector - { - public: - /** - * Typedef the function - * pointer type of the - * underlying class to a - * local type. - */ - typedef typename FunData2::FunPtr FunPtr; - - /** - * Constructor. Take and store a - * pointer to the function which - * is to be called. - */ - ArgCollector (FunPtr fun_ptr); - - /** - * Take the arguments with - * which we want to call the - * function and produce and - * object of the desired type - * from that. - */ - FunEncapsulation collect_args (Arg1 arg1, - Arg2 arg2); - - private: - /** - * Space to temporarily store - * the function pointer. - */ - FunPtr fun_ptr; - }; + 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; - /** - * Declare a function that uses - * the @ref{ArgCollector} as - * friend. - */ - template - friend - typename FunData2::ArgCollector - encapsulate (void (*fun_ptr)(Arg1_, Arg2_)); +#ifndef DEAL_II_NAMESP_TEMPL_FRIEND_BUG2 + template friend struct Threads::internal::wrapper_base; +#endif }; - -/** - * Class to store the parameters of a ternary function. For more - * information on use and internals of this class see the report on - * multithreading. - * - * @author Wolfgang Bangerth, 2000 - */ - template - class FunData3 : public FunDataBase - { - public: - /** - * Typedef a pointer to a global - * function which we will call - * from this class. - */ - typedef RetType (*FunPtr) (Arg1, Arg2, Arg3); - - /** - * Constructor. Store pointer to - * the function and the values of - * the arguments. - */ - FunData3 (FunPtr fun_ptr, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3); - - /** - * Copy constructor. - */ - FunData3 (const FunData3 &fun_data3); - - /** - * Virtual constructor. - */ - virtual FunDataBase * clone () const; - - private: - /** - * Pointer to the function to be - * called and values of the - * arguments to be passed. - */ - FunPtr fun_ptr; - /** - * Values of the arguments of the - * function to be called. - */ - Arg1 arg1; - Arg2 arg2; - Arg3 arg3; + namespace internal + { + + /** + * Base class for the classes + * wrapping function pointers and + * arguments for non-member and + * member functions. + * + * @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 (entry_point, (void *)this); + condition.wait (mutex); + + return thread_descriptor; + } + + protected: + /** + * Typedef for the type of a + * thread entry point, as + * required by POSIX. + */ + typedef void * (*EntryPoint) (void *); + + /** + * Typedef for shared + * pointers to the objects + * describing threads on the + * OS level. + */ + typedef + boost::shared_ptr > + DescriptionPointer; + + /** + * Constructor. Take the + * address of a thread entry + * point and store it. + */ + wrapper_base (const EntryPoint ep) + : entry_point (ep) {}; + + /** + * 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; + + private: + /** + * Address of the thread + * entry point. Is set in the + * constructor, and is the + * address of a function in + * derived classes. + */ + const EntryPoint entry_point; + }; + + + /** + * 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) + : wrapper_base (&entry_point), + 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; - /** - * Static function used as entry - * point for the new thread. - */ - static void * thread_entry_point (void *arg); - - /** - * Helper class, used to collect - * the values of the parameters - * which we will pass to the - * function, once we know its - * type. - */ - class ArgCollector - { - public: - /** - * Typedef the function - * pointer type of the - * underlying class to a - * local type. - */ - typedef typename FunData3::FunPtr FunPtr; - - /** - * Constructor. Take and store a - * pointer to the function which - * is to be called. - */ - ArgCollector (FunPtr fun_ptr); - - /** - * Take the arguments with - * which we want to call the - * function and produce and - * object of the desired type - * from that. - */ - FunEncapsulation collect_args (Arg1 arg1, - Arg2 arg2, - Arg3 arg3); - - private: - /** - * Space to temporarily store - * the function pointer. - */ - FunPtr fun_ptr; - }; - /** - * Declare a function that uses - * the @ref{ArgCollector} as - * friend. - */ - template - friend - typename FunData3::ArgCollector - encapsulate (void (*fun_ptr)(Arg1_,Arg2_,Arg3_)); - }; - - -/** - * Class to store the parameters of a quaternary function. For more - * information on use and internals of this class see the report on - * multithreading. - * - * @author Wolfgang Bangerth, 2000 - */ - template - class FunData4 : public FunDataBase - { - public: - /** - * Typedef a pointer to a global - * function which we will call - * from this class. - */ - typedef RetType (*FunPtr) (Arg1, Arg2, Arg3, Arg4); - - /** - * Constructor. Store pointer to - * the function and the values of - * the arguments. - */ - FunData4 (FunPtr fun_ptr, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4); - - /** - * Copy constructor. - */ - FunData4 (const FunData4 &fun_data4); - - /** - * Virtual constructor. - */ - virtual FunDataBase * clone () const; - - private: - - /** - * Pointer to the function to be - * called and values of the - * arguments to be passed. - */ - FunPtr fun_ptr; - - /** - * Values of the arguments of the - * function to be called. - */ - Arg1 arg1; - Arg2 arg2; - Arg3 arg3; - Arg4 arg4; - - /** - * Static function used as entry - * point for the new thread. - */ - static void * thread_entry_point (void *arg); - - /** - * Helper class, used to collect - * the values of the parameters - * which we will pass to the - * function, once we know its - * type. - */ - class ArgCollector - { - public: - /** - * Typedef the function - * pointer type of the - * underlying class to a - * local type. - */ - typedef typename FunData4::FunPtr FunPtr; - - /** - * Constructor. Take and store a - * pointer to the function which - * is to be called. - */ - ArgCollector (FunPtr fun_ptr); - - /** - * Take the arguments with - * which we want to call the - * function and produce and - * object of the desired type - * from that. - */ - FunEncapsulation collect_args (Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4); - - private: - /** - * Space to temporarily store - * the function pointer. - */ - FunPtr fun_ptr; - }; - - /** - * Declare a function that uses - * the @ref{ArgCollector} as - * friend. - */ - template - friend - typename FunData4::ArgCollector - encapsulate (void (*fun_ptr)(Arg1_, Arg2_, Arg3_, Arg4_)); - }; - - - -/** - * Class to store the parameters of a quintary function. For more - * information on use and internals of this class see the report on - * multithreading. - * - * @author Wolfgang Bangerth, 2000 - */ - template - class FunData5 : public FunDataBase - { - public: - /** - * Typedef a pointer to a global - * function which we will call - * from this class. - */ - typedef RetType (*FunPtr) (Arg1, Arg2, Arg3, Arg4, Arg5); - - /** - * Constructor. Store pointer to - * the function and the values of - * the arguments. - */ - FunData5 (FunPtr fun_ptr, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5); - - /** - * Copy constructor. - */ - FunData5 (const FunData5 &fun_data5); - - /** - * Virtual constructor. - */ - virtual FunDataBase * clone () const; - - private: - - /** - * Pointer to the function to be - * called and values of the - * arguments to be passed. - */ - FunPtr fun_ptr; - - /** - * Values of the arguments of the - * function to be called. - */ - Arg1 arg1; - Arg2 arg2; - Arg3 arg3; - Arg4 arg4; - Arg5 arg5; - - /** - * Static function used as entry - * point for the new thread. - */ - static void * thread_entry_point (void *arg); - - /** - * Helper class, used to collect - * the values of the parameters - * which we will pass to the - * function, once we know its - * type. - */ - class ArgCollector - { - public: - /** - * Typedef the function - * pointer type of the - * underlying class to a - * local type. - */ - typedef typename FunData5::FunPtr FunPtr; - - /** - * Constructor. Take and store a - * pointer to the function which - * is to be called. - */ - ArgCollector (FunPtr fun_ptr); - - /** - * Take the arguments with - * which we want to call the - * function and produce and - * object of the desired type - * from that. - */ - FunEncapsulation collect_args (Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5); - - private: - /** - * Space to temporarily store - * the function pointer. - */ - FunPtr fun_ptr; - }; - - /** - * Declare a function that uses - * the @ref{ArgCollector} as - * friend. - */ - template - friend - typename FunData5::ArgCollector - encapsulate (void (*fun_ptr)(Arg1_, Arg2_, Arg3_, Arg4_, Arg5_)); - }; - - -/** - * Class to store the parameters of a function with 6 arguments. For more - * information on use and internals of this class see the report on - * multithreading. - * - * @author Wolfgang Bangerth, 2000 - */ - template - class FunData6 : public FunDataBase - { - public: - /** - * Typedef a pointer to a global - * function which we will call - * from this class. - */ - typedef RetType (*FunPtr) (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6); - - /** - * Constructor. Store pointer to - * the function and the values of - * the arguments. - */ - FunData6 (FunPtr fun_ptr, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5, - Arg6 arg6); - - /** - * Copy constructor. - */ - FunData6 (const FunData6 &fun_data6); - - /** - * Virtual constructor. - */ - virtual FunDataBase * clone () const; - - private: - - /** - * Pointer to the function to be - * called and values of the - * arguments to be passed. - */ - FunPtr fun_ptr; - - /** - * Values of the arguments of the - * function to be called. - */ - Arg1 arg1; - Arg2 arg2; - Arg3 arg3; - Arg4 arg4; - Arg5 arg5; - Arg6 arg6; - - /** - * Static function used as entry - * point for the new thread. - */ - static void * thread_entry_point (void *arg); - - /** - * Helper class, used to collect - * the values of the parameters - * which we will pass to the - * function, once we know its - * type. - */ - class ArgCollector - { - public: - /** - * Typedef the function - * pointer type of the - * underlying class to a - * local type. - */ - typedef typename FunData6::FunPtr FunPtr; - - /** - * Constructor. Take and store a - * pointer to the function which - * is to be called. - */ - ArgCollector (FunPtr fun_ptr); - - /** - * Take the arguments with - * which we want to call the - * function and produce and - * object of the desired type - * from that. - */ - FunEncapsulation collect_args (Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5, - Arg6 arg6); - - private: - /** - * Space to temporarily store - * the function pointer. - */ - FunPtr fun_ptr; - }; - - /** - * Declare a function that uses - * the @ref{ArgCollector} as - * friend. - */ - template - friend - typename FunData6::ArgCollector - encapsulate (void (*fun_ptr)(Arg1_, Arg2_, Arg3_, - Arg4_, Arg5_, Arg6_)); - }; - - -/** - * Class to store the parameters of a function with 7 arguments. For more - * information on use and internals of this class see the report on - * multithreading. - * - * @author Wolfgang Bangerth, 2000 - */ - template - class FunData7 : public FunDataBase - { - public: - /** - * Typedef a pointer to a global - * function which we will call - * from this class. - */ - typedef RetType (*FunPtr) (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7); - - /** - * Constructor. Store pointer to - * the function and the values of - * the arguments. - */ - FunData7 (FunPtr fun_ptr, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5, - Arg6 arg6, - Arg7 arg7); - - /** - * Copy constructor. - */ - FunData7 (const FunData7 &fun_data7); - - /** - * Virtual constructor. - */ - virtual FunDataBase * clone () const; - - private: - - /** - * Pointer to the function to be - * called and values of the - * arguments to be passed. - */ - FunPtr fun_ptr; - - /** - * Values of the arguments of the - * function to be called. - */ - Arg1 arg1; - Arg2 arg2; - Arg3 arg3; - Arg4 arg4; - Arg5 arg5; - Arg6 arg6; - Arg7 arg7; - - /** - * Static function used as entry - * point for the new thread. - */ - static void * thread_entry_point (void *arg); - - /** - * Helper class, used to collect - * the values of the parameters - * which we will pass to the - * function, once we know its - * type. - */ - class ArgCollector - { - public: - /** - * Typedef the function - * pointer type of the - * underlying class to a - * local type. - */ - typedef typename FunData7::FunPtr FunPtr; - - /** - * Constructor. Take and store a - * pointer to the function which - * is to be called. - */ - ArgCollector (FunPtr fun_ptr); - - /** - * Take the arguments with - * which we want to call the - * function and produce and - * object of the desired type - * from that. - */ - FunEncapsulation collect_args (Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5, - Arg6 arg6, - Arg7 arg7); - - private: - /** - * Space to temporarily store - * the function pointer. - */ - FunPtr fun_ptr; - }; - - /** - * Declare a function that uses - * the @ref{ArgCollector} as - * friend. - */ - template - friend - typename FunData7::ArgCollector - encapsulate (void (*fun_ptr)(Arg1_, Arg2_, Arg3_, - Arg4_, Arg5_, Arg6_, Arg7_)); - }; - - -/** - * Class to store the parameters of a function with 8 arguments. For more - * information on use and internals of this class see the report on - * multithreading. - * - * @author Wolfgang Bangerth, 2000 - */ - template - class FunData8 : public FunDataBase - { - public: - /** - * Typedef a pointer to a global - * function which we will call - * from this class. - */ - typedef RetType (*FunPtr) (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8); - - /** - * Constructor. Store pointer to - * the function and the values of - * the arguments. - */ - FunData8 (FunPtr fun_ptr, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5, - Arg6 arg6, - Arg7 arg7, - Arg8 arg8); - - /** - * Copy constructor. - */ - FunData8 (const FunData8 &fun_data8); - - /** - * Virtual constructor. - */ - virtual FunDataBase * clone () const; - - private: - - /** - * Pointer to the function to be - * called and values of the - * arguments to be passed. - */ - FunPtr fun_ptr; - - /** - * Values of the arguments of the - * function to be called. - */ - Arg1 arg1; - Arg2 arg2; - Arg3 arg3; - Arg4 arg4; - Arg5 arg5; - Arg6 arg6; - Arg7 arg7; - Arg8 arg8; + /** + * 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; + }; + }; + + + + /** + * 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; - /** - * Static function used as entry - * point for the new thread. - */ - static void * thread_entry_point (void *arg); - - /** - * Helper class, used to collect - * the values of the parameters - * which we will pass to the - * function, once we know its - * type. - */ - class ArgCollector - { - public: - /** - * Typedef the function - * pointer type of the - * underlying class to a - * local type. - */ - typedef typename FunData8::FunPtr FunPtr; - - /** - * Constructor. Take and store a - * pointer to the function which - * is to be called. - */ - ArgCollector (FunPtr fun_ptr); - - /** - * Take the arguments with - * which we want to call the - * function and produce and - * object of the desired type - * from that. - */ - FunEncapsulation collect_args (Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5, - Arg6 arg6, - Arg7 arg7, - Arg8 arg8); - - private: - /** - * Space to temporarily store - * the function pointer. - */ - FunPtr fun_ptr; - }; - - /** - * Declare a function that uses - * the @ref{ArgCollector} as - * friend. - */ - template - friend - typename FunData8::ArgCollector - encapsulate (void (*fun_ptr)(Arg1_, Arg2_, Arg3_, - Arg4_, Arg5_, Arg6_, - Arg7_, Arg8_)); - }; - - -/** - * Class to store the parameters of a function with 9 arguments. For more - * information on use and internals of this class see the report on - * multithreading. - * - * @author Wolfgang Bangerth, 2001 - */ - template - class FunData9 : public FunDataBase - { - public: - /** - * Typedef a pointer to a global - * function which we will call - * from this class. - */ - typedef RetType (*FunPtr) (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9); - - /** - * Constructor. Store pointer to - * the function and the values of - * the arguments. - */ - FunData9 (FunPtr fun_ptr, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5, - Arg6 arg6, - Arg7 arg7, - Arg8 arg8, - Arg9 arg9); - - /** - * Copy constructor. - */ - FunData9 (const FunData9 &fun_data9); - - /** - * Virtual constructor. - */ - virtual FunDataBase * clone () const; - - private: - - /** - * Pointer to the function to be - * called and values of the - * arguments to be passed. - */ - FunPtr fun_ptr; - - /** - * Values of the arguments of the - * function to be called. - */ - Arg1 arg1; - Arg2 arg2; - Arg3 arg3; - Arg4 arg4; - Arg5 arg5; - Arg6 arg6; - Arg7 arg7; - Arg8 arg8; - Arg9 arg9; + /** + * 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) + : wrapper_base (&entry_point), + 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 &); - /** - * Static function used as entry - * point for the new thread. - */ - static void * thread_entry_point (void *arg); - - /** - * Helper class, used to collect - * the values of the parameters - * which we will pass to the - * function, once we know its - * type. - */ - class ArgCollector - { - public: - /** - * Typedef the function - * pointer type of the - * underlying class to a - * local type. - */ - typedef typename FunData9::FunPtr FunPtr; - - /** - * Constructor. Take and store a - * pointer to the function which - * is to be called. - */ - ArgCollector (FunPtr fun_ptr); - - /** - * Take the arguments with - * which we want to call the - * function and produce and - * object of the desired type - * from that. - */ - FunEncapsulation collect_args (Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5, - Arg6 arg6, - Arg7 arg7, - Arg8 arg8, - Arg9 arg9); - - private: - /** - * Space to temporarily store - * the function pointer. - */ - FunPtr fun_ptr; - }; - - /** - * Declare a function that uses - * the @ref{ArgCollector} as - * friend. - */ - template - friend - typename FunData9::ArgCollector - encapsulate (void (*fun_ptr)(Arg1_, Arg2_, Arg3_, - Arg4_, Arg5_, Arg6_, - Arg7_, Arg8_, Arg9_)); - }; - - -/** - * Class to store the parameters of a function with 10 arguments. For more - * information on use and internals of this class see the report on - * multithreading. - * - * @author Wolfgang Bangerth, 2001 - */ - template - class FunData10 : public FunDataBase - { - public: - /** - * Typedef a pointer to a global - * function which we will call - * from this class. - */ - typedef RetType (*FunPtr) (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9, Arg10); - - /** - * Constructor. Store pointer to - * the function and the values of - * the arguments. - */ - FunData10 (FunPtr fun_ptr, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5, - Arg6 arg6, - Arg7 arg7, - Arg8 arg8, - Arg9 arg9, - Arg10 arg10); - - /** - * Copy constructor. - */ - FunData10 (const FunData10 &fun_data10); - - /** - * Virtual constructor. - */ - virtual FunDataBase * clone () const; - - private: - - /** - * Pointer to the function to be - * called and values of the - * arguments to be passed. - */ - FunPtr fun_ptr; - - /** - * Values of the arguments of the - * function to be called. - */ - Arg1 arg1; - Arg2 arg2; - Arg3 arg3; - Arg4 arg4; - Arg5 arg5; - Arg6 arg6; - Arg7 arg7; - Arg8 arg8; - Arg9 arg9; - Arg10 arg10; - - /** - * Static function used as entry - * point for the new thread. - */ - static void * thread_entry_point (void *arg); - - /** - * Helper class, used to collect - * the values of the parameters - * which we will pass to the - * function, once we know its - * type. - */ - class ArgCollector - { - public: - /** - * Typedef the function - * pointer type of the - * underlying class to a - * local type. - */ - typedef typename FunData10::FunPtr FunPtr; - - /** - * Constructor. Take and store a - * pointer to the function which - * is to be called. - */ - ArgCollector (FunPtr fun_ptr); - - /** - * Take the arguments with - * which we want to call the - * function and produce and - * object of the desired type - * from that. - */ - FunEncapsulation collect_args (Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5, - Arg6 arg6, - Arg7 arg7, - Arg8 arg8, - Arg9 arg9, - Arg10 arg10); - - private: - /** - * Space to temporarily store - * the function pointer. - */ - FunPtr fun_ptr; - }; - - /** - * Declare a function that uses - * the @ref{ArgCollector} as - * friend. - */ - template - friend - typename FunData10::ArgCollector - encapsulate (void (*fun_ptr)(Arg1_, Arg2_, Arg3_, - Arg4_, Arg5_, Arg6_, - Arg7_, Arg8_, Arg9_, - Arg10_)); - }; - - -/** - * Class to store the parameters of a void function. For more - * information on use and internals of this class see the report on - * multithreading. - * - * @author Wolfgang Bangerth, 2000 - */ - template - class MemFunData0 : public FunDataBase - { - public: - /** - * Typedef a pointer to a member - * function which we will call - * from this class. - */ - typedef typename MemFunPtr0::type FunPtr; - - /** - * Constructor. Store pointer to - * the function and the values of - * the arguments. - */ - MemFunData0 (FunPtr fun_ptr, - Class *object); - - /** - * Copy constructor. - */ - MemFunData0 (const MemFunData0 &fun_data0); - - /** - * Virtual constructor. - */ - virtual FunDataBase * clone () const; - - private: - - /** - * Pointer to the function to be - * called and values of the - * arguments to be passed. - */ - FunPtr fun_ptr; - - /** - * Pointer to the object which - * we shall work on. - */ - Class *object; - - /** - * Static function used as entry - * point for the new thread. - */ - static void * thread_entry_point (void *arg); - - /** - * Helper class, used to collect - * the values of the parameters - * which we will pass to the - * function, once we know its - * type. - */ - class ArgCollector - { - public: - /** - * Typedef the function - * pointer type of the - * underlying class to a - * local type. - */ - typedef typename MemFunData0::FunPtr FunPtr; - - /** - * Constructor. Take and store a - * pointer to the function which - * is to be called. - */ - ArgCollector (FunPtr fun_ptr); - - /** - * Take the arguments with - * which we want to call the - * function and produce and - * object of the desired type - * from that. - */ - FunEncapsulation collect_args (Class *object); - - /** - * Same as above, but take - * a reference instead of a - * pointer. This allows us - * to be a little - * convenient, as we can - * use @p{object} or - * @p{this}, without taking - * care that one is a - * reference and the other - * a pointer. - */ - FunEncapsulation collect_args (Class &object); - - private: - /** - * Space to temporarily store - * the function pointer. - */ - FunPtr fun_ptr; - }; - - /** - * Declare a function that uses - * the @ref{ArgCollector} as - * friend. - */ - template - friend - typename MemFunData0::ArgCollector - encapsulate (void (Class_::*fun_ptr)()); - -#ifdef DEAL_II_TEMPL_CONST_MEM_PTR_BUG - template - friend - typename MemFunData0::ArgCollector - encapsulate (void (Class_::*fun_ptr)() const); -#endif - }; - - - -/** - * Class to store the parameters of a unary function. For more - * information on use and internals of this class see the report on - * multithreading. - * - * @author Wolfgang Bangerth, 2000 - */ - template - class MemFunData1 : public FunDataBase - { - public: - /** - * Typedef a pointer to a member - * function which we will call - * from this class. - */ - typedef typename MemFunPtr1::type FunPtr; - - /** - * Constructor. Store pointer to - * the function and the values of - * the arguments. - */ - MemFunData1 (FunPtr fun_ptr, - Class *object, - Arg1 arg1); - - /** - * Copy constructor. - */ - MemFunData1 (const MemFunData1 &fun_data1); - - /** - * Virtual constructor. - */ - virtual FunDataBase * clone () const; - - private: - - /** - * Pointer to the function to be - * called and values of the - * arguments to be passed. - */ - FunPtr fun_ptr; - - /** - * Pointer to the object which - * we shall work on. - */ - Class *object; - - /** - * Values of the arguments of the - * function to be called. - */ - Arg1 arg1; - - /** - * Static function used as entry - * point for the new thread. - */ - static void * thread_entry_point (void *arg); - - /** - * Helper class, used to collect - * the values of the parameters - * which we will pass to the - * function, once we know its - * type. - */ - class ArgCollector - { - public: - /** - * Typedef the function - * pointer type of the - * underlying class to a - * local type. - */ - typedef typename MemFunData1::FunPtr FunPtr; - - /** - * Constructor. Take and store a - * pointer to the function which - * is to be called. - */ - ArgCollector (FunPtr fun_ptr); - - /** - * Take the arguments with - * which we want to call the - * function and produce and - * object of the desired type - * from that. - */ - FunEncapsulation collect_args (Class *object, - Arg1 arg1); - - /** - * Same as above, but take - * a reference instead of a - * pointer. This allows us - * to be a little - * convenient, as we can - * use @p{object} or - * @p{this}, without taking - * care that one is a - * reference and the other - * a pointer. - */ - FunEncapsulation collect_args (Class &object, - Arg1 arg1); - - private: - /** - * Space to temporarily store - * the function pointer. - */ - FunPtr fun_ptr; - }; - - /** - * Declare a function that uses - * the @ref{ArgCollector} as - * friend. - */ - template - friend - typename MemFunData1::ArgCollector - encapsulate (void (Class_::*fun_ptr)(Arg1_)); - -#ifdef DEAL_II_TEMPL_CONST_MEM_PTR_BUG - template - friend - typename MemFunData1::ArgCollector - encapsulate (void (Class_::*fun_ptr)(Arg1_) const); -#endif - }; - - - -/** - * Class to store the parameters of a binary function. For more - * information on use and internals of this class see the report on - * multithreading. - * - * @author Wolfgang Bangerth, 2000 - */ - template - class MemFunData2 : public FunDataBase - { - public: - /** - * Typedef a pointer to a member - * function which we will call - * from this class. - */ - typedef typename MemFunPtr2::type FunPtr; - - /** - * Constructor. Store pointer to - * the function and the values of - * the arguments. - */ - MemFunData2 (FunPtr fun_ptr, - Class *object, - Arg1 arg1, - Arg2 arg2); - - /** - * Copy constructor. - */ - MemFunData2 (const MemFunData2 &fun_data2); - - /** - * Virtual constructor. - */ - virtual FunDataBase * clone () const; - - private: - - /** - * Pointer to the function to be - * called and values of the - * arguments to be passed. - */ - FunPtr fun_ptr; - - /** - * Pointer to the object which - * we shall work on. - */ - Class *object; - - /** - * Values of the arguments of the - * function to be called. - */ - Arg1 arg1; - Arg2 arg2; - - /** - * Static function used as entry - * point for the new thread. - */ - static void * thread_entry_point (void *arg); - - /** - * Helper class, used to collect - * the values of the parameters - * which we will pass to the - * function, once we know its - * type. - */ - class ArgCollector - { - public: - /** - * Typedef the function - * pointer type of the - * underlying class to a - * local type. - */ - typedef typename MemFunData2::FunPtr FunPtr; - - /** - * Constructor. Take and store a - * pointer to the function which - * is to be called. - */ - ArgCollector (FunPtr fun_ptr); - - /** - * Take the arguments with - * which we want to call the - * function and produce and - * object of the desired type - * from that. - */ - FunEncapsulation collect_args (Class *object, - Arg1 arg1, - Arg2 arg2); - - /** - * Same as above, but take - * a reference instead of a - * pointer. This allows us - * to be a little - * convenient, as we can - * use @p{object} or - * @p{this}, without taking - * care that one is a - * reference and the other - * a pointer. - */ - FunEncapsulation collect_args (Class &object, - Arg1 arg1, - Arg2 arg2); - - private: - /** - * Space to temporarily store - * the function pointer. - */ - FunPtr fun_ptr; - }; - - /** - * Declare a function that uses - * the @ref{ArgCollector} as - * friend. - */ - template - friend - typename MemFunData2::ArgCollector - encapsulate (void (Class_::*fun_ptr)(Arg1_, Arg2_)); - -#ifdef DEAL_II_TEMPL_CONST_MEM_PTR_BUG - template - friend - typename MemFunData2::ArgCollector - encapsulate (void (Class_::*fun_ptr)(Arg1_, Arg2_) const); -#endif - }; - - -/** - * Class to store the parameters of a ternary function. For more - * information on use and internals of this class see the report on - * multithreading. - * - * @author Wolfgang Bangerth, 2000 - */ - template - class MemFunData3 : public FunDataBase - { - public: - /** - * Typedef a pointer to a member - * function which we will call - * from this class. - */ - typedef typename MemFunPtr3::type FunPtr; - - /** - * Constructor. Store pointer to - * the function and the values of - * the arguments. - */ - MemFunData3 (FunPtr fun_ptr, - Class *object, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3); - - /** - * Copy constructor. - */ - MemFunData3 (const MemFunData3 &fun_data3); - - /** - * Virtual constructor. - */ - virtual FunDataBase * clone () const; - - private: - - /** - * Pointer to the function to be - * called and values of the - * arguments to be passed. - */ - FunPtr fun_ptr; - - /** - * Pointer to the object which - * we shall work on. - */ - Class *object; - - /** - * Values of the arguments of the - * function to be called. - */ - Arg1 arg1; - Arg2 arg2; - Arg3 arg3; - - /** - * Static function used as entry - * point for the new thread. - */ - static void * thread_entry_point (void *arg); - - /** - * Helper class, used to collect - * the values of the parameters - * which we will pass to the - * function, once we know its - * type. - */ - class ArgCollector - { - public: - /** - * Typedef the function - * pointer type of the - * underlying class to a - * local type. - */ - typedef typename MemFunData3::FunPtr FunPtr; - - /** - * Constructor. Take and store a - * pointer to the function which - * is to be called. - */ - ArgCollector (FunPtr fun_ptr); - - /** - * Take the arguments with - * which we want to call the - * function and produce and - * object of the desired type - * from that. - */ - FunEncapsulation collect_args (Class *object, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3); - - /** - * Same as above, but take - * a reference instead of a - * pointer. This allows us - * to be a little - * convenient, as we can - * use @p{object} or - * @p{this}, without taking - * care that one is a - * reference and the other - * a pointer. - */ - FunEncapsulation collect_args (Class &object, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3); - - private: - /** - * Space to temporarily store - * the function pointer. - */ - FunPtr fun_ptr; - }; - - /** - * Declare a function that uses - * the @ref{ArgCollector} as - * friend. - */ - template - friend - typename MemFunData3::ArgCollector - encapsulate (void (Class_::*fun_ptr)(Arg1_,Arg2_,Arg3_)); - -#ifdef DEAL_II_TEMPL_CONST_MEM_PTR_BUG - template - friend - typename MemFunData3::ArgCollector - encapsulate (void (Class_::*fun_ptr)(Arg1_,Arg2_,Arg3_) const); -#endif - }; - - - -/** - * Class to store the parameters of a quaternary function. For more - * information on use and internals of this class see the report on - * multithreading. - * - * @author Wolfgang Bangerth, 2000 - */ - template - class MemFunData4 : public FunDataBase - { - public: - /** - * Typedef a pointer to a member - * function which we will call - * from this class. - */ - typedef typename MemFunPtr4::type FunPtr; - - /** - * Constructor. Store pointer to - * the function and the values of - * the arguments. - */ - MemFunData4 (FunPtr fun_ptr, - Class *object, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4); - - /** - * Copy constructor. - */ - MemFunData4 (const MemFunData4 &fun_data4); - - /** - * Virtual constructor. - */ - virtual FunDataBase * clone () const; - - private: - - /** - * Pointer to the function to be - * called and values of the - * arguments to be passed. - */ - FunPtr fun_ptr; - - /** - * Pointer to the object which - * we shall work on. - */ - Class *object; - - /** - * Values of the arguments of the - * function to be called. - */ - Arg1 arg1; - Arg2 arg2; - Arg3 arg3; - Arg4 arg4; - - /** - * Static function used as entry - * point for the new thread. - */ - static void * thread_entry_point (void *arg); - - /** - * Helper class, used to collect - * the values of the parameters - * which we will pass to the - * function, once we know its - * type. - */ - class ArgCollector - { - public: - /** - * Typedef the function - * pointer type of the - * underlying class to a - * local type. - */ - typedef typename MemFunData4::FunPtr FunPtr; - - /** - * Constructor. Take and store a - * pointer to the function which - * is to be called. - */ - ArgCollector (FunPtr fun_ptr); - - /** - * Take the arguments with - * which we want to call the - * function and produce and - * object of the desired type - * from that. - */ - FunEncapsulation collect_args (Class *object, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4); - - /** - * Same as above, but take - * a reference instead of a - * pointer. This allows us - * to be a little - * convenient, as we can - * use @p{object} or - * @p{this}, without taking - * care that one is a - * reference and the other - * a pointer. - */ - FunEncapsulation collect_args (Class &object, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4); - private: - /** - * Space to temporarily store - * the function pointer. - */ - FunPtr fun_ptr; - }; - - /** - * Declare a function that uses - * the @ref{ArgCollector} as - * friend. - */ - template - friend - typename MemFunData4::ArgCollector - encapsulate (void (Class_::*fun_ptr)(Arg1_, Arg2_, Arg3_, Arg4_)); - -#ifdef DEAL_II_TEMPL_CONST_MEM_PTR_BUG - template - friend - typename MemFunData4::ArgCollector - encapsulate (void (Class_::*fun_ptr)(Arg1_, Arg2_, Arg3_, Arg4_) const); -#endif -}; - - - -/** - * Class to store the parameters of a quintary function. For more - * information on use and internals of this class see the report on - * multithreading. - * - * @author Wolfgang Bangerth, 2000 - */ - template - class MemFunData5 : public FunDataBase - { - public: - /** - * Typedef a pointer to a member - * function which we will call - * from this class. - */ - typedef typename MemFunPtr5::type FunPtr; - - /** - * Constructor. Store pointer to - * the function and the values of - * the arguments. - */ - MemFunData5 (FunPtr fun_ptr, - Class *object, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5); - - /** - * Copy constructor. - */ - MemFunData5 (const MemFunData5 &fun_data5); - - /** - * Virtual constructor. - */ - virtual FunDataBase * clone () const; - - private: - - /** - * Pointer to the function to be - * called and values of the - * arguments to be passed. - */ - FunPtr fun_ptr; - - /** - * Pointer to the object which - * we shall work on. - */ - Class *object; - - /** - * Values of the arguments of the - * function to be called. - */ - Arg1 arg1; - Arg2 arg2; - Arg3 arg3; - Arg4 arg4; - Arg5 arg5; - - /** - * Static function used as entry - * point for the new thread. - */ - static void * thread_entry_point (void *arg); - - /** - * Helper class, used to collect - * the values of the parameters - * which we will pass to the - * function, once we know its - * type. - */ - class ArgCollector - { - public: - /** - * Typedef the function - * pointer type of the - * underlying class to a - * local type. - */ - typedef typename MemFunData5::FunPtr FunPtr; - - /** - * Constructor. Take and store a - * pointer to the function which - * is to be called. - */ - ArgCollector (FunPtr fun_ptr); - - /** - * Take the arguments with - * which we want to call the - * function and produce and - * object of the desired type - * from that. - */ - FunEncapsulation collect_args (Class *object, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5); - - /** - * Same as above, but take - * a reference instead of a - * pointer. This allows us - * to be a little - * convenient, as we can - * use @p{object} or - * @p{this}, without taking - * care that one is a - * reference and the other - * a pointer. - */ - FunEncapsulation collect_args (Class &object, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5); - private: - /** - * Space to temporarily store - * the function pointer. - */ - FunPtr fun_ptr; - }; - - /** - * Declare a function that uses - * the @ref{ArgCollector} as - * friend. - */ - template - friend - typename MemFunData5::ArgCollector - encapsulate (void (Class_::*fun_ptr)(Arg1_, Arg2_, Arg3_, - Arg4_, Arg5_)); - -#ifdef DEAL_II_TEMPL_CONST_MEM_PTR_BUG - template - friend - typename MemFunData5::ArgCollector - encapsulate (void (Class_::*fun_ptr)(Arg1_, Arg2_, Arg3_, - Arg4_, Arg5_) const); -#endif - }; - - - -/** - * Class to store the parameters of a function with 6 arguments. For - * more information on use and internals of this class see the report - * on this subject. - * - * @author Wolfgang Bangerth, Ralf Hartmann, 2000 - */ - template - class MemFunData6 : public FunDataBase - { - public: - /** - * Typedef a pointer to a member - * function which we will call - * from this class. - */ - typedef typename MemFunPtr6::type FunPtr; - - /** - * Constructor. Store pointer to - * the function and the values of - * the arguments. - */ - MemFunData6 (FunPtr fun_ptr, - Class *object, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5, - Arg6 arg6); - - /** - * Copy constructor. - */ - MemFunData6 (const MemFunData6 &fun_data6); - - /** - * Virtual constructor. - */ - virtual FunDataBase * clone () const; - - private: - - /** - * Pointer to the function to be - * called and values of the - * arguments to be passed. - */ - FunPtr fun_ptr; - - /** - * Pointer to the object which - * we shall work on. - */ - Class *object; - - /** - * Values of the arguments of the - * function to be called. - */ - Arg1 arg1; - Arg2 arg2; - Arg3 arg3; - Arg4 arg4; - Arg5 arg5; - Arg6 arg6; - - /** - * Static function used as entry - * point for the new thread. - */ - static void * thread_entry_point (void *arg); - - /** - * Helper class, used to collect - * the values of the parameters - * which we will pass to the - * function, once we know its - * type. - */ - class ArgCollector - { - public: - /** - * Typedef the function - * pointer type of the - * underlying class to a - * local type. - */ - typedef typename MemFunData6::FunPtr FunPtr; - - /** - * Constructor. Take and store a - * pointer to the function which - * is to be called. - */ - ArgCollector (FunPtr fun_ptr); - - /** - * Take the arguments with - * which we want to call the - * function and produce and - * object of the desired type - * from that. - */ - FunEncapsulation collect_args (Class *object, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5, - Arg6 arg6); - - /** - * Same as above, but take - * a reference instead of a - * pointer. This allows us - * to be a little - * convenient, as we can - * use @p{object} or - * @p{this}, without taking - * care that one is a - * reference and the other - * a pointer. - */ - FunEncapsulation collect_args (Class &object, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5, - Arg6 arg6); - private: - /** - * Space to temporarily store - * the function pointer. - */ - FunPtr fun_ptr; - }; - - /** - * Declare a function that uses - * the @ref{ArgCollector} as - * friend. - */ - template - friend - typename MemFunData6::ArgCollector - encapsulate (void (Class_::*fun_ptr)(Arg1_, Arg2_, Arg3_, - Arg4_, Arg5_, Arg6_)); - -#ifdef DEAL_II_TEMPL_CONST_MEM_PTR_BUG - template - friend - typename MemFunData6::ArgCollector - encapsulate (void (Class_::*fun_ptr)(Arg1_, Arg2_, Arg3_, - Arg4_, Arg5_, Arg6_) const); -#endif - }; - - - -/** - * Class to store the parameters of a function with 7 arguments. For - * more information on use and internals of this class see the report - * on this subject. - * - * @author Wolfgang Bangerth, Ralf Hartmann, 2001 - */ - template - class MemFunData7 : public FunDataBase - { - public: - /** - * Typedef a pointer to a member - * function which we will call - * from this class. - */ - typedef typename MemFunPtr7::type FunPtr; - - /** - * Constructor. Store pointer to - * the function and the values of - * the arguments. - */ - MemFunData7 (FunPtr fun_ptr, - Class *object, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5, - Arg6 arg6, - Arg7 arg7); - - /** - * Copy constructor. - */ - MemFunData7 (const MemFunData7 &fun_data7); - - /** - * Virtual constructor. - */ - virtual FunDataBase * clone () const; - - private: - - /** - * Pointer to the function to be - * called and values of the - * arguments to be passed. - */ - FunPtr fun_ptr; - - /** - * Pointer to the object which - * we shall work on. - */ - Class *object; - - /** - * Values of the arguments of the - * function to be called. - */ - Arg1 arg1; - Arg2 arg2; - Arg3 arg3; - Arg4 arg4; - Arg5 arg5; - Arg6 arg6; - Arg7 arg7; - - /** - * Static function used as entry - * point for the new thread. - */ - static void * thread_entry_point (void *arg); - - /** - * Helper class, used to collect - * the values of the parameters - * which we will pass to the - * function, once we know its - * type. - */ - class ArgCollector - { - public: - /** - * Typedef the function - * pointer type of the - * underlying class to a - * local type. - */ - typedef typename MemFunData7::FunPtr FunPtr; - - /** - * Constructor. Take and store a - * pointer to the function which - * is to be called. - */ - ArgCollector (FunPtr fun_ptr); - - /** - * Take the arguments with - * which we want to call the - * function and produce and - * object of the desired type - * from that. - */ - FunEncapsulation collect_args (Class *object, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5, - Arg6 arg6, - Arg7 arg7); - - /** - * Same as above, but take - * a reference instead of a - * pointer. This allows us - * to be a little - * convenient, as we can - * use @p{object} or - * @p{this}, without taking - * care that one is a - * reference and the other - * a pointer. - */ - FunEncapsulation collect_args (Class &object, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5, - Arg6 arg6, - Arg7 arg7); - private: - /** - * Space to temporarily store - * the function pointer. - */ - FunPtr fun_ptr; - }; - - /** - * Declare a function that uses - * the @ref{ArgCollector} as - * friend. - */ - template - friend - typename MemFunData7::ArgCollector - encapsulate (void (Class_::*fun_ptr)(Arg1_, Arg2_, Arg3_, - Arg4_, Arg5_, Arg6_, Arg7_)); - -#ifdef DEAL_II_TEMPL_CONST_MEM_PTR_BUG - template - friend - typename MemFunData7::ArgCollector - encapsulate (void (Class_::*fun_ptr)(Arg1_, Arg2_, Arg3_, - Arg4_, Arg5_, Arg6_, Arg7_) const); -#endif - }; - - -/** - * Class to store the parameters of a function with 8 arguments. For - * more information on use and internals of this class see the report - * on this subject. - * - * @author Wolfgang Bangerth, Ralf Hartmann, 2001 - */ - template - class MemFunData8 : public FunDataBase - { - public: - /** - * Typedef a pointer to a member - * function which we will call - * from this class. - */ - typedef typename MemFunPtr8::type FunPtr; - - /** - * Constructor. Store pointer to - * the function and the values of - * the arguments. - */ - MemFunData8 (FunPtr fun_ptr, - Class *object, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5, - Arg6 arg6, - Arg7 arg7, - Arg8 arg8); - - /** - * Copy constructor. - */ - MemFunData8 (const MemFunData8 &fun_data8); - - /** - * Virtual constructor. - */ - virtual FunDataBase * clone () const; - - private: - - /** - * Pointer to the function to be - * called and values of the - * arguments to be passed. - */ - FunPtr fun_ptr; - - /** - * Pointer to the object which - * we shall work on. - */ - Class *object; - - /** - * Values of the arguments of the - * function to be called. - */ - Arg1 arg1; - Arg2 arg2; - Arg3 arg3; - Arg4 arg4; - Arg5 arg5; - Arg6 arg6; - Arg7 arg7; - Arg8 arg8; - - /** - * Static function used as entry - * point for the new thread. - */ - static void * thread_entry_point (void *arg); - - /** - * Helper class, used to collect - * the values of the parameters - * which we will pass to the - * function, once we know its - * type. - */ - class ArgCollector - { - public: - /** - * Typedef the function - * pointer type of the - * underlying class to a - * local type. - */ - typedef typename MemFunData8::FunPtr FunPtr; - - /** - * Constructor. Take and store a - * pointer to the function which - * is to be called. - */ - ArgCollector (FunPtr fun_ptr); - - /** - * Take the arguments with - * which we want to call the - * function and produce and - * object of the desired type - * from that. - */ - FunEncapsulation collect_args (Class *object, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5, - Arg6 arg6, - Arg7 arg7, - Arg8 arg8); - - /** - * Same as above, but take - * a reference instead of a - * pointer. This allows us - * to be a little - * convenient, as we can - * use @p{object} or - * @p{this}, without taking - * care that one is a - * reference and the other - * a pointer. - */ - FunEncapsulation collect_args (Class &object, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5, - Arg6 arg6, - Arg7 arg7, - Arg8 arg8); - private: - /** - * Space to temporarily store - * the function pointer. - */ - FunPtr fun_ptr; - }; - - /** - * Declare a function that uses - * the @ref{ArgCollector} as - * friend. - */ - template - friend - typename MemFunData8::ArgCollector - encapsulate (void (Class_::*fun_ptr)(Arg1_, Arg2_, Arg3_, - Arg4_, Arg5_, Arg6_, - Arg7_, Arg8_)); - -#ifdef DEAL_II_TEMPL_CONST_MEM_PTR_BUG - template - friend - typename MemFunData8::ArgCollector - encapsulate (void (Class_::*fun_ptr)(Arg1_, Arg2_, Arg3_, - Arg4_, Arg5_, Arg6_, - Arg7_, Arg8_) const); -#endif - }; - - -/** - * Class to store the parameters of a function with 9 arguments. For - * more information on use and internals of this class see the report - * on this subject. - * - * @author Wolfgang Bangerth, Ralf Hartmann, 2001 - */ - template - class MemFunData9 : public FunDataBase - { - public: - /** - * Typedef a pointer to a member - * function which we will call - * from this class. - */ - typedef typename MemFunPtr9::type FunPtr; - - /** - * Constructor. Store pointer to - * the function and the values of - * the arguments. - */ - MemFunData9 (FunPtr fun_ptr, - Class *object, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5, - Arg6 arg6, - Arg7 arg7, - Arg8 arg8, - Arg9 arg9); - - /** - * Copy constructor. - */ - MemFunData9 (const MemFunData9 &fun_data9); - - /** - * Virtual constructor. - */ - virtual FunDataBase * clone () const; - - private: - - /** - * Pointer to the function to be - * called and values of the - * arguments to be passed. - */ - FunPtr fun_ptr; - - /** - * Pointer to the object which - * we shall work on. - */ - Class *object; - - /** - * Values of the arguments of the - * function to be called. - */ - Arg1 arg1; - Arg2 arg2; - Arg3 arg3; - Arg4 arg4; - Arg5 arg5; - Arg6 arg6; - Arg7 arg7; - Arg8 arg8; - Arg9 arg9; - - /** - * Static function used as entry - * point for the new thread. - */ - static void * thread_entry_point (void *arg); - - /** - * Helper class, used to collect - * the values of the parameters - * which we will pass to the - * function, once we know its - * type. - */ - class ArgCollector - { - public: - /** - * Typedef the function - * pointer type of the - * underlying class to a - * local type. - */ - typedef typename MemFunData9::FunPtr FunPtr; - - /** - * Constructor. Take and store a - * pointer to the function which - * is to be called. - */ - ArgCollector (FunPtr fun_ptr); - - /** - * Take the arguments with - * which we want to call the - * function and produce and - * object of the desired type - * from that. - */ - FunEncapsulation collect_args (Class *object, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5, - Arg6 arg6, - Arg7 arg7, - Arg8 arg8, - Arg9 arg9); - - /** - * Same as above, but take - * a reference instead of a - * pointer. This allows us - * to be a little - * convenient, as we can - * use @p{object} or - * @p{this}, without taking - * care that one is a - * reference and the other - * a pointer. - */ - FunEncapsulation collect_args (Class &object, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5, - Arg6 arg6, - Arg7 arg7, - Arg8 arg8, - Arg9 arg9); - private: - /** - * Space to temporarily store - * the function pointer. - */ - FunPtr fun_ptr; - }; - - /** - * Declare a function that uses - * the @ref{ArgCollector} as - * friend. - */ - template - friend - typename MemFunData9::ArgCollector - encapsulate (void (Class_::*fun_ptr)(Arg1_, Arg2_, Arg3_, - Arg4_, Arg5_, Arg6_, - Arg7_, Arg8_, Arg9_)); - -#ifdef DEAL_II_TEMPL_CONST_MEM_PTR_BUG - template - friend - typename MemFunData9::ArgCollector - encapsulate (void (Class_::*fun_ptr)(Arg1_, Arg2_, Arg3_, - Arg4_, Arg5_, Arg6_, - Arg7_, Arg8_, Arg9_) const); -#endif - }; - - -/** - * Class to store the parameters of a function with 10 arguments. For - * more information on use and internals of this class see the report - * on this subject. - * - * @author Wolfgang Bangerth, Ralf Hartmann, 2001 - */ - template - class MemFunData10 : public FunDataBase - { - public: - /** - * Typedef a pointer to a member - * function which we will call - * from this class. - */ - typedef typename MemFunPtr10::type FunPtr; - - /** - * Constructor. Store pointer to - * the function and the values of - * the arguments. - */ - MemFunData10 (FunPtr fun_ptr, - Class *object, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5, - Arg6 arg6, - Arg7 arg7, - Arg8 arg8, - Arg9 arg9, - Arg10 arg10); - - /** - * Copy constructor. - */ - MemFunData10 (const MemFunData10 &fun_data10); - - /** - * Virtual constructor. - */ - virtual FunDataBase * clone () const; - - private: - - /** - * Pointer to the function to be - * called and values of the - * arguments to be passed. - */ - FunPtr fun_ptr; - - /** - * Pointer to the object which - * we shall work on. - */ - Class *object; - - /** - * Values of the arguments of the - * function to be called. - */ - Arg1 arg1; - Arg2 arg2; - Arg3 arg3; - Arg4 arg4; - Arg5 arg5; - Arg6 arg6; - Arg7 arg7; - Arg8 arg8; - Arg9 arg9; - Arg10 arg10; - - /** - * Static function used as entry - * point for the new thread. - */ - static void * thread_entry_point (void *arg); - - /** - * Helper class, used to collect - * the values of the parameters - * which we will pass to the - * function, once we know its - * type. - */ - class ArgCollector - { - public: - /** - * Typedef the function - * pointer type of the - * underlying class to a - * local type. - */ - typedef typename MemFunData10::FunPtr FunPtr; - - /** - * Constructor. Take and store a - * pointer to the function which - * is to be called. - */ - ArgCollector (FunPtr fun_ptr); - - /** - * Take the arguments with - * which we want to call the - * function and produce and - * object of the desired type - * from that. - */ - FunEncapsulation collect_args (Class *object, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5, - Arg6 arg6, - Arg7 arg7, - Arg8 arg8, - Arg9 arg9, - Arg10 arg10); - - /** - * Same as above, but take - * a reference instead of a - * pointer. This allows us - * to be a little - * convenient, as we can - * use @p{object} or - * @p{this}, without taking - * care that one is a - * reference and the other - * a pointer. - */ - FunEncapsulation collect_args (Class &object, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5, - Arg6 arg6, - Arg7 arg7, - Arg8 arg8, - Arg9 arg9, - Arg10 arg10); - private: - /** - * Space to temporarily store - * the function pointer. - */ - FunPtr fun_ptr; - }; - - /** - * Declare a function that uses - * the @ref{ArgCollector} as - * friend. - */ - template - friend - typename MemFunData10::ArgCollector - encapsulate (void (Class_::*fun_ptr)(Arg1_, Arg2_, Arg3_, - Arg4_, Arg5_, Arg6_, - Arg7_, Arg8_, Arg9_, Arg10_)); - -#ifdef DEAL_II_TEMPL_CONST_MEM_PTR_BUG - template - friend - typename MemFunData10::ArgCollector - encapsulate (void (Class_::*fun_ptr)(Arg1_, Arg2_, Arg3_, - Arg4_, Arg5_, Arg6_, - Arg7_, Arg8_, Arg9_, Arg10_) const); -#endif - }; - - - - /** - * Encapsulate a function pointer - * into an object with which a new - * thread can later be spawned. - * For more information on use and - * internals of this class see the - * report on multithreading. - * - * This function exists once for - * each number of parameters. - */ - inline - FunData0::ArgCollector - encapsulate (void (*fun_ptr)()); - - /** - * Encapsulate a function pointer - * into an object with which a new - * thread can later be spawned. - * For more information on use and - * internals of this class see the - * report on multithreading. - * - * This function exists once for - * each number of parameters. - */ - template - inline - typename FunData1::ArgCollector - encapsulate (void (*fun_ptr)(Arg1)); - - - /** - * Encapsulate a function pointer - * into an object with which a new - * thread can later be spawned. - * For more information on use and - * internals of this class see the - * report on multithreading. - * - * This function exists once for - * each number of parameters. - */ - template - inline - typename FunData2::ArgCollector - encapsulate (void (*fun_ptr)(Arg1, Arg2)); - - - /** - * Encapsulate a function pointer - * into an object with which a new - * thread can later be spawned. - * For more information on use and - * internals of this class see the - * report on multithreading. - * - * This function exists once for - * each number of parameters. - */ - template - inline - typename FunData3::ArgCollector - encapsulate (void (*fun_ptr)(Arg1, Arg2, Arg3)); - - - /** - * Encapsulate a function pointer - * into an object with which a new - * thread can later be spawned. - * For more information on use and - * internals of this class see the - * report on multithreading. - * - * This function exists once for - * each number of parameters. - */ - template - inline - typename FunData4::ArgCollector - encapsulate (void (*fun_ptr)(Arg1, Arg2, Arg3, Arg4)); - - - - /** - * Encapsulate a function pointer - * into an object with which a new - * thread can later be spawned. - * For more information on use and - * internals of this class see the - * report on multithreading. - * - * This function exists once for - * each number of parameters. - */ - template - inline - typename FunData5::ArgCollector - encapsulate (void (*fun_ptr)(Arg1, Arg2, Arg3, Arg4, Arg5)); - - - /** - * Encapsulate a function pointer - * into an object with which a new - * thread can later be spawned. - * For more information on use and - * internals of this class see the - * report on multithreading. - * - * This function exists once for - * each number of parameters. - */ - template - inline - typename FunData6::ArgCollector - encapsulate (void (*fun_ptr)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6)); - - - /** - * Encapsulate a function pointer - * into an object with which a new - * thread can later be spawned. - * For more information on use and - * internals of this class see the - * report on multithreading. - * - * This function exists once for - * each number of parameters. - */ - template - inline - typename FunData7::ArgCollector - encapsulate (void (*fun_ptr)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7)); - - - /** - * Encapsulate a function pointer - * into an object with which a new - * thread can later be spawned. - * For more information on use and - * internals of this class see the - * report on multithreading. - * - * This function exists once for - * each number of parameters. - */ - template - inline - typename FunData8::ArgCollector - encapsulate (void (*fun_ptr)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8)); - - - /** - * Encapsulate a function pointer - * into an object with which a new - * thread can later be spawned. - * For more information on use and - * internals of this class see the - * report on multithreading. - * - * This function exists once for - * each number of parameters. - */ - template - inline - typename FunData9::ArgCollector - encapsulate (void (*fun_ptr)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9)); - - - /** - * Encapsulate a function pointer - * into an object with which a new - * thread can later be spawned. - * For more information on use and - * internals of this class see the - * report on multithreading. - * - * This function exists once for - * each number of parameters. - */ - template - inline - typename FunData10::ArgCollector - encapsulate (void (*fun_ptr)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9, Arg10)); - - - /** - * Encapsulate a member function - * pointer into an object with - * which a new thread can later be - * spawned. For more information - * on use and internals of this - * class see the report on this - * subject. - * - * This function exists once for - * each number of parameters. - */ - template - inline - typename MemFunData0::ArgCollector - encapsulate (void (Class::*fun_ptr)()); - -#ifdef DEAL_II_TEMPL_CONST_MEM_PTR_BUG - /** - * Same as the previous function, - * but for member functions marked - * @p{const}. This function should - * not be necessary, since the - * compiler should deduce a - * constant class as template - * argument, but we have to work - * around a bug in Intel's icc - * compiler with this. - */ - template - inline - typename MemFunData0::ArgCollector - encapsulate (void (Class::*fun_ptr)() const); -#endif - - /** - * Encapsulate a member function - * pointer into an object with - * which a new thread can later be - * spawned. For more information - * on use and internals of this - * class see the report on this - * subject. - * - * This function exists once for - * each number of parameters. - */ - template - inline - typename MemFunData1::ArgCollector - encapsulate (void (Class::*fun_ptr)(Arg1)); - -#ifdef DEAL_II_TEMPL_CONST_MEM_PTR_BUG - /** - * Same as the previous function, - * but for member functions marked - * @p{const}. This function should - * not be necessary, since the - * compiler should deduce a - * constant class as template - * argument, but we have to work - * around a bug in Intel's icc - * compiler with this. - */ - template - inline - typename MemFunData1::ArgCollector - encapsulate (void (Class::*fun_ptr)(Arg1) const); -#endif - - - /** - * Encapsulate a member function - * pointer into an object with - * which a new thread can later be - * spawned. For more information - * on use and internals of this - * class see the report on this - * subject. - * - * This function exists once for - * each number of parameters. - */ - template - inline - typename MemFunData2::ArgCollector - encapsulate (void (Class::*fun_ptr)(Arg1, Arg2)); - -#ifdef DEAL_II_TEMPL_CONST_MEM_PTR_BUG - /** - * Same as the previous function, - * but for member functions marked - * @p{const}. This function should - * not be necessary, since the - * compiler should deduce a - * constant class as template - * argument, but we have to work - * around a bug in Intel's icc - * compiler with this. - */ - template - inline - typename MemFunData2::ArgCollector - encapsulate (void (Class::*fun_ptr)(Arg1, Arg2) const); -#endif - - - /** - * Encapsulate a member function - * pointer into an object with - * which a new thread can later be - * spawned. For more information - * on use and internals of this - * class see the report on this - * subject. - * - * This function exists once for - * each number of parameters. - */ - template - inline - typename MemFunData3::ArgCollector - encapsulate (void (Class::*fun_ptr)(Arg1, Arg2, Arg3)); - -#ifdef DEAL_II_TEMPL_CONST_MEM_PTR_BUG - /** - * Same as the previous function, - * but for member functions marked - * @p{const}. This function should - * not be necessary, since the - * compiler should deduce a - * constant class as template - * argument, but we have to work - * around a bug in Intel's icc - * compiler with this. - */ - template - inline - typename MemFunData3::ArgCollector - encapsulate (void (Class::*fun_ptr)(Arg1, Arg2, Arg3) const); -#endif - - - /** - * Encapsulate a member function - * pointer into an object with - * which a new thread can later be - * spawned. For more information - * on use and internals of this - * class see the report on this - * subject. - * - * This function exists once for - * each number of parameters. - */ - template - inline - typename MemFunData4::ArgCollector - encapsulate (void (Class::*fun_ptr)(Arg1, Arg2, Arg3, Arg4)); - -#ifdef DEAL_II_TEMPL_CONST_MEM_PTR_BUG - /** - * Same as the previous function, - * but for member functions marked - * @p{const}. This function should - * not be necessary, since the - * compiler should deduce a - * constant class as template - * argument, but we have to work - * around a bug in Intel's icc - * compiler with this. - */ - template - inline - typename MemFunData4::ArgCollector - encapsulate (void (Class::*fun_ptr)(Arg1, Arg2, Arg3, Arg4) const); -#endif - - - /** - * Encapsulate a member function - * pointer into an object with - * which a new thread can later be - * spawned. For more information - * on use and internals of this - * class see the report on this - * subject. - * - * This function exists once for - * each number of parameters. - */ - template - inline - typename MemFunData5::ArgCollector - encapsulate (void (Class::*fun_ptr)(Arg1, Arg2, Arg3, Arg4, Arg5)); - -#ifdef DEAL_II_TEMPL_CONST_MEM_PTR_BUG - /** - * Same as the previous function, - * but for member functions marked - * @p{const}. This function should - * not be necessary, since the - * compiler should deduce a - * constant class as template - * argument, but we have to work - * around a bug in Intel's icc - * compiler with this. - */ - template - inline - typename MemFunData5::ArgCollector - encapsulate (void (Class::*fun_ptr)(Arg1, Arg2, Arg3, Arg4, Arg5) const); -#endif - - - /** - * Encapsulate a member function - * pointer into an object with - * which a new thread can later be - * spawned. For more information - * on use and internals of this - * class see the report on this - * subject. - * - * This function exists once for - * each number of parameters. - */ - template - inline - typename MemFunData6::ArgCollector - encapsulate (void (Class::*fun_ptr)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6)); - -#ifdef DEAL_II_TEMPL_CONST_MEM_PTR_BUG - /** - * Same as the previous function, - * but for member functions marked - * @p{const}. This function should - * not be necessary, since the - * compiler should deduce a - * constant class as template - * argument, but we have to work - * around a bug in Intel's icc - * compiler with this. - */ - template - inline - typename MemFunData6::ArgCollector - encapsulate (void (Class::*fun_ptr)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6) const); -#endif - - /** - * Encapsulate a member function - * pointer into an object with - * which a new thread can later be - * spawned. For more information - * on use and internals of this - * class see the report on this - * subject. - * - * This function exists once for - * each number of parameters. - */ - template - inline - typename MemFunData7::ArgCollector - encapsulate (void (Class::*fun_ptr)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7)); - -#ifdef DEAL_II_TEMPL_CONST_MEM_PTR_BUG - /** - * Same as the previous function, - * but for member functions marked - * @p{const}. This function should - * not be necessary, since the - * compiler should deduce a - * constant class as template - * argument, but we have to work - * around a bug in Intel's icc - * compiler with this. - */ - template - inline - typename MemFunData7::ArgCollector - encapsulate (void (Class::*fun_ptr)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7) const); -#endif - - /** - * Encapsulate a member function - * pointer into an object with - * which a new thread can later be - * spawned. For more information - * on use and internals of this - * class see the report on this - * subject. - * - * This function exists once for - * each number of parameters. - */ - template - inline - typename MemFunData8::ArgCollector - encapsulate (void (Class::*fun_ptr)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8)); - -#ifdef DEAL_II_TEMPL_CONST_MEM_PTR_BUG - /** - * Same as the previous function, - * but for member functions marked - * @p{const}. This function should - * not be necessary, since the - * compiler should deduce a - * constant class as template - * argument, but we have to work - * around a bug in Intel's icc - * compiler with this. - */ - template - inline - typename MemFunData8::ArgCollector - encapsulate (void (Class::*fun_ptr)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8) const); -#endif - - /** - * Encapsulate a member function - * pointer into an object with - * which a new thread can later be - * spawned. For more information - * on use and internals of this - * class see the report on this - * subject. - * - * This function exists once for - * each number of parameters. - */ - template - inline - typename MemFunData9::ArgCollector - encapsulate (void (Class::*fun_ptr)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9)); - -#ifdef DEAL_II_TEMPL_CONST_MEM_PTR_BUG - /** - * Same as the previous function, - * but for member functions marked - * @p{const}. This function should - * not be necessary, since the - * compiler should deduce a - * constant class as template - * argument, but we have to work - * around a bug in Intel's icc - * compiler with this. - */ - template - inline - typename MemFunData9::ArgCollector - encapsulate (void (Class::*fun_ptr)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9) const); -#endif - - /** - * Encapsulate a member function - * pointer into an object with - * which a new thread can later be - * spawned. For more information - * on use and internals of this - * class see the report on this - * subject. - * - * This function exists once for - * each number of parameters. - */ - template - inline - typename MemFunData10::ArgCollector - encapsulate (void (Class::*fun_ptr)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9, Arg10)); - -#ifdef DEAL_II_TEMPL_CONST_MEM_PTR_BUG - /** - * Same as the previous function, - * but for member functions marked - * @p{const}. This function should - * not be necessary, since the - * compiler should deduce a - * constant class as template - * argument, but we have to work - * around a bug in Intel's icc - * compiler with this. - */ - template - inline - typename MemFunData10::ArgCollector - encapsulate (void (Class::*fun_ptr)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9, Arg10) const); -#endif - - - /** - * Spawn a new thread using the - * function and parameters - * encapsulated in @p{fun_data}, and - * using the given thread manager - * object. - */ - void spawn (ThreadManager &thread_manager, - const FunEncapsulation &fun_data); - - - /** - * Spawn several threads at once, - * using the same parameters and - * calling the same function. - */ - void spawn_n (ThreadManager &thread_manager, - const FunEncapsulation &fun_encapsulation, - const unsigned int n_threads); - - /** - * Return the number of presently - * existing threads. This function - * may be useful in a situation - * where a large number of threads - * are concurrently, and you want - * to decide whether creation of - * another thread is reasonable or - * whether running the respective - * operation sequentially is more - * useful since already many more - * threads than processors are - * running. - * - * Note that the function returns - * the total number of threads, not - * those actually running. Some of - * the threads may be waiting for - * locks and mutexes, or may be - * sleeping until they are - * delivered with data to work on. - * - * Upon program start, this number - * is one. It is increased each - * time a thread is created using - * the @ref{Threads::spawn} or - * @ref{Threads::spawn_n} - * functions. It is decreased once - * a thread terminates by returning - * from the function that was - * spawned. - * - * Note that this means that only - * threads created and terminated - * through the interfaces of this - * namespace are taken care of. If - * threads are created by directly - * calling the respective functions - * of the operating system - * (e.g. @p{pthread_create} for the - * POSIX thread interface), or if - * they are killed (e.g. either - * through @p{pthread_exit} from - * the spawned thread, or - * @p{pthread_kill} from another - * thread), then these events are - * not registered and counted for - * the result of this function. - */ - unsigned int n_existing_threads (); - - /** - * Split the range @p{[begin,end)} - * into @p{n_intervals} subintervals - * of equal size. The last interval - * will be a little bit larger, if - * the number of elements in the - * whole range is not exactly - * divisible by @p{n_intervals}. The - * type of the iterators has to - * fulfill the requirements of a - * forward iterator, - * i.e. @p{operator++} must be - * available, and of course it must - * be assignable. - * - * A list of subintervals is - * returned as a vector of pairs of - * iterators, where each pair - * denotes the range - * @p{[begin[i],end[i])}. - */ - template - std::vector > - split_range (const ForwardIterator &begin, - const ForwardIterator &end, - const unsigned int n_intervals); - - /** - * Split the interval @p{[begin,end)} - * into subintervals of (almost) - * equal size. This function works - * mostly as the one before, with - * the difference that instead of - * iterators, now values are taken - * that define the whole interval. - */ - std::vector > - split_interval (const unsigned int begin, - const unsigned int end, - const unsigned int n_intervals); - - - -/** - * This class is used to make some sanity checks on the numbers of - * objects of some types related with thread spawning, which are - * created and deleted. This is a helpful thing when trying to - * implement the data copying using @p{clone} functions etc, in order to - * avoid that there are some objects which are copied but not deleted. - * - * It basically only monitors the number of objects which is alive at - * each time, and complains if the number is nonzero when the counting - * object is deleted. Since one will probably want to use one global - * counter, the complaint is raised at the end of the program, and - * then means that somewhen within the lifetime of your program there - * has occured a memory leak. - * - * This class is not meant for public use. - * - * @author Wolfgang Bangerth, 2000 - */ - struct FunDataCounter - { - /** - * Constructor. Sets all - * counters to zero. - */ - FunDataCounter (); - - /** - * Destructor. Check whether - * the total number of objects - * is zero, otherwise throw an - * exception. - */ - ~FunDataCounter (); - - /** - * Counters for the two types - * of objects which we - * presently monitor. - */ - unsigned int n_fun_encapsulation_objects; - unsigned int n_fun_data_base_objects; - - /** - * Exception - */ - DeclException2 (ExcObjectsExist, - char*, int, - << "There are still " << arg2 << " objects of type " - << arg1 << " alive. You probably have a memory " - << "leak somewhere."); - }; - - - /** - * The following function is used - * for internal bookkeeping of the - * number of existing threads. It - * is not thought for use in - * application programs, but only - * for use in the template - * functions below. - */ - void register_new_thread (); - - /** - * The following function is used - * for internal bookkeeping of the - * number of existing threads. It - * is not thought for use in - * application programs, but only - * for use in the template - * functions below. - */ - void deregister_new_thread (); - - /** - * If in a sub-thread an exception - * is thrown, it is not propagated - * to the main thread. Therefore, - * the exception handler that is - * provided by the applications - * main function or some of its - * other parts will not be able to - * catch these - * exceptions. Therefore, we have - * to provide an exception handler - * in the top function of each - * sub-thread that at least catches - * the exception and prints some - * information, rather than letting - * the operating system to just - * kill the program without a - * message. In each of the - * functions we use as entry points - * to new threads, we therefore - * install a try-catch block, and - * if an exception of type - * @p{std::exception} is caught, it - * passes over control to this - * function, which will then - * provide some output. - */ - void handle_std_exception (const std::exception &exc); - - /** - * Same as above, but the type of - * the exception is not derived - * from @p{std::exception}, so - * there is little way to provide - * something more useful. - */ - void handle_unknown_exception (); - -} // end declarations of namespace Threads - - - - - - - -/* ----------- implementation of functions in namespace Threads ---------- */ -namespace Threads -{ - -/* ---------------------- FunData0 implementation ------------------------ */ - - template - FunData0::FunData0 (FunPtr fun_ptr) : - FunDataBase (&FunData0::thread_entry_point), - fun_ptr (fun_ptr) - {} - - - - template - FunData0::FunData0 (const FunData0 &fun_data) : - FunDataBase (fun_data), - fun_ptr (fun_data.fun_ptr) - {} - - - - template - FunDataBase * - FunData0::clone () const - { - return new FunData0 (*this); - } - - - - template - void * - FunData0::thread_entry_point (void *arg) - { - // convenience typedef, since we - // will need that class name - // several times below - typedef FunData0 ThisClass; - - FunEncapsulation *fun_encapsulation - = reinterpret_cast(arg); - const ThisClass *fun_data - = dynamic_cast (fun_encapsulation->fun_data_base); - - // copy the parameters - typename ThisClass::FunPtr fun_ptr = fun_data->fun_ptr; - - - // copying of parameters is done, - // now we can release the lock on - // @p{fun_data}, by first making - // sure that the main thread is - // hanging in the condition - // variable's wait() function, - // and then signalling that the - // condition has been met, - // i.e. that the data has been - // copied. (note that there can - // be only one listener, so - // signal() is fine and we don't - // need broadcast()) - fun_data->lock.acquire (); - fun_data->condition.signal (); - fun_data->lock.release (); - - // register new thread, call the - // function, and upon its return, - // de-register it again. 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 - register_new_thread (); - try - { - (*fun_ptr)(); - } - catch (const std::exception &exc) - { - handle_std_exception (exc); - } - catch (...) - { - handle_unknown_exception (); - }; - deregister_new_thread (); - - return 0; - } - - - - template - FunData0::ArgCollector::ArgCollector (FunPtr fun_ptr) : - fun_ptr (fun_ptr) - {} - - - - template - FunEncapsulation - FunData0::ArgCollector::collect_args () - { - return new FunData0(fun_ptr); - } - - - -/* ---------------------- FunData1 implementation ------------------------ */ - - template - FunData1::FunData1 (FunPtr fun_ptr, - Arg1 arg1) : - FunDataBase (&FunData1::thread_entry_point), - fun_ptr (fun_ptr), - arg1 (arg1) - {} - - - - template - FunData1::FunData1 (const FunData1 &fun_data) : - FunDataBase (fun_data), - fun_ptr (fun_data.fun_ptr), - arg1 (fun_data.arg1) - {} - - - - template - FunDataBase * - FunData1::clone () const - { - return new FunData1 (*this); - } - - - - template - void * - FunData1::thread_entry_point (void *arg) - { - // convenience typedef, since we - // will need that class name - // several times below - typedef FunData1 ThisClass; - - FunEncapsulation *fun_encapsulation - = reinterpret_cast(arg); - const ThisClass *fun_data - = dynamic_cast (fun_encapsulation->fun_data_base); - - // copy the parameters - typename ThisClass::FunPtr fun_ptr = fun_data->fun_ptr; - Arg1 arg1 = fun_data->arg1; - - - // copying of parameters is done, - // now we can release the lock on - // @p{fun_data}, by first making - // sure that the main thread is - // hanging in the condition - // variable's wait() function, - // and then signalling that the - // condition has been met, - // i.e. that the data has been - // copied. (note that there can - // be only one listener, so - // signal() is fine and we don't - // need broadcast()) - fun_data->lock.acquire (); - fun_data->condition.signal (); - fun_data->lock.release (); - - // register new thread, call the - // function, and upon its return, - // de-register it again. 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 - register_new_thread (); - try - { - (*fun_ptr)(arg1); - } - catch (const std::exception &exc) - { - handle_std_exception (exc); - } - catch (...) - { - handle_unknown_exception (); - }; - deregister_new_thread (); - - return 0; - } - - - - template - FunData1::ArgCollector::ArgCollector (FunPtr fun_ptr) : - fun_ptr (fun_ptr) - {} - - - template - FunEncapsulation - FunData1::ArgCollector::collect_args (Arg1 arg1) - { - return new FunData1(fun_ptr, arg1); - } - - - - -/* ---------------------- FunData2 implementation ------------------------ */ - - template - FunData2::FunData2 (FunPtr fun_ptr, - Arg1 arg1, - Arg2 arg2) : - FunDataBase (&FunData2::thread_entry_point), - fun_ptr (fun_ptr), - arg1 (arg1), - arg2 (arg2) - {} - - - - template - FunData2::FunData2 (const FunData2 &fun_data) : - FunDataBase (fun_data), - fun_ptr (fun_data.fun_ptr), - arg1 (fun_data.arg1), - arg2 (fun_data.arg2) - {} - - - - template - FunDataBase * - FunData2::clone () const - { - return new FunData2 (*this); - } - - - - template - void * - FunData2::thread_entry_point (void *arg) - { - // convenience typedef, since we - // will need that class name - // several times below - typedef FunData2 ThisClass; - - FunEncapsulation *fun_encapsulation - = reinterpret_cast(arg); - const ThisClass *fun_data - = dynamic_cast (fun_encapsulation->fun_data_base); - - // copy the parameters - typename ThisClass::FunPtr fun_ptr = fun_data->fun_ptr; - Arg1 arg1 = fun_data->arg1; - Arg2 arg2 = fun_data->arg2; - - - // copying of parameters is done, - // now we can release the lock on - // @p{fun_data}, by first making - // sure that the main thread is - // hanging in the condition - // variable's wait() function, - // and then signalling that the - // condition has been met, - // i.e. that the data has been - // copied. (note that there can - // be only one listener, so - // signal() is fine and we don't - // need broadcast()) - fun_data->lock.acquire (); - fun_data->condition.signal (); - fun_data->lock.release (); - - // register new thread, call the - // function, and upon its return, - // de-register it again. 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 - register_new_thread (); - try - { - (*fun_ptr)(arg1, arg2); - } - catch (const std::exception &exc) - { - handle_std_exception (exc); - } - catch (...) - { - handle_unknown_exception (); - }; - deregister_new_thread (); - - return 0; - } - - - - template - FunData2::ArgCollector::ArgCollector (FunPtr fun_ptr) : - fun_ptr (fun_ptr) - {} - - - - template - FunEncapsulation - FunData2::ArgCollector::collect_args (Arg1 arg1, - Arg2 arg2) - { - return new FunData2(fun_ptr, arg1, arg2); - } - - - - -/* ---------------------- FunData3 implementation ------------------------ */ - - template - FunData3::FunData3 (FunPtr fun_ptr, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3) : - FunDataBase (&FunData3::thread_entry_point), - fun_ptr (fun_ptr), - arg1 (arg1), - arg2 (arg2), - arg3 (arg3) - {} - - - - template - FunData3::FunData3 (const FunData3 &fun_data) : - FunDataBase (fun_data), - fun_ptr (fun_data.fun_ptr), - arg1 (fun_data.arg1), - arg2 (fun_data.arg2), - arg3 (fun_data.arg3) - {} - - - - template - FunDataBase * - FunData3::clone () const - { - return new FunData3 (*this); - } - - - - template - void * - FunData3::thread_entry_point (void *arg) - { - // convenience typedef, since we - // will need that class name - // several times below - typedef FunData3 ThisClass; - - FunEncapsulation *fun_encapsulation - = reinterpret_cast(arg); - const ThisClass *fun_data - = dynamic_cast (fun_encapsulation->fun_data_base); - - // copy the parameters - typename ThisClass::FunPtr fun_ptr = fun_data->fun_ptr; - Arg1 arg1 = fun_data->arg1; - Arg2 arg2 = fun_data->arg2; - Arg3 arg3 = fun_data->arg3; - - - // copying of parameters is done, - // now we can release the lock on - // @p{fun_data}, by first making - // sure that the main thread is - // hanging in the condition - // variable's wait() function, - // and then signalling that the - // condition has been met, - // i.e. that the data has been - // copied. (note that there can - // be only one listener, so - // signal() is fine and we don't - // need broadcast()) - fun_data->lock.acquire (); - fun_data->condition.signal (); - fun_data->lock.release (); - - // register new thread, call the - // function, and upon its return, - // de-register it again. 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 - register_new_thread (); - try - { - (*fun_ptr)(arg1, arg2, arg3); - } - catch (const std::exception &exc) - { - handle_std_exception (exc); - } - catch (...) - { - handle_unknown_exception (); - }; - deregister_new_thread (); - - return 0; - } - - - - template - FunData3::ArgCollector::ArgCollector (FunPtr fun_ptr) : - fun_ptr (fun_ptr) - {} - - - - template - FunEncapsulation - FunData3::ArgCollector::collect_args (Arg1 arg1, - Arg2 arg2, - Arg3 arg3) - { - return new FunData3(fun_ptr, arg1, arg2, arg3); - } - - - - -/* ---------------------- FunData4 implementation ------------------------ */ - - template - FunData4::FunData4 (FunPtr fun_ptr, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4) : - FunDataBase (&FunData4::thread_entry_point), - fun_ptr (fun_ptr), - arg1 (arg1), - arg2 (arg2), - arg3 (arg3), - arg4 (arg4) - {} - - - - template - FunData4::FunData4 (const FunData4 &fun_data) : - FunDataBase (fun_data), - fun_ptr (fun_data.fun_ptr), - arg1 (fun_data.arg1), - arg2 (fun_data.arg2), - arg3 (fun_data.arg3), - arg4 (fun_data.arg4) - {} - - - - template - FunDataBase * - FunData4::clone () const - { - return new FunData4 (*this); - } - - - - template - void * - FunData4::thread_entry_point (void *arg) - { - // convenience typedef, since we - // will need that class name - // several times below - typedef FunData4 ThisClass; - - FunEncapsulation *fun_encapsulation - = reinterpret_cast(arg); - const ThisClass *fun_data - = dynamic_cast (fun_encapsulation->fun_data_base); - - // copy the parameters - typename ThisClass::FunPtr fun_ptr = fun_data->fun_ptr; - Arg1 arg1 = fun_data->arg1; - Arg2 arg2 = fun_data->arg2; - Arg3 arg3 = fun_data->arg3; - Arg4 arg4 = fun_data->arg4; - - - // copying of parameters is done, - // now we can release the lock on - // @p{fun_data}, by first making - // sure that the main thread is - // hanging in the condition - // variable's wait() function, - // and then signalling that the - // condition has been met, - // i.e. that the data has been - // copied. (note that there can - // be only one listener, so - // signal() is fine and we don't - // need broadcast()) - fun_data->lock.acquire (); - fun_data->condition.signal (); - fun_data->lock.release (); - - // register new thread, call the - // function, and upon its return, - // de-register it again. 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 - register_new_thread (); - try - { - (*fun_ptr)(arg1, arg2, arg3, arg4); - } - catch (const std::exception &exc) - { - handle_std_exception (exc); - } - catch (...) - { - handle_unknown_exception (); - }; - deregister_new_thread (); - - return 0; + /** + * 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; + }; + }; } - - template - FunData4::ArgCollector::ArgCollector (FunPtr fun_ptr) : - fun_ptr (fun_ptr) - {} + namespace 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 ::value> + class fun_encapsulator; + + + /** + * 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 ::value> + class mem_fun_encapsulator; + } +// ----------- encapsulators for member functions not taking any parameters - template - FunEncapsulation - FunData4::ArgCollector::collect_args (Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4) + namespace internal { - return new FunData4(fun_ptr, arg1, arg2, arg3, arg4); - } - - + /** + * 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) {}; -/* ---------------------- FunData5 implementation ------------------------ */ + inline + Thread + operator() () { + return mem_fun_wrapper (mem_fun_ptr, c, + ArgList()).fire_up (); + }; + + private: + C &c; + MemFunPtr mem_fun_ptr; + }; + + } - template - FunData5::FunData5 (FunPtr fun_ptr, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5) : - FunDataBase (&FunData5::thread_entry_point), - fun_ptr (fun_ptr), - arg1 (arg1), - arg2 (arg2), - arg3 (arg3), - arg4 (arg4), - arg5 (arg5) - {} + + /** + * Overload of the non-const spawn + * function for member functions with + * no arguments. + */ + template + inline + internal::mem_fun_encapsulator > + spawn (C &c, RT (C::*fun_ptr)()) { + return internal::mem_fun_encapsulator > (c,fun_ptr); + } + /** + * Overload of the spawn function for + * const member functions with no + * arguments. + */ + template + inline + internal::mem_fun_encapsulator > + spawn (const C &c, RT (C::*fun_ptr)() const) { + return internal::mem_fun_encapsulator > (c,fun_ptr); + } - template - FunData5::FunData5 (const FunData5 &fun_data) : - FunDataBase (fun_data), - fun_ptr (fun_data.fun_ptr), - arg1 (fun_data.arg1), - arg2 (fun_data.arg2), - arg3 (fun_data.arg3), - arg4 (fun_data.arg4), - arg5 (fun_data.arg5) - {} +// ----------- encapsulators for unary member functions - template - FunDataBase * - FunData5::clone () const + namespace internal { - return new FunData5 (*this); - } - + /** + * 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) {}; - template - void * - FunData5::thread_entry_point (void *arg) - { - // convenience typedef, since we - // will need that class name - // several times below - typedef FunData5 ThisClass; - - FunEncapsulation *fun_encapsulation - = reinterpret_cast(arg); - const ThisClass *fun_data - = dynamic_cast (fun_encapsulation->fun_data_base); - - // copy the parameters - typename ThisClass::FunPtr fun_ptr = fun_data->fun_ptr; - Arg1 arg1 = fun_data->arg1; - Arg2 arg2 = fun_data->arg2; - Arg3 arg3 = fun_data->arg3; - Arg4 arg4 = fun_data->arg4; - Arg5 arg5 = fun_data->arg5; - - - // copying of parameters is done, - // now we can release the lock on - // @p{fun_data}, by first making - // sure that the main thread is - // hanging in the condition - // variable's wait() function, - // and then signalling that the - // condition has been met, - // i.e. that the data has been - // copied. (note that there can - // be only one listener, so - // signal() is fine and we don't - // need broadcast()) - fun_data->lock.acquire (); - fun_data->condition.signal (); - fun_data->lock.release (); - - // register new thread, call the - // function, and upon its return, - // de-register it again. 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 - register_new_thread (); - try - { - (*fun_ptr)(arg1, arg2, arg3, arg4, arg5); - } - catch (const std::exception &exc) - { - handle_std_exception (exc); - } - catch (...) - { - handle_unknown_exception (); - }; - deregister_new_thread (); + 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; + }; - return 0; } + + /** + * Overload of the non-const spawn + * function for member functions with + * 1 argument. + */ + template + inline + internal::mem_fun_encapsulator > + spawn (C &c, RT (C::*fun_ptr)(Arg1)) { + return internal::mem_fun_encapsulator > (c,fun_ptr); + } + + /** + * Overload of the spawn function for + * const member functions with 1 + * argument. + */ + template + inline + internal::mem_fun_encapsulator > + spawn (const C &c, RT (C::*fun_ptr)(Arg1) const) { + return internal::mem_fun_encapsulator > (c,fun_ptr); + } - template - FunData5::ArgCollector::ArgCollector (FunPtr fun_ptr) : - fun_ptr (fun_ptr) - {} +// ----------- encapsulators for binary member functions - template - FunEncapsulation - FunData5::ArgCollector::collect_args (Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5) + namespace internal { - return new FunData5(fun_ptr, arg1, arg2, - arg3, arg4, arg5); - } - + /** + * 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; + }; -/* ---------------------- FunData6 implementation ------------------------ */ - - template - FunData6::FunData6 (FunPtr fun_ptr, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5, - Arg6 arg6) : - FunDataBase (&FunData6::thread_entry_point), - fun_ptr (fun_ptr), - arg1 (arg1), - arg2 (arg2), - arg3 (arg3), - arg4 (arg4), - arg5 (arg5), - arg6 (arg6) - {} - - - - template - FunData6::FunData6 (const FunData6 &fun_data) : - FunDataBase (fun_data), - fun_ptr (fun_data.fun_ptr), - arg1 (fun_data.arg1), - arg2 (fun_data.arg2), - arg3 (fun_data.arg3), - arg4 (fun_data.arg4), - arg5 (fun_data.arg5), - arg6 (fun_data.arg6) - {} - - - - template - FunDataBase * - FunData6::clone () const - { - return new FunData6 (*this); } + /** + * Overload of the non-const spawn + * function for member functions with + * 2 arguments. + */ + template + inline + internal::mem_fun_encapsulator > + spawn (C &c, RT (C::*fun_ptr)(Arg1,Arg2)) { + return internal::mem_fun_encapsulator > (c,fun_ptr); + } - template - void * - FunData6::thread_entry_point (void *arg) - { - // convenience typedef, since we - // will need that class name - // several times below - typedef FunData6 ThisClass; - - FunEncapsulation *fun_encapsulation - = reinterpret_cast(arg); - const ThisClass *fun_data - = dynamic_cast (fun_encapsulation->fun_data_base); - - // copy the parameters - typename ThisClass::FunPtr fun_ptr = fun_data->fun_ptr; - Arg1 arg1 = fun_data->arg1; - Arg2 arg2 = fun_data->arg2; - Arg3 arg3 = fun_data->arg3; - Arg4 arg4 = fun_data->arg4; - Arg5 arg5 = fun_data->arg5; - Arg6 arg6 = fun_data->arg6; - - - // copying of parameters is done, - // now we can release the lock on - // @p{fun_data}, by first making - // sure that the main thread is - // hanging in the condition - // variable's wait() function, - // and then signalling that the - // condition has been met, - // i.e. that the data has been - // copied. (note that there can - // be only one listener, so - // signal() is fine and we don't - // need broadcast()) - fun_data->lock.acquire (); - fun_data->condition.signal (); - fun_data->lock.release (); - - // register new thread, call the - // function, and upon its return, - // de-register it again. 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 - register_new_thread (); - try - { - (*fun_ptr)(arg1, arg2, arg3, arg4, arg5, arg6); - } - catch (const std::exception &exc) - { - handle_std_exception (exc); - } - catch (...) - { - handle_unknown_exception (); - }; - deregister_new_thread (); - - return 0; + /** + * Overload of the spawn function for + * const member functions with 2 + * arguments. + */ + template + inline + internal::mem_fun_encapsulator > + spawn (const C &c, RT (C::*fun_ptr)(Arg1,Arg2) const) { + return internal::mem_fun_encapsulator > (c,fun_ptr); } - template - FunData6::ArgCollector::ArgCollector (FunPtr fun_ptr) : - fun_ptr (fun_ptr) - {} +// ----------- encapsulators for ternary member functions + namespace 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) {}; - template - FunEncapsulation - FunData6::ArgCollector::collect_args (Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5, - Arg6 arg6) - { - return new FunData6(fun_ptr, arg1, arg2, - arg3, arg4, arg5, arg6); - } - + 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 > + spawn (C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3)) { + return internal::mem_fun_encapsulator > (c,fun_ptr); + } -/* ---------------------- FunData7 implementation ------------------------ */ - - template - FunData7::FunData7 (FunPtr fun_ptr, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5, - Arg6 arg6, - Arg7 arg7) : - FunDataBase (&FunData7::thread_entry_point), - fun_ptr (fun_ptr), - arg1 (arg1), - arg2 (arg2), - arg3 (arg3), - arg4 (arg4), - arg5 (arg5), - arg6 (arg6), - arg7 (arg7) - {} - - - - template - FunData7::FunData7 (const FunData7 &fun_data) : - FunDataBase (fun_data), - fun_ptr (fun_data.fun_ptr), - arg1 (fun_data.arg1), - arg2 (fun_data.arg2), - arg3 (fun_data.arg3), - arg4 (fun_data.arg4), - arg5 (fun_data.arg5), - arg6 (fun_data.arg6), - arg7 (fun_data.arg7) - {} - - - - template - FunDataBase * - FunData7::clone () const - { - return new FunData7 (*this); + /** + * Overload of the spawn function for + * const member functions with 3 + * arguments. + */ + template + inline + internal::mem_fun_encapsulator > + spawn (const C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3) const) { + return internal::mem_fun_encapsulator > (c,fun_ptr); } - template - void * - FunData7::thread_entry_point (void *arg) - { - // convenience typedef, since we - // will need that class name - // several times below - typedef FunData7 ThisClass; - - FunEncapsulation *fun_encapsulation - = reinterpret_cast(arg); - const ThisClass *fun_data - = dynamic_cast (fun_encapsulation->fun_data_base); - - // copy the parameters - typename ThisClass::FunPtr fun_ptr = fun_data->fun_ptr; - Arg1 arg1 = fun_data->arg1; - Arg2 arg2 = fun_data->arg2; - Arg3 arg3 = fun_data->arg3; - Arg4 arg4 = fun_data->arg4; - Arg5 arg5 = fun_data->arg5; - Arg6 arg6 = fun_data->arg6; - Arg7 arg7 = fun_data->arg7; - - - // copying of parameters is done, - // now we can release the lock on - // @p{fun_data}, by first making - // sure that the main thread is - // hanging in the condition - // variable's wait() function, - // and then signalling that the - // condition has been met, - // i.e. that the data has been - // copied. (note that there can - // be only one listener, so - // signal() is fine and we don't - // need broadcast()) - fun_data->lock.acquire (); - fun_data->condition.signal (); - fun_data->lock.release (); - - // register new thread, call the - // function, and upon its return, - // de-register it again. 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 - register_new_thread (); - try - { - (*fun_ptr)(arg1, arg2, arg3, arg4, arg5, arg6, arg7); - } - catch (const std::exception &exc) - { - handle_std_exception (exc); - } - catch (...) - { - handle_unknown_exception (); - }; - deregister_new_thread (); - - return 0; - } +// ----------- encapsulators for member functions with 4 arguments + namespace internal + { + /** + * Encapsulator class for member + * functions with 4 arguments. + */ + template + class mem_fun_encapsulator + { + typedef typename internal::mem_fun_ptr::type MemFunPtr; - template - FunData7::ArgCollector::ArgCollector (FunPtr fun_ptr) : - fun_ptr (fun_ptr) - {} + 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; + }; + + } - template - FunEncapsulation - FunData7::ArgCollector::collect_args (Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5, - Arg6 arg6, - Arg7 arg7) - { - return new FunData7(fun_ptr, arg1, arg2, - arg3, arg4, arg5, arg6, arg7); + /** + * Overload of the non-const spawn + * function for member functions with + * 4 arguments. + */ + template + inline + internal::mem_fun_encapsulator > + spawn (C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4)) { + return internal::mem_fun_encapsulator > (c,fun_ptr); } - - + /** + * Overload of the spawn function for + * const member functions with 4 + * arguments. + */ + template + inline + internal::mem_fun_encapsulator > + spawn (const C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4) const) { + return internal::mem_fun_encapsulator > (c,fun_ptr); + } -/* ---------------------- FunData8 implementation ------------------------ */ - - template - FunData8:: - FunData8 (FunPtr fun_ptr, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5, - Arg6 arg6, - Arg7 arg7, - Arg8 arg8) : - FunDataBase (&FunData8::thread_entry_point), - fun_ptr (fun_ptr), - arg1 (arg1), - arg2 (arg2), - arg3 (arg3), - arg4 (arg4), - arg5 (arg5), - arg6 (arg6), - arg7 (arg7), - arg8 (arg8) - {} - - - - template - FunData8:: - FunData8 (const FunData8 &fun_data) : - FunDataBase (fun_data), - fun_ptr (fun_data.fun_ptr), - arg1 (fun_data.arg1), - arg2 (fun_data.arg2), - arg3 (fun_data.arg3), - arg4 (fun_data.arg4), - arg5 (fun_data.arg5), - arg6 (fun_data.arg6), - arg7 (fun_data.arg7), - arg8 (fun_data.arg8) - {} - - - - template - FunDataBase * - FunData8::clone () const - { - return new FunData8 (*this); - } +// ----------- encapsulators for member functions with 5 arguments - template - void * - FunData8::thread_entry_point (void *arg) + namespace internal { - // convenience typedef, since we - // will need that class name - // several times below - typedef FunData8 ThisClass; - - FunEncapsulation *fun_encapsulation - = reinterpret_cast(arg); - const ThisClass *fun_data - = dynamic_cast (fun_encapsulation->fun_data_base); - - // copy the parameters - typename ThisClass::FunPtr fun_ptr = fun_data->fun_ptr; - Arg1 arg1 = fun_data->arg1; - Arg2 arg2 = fun_data->arg2; - Arg3 arg3 = fun_data->arg3; - Arg4 arg4 = fun_data->arg4; - Arg5 arg5 = fun_data->arg5; - Arg6 arg6 = fun_data->arg6; - Arg7 arg7 = fun_data->arg7; - Arg8 arg8 = fun_data->arg8; - - - // copying of parameters is done, - // now we can release the lock on - // @p{fun_data}, by first making - // sure that the main thread is - // hanging in the condition - // variable's wait() function, - // and then signalling that the - // condition has been met, - // i.e. that the data has been - // copied. (note that there can - // be only one listener, so - // signal() is fine and we don't - // need broadcast()) - fun_data->lock.acquire (); - fun_data->condition.signal (); - fun_data->lock.release (); - - // register new thread, call the - // function, and upon its return, - // de-register it again. 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 - register_new_thread (); - try - { - (*fun_ptr)(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); - } - catch (const std::exception &exc) - { - handle_std_exception (exc); - } - catch (...) - { - handle_unknown_exception (); - }; - deregister_new_thread (); + /** + * 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; + }; - return 0; } + /** + * Overload of the non-const spawn + * function for member functions with + * 5 arguments. + */ + template + inline + internal::mem_fun_encapsulator > + spawn (C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5)) { + return internal::mem_fun_encapsulator > (c,fun_ptr); + } - template - FunData8::ArgCollector::ArgCollector (FunPtr fun_ptr) : - fun_ptr (fun_ptr) - {} - + /** + * Overload of the spawn function for + * const member functions with 5 + * arguments. + */ + template + inline + internal::mem_fun_encapsulator > + spawn (const C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5) const) { + return internal::mem_fun_encapsulator > (c,fun_ptr); + } - template - FunEncapsulation - FunData8::ArgCollector::collect_args (Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5, - Arg6 arg6, - Arg7 arg7, - Arg8 arg8) - { - return new FunData8(fun_ptr, arg1, arg2, - arg3, arg4, arg5, arg6, - arg7, arg8); - } - +// ----------- encapsulators for member functions with 6 arguments + + namespace 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; + }; + } -/* ---------------------- FunData9 implementation ------------------------ */ - - template - FunData9:: - FunData9 (FunPtr fun_ptr, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5, - Arg6 arg6, - Arg7 arg7, - Arg8 arg8, - Arg9 arg9) : - FunDataBase (&FunData9::thread_entry_point), - fun_ptr (fun_ptr), - arg1 (arg1), - arg2 (arg2), - arg3 (arg3), - arg4 (arg4), - arg5 (arg5), - arg6 (arg6), - arg7 (arg7), - arg8 (arg8), - arg9 (arg9) - {} - - - - template - FunData9:: - FunData9 (const FunData9 &fun_data) : - FunDataBase (fun_data), - fun_ptr (fun_data.fun_ptr), - arg1 (fun_data.arg1), - arg2 (fun_data.arg2), - arg3 (fun_data.arg3), - arg4 (fun_data.arg4), - arg5 (fun_data.arg5), - arg6 (fun_data.arg6), - arg7 (fun_data.arg7), - arg8 (fun_data.arg8), - arg9 (fun_data.arg9) - {} - - - - template - FunDataBase * - FunData9::clone () const - { - return new FunData9 (*this); + + /** + * Overload of the non-const spawn + * function for member functions with + * 6 arguments. + */ + template + inline + internal::mem_fun_encapsulator > + spawn (C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5,Arg6)) { + return internal::mem_fun_encapsulator > (c,fun_ptr); } + /** + * Overload of the spawn function for + * const member functions with 6 + * arguments. + */ + template + inline + internal::mem_fun_encapsulator > + spawn (const C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5,Arg6) const) { + return internal::mem_fun_encapsulator > (c,fun_ptr); + } - template - void * - FunData9::thread_entry_point (void *arg) - { - // convenience typedef, since we - // will need that class name - // several times below - typedef FunData9 ThisClass; - - FunEncapsulation *fun_encapsulation - = reinterpret_cast(arg); - const ThisClass *fun_data - = dynamic_cast (fun_encapsulation->fun_data_base); - - // copy the parameters - typename ThisClass::FunPtr fun_ptr = fun_data->fun_ptr; - Arg1 arg1 = fun_data->arg1; - Arg2 arg2 = fun_data->arg2; - Arg3 arg3 = fun_data->arg3; - Arg4 arg4 = fun_data->arg4; - Arg5 arg5 = fun_data->arg5; - Arg6 arg6 = fun_data->arg6; - Arg7 arg7 = fun_data->arg7; - Arg8 arg8 = fun_data->arg8; - Arg9 arg9 = fun_data->arg9; - - - // copying of parameters is done, - // now we can release the lock on - // @p{fun_data}, by first making - // sure that the main thread is - // hanging in the condition - // variable's wait() function, - // and then signalling that the - // condition has been met, - // i.e. that the data has been - // copied. (note that there can - // be only one listener, so - // signal() is fine and we don't - // need broadcast()) - fun_data->lock.acquire (); - fun_data->condition.signal (); - fun_data->lock.release (); - - // register new thread, call the - // function, and upon its return, - // de-register it again. 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 - register_new_thread (); - try - { - (*fun_ptr)(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); - } - catch (const std::exception &exc) - { - handle_std_exception (exc); - } - catch (...) - { - handle_unknown_exception (); - }; - deregister_new_thread (); +// ----------- encapsulators for member functions with 7 arguments + + namespace 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; + }; - return 0; } + /** + * Overload of the non-const spawn + * function for member functions with + * 7 arguments. + */ + template + inline + internal::mem_fun_encapsulator > + spawn (C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5,Arg6,Arg7)) { + return internal::mem_fun_encapsulator > (c,fun_ptr); + } - template - FunData9::ArgCollector::ArgCollector (FunPtr fun_ptr) : - fun_ptr (fun_ptr) - {} - + /** + * Overload of the spawn function for + * const member functions with 7 + * arguments. + */ + template + inline + internal::mem_fun_encapsulator > + spawn (const C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5,Arg6,Arg7) const) { + return internal::mem_fun_encapsulator > (c,fun_ptr); + } - template - FunEncapsulation - FunData9::ArgCollector:: - collect_args (Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5, - Arg6 arg6, - Arg7 arg7, - Arg8 arg8, - Arg9 arg9) - { - return - new FunData9 - (fun_ptr, arg1, arg2, - arg3, arg4, arg5, arg6, - arg7, arg8, arg9); - } - +// ----------- encapsulators for member functions with 8 arguments + + namespace 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; + }; + } -/* ---------------------- FunData10 implementation ------------------------ */ - - template - FunData10:: - FunData10 (FunPtr fun_ptr, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5, - Arg6 arg6, - Arg7 arg7, - Arg8 arg8, - Arg9 arg9, - Arg10 arg10) : - FunDataBase (&FunData10::thread_entry_point), - fun_ptr (fun_ptr), - arg1 (arg1), - arg2 (arg2), - arg3 (arg3), - arg4 (arg4), - arg5 (arg5), - arg6 (arg6), - arg7 (arg7), - arg8 (arg8), - arg9 (arg9), - arg10 (arg10) - {} - - - - template - FunData10:: - FunData10 (const FunData10 &fun_data) : - FunDataBase (fun_data), - fun_ptr (fun_data.fun_ptr), - arg1 (fun_data.arg1), - arg2 (fun_data.arg2), - arg3 (fun_data.arg3), - arg4 (fun_data.arg4), - arg5 (fun_data.arg5), - arg6 (fun_data.arg6), - arg7 (fun_data.arg7), - arg8 (fun_data.arg8), - arg9 (fun_data.arg9), - arg10 (fun_data.arg10) - {} - - - - template - FunDataBase * - FunData10::clone () const - { - return new FunData10 (*this); + + /** + * Overload of the non-const spawn + * function for member functions with + * 8 arguments. + */ + template + inline + internal::mem_fun_encapsulator > + spawn (C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5, + Arg6,Arg7,Arg8)) { + return internal::mem_fun_encapsulator > (c,fun_ptr); } + /** + * Overload of the spawn function for + * const member functions with 8 + * arguments. + */ + template + inline + internal::mem_fun_encapsulator > + spawn (const C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5, + Arg6,Arg7,Arg8) const) { + return internal::mem_fun_encapsulator > (c,fun_ptr); + } - template - void * - FunData10::thread_entry_point (void *arg) - { - // convenience typedef, since we - // will need that class name - // several times below - typedef FunData10 ThisClass; - - FunEncapsulation *fun_encapsulation - = reinterpret_cast(arg); - const ThisClass *fun_data - = dynamic_cast (fun_encapsulation->fun_data_base); - - // copy the parameters - typename ThisClass::FunPtr fun_ptr = fun_data->fun_ptr; - Arg1 arg1 = fun_data->arg1; - Arg2 arg2 = fun_data->arg2; - Arg3 arg3 = fun_data->arg3; - Arg4 arg4 = fun_data->arg4; - Arg5 arg5 = fun_data->arg5; - Arg6 arg6 = fun_data->arg6; - Arg7 arg7 = fun_data->arg7; - Arg8 arg8 = fun_data->arg8; - Arg9 arg9 = fun_data->arg9; - Arg10 arg10 = fun_data->arg10; - - - // copying of parameters is done, - // now we can release the lock on - // @p{fun_data}, by first making - // sure that the main thread is - // hanging in the condition - // variable's wait() function, - // and then signalling that the - // condition has been met, - // i.e. that the data has been - // copied. (note that there can - // be only one listener, so - // signal() is fine and we don't - // need broadcast()) - fun_data->lock.acquire (); - fun_data->condition.signal (); - fun_data->lock.release (); - - // register new thread, call the - // function, and upon its return, - // de-register it again. 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 - register_new_thread (); - try - { - (*fun_ptr)(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); - } - catch (const std::exception &exc) - { - handle_std_exception (exc); - } - catch (...) - { - handle_unknown_exception (); - }; - deregister_new_thread (); +// ----------- encapsulators for member functions with 9 arguments + + namespace 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; + }; - return 0; } + /** + * Overload of the non-const spawn + * function for member functions with + * 9 arguments. + */ + template + inline + internal::mem_fun_encapsulator > + spawn (C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5, + Arg6,Arg7,Arg8,Arg9)) { + return internal::mem_fun_encapsulator > (c,fun_ptr); + } - template - FunData10::ArgCollector::ArgCollector (FunPtr fun_ptr) : - fun_ptr (fun_ptr) - {} - + /** + * Overload of the spawn function for + * const member functions with 9 + * arguments. + */ + template + inline + internal::mem_fun_encapsulator > + spawn (const C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5, + Arg6,Arg7,Arg8,Arg9) const) { + return internal::mem_fun_encapsulator > (c,fun_ptr); + } - template - FunEncapsulation - FunData10::ArgCollector:: - collect_args (Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5, - Arg6 arg6, - Arg7 arg7, - Arg8 arg8, - Arg9 arg9, - Arg10 arg10) - { - return - new FunData10 - (fun_ptr, arg1, arg2, - arg3, arg4, arg5, arg6, - arg7, arg8, arg9, arg10); - } - +// ----------- encapsulators for member functions with 10 arguments + + namespace 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 > + spawn (C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5, + Arg6,Arg7,Arg8,Arg9,Arg10)) { + return internal::mem_fun_encapsulator > (c,fun_ptr); + } -/* ---------------------- MemFunData0 implementation ------------------------ */ + /** + * Overload of the spawn function for + * const member functions with 10 + * arguments. + */ + template + inline + internal::mem_fun_encapsulator > + spawn (const C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5, + Arg6,Arg7,Arg8,Arg9,Arg10) const) { + return internal::mem_fun_encapsulator > (c,fun_ptr); + } - template - MemFunData0::MemFunData0 (FunPtr fun_ptr, - Class *object) : - FunDataBase (&MemFunData0::thread_entry_point), - fun_ptr (fun_ptr), - object (object) - {} +// ----------- encapsulators for functions not taking any parameters - template - MemFunData0::MemFunData0 (const MemFunData0 &fun_data) : - FunDataBase (fun_data), - fun_ptr (fun_data.fun_ptr), - object (fun_data.object) - {} + namespace 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; + }; + + } - template - FunDataBase * - MemFunData0::clone () const - { - return new MemFunData0 (*this); + + /** + * Overload of the spawn function for + * non-member or static member + * functions with no arguments. + */ + template + inline + internal::fun_encapsulator > + spawn (RT (*fun_ptr)()) { + return internal::fun_encapsulator > (fun_ptr); } - template - void * - MemFunData0::thread_entry_point (void *arg) - { - // convenience typedef, since we - // will need that class name - // several times below - typedef MemFunData0 ThisClass; - - FunEncapsulation *fun_encapsulation - = reinterpret_cast(arg); - const ThisClass *fun_data - = dynamic_cast (fun_encapsulation->fun_data_base); - - // copy the parameters - typename ThisClass::FunPtr fun_ptr = fun_data->fun_ptr; - Class *object = fun_data->object; - - // copying of parameters is done, - // now we can release the lock on - // @p{fun_data}, by first making - // sure that the main thread is - // hanging in the condition - // variable's wait() function, - // and then signalling that the - // condition has been met, - // i.e. that the data has been - // copied. (note that there can - // be only one listener, so - // signal() is fine and we don't - // need broadcast()) - fun_data->lock.acquire (); - fun_data->condition.signal (); - fun_data->lock.release (); - - // register new thread, call the - // function, and upon its return, - // de-register it again. 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 - register_new_thread (); - try - { - (object->*fun_ptr)(); - } - catch (const std::exception &exc) - { - handle_std_exception (exc); - } - catch (...) - { - handle_unknown_exception (); - }; - deregister_new_thread (); - - return 0; - } +// ----------- encapsulators for unary functions + namespace internal + { + /** + * Encapsulator class for + * functions with 1 argument. + */ + template + class fun_encapsulator + { + typedef typename internal::fun_ptr::type FunPtr; - template - MemFunData0::ArgCollector::ArgCollector (FunPtr fun_ptr) : - fun_ptr (fun_ptr) - {} - + 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; + }; - template - FunEncapsulation - MemFunData0::ArgCollector::collect_args (Class *object) - { - return new MemFunData0(fun_ptr, object); } - - - template + + /** + * Overload of the spawn function for + * non-member or static member + * functions with 1 argument. + */ + template inline - FunEncapsulation - MemFunData0::ArgCollector::collect_args (Class &object) - { - return collect_args (&object); + internal::fun_encapsulator > + spawn (RT (*fun_ptr)(Arg1)) { + return internal::fun_encapsulator > (fun_ptr); } - -/* ---------------------- MemFunData1 implementation ------------------------ */ - template - MemFunData1::MemFunData1 (FunPtr fun_ptr, - Class *object, - Arg1 arg1) : - FunDataBase (&MemFunData1::thread_entry_point), - fun_ptr (fun_ptr), - object (object), - arg1 (arg1) - {} +// ----------- encapsulators for binary functions + namespace internal + { + /** + * Encapsulator class for + * functions with 2 arguments. + */ + template + class fun_encapsulator + { + typedef typename internal::fun_ptr::type FunPtr; - template - MemFunData1::MemFunData1 (const MemFunData1 &fun_data) : - FunDataBase (fun_data), - fun_ptr (fun_data.fun_ptr), - object (fun_data.object), - arg1 (fun_data.arg1) - {} + 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; + }; + + } - template - FunDataBase * - MemFunData1::clone () const - { - return new MemFunData1 (*this); + /** + * Overload of the spawn function for + * non-member or static member + * functions with 2 arguments. + */ + template + inline + internal::fun_encapsulator > + spawn (RT (*fun_ptr)(Arg1,Arg2)) { + return internal::fun_encapsulator > (fun_ptr); } - template - void * - MemFunData1::thread_entry_point (void *arg) +// ----------- encapsulators for ternary functions + + namespace internal { - // convenience typedef, since we - // will need that class name - // several times below - typedef MemFunData1 ThisClass; - - FunEncapsulation *fun_encapsulation - = reinterpret_cast(arg); - const ThisClass *fun_data - = dynamic_cast (fun_encapsulation->fun_data_base); - - // copy the parameters - typename ThisClass::FunPtr fun_ptr = fun_data->fun_ptr; - Class *object = fun_data->object; - Arg1 arg1 = fun_data->arg1; - - - // copying of parameters is done, - // now we can release the lock on - // @p{fun_data}, by first making - // sure that the main thread is - // hanging in the condition - // variable's wait() function, - // and then signalling that the - // condition has been met, - // i.e. that the data has been - // copied. (note that there can - // be only one listener, so - // signal() is fine and we don't - // need broadcast()) - fun_data->lock.acquire (); - fun_data->condition.signal (); - fun_data->lock.release (); - - // register new thread, call the - // function, and upon its return, - // de-register it again. 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 - register_new_thread (); - try - { - (object->*fun_ptr)(arg1); - } - catch (const std::exception &exc) - { - handle_std_exception (exc); - } - catch (...) - { - handle_unknown_exception (); - }; - deregister_new_thread (); + /** + * 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; + }; - return 0; } + /** + * Overload of the spawn function for + * non-member or static member + * functions with 3 arguments. + */ + template + inline + internal::fun_encapsulator > + spawn (RT (*fun_ptr)(Arg1,Arg2,Arg3)) { + return internal::fun_encapsulator > (fun_ptr); + } - template - MemFunData1::ArgCollector::ArgCollector (FunPtr fun_ptr) : - fun_ptr (fun_ptr) - {} - - template - FunEncapsulation - MemFunData1::ArgCollector::collect_args (Class *object, - Arg1 arg1) - { - return new MemFunData1(fun_ptr, object, arg1); - } - - - template - inline - FunEncapsulation - MemFunData1::ArgCollector::collect_args (Class &object, - Arg1 arg1) + +// ----------- encapsulators for functions with 4 arguments + + namespace internal { - return collect_args (&object, arg1); - } + /** + * 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; + }; -/* ---------------------- MemFunData2 implementation ------------------------ */ + } - template - MemFunData2::MemFunData2 (FunPtr fun_ptr, - Class *object, - Arg1 arg1, - Arg2 arg2) : - FunDataBase (&MemFunData2::thread_entry_point), - fun_ptr (fun_ptr), - object (object), - arg1 (arg1), - arg2 (arg2) - {} + /** + * Overload of the spawn function for + * non-member or static member + * functions with 4 arguments. + */ + template + inline + internal::fun_encapsulator > + spawn (RT (*fun_ptr)(Arg1,Arg2,Arg3,Arg4)) { + return internal::fun_encapsulator > (fun_ptr); + } - template - MemFunData2::MemFunData2 (const MemFunData2 &fun_data) : - FunDataBase (fun_data), - fun_ptr (fun_data.fun_ptr), - object (fun_data.object), - arg1 (fun_data.arg1), - arg2 (fun_data.arg2) - {} +// ----------- encapsulators for functions with 5 arguments - template - FunDataBase * - MemFunData2::clone () const + namespace internal { - return new MemFunData2 (*this); - } - + /** + * 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) {}; - template - void * - MemFunData2::thread_entry_point (void *arg) - { - // convenience typedef, since we - // will need that class name - // several times below - typedef MemFunData2 ThisClass; - - FunEncapsulation *fun_encapsulation - = reinterpret_cast(arg); - const ThisClass *fun_data - = dynamic_cast (fun_encapsulation->fun_data_base); - - // copy the parameters - typename ThisClass::FunPtr fun_ptr = fun_data->fun_ptr; - Class *object = fun_data->object; - Arg1 arg1 = fun_data->arg1; - Arg2 arg2 = fun_data->arg2; - - - // copying of parameters is done, - // now we can release the lock on - // @p{fun_data}, by first making - // sure that the main thread is - // hanging in the condition - // variable's wait() function, - // and then signalling that the - // condition has been met, - // i.e. that the data has been - // copied. (note that there can - // be only one listener, so - // signal() is fine and we don't - // need broadcast()) - fun_data->lock.acquire (); - fun_data->condition.signal (); - fun_data->lock.release (); - - // register new thread, call the - // function, and upon its return, - // de-register it again. 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 - register_new_thread (); - try - { - (object->*fun_ptr)(arg1, arg2); - } - catch (const std::exception &exc) - { - handle_std_exception (exc); - } - catch (...) - { - handle_unknown_exception (); - }; - deregister_new_thread (); + 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; + }; - return 0; } + /** + * Overload of the spawn function for + * non-member or static member + * functions with 5 arguments. + */ + template + inline + internal::fun_encapsulator > + spawn (RT (*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5)) { + return internal::fun_encapsulator > (fun_ptr); + } - template - MemFunData2::ArgCollector::ArgCollector (FunPtr fun_ptr) : - fun_ptr (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; + }; - template - FunEncapsulation - MemFunData2::ArgCollector::collect_args (Class *object, - Arg1 arg1, - Arg2 arg2) - { - return new MemFunData2(fun_ptr, object, arg1, arg2); } - - - template + + + /** + * Overload of the spawn function for + * non-member or static member + * functions with 6 arguments. + */ + template inline - FunEncapsulation - MemFunData2::ArgCollector::collect_args (Class &object, - Arg1 arg1, - Arg2 arg2) - { - return collect_args (&object, arg1, arg2); + internal::fun_encapsulator > + spawn (RT (*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5,Arg6)) { + return internal::fun_encapsulator > (fun_ptr); } - - -/* ---------------------- MemFunData3 implementation ------------------------ */ - - template - MemFunData3::MemFunData3 (FunPtr fun_ptr, - Class *object, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3) : - FunDataBase (&MemFunData3::thread_entry_point), - fun_ptr (fun_ptr), - object (object), - arg1 (arg1), - arg2 (arg2), - arg3 (arg3) - {} +// ----------- 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 > + spawn (RT (*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5,Arg6,Arg7)) { + return internal::fun_encapsulator > (fun_ptr); + } - template - MemFunData3::MemFunData3 (const MemFunData3 &fun_data) : - FunDataBase (fun_data), - fun_ptr (fun_data.fun_ptr), - object (fun_data.object), - arg1 (fun_data.arg1), - arg2 (fun_data.arg2), - arg3 (fun_data.arg3) - {} +// ----------- 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; + }; + + } - template - FunDataBase * - MemFunData3::clone () const - { - return new MemFunData3 (*this); + /** + * Overload of the spawn function for + * non-member or static member + * functions with 8 arguments. + */ + template + inline + internal::fun_encapsulator > + spawn (RT (*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5, + Arg6,Arg7,Arg8)) { + return internal::fun_encapsulator > (fun_ptr); } - - template - void * - MemFunData3::thread_entry_point (void *arg) - { - // convenience typedef, since we - // will need that class name - // several times below - typedef MemFunData3 ThisClass; - - FunEncapsulation *fun_encapsulation - = reinterpret_cast(arg); - const ThisClass *fun_data - = dynamic_cast (fun_encapsulation->fun_data_base); - - // copy the parameters - typename ThisClass::FunPtr fun_ptr = fun_data->fun_ptr; - Class *object = fun_data->object; - Arg1 arg1 = fun_data->arg1; - Arg2 arg2 = fun_data->arg2; - Arg3 arg3 = fun_data->arg3; - - - // copying of parameters is done, - // now we can release the lock on - // @p{fun_data}, by first making - // sure that the main thread is - // hanging in the condition - // variable's wait() function, - // and then signalling that the - // condition has been met, - // i.e. that the data has been - // copied. (note that there can - // be only one listener, so - // signal() is fine and we don't - // need broadcast()) - fun_data->lock.acquire (); - fun_data->condition.signal (); - fun_data->lock.release (); - - // register new thread, call the - // function, and upon its return, - // de-register it again. 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 - register_new_thread (); - try - { - (object->*fun_ptr)(arg1, arg2, arg3); - } - catch (const std::exception &exc) - { - handle_std_exception (exc); - } - catch (...) - { - handle_unknown_exception (); - }; - deregister_new_thread (); +// ----------- encapsulators for functions with 9 arguments + + 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) {}; + + 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; + }; - return 0; } + /** + * Overload of the spawn function for + * non-member or static member + * functions with 9 arguments. + */ + template + inline + internal::fun_encapsulator > + spawn (RT (*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5, + Arg6,Arg7,Arg8,Arg9)) { + return internal::fun_encapsulator > (fun_ptr); + } - template - MemFunData3::ArgCollector::ArgCollector (FunPtr fun_ptr) : - fun_ptr (fun_ptr) - {} - +// ----------- encapsulators for functions with 10 arguments + + namespace internal + { + /** + * Encapsulator class for + * functions with 10 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, + 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 (); + }; + + private: + FunPtr fun_ptr; + }; - template - FunEncapsulation - MemFunData3::ArgCollector::collect_args (Class *object, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3) - { - return new MemFunData3(fun_ptr, object, - arg1, arg2, arg3); } - - - - template + + + /** + * Overload of the spawn function for + * non-member or static member + * functions with 10 arguments. + */ + template inline - FunEncapsulation - MemFunData3::ArgCollector::collect_args (Class &object, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3) - { - return collect_args (&object, arg1, arg2, arg3); + internal::fun_encapsulator > + spawn (RT (*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5, + Arg6,Arg7,Arg8,Arg9,Arg10)) { + return internal::fun_encapsulator > (fun_ptr); } - +#else // #if (DEAL_II_USE_MT == 1) -/* ---------------------- MemFunData4 implementation ------------------------ */ - - template - MemFunData4::MemFunData4 (FunPtr fun_ptr, - Class *object, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4) : - FunDataBase (&MemFunData4::thread_entry_point), - fun_ptr (fun_ptr), - object (object), - arg1 (arg1), - arg2 (arg2), - arg3 (arg3), - arg4 (arg4) - {} + template + class Thread + { + public: + /** + * Default constructor. + */ + Thread () {}; + /** + * 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); + }; + /** + * 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); + }; - template - MemFunData4::MemFunData4 (const MemFunData4 &fun_data) : - FunDataBase (fun_data), - fun_ptr (fun_data.fun_ptr), - object (fun_data.object), - arg1 (fun_data.arg1), - arg2 (fun_data.arg2), - arg3 (fun_data.arg3), - arg4 (fun_data.arg4) - {} + /** + * Get the return value of the + * function of the + * thread. + */ + RT return_value () const + { + return rv.get(); + }; + /** + * Join this thread. Is of + * course a no-op in this of no + * thread support. + */ + void join () const {}; + /** + * Compare for equality of + * threads. Since thrheads are + * not supported, there can + * only be exactly one thread, + * and the result is + * @p{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; + }; + - template - FunDataBase * - MemFunData4::clone () const - { - return new MemFunData4 (*this); + namespace internal + { + /** + * General template declaration + * of a class that is used to + * forward arguments to + * global and 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 ::value> + class fun_forwarder; + + /** + * 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 ::value> + class mem_fun_forwarder; } - - template - void * - MemFunData4::thread_entry_point (void *arg) + namespace internal { - // convenience typedef, since we - // will need that class name - // several times below - typedef MemFunData4 ThisClass; - - FunEncapsulation *fun_encapsulation - = reinterpret_cast(arg); - const ThisClass *fun_data - = dynamic_cast (fun_encapsulation->fun_data_base); - - // copy the parameters - typename ThisClass::FunPtr fun_ptr = fun_data->fun_ptr; - Class *object = fun_data->object; - Arg1 arg1 = fun_data->arg1; - Arg2 arg2 = fun_data->arg2; - Arg3 arg3 = fun_data->arg3; - Arg4 arg4 = fun_data->arg4; - - - // copying of parameters is done, - // now we can release the lock on - // @p{fun_data}, by first making - // sure that the main thread is - // hanging in the condition - // variable's wait() function, - // and then signalling that the - // condition has been met, - // i.e. that the data has been - // copied. (note that there can - // be only one listener, so - // signal() is fine and we don't - // need broadcast()) - fun_data->lock.acquire (); - fun_data->condition.signal (); - fun_data->lock.release (); - - // register new thread, call the - // function, and upon its return, - // de-register it again. 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 - register_new_thread (); - try - { - (object->*fun_ptr)(arg1, arg2, arg3, arg4); - } - catch (const std::exception &exc) - { - handle_std_exception (exc); - } - catch (...) - { - handle_unknown_exception (); - }; - deregister_new_thread (); + /** + * Forwarder class for member + * functions with no arguments. + */ + template + class mem_fun_forwarder + { + 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() () { + return Thread (mem_fun_ptr, c, + ArgList()); + }; + + private: + C &c; + MemFunPtr mem_fun_ptr; + }; - return 0; } + + /** + * Overload of the non-const spawn + * function for member functions + * with no arguments. This is the + * version of the @p{spawn} + * function for the case that + * threading is not enabled. + */ + template + inline + internal::mem_fun_forwarder > + spawn (C &c, RT (C::*fun_ptr)()) { + return internal::mem_fun_forwarder > (c,fun_ptr); + } + + /** + * Overload of the spawn function + * for const member functions with + * no arguments. This is the + * version of the @p{spawn} + * function for the case that + * threading is not enabled. + */ + template + inline + internal::mem_fun_forwarder > + spawn (const C &c, RT (C::*fun_ptr)() const) { + return internal::mem_fun_forwarder > (c,fun_ptr); + } - template - MemFunData4::ArgCollector::ArgCollector (FunPtr fun_ptr) : - fun_ptr (fun_ptr) - {} +// ----------- forwarders for unary member functions - template - FunEncapsulation - MemFunData4::ArgCollector::collect_args (Class *object, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4) + namespace internal { - return new MemFunData4(fun_ptr, object, - arg1, arg2, arg3, arg4); - } - + /** + * Forwarder class for member + * functions with 1 argument. + */ + template + class mem_fun_forwarder + { + 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; + }; + } - template + + /** + * Overload of the non-const spawn + * function for member functions with + * 1 argument. This is the + * version of the @p{spawn} + * function for the case that + * threading is not enabled. + */ + template inline - FunEncapsulation - MemFunData4::ArgCollector::collect_args (Class &object, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4) - { - return collect_args (&object, arg1, arg2, arg3, arg4); + internal::mem_fun_forwarder > + spawn (C &c, RT (C::*fun_ptr)(Arg1)) { + return internal::mem_fun_forwarder > (c,fun_ptr); } - -/* ---------------------- MemFunData5 implementation ------------------------ */ - - template - MemFunData5::MemFunData5 (FunPtr fun_ptr, - Class *object, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5) : - FunDataBase (&MemFunData5::thread_entry_point), - fun_ptr (fun_ptr), - object (object), - arg1 (arg1), - arg2 (arg2), - arg3 (arg3), - arg4 (arg4), - arg5 (arg5) - {} - - - - template - MemFunData5::MemFunData5 (const MemFunData5 &fun_data) : - FunDataBase (fun_data), - fun_ptr (fun_data.fun_ptr), - object (fun_data.object), - arg1 (fun_data.arg1), - arg2 (fun_data.arg2), - arg3 (fun_data.arg3), - arg4 (fun_data.arg4), - arg5 (fun_data.arg5) - {} - - - - template - FunDataBase * - MemFunData5::clone () const - { - return new MemFunData5 (*this); + /** + * Overload of the spawn function for + * const member functions with 1 + * argument. This is the + * version of the @p{spawn} + * function for the case that + * threading is not enabled. + */ + template + inline + internal::mem_fun_forwarder > + spawn (const C &c, RT (C::*fun_ptr)(Arg1) const) { + return internal::mem_fun_forwarder > (c,fun_ptr); } - template - void * - MemFunData5::thread_entry_point (void *arg) + +// ----------- forwarders for binary member functions + + namespace internal { - // convenience typedef, since we - // will need that class name - // several times below - typedef MemFunData5 ThisClass; - - FunEncapsulation *fun_encapsulation - = reinterpret_cast(arg); - const ThisClass *fun_data - = dynamic_cast (fun_encapsulation->fun_data_base); - - // copy the parameters - typename ThisClass::FunPtr fun_ptr = fun_data->fun_ptr; - Class *object = fun_data->object; - Arg1 arg1 = fun_data->arg1; - Arg2 arg2 = fun_data->arg2; - Arg3 arg3 = fun_data->arg3; - Arg4 arg4 = fun_data->arg4; - Arg5 arg5 = fun_data->arg5; - - - // copying of parameters is done, - // now we can release the lock on - // @p{fun_data}, by first making - // sure that the main thread is - // hanging in the condition - // variable's wait() function, - // and then signalling that the - // condition has been met, - // i.e. that the data has been - // copied. (note that there can - // be only one listener, so - // signal() is fine and we don't - // need broadcast()) - fun_data->lock.acquire (); - fun_data->condition.signal (); - fun_data->lock.release (); - - // register new thread, call the - // function, and upon its return, - // de-register it again. 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 - register_new_thread (); - try - { - (object->*fun_ptr)(arg1, arg2, arg3, arg4, arg5); - } - catch (const std::exception &exc) - { - handle_std_exception (exc); - } - catch (...) - { - handle_unknown_exception (); - }; - deregister_new_thread (); + /** + * Forwarder class for member + * functions with 2 + * arguments. + */ + template + class mem_fun_forwarder + { + 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) { + return Thread (mem_fun_ptr, c, + boost::tie(arg1, + arg2)); + }; + + private: + C &c; + MemFunPtr mem_fun_ptr; + }; - return 0; } + /** + * Overload of the non-const spawn + * function for member functions + * with 2 arguments. This is the + * version of the @p{spawn} + * function for the case that + * threading is not enabled. + */ + template + inline + internal::mem_fun_forwarder > + spawn (C &c, RT (C::*fun_ptr)(Arg1,Arg2)) { + return internal::mem_fun_forwarder > (c,fun_ptr); + } + + /** + * Overload of the spawn function + * for const member functions with + * 2 arguments. This is the version + * of the @p{spawn} function for + * the case that threading is not + * enabled. + */ + template + inline + internal::mem_fun_forwarder > + spawn (const C &c, RT (C::*fun_ptr)(Arg1,Arg2) const) { + return internal::mem_fun_forwarder > (c,fun_ptr); + } - template - MemFunData5::ArgCollector::ArgCollector (FunPtr fun_ptr) : - fun_ptr (fun_ptr) - {} +// ----------- forwarders for ternary member functions - template - FunEncapsulation - MemFunData5::ArgCollector::collect_args (Class *object, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5) + namespace internal { - return new MemFunData5(fun_ptr, object, - arg1, arg2, arg3, arg4, arg5); - } - + /** + * Forwarder class for member + * functions with 3 + * arguments. + */ + template + class mem_fun_forwarder + { + 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)); + }; + + private: + C &c; + MemFunPtr mem_fun_ptr; + }; - template + } + + + /** + * Overload of the non-const spawn + * function for member functions + * with 3 arguments. This is the + * version of the @p{spawn} + * function for the case that + * threading is not enabled. + */ + template inline - FunEncapsulation - MemFunData5::ArgCollector::collect_args (Class &object, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5) - { - return collect_args (&object, arg1, arg2, arg3, arg4, arg5); + internal::mem_fun_forwarder > + spawn (C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3)) { + return internal::mem_fun_forwarder > (c,fun_ptr); } - - -/* ---------------------- MemFunData6 implementation ------------------------ */ - - template - MemFunData6::MemFunData6 (FunPtr fun_ptr, - Class *object, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5, - Arg6 arg6) : - FunDataBase (&MemFunData6::thread_entry_point), - fun_ptr (fun_ptr), - object (object), - arg1 (arg1), - arg2 (arg2), - arg3 (arg3), - arg4 (arg4), - arg5 (arg5), - arg6 (arg6) - {} - - - - template - MemFunData6::MemFunData6 (const MemFunData6 &fun_data) : - FunDataBase (fun_data), - fun_ptr (fun_data.fun_ptr), - object (fun_data.object), - arg1 (fun_data.arg1), - arg2 (fun_data.arg2), - arg3 (fun_data.arg3), - arg4 (fun_data.arg4), - arg5 (fun_data.arg5), - arg6 (fun_data.arg6) - {} - - - - template - FunDataBase * - MemFunData6::clone () const - { - return new MemFunData6 (*this); + /** + * Overload of the spawn function + * for const member functions with + * 3 arguments. This is the version + * of the @p{spawn} function for + * the case that threading is not + * enabled. + */ + template + inline + internal::mem_fun_forwarder > + spawn (const C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3) const) { + return internal::mem_fun_forwarder > (c,fun_ptr); } - template - void * - MemFunData6::thread_entry_point (void *arg) + +// ----------- forwarders for member functions with 4 arguments + + namespace internal { - // convenience typedef, since we - // will need that class name - // several times below - typedef MemFunData6 ThisClass; - - FunEncapsulation *fun_encapsulation - = reinterpret_cast(arg); - const ThisClass *fun_data - = dynamic_cast (fun_encapsulation->fun_data_base); - - // copy the parameters - typename ThisClass::FunPtr fun_ptr = fun_data->fun_ptr; - Class *object = fun_data->object; - Arg1 arg1 = fun_data->arg1; - Arg2 arg2 = fun_data->arg2; - Arg3 arg3 = fun_data->arg3; - Arg4 arg4 = fun_data->arg4; - Arg5 arg5 = fun_data->arg5; - Arg6 arg6 = fun_data->arg6; - - - // copying of parameters is done, - // now we can release the lock on - // @p{fun_data}, by first making - // sure that the main thread is - // hanging in the condition - // variable's wait() function, - // and then signalling that the - // condition has been met, - // i.e. that the data has been - // copied. (note that there can - // be only one listener, so - // signal() is fine and we don't - // need broadcast()) - fun_data->lock.acquire (); - fun_data->condition.signal (); - fun_data->lock.release (); - - // register new thread, call the - // function, and upon its return, - // de-register it again. 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 - register_new_thread (); - try - { - (object->*fun_ptr)(arg1, arg2, arg3, arg4, arg5, arg6); - } - catch (const std::exception &exc) - { - handle_std_exception (exc); - } - catch (...) - { - handle_unknown_exception (); - }; - deregister_new_thread (); + /** + * Forwarder class for member + * functions with 4 + * arguments. + */ + template + class mem_fun_forwarder + { + 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)); + }; + + private: + C &c; + MemFunPtr mem_fun_ptr; + }; - return 0; } + /** + * Overload of the non-const spawn + * function for member functions + * with 4 arguments. This is the + * version of the @p{spawn} + * function for the case that + * threading is not enabled. + */ + template + inline + internal::mem_fun_forwarder > + spawn (C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4)) { + return internal::mem_fun_forwarder > (c,fun_ptr); + } - template - MemFunData6::ArgCollector::ArgCollector (FunPtr fun_ptr) : - fun_ptr (fun_ptr) - {} + /** + * Overload of the spawn function + * for const member functions with + * 4 arguments. This is the version + * of the @p{spawn} function for + * the case that threading is not + * enabled. + */ + template + inline + internal::mem_fun_forwarder > + spawn (const C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4) const) { + return internal::mem_fun_forwarder > (c,fun_ptr); + } - template - FunEncapsulation - MemFunData6::ArgCollector::collect_args (Class *object, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5, - Arg6 arg6) - { - return new MemFunData6(fun_ptr, object, - arg1, arg2, arg3, arg4, arg5, arg6); - } - +// ----------- forwarders for member functions with 5 arguments - template - inline - FunEncapsulation - MemFunData6::ArgCollector::collect_args (Class &object, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5, - Arg6 arg6) + namespace internal { - return collect_args (&object, arg1, arg2, arg3, arg4, arg5, arg6); - } - + /** + * Forwarder class for member + * functions with 5 + * arguments. + */ + template + class mem_fun_forwarder + { + 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)); + }; + + private: + C &c; + MemFunPtr mem_fun_ptr; + }; + } -/* ---------------------- MemFunData7 implementation ------------------------ */ - - template - MemFunData7::MemFunData7 (FunPtr fun_ptr, - Class *object, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5, - Arg6 arg6, - Arg7 arg7) : - FunDataBase (&MemFunData7::thread_entry_point), - fun_ptr (fun_ptr), - object (object), - arg1 (arg1), - arg2 (arg2), - arg3 (arg3), - arg4 (arg4), - arg5 (arg5), - arg6 (arg6), - arg7 (arg7) - {} - - - - template - MemFunData7::MemFunData7 (const MemFunData7 &fun_data) : - FunDataBase (fun_data), - fun_ptr (fun_data.fun_ptr), - object (fun_data.object), - arg1 (fun_data.arg1), - arg2 (fun_data.arg2), - arg3 (fun_data.arg3), - arg4 (fun_data.arg4), - arg5 (fun_data.arg5), - arg6 (fun_data.arg6), - arg7 (fun_data.arg7) - {} - - - - template - FunDataBase * - MemFunData7::clone () const - { - return new MemFunData7 (*this); + + /** + * Overload of the non-const spawn + * function for member functions + * with 5 arguments. This is the + * version of the @p{spawn} + * function for the case that + * threading is not enabled. + */ + template + inline + internal::mem_fun_forwarder > + spawn (C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5)) { + return internal::mem_fun_forwarder > (c,fun_ptr); } + /** + * Overload of the spawn function + * for const member functions with + * 5 arguments. This is the version + * of the @p{spawn} function for + * the case that threading is not + * enabled. + */ + template + inline + internal::mem_fun_forwarder > + spawn (const C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5) const) { + return internal::mem_fun_forwarder > (c,fun_ptr); + } - template - void * - MemFunData7::thread_entry_point (void *arg) - { - // convenience typedef, since we - // will need that class name - // several times below - typedef MemFunData7 ThisClass; - - FunEncapsulation *fun_encapsulation - = reinterpret_cast(arg); - const ThisClass *fun_data - = dynamic_cast (fun_encapsulation->fun_data_base); - - // copy the parameters - typename ThisClass::FunPtr fun_ptr = fun_data->fun_ptr; - Class *object = fun_data->object; - Arg1 arg1 = fun_data->arg1; - Arg2 arg2 = fun_data->arg2; - Arg3 arg3 = fun_data->arg3; - Arg4 arg4 = fun_data->arg4; - Arg5 arg5 = fun_data->arg5; - Arg6 arg6 = fun_data->arg6; - Arg7 arg7 = fun_data->arg7; - - - // copying of parameters is done, - // now we can release the lock on - // @p{fun_data}, by first making - // sure that the main thread is - // hanging in the condition - // variable's wait() function, - // and then signalling that the - // condition has been met, - // i.e. that the data has been - // copied. (note that there can - // be only one listener, so - // signal() is fine and we don't - // need broadcast()) - fun_data->lock.acquire (); - fun_data->condition.signal (); - fun_data->lock.release (); - - // register new thread, call the - // function, and upon its return, - // de-register it again. 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 - register_new_thread (); - try - { - (object->*fun_ptr)(arg1, arg2, arg3, arg4, arg5, arg6, arg7); - } - catch (const std::exception &exc) - { - handle_std_exception (exc); - } - catch (...) - { - handle_unknown_exception (); - }; - deregister_new_thread (); +// ----------- forwarders for member functions with 6 arguments + + namespace internal + { + /** + * Forwarder class for member + * functions with 6 + * arguments. + */ + template + class mem_fun_forwarder + { + 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)); + }; + + private: + C &c; + MemFunPtr mem_fun_ptr; + }; - return 0; } + /** + * Overload of the non-const spawn + * function for member functions + * with 6 arguments. This is the + * version of the @p{spawn} + * function for the case that + * threading is not enabled. + */ + template + inline + internal::mem_fun_forwarder > + spawn (C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5,Arg6)) { + return internal::mem_fun_forwarder > (c,fun_ptr); + } - template - MemFunData7::ArgCollector::ArgCollector (FunPtr fun_ptr) : - fun_ptr (fun_ptr) - {} - + /** + * Overload of the spawn function + * for const member functions with + * 6 arguments. This is the version + * of the @p{spawn} function for + * the case that threading is not + * enabled. + */ + template + inline + internal::mem_fun_forwarder > + spawn (const C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5,Arg6) const) { + return internal::mem_fun_forwarder > (c,fun_ptr); + } - template - FunEncapsulation - MemFunData7::ArgCollector::collect_args (Class *object, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5, - Arg6 arg6, - Arg7 arg7) - { - return new MemFunData7(fun_ptr, object, - arg1, arg2, arg3, arg4, arg5, arg6, arg7); - } +// ----------- forwarders for member functions with 7 arguments + + namespace internal + { + /** + * Forwarder class for member + * functions with 7 + * arguments. + */ + template + class mem_fun_forwarder + { + 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)); + }; + + private: + C &c; + MemFunPtr mem_fun_ptr; + }; + } - template + /** + * Overload of the non-const spawn + * function for member functions + * with 7 arguments. This is the + * version of the @p{spawn} + * function for the case that + * threading is not enabled. + */ + template inline - FunEncapsulation - MemFunData7::ArgCollector::collect_args (Class &object, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5, - Arg6 arg6, - Arg7 arg7) - { - return collect_args (&object, arg1, arg2, arg3, arg4, arg5, arg6, arg7); + internal::mem_fun_forwarder > + spawn (C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5,Arg6,Arg7)) { + return internal::mem_fun_forwarder > (c,fun_ptr); } - -/* ---------------------- MemFunData8 implementation ------------------------ */ - - template - MemFunData8::MemFunData8 (FunPtr fun_ptr, - Class *object, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5, - Arg6 arg6, - Arg7 arg7, - Arg8 arg8) : - FunDataBase (&MemFunData8::thread_entry_point), - fun_ptr (fun_ptr), - object (object), - arg1 (arg1), - arg2 (arg2), - arg3 (arg3), - arg4 (arg4), - arg5 (arg5), - arg6 (arg6), - arg7 (arg7), - arg8 (arg8) - {} - - - - template - MemFunData8::MemFunData8 (const MemFunData8 &fun_data) : - FunDataBase (fun_data), - fun_ptr (fun_data.fun_ptr), - object (fun_data.object), - arg1 (fun_data.arg1), - arg2 (fun_data.arg2), - arg3 (fun_data.arg3), - arg4 (fun_data.arg4), - arg5 (fun_data.arg5), - arg6 (fun_data.arg6), - arg7 (fun_data.arg7), - arg8 (fun_data.arg8) - {} - - - - template - FunDataBase * - MemFunData8::clone () const - { - return new MemFunData8 (*this); + /** + * Overload of the spawn function + * for const member functions with + * 7 arguments. This is the version + * of the @p{spawn} function for + * the case that threading is not + * enabled. + */ + template + inline + internal::mem_fun_forwarder > + spawn (const C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5,Arg6,Arg7) const) { + return internal::mem_fun_forwarder > (c,fun_ptr); } - - template - void * - MemFunData8::thread_entry_point (void *arg) - { - // convenience typedef, since we - // will need that class name - // several times below - typedef MemFunData8 ThisClass; - - FunEncapsulation *fun_encapsulation - = reinterpret_cast(arg); - const ThisClass *fun_data - = dynamic_cast (fun_encapsulation->fun_data_base); - - // copy the parameters - typename ThisClass::FunPtr fun_ptr = fun_data->fun_ptr; - Class *object = fun_data->object; - Arg1 arg1 = fun_data->arg1; - Arg2 arg2 = fun_data->arg2; - Arg3 arg3 = fun_data->arg3; - Arg4 arg4 = fun_data->arg4; - Arg5 arg5 = fun_data->arg5; - Arg6 arg6 = fun_data->arg6; - Arg7 arg7 = fun_data->arg7; - Arg8 arg8 = fun_data->arg8; - - - // copying of parameters is done, - // now we can release the lock on - // @p{fun_data}, by first making - // sure that the main thread is - // hanging in the condition - // variable's wait() function, - // and then signalling that the - // condition has been met, - // i.e. that the data has been - // copied. (note that there can - // be only one listener, so - // signal() is fine and we don't - // need broadcast()) - fun_data->lock.acquire (); - fun_data->condition.signal (); - fun_data->lock.release (); - - // register new thread, call the - // function, and upon its return, - // de-register it again. 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 - register_new_thread (); - try - { - (object->*fun_ptr)(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); - } - catch (const std::exception &exc) - { - handle_std_exception (exc); - } - catch (...) - { - handle_unknown_exception (); - }; - deregister_new_thread (); +// ----------- forwarders for member functions with 8 arguments + + namespace internal + { + /** + * Forwarder class for member + * functions with 8 + * arguments. + */ + template + class mem_fun_forwarder + { + 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)); + }; + + private: + C &c; + MemFunPtr mem_fun_ptr; + }; - return 0; } + /** + * Overload of the non-const spawn + * function for member functions + * with 8 arguments. This is the + * version of the @p{spawn} + * function for the case that + * threading is not enabled. + */ + template + inline + internal::mem_fun_forwarder > + spawn (C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5, + Arg6,Arg7,Arg8)) { + return internal::mem_fun_forwarder > (c,fun_ptr); + } + + /** + * Overload of the spawn function + * for const member functions with + * 8 arguments. This is the version + * of the @p{spawn} function for + * the case that threading is not + * enabled. + */ + template + inline + internal::mem_fun_forwarder > + spawn (const C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5, + Arg6,Arg7,Arg8) const) { + return internal::mem_fun_forwarder > (c,fun_ptr); + } - template - MemFunData8::ArgCollector::ArgCollector (FunPtr fun_ptr) : - fun_ptr (fun_ptr) - {} +// ----------- forwarders for member functions with 9 arguments + + namespace internal + { + /** + * Forwarder class for member + * functions with 9 + * arguments. + */ + template + class mem_fun_forwarder + { + 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)); + }; + + private: + C &c; + MemFunPtr mem_fun_ptr; + }; + + } - template - FunEncapsulation - MemFunData8::ArgCollector::collect_args (Class *object, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5, - Arg6 arg6, - Arg7 arg7, - Arg8 arg8) - { - return new MemFunData8(fun_ptr, object, - arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); + /** + * Overload of the non-const spawn + * function for member functions + * with 9 arguments. This is the + * version of the @p{spawn} + * function for the case that + * threading is not enabled. + */ + template + inline + internal::mem_fun_forwarder > + spawn (C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5, + Arg6,Arg7,Arg8,Arg9)) { + return internal::mem_fun_forwarder > (c,fun_ptr); } - - - template + /** + * Overload of the spawn function + * for const member functions with + * 9 arguments. This is the version + * of the @p{spawn} function for + * the case that threading is not + * enabled. + */ + template inline - FunEncapsulation - MemFunData8::ArgCollector::collect_args (Class &object, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5, - Arg6 arg6, - Arg7 arg7, - Arg8 arg8) - { - return collect_args (&object, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); + internal::mem_fun_forwarder > + spawn (const C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5, + Arg6,Arg7,Arg8,Arg9) const) { + return internal::mem_fun_forwarder > (c,fun_ptr); } -/* ---------------------- MemFunData9 implementation ------------------------ */ +// ----------- forwarders for member functions with 10 arguments + + namespace internal + { + /** + * Forwarder class for member + * functions with 10 + * arguments. + */ + template + class mem_fun_forwarder + { + 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)); + }; + + private: + C &c; + MemFunPtr mem_fun_ptr; + }; - template - MemFunData9::MemFunData9 (FunPtr fun_ptr, - Class *object, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5, - Arg6 arg6, - Arg7 arg7, - Arg8 arg8, - Arg9 arg9) : - FunDataBase (&MemFunData9::thread_entry_point), - fun_ptr (fun_ptr), - object (object), - arg1 (arg1), - arg2 (arg2), - arg3 (arg3), - arg4 (arg4), - arg5 (arg5), - arg6 (arg6), - arg7 (arg7), - arg8 (arg8), - arg9 (arg9) - {} - - - - template - MemFunData9::MemFunData9 (const MemFunData9 &fun_data) : - FunDataBase (fun_data), - fun_ptr (fun_data.fun_ptr), - object (fun_data.object), - arg1 (fun_data.arg1), - arg2 (fun_data.arg2), - arg3 (fun_data.arg3), - arg4 (fun_data.arg4), - arg5 (fun_data.arg5), - arg6 (fun_data.arg6), - arg7 (fun_data.arg7), - arg8 (fun_data.arg8), - arg9 (fun_data.arg9) - {} - - - - template - FunDataBase * - MemFunData9::clone () const - { - return new MemFunData9 (*this); } + /** + * Overload of the non-const spawn + * function for member functions + * with 10 arguments. This is the + * version of the @p{spawn} + * function for the case that + * threading is not enabled. + */ + template + inline + internal::mem_fun_forwarder > + spawn (C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5, + Arg6,Arg7,Arg8,Arg9,Arg10)) { + return internal::mem_fun_forwarder > (c,fun_ptr); + } - template - void * - MemFunData9::thread_entry_point (void *arg) - { - // convenience typedef, since we - // will need that class name - // several times below - typedef MemFunData9 ThisClass; - - FunEncapsulation *fun_encapsulation - = reinterpret_cast(arg); - const ThisClass *fun_data - = dynamic_cast (fun_encapsulation->fun_data_base); - - // copy the parameters - typename ThisClass::FunPtr fun_ptr = fun_data->fun_ptr; - Class *object = fun_data->object; - Arg1 arg1 = fun_data->arg1; - Arg2 arg2 = fun_data->arg2; - Arg3 arg3 = fun_data->arg3; - Arg4 arg4 = fun_data->arg4; - Arg5 arg5 = fun_data->arg5; - Arg6 arg6 = fun_data->arg6; - Arg7 arg7 = fun_data->arg7; - Arg8 arg8 = fun_data->arg8; - Arg9 arg9 = fun_data->arg9; - - - // copying of parameters is done, - // now we can release the lock on - // @p{fun_data}, by first making - // sure that the main thread is - // hanging in the condition - // variable's wait() function, - // and then signalling that the - // condition has been met, - // i.e. that the data has been - // copied. (note that there can - // be only one listener, so - // signal() is fine and we don't - // need broadcast()) - fun_data->lock.acquire (); - fun_data->condition.signal (); - fun_data->lock.release (); - - // register new thread, call the - // function, and upon its return, - // de-register it again. 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 - register_new_thread (); - try - { - (object->*fun_ptr)(arg1, arg2, arg3, arg4, - arg5, arg6, arg7, arg8, arg9); - } - catch (const std::exception &exc) - { - handle_std_exception (exc); - } - catch (...) - { - handle_unknown_exception (); - }; - deregister_new_thread (); - - return 0; + /** + * Overload of the spawn function + * for const member functions with + * 10 arguments. This is the + * version of the @p{spawn} + * function for the case that + * threading is not enabled. + */ + template + inline + internal::mem_fun_forwarder > + spawn (const C &c, RT (C::*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5, + Arg6,Arg7,Arg8,Arg9,Arg10) const) { + return internal::mem_fun_forwarder > (c,fun_ptr); } - template - MemFunData9::ArgCollector::ArgCollector (FunPtr fun_ptr) : - fun_ptr (fun_ptr) - {} +// ----------- forwarders for functions not taking any parameters + namespace 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) {}; - template - FunEncapsulation - MemFunData9::ArgCollector::collect_args (Class *object, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5, - Arg6 arg6, - Arg7 arg7, - Arg8 arg8, - Arg9 arg9) - { - return new MemFunData9(fun_ptr, object, - arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); - } + inline + Thread + operator() () { + return Thread (fun_ptr, + ArgList()); + }; + + private: + FunPtr fun_ptr; + }; + } - - template + + /** + * Overload of the spawn function + * for non-member or static member + * functions with no + * arguments. This is the version + * of the @p{spawn} function for + * the case that threading is not + * enabled. + */ + template inline - FunEncapsulation - MemFunData9::ArgCollector::collect_args (Class &object, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5, - Arg6 arg6, - Arg7 arg7, - Arg8 arg8, - Arg9 arg9) - { - return collect_args (&object, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); + internal::fun_forwarder > + spawn (RT (*fun_ptr)()) { + return internal::fun_forwarder > (fun_ptr); } -/* ---------------------- MemFunData10 implementation ------------------------ */ - - template - MemFunData10::MemFunData10 (FunPtr fun_ptr, - Class *object, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5, - Arg6 arg6, - Arg7 arg7, - Arg8 arg8, - Arg9 arg9, - Arg10 arg10) : - FunDataBase (&MemFunData10::thread_entry_point), - fun_ptr (fun_ptr), - object (object), - arg1 (arg1), - arg2 (arg2), - arg3 (arg3), - arg4 (arg4), - arg5 (arg5), - arg6 (arg6), - arg7 (arg7), - arg8 (arg8), - arg9 (arg9), - arg10 (arg10) - {} - - - - template - MemFunData10::MemFunData10 (const MemFunData10 &fun_data) : - FunDataBase (fun_data), - fun_ptr (fun_data.fun_ptr), - object (fun_data.object), - arg1 (fun_data.arg1), - arg2 (fun_data.arg2), - arg3 (fun_data.arg3), - arg4 (fun_data.arg4), - arg5 (fun_data.arg5), - arg6 (fun_data.arg6), - arg7 (fun_data.arg7), - arg8 (fun_data.arg8), - arg9 (fun_data.arg9), - arg10(fun_data.arg10) - {} - - - - template - FunDataBase * - MemFunData10::clone () const - { - return new MemFunData10 (*this); - } +// ----------- forwarders for unary functions - template - void * - MemFunData10::thread_entry_point (void *arg) + namespace internal { - // convenience typedef, since we - // will need that class name - // several times below - typedef MemFunData10 ThisClass; - - FunEncapsulation *fun_encapsulation - = reinterpret_cast(arg); - const ThisClass *fun_data - = dynamic_cast (fun_encapsulation->fun_data_base); - - // copy the parameters - typename ThisClass::FunPtr fun_ptr = fun_data->fun_ptr; - Class *object = fun_data->object; - Arg1 arg1 = fun_data->arg1; - Arg2 arg2 = fun_data->arg2; - Arg3 arg3 = fun_data->arg3; - Arg4 arg4 = fun_data->arg4; - Arg5 arg5 = fun_data->arg5; - Arg6 arg6 = fun_data->arg6; - Arg7 arg7 = fun_data->arg7; - Arg8 arg8 = fun_data->arg8; - Arg9 arg9 = fun_data->arg9; - Arg10 arg10 = fun_data->arg10; - - - // copying of parameters is done, - // now we can release the lock on - // @p{fun_data}, by first making - // sure that the main thread is - // hanging in the condition - // variable's wait() function, - // and then signalling that the - // condition has been met, - // i.e. that the data has been - // copied. (note that there can - // be only one listener, so - // signal() is fine and we don't - // need broadcast()) - fun_data->lock.acquire (); - fun_data->condition.signal (); - fun_data->lock.release (); - - // register new thread, call the - // function, and upon its return, - // de-register it again. 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 - register_new_thread (); - try - { - (object->*fun_ptr)(arg1, arg2, arg3, arg4, arg5, - arg6, arg7, arg8, arg9, arg10); - } - catch (const std::exception &exc) - { - handle_std_exception (exc); - } - catch (...) - { - handle_unknown_exception (); - }; - deregister_new_thread (); + /** + * 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; + }; - return 0; } + + /** + * Overload of the spawn function + * for non-member or static member + * functions with 1 argument. This + * is the version of the @p{spawn} + * function for the case that + * threading is not enabled. + */ + template + inline + internal::fun_forwarder > + spawn (RT (*fun_ptr)(Arg1)) { + return internal::fun_forwarder > (fun_ptr); + } - template - MemFunData10::ArgCollector::ArgCollector (FunPtr fun_ptr) : - fun_ptr (fun_ptr) - {} +// ----------- forwarders for binary functions - template - FunEncapsulation - MemFunData10::ArgCollector::collect_args (Class *object, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5, - Arg6 arg6, - Arg7 arg7, - Arg8 arg8, - Arg9 arg9, - Arg10 arg10) + namespace internal { - return new MemFunData10(fun_ptr, object, - arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); - } - + /** + * Forwarder class for functions + * with 2 arguments. + */ + template + class fun_forwarder + { + typedef typename internal::fun_ptr::type FunPtr; + public: + inline fun_forwarder (FunPtr fun_ptr) + : fun_ptr(fun_ptr) {}; - template - inline - FunEncapsulation - MemFunData10::ArgCollector::collect_args (Class &object, - Arg1 arg1, - Arg2 arg2, - Arg3 arg3, - Arg4 arg4, - Arg5 arg5, - Arg6 arg6, - Arg7 arg7, - Arg8 arg8, - Arg9 arg9, - Arg10 arg10) - { - return collect_args (&object, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); + 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; + }; + } -/* ---------------------------------------------------------------- */ - + /** + * Overload of the spawn function + * for non-member or static member + * functions with 2 arguments. This + * is the version of the @p{spawn} + * function for the case that + * threading is not enabled. + */ + template inline - FunData0::ArgCollector - encapsulate (void (*fun_ptr)()) - { - return fun_ptr; + internal::fun_forwarder > + spawn (RT (*fun_ptr)(Arg1,Arg2)) { + return internal::fun_forwarder > (fun_ptr); } - template - typename FunData1::ArgCollector - encapsulate (void (*fun_ptr)(Arg1)) - { - return fun_ptr; - } - - - - template - typename FunData2::ArgCollector - encapsulate (void (*fun_ptr)(Arg1, Arg2)) - { - return fun_ptr; - } - +// ----------- forwarders for ternary functions - - template - typename FunData3::ArgCollector - encapsulate (void (*fun_ptr)(Arg1, Arg2, Arg3)) + namespace internal { - return fun_ptr; - } - + /** + * Forwarder class for functions + * with 3 arguments. + */ + template + class fun_forwarder + { + typedef typename internal::fun_ptr::type FunPtr; - - template - typename FunData4::ArgCollector - encapsulate (void (*fun_ptr)(Arg1, Arg2, Arg3, Arg4)) - { - return fun_ptr; - } - + 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; + }; - template - typename FunData5::ArgCollector - encapsulate (void (*fun_ptr)(Arg1, Arg2, Arg3, Arg4, Arg5)) - { - return fun_ptr; } - - template - typename FunData6::ArgCollector - encapsulate (void (*fun_ptr)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6)) - { - return fun_ptr; + /** + * Overload of the spawn function + * for non-member or static member + * functions with 3 arguments. This + * is the version of the @p{spawn} + * function for the case that + * threading is not enabled. + */ + template + inline + internal::fun_forwarder > + spawn (RT (*fun_ptr)(Arg1,Arg2,Arg3)) { + return internal::fun_forwarder > (fun_ptr); } - - template - typename FunData7::ArgCollector - encapsulate (void (*fun_ptr)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7)) - { - return fun_ptr; - } - - - template - typename FunData8::ArgCollector - encapsulate (void (*fun_ptr)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8)) - { - return fun_ptr; - } +// ----------- forwarders for functions with 4 arguments - - template - typename FunData9::ArgCollector - encapsulate (void (*fun_ptr)(Arg1, Arg2, Arg3, Arg4, Arg5, - Arg6, Arg7, Arg8, Arg9)) + namespace internal { - return fun_ptr; - } + /** + * Forwarder class for functions + * with 4 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) { + return Thread (fun_ptr, + boost::tie(arg1,arg2, + arg3,arg4)); + }; + + private: + FunPtr fun_ptr; + }; - template - typename FunData10::ArgCollector - encapsulate (void (*fun_ptr)(Arg1, Arg2, Arg3, Arg4, Arg5, - Arg6, Arg7, Arg8, Arg9, Arg10)) - { - return fun_ptr; } - - template - typename MemFunData0::ArgCollector - encapsulate (void (Class::*fun_ptr)()) - { - return fun_ptr; - } - -#ifdef DEAL_II_TEMPL_CONST_MEM_PTR_BUG - template - typename MemFunData0::ArgCollector - encapsulate (void (Class::*fun_ptr)() const) - { - return fun_ptr; + /** + * Overload of the spawn function + * for non-member or static member + * functions with 4 arguments. This + * is the version of the @p{spawn} + * function for the case that + * threading is not enabled. + */ + template + inline + internal::fun_forwarder > + spawn (RT (*fun_ptr)(Arg1,Arg2,Arg3,Arg4)) { + return internal::fun_forwarder > (fun_ptr); } -#endif - template - typename MemFunData1::ArgCollector - encapsulate (void (Class::*fun_ptr)(Arg1)) - { - return fun_ptr; - } -#ifdef DEAL_II_TEMPL_CONST_MEM_PTR_BUG - template - typename MemFunData1::ArgCollector - encapsulate (void (Class::*fun_ptr)(Arg1) const) - { - return fun_ptr; - } -#endif - +// ----------- forwarders for functions with 5 arguments - - template - typename MemFunData2::ArgCollector - encapsulate (void (Class::*fun_ptr)(Arg1, Arg2)) + namespace internal { - return fun_ptr; - } + /** + * Forwarder class for functions + * with 5 arguments. + */ + template + class fun_forwarder + { + typedef typename internal::fun_ptr::type FunPtr; -#ifdef DEAL_II_TEMPL_CONST_MEM_PTR_BUG - template - typename MemFunData2::ArgCollector - encapsulate (void (Class::*fun_ptr)(Arg1, Arg2) const) - { - return fun_ptr; - } -#endif - + 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; + }; - template - typename MemFunData3::ArgCollector - encapsulate (void (Class::*fun_ptr)(Arg1, Arg2, Arg3)) - { - return fun_ptr; - } - -#ifdef DEAL_II_TEMPL_CONST_MEM_PTR_BUG - template - typename MemFunData3::ArgCollector - encapsulate (void (Class::*fun_ptr)(Arg1, Arg2, Arg3) const) - { - return fun_ptr; } -#endif - - - template - typename MemFunData4::ArgCollector - encapsulate (void (Class::*fun_ptr)(Arg1, Arg2, Arg3, Arg4)) - { - return fun_ptr; - } -#ifdef DEAL_II_TEMPL_CONST_MEM_PTR_BUG - template - typename MemFunData4::ArgCollector - encapsulate (void (Class::*fun_ptr)(Arg1, Arg2, Arg3, Arg4) const) - { - return fun_ptr; + /** + * Overload of the spawn function + * for non-member or static member + * functions with 5 arguments. This + * is the version of the @p{spawn} + * function for the case that + * threading is not enabled. + */ + template + inline + internal::fun_forwarder > + spawn (RT (*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5)) { + return internal::fun_forwarder > (fun_ptr); } -#endif +// ----------- forwarders for functions with 6 arguments + + namespace 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) {}; + + 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; + }; - template - typename MemFunData5::ArgCollector - encapsulate (void (Class::*fun_ptr)(Arg1, Arg2, Arg3, Arg4, Arg5)) - { - return fun_ptr; } -#ifdef DEAL_II_TEMPL_CONST_MEM_PTR_BUG - template - typename MemFunData5::ArgCollector - encapsulate (void (Class::*fun_ptr)(Arg1, Arg2, Arg3, Arg4, Arg5) const) - { - return fun_ptr; + + /** + * Overload of the spawn function + * for non-member or static member + * functions with 6 arguments. This + * is the version of the @p{spawn} + * function for the case that + * threading is not enabled. + */ + template + inline + internal::fun_forwarder > + spawn (RT (*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5,Arg6)) { + return internal::fun_forwarder > (fun_ptr); } -#endif +// ----------- forwarders for functions with 7 arguments + + namespace 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) {}; + + 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; + }; - template - typename MemFunData6::ArgCollector - encapsulate (void (Class::*fun_ptr)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6)) - { - return fun_ptr; } -#ifdef DEAL_II_TEMPL_CONST_MEM_PTR_BUG - template - typename MemFunData6::ArgCollector - encapsulate (void (Class::*fun_ptr)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6) const) - { - return fun_ptr; + + /** + * Overload of the spawn function + * for non-member or static member + * functions with 7 arguments. This + * is the version of the @p{spawn} + * function for the case that + * threading is not enabled. + */ + template + inline + internal::fun_forwarder > + spawn (RT (*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5,Arg6,Arg7)) { + return internal::fun_forwarder > (fun_ptr); } -#endif +// ----------- forwarders for functions with 8 arguments + + namespace 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) {}; + + 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; + }; - template - typename MemFunData7::ArgCollector - encapsulate (void (Class::*fun_ptr)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7)) - { - return fun_ptr; } -#ifdef DEAL_II_TEMPL_CONST_MEM_PTR_BUG - template - typename MemFunData7::ArgCollector - encapsulate (void (Class::*fun_ptr)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7) const) - { - return fun_ptr; + + /** + * Overload of the spawn function + * for non-member or static member + * functions with 8 arguments. This + * is the version of the @p{spawn} + * function for the case that + * threading is not enabled. + */ + template + inline + internal::fun_forwarder > + spawn (RT (*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5, + Arg6,Arg7,Arg8)) { + return internal::fun_forwarder > (fun_ptr); } -#endif +// ----------- forwarders for functions with 9 arguments + + namespace 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) {}; + + 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; + }; - template - typename MemFunData8::ArgCollector - encapsulate (void (Class::*fun_ptr)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8)) - { - return fun_ptr; - } - -#ifdef DEAL_II_TEMPL_CONST_MEM_PTR_BUG - template - typename MemFunData8::ArgCollector - encapsulate (void (Class::*fun_ptr)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8) const) - { - return fun_ptr; } -#endif - - template - typename MemFunData9::ArgCollector - encapsulate (void (Class::*fun_ptr)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9)) - { - return fun_ptr; + /** + * Overload of the spawn function + * for non-member or static member + * functions with 9 arguments. This + * is the version of the @p{spawn} + * function for the case that + * threading is not enabled. + */ + template + inline + internal::fun_forwarder > + spawn (RT (*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5, + Arg6,Arg7,Arg8,Arg9)) { + return internal::fun_forwarder > (fun_ptr); } -#ifdef DEAL_II_TEMPL_CONST_MEM_PTR_BUG - template - typename MemFunData9::ArgCollector - encapsulate (void (Class::*fun_ptr)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9) const) - { - return fun_ptr; - } -#endif - +// ----------- forwarders for functions with 10 arguments + + namespace 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; + }; - template - typename MemFunData10::ArgCollector - encapsulate (void (Class::*fun_ptr)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9, Arg10)) - { - return fun_ptr; } -#ifdef DEAL_II_TEMPL_CONST_MEM_PTR_BUG - template - typename MemFunData10::ArgCollector - encapsulate (void (Class::*fun_ptr)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9, Arg10) const) - { - return fun_ptr; + + /** + * Overload of the spawn function + * for non-member or static member + * functions with 10 + * arguments. This is the version + * of the @p{spawn} function for + * the case that threading is not + * enabled. + */ + template + inline + internal::fun_forwarder > + spawn (RT (*fun_ptr)(Arg1,Arg2,Arg3,Arg4,Arg5, + Arg6,Arg7,Arg8,Arg9,Arg10)) { + return internal::fun_forwarder > (fun_ptr); } -#endif - template - std::vector > - split_range (const ForwardIterator &begin, - const ForwardIterator &end, - const unsigned int n_intervals) - { - typedef std::pair IteratorPair; +#endif // #if (DEAL_II_USE_MT == 1) - // in non-multithreaded mode, we - // often have the case that this - // function is called with - // n_intervals==1, so have a - // shortcut here to handle that - // case efficiently - - if (n_intervals==1) - return (std::vector - (1, IteratorPair(begin, end))); - - // if more than one interval - // requested, do the full work - const unsigned int n_elements = distance (begin, end); - const unsigned int n_elements_per_interval = n_elements / n_intervals; - const unsigned int residual = n_elements % n_intervals; - - std::vector return_values (n_intervals); - return_values[0].first = begin; - for (unsigned int i=0; i=0' - // is checked (dist has a - // template type, which - // here is unsigned if no - // cast is performed) - std::advance (return_values[i].second, - static_cast(n_elements_per_interval)); - // distribute residual in - // division equally among - // the first few - // subintervals - if (i < residual) - ++return_values[i].second; - - return_values[i+1].first = return_values[i].second; - } - else - return_values[i].second = end; - } - return return_values; - } + /** + * A container for thread + * objects. Allows to add new + * thread objects and wait for them + * all together. The thread objects + * need to have the same return + * value for the called function. + * + * @author Wolfgang Bangerth, 2003 + */ + template + class ThreadGroup + { + public: + /** + * Add another thread object to + * the collection. + */ + ThreadGroup & operator += (const Thread &t) { + threads.push_back (t); + return *this; + }; - + /** + * Wait for all threads in the + * collection to finish. It is + * not a problem if some of + * them have already been + * waited for, i.e. you may + * call this function more than + * once, and you can also add + * new thread objects between + * subsequent calls to this + * function if you want. + */ + void join_all () const { + for (typename std::list >::const_iterator + t=threads.begin(); t!=threads.end(); ++t) + t->join (); + }; + + private: + /** + * List of thread objects. + */ + std::list > threads; + }; + + } // end of implementation of namespace Threads diff --git a/deal.II/base/source/data_out_base.cc b/deal.II/base/source/data_out_base.cc index 425823c4d0..37feed730b 100644 --- a/deal.II/base/source/data_out_base.cc +++ b/deal.II/base/source/data_out_base.cc @@ -2497,13 +2497,10 @@ void DataOutBase::write_gmv (const std::vector > &patches, // to write out the data, we wait // for that thread to finish Table<2,double> data_vectors (n_data_sets, n_nodes); - Threads::ThreadManager thread_manager; void (*fun_ptr) (const std::vector > &, Table<2,double> &) = &DataOutBase::template write_gmv_reorder_data_vectors; - Threads::spawn (thread_manager, - Threads::encapsulate (fun_ptr) - .collect_args(patches, data_vectors)); + Threads::Thread<> reorder_thread = Threads::spawn (fun_ptr)(patches, data_vectors); /////////////////////////////// // first make up a list of used @@ -2702,7 +2699,7 @@ void DataOutBase::write_gmv (const std::vector > &patches, // now write the data vectors to // @p{out} first make sure that all // data is in place - thread_manager.wait (); + reorder_thread.join (); // then write data. // the '1' means: node data (as opposed @@ -2877,13 +2874,10 @@ void DataOutBase::write_tecplot (const std::vector > &patche Table<2,double> data_vectors (n_data_sets, n_nodes); - Threads::ThreadManager thread_manager; void (*fun_ptr) (const std::vector > &, Table<2,double> &) = &DataOutBase::template write_gmv_reorder_data_vectors; - Threads::spawn (thread_manager, - Threads::encapsulate (fun_ptr) - .collect_args(patches, data_vectors)); + Threads::Thread<> reorder_thread = Threads::spawn (fun_ptr)(patches, data_vectors); /////////////////////////////// // first make up a list of used @@ -2977,7 +2971,7 @@ void DataOutBase::write_tecplot (const std::vector > &patche // now write the data vectors to // @p{out} first make sure that all // data is in place - thread_manager.wait (); + reorder_thread.join (); // then write data. for (unsigned int data_set=0; data_set > Table<2,double> data_vectors (n_data_sets, n_nodes); - Threads::ThreadManager thread_manager; - void (*fun_ptr) (const std::vector > &, - Table<2,double> &) - = &DataOutBase::template write_gmv_reorder_data_vectors; - Threads::spawn (thread_manager, - Threads::encapsulate (fun_ptr) - .collect_args(patches, data_vectors)); + void (*fun_ptr) (const std::vector > &, + Table<2,double> &) + = &DataOutBase::template write_gmv_reorder_data_vectors; + Threads::Thread<> reorder_thread = Threads::spawn (fun_ptr)(patches, data_vectors); /////////////////////////////// // first make up a list of used @@ -3319,7 +3310,7 @@ void DataOutBase::write_tecplot_binary (const std::vector > // coordinates - for (unsigned int d=1; d<=spacedim; ++d) + for (unsigned int d=1; d<=spacedim; ++d) { unsigned int entry=0; @@ -3395,7 +3386,7 @@ void DataOutBase::write_tecplot_binary (const std::vector > /////////////////////////////////////// // data output. // - thread_manager.wait (); + reorder_thread.join (); // then write data. for (unsigned int data_set=0; data_set > &patches, // for that thread to finish Table<2,double> data_vectors (n_data_sets, n_nodes); - Threads::ThreadManager thread_manager; void (*fun_ptr) (const std::vector > &, Table<2,double> &) = &DataOutBase::template write_gmv_reorder_data_vectors; - Threads::spawn (thread_manager, - Threads::encapsulate (fun_ptr) - .collect_args(patches, data_vectors)); + Threads::Thread<> reorder_thread = Threads::spawn (fun_ptr)(patches, data_vectors); /////////////////////////////// // first make up a list of used @@ -3832,7 +3820,7 @@ void DataOutBase::write_vtk (const std::vector > &patches, // now write the data vectors to // @p{out} first make sure that all // data is in place - thread_manager.wait (); + reorder_thread.join (); // then write data. the // 'POINTD_DATA' means: node data diff --git a/deal.II/base/source/thread_management.cc b/deal.II/base/source/thread_management.cc index 8fdf6941fb..ab7c5b3a4d 100644 --- a/deal.II/base/source/thread_management.cc +++ b/deal.II/base/source/thread_management.cc @@ -1,3 +1,6 @@ +// files on the new-threads branch: base/include/base/thread_management.h base/source/data_out_base.cc base/source/thread_management.cc deal.II/source/dofs/dof_tools.cc deal.II/source/grid/grid_generator.cc deal.II/source/multigrid/mg_dof_tools.cc deal.II/source/numerics/data_out.cc deal.II/source/numerics/data_out_faces.cc deal.II/source/numerics/data_out_rotation.cc deal.II/source/numerics/derivative_approximation.cc deal.II/source/numerics/error_estimator.cc deal.II/source/numerics/matrices.cc deal.II/source/numerics/time_dependent.cc examples/step-13/step-13.cc examples/step-14/step-14.cc examples/step-9/step-9.cc lac/include/lac/sparse_matrix.templates.h lac/include/lac/sparse_vanka.templates.h lac/include/lac/swappable_vector.h lac/include/lac/swappable_vector.templates.h configure configure.in aclocal.m4 common/Make.global_options.in contrib/hsl/source/detached_ma27.cc base/include/base/config.h.in + + //---------------------------- thread_management.cc --------------------------- // $Id$ // Version: $Name$ @@ -29,91 +32,85 @@ namespace Threads { - // counter and access mutex for the - // number of threads - volatile unsigned int n_existing_threads_counter = 1; - ThreadMutex n_existing_threads_mutex; - - - void register_new_thread () + namespace internal { - ThreadMutex::ScopedLock lock (n_existing_threads_mutex); - ++n_existing_threads_counter; - } - + // counter and access mutex for the + // number of threads + volatile unsigned int n_existing_threads_counter = 1; + ThreadMutex n_existing_threads_mutex; - void deregister_new_thread () - { - ThreadMutex::ScopedLock lock (n_existing_threads_mutex); - --n_existing_threads_counter; - Assert (n_existing_threads_counter >= 1, - ExcInternalError()); - } + void register_thread () + { + ThreadMutex::ScopedLock lock (n_existing_threads_mutex); + ++n_existing_threads_counter; + } - - void handle_std_exception (const std::exception &exc) - { - std::cerr << std::endl << std::endl - << "---------------------------------------------------------" - << std::endl - << "In one of the sub-threads of this program, an exception\n" - << "was thrown and not caught. Since exceptions do not\n" - << "propagate to the main thread, the library has caught it.\n" - << "The information carried by this exception is given below.\n" - << std::endl - << "---------------------------------------------------------" - << std::endl; - std::cerr << "Exception on processing: " << std::endl - << exc.what() << std::endl - << "Aborting!" << std::endl - << "---------------------------------------------------------" - << std::endl; - std::abort (); - } - - - - void handle_unknown_exception () - { - std::cerr << std::endl << std::endl - << "---------------------------------------------------------" - << std::endl - << "In one of the sub-threads of this program, an exception\n" - << "was thrown and not caught. Since exceptions do not\n" - << "propagate to the main thread, the library has caught it.\n" - << "The information carried by this exception is given below.\n" - << std::endl - << "---------------------------------------------------------" - << std::endl; - std::cerr << "Type of exception is unknown, but not std::exception.\n" - << "No additional information is available.\n" - << "---------------------------------------------------------" - << std::endl; - std::abort (); + + void deregister_thread () + { + ThreadMutex::ScopedLock lock (n_existing_threads_mutex); + --n_existing_threads_counter; + Assert (n_existing_threads_counter >= 1, + ExcInternalError()); + } + + + + void handle_std_exception (const std::exception &exc) + { + std::cerr << std::endl << std::endl + << "---------------------------------------------------------" + << std::endl + << "In one of the sub-threads of this program, an exception\n" + << "was thrown and not caught. Since exceptions do not\n" + << "propagate to the main thread, the library has caught it.\n" + << "The information carried by this exception is given below.\n" + << std::endl + << "---------------------------------------------------------" + << std::endl; + std::cerr << "Exception on processing: " << std::endl + << exc.what() << std::endl + << "Aborting!" << std::endl + << "---------------------------------------------------------" + << std::endl; + std::abort (); + } + + + + void handle_unknown_exception () + { + std::cerr << std::endl << std::endl + << "---------------------------------------------------------" + << std::endl + << "In one of the sub-threads of this program, an exception\n" + << "was thrown and not caught. Since exceptions do not\n" + << "propagate to the main thread, the library has caught it.\n" + << "The information carried by this exception is given below.\n" + << std::endl + << "---------------------------------------------------------" + << std::endl; + std::cerr << "Type of exception is unknown, but not std::exception.\n" + << "No additional information is available.\n" + << "---------------------------------------------------------" + << std::endl; + std::abort (); + } } unsigned int n_existing_threads () { - ThreadMutex::ScopedLock lock (n_existing_threads_mutex); - const unsigned int n = n_existing_threads_counter; + ThreadMutex::ScopedLock lock (internal::n_existing_threads_mutex); + const unsigned int n = internal::n_existing_threads_counter; return n; } #if DEAL_II_USE_MT != 1 - void DummyThreadManager::spawn (const FunPtr fun_ptr, - void * fun_data, - int /*flags*/) const - { - (*fun_ptr) (fun_data); - } - - - DummyBarrier::DummyBarrier (const unsigned int count, const char *, void *) @@ -219,256 +216,10 @@ namespace Threads - PosixThreadManager::PosixThreadManager () - : - thread_id_list (new std::list()) - {} - - - PosixThreadManager::~PosixThreadManager () - { - // wait for all threads, and - // release memory - wait (); - ThreadMutex::ScopedLock lock (list_mutex); - if (thread_id_list != 0) - delete reinterpret_cast*>(thread_id_list); - } - - - - void - PosixThreadManager::spawn (const FunPtr fun_ptr, - void * fun_data, - int) - { - std::list &tid_list - = *reinterpret_cast*>(thread_id_list); - - list_mutex.acquire (); - tid_list.push_back (pthread_t()); - pthread_t *tid = &tid_list.back(); - list_mutex.release (); - - // start new thread. retry until - // we either succeed or get an - // error other than EAGAIN - int error = 0; - do - { - error = pthread_create (tid, 0, fun_ptr, fun_data); - } - while (error == EAGAIN); - - AssertThrow (error == 0, ExcInternalError()); - } - - - - void - PosixThreadManager::wait () const - { - ThreadMutex::ScopedLock lock (list_mutex); - std::list &tid_list - = *reinterpret_cast*>(thread_id_list); - - // wait for all the threads in - // turn - for (std::list::iterator i=tid_list.begin(); - i != tid_list.end(); ++i) - pthread_join (*i, 0); - - // now we know that these threads - // have finished, remove their - // tid's from the list. this way, - // when new threads are spawned - // and waited for, we won't wait - // for expired threads with their - // invalid handles again - tid_list.clear (); - } # endif #endif - FunDataCounter::FunDataCounter () : - n_fun_encapsulation_objects (0), - n_fun_data_base_objects (0) - {} - - - - FunDataCounter::~FunDataCounter () - { - AssertThrow (n_fun_encapsulation_objects == 0, - ExcObjectsExist("FunEncapsulation", n_fun_encapsulation_objects)); - AssertThrow (n_fun_data_base_objects == 0, - ExcObjectsExist("FunDataBase", n_fun_data_base_objects)); - } - - - -/** - * This is the global object which we will use to count the number of - * threads generated, and which is used to complain when there is a - * memory leak. - */ - FunDataCounter fun_data_counter; - - - FunEncapsulation::FunEncapsulation () : - fun_data_base (0) - { - // keep some statistics on the - // number of variables around - ++fun_data_counter.n_fun_encapsulation_objects; - } - - - - FunEncapsulation::FunEncapsulation (FunDataBase *fun_data_base) : - fun_data_base (fun_data_base) - { - // keep some statistics on the - // number of variables around - ++fun_data_counter.n_fun_encapsulation_objects; - } - - - - FunEncapsulation::FunEncapsulation (const FunEncapsulation &fun_data) : - fun_data_base (fun_data.fun_data_base->clone ()) - { - // keep some statistics on the - // number of variables around - ++fun_data_counter.n_fun_encapsulation_objects; - } - - - FunEncapsulation::~FunEncapsulation () - { - // note that the spawn() function - // makes sure that we only get - // here if the data has already - // been copied by the spawned - // thread, so destruction is safe - // here. - // - // so do so. - delete fun_data_base; - fun_data_base = 0; - - // keep some statistics on the - // number of variables around - --fun_data_counter.n_fun_encapsulation_objects; - } - - - const FunEncapsulation & - FunEncapsulation::operator = (const FunEncapsulation &/*fun_data*/) - { - // this is not implemented at - // present. return dummy value - // instead - Assert (false, ExcNotImplemented()); - const FunEncapsulation * const p = 0; - return *p; - } - - - - FunDataBase::FunDataBase (const ThreadEntryPoint thread_entry_point) : - thread_entry_point (thread_entry_point) - { - // keep some statistics on the - // number of variables around - ++fun_data_counter.n_fun_data_base_objects; - } - - - - FunDataBase::FunDataBase (const FunDataBase &fun_data_base) : - thread_entry_point (fun_data_base.thread_entry_point) - { - // keep some statistics on the - // number of variables around - ++fun_data_counter.n_fun_data_base_objects; - } - - - - FunDataBase::~FunDataBase () - { - // invalidate pointer for security - // reasons. accesses to this - // pointer after lifetime of this - // object will then fail - thread_entry_point = 0; - - // keep some statistics on the - // number of variables around - --fun_data_counter.n_fun_data_base_objects; - } - - - - void spawn (ThreadManager &thread_manager, - const FunEncapsulation &fun_data) - { - // lock the @p{fun_data_base} object - // to avoid destruction while its - // data is still accessed. the lock - // is released by the new thread - // once it has copied all data - fun_data.fun_data_base->lock.acquire (); - // now start the new thread -#if DEAL_II_USE_MT == 1 -# if defined(DEAL_II_USE_MT_POSIX) - thread_manager.spawn (*fun_data.fun_data_base->thread_entry_point, - (void*)&fun_data, - 0); -# else -# error Not implemented -# endif -#else - // if not in MT mode, then simply - // call the respective - // serializing function, that - // executes the given function - // and return - thread_manager.spawn (*fun_data.fun_data_base->thread_entry_point, - (void*)&fun_data, - 0); -#endif - - // unlock the mutex and wait for - // the condition that the data - // has been copied to be - // signalled. unlocking the mutex - // will allow the other thread to - // proceed to the signal() call, - // which we want to catch here - // - // the mutex will subsequently be - // locked again, but since we - // don't need it any more, we can - // go on unlocking it immediately - // again - fun_data.fun_data_base->condition.wait(fun_data.fun_data_base->lock); - fun_data.fun_data_base->lock.release (); - } - - - - void spawn_n (ThreadManager &thread_manager, - const FunEncapsulation &fun_data, - const unsigned int n_threads) - { - for (unsigned int i=0; i > @@ -504,5 +255,159 @@ namespace Threads }; return return_values; } - + + +#if (DEAL_II_USE_MT == 1) && defined(DEAL_II_USE_MT_POSIX) + + namespace internal + { + thread_description_base::~thread_description_base () + { + // if we are here, then the + // last listener is just about + // to cease to exists. there + // are two possibilities (since + // there are two types of + // possible listeners, and + // exactly one listener is + // around): + // + // 1. there are no Thread<> + // objects around any more, but + // we are at the end of the + // entry_point function of the + // new thread; the thread is + // still running, though, and + // we are called from this new + // thread. + // + // if this is the case, + // apparently none of the + // orginal listeners has called + // join(), otherwise the thread + // would not be running any + // more. since there are no + // listeners any more, nobody + // will ever call join() on + // this thread any + // more. however, to avoid a + // resource leak, somebody has + // to do something like that -- + // on the other hand, we can't + // since calling pthread_join() + // on ourself will create a + // deadlock, of course. so + // detach the thread. + // + // note that in this case, + // since nobody has ever called + // join(), was_joined must be + // false + // + // 2. the thread has already + // ended. in this case, the + // last Thread<> object + // refering to it just went out + // of scope. If this is the + // case, to prevent a memory + // leak, we have to call join + // on the thread, if this has + // not yet happened, i.e. if + // was_joined is false. + // + // if we are in case 2, then + // the destructor is called + // from another than the + // presently running thread + // + // + // now: how do we find out + // which case we're in? we + // could either call + // pthread_join and see whether + // we get an error back, or if + // we get back an error on + // pthread_detach. from the man + // pages, the second way seems + // a little bit safer, so go it: + if (was_joined == false) + { + // assume case 1: + int error = pthread_detach (thread); + if (error == 0) + return; + + // ouch, could not + // detach. see if thread + // could not be found any + // more: + if (error == ESRCH) + // ok, this is the + // case. then we are in + // branch 2, and need to + // join the thread + join (); + else + // something went + // terribly wrong + AssertThrow (false, ExcInternalError()); + } + } + + + void + thread_description_base::create (void * (*p) (void *), void *d) + { + // start new thread. retry until + // we either succeed or get an + // error other than EAGAIN + int error = 0; + do + { + error = pthread_create (&thread, 0, p, d); + } + while (error == EAGAIN); + + AssertThrow (error == 0, ExcInternalError()); + } + + + + void + thread_description_base::join () const + { + // use Schmidt's double + // checking pattern: if thread + // was already joined, then + // return immediately + if (was_joined) + return; + + // otherwise make sure that + // only one thread can enter + // the following section at a + // time + ThreadMutex::ScopedLock lock(join_mutex); + // while getting the lock, + // another thread may have set + // was_joined to true, so check + // again (this is the double + // checking pattern) and only + // if we are really sure that + // this has not happened, call + // pthread_join + if (!was_joined) + { + const int error = pthread_join (thread, 0); + AssertThrow (error == 0, ExcInternalError()); + } + + // set the flag + was_joined = true; + } + + } // end namespace internal + +#endif // (DEAL_II_USE_MT == 1) && defined(DEAL_II_USE_MT_POSIX) + } // end namespace Thread diff --git a/deal.II/common/Make.global_options.in b/deal.II/common/Make.global_options.in index 8636d7ba10..2468a45222 100644 --- a/deal.II/common/Make.global_options.in +++ b/deal.II/common/Make.global_options.in @@ -95,17 +95,19 @@ endif # environment variable, since the compiler will evaluate the value of # that anyway at compile time -include-path-base = $D/base/include -include-path-lac = $D/lac/include -include-path-deal2 = $D/deal.II/include -include-path-contrib-hsl = $D/contrib/hsl/include -include-path-tecplot = $(TECIO_INCLUDE) +include-path-base = $D/base/include +include-path-lac = $D/lac/include +include-path-deal2 = $D/deal.II/include +include-path-contrib-hsl = $D/contrib/hsl/include +include-path-contrib-boost = $D/contrib/boost/include +include-path-tecplot = $(TECIO_INCLUDE) INCLUDE = $(addprefix -I, $(include-path-base) \ $(include-path-lac) \ $(include-path-deal2)\ $(include-path-contrib-hsl)\ + $(include-path-contrib-boost)\ $(include-path-tecplot)) # compiler flags for debug and optimized mode diff --git a/deal.II/configure b/deal.II/configure index 5cfbf55db5..66fa4cb198 100755 --- a/deal.II/configure +++ b/deal.II/configure @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.in Revision: 1.141 . +# From configure.in Revision: 1.141.2.1 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.57. # @@ -2807,18 +2807,26 @@ echo "${ECHO_T}C++ compiler is HP aCC" >&6 GXX_VERSION=hp_aCC else - is_kai_cc="`($CXX --version 2>&1) | grep 'KAI C++'`" - is_kai_cc="$is_kai_cc`($CXX -v 2>&1) | grep /KCC/`" - if test "x$is_kai_cc" != "x" ; then - echo "$as_me:$LINENO: result: C++ compiler is KAI C++" >&5 -echo "${ECHO_T}C++ compiler is KAI C++" >&6 - GXX_VERSION=kai_cc + is_bcc="`($CXX -h 2>&1) | grep 'Borland'`" + if test "x$is_bcc" != "x" ; then + echo "$as_me:$LINENO: result: C++ compiler is Borland C++" >&5 +echo "${ECHO_T}C++ compiler is Borland C++" >&6 + GXX_VERSION=borland_bcc else - { { echo "$as_me:$LINENO: error: Unrecognized compiler -- sorry" >&5 + is_kai_cc="`($CXX --version 2>&1) | grep 'KAI C++'`" + is_kai_cc="$is_kai_cc`($CXX -v 2>&1) | grep /KCC/`" + if test "x$is_kai_cc" != "x" ; then + echo "$as_me:$LINENO: result: C++ compiler is KAI C++" >&5 +echo "${ECHO_T}C++ compiler is KAI C++" >&6 + GXX_VERSION=kai_cc + else + + { { echo "$as_me:$LINENO: error: Unrecognized compiler -- sorry" >&5 echo "$as_me: error: Unrecognized compiler -- sorry" >&2;} { (exit 1); exit 1; }; } - exit 1 + exit 1 + fi fi fi fi @@ -2836,6 +2844,8 @@ echo "$as_me: error: Unrecognized compiler -- sorry" >&2;} CXXFLAGSO="$CXXFLAGS -O2 -Wuninitialized -felide-constructors -ftemplate-depth-32" CXXFLAGSG="$CXXFLAGS -DDEBUG -pedantic -Wall -W -Wpointer-arith -Wwrite-strings -Wmissing-prototypes -Winline -Woverloaded-virtual -Wstrict-prototypes -Wsynth -Wsign-compare -Wconversion -Wswitch -ftemplate-depth-32" + CXXFLAGSG="$CXXFLAGSG -Wno-long-long" + case "$target" in *aix* ) CXXFLAGSPIC= @@ -2879,6 +2889,8 @@ echo "$as_me: error: Unrecognized compiler -- sorry" >&2;} esac + echo "$as_me:$LINENO: checking for std::advance warning" >&5 +echo $ECHO_N "checking for std::advance warning... $ECHO_C" >&6 ac_ext=cc ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -2886,8 +2898,6 @@ ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ex ac_compiler_gnu=$ac_cv_cxx_compiler_gnu CXXFLAGS="$CXXFLAGSG -Werror" - echo "$as_me:$LINENO: checking for std::advance warning" >&5 -echo $ECHO_N "checking for std::advance warning... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ @@ -2946,9 +2956,62 @@ rm -f conftest.$ac_objext conftest.$ac_ext fi case "$target" in - *apple-darwin*) + *apple-darwin*) CXXFLAGSG="$CXXFLAGSG -Wno-long-double" CXXFLAGSO="$CXXFLAGSO -Wno-long-double" + ;; + + *dec-osf*) + echo "$as_me:$LINENO: checking for preprocessor warning with cuserid" >&5 +echo $ECHO_N "checking for preprocessor warning with cuserid... $ECHO_C" >&6 + CXXFLAGS="$CXXFLAGSG -Werror" + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +# include +# include + +int +main () +{ +; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + CXXFLAGSG="$CXXFLAGSG -Wp,-w" + CXXFLAGSO="$CXXFLAGSO -Wp,-w" + +fi +rm -f conftest.$ac_objext conftest.$ac_ext ;; esac @@ -3003,11 +3066,12 @@ rm -f conftest.$ac_objext conftest.$ac_ext CXXFLAGSG="$CXXFLAGS -model ansi -std strict_ansi -w1 -msg_display_number -timplicit_local -DDEBUG" CXXFLAGSO="$CXXFLAGS -model ansi -std strict_ansi -w2 -msg_display_number -timplicit_local -fast" - for i in 175 236 237 381 487 1136 1156 111 1182 265 ; do + for i in 175 236 237 381 487 1136 1156 111 1182 265 450 ; do CXXFLAGSG="$CXXFLAGSG -msg_disable $i" CXXFLAGSO="$CXXFLAGSO -msg_disable $i" done + LDFLAGS="$LDFLAGS -model ansi" LDFLAGS="$LDFLAGS -lm" @@ -3042,6 +3106,13 @@ rm -f conftest.$ac_objext conftest.$ac_ext # for linking shared libs, -b is also necessary... ;; + borland_bcc) + CXXFLAGSG="$CXXFLAGS -q -DDEBUG -w -w-use -w-amp -w-prc" + CXXFLAGSO="$CXXFLAGS -q -O2" + CXXFLAGSPIC="" + LDFLAGSPIC="" + ;; + *) { { echo "$as_me:$LINENO: error: No compiler options for this C++ compiler specified at present" >&5 @@ -3174,7 +3245,15 @@ rm -f conftest.$ac_objext conftest.$ac_ext esac else - CXXFLAGSG="-g $CXXFLAGSG" + case "$GXX_VERSION" in + borland_bcc) + CXXFLAGSG="-v -y $CXXFLAGSG" + ;; + + *) + CXXFLAGSG="-g $CXXFLAGSG" + ;; + esac fi @@ -3261,6 +3340,7 @@ ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + CXXFLAGS="$CXXFLAGSG" cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ @@ -3357,13 +3437,13 @@ echo "$as_me: error: No threading compiler options for this C++ compiler gcc*) echo "$as_me:$LINENO: checking for only partly bracketed mutex initializer" >&5 echo $ECHO_N "checking for only partly bracketed mutex initializer... $ECHO_C" >&6 - CXXFLAGS="$CXXFLAGSG -Werror" ac_ext=cc ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + CXXFLAGS="$CXXFLAGSG -Werror" cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ @@ -3443,6 +3523,7 @@ ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + CXXFLAGS="$CXXFLAGSG" cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ @@ -4173,8 +4254,8 @@ _ACEOF - echo "$as_me:$LINENO: checking for template friend in namespace bug" >&5 -echo $ECHO_N "checking for template friend in namespace bug... $ECHO_C" >&6 + echo "$as_me:$LINENO: checking for 1st template friend in namespace bug" >&5 +echo $ECHO_N "checking for 1st template friend in namespace bug... $ECHO_C" >&6 ac_ext=cc ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -4250,6 +4331,78 @@ cat >>confdefs.h <<_ACEOF _ACEOF +fi +rm -f conftest.$ac_objext conftest.$ac_ext + + + echo "$as_me:$LINENO: checking for 2nd template friend in namespace bug" >&5 +echo $ECHO_N "checking for 2nd template friend in namespace bug... $ECHO_C" >&6 + ac_ext=cc +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + CXXFLAGS="$CXXFLAGSG -Werror" + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + namespace NS { + template struct Foo; + } + + class Bar { + template friend struct NS::Foo; + }; + + namespace NS { + template struct Foo { Foo (); }; + } + + template struct NS::Foo; + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + + echo "$as_me:$LINENO: result: yes. using workaround" >&5 +echo "${ECHO_T}yes. using workaround" >&6 + +cat >>confdefs.h <<_ACEOF +#define DEAL_II_NAMESP_TEMPL_FRIEND_BUG2 1 +_ACEOF + + fi rm -f conftest.$ac_objext conftest.$ac_ext @@ -4817,6 +4970,67 @@ fi rm -f conftest.$ac_objext conftest.$ac_ext + if test "x$GXX_VERSION" != "x" ; then + echo "$as_me:$LINENO: checking for boost::shared_ptr assignment operator= template buglet" >&5 +echo $ECHO_N "checking for boost::shared_ptr assignment operator= template buglet... $ECHO_C" >&6 + ac_ext=cc +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + CXXFLAGS="-Wsynth -Werror -I `pwd`/contrib/boost/include" + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +# include + +int +main () +{ + + boost::shared_ptr a,b; + a = b; + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + CXXFLAGSG="`echo $CXXFLAGSG | perl -pi -e 's/-Wsynth\s*//g;'`" + +fi +rm -f conftest.$ac_objext conftest.$ac_ext + fi + + echo "$as_me:$LINENO: checking for __PRETTY_FUNCTION__" >&5 echo $ECHO_N "checking for __PRETTY_FUNCTION__... $ECHO_C" >&6 ac_ext=cc @@ -5385,6 +5599,7 @@ ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + CXXFLAGS="$CXXFLAGSG" cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ @@ -5863,6 +6078,8 @@ echo "${ECHO_T}using $testflag" >&6 + echo "$as_me:$LINENO: checking for rand_r" >&5 +echo $ECHO_N "checking for rand_r... $ECHO_C" >&6 ac_ext=cc ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -5870,8 +6087,6 @@ ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ex ac_compiler_gnu=$ac_cv_cxx_compiler_gnu CXXFLAGS=$CXXFLAGSG - echo "$as_me:$LINENO: checking for rand_r" >&5 -echo $ECHO_N "checking for rand_r... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ @@ -5988,8 +6203,8 @@ fi rm -f conftest.$ac_objext conftest.$ac_ext - echo "$as_me:$LINENO: checking for defintions of error codes in errno.h" >&5 -echo $ECHO_N "checking for defintions of error codes in errno.h... $ECHO_C" >&6 + echo "$as_me:$LINENO: checking for definitions of error codes in errno.h" >&5 +echo $ECHO_N "checking for definitions of error codes in errno.h... $ECHO_C" >&6 ac_ext=cc ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -6798,6 +7013,8 @@ echo "$as_me:$LINENO: result: ------------------ checking compiler flags ------- echo "${ECHO_T}------------------ checking compiler flags ------------------" >&6 + echo "$as_me:$LINENO: checking for consistency of CXXFLAGSG flags" >&5 +echo $ECHO_N "checking for consistency of CXXFLAGSG flags... $ECHO_C" >&6 ac_ext=cc ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -6805,8 +7022,6 @@ ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ex ac_compiler_gnu=$ac_cv_cxx_compiler_gnu CXXFLAGS="$CXXFLAGSG" - echo "$as_me:$LINENO: checking for consistency of CXXFLAGSG flags" >&5 -echo $ECHO_N "checking for consistency of CXXFLAGSG flags... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ @@ -6852,9 +7067,9 @@ echo "$as_me: error: invalid combination of flags!" >&2;} fi rm -f conftest.$ac_objext conftest.$ac_ext - CXXFLAGS="$CXXFLAGSO" echo "$as_me:$LINENO: checking for consistency of CXXFLAGSO flags" >&5 echo $ECHO_N "checking for consistency of CXXFLAGSO flags... $ECHO_C" >&6 + CXXFLAGS="$CXXFLAGSO" cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" /* confdefs.h. */ diff --git a/deal.II/configure.in b/deal.II/configure.in index 00f68ec07d..1593df5c55 100644 --- a/deal.II/configure.in +++ b/deal.II/configure.in @@ -167,6 +167,7 @@ DEAL_II_CHECK_LOCAL_TYPEDEF_COMP DEAL_II_CHECK_TEMPLATE_SPEC_ACCESS DEAL_II_CHECK_MEMBER_OP_TEMPLATE_INST DEAL_II_CHECK_NAMESP_TEMPL_FRIEND_BUG +DEAL_II_CHECK_NAMESP_TEMPL_FRIEND_BUG2 DEAL_II_CHECK_TEMPL_SPEC_FRIEND_BUG DEAL_II_CHECK_TEMPL_CONST_MEM_PTR_BUG DEAL_II_CHECK_CONST_MEM_FUN_PTR_BUG @@ -175,6 +176,7 @@ DEAL_II_CHECK_TEMPLATE_TEMPLATE_TYPEDEF_BUG DEAL_II_CHECK_NESTED_CLASS_FRIEND_BUG DEAL_II_CHECK_MEMBER_VAR_SPECIALIZATION_BUG DEAL_II_CHECK_LONG_DOUBLE_LOOP_BUG +DEAL_II_CHECK_BOOST_SHARED_PTR_ASSIGNMENT DEAL_II_HAVE_PRETTY_FUNCTION DEAL_II_HAVE_STD_ITERATOR DEAL_II_HAVE_STD_STRINGSTREAM diff --git a/deal.II/contrib/hsl/source/detached_ma27.cc b/deal.II/contrib/hsl/source/detached_ma27.cc index 9b619410ff..91f34ef2e8 100644 --- a/deal.II/contrib/hsl/source/detached_ma27.cc +++ b/deal.II/contrib/hsl/source/detached_ma27.cc @@ -243,11 +243,12 @@ int main () pid_t master_pid; get (&master_pid, 1, "master_pid"); // ...and start off a thread that - // actually checks that - Threads::ThreadManager thread_manager; - Threads::spawn (thread_manager, - Threads::encapsulate (&monitor_parent_liveness) - .collect_args(master_pid, getpid())); + // actually checks that. this + // second process will eventually + // be kill when we exit the main + // program, but part from that we + // create it detached + Threads::spawn (&monitor_parent_liveness)(master_pid, getpid()); // then go into the action loop... unsigned int N, NZ, NSTEPS, LA, MAXFRT, LIW; @@ -373,14 +374,11 @@ int main () getpid()); }; }; - // exit here explicitly, without - // giving the thread manager a - // chance to wait for the child - // thread, since that will loop - // forever. however, we should + // exit without waiting for the + // child thread, since that will + // loop forever. however, we should // never be able to get to this // point anyway... - exit (1); } diff --git a/deal.II/deal.II/source/dofs/dof_tools.cc b/deal.II/deal.II/source/dofs/dof_tools.cc index d05aa72fda..b4202eb69e 100644 --- a/deal.II/deal.II/source/dofs/dof_tools.cc +++ b/deal.II/deal.II/source/dofs/dof_tools.cc @@ -1550,7 +1550,7 @@ count_dofs_per_component (const DoFHandler &dof_handler, std::vector > component_select (n_components, std::vector(n_components, false)); - Threads::ThreadManager thread_manager; + Threads::ThreadGroup<> threads; for (unsigned int i=0; i &, @@ -1558,12 +1558,10 @@ count_dofs_per_component (const DoFHandler &dof_handler, std::vector &) = &DoFTools::template extract_dofs; component_select[i][i] = true; - Threads::spawn (thread_manager, - Threads::encapsulate (fun_ptr) - .collect_args (dof_handler, component_select[i], - dofs_in_component[i])); + threads += Threads::spawn (fun_ptr)(dof_handler, component_select[i], + dofs_in_component[i]); }; - thread_manager.wait(); + threads.join_all (); // next count what we got for (unsigned int i=0; i &coars coarse_grid.end(), multithread_info.n_default_threads); - Threads::ThreadManager thread_manager; + Threads::ThreadGroup<> threads; void (*fun_ptr) (const DoFHandler &, const unsigned int , const InterGridMap &, @@ -2178,16 +2176,14 @@ DoFTools::compute_intergrid_weights_2 (const DoFHandler &coars const typename DoFHandler::active_cell_iterator &) = &DoFTools::template compute_intergrid_weights_3; for (unsigned int i=0; i &tria, std::vector > us(dim, Vector (dof_handler.n_dofs())); // solve linear systems in parallel - Threads::ThreadManager thread_manager; + Threads::ThreadGroup<> threads; for (unsigned int i=0; i& dof_handler, std::vector > component_select (n_components, std::vector(n_components, false)); - Threads::ThreadManager thread_manager; + Threads::ThreadGroup<> threads; for (unsigned int i=0; i& dof_handler, std::vector &) = &DoFTools::template extract_level_dofs; component_select[i][i] = true; - Threads::spawn (thread_manager, - Threads::encapsulate (fun_ptr) - .collect_args (l, dof_handler, component_select[i], - dofs_in_component[i])); + threads += Threads::spawn (fun_ptr)(l, dof_handler, component_select[i], + dofs_in_component[i]); }; - thread_manager.wait(); + threads.join_all(); // next count what we got for (unsigned int i=0; i::build_patches (const unsigned int n_subdivisions, thread_data[i].patch_values_system[k].reinit(n_components); } - Threads::ThreadManager thread_manager; + Threads::ThreadGroup<> threads; for (unsigned int l=0; l::build_some_patches) - .collect_args (this, thread_data[l])); - thread_manager.wait(); + threads += Threads::spawn (*this, &DataOut::build_some_patches)(thread_data[l]); + threads.join_all(); } diff --git a/deal.II/deal.II/source/numerics/data_out_faces.cc b/deal.II/deal.II/source/numerics/data_out_faces.cc index 1ce9a141c0..b56dea8934 100644 --- a/deal.II/deal.II/source/numerics/data_out_faces.cc +++ b/deal.II/deal.II/source/numerics/data_out_faces.cc @@ -201,12 +201,10 @@ void DataOutFaces::build_patches (const unsigned int n_subdivisions, if (DEAL_II_USE_MT) { - Threads::ThreadManager thread_manager; + Threads::ThreadGroup<> threads; for (unsigned int l=0;l::build_some_patches) - .collect_args (this, thread_data[l])); - thread_manager.wait(); + threads += Threads::spawn (*this, &DataOutFaces::build_some_patches)(thread_data[l]); + threads.join_all(); } else // just one thread diff --git a/deal.II/deal.II/source/numerics/data_out_rotation.cc b/deal.II/deal.II/source/numerics/data_out_rotation.cc index e15a615de8..c91ef5c30d 100644 --- a/deal.II/deal.II/source/numerics/data_out_rotation.cc +++ b/deal.II/deal.II/source/numerics/data_out_rotation.cc @@ -385,12 +385,11 @@ void DataOutRotation::build_patches (const unsigned int n_patches_per_circl if (DEAL_II_USE_MT) { - Threads::ThreadManager thread_manager; + Threads::ThreadGroup<> threads; for (unsigned int l=0;l::build_some_patches) - .collect_args (this, thread_data[l])); - thread_manager.wait(); + threads += Threads::spawn (*this, &DataOutRotation::build_some_patches) + (thread_data[l]); + threads.join_all(); } else // just one thread diff --git a/deal.II/deal.II/source/numerics/derivative_approximation.cc b/deal.II/deal.II/source/numerics/derivative_approximation.cc index 34ad0e83bb..7549c9b079 100644 --- a/deal.II/deal.II/source/numerics/derivative_approximation.cc +++ b/deal.II/deal.II/source/numerics/derivative_approximation.cc @@ -468,7 +468,7 @@ approximate_derivative (const Mapping &mapping, std::vector index_intervals = Threads::split_interval (0, dof_handler.get_tria().n_active_cells(), n_threads); - Threads::ThreadManager thread_manager; + Threads::ThreadGroup<> threads; void (*fun_ptr) (const Mapping &, const DoFHandler &, const Vector &, @@ -477,12 +477,10 @@ approximate_derivative (const Mapping &mapping, Vector &) = &DerivativeApproximation::template approximate; for (unsigned int i=0; i::estimate (const Mapping &mapping // split all cells into threads if // multithreading is used and run // the whole thing - Threads::ThreadManager thread_manager; + Threads::ThreadGroup<> threads; for (unsigned int i=0; i::estimate_some) - .collect_args (mapping, dof_handler, - quadrature, neumann_bc, solutions, - component_mask, coefficients, - std::make_pair(i, n_threads), - face_integrals, - *data_structures[i])); - thread_manager.wait(); + threads += Threads::spawn (&KellyErrorEstimator::estimate_some) + (mapping, dof_handler, + quadrature, neumann_bc, solutions, + component_mask, coefficients, + std::make_pair(i, n_threads), + face_integrals, + *data_structures[i]); + threads.join_all(); // delete the structures for the // different threads again. the diff --git a/deal.II/deal.II/source/numerics/matrices.cc b/deal.II/deal.II/source/numerics/matrices.cc index 861d3f02ba..faa104f129 100644 --- a/deal.II/deal.II/source/numerics/matrices.cc +++ b/deal.II/deal.II/source/numerics/matrices.cc @@ -71,7 +71,7 @@ void MatrixCreator::create_mass_matrix (const Mapping &mapping, ExcDimensionMismatch (matrix.n(), dof.n_dofs())); const unsigned int n_threads = multithread_info.n_default_threads; - Threads::ThreadManager thread_manager; + Threads::ThreadGroup<> threads; // define starting and end point // for each thread @@ -94,11 +94,9 @@ void MatrixCreator::create_mass_matrix (const Mapping &mapping, Threads::ThreadMutex &mutex); create_mass_matrix_1_t p = &MatrixCreator::template create_mass_matrix_1; for (unsigned int thread=0; thread &mapping, ExcDimensionMismatch (matrix.n(), dof.n_dofs())); const unsigned int n_threads = multithread_info.n_default_threads; - Threads::ThreadManager thread_manager; + Threads::ThreadGroup<> threads; // define starting and end point // for each thread @@ -276,12 +274,10 @@ void MatrixCreator::create_mass_matrix (const Mapping &mapping, Threads::ThreadMutex &mutex); create_mass_matrix_2_t p = &MatrixCreator::template create_mass_matrix_2; for (unsigned int thread=0; thread &mapping, const Function * const coefficient) { const unsigned int n_threads = multithread_info.n_default_threads; - Threads::ThreadManager thread_manager; + Threads::ThreadGroup<> threads; // define starting and end point // for each thread @@ -497,13 +493,11 @@ MatrixCreator::create_boundary_mass_matrix (const Mapping &mapping, Threads::ThreadMutex &mutex); create_boundary_mass_matrix_1_t p = &MatrixCreator::template create_boundary_mass_matrix_1; for (unsigned int thread=0; thread &mapping, ExcDimensionMismatch (matrix.n(), dof.n_dofs())); const unsigned int n_threads = multithread_info.n_default_threads; - Threads::ThreadManager thread_manager; + Threads::ThreadGroup<> threads; // define starting and end point // for each thread @@ -921,11 +915,9 @@ void MatrixCreator::create_laplace_matrix (const Mapping &mapping, Threads::ThreadMutex &mutex); create_laplace_matrix_1_t p = &MatrixCreator::template create_laplace_matrix_1; for (unsigned int thread=0; thread &mapping, ExcDimensionMismatch (matrix.n(), dof.n_dofs())); const unsigned int n_threads = multithread_info.n_default_threads; - Threads::ThreadManager thread_manager; + Threads::ThreadGroup<> threads; // define starting and end point // for each thread @@ -1106,12 +1098,10 @@ void MatrixCreator::create_laplace_matrix (const Mapping &mapping, Threads::ThreadMutex &mutex); create_laplace_matrix_2_t p = &MatrixCreator::template create_laplace_matrix_2; for (unsigned int thread=0; thread 1)) { const unsigned int stride = timesteps.size() / n_threads; - Threads::ThreadManager thread_manager; + Threads::ThreadGroup<> threads; void (TimeDependent::*p) (const unsigned int, const unsigned int) = &TimeDependent::end_sweep; for (unsigned int i=0; i threads; for (unsigned int thread=0; thread::assemble_matrix) - .collect_args (this, - linear_system, - thread_ranges[thread].first, - thread_ranges[thread].second, - mutex)); + threads += Threads::spawn (*this, &Solver::assemble_matrix) + (linear_system, + thread_ranges[thread].first, + thread_ranges[thread].second, + mutex); // While the spawned threads // assemble the system matrix, we @@ -1244,7 +1242,7 @@ namespace LaplaceSolver // matrix assembling threads, and // condense the constraints in // the matrix as well: - thread_manager.wait (); + threads.join_all (); linear_system.hanging_node_constraints.condense (linear_system.matrix); // Now that we have the linear @@ -1420,7 +1418,13 @@ namespace LaplaceSolver // performed sequentially). Note // that we spawn only one thread, // and do the second action in the - // main thread. + // main thread. Since only one + // thread is generated, we don't + // use the ``Threads::ThreadGroup'' + // class here, but rather use the + // one created thread object + // directly to wait for this + // particular thread's exit. // // Note that taking up the address // of the @@ -1468,11 +1472,9 @@ namespace LaplaceSolver ConstraintMatrix &) = &DoFTools::make_hanging_node_constraints; - Threads::ThreadManager thread_manager; - Threads::spawn (thread_manager, - Threads::encapsulate (mhnc_p) - .collect_args (dof_handler, - hanging_node_constraints)); + Threads::Thread<> + mhnc_thread = Threads::spawn (mhnc_p)(dof_handler, + hanging_node_constraints); sparsity_pattern.reinit (dof_handler.n_dofs(), dof_handler.n_dofs(), @@ -1484,7 +1486,7 @@ namespace LaplaceSolver // object is fully set up, then // close it and use it to // condense the sparsity pattern: - thread_manager.wait (); + mhnc_thread.join (); hanging_node_constraints.close (); hanging_node_constraints.condense (sparsity_pattern); diff --git a/deal.II/examples/step-14/step-14.cc b/deal.II/examples/step-14/step-14.cc index 6b2b02af5a..ea5cc546e4 100644 --- a/deal.II/examples/step-14/step-14.cc +++ b/deal.II/examples/step-14/step-14.cc @@ -656,15 +656,13 @@ namespace LaplaceSolver n_threads); Threads::ThreadMutex mutex; - Threads::ThreadManager thread_manager; + Threads::ThreadGroup<> threads; for (unsigned int thread=0; thread::assemble_matrix) - .collect_args (this, - linear_system, - thread_ranges[thread].first, - thread_ranges[thread].second, - mutex)); + threads += Threads::spawn (*this, &Solver::assemble_matrix) + (linear_system, + thread_ranges[thread].first, + thread_ranges[thread].second, + mutex); assemble_rhs (linear_system.rhs); linear_system.hanging_node_constraints.condense (linear_system.rhs); @@ -675,7 +673,7 @@ namespace LaplaceSolver *boundary_values, boundary_value_map); - thread_manager.wait (); + threads.join_all (); linear_system.hanging_node_constraints.condense (linear_system.matrix); MatrixTools::apply_boundary_values (boundary_value_map, @@ -739,18 +737,15 @@ namespace LaplaceSolver ConstraintMatrix &) = &DoFTools::make_hanging_node_constraints; - Threads::ThreadManager thread_manager; - Threads::spawn (thread_manager, - Threads::encapsulate (mhnc_p) - .collect_args (dof_handler, - hanging_node_constraints)); + Threads::Thread<> + mhnc_thread = Threads::spawn (mhnc_p)(dof_handler, hanging_node_constraints); sparsity_pattern.reinit (dof_handler.n_dofs(), dof_handler.n_dofs(), dof_handler.max_couplings_between_dofs()); DoFTools::make_sparsity_pattern (dof_handler, sparsity_pattern); - thread_manager.wait (); + mhnc_thread.join (); hanging_node_constraints.close (); hanging_node_constraints.condense (sparsity_pattern); @@ -2651,14 +2646,10 @@ namespace LaplaceSolver void WeightedResidual::solve_problem () { - Threads::ThreadManager thread_manager; - Threads::spawn (thread_manager, - Threads::encapsulate (&WeightedResidual<2>::solve_primal_problem) - .collect_args (this)); - Threads::spawn (thread_manager, - Threads::encapsulate (&WeightedResidual<2>::solve_dual_problem) - .collect_args (this)); - thread_manager.wait (); + Threads::ThreadGroup<> threads; + threads += Threads::spawn (*this, &WeightedResidual<2>::solve_primal_problem)(); + threads += Threads::spawn (*this, &WeightedResidual<2>::solve_dual_problem)(); + threads.join_all (); } @@ -3007,7 +2998,8 @@ namespace LaplaceSolver // us from the necessity to // synchronise the threads // through a mutex each time they - // write to this map. + // write to (and modify the + // structure of) this map. FaceIntegrals face_integrals; for (active_cell_iterator cell=dual_solver.dof_handler.begin_active(); cell!=dual_solver.dof_handler.end(); @@ -3031,18 +3023,15 @@ namespace LaplaceSolver // started wait until they have // all finished: const unsigned int n_threads = multithread_info.n_default_threads; - Threads::ThreadManager thread_manager; + Threads::ThreadGroup<> threads; for (unsigned int i=0; i:: - estimate_some) - .collect_args (this, - primal_solution, - dual_weights, - n_threads, i, - error_indicators, - face_integrals)); - thread_manager.wait(); + threads += Threads::spawn (*this, &WeightedResidual::estimate_some) + (primal_solution, + dual_weights, + n_threads, i, + error_indicators, + face_integrals); + threads.join_all(); // Once the error contributions // are computed, sum them up. For diff --git a/deal.II/examples/step-9/step-9.cc b/deal.II/examples/step-9/step-9.cc index 3be63565dc..bedbda9b03 100644 --- a/deal.II/examples/step-9/step-9.cc +++ b/deal.II/examples/step-9/step-9.cc @@ -48,10 +48,8 @@ // functions are declared which we // need to start new threads and to // wait for threads to return - // (i.e. the ``ThreadManager'' class - // and the ``spawn'', - // ``encapsulate'', and - // ``collect_args'' functions). The + // (i.e. the ``Thread'' class + // and the ``spawn'' functions). The // second file has a class // ``MultithreadInfo'' (and a global // object ``multithread_info'' of @@ -162,8 +160,8 @@ class AdvectionProblem // local contributions of a cell // to the global matrix at the // same time. This is done using - // a ``Mutex'', which is a kind - // of lock that can be owned by + // a ``Mutex'', which is an + // object that can be owned by // only one thread at a time. If // a thread wants to write to the // matrix, it has to acquire this @@ -744,33 +742,53 @@ void AdvectionProblem::assemble_system () // many threads they shall spawn. const unsigned int n_threads = multithread_info.n_default_threads; // Next, we need an object which is - // capable of starting new threads - // and waiting for them to - // finish. This is done using the - // ``Threads::ThreadManager'' - // typedef. If the library is - // configured to support - // multi-threading, then this - // typedef points to a class in the - // ACE library which provides this - // functionality. If you did not - // configure for multi-threading, - // then the typedef points to a - // dummy class in which the + // capable of keeping track of the + // threads we created, and allows + // us to wait until they all have + // finished (to ``join'' them in + // the language of threads). The + // ``Threads::ThreadGroup'' class + // does this, which is basically + // just a container for objects of + // type ``Threads::Thread'' that + // represent a single thread; + // ``Threads::Thread'' is what the + // ``spawn'' function below will + // return when we start a new + // thread. + // + // Note that both ``ThreadGroup'' + // and ``Thread'' have a template + // argument that represents the + // return type of the function + // being called on a separate + // thread. Since most of the + // functions that we will call on + // different threads have return + // type ``void'', the template + // argument has a default value + // ``void'', so that in that case + // it can be omitted. (However, you + // still need to write the angle + // brackets, even if they are + // empty.) + // + // If you did not configure for + // multi-threading, then the // ``spawn'' function that is // supposed to start a new thread // in parallel only executes the // function which should be run in - // parallel and waits for it to - // return (i.e. the function is - // executed - // sequentially). Likewise, the - // function ``wait'' that is - // supposed to wait for all spawned - // threads to return, returns - // immediately, as there can't be - // threads running. - Threads::ThreadManager thread_manager; + // parallel, waits for it to return + // (i.e. the function is executed + // sequentially), and puts the + // return value into the ``Thread'' + // object. Likewise, the function + // ``join'' that is supposed to + // wait for all spawned threads to + // return, returns immediately, as + // there can't be threads running. + Threads::ThreadGroup<> threads; // Now we have to split the range // of cells into chunks of @@ -827,8 +845,8 @@ void AdvectionProblem::assemble_system () dof_handler.end (), n_threads); - // Now, for each of the chunks of - // iterators we have computed, + // Finally, for each of the chunks + // of iterators we have computed, // start one thread (or if not in // multi-thread mode: execute // assembly on these chunks @@ -836,11 +854,9 @@ void AdvectionProblem::assemble_system () // using the following sequence of // function calls: for (unsigned int thread=0; thread::assemble_system_interval) - .collect_args (this, - thread_ranges[thread].first, - thread_ranges[thread].second)); + threads += Threads::spawn (*this, &AdvectionProblem::assemble_system_interval) + (thread_ranges[thread].first, + thread_ranges[thread].second); // The reasons and internal // workings of these functions can // be found in the report on the @@ -851,11 +867,25 @@ void AdvectionProblem::assemble_system () // the ``assemble_system_interval'' // function on the present object // (the ``this'' pointer), with the - // next to arguments passed as - // parameters. Each thread's number - // is entered into an array - // administered by the - // ``thread_manager'' object. + // arguments following in the + // second set of parentheses passed + // as parameters. The ``spawn'' + // function return an object of + // type ``Threads::Thread'', which + // we put into the ``threads'' + // container. If a thread exits, + // the return value of the function + // being called is put into a place + // such that the thread objects can + // access it using their + // ``return_value'' function; since + // the function we call doesn't + // have a return value, this does + // not apply here. Note that you + // can copy around thread objects + // freely, and that of course they + // will still represent the same + // thread. // When all the threads are // running, the only thing we have @@ -866,18 +896,18 @@ void AdvectionProblem::assemble_system () // right hand side are // assemblesd. Waiting for all the // threads to finish can be done - // using the following function - // call, which uses the facts that - // the identification number of the - // spawned threads are stored in - // the ``thread_manager'' - // object. Again, if the library - // was not configured to use + // using the ``joint_all'' function + // in the ``ThreadGroup'' + // container, which just calls + // ``join'' on each of the thread + // objects it stores. + // + // Again, if the library was not + // configured to use // multi-threading, then no threads // can run in parallel and the - // following function returns - // immediately. - thread_manager.wait (); + // function returns immediately. + threads.join_all (); // After the matrix has been @@ -1190,13 +1220,13 @@ assemble_system_interval (const typename DoFHandler::active_cell_iterator & // the information on the grid, // the DoF handler, or the DoF // numbers) they are only - // read. This, the different + // read. Thus, the different // threads do not disturb each // other. // // On the other hand, we would // now like to write the local - // contributions to the glbal + // contributions to the global // system of equations into the // global objects. This needs // some kind of @@ -1452,15 +1482,17 @@ GradientEstimation::estimate (const DoFHandler &dof_handler, = Threads::split_interval (0, dof_handler.get_tria().n_active_cells(), n_threads); - // Now we need a thread management - // object, and then we can spawn - // the threads which each work on - // their assigned chunk of - // cells. Note that as the function - // called is not a member function, - // but rather a static function, we - // need not (and can not) pass a - // ``this'' function in this case. + // In the same way as before, we + // use a ``Threads::ThreadGroup'' + // object to collect the descriptor + // objects of different + // threads. Note that as the + // function called is not a member + // function, but rather a static + // function, we need not (and can + // not) pass a ``this'' pointer to + // the ``spawn'' function in this + // case. // // Taking pointers to templated // functions seems to be @@ -1477,28 +1509,27 @@ GradientEstimation::estimate (const DoFHandler &dof_handler, // to take a temporary variable for // that purpose. Here, in this // case, Compaq's ``cxx'' compiler - // choked on the code so we use the - // workaround with the function - // pointer: - Threads::ThreadManager thread_manager; + // choked on the code so we use + // this workaround with the + // function pointer: + Threads::ThreadGroup<> threads; void (*estimate_interval_ptr) (const DoFHandler &, const Vector &, const IndexInterval &, Vector &) = &GradientEstimation::template estimate_interval; for (unsigned int i=0; i::vmult (Vector& dst, const mem_fun_p comp = (&SparseMatrix:: template threaded_vmult); - Threads::ThreadManager thread_manager; + Threads::ThreadGroup<> threads; for (unsigned int i=0; i::matrix_norm_square (const Vector& v) const // space for the norms of // the different parts std::vector partial_sums (n_threads, 0); - Threads::ThreadManager thread_manager; // then spawn threads. since // some compilers have trouble // finding out which @@ -485,16 +482,15 @@ SparseMatrix::matrix_norm_square (const Vector& v) const const mem_fun_p comp = (&SparseMatrix:: template threaded_matrix_norm_square); + Threads::ThreadGroup<> threads; for (unsigned int i=0; i::matrix_scalar_product (const Vector& u, // space for the norms of // the different parts std::vector partial_sums (n_threads, 0); - Threads::ThreadManager thread_manager; // then spawn threads. since // some compilers have trouble // finding out which @@ -599,16 +594,15 @@ SparseMatrix::matrix_scalar_product (const Vector& u, const mem_fun_p comp = (&SparseMatrix:: template threaded_matrix_scalar_product); + Threads::ThreadGroup<> threads; for (unsigned int i=0; i::residual (Vector &dst, somenumber *) const; const mem_fun_p comp_residual = &SparseMatrix:: template threaded_residual; - Threads::ThreadManager thread_manager; + Threads::ThreadGroup<> threads; for (unsigned int i=0; i - (n_rows * i / n_threads, - n_rows * (i+1) / n_threads), - &partial_norms[i])); + threads += Threads::spawn (*this, comp_residual)(dst, u, b, + std::pair + (n_rows * i / n_threads, + n_rows * (i+1) / n_threads), + &partial_norms[i]); // ... and wait until they're finished - thread_manager.wait (); + threads.join_all (); // accumulate the partial results return std::sqrt(std::accumulate (partial_norms.begin(), partial_norms.end(), diff --git a/deal.II/lac/include/lac/sparse_vanka.templates.h b/deal.II/lac/include/lac/sparse_vanka.templates.h index de3a063148..4f3831955e 100644 --- a/deal.II/lac/include/lac/sparse_vanka.templates.h +++ b/deal.II/lac/include/lac/sparse_vanka.templates.h @@ -112,16 +112,14 @@ SparseVanka::compute_inverses () typedef void (SparseVanka::*FunPtr)(const unsigned int, const unsigned int); - FunPtr fun_ptr = &SparseVanka::compute_inverses; + const FunPtr fun_ptr = &SparseVanka::compute_inverses; // Now spawn the threads - Threads::ThreadManager thread_manager; + Threads::ThreadGroup<> threads; for (unsigned int i=0; i::vmult (Vector &dst, const std::vector * const) const; const mem_fun_p comp = &SparseVanka::template apply_preconditioner; - Threads::ThreadManager thread_manager; + Threads::ThreadGroup<> threads; for (unsigned int block=0; block*>(this), comp) + (dst, src,&dof_masks[block]); + threads.join_all (); } else for (unsigned int block=0; block */ Threads::ThreadMutex lock; - /** - * Declare a thread manager that - * is used to spawn threads in - * @p{alert} detached. - * - * If not in MT mode, then the - * class used here is empty, and - * we can as well get away - * without it. - */ - static Threads::ThreadManager thread_manager; - /** * Flag by which the @p{alert} * function signifies that the diff --git a/deal.II/lac/include/lac/swappable_vector.templates.h b/deal.II/lac/include/lac/swappable_vector.templates.h index da9995a90d..a6f38266b2 100644 --- a/deal.II/lac/include/lac/swappable_vector.templates.h +++ b/deal.II/lac/include/lac/swappable_vector.templates.h @@ -20,13 +20,6 @@ - // allocate static variable -template -Threads::ThreadManager SwappableVector::thread_manager; - - - - template SwappableVector::SwappableVector () : @@ -172,10 +165,9 @@ void SwappableVector::alert () lock.release (); else // data has not been preloaded so - // far, so go on! - Threads::spawn (thread_manager, - Threads::encapsulate (&SwappableVector::reload_vector) - .collect_args(this, true)); + // far, so go on! For this, start + // a detached thread + Threads::spawn (*this, &SwappableVector::reload_vector)(true); // note that reload_vector also // releases the lock } diff --git a/tests/base/Makefile b/tests/base/Makefile index 643c0529da..2747de2d9a 100644 --- a/tests/base/Makefile +++ b/tests/base/Makefile @@ -20,6 +20,10 @@ default: run-tests ############################################################ +threads.cc : threads.pl + @echo =====regenerating== $@ + @$(PERL) $^ > $@ + logtest.exe : logtest.g.$(OBJEXT) $(lib-base.g) polynomial_test.exe: polynomial_test.g.$(OBJEXT) abort.g.$(OBJEXT) $(lib-base.g) polynomial1d.exe : polynomial1d.g.$(OBJEXT) $(lib-base.g) @@ -28,12 +32,14 @@ reference.exe : reference.g.$(OBJEXT) abort.g.$(OBJEXT) $(libraries) table.exe : table.g.$(OBJEXT) $(libraries) tensor.exe : tensor.g.$(OBJEXT) $(libraries) timer.exe : timer.g.$(OBJEXT) $(libraries) +threads.exe : threads.g.$(OBJEXT) $(libraries) auto_derivative_function.exe : auto_derivative_function.g.$(OBJEXT) $(libraries) tests = $(sort \ logtest reference quadrature_test table tensor \ - timer polynomial1d polynomial_test auto_derivative_function) + timer threads polynomial1d polynomial_test \ + auto_derivative_function) ############################################################ -- 2.39.5