Thread_Manager.cpp

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

Generated on Sun Jan 27 12:05:41 2008 for ACE by doxygen 1.3.6