From: wolf Date: Mon, 9 Sep 2002 14:38:16 +0000 (+0000) Subject: Implement n_existing_threads. X-Git-Url: https://gitweb.dealii.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6c70daf02e988caaf72f9af3185d3e124d4dd0f1;p=dealii-svn.git Implement n_existing_threads. git-svn-id: https://svn.dealii.org/trunk@6373 0785d39b-7218-0410-832d-ea1e28bc413d --- diff --git a/deal.II/base/include/base/thread_management.h b/deal.II/base/include/base/thread_management.h index 8dc20c2fa7..3aa3863510 100644 --- a/deal.II/base/include/base/thread_management.h +++ b/deal.II/base/include/base/thread_management.h @@ -4566,6 +4566,56 @@ namespace Threads 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)} @@ -4662,6 +4712,29 @@ namespace Threads << "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 (); + }; // end declarations of namespace Threads @@ -4724,8 +4797,12 @@ namespace Threads // @p{fun_data} fun_data->lock.release (); - // call the function + // register new thread, call the + // function, and upon its return, + // de-register it again + register_new_thread (); (*fun_ptr)(); + deregister_new_thread (); return 0; } @@ -4802,8 +4879,12 @@ namespace Threads // @p{fun_data} fun_data->lock.release (); - // call the function + // register new thread, call the + // function, and upon its return, + // de-register it again + register_new_thread (); (*fun_ptr)(arg1); + deregister_new_thread (); return 0; } @@ -4884,8 +4965,12 @@ namespace Threads // @p{fun_data} fun_data->lock.release (); - // call the function + // register new thread, call the + // function, and upon its return, + // de-register it again + register_new_thread (); (*fun_ptr)(arg1, arg2); + deregister_new_thread (); return 0; } @@ -4972,9 +5057,13 @@ namespace Threads // @p{fun_data} fun_data->lock.release (); - // call the function + // register new thread, call the + // function, and upon its return, + // de-register it again + register_new_thread (); (*fun_ptr)(arg1, arg2, arg3); - + deregister_new_thread (); + return 0; } @@ -5065,8 +5154,12 @@ namespace Threads // @p{fun_data} fun_data->lock.release (); - // call the function + // register new thread, call the + // function, and upon its return, + // de-register it again + register_new_thread (); (*fun_ptr)(arg1, arg2, arg3, arg4); + deregister_new_thread (); return 0; } @@ -5163,8 +5256,12 @@ namespace Threads // @p{fun_data} fun_data->lock.release (); - // call the function + // register new thread, call the + // function, and upon its return, + // de-register it again + register_new_thread (); (*fun_ptr)(arg1, arg2, arg3, arg4, arg5); + deregister_new_thread (); return 0; } @@ -5267,8 +5364,12 @@ namespace Threads // @p{fun_data} fun_data->lock.release (); - // call the function + // register new thread, call the + // function, and upon its return, + // de-register it again + register_new_thread (); (*fun_ptr)(arg1, arg2, arg3, arg4, arg5, arg6); + deregister_new_thread (); return 0; } @@ -5377,8 +5478,12 @@ namespace Threads // @p{fun_data} fun_data->lock.release (); - // call the function + // register new thread, call the + // function, and upon its return, + // de-register it again + register_new_thread (); (*fun_ptr)(arg1, arg2, arg3, arg4, arg5, arg6, arg7); + deregister_new_thread (); return 0; } @@ -5494,8 +5599,12 @@ namespace Threads // @p{fun_data} fun_data->lock.release (); - // call the function + // register new thread, call the + // function, and upon its return, + // de-register it again + register_new_thread (); (*fun_ptr)(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); + deregister_new_thread (); return 0; } @@ -5615,8 +5724,12 @@ namespace Threads // @p{fun_data} fun_data->lock.release (); - // call the function + // register new thread, call the + // function, and upon its return, + // de-register it again + register_new_thread (); (*fun_ptr)(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); + deregister_new_thread (); return 0; } @@ -5744,8 +5857,12 @@ namespace Threads // @p{fun_data} fun_data->lock.release (); - // call the function + // register new thread, call the + // function, and upon its return, + // de-register it again + register_new_thread (); (*fun_ptr)(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); + deregister_new_thread (); return 0; } @@ -5837,8 +5954,12 @@ namespace Threads // @p{fun_data} fun_data->lock.release (); - // call the function + // register new thread, call the + // function, and upon its return, + // de-register it again + register_new_thread (); (object->*fun_ptr)(); + deregister_new_thread (); return 0; } @@ -5929,8 +6050,12 @@ namespace Threads // @p{fun_data} fun_data->lock.release (); - // call the function + // register new thread, call the + // function, and upon its return, + // de-register it again + register_new_thread (); (object->*fun_ptr)(arg1); + deregister_new_thread (); return 0; } @@ -6025,8 +6150,12 @@ namespace Threads // @p{fun_data} fun_data->lock.release (); - // call the function + // register new thread, call the + // function, and upon its return, + // de-register it again + register_new_thread (); (object->*fun_ptr)(arg1, arg2); + deregister_new_thread (); return 0; } @@ -6129,8 +6258,12 @@ namespace Threads // @p{fun_data} fun_data->lock.release (); - // call the function + // register new thread, call the + // function, and upon its return, + // de-register it again + register_new_thread (); (object->*fun_ptr)(arg1, arg2, arg3); + deregister_new_thread (); return 0; } @@ -6240,8 +6373,12 @@ namespace Threads // @p{fun_data} fun_data->lock.release (); - // call the function + // register new thread, call the + // function, and upon its return, + // de-register it again + register_new_thread (); (object->*fun_ptr)(arg1, arg2, arg3, arg4); + deregister_new_thread (); return 0; } @@ -6356,8 +6493,12 @@ namespace Threads // @p{fun_data} fun_data->lock.release (); - // call the function + // register new thread, call the + // function, and upon its return, + // de-register it again + register_new_thread (); (object->*fun_ptr)(arg1, arg2, arg3, arg4, arg5); + deregister_new_thread (); return 0; } @@ -6479,8 +6620,12 @@ namespace Threads // @p{fun_data} fun_data->lock.release (); - // call the function + // register new thread, call the + // function, and upon its return, + // de-register it again + register_new_thread (); (object->*fun_ptr)(arg1, arg2, arg3, arg4, arg5, arg6); + deregister_new_thread (); return 0; } @@ -6610,8 +6755,12 @@ namespace Threads // @p{fun_data} fun_data->lock.release (); - // call the function + // register new thread, call the + // function, and upon its return, + // de-register it again + register_new_thread (); (object->*fun_ptr)(arg1, arg2, arg3, arg4, arg5, arg6, arg7); + deregister_new_thread (); return 0; } @@ -6744,8 +6893,12 @@ namespace Threads // @p{fun_data} fun_data->lock.release (); - // call the function + // register new thread, call the + // function, and upon its return, + // de-register it again + register_new_thread (); (object->*fun_ptr)(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); + deregister_new_thread (); return 0; } @@ -6884,8 +7037,12 @@ namespace Threads // @p{fun_data} fun_data->lock.release (); - // call the function + // register new thread, call the + // function, and upon its return, + // de-register it again + register_new_thread (); (object->*fun_ptr)(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); + deregister_new_thread (); return 0; } @@ -7030,8 +7187,12 @@ namespace Threads // @p{fun_data} fun_data->lock.release (); - // call the function + // register new thread, call the + // function, and upon its return, + // de-register it again + register_new_thread (); (object->*fun_ptr)(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); + deregister_new_thread (); return 0; } diff --git a/deal.II/base/source/thread_management.cc b/deal.II/base/source/thread_management.cc index dccdd02e3b..e21374e29a 100644 --- a/deal.II/base/source/thread_management.cc +++ b/deal.II/base/source/thread_management.cc @@ -20,6 +20,41 @@ 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 () + { + n_existing_threads_mutex.acquire (); + ++n_existing_threads_counter; + n_existing_threads_mutex.release (); + }; + + + + void deregister_new_thread () + { + n_existing_threads_mutex.acquire (); + --n_existing_threads_counter; + Assert (n_existing_threads_counter >= 1, + ExcInternalError()); + n_existing_threads_mutex.release (); + }; + + + + unsigned int n_existing_threads () + { + n_existing_threads_mutex.acquire (); + const unsigned int n = n_existing_threads_counter; + n_existing_threads_mutex.release (); + return n; + }; + + #ifndef DEAL_II_USE_MT void DummyThreadManager::spawn (const FunPtr fun_ptr, void * fun_data, @@ -54,7 +89,7 @@ namespace Threads }; -#ifndef DEAL_II_USE_MT_POSIX_NO_BARRIERS +#ifdef DEAL_II_USE_MT_POSIX_NO_BARRIERS PosixThreadBarrier::PosixThreadBarrier (const unsigned int count, const char *, void *) @@ -148,6 +183,7 @@ namespace Threads tid_list.push_back (pthread_t()); + // start new thread const int error = pthread_create (&tid_list.back(), 0, fun_ptr, fun_data); @@ -308,8 +344,19 @@ namespace Threads thread_manager.spawn (*fun_data.fun_data_base->thread_entry_point, (void*)&fun_data, 0); -# endif +# endif + + // if truly in MT mode, increase + // thread number counter + ++n_existing_thread_counter; + #else + // if not in MT mode, then simply + // call the respective + // serializing function, that + // executes the given function + // and return. don't have to + // adjust the number of threads thread_manager.spawn (*fun_data.fun_data_base->thread_entry_point, (void*)&fun_data, 0); diff --git a/deal.II/doc/news/2002/c-3-4.html b/deal.II/doc/news/2002/c-3-4.html index 66d60425f0..7801e6758c 100644 --- a/deal.II/doc/news/2002/c-3-4.html +++ b/deal.II/doc/news/2002/c-3-4.html @@ -122,6 +122,15 @@ contributor's names are abbreviated by WB (Wolfgang Bangerth), GK

base

    +
  1. + New: The Threads::n_existing_threads + function returns the present number of existing threads, allowing an + assessment whether it is useful to spawn new threads or rather perform + the operation in question sequentially. +
    + (WB 2002/09/08) +

    +
  2. Extended: Previously, the Threads::PosixThreadBarrier class could not be used at all (they threw exceptions), if your system