Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

Thread_Manager.cpp

Go to the documentation of this file.
00001 #include "ace_pch.h"
00002 // $Id: Thread_Manager.cpp,v 1.1.1.4.2.1 2003/03/13 19:44:22 chad Exp $
00003 
00004 #include "ace/Synch_T.h"
00005 #include "ace/Thread_Manager.h"
00006 #include "ace/Dynamic.h"
00007 #include "ace/Object_Manager.h"
00008 #include "ace/Singleton.h"
00009 #include "ace/Auto_Ptr.h"
00010 
00011 #if !defined (__ACE_INLINE__)
00012 #include "ace/Thread_Manager.i"
00013 #endif /* __ACE_INLINE__ */
00014 
00015 ACE_RCSID(ace, Thread_Manager, "$Id: Thread_Manager.cpp,v 1.1.1.4.2.1 2003/03/13 19:44:22 chad Exp $")
00016 
00017 ACE_ALLOC_HOOK_DEFINE(ACE_Thread_Control)
00018 ACE_ALLOC_HOOK_DEFINE(ACE_Thread_Manager)
00019 
00020 #if ! defined (ACE_THREAD_MANAGER_LACKS_STATICS)
00021 // Process-wide Thread Manager.
00022 ACE_Thread_Manager *ACE_Thread_Manager::thr_mgr_ = 0;
00023 
00024 // Controls whether the Thread_Manager is deleted when we shut down
00025 // (we can only delete it safely if we created it!)
00026 int ACE_Thread_Manager::delete_thr_mgr_ = 0;
00027 #endif /* ! defined (ACE_THREAD_MANAGER_LACKS_STATICS) */
00028 
00029 ACE_TSS_TYPE (ACE_Thread_Exit) *ACE_Thread_Manager::thr_exit_ = 0;
00030 
00031 int
00032 ACE_Thread_Manager::set_thr_exit (ACE_TSS_TYPE (ACE_Thread_Exit) *ptr)
00033 {
00034   if (ACE_Thread_Manager::thr_exit_ == 0)
00035     ACE_Thread_Manager::thr_exit_ = ptr;
00036   else
00037     return -1;
00038   return 0;
00039 }
00040 
00041 void
00042 ACE_Thread_Manager::dump (void)
00043 {
00044   ACE_TRACE ("ACE_Thread_Manager::dump");
00045   // Cast away const-ness of this in order to use its non-const lock_.
00046   ACE_MT (ACE_GUARD (ACE_Thread_Mutex, ace_mon,
00047                      ((ACE_Thread_Manager *) this)->lock_));
00048 
00049   ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
00050 
00051   ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\ngrp_id_ = %d"), this->grp_id_));
00052   ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\ncurrent_count_ = %d"), this->thr_list_.size ()));
00053 
00054   for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
00055        !iter.done ();
00056        iter.advance ())
00057     iter.next ()->dump ();
00058 
00059   ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
00060 }
00061 
00062 ACE_Thread_Descriptor::~ACE_Thread_Descriptor (void)
00063 {
00064   delete this->sync_;
00065 }
00066 
00067 #if !defined(ACE_USE_ONE_SHOT_AT_THREAD_EXIT)
00068 void ACE_Thread_Descriptor::at_pop (int apply)
00069 
00070 {
00071   ACE_TRACE ("ACE_Thread_Descriptor::at_pop");
00072   // Get first at from at_exit_list
00073   ACE_At_Thread_Exit* at = this->at_exit_list_;
00074   // Remove at from at_exit list
00075   this->at_exit_list_ = at->next_;
00076   // Apply if required
00077   if (apply)
00078    {
00079      at->apply ();
00080      // Do the apply method
00081      at->was_applied (1);
00082      // Mark at has been applied to avoid double apply from
00083      // at destructor
00084    }
00085   // If at is not owner delete at.
00086   if (!at->is_owner ())
00087    delete at;
00088 }
00089 
00090 void
00091 ACE_Thread_Descriptor::at_push (ACE_At_Thread_Exit* cleanup, int is_owner)
00092 
00093 {
00094   ACE_TRACE ("ACE_Thread_Descriptor::at_push");
00095   cleanup->is_owner (is_owner);
00096   cleanup->td_ = this;
00097   cleanup->next_ = at_exit_list_;
00098   at_exit_list_ = cleanup;
00099 }
00100 
00101 int
00102 ACE_Thread_Descriptor::at_exit (ACE_At_Thread_Exit& cleanup)
00103 
00104 {
00105   ACE_TRACE ("ACE_Thread_Descriptor::at_exit");
00106   at_push (&cleanup, 1);
00107   return 0;
00108 }
00109 
00110 int
00111 ACE_Thread_Descriptor::at_exit (ACE_At_Thread_Exit* cleanup)
00112 
00113 {
00114   ACE_TRACE ("ACE_Thread_Descriptor::at_exit");
00115   if (cleanup==0)
00116    return -1;
00117   else
00118    {
00119      this->at_push (cleanup);
00120      return 0;
00121    }
00122 }
00123 
00124 void
00125 ACE_Thread_Descriptor::do_at_exit ()
00126 
00127 {
00128   ACE_TRACE ("ACE_Thread_Descriptor::do_at_exit");
00129   while (at_exit_list_!=0)
00130     this->at_pop ();
00131 }
00132 
00133 void
00134 ACE_Thread_Descriptor::terminate ()
00135 
00136 {
00137   ACE_TRACE ("ACE_Thread_Descriptor::terminate");
00138 
00139   if (!terminated_)
00140    {
00141      ACE_Log_Msg* log_msg = this->log_msg_;
00142      terminated_ = 1;
00143      // Run at_exit hooks
00144      this->do_at_exit ();
00145      // We must remove Thread_Descriptor from Thread_Manager list
00146      if (this->tm_ != 0)
00147       {
00148          int close_handle = 0;
00149 
00150 #if !defined (VXWORKS)
00151          // Threads created with THR_DAEMON shouldn't exist here, but
00152          // just to be safe, let's put it here.
00153 
00154          if (ACE_BIT_DISABLED (this->thr_state_, ACE_Thread_Manager::ACE_THR_JOINING))
00155            {
00156              if (ACE_BIT_DISABLED (this->flags_, THR_DETACHED | THR_DAEMON)
00157                  || ACE_BIT_ENABLED (this->flags_, THR_JOINABLE))
00158                {
00159                  // Mark thread as terminated.
00160                  ACE_SET_BITS (this->thr_state_, ACE_Thread_Manager::ACE_THR_TERMINATED);
00161                  tm_->register_as_terminated (this);
00162                  // Must copy the information here because td will be
00163                  // "freed" below.
00164                }
00165 #if defined (ACE_WIN32)
00166              else
00167                {
00168                  close_handle = 1;
00169                }
00170 #endif /* ACE_WIN32 */
00171            }
00172 #endif /* ! VXWORKS */
00173 
00174          // Remove thread descriptor from the table.
00175          if (this->tm_ != 0)
00176            tm_->remove_thr (this, close_handle);
00177       }
00178 
00179      // Check if we need delete ACE_Log_Msg instance
00180      // If ACE_TSS_cleanup was not executed first log_msg == 0
00181      if (log_msg == 0)
00182       {
00183         // Only inform to ACE_TSS_cleanup that it must delete the log instance
00184         // setting ACE_LOG_MSG thr_desc to 0.
00185         ACE_LOG_MSG->thr_desc (0);
00186       }
00187      else
00188       {
00189         // Thread_Descriptor is the owner of the Log_Msg instance!!
00190         // deleted.
00191         this->log_msg_ = 0;
00192         delete log_msg;
00193       }
00194    }
00195 }
00196 
00197 #endif /* !ACE_USE_ONE_SHOT_AT_THREAD_EXIT */
00198 
00199 int
00200 ACE_Thread_Descriptor::at_exit (void *object,
00201                                 ACE_CLEANUP_FUNC cleanup_hook,
00202                                 void *param)
00203 {
00204   ACE_TRACE ("ACE_Thread_Descriptor::at_exit");
00205 #if defined(ACE_USE_ONE_SHOT_AT_THREAD_EXIT)
00206   this->cleanup_info_.cleanup_hook_ = cleanup_hook;
00207   this->cleanup_info_.object_ = object;
00208   this->cleanup_info_.param_ = param;
00209 #else
00210   // To keep compatibility, when cleanup_hook is null really is a at_pop
00211   // without apply.
00212   if (cleanup_hook == 0)
00213    {
00214      if (this->at_exit_list_!= 0)
00215       this->at_pop(0);
00216    }
00217   else
00218    {
00219      ACE_At_Thread_Exit* cleanup;
00220      ACE_NEW_RETURN (cleanup,
00221                      ACE_At_Thread_Exit_Func (object,
00222                                               cleanup_hook,
00223                                               param),
00224                      -1);
00225      this->at_push (cleanup);
00226    }
00227 #endif /* ACE_USE_ONE_SHOT_AT_THREAD_EXIT */
00228   return 0;
00229 }
00230 
00231 void
00232 ACE_Thread_Descriptor::dump (void) const
00233 {
00234   ACE_TRACE ("ACE_Thread_Descriptor::dump");
00235   ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
00236 
00237   ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nthr_id_ = %d"), this->thr_id_));
00238   ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nthr_handle_ = %d"), this->thr_handle_));
00239   ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\ngrp_id_ = %d"), this->grp_id_));
00240   ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nthr_state_ = %d"), this->thr_state_));
00241   ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\ncleanup_info_.cleanup_hook_ = %x"), this->cleanup_info_.cleanup_hook_));
00242   ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nflags_ = %x\n"), this->flags_));
00243 
00244   ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
00245 }
00246 
00247 ACE_Thread_Descriptor::ACE_Thread_Descriptor (void)
00248 #if !defined (ACE_USE_ONE_SHOT_AT_THREAD_EXIT)
00249   : log_msg_ (0),
00250     at_exit_list_ (0),
00251     terminated_ (0)
00252 #endif /* !ACE_USE_ONE_SHOT_AT_THREAD_EXIT */
00253 {
00254   ACE_TRACE ("ACE_Thread_Descriptor::ACE_Thread_Descriptor");
00255   ACE_NEW (this->sync_,
00256            ACE_DEFAULT_THREAD_MANAGER_LOCK);
00257 }
00258 
00259 void
00260 ACE_Thread_Descriptor::acquire_release (void)
00261 {
00262   // Just try to acquire the lock then release it.
00263 #if defined (ACE_THREAD_MANAGER_USES_SAFE_SPAWN)
00264   if (ACE_BIT_DISABLED (this->thr_state_, ACE_Thread_Manager::ACE_THR_SPAWNED))
00265 #endif /* ACE_THREAD_MANAGER_USES_SAFE_SPAWN */
00266     {
00267       this->sync_->acquire ();
00268       // Acquire the lock before removing <td> from the thread table.  If
00269       // this thread is in the table already, it should simply acquire the
00270       // lock easily.
00271 
00272       // Once we get the lock, we must have registered.
00273       ACE_ASSERT (ACE_BIT_ENABLED (this->thr_state_, ACE_Thread_Manager::ACE_THR_SPAWNED));
00274 
00275       this->sync_->release ();
00276       // Release the lock before putting it back to freelist.
00277     }
00278 }
00279 
00280 // The following macro simplifies subsequence code.
00281 #define ACE_FIND(OP,INDEX) \
00282   ACE_Thread_Descriptor *INDEX = OP; \
00283 
00284 ACE_Thread_Descriptor *
00285 ACE_Thread_Manager::thread_descriptor (ACE_thread_t thr_id)
00286 {
00287   ACE_TRACE ("ACE_Thread_Manager::thread_descriptor");
00288   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0));
00289 
00290   ACE_FIND (this->find_thread (thr_id), ptr);
00291   return ptr;
00292 }
00293 
00294 ACE_Thread_Descriptor *
00295 ACE_Thread_Manager::hthread_descriptor (ACE_hthread_t thr_handle)
00296 {
00297   ACE_TRACE ("ACE_Thread_Manager::hthread_descriptor");
00298   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0));
00299 
00300   ACE_FIND (this->find_hthread (thr_handle), ptr);
00301   return ptr;
00302 }
00303 
00304 // Return the thread descriptor (indexed by ACE_hthread_t).
00305 
00306 int
00307 ACE_Thread_Manager::thr_self (ACE_hthread_t &self)
00308 {
00309   ACE_TRACE ("ACE_Thread_Manager::thr_self");
00310 
00311   ACE_Thread_Descriptor *desc =
00312     this->thread_desc_self ();
00313 
00314   if (desc == 0)
00315     return -1;
00316   else
00317     desc->self (self);
00318 
00319   return 0;
00320 }
00321 
00322 // Initialize the synchronization variables.
00323 
00324 ACE_Thread_Manager::ACE_Thread_Manager (size_t prealloc,
00325                                         size_t lwm,
00326                                         size_t inc,
00327                                         size_t hwm)
00328   : grp_id_ (1),
00329     automatic_wait_ (1)
00330 #if defined (ACE_HAS_THREADS)
00331     , zero_cond_ (lock_)
00332 #endif /* ACE_HAS_THREADS */
00333     , thread_desc_freelist_ (ACE_FREE_LIST_WITH_POOL,
00334                              prealloc, lwm, hwm, inc)
00335 {
00336   ACE_TRACE ("ACE_Thread_Manager::ACE_Thread_Manager");
00337 }
00338 
00339 #if ! defined (ACE_THREAD_MANAGER_LACKS_STATICS)
00340 ACE_Thread_Manager *
00341 ACE_Thread_Manager::instance (void)
00342 {
00343   ACE_TRACE ("ACE_Thread_Manager::instance");
00344 
00345   if (ACE_Thread_Manager::thr_mgr_ == 0)
00346     {
00347       // Perform Double-Checked Locking Optimization.
00348       ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
00349                                 *ACE_Static_Object_Lock::instance (), 0));
00350 
00351       if (ACE_Thread_Manager::thr_mgr_ == 0)
00352         {
00353           ACE_NEW_RETURN (ACE_Thread_Manager::thr_mgr_,
00354                           ACE_Thread_Manager,
00355                           0);
00356           ACE_Thread_Manager::delete_thr_mgr_ = 1;
00357         }
00358     }
00359 
00360   return ACE_Thread_Manager::thr_mgr_;
00361 }
00362 
00363 ACE_Thread_Manager *
00364 ACE_Thread_Manager::instance (ACE_Thread_Manager *tm)
00365 {
00366   ACE_TRACE ("ACE_Thread_Manager::instance");
00367   ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
00368                             *ACE_Static_Object_Lock::instance (), 0));
00369 
00370   ACE_Thread_Manager *t = ACE_Thread_Manager::thr_mgr_;
00371   // We can't safely delete it since we don't know who created it!
00372   ACE_Thread_Manager::delete_thr_mgr_ = 0;
00373 
00374   ACE_Thread_Manager::thr_mgr_ = tm;
00375   return t;
00376 }
00377 
00378 void
00379 ACE_Thread_Manager::close_singleton (void)
00380 {
00381   ACE_TRACE ("ACE_Thread_Manager::close_singleton");
00382 
00383   ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex, ace_mon,
00384                      *ACE_Static_Object_Lock::instance ()));
00385 
00386   if (ACE_Thread_Manager::delete_thr_mgr_)
00387     {
00388       // First, we clean up the thread descriptor list.
00389       ACE_Thread_Manager::thr_mgr_->close ();
00390       delete ACE_Thread_Manager::thr_mgr_;
00391       ACE_Thread_Manager::thr_mgr_ = 0;
00392       ACE_Thread_Manager::delete_thr_mgr_ = 0;
00393     }
00394 
00395   ACE_Thread_Exit::cleanup (ACE_Thread_Manager::thr_exit_);
00396 }
00397 #endif /* ! defined (ACE_THREAD_MANAGER_LACKS_STATICS) */
00398 
00399 // Close up and release all resources.
00400 
00401 int
00402 ACE_Thread_Manager::close ()
00403 {
00404   ACE_TRACE ("ACE_Thread_Manager::close");
00405 
00406   // Clean up the thread descriptor list.
00407   if (this->automatic_wait_)
00408     this->wait (0, 1);
00409   else
00410     {
00411       ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
00412 
00413       this->remove_thr_all ();
00414     }
00415 
00416   return 0;
00417 }
00418 
00419 ACE_Thread_Manager::~ACE_Thread_Manager (void)
00420 {
00421   ACE_TRACE ("ACE_Thread_Manager::~ACE_Thread_Manager");
00422   this->close ();
00423 }
00424 
00425 
00426 // Run the entry point for thread spawned under the control of the
00427 // <ACE_Thread_Manager>.  This must be an extern "C" to make certain
00428 // compilers happy...
00429 //
00430 // The interaction with <ACE_Thread_Exit> and
00431 // <ace_thread_manager_adapter> works like this, with
00432 // ACE_HAS_THREAD_SPECIFIC_STORAGE or ACE_HAS_TSS_EMULATION:
00433 //
00434 // o Every thread in the <ACE_Thread_Manager> is run with
00435 //   <ace_thread_manager_adapter>.
00436 //
00437 // o <ace_thread_manager_adapter> retrieves the singleton
00438 //   <ACE_Thread_Exit> instance from <ACE_Thread_Exit::instance>.
00439 //   The singleton gets created in thread-specific storage
00440 //   in the first call to that function.  The key point is that the
00441 //   instance is in thread-specific storage.
00442 //
00443 // o A thread can exit by various means, such as <ACE_Thread::exit>, C++
00444 //   or Win32 exception, "falling off the end" of the thread entry
00445 //   point function, etc.
00446 //
00447 // o If you follow this so far, now it gets really fun . . .
00448 //   When the thread-specific storage (for the thread that
00449 //   is being destroyed) is cleaned up, the OS threads package (or
00450 //   the ACE emulation of thread-specific storage) will destroy any
00451 //   objects that are in thread-specific storage.  It has a list of
00452 //   them, and just walks down the list and destroys each one.
00453 //
00454 // o That's where the ACE_Thread_Exit destructor gets called.
00455 
00456 #if defined(ACE_USE_THREAD_MANAGER_ADAPTER)
00457 extern "C" void *
00458 ace_thread_manager_adapter (void *args)
00459 {
00460 #if defined (ACE_HAS_TSS_EMULATION)
00461   // As early as we can in the execution of the new thread, allocate
00462   // its local TS storage.  Allocate it on the stack, to save dynamic
00463   // allocation/dealloction.
00464   void *ts_storage[ACE_TSS_Emulation::ACE_TSS_THREAD_KEYS_MAX];
00465   ACE_TSS_Emulation::tss_open (ts_storage);
00466 #endif /* ACE_HAS_TSS_EMULATION */
00467 
00468   ACE_Thread_Adapter *thread_args = (ACE_Thread_Adapter *) args;
00469 
00470   // NOTE: this preprocessor directive should match the one in above
00471   // ACE_Thread_Exit::instance ().  With the Xavier Pthreads package,
00472   // the exit_hook in TSS causes a seg fault.  So, this works around
00473   // that by creating exit_hook on the stack.
00474 #if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION)
00475   // Obtain our thread-specific exit hook and make sure that it knows
00476   // how to clean us up!  Note that we never use this pointer directly
00477   // (it's stored in thread-specific storage), so it's ok to
00478   // dereference it here and only store it as a reference.
00479   ACE_Thread_Exit &exit_hook = *ACE_Thread_Exit::instance ();
00480 #else
00481   // Without TSS, create an <ACE_Thread_Exit> instance.  When this
00482   // function returns, its destructor will be called because the
00483   // object goes out of scope.  The drawback with this appraoch is
00484   // that the destructor _won't_ get called if <thr_exit> is called.
00485   // So, threads shouldn't exit that way.  Instead, they should return
00486   // from <svc>.
00487   ACE_Thread_Exit exit_hook;
00488 #endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE || ACE_HAS_TSS_EMULATION */
00489 
00490   // Keep track of the <Thread_Manager> that's associated with this
00491   // <exit_hook>.
00492   exit_hook.thr_mgr (thread_args->thr_mgr ());
00493 
00494   // Invoke the user-supplied function with the args.
00495   void *status = thread_args->invoke ();
00496 
00497   return status;
00498 }
00499 #endif
00500 
00501 // Call the appropriate OS routine to spawn a thread.  Should *not* be
00502 // called with the lock_ held...
00503 
00504 int
00505 ACE_Thread_Manager::spawn_i (ACE_THR_FUNC func,
00506                              void *args,
00507                              long flags,
00508                              ACE_thread_t *t_id,
00509                              ACE_hthread_t *t_handle,
00510                              long priority,
00511                              int grp_id,
00512                              void *stack,
00513                              size_t stack_size,
00514                              ACE_Task_Base *task)
00515 {
00516   // First, threads created by Thread Manager should not be daemon threads.
00517   // Using assertion is probably a bit too strong.  However, it helps
00518   // finding this kind of error as early as possible.  Perhaps we can replace
00519   // assertion by returning error.
00520   ACE_ASSERT (ACE_BIT_DISABLED (flags, THR_DAEMON));
00521 
00522   // Create a new thread running <func>.  *Must* be called with the
00523   // <lock_> held...
00524   // Get a "new" Thread Descriptor from the freelist.
00525   auto_ptr<ACE_Thread_Descriptor> new_thr_desc (this->thread_desc_freelist_.remove ());
00526 
00527   // Reset thread descriptor status
00528   new_thr_desc->reset (this);
00529 
00530   ACE_Thread_Adapter *thread_args = 0;
00531 # if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS)
00532   ACE_NEW_RETURN (thread_args,
00533                   ACE_Thread_Adapter (func,
00534                                       args,
00535                                       (ACE_THR_C_FUNC) ace_thread_adapter,
00536                                       this,
00537                                       new_thr_desc.get (),
00538                                       ACE_OS_Object_Manager::seh_except_selector(),
00539                                       ACE_OS_Object_Manager::seh_except_handler()),
00540                   -1);
00541 #else
00542   ACE_NEW_RETURN (thread_args,
00543                   ACE_Thread_Adapter (func,
00544                                       args,
00545                                       (ACE_THR_C_FUNC) ace_thread_adapter,
00546                                       this,
00547                                       new_thr_desc.get ()),
00548                   -1);
00549 # endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */
00550 
00551   ACE_TRACE ("ACE_Thread_Manager::spawn_i");
00552   ACE_hthread_t thr_handle;
00553 
00554 #if defined (VXWORKS)
00555   // On VxWorks, ACE_thread_t is char *.  If t_id is 0, allocate space
00556   // for ACE_OS::thr_create () to store the task name.  If t_id is not
00557   // 0, and it doesn't point to a 0 char *, then the non-zero char *
00558   // will be used for the task name in ACE_OS::thr_create ().  If t_id
00559   // is not 0, but does point to a 0 char *, the t_id will be set to
00560   // point to the task name in the TCB in ACE_OS::thr_create ().
00561   if (t_id == 0)
00562     {
00563       char *thr_id;
00564       ACE_NEW_RETURN (thr_id,
00565                       char[16],
00566                       -1);
00567       // Mark the thread ID to show that the ACE_Thread_Manager
00568       // allocated it.
00569       thr_id[0] = ACE_THR_ID_ALLOCATED;
00570       thr_id[1] = '\0';
00571       t_id = &thr_id;
00572     }
00573 #else  /* ! VXWORKS */
00574   ACE_thread_t thr_id;
00575   if (t_id == 0)
00576     t_id = &thr_id;
00577 #endif /* ! VXWORKS */
00578 
00579   new_thr_desc->sync_->acquire ();
00580   // Acquire the <sync_> lock to block the spawned thread from
00581   // removing this Thread Descriptor before it gets put into our
00582   // thread table.
00583 
00584   int result = ACE_Thread::spawn (func,
00585                                   args,
00586                                   flags,
00587                                   t_id,
00588                                   &thr_handle,
00589                                   priority,
00590                                   stack,
00591                                   stack_size,
00592                                   thread_args);
00593 
00594   if (result != 0)
00595     {
00596       // _Don't_ clobber errno here!  result is either 0 or -1, and
00597       // ACE_OS::thr_create () already set errno!  D. Levine 28 Mar 1997
00598       // errno = result;
00599       ACE_Errno_Guard guard (errno);     // Lock release may smash errno
00600       new_thr_desc->sync_->release ();
00601       return -1;
00602     }
00603   else
00604     {
00605 #if defined (ACE_HAS_WTHREADS)
00606       // Have to duplicate handle if client asks for it.
00607       // @@ How are thread handles implemented on AIX?  Do they
00608       // also need to be duplicated?
00609       if (t_handle != 0)
00610 # if defined (ACE_HAS_WINCE)
00611         *t_handle = thr_handle;
00612 # else  /* ! ACE_HAS_WINCE */
00613         (void) ::DuplicateHandle (::GetCurrentProcess (),
00614                                   thr_handle,
00615                                   ::GetCurrentProcess (),
00616                                   t_handle,
00617                                   0,
00618                                   TRUE,
00619                                   DUPLICATE_SAME_ACCESS);
00620 # endif /* ! ACE_HAS_WINCE */
00621 #elif defined (VXWORKS)
00622      if (t_handle != 0)
00623        *t_handle = thr_handle;
00624 #else  /* ! ACE_HAS_WTHREADS && ! VXWORKS */
00625       ACE_UNUSED_ARG (t_handle);
00626 #endif /* ! ACE_HAS_WTHREADS && ! VXWORKS */
00627 
00628       // append_thr also put the <new_thr_desc> into Thread_Manager's
00629       // double-linked list.  Only after this point, can we manipulate
00630       // double-linked list from a spawned thread's context.
00631       return this->append_thr (*t_id,
00632                                thr_handle,
00633                                ACE_THR_SPAWNED,
00634                                grp_id,
00635                                task,
00636                                flags,
00637                                new_thr_desc.release ());
00638     }
00639 }
00640 
00641 int
00642 ACE_Thread_Manager::spawn (ACE_THR_FUNC func,
00643                            void *args,
00644                            long flags,
00645                            ACE_thread_t *t_id,
00646                            ACE_hthread_t *t_handle,
00647                            long priority,
00648                            int grp_id,
00649                            void *stack,
00650                            size_t stack_size)
00651 {
00652   ACE_TRACE ("ACE_Thread_Manager::spawn");
00653 
00654   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
00655 
00656   if (grp_id == -1)
00657     grp_id = this->grp_id_++; // Increment the group id.
00658 
00659   if (this->spawn_i (func, args, flags, t_id, t_handle,
00660                      priority, grp_id, stack, stack_size) == -1)
00661     return -1;
00662 
00663   return grp_id;
00664 }
00665 
00666 // Create N new threads running FUNC.
00667 
00668 int
00669 ACE_Thread_Manager::spawn_n (size_t n,
00670                              ACE_THR_FUNC func,
00671                              void *args,
00672                              long flags,
00673                              long priority,
00674                              int grp_id,
00675                              ACE_Task_Base *task,
00676                              ACE_hthread_t thread_handles[],
00677                              void *stack[],
00678                              size_t stack_size[])
00679 {
00680   ACE_TRACE ("ACE_Thread_Manager::spawn_n");
00681   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
00682 
00683   if (grp_id == -1)
00684     grp_id = this->grp_id_++; // Increment the group id.
00685 
00686   for (size_t i = 0; i < n; i++)
00687     {
00688       // @@ What should happen if this fails?! e.g., should we try to
00689       // cancel the other threads that we've already spawned or what?
00690       if (this->spawn_i (func,
00691                          args,
00692                          flags,
00693                          0,
00694                          thread_handles == 0 ? 0 : &thread_handles[i],
00695                          priority,
00696                          grp_id,
00697                          stack == 0 ? 0 : stack[i],
00698                          stack_size == 0 ? 0 : stack_size[i],
00699                          task) == -1)
00700         return -1;
00701     }
00702 
00703   return grp_id;
00704 }
00705 
00706 // Create N new threads running FUNC.
00707 
00708 int
00709 ACE_Thread_Manager::spawn_n (ACE_thread_t thread_ids[],
00710                              size_t n,
00711                              ACE_THR_FUNC func,
00712                              void *args,
00713                              long flags,
00714                              long priority,
00715                              int grp_id,
00716                              void *stack[],
00717                              size_t stack_size[],
00718                              ACE_hthread_t thread_handles[],
00719                              ACE_Task_Base *task)
00720 {
00721   ACE_TRACE ("ACE_Thread_Manager::spawn_n");
00722   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
00723 
00724   if (grp_id == -1)
00725     grp_id = this->grp_id_++; // Increment the group id.
00726 
00727   for (size_t i = 0; i < n; i++)
00728     {
00729       // @@ What should happen if this fails?! e.g., should we try to
00730       // cancel the other threads that we've already spawned or what?
00731       if (this->spawn_i (func,
00732                          args,
00733                          flags,
00734                          thread_ids == 0 ? 0 : &thread_ids[i],
00735                          thread_handles == 0 ? 0 : &thread_handles[i],
00736                          priority,
00737                          grp_id,
00738                          stack == 0 ? 0 : stack[i],
00739                          stack_size == 0 ? 0 : stack_size[i],
00740                          task) == -1)
00741         return -1;
00742     }
00743 
00744   return grp_id;
00745 }
00746 
00747 // Append a thread into the pool (does not check for duplicates).
00748 // Must be called with locks held.
00749 
00750 int
00751 ACE_Thread_Manager::append_thr (ACE_thread_t t_id,
00752                                 ACE_hthread_t t_handle,
00753                                 ACE_UINT32 thr_state,
00754                                 int grp_id,
00755                                 ACE_Task_Base *task,
00756                                 long flags,
00757                                 ACE_Thread_Descriptor *td)
00758 {
00759   ACE_TRACE ("ACE_Thread_Manager::append_thr");
00760   ACE_Thread_Descriptor *thr_desc;
00761 
00762   if (td == 0)
00763     {
00764     ACE_NEW_RETURN (thr_desc,
00765                     ACE_Thread_Descriptor,
00766                     -1);
00767 #if !defined(ACE_USE_ONE_SHOT_AT_THREAD_EXIT)
00768     thr_desc->tm_ = this;
00769     // Setup the Thread_Manager.
00770 #endif /* !ACE_USE_ONE_SHOT_AT_THREAD_EXIT */
00771   }
00772   else
00773     thr_desc = td;
00774 
00775   thr_desc->thr_id_ = t_id;
00776   thr_desc->thr_handle_ = t_handle;
00777   thr_desc->grp_id_ = grp_id;
00778   thr_desc->task_ = task;
00779   thr_desc->flags_ = flags;
00780 
00781   this->thr_list_.insert_head (thr_desc);
00782   ACE_SET_BITS (thr_desc->thr_state_, thr_state);
00783   thr_desc->sync_->release ();
00784 
00785   return 0;
00786 }
00787 
00788 // Return the thread descriptor (indexed by ACE_hthread_t).
00789 
00790 ACE_Thread_Descriptor *
00791 ACE_Thread_Manager::find_hthread (ACE_hthread_t h_id)
00792 {
00793   for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
00794        !iter.done ();
00795        iter.advance ())
00796     if (ACE_OS::thr_cmp (iter.next ()->thr_handle_, h_id))
00797       return iter.next ();
00798 
00799   return 0;
00800 }
00801 
00802 // Locate the index in the table associated with <t_id>.  Must be
00803 // called with the lock held.
00804 
00805 ACE_Thread_Descriptor *
00806 ACE_Thread_Manager::find_thread (ACE_thread_t t_id)
00807 {
00808   ACE_TRACE ("ACE_Thread_Manager::find_thread");
00809 
00810   for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
00811        !iter.done ();
00812        iter.advance ())
00813     if (ACE_OS::thr_equal (iter.next ()->thr_id_, t_id))
00814       return iter.next ();
00815   return 0;
00816 }
00817 
00818 // Insert a thread into the pool (checks for duplicates and doesn't
00819 // allow them to be inserted twice).
00820 
00821 int
00822 ACE_Thread_Manager::insert_thr (ACE_thread_t t_id,
00823                                 ACE_hthread_t t_handle,
00824                                 int grp_id,
00825                                 long flags)
00826 {
00827   ACE_TRACE ("ACE_Thread_Manager::insert_thr");
00828   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
00829 
00830   // Check for duplicates and bail out if we're already registered...
00831 #if defined (VXWORKS)
00832   if (this->find_hthread (t_handle) != 0 )
00833     return -1;
00834 #else  /* ! VXWORKS */
00835   if (this->find_thread (t_id) != 0 )
00836     return -1;
00837 #endif /* ! VXWORKS */
00838 
00839   if (grp_id == -1)
00840     grp_id = this->grp_id_++;
00841 
00842   if (this->append_thr (t_id,
00843                         t_handle,
00844                         ACE_THR_SPAWNED,
00845                         grp_id,
00846                         0,
00847                         flags) == -1)
00848     return -1;
00849 
00850   return grp_id;
00851 }
00852 
00853 // Run the registered hooks when the thread exits.
00854 
00855 void
00856 ACE_Thread_Manager::run_thread_exit_hooks (int i)
00857 {
00858 #if 0 // currently unused!
00859   ACE_TRACE ("ACE_Thread_Manager::run_thread_exit_hooks");
00860 
00861   // @@ Currently, we have just one hook.  This should clearly be
00862   // generalized to support an arbitrary number of hooks.
00863 
00864   ACE_Thread_Descriptor *td = this->thread_desc_self ();
00865   if (td != 0 && td->cleanup_info.cleanup_hook_ != 0)
00866     {
00867       (*td->cleanup_info_.cleanup_hook_)
00868         (td->cleanup_info_.object_,
00869          td->cleanup_info_.param_);
00870 
00871       td->cleanup_info_.cleanup_hook_ = 0;
00872     }
00873   ACE_UNUSED_ARG (i);
00874 #else
00875   ACE_UNUSED_ARG (i);
00876 #endif /* 0 */
00877 }
00878 
00879 // Remove a thread from the pool.  Must be called with locks held.
00880 
00881 void
00882 ACE_Thread_Manager::remove_thr (ACE_Thread_Descriptor *td,
00883                                 int close_handler)
00884 {
00885   ACE_TRACE ("ACE_Thread_Manager::remove_thr");
00886 
00887 #if defined (VXWORKS)
00888   ACE_thread_t tid = td->self ();
00889 #endif /* VXWORKS */
00890 
00891 #if !defined(ACE_USE_ONE_SHOT_AT_THREAD_EXIT)
00892   td->tm_ = 0;
00893 #endif /* !ACE_USE_ONE_SHOT_AT_THREAD_EXIT */
00894   this->thr_list_.remove (td);
00895 
00896 #if defined (VXWORKS)
00897   // Delete the thread ID, if the ACE_Thread_Manager allocated it.
00898   if (tid  &&  tid[0] == ACE_THR_ID_ALLOCATED)
00899     {
00900       delete [] tid;
00901     }
00902 #endif /* VXWORKS */
00903 
00904 #if defined (ACE_WIN32)
00905   if (close_handler != 0)
00906     ::CloseHandle (td->thr_handle_);
00907 #else
00908   ACE_UNUSED_ARG (close_handler);
00909 #endif /* ACE_WIN32 */
00910 
00911 #if 1
00912 
00913   this->thread_desc_freelist_.add (td);
00914 #else
00915   delete td;
00916 #endif /* 1 */
00917 
00918 #if defined (ACE_HAS_THREADS)
00919   // Tell all waiters when there are no more threads left in the pool.
00920   if (this->thr_list_.size () == 0)
00921     this->zero_cond_.broadcast ();
00922 #endif /* ACE_HAS_THREADS */
00923 }
00924 
00925 // Repeatedly call remove_thr on all table entries until there
00926 // is no thread left.   Must be called with lock held.
00927 
00928 void
00929 ACE_Thread_Manager::remove_thr_all (void)
00930 {
00931   ACE_Thread_Descriptor *td;
00932 
00933   while ((td = this->thr_list_.delete_head ()) != 0)
00934     {
00935 #if defined (ACE_WIN32)
00936       // We need to let go handles if we want to let the threads
00937       // run wild.
00938       // @@ Do we need to close down AIX thread handles too?
00939       ::CloseHandle (td->thr_handle_);
00940 #endif /* ACE_WIN32 */
00941       delete td;
00942     }
00943 
00944 }
00945 
00946 // ------------------------------------------------------------------
00947 // Factor out some common behavior to simplify the following methods.
00948 #define ACE_THR_OP(OP,STATE) \
00949   int result = OP (td->thr_handle_); \
00950   if (result == -1) { \
00951     if (errno != ENOTSUP) \
00952       this->thr_to_be_removed_.enqueue_tail (td); \
00953     return -1; \
00954   } \
00955   else { \
00956     ACE_SET_BITS (td->thr_state_, STATE); \
00957     return 0; \
00958   }
00959 
00960 int
00961 ACE_Thread_Manager::join_thr (ACE_Thread_Descriptor *td, int)
00962 {
00963   ACE_TRACE ("ACE_Thread_Manager::join_thr");
00964   int result = ACE_Thread::join (td->thr_handle_);
00965   if (result != 0)
00966     {
00967       // Since the thread are being joined, we should
00968       // let it remove itself from the list.
00969 
00970       //      this->remove_thr (td);
00971       errno = result;
00972       return -1;
00973     }
00974 
00975   return 0;
00976 }
00977 
00978 int
00979 ACE_Thread_Manager::suspend_thr (ACE_Thread_Descriptor *td, int)
00980 {
00981   ACE_TRACE ("ACE_Thread_Manager::suspend_thr");
00982 
00983   int result = ACE_Thread::suspend (td->thr_handle_);
00984   if (result == -1) {
00985     if (errno != ENOTSUP)
00986       this->thr_to_be_removed_.enqueue_tail (td);
00987     return -1;
00988   }
00989   else {
00990     ACE_SET_BITS (td->thr_state_, ACE_THR_SUSPENDED);
00991     return 0;
00992   }
00993 }
00994 
00995 int
00996 ACE_Thread_Manager::resume_thr (ACE_Thread_Descriptor *td, int)
00997 {
00998   ACE_TRACE ("ACE_Thread_Manager::resume_thr");
00999 
01000   int result = ACE_Thread::resume (td->thr_handle_);
01001   if (result == -1) {
01002     if (errno != ENOTSUP)
01003       this->thr_to_be_removed_.enqueue_tail (td);
01004     return -1;
01005   }
01006   else {
01007     ACE_CLR_BITS (td->thr_state_, ACE_THR_SUSPENDED);
01008     return 0;
01009   }
01010 }
01011 
01012 int
01013 ACE_Thread_Manager::cancel_thr (ACE_Thread_Descriptor *td, int async_cancel)
01014 {
01015   ACE_TRACE ("ACE_Thread_Manager::cancel_thr");
01016   // Must set the state first and then try to cancel the thread.
01017   ACE_SET_BITS (td->thr_state_, ACE_THR_CANCELLED);
01018 
01019   if (async_cancel != 0)
01020     // Note that this call only does something relevant if the OS
01021     // platform supports asynchronous thread cancellation.  Otherwise,
01022     // it's a no-op.
01023     return ACE_Thread::cancel (td->thr_id_);
01024 
01025   return 0;
01026 }
01027 
01028 int
01029 ACE_Thread_Manager::kill_thr (ACE_Thread_Descriptor *td, int signum)
01030 {
01031   ACE_TRACE ("ACE_Thread_Manager::kill_thr");
01032 
01033   ACE_thread_t tid = td->thr_id_;
01034 #if defined (VXWORKS)
01035   // Skip over the ID-allocated marker, if present.
01036   tid += tid[0] == ACE_THR_ID_ALLOCATED  ?  1  :  0;
01037 #endif /* VXWORKS */
01038 
01039   int result = ACE_Thread::kill (tid, signum);
01040 
01041   if (result != 0)
01042     {
01043       // Only remove a thread from us when there is a "real" error.
01044       if (errno != ENOTSUP)
01045         this->thr_to_be_removed_.enqueue_tail (td);
01046 
01047       return -1;
01048     }
01049 #if defined (CHORUS)
01050   else if (signum == SIGTHREADKILL)
01051     this->thr_to_be_removed_.enqueue_tail (td);
01052 #endif /* CHORUS */
01053 
01054     return 0;
01055 }
01056 
01057 // ------------------------------------------------------------------
01058 // Factor out some common behavior to simplify the following methods.
01059 #define ACE_EXECUTE_OP(OP, ARG) \
01060   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1)); \
01061   ACE_ASSERT (this->thr_to_be_removed_.is_empty ()); \
01062   ACE_FIND (this->find_thread (t_id), ptr); \
01063   if (ptr == 0) \
01064     { \
01065       errno = ENOENT; \
01066       return -1; \
01067     } \
01068   int result = OP (ptr, ARG); \
01069   ACE_Errno_Guard error (errno); \
01070   while (! this->thr_to_be_removed_.is_empty ()) { \
01071     ACE_Thread_Descriptor *td; \
01072     this->thr_to_be_removed_.dequeue_head (td); \
01073     this->remove_thr (td, 1); \
01074   } \
01075   return result
01076 
01077 // Suspend a single thread.
01078 
01079 int
01080 ACE_Thread_Manager::suspend (ACE_thread_t t_id)
01081 {
01082   ACE_TRACE ("ACE_Thread_Manager::suspend");
01083   ACE_EXECUTE_OP (this->suspend_thr, 0);
01084 }
01085 
01086 // Resume a single thread.
01087 
01088 int
01089 ACE_Thread_Manager::resume (ACE_thread_t t_id)
01090 {
01091   ACE_TRACE ("ACE_Thread_Manager::resume");
01092   ACE_EXECUTE_OP (this->resume_thr, 0);
01093 }
01094 
01095 // Cancel a single thread.
01096 
01097 int
01098 ACE_Thread_Manager::cancel (ACE_thread_t t_id, int async_cancel)
01099 {
01100   ACE_TRACE ("ACE_Thread_Manager::cancel");
01101   ACE_EXECUTE_OP (this->cancel_thr, async_cancel);
01102 }
01103 
01104 // Send a signal to a single thread.
01105 
01106 int
01107 ACE_Thread_Manager::kill (ACE_thread_t t_id, int signum)
01108 {
01109   ACE_TRACE ("ACE_Thread_Manager::kill");
01110   ACE_EXECUTE_OP (this->kill_thr, signum);
01111 }
01112 
01113 int
01114 ACE_Thread_Manager::check_state (ACE_UINT32 state,
01115                                  ACE_thread_t id,
01116                                  int enable)
01117 {
01118   ACE_TRACE ("ACE_Thread_Manager::check_state");
01119   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
01120 
01121   ACE_UINT32 thr_state;
01122 
01123   int self_check = ACE_OS::thr_equal (id, ACE_OS::thr_self ());
01124 
01125   // If we're checking the state of our thread, try to get the cached
01126   // value out of TSS to avoid lookup.
01127   if (self_check)
01128     {
01129       ACE_Thread_Descriptor *desc = ACE_LOG_MSG->thr_desc ();
01130       if (desc == 0)
01131         return 0;               // Always return false.
01132       thr_state = desc->thr_state_;
01133     }
01134   else
01135     {
01136       // Not calling from self, have to look it up from the list.
01137       ACE_FIND (this->find_thread (id), ptr);
01138       if (ptr == 0)
01139         return 0;
01140       thr_state = ptr->thr_state_;
01141     }
01142   if (enable)
01143     return ACE_BIT_ENABLED (thr_state, state);
01144 
01145   return ACE_BIT_DISABLED (thr_state, state);
01146 }
01147 
01148 // Test if a single thread is suspended.
01149 
01150 int
01151 ACE_Thread_Manager::testsuspend (ACE_thread_t t_id)
01152 {
01153   ACE_TRACE ("ACE_Thread_Manager::testsuspend");
01154   return this->check_state (ACE_THR_SUSPENDED, t_id);
01155 }
01156 
01157 // Test if a single thread is active (i.e., resumed).
01158 
01159 int
01160 ACE_Thread_Manager::testresume (ACE_thread_t t_id)
01161 {
01162   ACE_TRACE ("ACE_Thread_Manager::testresume");
01163   return this->check_state (ACE_THR_SUSPENDED, t_id, 0);
01164 }
01165 
01166 // Test if a single thread is cancelled.
01167 
01168 int
01169 ACE_Thread_Manager::testcancel (ACE_thread_t t_id)
01170 {
01171   ACE_TRACE ("ACE_Thread_Manager::testcancel");
01172   return this->check_state (ACE_THR_CANCELLED, t_id);
01173 }
01174 
01175 // Thread information query functions.
01176 
01177 int
01178 ACE_Thread_Manager::hthread_within (ACE_hthread_t handle)
01179 {
01180   ACE_TRACE ("ACE_Thread_Manager::hthread_within");
01181   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_monx, this->lock_, -1));
01182 
01183   for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
01184        !iter.done ();
01185        iter.advance ())
01186     if (ACE_OS::thr_cmp(iter.next ()->thr_handle_, handle))
01187       return 1;
01188 
01189   return 0;
01190 }
01191 
01192 int
01193 ACE_Thread_Manager::thread_within (ACE_thread_t tid)
01194 {
01195   ACE_TRACE ("ACE_Thread_Manager::thread_within");
01196   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_monx, this->lock_, -1));
01197 
01198   for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
01199        !iter.done ();
01200        iter.advance ())
01201     if (ACE_OS::thr_equal (iter.next ()->thr_id_, tid))
01202       return 1;
01203 
01204   return 0;
01205 }
01206 
01207 // Get group ids for a particular thread id.
01208 
01209 int
01210 ACE_Thread_Manager::get_grp (ACE_thread_t t_id, int &grp_id)
01211 {
01212   ACE_TRACE ("ACE_Thread_Manager::get_grp");
01213   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
01214 
01215   ACE_FIND (this->find_thread (t_id), ptr);
01216 
01217   if (ptr)
01218     grp_id = ptr->grp_id_;
01219   else
01220     return -1;
01221   return 0;
01222 }
01223 
01224 // Set group ids for a particular thread id.
01225 
01226 int
01227 ACE_Thread_Manager::set_grp (ACE_thread_t t_id, int grp_id)
01228 {
01229   ACE_TRACE ("ACE_Thread_Manager::set_grp");
01230   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
01231 
01232   ACE_FIND (this->find_thread (t_id), ptr);
01233   if (ptr)
01234     ptr->grp_id_ = grp_id;
01235   else
01236     return -1;
01237   return 0;
01238 }
01239 
01240 // Suspend a group of threads.
01241 
01242 int
01243 ACE_Thread_Manager::apply_grp (int grp_id,
01244                                ACE_THR_MEMBER_FUNC func,
01245                                int arg)
01246 {
01247   ACE_TRACE ("ACE_Thread_Manager::apply_grp");
01248   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_monx, this->lock_, -1));
01249   ACE_ASSERT (this->thr_to_be_removed_.is_empty ());
01250 
01251   int result = 0;
01252 
01253   for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
01254        !iter.done ();
01255        iter.advance ())
01256     if (iter.next ()->grp_id_ == grp_id)
01257       if ((this->*func) (iter.next (), arg) == -1)
01258         result = -1;
01259 
01260   // Must remove threads after we have traversed the thr_list_ to
01261   // prevent clobber thr_list_'s integrity.
01262 
01263   if (! this->thr_to_be_removed_.is_empty ())
01264     {
01265       // Save/restore errno.
01266       ACE_Errno_Guard error (errno);
01267 
01268       for (ACE_Thread_Descriptor *td;
01269            this->thr_to_be_removed_.dequeue_head (td) != -1;
01270            )
01271         this->remove_thr (td, 1);
01272     }
01273 
01274   return result;
01275 }
01276 
01277 int
01278 ACE_Thread_Manager::suspend_grp (int grp_id)
01279 {
01280   ACE_TRACE ("ACE_Thread_Manager::suspend_grp");
01281   return this->apply_grp (grp_id,
01282                           ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::suspend_thr));
01283 }
01284 
01285 // Resume a group of threads.
01286 
01287 int
01288 ACE_Thread_Manager::resume_grp (int grp_id)
01289 {
01290   ACE_TRACE ("ACE_Thread_Manager::resume_grp");
01291   return this->apply_grp (grp_id,
01292                           ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::resume_thr));
01293 }
01294 
01295 // Kill a group of threads.
01296 
01297 int
01298 ACE_Thread_Manager::kill_grp (int grp_id, int signum)
01299 {
01300   ACE_TRACE ("ACE_Thread_Manager::kill_grp");
01301   return this->apply_grp (grp_id,
01302                           ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::kill_thr), signum);
01303 }
01304 
01305 // Cancel a group of threads.
01306 
01307 int
01308 ACE_Thread_Manager::cancel_grp (int grp_id, int async_cancel)
01309 {
01310   ACE_TRACE ("ACE_Thread_Manager::cancel_grp");
01311   return this->apply_grp (grp_id,
01312                           ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::cancel_thr),
01313                           async_cancel);
01314 }
01315 
01316 int
01317 ACE_Thread_Manager::apply_all (ACE_THR_MEMBER_FUNC func, int arg)
01318 {
01319   ACE_TRACE ("ACE_Thread_Manager::apply_all");
01320   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
01321   ACE_ASSERT (this->thr_to_be_removed_.is_empty ());
01322 
01323   int result = 0;
01324 
01325   for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
01326        !iter.done ();
01327        iter.advance ())
01328     if ((this->*func)(iter.next (), arg) == -1)
01329       result = -1;
01330 
01331   // Must remove threads after we have traversed the thr_list_ to
01332   // prevent clobber thr_list_'s integrity.
01333 
01334   if (! this->thr_to_be_removed_.is_empty ())
01335     {
01336       // Save/restore errno.
01337       ACE_Errno_Guard error (errno);
01338 
01339       for (ACE_Thread_Descriptor *td;
01340            this->thr_to_be_removed_.dequeue_head (td) != -1;
01341            )
01342         this->remove_thr (td, 1);
01343     }
01344 
01345   return result;
01346 }
01347 
01348 // Resume all threads that are suspended.
01349 
01350 int
01351 ACE_Thread_Manager::resume_all (void)
01352 {
01353   ACE_TRACE ("ACE_Thread_Manager::resume_all");
01354   return this->apply_all (ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::resume_thr));
01355 }
01356 
01357 int
01358 ACE_Thread_Manager::suspend_all (void)
01359 {
01360   ACE_TRACE ("ACE_Thread_Manager::suspend_all");
01361   return this->apply_all (ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::suspend_thr));
01362 }
01363 
01364 int
01365 ACE_Thread_Manager::kill_all (int sig)
01366 {
01367   ACE_TRACE ("ACE_Thread_Manager::kill_all");
01368   return this->apply_all (&ACE_Thread_Manager::kill_thr, sig);
01369 }
01370 
01371 int
01372 ACE_Thread_Manager::cancel_all (int async_cancel)
01373 {
01374   ACE_TRACE ("ACE_Thread_Manager::cancel_all");
01375   return this->apply_all (ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::cancel_thr),
01376                           async_cancel);
01377 }
01378 
01379 int
01380 ACE_Thread_Manager::join (ACE_thread_t tid, ACE_THR_FUNC_RETURN *status)
01381 {
01382   ACE_TRACE ("ACE_Thread_Manager::join");
01383 
01384   ACE_Thread_Descriptor_Base tdb;
01385   int found = 0;
01386 
01387   {
01388     ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
01389 
01390 #if !defined (VXWORKS)
01391     for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor_Base> biter (this->terminated_thr_list_);
01392          !biter.done ();
01393          biter.advance ())
01394       if (ACE_OS::thr_equal (biter.next ()->thr_id_, tid))
01395         {
01396           ACE_Thread_Descriptor_Base *tdb = biter.advance_and_remove (0);
01397 # if defined (_AIX)
01398   // The AIX xlC compiler does not match the proper function here - it
01399   // confuses ACE_Thread::join(ACE_thread_t, ACE_thread_t *, void **=0) and
01400   // ACE_Thread::join(ACE_hthread_t, void **=0).  At least at 3.1.4.7 and .8.
01401   // The 2nd arg is ignored for pthreads anyway.
01402 
01403   // And, g++ on AIX needs the three-arg thr_join, also, to pick up the
01404   // proper version from the AIX libraries.
01405           if (ACE_Thread::join (tdb->thr_handle_,
01406                                 &tdb->thr_handle_,
01407                                 status) == -1)
01408 # else  /* ! _AIX */
01409           if (ACE_Thread::join (tdb->thr_handle_, status) == -1)
01410 # endif /* ! _AIX */
01411             return -1;
01412 
01413 # if defined (ACE_HAS_PTHREADS_DRAFT4)  &&  defined (ACE_LACKS_SETDETACH)
01414           // Must explicitly detach threads.  Threads without THR_DETACHED
01415           // were detached in ACE_OS::thr_create ().
01416           ::pthread_detach (&tdb->thr_handle_);
01417 # endif /* ACE_HAS_PTHREADS_DRAFT4 && ACE_LACKS_SETDETACH */
01418 
01419           delete tdb;
01420           return 0;
01421           // return immediately if we've found the thread we want to join.
01422         }
01423 #endif /* !VXWORKS */
01424 
01425     for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
01426          !iter.done ();
01427          iter.advance ())
01428       // If threads are created as THR_DETACHED or THR_DAEMON, we
01429       // can't help much.
01430       if (ACE_OS::thr_equal (iter.next ()->thr_id_,tid) &&
01431           (ACE_BIT_DISABLED (iter.next ()->flags_, THR_DETACHED | THR_DAEMON)
01432            || ACE_BIT_ENABLED (iter.next ()->flags_, THR_JOINABLE)))
01433         {
01434           tdb = *iter.next ();
01435           ACE_SET_BITS (iter.next ()->thr_state_, ACE_THR_JOINING);
01436           found = 1;
01437           break;
01438         }
01439 
01440     if (found == 0)
01441       return -1;
01442     // Didn't find the thread we want or the thread is not joinable.
01443   }
01444 
01445 # if defined (_AIX)
01446   // The AIX xlC compiler does not match the proper function here - it
01447   // confuses ACE_Thread::join(ACE_thread_t, ACE_thread_t *, void **=0) and
01448   // ACE_Thread::join(ACE_hthread_t, void **=0).  At least at 3.1.4.7 and .8.
01449   // The 2nd arg is ignored for pthreads anyway.
01450 
01451   // And, g++ on AIX needs the three-arg thr_join, also, to pick up the
01452   // proper version from the AIX libraries.
01453   if (ACE_Thread::join (tdb.thr_handle_, &tdb.thr_handle_, status) == -1)
01454 # else  /* ! _AIX */
01455   if (ACE_Thread::join (tdb.thr_handle_, status) == -1)
01456 # endif /* ! _AIX */
01457     return -1;
01458 
01459 # if defined (ACE_HAS_PTHREADS_DRAFT4)  &&  defined (ACE_LACKS_SETDETACH)
01460   // Must explicitly detach threads.  Threads without THR_DETACHED
01461   // were detached in ACE_OS::thr_create ().
01462 
01463 #   if defined (HPUX_10)
01464   // HP-UX DCE threads' pthread_detach will smash thr_id if it's just given
01465   // as an argument.  Since the thread handle is still needed, give
01466   // pthread_detach a junker to scribble on.
01467   ACE_thread_t  junker;
01468   cma_handle_assign(&tdb.thr_handle_, &junker);
01469   ::pthread_detach (&junker);
01470 #   else
01471   ::pthread_detach (&tdb.thr_handle_);
01472     #endif /* HPUX_10 */
01473 # endif /* ACE_HAS_PTHREADS_DRAFT4 && ACE_LACKS_SETDETACH */
01474   return 0;
01475 }
01476 
01477 // Wait for group of threads
01478 
01479 int
01480 ACE_Thread_Manager::wait_grp (int grp_id)
01481 {
01482   ACE_TRACE ("ACE_Thread_Manager::wait_grp");
01483 
01484   int copy_count = 0;
01485   ACE_Thread_Descriptor_Base *copy_table = 0;
01486 
01487   // We have to make sure that while we wait for these threads to
01488   // exit, we do not have the lock.  Therefore we make a copy of all
01489   // interesting entries and let go of the lock.
01490   {
01491     ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
01492 
01493 #if !defined (VXWORKS)
01494     ACE_NEW_RETURN (copy_table,
01495                     ACE_Thread_Descriptor_Base [this->thr_list_.size ()
01496                                                + this->terminated_thr_list_.size ()],
01497                     -1);
01498 #else
01499     ACE_NEW_RETURN (copy_table,
01500                     ACE_Thread_Descriptor_Base [this->thr_list_.size ()],
01501                     -1);
01502 #endif /* VXWORKS */
01503 
01504     for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
01505          !iter.done ();
01506          iter.advance ())
01507       // If threads are created as THR_DETACHED or THR_DAEMON, we
01508       // can't help much.
01509       if (iter.next ()->grp_id_ == grp_id &&
01510           (ACE_BIT_DISABLED (iter.next ()->flags_, THR_DETACHED | THR_DAEMON)
01511            || ACE_BIT_ENABLED (iter.next ()->flags_, THR_JOINABLE)))
01512         {
01513           ACE_SET_BITS (iter.next ()->thr_state_, ACE_THR_JOINING);
01514           copy_table[copy_count++] = *iter.next ();
01515         }
01516 
01517 #if !defined (VXWORKS)
01518     for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor_Base> biter (this->terminated_thr_list_);
01519          !biter.done ();
01520          biter.advance ())
01521       // If threads are created as THR_DETACHED or THR_DAEMON, we
01522       // can't help much.
01523       if (biter.next ()->grp_id_ == grp_id)
01524         {
01525           ACE_Thread_Descriptor_Base *tdb = biter.advance_and_remove (0);
01526           copy_table[copy_count++] = *tdb;
01527           delete tdb;
01528         }
01529 #endif /* !VXWORKS */
01530   }
01531 
01532   // Now actually join() with all the threads in this group.
01533   int result = 0;
01534 
01535   for (int i = 0;
01536        i < copy_count && result != -1;
01537        i++)
01538     {
01539       if (ACE_Thread::join (copy_table[i].thr_handle_) == -1)
01540         result = -1;
01541 
01542 # if defined (ACE_HAS_PTHREADS_DRAFT4)  &&  defined (ACE_LACKS_SETDETACH)
01543       // Must explicitly detach threads.  Threads without THR_DETACHED
01544       // were detached in ACE_OS::thr_create ().
01545       ::pthread_detach (&copy_table[i].thr_handle_);
01546 # endif /* ACE_HAS_PTHREADS_DRAFT4 && ACE_LACKS_SETDETACH */
01547     }
01548 
01549   delete [] copy_table;
01550 
01551   return result;
01552 }
01553 
01554 // Must be called when thread goes out of scope to clean up its table
01555 // slot.
01556 
01557 ACE_THR_FUNC_RETURN
01558 ACE_Thread_Manager::exit (ACE_THR_FUNC_RETURN status, int do_thr_exit)
01559 {
01560   ACE_TRACE ("ACE_Thread_Manager::exit");
01561 #if defined(ACE_USE_ONE_SHOT_AT_THREAD_EXIT)
01562   int close_handle = 0;
01563 #endif /* ACE_USE_ONE_SHOT_AT_THREAD_EXIT */
01564 
01565 #if defined (ACE_WIN32)
01566   // Remove detached thread handle.
01567 
01568   if (do_thr_exit)
01569     {
01570 #if 0
01571       // @@ This callback is now taken care of by TSS_Cleanup.  Do we
01572       //    need it anymore?
01573 
01574       // On Win32, if we really wants to exit from a thread, we must
01575       // first  clean up the thread specific storage.  By doing so,
01576       // ACE_Thread_Manager::exit will be called again with
01577       // do_thr_exit = 0 and cleaning up the ACE_Cleanup_Info (but not
01578       // exiting the thread.)  After the following call returns, we
01579       // are safe to exit this thread.
01580       delete ACE_Thread_Exit::instance ();
01581 #endif /* 0 */
01582       ACE_Thread::exit (status);
01583     }
01584 #endif /* ACE_WIN32 */
01585 
01586 #if defined(ACE_USE_ONE_SHOT_AT_THREAD_EXIT)
01587   ACE_Cleanup_Info cleanup_info;
01588 
01589   // Just hold onto the guard while finding this thread's id and
01590   // copying the exit hook.
01591   {
01592     ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0));
01593 
01594     // Find the thread id, but don't use the cache.  It might have been
01595     // deleted already.
01596 #if defined (VXWORKS)
01597     ACE_hthread_t id;
01598     ACE_OS::thr_self (id);
01599     ACE_Thread_Descriptor *td = this->find_hthread (id);
01600 #else  /* ! VXWORKS */
01601     ACE_thread_t id = ACE_OS::thr_self ();
01602     ACE_Thread_Descriptor *td = this->find_thread (id);
01603 #endif /* ! VXWORKS */
01604 
01605     // Locate thread id.
01606     if (td != 0)
01607       {
01608         // @@ Currently, we have just one hook.  This should clearly
01609         // be generalized to support an arbitrary number of hooks.
01610 
01611         if (td->cleanup_info_.cleanup_hook_ != 0)
01612           {
01613             // Copy the hook so that we can call it after releasing
01614             // the guard.
01615             cleanup_info = td->cleanup_info_;
01616             td->cleanup_info_.cleanup_hook_ = 0;
01617           }
01618 
01619 #if !defined (VXWORKS)
01620         // Threads created with THR_DAEMON shouldn't exist here, but
01621         // just to be safe, let's put it here.
01622 
01623         if (ACE_BIT_DISABLED (td->thr_state_, ACE_THR_JOINING))
01624           if (ACE_BIT_DISABLED (td->flags_, THR_DETACHED | THR_DAEMON)
01625               || ACE_BIT_ENABLED (td->flags_, THR_JOINABLE))
01626             {
01627               // Mark thread as terminated.
01628               ACE_SET_BITS (td->thr_state_, ACE_THR_TERMINATED);
01629               this->register_as_terminated (td);
01630               // Must copy the information here because td will be "freed" below.
01631             }
01632 #if defined (ACE_WIN32)
01633           else
01634             {
01635               close_handle = 1;
01636             }
01637 #endif /* ACE_WIN32 */
01638 #endif /* ! VXWORKS */
01639 
01640         // Remove thread descriptor from the table.
01641         this->remove_thr (td, close_handle);
01642       }
01643     // Release the guard.
01644   }
01645 
01646   // Call the cleanup hook.
01647   if (cleanup_info.cleanup_hook_ != 0)
01648     (*cleanup_info.cleanup_hook_) (cleanup_info.object_,
01649                                    cleanup_info.param_);
01650 #else /* !ACE_USE_ONE_SHOT_AT_THREAD_EXIT */
01651   // Just hold onto the guard while finding this thread's id and
01652   {
01653     ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0));
01654 
01655     // Find the thread id, but don't use the cache.  It might have been
01656     // deleted already.
01657 #if defined (VXWORKS)
01658     ACE_hthread_t id;
01659     ACE_OS::thr_self (id);
01660     ACE_Thread_Descriptor* td = this->find_hthread (id);
01661 #else  /* ! VXWORKS */
01662     ACE_thread_t id = ACE_OS::thr_self ();
01663     ACE_Thread_Descriptor* td = this->find_thread (id);
01664 #endif /* ! VXWORKS */
01665     if (td != 0)
01666      {
01667        // @@ We call Thread_Descriptor terminate this realize the cleanup
01668        // process itself.
01669        td->terminate();
01670      }
01671   }
01672 
01673 
01674 #endif /* !ACE_USE_ONE_SHOT_AT_THREAD_EXIT */
01675 
01676   if (do_thr_exit)
01677     {
01678       ACE_Thread::exit (status);
01679       // On reasonable systems <ACE_Thread::exit> should not return.
01680       // However, due to horrible semantics with Win32 thread-specific
01681       // storage this call can return (don't ask...).
01682     }
01683 
01684   return 0;
01685 }
01686 
01687 // Wait for all the threads to exit.
01688 
01689 int
01690 ACE_Thread_Manager::wait (const ACE_Time_Value *timeout,
01691                           int abandon_detached_threads)
01692 {
01693   ACE_TRACE ("ACE_Thread_Manager::wait");
01694 
01695 #if defined (ACE_HAS_THREADS)
01696   {
01697     // Just hold onto the guard while waiting.
01698     ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
01699 
01700     if (ACE_Object_Manager::shutting_down () != 1)
01701       {
01702         // Program is not shutting down.  Perform a normal wait on threads.
01703         if (abandon_detached_threads != 0)
01704           {
01705             ACE_ASSERT (this->thr_to_be_removed_.is_empty ());
01706             for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor>
01707                    iter (this->thr_list_);
01708                  !iter.done ();
01709                  iter.advance ())
01710               if (ACE_BIT_ENABLED (iter.next ()->flags_,
01711                                    THR_DETACHED | THR_DAEMON)
01712                   && ACE_BIT_DISABLED (iter.next ()->flags_, THR_JOINABLE))
01713                 {
01714                   this->thr_to_be_removed_.enqueue_tail (iter.next ());
01715                   ACE_SET_BITS (iter.next ()->thr_state_, ACE_THR_JOINING);
01716                 }
01717 
01718             if (! this->thr_to_be_removed_.is_empty ())
01719               {
01720                 ACE_Thread_Descriptor *td;
01721                 while (this->thr_to_be_removed_.dequeue_head (td) != -1)
01722                   this->remove_thr (td, 1);
01723               }
01724           }
01725 
01726         while (this->thr_list_.size () > 0)
01727           if (this->zero_cond_.wait (timeout) == -1)
01728             return -1;
01729       }
01730     else
01731         // Program is shutting down, no chance to wait on threads.
01732         // Therefore, we'll just remove threads from the list.
01733         this->remove_thr_all ();
01734     // Release the guard, giving other threads a chance to run.
01735   }
01736 
01737 #if !defined (VXWORKS)
01738   // @@ VxWorks doesn't support thr_join (yet.)  We are working
01739   //on our implementation.   Chorus'es thr_join seems broken.
01740   ACE_Thread_Descriptor_Base *item;
01741 
01742 #if defined (CHORUS)
01743   if (ACE_Object_Manager::shutting_down () != 1)
01744     {
01745 #endif /* CHORUS */
01746       while ((item = this->terminated_thr_list_.delete_head ()) != 0)
01747         {
01748           if (ACE_BIT_DISABLED (item->flags_, THR_DETACHED | THR_DAEMON)
01749               || ACE_BIT_ENABLED (item->flags_, THR_JOINABLE))
01750             // Detached handles shouldn't reached here.
01751               ACE_Thread::join (item->thr_handle_);
01752 
01753 # if defined (ACE_HAS_PTHREADS_DRAFT4)  &&  defined (ACE_LACKS_SETDETACH)
01754           // Must explicitly detach threads.  Threads without
01755           // THR_DETACHED were detached in ACE_OS::thr_create ().
01756           ::pthread_detach (&item->thr_handle_);
01757 # endif /* ACE_HAS_PTHREADS_DRAFT4 && ACE_LACKS_SETDETACH */
01758           delete item;
01759         }
01760 #if defined (CHORUS)
01761     }
01762 #endif /* CHORUS */
01763 
01764 #endif /* ! VXWORKS */
01765 #else
01766   ACE_UNUSED_ARG (timeout);
01767   ACE_UNUSED_ARG (abandon_detached_threads);
01768 #endif /* ACE_HAS_THREADS */
01769 
01770   return 0;
01771 }
01772 
01773 int
01774 ACE_Thread_Manager::apply_task (ACE_Task_Base *task,
01775                                 ACE_THR_MEMBER_FUNC func,
01776                                 int arg)
01777 {
01778   ACE_TRACE ("ACE_Thread_Manager::apply_task");
01779   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
01780   ACE_ASSERT (this->thr_to_be_removed_.is_empty ());
01781 
01782   int result = 0;
01783 
01784   for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
01785        !iter.done ();
01786        iter.advance ())
01787     if (iter.next ()->task_ == task
01788         && (this->*func) (iter.next (), arg) == -1)
01789       result = -1;
01790 
01791   // Must remove threads after we have traversed the thr_list_ to
01792   // prevent clobber thr_list_'s integrity.
01793 
01794   if (! this->thr_to_be_removed_.is_empty ())
01795     {
01796       // Save/restore errno.
01797       ACE_Errno_Guard error (errno);
01798 
01799       for (ACE_Thread_Descriptor *td;
01800            this->thr_to_be_removed_.dequeue_head (td) != -1;
01801            )
01802         this->remove_thr (td, 1);
01803     }
01804 
01805   return result;
01806 }
01807 
01808 // Wait for all threads to exit a task.
01809 
01810 int
01811 ACE_Thread_Manager::wait_task (ACE_Task_Base *task)
01812 {
01813   int copy_count = 0;
01814   ACE_Thread_Descriptor_Base *copy_table = 0;
01815 
01816   // We have to make sure that while we wait for these threads to
01817   // exit, we do not have the lock.  Therefore we make a copy of all
01818   // interesting entries and let go of the lock.
01819   {
01820     ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
01821 
01822 #if !defined (VXWORKS)
01823     ACE_NEW_RETURN (copy_table,
01824                     ACE_Thread_Descriptor_Base [this->thr_list_.size ()
01825                                                 + this->terminated_thr_list_.size ()],
01826                     -1);
01827 #else
01828     ACE_NEW_RETURN (copy_table,
01829                     ACE_Thread_Descriptor_Base [this->thr_list_.size ()],
01830                     -1);
01831 #endif /* VXWORKS */
01832 
01833     for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
01834          !iter.done ();
01835          iter.advance ())
01836       // If threads are created as THR_DETACHED or THR_DAEMON, we
01837       // can't wait on them here.
01838       if (iter.next ()->task_ == task &&
01839           (ACE_BIT_DISABLED (iter.next ()->flags_,
01840                              THR_DETACHED | THR_DAEMON)
01841            || ACE_BIT_ENABLED (iter.next ()->flags_,
01842                                THR_JOINABLE)))
01843         {
01844           ACE_SET_BITS (iter.next ()->thr_state_,
01845                         ACE_THR_JOINING);
01846           copy_table[copy_count++] = *iter.next ();
01847         }
01848 
01849 #if !defined (VXWORKS)
01850     for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor_Base> titer (this->terminated_thr_list_);
01851          !titer.done ();
01852          titer.advance ())
01853       // If threads are created as THR_DETACHED or THR_DAEMON, we can't help much here.
01854       if (titer.next ()->task_ == task)
01855         {
01856           ACE_Thread_Descriptor_Base *tdb =
01857             titer.advance_and_remove (0);
01858           copy_table[copy_count++] = *tdb;
01859           delete tdb;
01860         }
01861 #endif /* VXWORKS */
01862   }
01863 
01864   // Now to do the actual work
01865   int result = 0;
01866 
01867   for (int i = 0;
01868        i < copy_count && result != -1;
01869        i++)
01870     {
01871       if (ACE_Thread::join (copy_table[i].thr_handle_) == -1)
01872         result = -1;
01873 
01874 # if defined (ACE_HAS_PTHREADS_DRAFT4)  &&  defined (ACE_LACKS_SETDETACH)
01875       // Must explicitly detach threads.  Threads without THR_DETACHED
01876       // were detached in ACE_OS::thr_create ().
01877       ::pthread_detach (&copy_table[i].thr_handle_);
01878 # endif /* ACE_HAS_PTHREADS_DRAFT4 && ACE_LACKS_SETDETACH */
01879     }
01880 
01881   delete [] copy_table;
01882 
01883   return result;
01884 }
01885 
01886 // Suspend a task
01887 
01888 int
01889 ACE_Thread_Manager::suspend_task (ACE_Task_Base *task)
01890 {
01891   ACE_TRACE ("ACE_Thread_Manager::suspend_task");
01892   return this->apply_task (task,
01893                            ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::suspend_thr));
01894 }
01895 
01896 // Resume a task.
01897 int
01898 ACE_Thread_Manager::resume_task (ACE_Task_Base *task)
01899 {
01900   ACE_TRACE ("ACE_Thread_Manager::resume_task");
01901   return this->apply_task (task,
01902                            ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::resume_thr));
01903 }
01904 
01905 // Kill a task.
01906 
01907 int
01908 ACE_Thread_Manager::kill_task (ACE_Task_Base *task, int /* signum */)
01909 {
01910   ACE_TRACE ("ACE_Thread_Manager::kill_task");
01911   return this->apply_task (task,
01912                            ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::kill_thr));
01913 }
01914 
01915 // Cancel a task.
01916 int
01917 ACE_Thread_Manager::cancel_task (ACE_Task_Base *task,
01918                                  int async_cancel)
01919 {
01920   ACE_TRACE ("ACE_Thread_Manager::cancel_task");
01921   return this->apply_task (task,
01922                            ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::cancel_thr),
01923                            async_cancel);
01924 }
01925 
01926 // Locate the index in the table associated with <task> from the
01927 // beginning of the table up to an index.  Must be called with the
01928 // lock held.
01929 
01930 ACE_Thread_Descriptor *
01931 ACE_Thread_Manager::find_task (ACE_Task_Base *task, size_t slot)
01932 {
01933   ACE_TRACE ("ACE_Thread_Manager::find_task");
01934 
01935   size_t i = 0;
01936 
01937   for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
01938        !iter.done ();
01939        iter.advance ())
01940     {
01941       if (i >= slot)
01942         break;
01943 
01944       if (task == iter.next ()->task_)
01945         return iter.next ();
01946 
01947       i++;
01948     }
01949 
01950   return 0;
01951 }
01952 
01953 // Returns the number of ACE_Task in a group.
01954 
01955 int
01956 ACE_Thread_Manager::num_tasks_in_group (int grp_id)
01957 {
01958   ACE_TRACE ("ACE_Thread_Manager::num_tasks_in_group");
01959   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
01960 
01961   int tasks_count = 0;
01962   size_t i = 0;
01963 
01964   for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
01965        !iter.done ();
01966        iter.advance ())
01967     {
01968       if (iter.next ()->grp_id_ == grp_id
01969           && this->find_task (iter.next ()->task_, i) == 0
01970           && iter.next ()->task_ != 0)
01971         tasks_count++;
01972 
01973       i++;
01974     }
01975   return tasks_count;
01976 }
01977 
01978 // Returns the number of threads in an ACE_Task.
01979 
01980 int
01981 ACE_Thread_Manager::num_threads_in_task (ACE_Task_Base *task)
01982 {
01983   ACE_TRACE ("ACE_Thread_Manager::num_threads_in_task");
01984   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
01985 
01986   int threads_count = 0;
01987 
01988   for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
01989        !iter.done ();
01990        iter.advance ())
01991     if (iter.next ()->task_ == task)
01992       threads_count++;
01993 
01994   return threads_count;
01995 }
01996 
01997 // Returns in task_list a list of ACE_Tasks registered with ACE_Thread_Manager.
01998 
01999 ssize_t
02000 ACE_Thread_Manager::task_all_list (ACE_Task_Base *task_list[],
02001                                    size_t n)
02002 {
02003   ACE_TRACE ("ACE_Thread_Manager::task_all_list");
02004   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
02005 
02006   size_t task_list_count = 0;
02007 
02008   for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
02009        !iter.done ();
02010        iter.advance ())
02011     {
02012       if (task_list_count >= n)
02013         break;
02014 
02015       ACE_Task_Base *task_p = iter.next ()->task_;
02016       if (0 != task_p)
02017         {
02018           // This thread has a task pointer; see if it's already in the
02019           // list. Don't add duplicates.
02020           size_t i = 0;
02021           for (; i < task_list_count; ++i)
02022             if (task_list[i] == task_p)
02023               break;
02024           if (i == task_list_count)        // No match - add this one
02025             task_list[task_list_count++] = task_p;
02026         }
02027     }
02028 
02029   return task_list_count;
02030 }
02031 
02032 // Returns in thread_list a list of all thread ids
02033 
02034 ssize_t
02035 ACE_Thread_Manager::thread_all_list (ACE_thread_t thread_list[],
02036                                      size_t n)
02037 {
02038   ACE_TRACE ("ACE_Thread_Manager::thread_all_list");
02039   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
02040 
02041   size_t thread_count = 0;
02042 
02043   for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
02044        !iter.done ();
02045        iter.advance ())
02046     {
02047       if (thread_count >= n)
02048         break;
02049 
02050       thread_list[thread_count] = iter.next ()->thr_id_;
02051       thread_count ++;
02052     }
02053 
02054   return thread_count;
02055 }
02056 
02057 // Returns in task_list a list of ACE_Tasks in a group.
02058 
02059 ssize_t
02060 ACE_Thread_Manager::task_list (int grp_id,
02061                                ACE_Task_Base *task_list[],
02062                                size_t n)
02063 {
02064   ACE_TRACE ("ACE_Thread_Manager::task_list");
02065   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
02066 
02067   ACE_Task_Base **task_list_iterator = task_list;
02068   size_t task_list_count = 0;
02069   size_t i = 0;
02070 
02071   for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
02072        !iter.done ();
02073        iter.advance ())
02074     {
02075       if (task_list_count >= n)
02076         break;
02077 
02078       if (iter.next ()->grp_id_ == grp_id
02079           && this->find_task (iter.next ()->task_, i) == 0)
02080         {
02081           task_list_iterator[task_list_count] = iter.next ()->task_;
02082           task_list_count++;
02083         }
02084 
02085       i++;
02086     }
02087 
02088   return task_list_count;
02089 }
02090 
02091 // Returns in thread_list a list of thread ids in an ACE_Task.
02092 
02093 ssize_t
02094 ACE_Thread_Manager::thread_list (ACE_Task_Base *task,
02095                                  ACE_thread_t thread_list[],
02096                                  size_t n)
02097 {
02098   ACE_TRACE ("ACE_Thread_Manager::thread_list");
02099   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
02100 
02101   size_t thread_count = 0;
02102 
02103   for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
02104        !iter.done ();
02105        iter.advance ())
02106     {
02107       if (thread_count >= n)
02108         break;
02109 
02110       if (iter.next ()->task_ == task)
02111         {
02112           thread_list[thread_count] = iter.next ()->thr_id_;
02113           thread_count++;
02114         }
02115     }
02116 
02117   return thread_count;
02118 }
02119 
02120 // Returns in thread_list a list of thread handles in an ACE_Task.
02121 
02122 ssize_t
02123 ACE_Thread_Manager::hthread_list (ACE_Task_Base *task,
02124                                   ACE_hthread_t hthread_list[],
02125                                   size_t n)
02126 {
02127   ACE_TRACE ("ACE_Thread_Manager::hthread_list");
02128   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
02129 
02130   size_t hthread_count = 0;
02131 
02132   for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
02133        !iter.done ();
02134        iter.advance ())
02135     {
02136       if (hthread_count >= n)
02137         break;
02138 
02139       if (iter.next ()->task_ == task)
02140         {
02141           hthread_list[hthread_count] = iter.next ()->thr_handle_;
02142           hthread_count++;
02143         }
02144     }
02145 
02146   return hthread_count;
02147 }
02148 
02149 ssize_t
02150 ACE_Thread_Manager::thread_grp_list (int grp_id,
02151                                      ACE_thread_t thread_list[],
02152                                      size_t n)
02153 {
02154   ACE_TRACE ("ACE_Thread_Manager::thread_grp_list");
02155   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
02156 
02157   size_t thread_count = 0;
02158 
02159   for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
02160        !iter.done ();
02161        iter.advance ())
02162     {
02163       if (thread_count >= n)
02164         break;
02165 
02166       if (iter.next ()->grp_id_ == grp_id)
02167         {
02168           thread_list[thread_count] = iter.next ()->thr_id_;
02169           thread_count++;
02170         }
02171     }
02172 
02173   return thread_count;
02174 }
02175 
02176 // Returns in thread_list a list of thread handles in an ACE_Task.
02177 
02178 ssize_t
02179 ACE_Thread_Manager::hthread_grp_list (int grp_id,
02180                                       ACE_hthread_t hthread_list[],
02181                                       size_t n)
02182 {
02183   ACE_TRACE ("ACE_Thread_Manager::hthread_grp_list");
02184   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
02185 
02186   size_t hthread_count = 0;
02187 
02188   for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
02189        !iter.done ();
02190        iter.advance ())
02191     {
02192       if (hthread_count >= n)
02193         break;
02194 
02195       if (iter.next ()->grp_id_ == grp_id)
02196         {
02197           hthread_list[hthread_count] = iter.next ()->thr_handle_;
02198           hthread_count++;
02199         }
02200     }
02201 
02202   return hthread_count;
02203 }
02204 
02205 int
02206 ACE_Thread_Manager::set_grp (ACE_Task_Base *task, int grp_id)
02207 {
02208   ACE_TRACE ("ACE_Thread_Manager::set_grp");
02209   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
02210 
02211   for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
02212        !iter.done ();
02213        iter.advance ())
02214     if (iter.next ()->task_ == task)
02215       iter.next ()->grp_id_ = grp_id;
02216 
02217   return 0;
02218 }
02219 
02220 int
02221 ACE_Thread_Manager::get_grp (ACE_Task_Base *task, int &grp_id)
02222 {
02223   ACE_TRACE ("ACE_Thread_Manager::get_grp");
02224   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
02225 
02226   ACE_FIND (this->find_task (task), ptr);
02227   grp_id = ptr->grp_id_;
02228   return 0;
02229 }
02230 
02231 #if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
02232 # if defined (ACE_THREAD_MANAGER_LACKS_STATICS)
02233 template class ACE_Singleton<ACE_Thread_Manager, ACE_SYNCH_MUTEX>;
02234 # endif /* defined (ACE_THREAD_MANAGER_LACKS_STATICS) */
02235 #  if defined (ACE_LACKS_AUTO_PTR) \
02236       || !(defined (ACE_HAS_STANDARD_CPP_LIBRARY) \
02237            && (ACE_HAS_STANDARD_CPP_LIBRARY != 0))
02238 template class ACE_Auto_Basic_Ptr<ACE_Thread_Descriptor>;
02239 #  endif  /* ACE_LACKS_AUTO_PTR */
02240 template class auto_ptr<ACE_Thread_Descriptor>;
02241 template class ACE_Double_Linked_List<ACE_Thread_Descriptor_Base>;
02242 template class ACE_Double_Linked_List_Iterator_Base<ACE_Thread_Descriptor_Base>;
02243 template class ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor_Base>;
02244 template class ACE_Double_Linked_List<ACE_Thread_Descriptor>;
02245 template class ACE_Double_Linked_List_Iterator_Base<ACE_Thread_Descriptor>;
02246 template class ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor>;
02247 template class ACE_Node<ACE_Thread_Descriptor*>;
02248 template class ACE_Unbounded_Queue<ACE_Thread_Descriptor*>;
02249 template class ACE_Unbounded_Queue_Iterator<ACE_Thread_Descriptor*>;
02250 template class ACE_Free_List<ACE_Thread_Descriptor>;
02251 template class ACE_Locked_Free_List<ACE_Thread_Descriptor, ACE_DEFAULT_THREAD_MANAGER_LOCK>;
02252 #elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
02253 #  if defined (ACE_THREAD_MANAGER_LACKS_STATICS)
02254 #    pragma instantiate ACE_Singleton<ACE_Thread_Manager, ACE_SYNCH_MUTEX>
02255 #   endif /* defined (ACE_THREAD_MANAGER_LACKS_STATICS) */
02256 
02257 #  if defined (ACE_LACKS_AUTO_PTR) \
02258       || !(defined (ACE_HAS_STANDARD_CPP_LIBRARY) \
02259            && (ACE_HAS_STANDARD_CPP_LIBRARY != 0))
02260 #    pragma instantiate ACE_Auto_Basic_Ptr<ACE_Thread_Descriptor>
02261 #  endif  /* ACE_LACKS_AUTO_PTR */
02262 #  pragma instantiate auto_ptr<ACE_Thread_Descriptor>
02263 #  pragma instantiate ACE_Double_Linked_List<ACE_Thread_Descriptor_Base>
02264 #  pragma instantiate ACE_Double_Linked_List_Iterator_Base<ACE_Thread_Descriptor_Base>
02265 #  pragma instantiate ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor_Base>
02266 #  pragma instantiate ACE_Double_Linked_List<ACE_Thread_Descriptor>
02267 #  pragma instantiate ACE_Double_Linked_List_Iterator_Base<ACE_Thread_Descriptor>
02268 #  pragma instantiate ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor>
02269 #  pragma instantiate ACE_Node<ACE_Thread_Descriptor*>
02270 #  pragma instantiate ACE_Unbounded_Queue<ACE_Thread_Descriptor*>
02271 #  pragma instantiate ACE_Unbounded_Queue_Iterator<ACE_Thread_Descriptor*>
02272 #  pragma instantiate ACE_Free_List<ACE_Thread_Descriptor>
02273 #  pragma instantiate ACE_Locked_Free_List<ACE_Thread_Descriptor, ACE_DEFAULT_THREAD_MANAGER_LOCK>
02274 #endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */

Generated on Mon Jun 16 11:21:46 2003 for ACE by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002