]> https://gitweb.dealii.org/ - dealii-svn.git/commitdiff
Implement n_existing_threads.
authorwolf <wolf@0785d39b-7218-0410-832d-ea1e28bc413d>
Mon, 9 Sep 2002 14:38:16 +0000 (14:38 +0000)
committerwolf <wolf@0785d39b-7218-0410-832d-ea1e28bc413d>
Mon, 9 Sep 2002 14:38:16 +0000 (14:38 +0000)
git-svn-id: https://svn.dealii.org/trunk@6373 0785d39b-7218-0410-832d-ea1e28bc413d

deal.II/base/include/base/thread_management.h
deal.II/base/source/thread_management.cc
deal.II/doc/news/2002/c-3-4.html

index 8dc20c2fa76cabe4848dac4a4cd96dd65e45d942..3aa38635105097af701d1c1c896e5f3bb58fa7c6 100644 (file)
@@ -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;
   }
index dccdd02e3bbf1858f5e877fa6227f7b4ec25d622..e21374e29a7ac0f00aa85e3d2436599e1e12979d 100644 (file)
 
 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);
index 66d60425f0bd67a69e3b44cedeefb4524f906693..7801e6758c4723e6f3db231b00a866d5e6ddae46 100644 (file)
@@ -122,6 +122,15 @@ contributor's names are abbreviated by WB (Wolfgang Bangerth), GK
 <h3>base</h3>
 
 <ol>
+  <li> <p> 
+       New: The <code class="member">Threads::n_existing_threads</code>
+       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.
+       <br>
+       (WB 2002/09/08)
+       </p>
+
   <li> <p> 
        Extended: Previously, the <code class="class">Threads::PosixThreadBarrier</code>
        class could not be used at all (they threw exceptions), if your system

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.

Douglas Adams


Typeset in Trocchi and Trocchi Bold Sans Serif.