Thread_Manager.cpp

Go to the documentation of this file.
00001 // $Id: Thread_Manager.cpp 80826 2008-03-04 14:51:23Z wotte $
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 80826 2008-03-04 14:51:23Z wotte $")
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 bool ACE_Thread_Manager::delete_thr_mgr_ = false;
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, bool 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_HAS_VXTHREADS)
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_HAS_VXTHREADS */
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_ = true;
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_ = false;
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_ = false;
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                              const char** thr_name)
00555 {
00556   // First, threads created by Thread Manager should not be daemon threads.
00557   // Using assertion is probably a bit too strong.  However, it helps
00558   // finding this kind of error as early as possible.  Perhaps we can replace
00559   // assertion by returning error.
00560   ACE_ASSERT (ACE_BIT_DISABLED (flags, THR_DAEMON));
00561 
00562   // Create a new thread running <func>.  *Must* be called with the
00563   // <lock_> held...
00564   // Get a "new" Thread Descriptor from the freelist.
00565   auto_ptr<ACE_Thread_Descriptor> new_thr_desc (this->thread_desc_freelist_.remove ());
00566 
00567   // Reset thread descriptor status
00568   new_thr_desc->reset (this);
00569 
00570   ACE_Thread_Adapter *thread_args = 0;
00571 # if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS)
00572   ACE_NEW_RETURN (thread_args,
00573                   ACE_Thread_Adapter (func,
00574                                       args,
00575                                       (ACE_THR_C_FUNC) ACE_THREAD_ADAPTER_NAME,
00576                                       this,
00577                                       new_thr_desc.get (),
00578                                       ACE_OS_Object_Manager::seh_except_selector(),
00579                                       ACE_OS_Object_Manager::seh_except_handler()),
00580                   -1);
00581 # else
00582   ACE_NEW_RETURN (thread_args,
00583                   ACE_Thread_Adapter (func,
00584                                       args,
00585                                       (ACE_THR_C_FUNC) ACE_THREAD_ADAPTER_NAME,
00586                                       this,
00587                                       new_thr_desc.get ()),
00588                   -1);
00589 # endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */
00590   auto_ptr <ACE_Base_Thread_Adapter> auto_thread_args (static_cast<ACE_Base_Thread_Adapter *> (thread_args));
00591 
00592   ACE_TRACE ("ACE_Thread_Manager::spawn_i");
00593   ACE_hthread_t thr_handle;
00594 
00595   ACE_thread_t thr_id;
00596   if (t_id == 0)
00597     t_id = &thr_id;
00598 
00599   // Acquire the <sync_> lock to block the spawned thread from
00600   // removing this Thread Descriptor before it gets put into our
00601   // thread table.
00602   new_thr_desc->sync_->acquire ();
00603 
00604   int const result = ACE_Thread::spawn (func,
00605                                         args,
00606                                         flags,
00607                                         t_id,
00608                                         &thr_handle,
00609                                         priority,
00610                                         stack,
00611                                         stack_size,
00612                                         thread_args,
00613                                         thr_name);
00614 
00615   if (result != 0)
00616     {
00617       // _Don't_ clobber errno here!  result is either 0 or -1, and
00618       // ACE_OS::thr_create () already set errno!  D. Levine 28 Mar 1997
00619       // errno = result;
00620       ACE_Errno_Guard guard (errno);     // Lock release may smash errno
00621       new_thr_desc->sync_->release ();
00622       return -1;
00623     }
00624   auto_thread_args.release ();
00625 
00626 #if defined (ACE_HAS_WTHREADS)
00627   // Have to duplicate handle if client asks for it.
00628   // @@ How are thread handles implemented on AIX?  Do they
00629   // also need to be duplicated?
00630   if (t_handle != 0)
00631 # if defined (ACE_HAS_WINCE)
00632     *t_handle = thr_handle;
00633 # else  /* ! ACE_HAS_WINCE */
00634   (void) ::DuplicateHandle (::GetCurrentProcess (),
00635                             thr_handle,
00636                             ::GetCurrentProcess (),
00637                             t_handle,
00638                             0,
00639                             TRUE,
00640                             DUPLICATE_SAME_ACCESS);
00641 # endif /* ! ACE_HAS_WINCE */
00642 #else  /* ! ACE_HAS_WTHREADS */
00643   if (t_handle != 0)
00644     *t_handle = thr_handle;
00645 #endif /* ! ACE_HAS_WTHREADS */
00646 
00647   // append_thr also put the <new_thr_desc> into Thread_Manager's
00648   // double-linked list.  Only after this point, can we manipulate
00649   // double-linked list from a spawned thread's context.
00650   return this->append_thr (*t_id,
00651                            thr_handle,
00652                            ACE_THR_SPAWNED,
00653                            grp_id,
00654                            task,
00655                            flags,
00656                            new_thr_desc.release ());
00657 }
00658 
00659 int
00660 ACE_Thread_Manager::spawn (ACE_THR_FUNC func,
00661                            void *args,
00662                            long flags,
00663                            ACE_thread_t *t_id,
00664                            ACE_hthread_t *t_handle,
00665                            long priority,
00666                            int grp_id,
00667                            void *stack,
00668                            size_t stack_size,
00669                            const char** thr_name)
00670 {
00671   ACE_TRACE ("ACE_Thread_Manager::spawn");
00672 
00673   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
00674 
00675   if (grp_id == -1)
00676     grp_id = this->grp_id_++; // Increment the group id.
00677 
00678   if (priority != ACE_DEFAULT_THREAD_PRIORITY)
00679     ACE_CLR_BITS (flags, THR_INHERIT_SCHED);
00680 
00681   if (this->spawn_i (func,
00682                      args,
00683                      flags,
00684                      t_id,
00685                      t_handle,
00686                      priority,
00687                      grp_id,
00688                      stack,
00689                      stack_size,
00690                      0,
00691                      thr_name) == -1)
00692     return -1;
00693 
00694   return grp_id;
00695 }
00696 
00697 // Create N new threads running FUNC.
00698 
00699 int
00700 ACE_Thread_Manager::spawn_n (size_t n,
00701                              ACE_THR_FUNC func,
00702                              void *args,
00703                              long flags,
00704                              long priority,
00705                              int grp_id,
00706                              ACE_Task_Base *task,
00707                              ACE_hthread_t thread_handles[],
00708                              void *stack[],
00709                              size_t stack_size[],
00710                              const char* thr_name[])
00711 {
00712   ACE_TRACE ("ACE_Thread_Manager::spawn_n");
00713   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
00714 
00715   if (grp_id == -1)
00716     grp_id = this->grp_id_++; // Increment the group id.
00717 
00718   for (size_t i = 0; i < n; i++)
00719     {
00720       // @@ What should happen if this fails?! e.g., should we try to
00721       // cancel the other threads that we've already spawned or what?
00722       if (this->spawn_i (func,
00723                          args,
00724                          flags,
00725                          0,
00726                          thread_handles == 0 ? 0 : &thread_handles[i],
00727                          priority,
00728                          grp_id,
00729                          stack == 0 ? 0 : stack[i],
00730                          stack_size == 0 ? ACE_DEFAULT_THREAD_STACKSIZE : stack_size[i],
00731                          task,
00732                          thr_name == 0 ? 0 : &thr_name [i]) == -1)
00733         return -1;
00734     }
00735 
00736   return grp_id;
00737 }
00738 
00739 // Create N new threads running FUNC.
00740 
00741 int
00742 ACE_Thread_Manager::spawn_n (ACE_thread_t thread_ids[],
00743                              size_t n,
00744                              ACE_THR_FUNC func,
00745                              void *args,
00746                              long flags,
00747                              long priority,
00748                              int grp_id,
00749                              void *stack[],
00750                              size_t stack_size[],
00751                              ACE_hthread_t thread_handles[],
00752                              ACE_Task_Base *task,
00753                              const char* thr_name[])
00754 {
00755   ACE_TRACE ("ACE_Thread_Manager::spawn_n");
00756   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
00757 
00758   if (grp_id == -1)
00759     grp_id = this->grp_id_++; // Increment the group id.
00760 
00761   for (size_t i = 0; i < n; i++)
00762     {
00763       // @@ What should happen if this fails?! e.g., should we try to
00764       // cancel the other threads that we've already spawned or what?
00765       if (this->spawn_i (func,
00766                          args,
00767                          flags,
00768                          thread_ids == 0 ? 0 : &thread_ids[i],
00769                          thread_handles == 0 ? 0 : &thread_handles[i],
00770                          priority,
00771                          grp_id,
00772                          stack == 0 ? 0 : stack[i],
00773                          stack_size == 0 ? ACE_DEFAULT_THREAD_STACKSIZE : stack_size[i],
00774                          task,
00775                          thr_name == 0 ? 0 : &thr_name [i]) == -1)
00776         return -1;
00777     }
00778 
00779   return grp_id;
00780 }
00781 
00782 // Append a thread into the pool (does not check for duplicates).
00783 // Must be called with locks held.
00784 
00785 int
00786 ACE_Thread_Manager::append_thr (ACE_thread_t t_id,
00787                                 ACE_hthread_t t_handle,
00788                                 ACE_UINT32 thr_state,
00789                                 int grp_id,
00790                                 ACE_Task_Base *task,
00791                                 long flags,
00792                                 ACE_Thread_Descriptor *td)
00793 {
00794   ACE_TRACE ("ACE_Thread_Manager::append_thr");
00795   ACE_Thread_Descriptor *thr_desc = 0;
00796 
00797   if (td == 0)
00798     {
00799       ACE_NEW_RETURN (thr_desc,
00800                       ACE_Thread_Descriptor,
00801                       -1);
00802       thr_desc->tm_ = this;
00803       // Setup the Thread_Manager.
00804     }
00805   else
00806     thr_desc = td;
00807 
00808   thr_desc->thr_id_ = t_id;
00809   thr_desc->thr_handle_ = t_handle;
00810   thr_desc->grp_id_ = grp_id;
00811   thr_desc->task_ = task;
00812   thr_desc->flags_ = flags;
00813 
00814   this->thr_list_.insert_head (thr_desc);
00815   ACE_SET_BITS (thr_desc->thr_state_, thr_state);
00816   thr_desc->sync_->release ();
00817 
00818   return 0;
00819 }
00820 
00821 // Return the thread descriptor (indexed by ACE_hthread_t).
00822 
00823 ACE_Thread_Descriptor *
00824 ACE_Thread_Manager::find_hthread (ACE_hthread_t h_id)
00825 {
00826   for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
00827        !iter.done ();
00828        iter.advance ())
00829     if (ACE_OS::thr_cmp (iter.next ()->thr_handle_, h_id))
00830       return iter.next ();
00831 
00832   return 0;
00833 }
00834 
00835 // Locate the index in the table associated with <t_id>.  Must be
00836 // called with the lock held.
00837 
00838 ACE_Thread_Descriptor *
00839 ACE_Thread_Manager::find_thread (ACE_thread_t t_id)
00840 {
00841   ACE_TRACE ("ACE_Thread_Manager::find_thread");
00842 
00843   for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
00844        !iter.done ();
00845        iter.advance ())
00846     if (ACE_OS::thr_equal (iter.next ()->thr_id_, t_id))
00847       return iter.next ();
00848   return 0;
00849 }
00850 
00851 // Insert a thread into the pool (checks for duplicates and doesn't
00852 // allow them to be inserted twice).
00853 
00854 int
00855 ACE_Thread_Manager::insert_thr (ACE_thread_t t_id,
00856                                 ACE_hthread_t t_handle,
00857                                 int grp_id,
00858                                 long flags)
00859 {
00860   ACE_TRACE ("ACE_Thread_Manager::insert_thr");
00861   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
00862 
00863   // Check for duplicates and bail out if we're already registered...
00864   if (this->find_thread (t_id) != 0 )
00865     return -1;
00866 
00867   if (grp_id == -1)
00868     grp_id = this->grp_id_++;
00869 
00870   if (this->append_thr (t_id,
00871                         t_handle,
00872                         ACE_THR_SPAWNED,
00873                         grp_id,
00874                         0,
00875                         flags) == -1)
00876     return -1;
00877 
00878   return grp_id;
00879 }
00880 
00881 // Run the registered hooks when the thread exits.
00882 
00883 void
00884 ACE_Thread_Manager::run_thread_exit_hooks (int i)
00885 {
00886 #if 0 // currently unused!
00887   ACE_TRACE ("ACE_Thread_Manager::run_thread_exit_hooks");
00888 
00889   // @@ Currently, we have just one hook.  This should clearly be
00890   // generalized to support an arbitrary number of hooks.
00891 
00892   ACE_Thread_Descriptor *td = this->thread_desc_self ();
00893   if (td != 0 && td->cleanup_info.cleanup_hook_ != 0)
00894     {
00895       (*td->cleanup_info_.cleanup_hook_)
00896         (td->cleanup_info_.object_,
00897          td->cleanup_info_.param_);
00898 
00899       td->cleanup_info_.cleanup_hook_ = 0;
00900     }
00901   ACE_UNUSED_ARG (i);
00902 #else
00903   ACE_UNUSED_ARG (i);
00904 #endif /* 0 */
00905 }
00906 
00907 // Remove a thread from the pool.  Must be called with locks held.
00908 
00909 void
00910 ACE_Thread_Manager::remove_thr (ACE_Thread_Descriptor *td,
00911                                 int close_handler)
00912 {
00913   ACE_TRACE ("ACE_Thread_Manager::remove_thr");
00914 
00915   td->tm_ = 0;
00916   this->thr_list_.remove (td);
00917 
00918 #if defined (ACE_WIN32)
00919   if (close_handler != 0)
00920     ::CloseHandle (td->thr_handle_);
00921 #else
00922   ACE_UNUSED_ARG (close_handler);
00923 #endif /* ACE_WIN32 */
00924 
00925   this->thread_desc_freelist_.add (td);
00926 
00927 #if defined (ACE_HAS_THREADS)
00928   // Tell all waiters when there are no more threads left in the pool.
00929   if (this->thr_list_.size () == 0)
00930     this->zero_cond_.broadcast ();
00931 #endif /* ACE_HAS_THREADS */
00932 }
00933 
00934 // Repeatedly call remove_thr on all table entries until there
00935 // is no thread left.   Must be called with lock held.
00936 void
00937 ACE_Thread_Manager::remove_thr_all (void)
00938 {
00939   ACE_Thread_Descriptor *td = 0;
00940 
00941   while ((td = this->thr_list_.delete_head ()) != 0)
00942     {
00943       this->remove_thr (td, 1);
00944     }
00945 }
00946 
00947 // ------------------------------------------------------------------
00948 // Factor out some common behavior to simplify the following methods.
00949 #define ACE_THR_OP(OP,STATE) \
00950   int result = OP (td->thr_handle_); \
00951   if (result == -1) { \
00952     if (errno != ENOTSUP) \
00953       this->thr_to_be_removed_.enqueue_tail (td); \
00954     return -1; \
00955   } \
00956   else { \
00957     ACE_SET_BITS (td->thr_state_, STATE); \
00958     return 0; \
00959   }
00960 
00961 int
00962 ACE_Thread_Manager::join_thr (ACE_Thread_Descriptor *td, int)
00963 {
00964   ACE_TRACE ("ACE_Thread_Manager::join_thr");
00965   int const result = ACE_Thread::join (td->thr_handle_);
00966   if (result != 0)
00967     {
00968       // Since the thread are being joined, we should
00969       // let it remove itself from the list.
00970 
00971       //      this->remove_thr (td);
00972       errno = result;
00973       return -1;
00974     }
00975 
00976   return 0;
00977 }
00978 
00979 int
00980 ACE_Thread_Manager::suspend_thr (ACE_Thread_Descriptor *td, int)
00981 {
00982   ACE_TRACE ("ACE_Thread_Manager::suspend_thr");
00983 
00984   int const result = ACE_Thread::suspend (td->thr_handle_);
00985   if (result == -1) {
00986     if (errno != ENOTSUP)
00987       this->thr_to_be_removed_.enqueue_tail (td);
00988     return -1;
00989   }
00990   else {
00991     ACE_SET_BITS (td->thr_state_, ACE_THR_SUSPENDED);
00992     return 0;
00993   }
00994 }
00995 
00996 int
00997 ACE_Thread_Manager::resume_thr (ACE_Thread_Descriptor *td, int)
00998 {
00999   ACE_TRACE ("ACE_Thread_Manager::resume_thr");
01000 
01001   int const result = ACE_Thread::resume (td->thr_handle_);
01002   if (result == -1) {
01003     if (errno != ENOTSUP)
01004       this->thr_to_be_removed_.enqueue_tail (td);
01005     return -1;
01006   }
01007   else {
01008     ACE_CLR_BITS (td->thr_state_, ACE_THR_SUSPENDED);
01009     return 0;
01010   }
01011 }
01012 
01013 int
01014 ACE_Thread_Manager::cancel_thr (ACE_Thread_Descriptor *td, int async_cancel)
01015 {
01016   ACE_TRACE ("ACE_Thread_Manager::cancel_thr");
01017   // Must set the state first and then try to cancel the thread.
01018   ACE_SET_BITS (td->thr_state_, ACE_THR_CANCELLED);
01019 
01020   if (async_cancel != 0)
01021     // Note that this call only does something relevant if the OS
01022     // platform supports asynchronous thread cancellation.  Otherwise,
01023     // it's a no-op.
01024     return ACE_Thread::cancel (td->thr_id_);
01025 
01026   return 0;
01027 }
01028 
01029 int
01030 ACE_Thread_Manager::kill_thr (ACE_Thread_Descriptor *td, int signum)
01031 {
01032   ACE_TRACE ("ACE_Thread_Manager::kill_thr");
01033 
01034   ACE_thread_t tid = td->thr_id_;
01035 
01036   int const result = ACE_Thread::kill (tid, signum);
01037 
01038   if (result != 0)
01039     {
01040       // Only remove a thread from us when there is a "real" error.
01041       if (errno != ENOTSUP)
01042         this->thr_to_be_removed_.enqueue_tail (td);
01043 
01044       return -1;
01045     }
01046 
01047     return 0;
01048 }
01049 
01050 // ------------------------------------------------------------------
01051 // Factor out some common behavior to simplify the following methods.
01052 #define ACE_EXECUTE_OP(OP, ARG) \
01053   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1)); \
01054   ACE_ASSERT (this->thr_to_be_removed_.is_empty ()); \
01055   ACE_FIND (this->find_thread (t_id), ptr); \
01056   if (ptr == 0) \
01057     { \
01058       errno = ENOENT; \
01059       return -1; \
01060     } \
01061   int result = OP (ptr, ARG); \
01062   ACE_Errno_Guard error (errno); \
01063   while (! this->thr_to_be_removed_.is_empty ()) { \
01064     ACE_Thread_Descriptor * td = 0; \
01065     this->thr_to_be_removed_.dequeue_head (td); \
01066     this->remove_thr (td, 1); \
01067   } \
01068   return result
01069 
01070 // Suspend a single thread.
01071 
01072 int
01073 ACE_Thread_Manager::suspend (ACE_thread_t t_id)
01074 {
01075   ACE_TRACE ("ACE_Thread_Manager::suspend");
01076   ACE_EXECUTE_OP (this->suspend_thr, 0);
01077 }
01078 
01079 // Resume a single thread.
01080 
01081 int
01082 ACE_Thread_Manager::resume (ACE_thread_t t_id)
01083 {
01084   ACE_TRACE ("ACE_Thread_Manager::resume");
01085   ACE_EXECUTE_OP (this->resume_thr, 0);
01086 }
01087 
01088 // Cancel a single thread.
01089 
01090 int
01091 ACE_Thread_Manager::cancel (ACE_thread_t t_id, int async_cancel)
01092 {
01093   ACE_TRACE ("ACE_Thread_Manager::cancel");
01094   ACE_EXECUTE_OP (this->cancel_thr, async_cancel);
01095 }
01096 
01097 // Send a signal to a single thread.
01098 
01099 int
01100 ACE_Thread_Manager::kill (ACE_thread_t t_id, int signum)
01101 {
01102   ACE_TRACE ("ACE_Thread_Manager::kill");
01103   ACE_EXECUTE_OP (this->kill_thr, signum);
01104 }
01105 
01106 int
01107 ACE_Thread_Manager::check_state (ACE_UINT32 state,
01108                                  ACE_thread_t id,
01109                                  int enable)
01110 {
01111   ACE_TRACE ("ACE_Thread_Manager::check_state");
01112   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
01113 
01114   ACE_UINT32 thr_state;
01115 
01116   int self_check = ACE_OS::thr_equal (id, ACE_OS::thr_self ());
01117 
01118   // If we're checking the state of our thread, try to get the cached
01119   // value out of TSS to avoid lookup.
01120   if (self_check)
01121     {
01122       ACE_Thread_Descriptor *desc = ACE_LOG_MSG->thr_desc ();
01123       if (desc == 0)
01124         return 0;               // Always return false.
01125       thr_state = desc->thr_state_;
01126     }
01127   else
01128     {
01129       // Not calling from self, have to look it up from the list.
01130       ACE_FIND (this->find_thread (id), ptr);
01131       if (ptr == 0)
01132         return 0;
01133       thr_state = ptr->thr_state_;
01134     }
01135   if (enable)
01136     return ACE_BIT_ENABLED (thr_state, state);
01137 
01138   return ACE_BIT_DISABLED (thr_state, state);
01139 }
01140 
01141 // Test if a single thread has terminated.
01142 
01143 int
01144 ACE_Thread_Manager::testterminate (ACE_thread_t t_id)
01145 {
01146   ACE_TRACE ("ACE_Thread_Manager::testterminate");
01147   return this->check_state (ACE_THR_TERMINATED, t_id);
01148 }
01149 
01150 // Test if a single thread is suspended.
01151 
01152 int
01153 ACE_Thread_Manager::testsuspend (ACE_thread_t t_id)
01154 {
01155   ACE_TRACE ("ACE_Thread_Manager::testsuspend");
01156   return this->check_state (ACE_THR_SUSPENDED, t_id);
01157 }
01158 
01159 // Test if a single thread is active (i.e., resumed).
01160 
01161 int
01162 ACE_Thread_Manager::testresume (ACE_thread_t t_id)
01163 {
01164   ACE_TRACE ("ACE_Thread_Manager::testresume");
01165   return this->check_state (ACE_THR_SUSPENDED, t_id, 0);
01166 }
01167 
01168 // Test if a single thread is cancelled.
01169 
01170 int
01171 ACE_Thread_Manager::testcancel (ACE_thread_t t_id)
01172 {
01173   ACE_TRACE ("ACE_Thread_Manager::testcancel");
01174   return this->check_state (ACE_THR_CANCELLED, t_id);
01175 }
01176 
01177 // Thread information query functions.
01178 
01179 int
01180 ACE_Thread_Manager::hthread_within (ACE_hthread_t handle)
01181 {
01182   ACE_TRACE ("ACE_Thread_Manager::hthread_within");
01183   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_monx, this->lock_, -1));
01184 
01185   for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
01186        !iter.done ();
01187        iter.advance ())
01188     if (ACE_OS::thr_cmp(iter.next ()->thr_handle_, handle))
01189       return 1;
01190 
01191   return 0;
01192 }
01193 
01194 int
01195 ACE_Thread_Manager::thread_within (ACE_thread_t tid)
01196 {
01197   ACE_TRACE ("ACE_Thread_Manager::thread_within");
01198   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_monx, this->lock_, -1));
01199 
01200   for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
01201        !iter.done ();
01202        iter.advance ())
01203     if (ACE_OS::thr_equal (iter.next ()->thr_id_, tid))
01204       return 1;
01205 
01206   return 0;
01207 }
01208 
01209 // Get group ids for a particular thread id.
01210 
01211 int
01212 ACE_Thread_Manager::get_grp (ACE_thread_t t_id, int &grp_id)
01213 {
01214   ACE_TRACE ("ACE_Thread_Manager::get_grp");
01215   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
01216 
01217   ACE_FIND (this->find_thread (t_id), ptr);
01218 
01219   if (ptr)
01220     grp_id = ptr->grp_id_;
01221   else
01222     return -1;
01223   return 0;
01224 }
01225 
01226 // Set group ids for a particular thread id.
01227 
01228 int
01229 ACE_Thread_Manager::set_grp (ACE_thread_t t_id, int grp_id)
01230 {
01231   ACE_TRACE ("ACE_Thread_Manager::set_grp");
01232   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
01233 
01234   ACE_FIND (this->find_thread (t_id), ptr);
01235   if (ptr)
01236     ptr->grp_id_ = grp_id;
01237   else
01238     return -1;
01239   return 0;
01240 }
01241 
01242 // Suspend a group of threads.
01243 
01244 int
01245 ACE_Thread_Manager::apply_grp (int grp_id,
01246                                ACE_THR_MEMBER_FUNC func,
01247                                int arg)
01248 {
01249   ACE_TRACE ("ACE_Thread_Manager::apply_grp");
01250   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_monx, this->lock_, -1));
01251   ACE_ASSERT (this->thr_to_be_removed_.is_empty ());
01252 
01253   int result = 0;
01254 
01255   for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
01256        !iter.done ();
01257        iter.advance ())
01258     if (iter.next ()->grp_id_ == grp_id)
01259       if ((this->*func) (iter.next (), arg) == -1)
01260         result = -1;
01261 
01262   // Must remove threads after we have traversed the thr_list_ to
01263   // prevent clobber thr_list_'s integrity.
01264 
01265   if (! this->thr_to_be_removed_.is_empty ())
01266     {
01267       // Save/restore errno.
01268       ACE_Errno_Guard error (errno);
01269 
01270       for (ACE_Thread_Descriptor *td;
01271            this->thr_to_be_removed_.dequeue_head (td) != -1;
01272            )
01273         this->remove_thr (td, 1);
01274     }
01275 
01276   return result;
01277 }
01278 
01279 int
01280 ACE_Thread_Manager::suspend_grp (int grp_id)
01281 {
01282   ACE_TRACE ("ACE_Thread_Manager::suspend_grp");
01283   return this->apply_grp (grp_id,
01284                           ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::suspend_thr));
01285 }
01286 
01287 // Resume a group of threads.
01288 
01289 int
01290 ACE_Thread_Manager::resume_grp (int grp_id)
01291 {
01292   ACE_TRACE ("ACE_Thread_Manager::resume_grp");
01293   return this->apply_grp (grp_id,
01294                           ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::resume_thr));
01295 }
01296 
01297 // Kill a group of threads.
01298 
01299 int
01300 ACE_Thread_Manager::kill_grp (int grp_id, int signum)
01301 {
01302   ACE_TRACE ("ACE_Thread_Manager::kill_grp");
01303   return this->apply_grp (grp_id,
01304                           ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::kill_thr), signum);
01305 }
01306 
01307 // Cancel a group of threads.
01308 
01309 int
01310 ACE_Thread_Manager::cancel_grp (int grp_id, int async_cancel)
01311 {
01312   ACE_TRACE ("ACE_Thread_Manager::cancel_grp");
01313   return this->apply_grp (grp_id,
01314                           ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::cancel_thr),
01315                           async_cancel);
01316 }
01317 
01318 int
01319 ACE_Thread_Manager::apply_all (ACE_THR_MEMBER_FUNC func, int arg)
01320 {
01321   ACE_TRACE ("ACE_Thread_Manager::apply_all");
01322   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
01323   ACE_ASSERT (this->thr_to_be_removed_.is_empty ());
01324 
01325   int result = 0;
01326 
01327   for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
01328        !iter.done ();
01329        iter.advance ())
01330     if ((this->*func)(iter.next (), arg) == -1)
01331       result = -1;
01332 
01333   // Must remove threads after we have traversed the thr_list_ to
01334   // prevent clobber thr_list_'s integrity.
01335 
01336   if (! this->thr_to_be_removed_.is_empty ())
01337     {
01338       // Save/restore errno.
01339       ACE_Errno_Guard error (errno);
01340 
01341       for (ACE_Thread_Descriptor *td;
01342            this->thr_to_be_removed_.dequeue_head (td) != -1;
01343            )
01344         this->remove_thr (td, 1);
01345     }
01346 
01347   return result;
01348 }
01349 
01350 // Resume all threads that are suspended.
01351 
01352 int
01353 ACE_Thread_Manager::resume_all (void)
01354 {
01355   ACE_TRACE ("ACE_Thread_Manager::resume_all");
01356   return this->apply_all (ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::resume_thr));
01357 }
01358 
01359 int
01360 ACE_Thread_Manager::suspend_all (void)
01361 {
01362   ACE_TRACE ("ACE_Thread_Manager::suspend_all");
01363   return this->apply_all (ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::suspend_thr));
01364 }
01365 
01366 int
01367 ACE_Thread_Manager::kill_all (int sig)
01368 {
01369   ACE_TRACE ("ACE_Thread_Manager::kill_all");
01370   return this->apply_all (&ACE_Thread_Manager::kill_thr, sig);
01371 }
01372 
01373 int
01374 ACE_Thread_Manager::cancel_all (int async_cancel)
01375 {
01376   ACE_TRACE ("ACE_Thread_Manager::cancel_all");
01377   return this->apply_all (ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::cancel_thr),
01378                           async_cancel);
01379 }
01380 
01381 int
01382 ACE_Thread_Manager::join (ACE_thread_t tid, ACE_THR_FUNC_RETURN *status)
01383 {
01384   ACE_TRACE ("ACE_Thread_Manager::join");
01385 
01386   ACE_Thread_Descriptor_Base tdb;
01387   int found = 0;
01388 
01389   {
01390     ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
01391 
01392 #if !defined (ACE_HAS_VXTHREADS)
01393     for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor_Base> biter (this->terminated_thr_list_);
01394          !biter.done ();
01395          biter.advance ())
01396       if (ACE_OS::thr_equal (biter.next ()->thr_id_, tid))
01397         {
01398           ACE_Thread_Descriptor_Base *tdb = biter.advance_and_remove (0);
01399 # if defined (_AIX)
01400   // The AIX xlC compiler does not match the proper function here - it
01401   // confuses ACE_Thread::join(ACE_thread_t, ACE_thread_t *, void **=0) and
01402   // ACE_Thread::join(ACE_hthread_t, void **=0).  At least at 3.1.4.7 and .8.
01403   // The 2nd arg is ignored for pthreads anyway.
01404 
01405   // And, g++ on AIX needs the three-arg thr_join, also, to pick up the
01406   // proper version from the AIX libraries.
01407           if (ACE_Thread::join (tdb->thr_handle_,
01408                                 &tdb->thr_handle_,
01409                                 status) == -1)
01410 # else  /* ! _AIX */
01411           if (ACE_Thread::join (tdb->thr_handle_, status) == -1)
01412 # endif /* ! _AIX */
01413             return -1;
01414 
01415           delete tdb;
01416           return 0;
01417           // return immediately if we've found the thread we want to join.
01418         }
01419 #endif /* !ACE_HAS_VXTHREADS */
01420 
01421     for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
01422          !iter.done ();
01423          iter.advance ())
01424       // If threads are created as THR_DETACHED or THR_DAEMON, we
01425       // can't help much.
01426       if (ACE_OS::thr_equal (iter.next ()->thr_id_,tid) &&
01427           (ACE_BIT_DISABLED (iter.next ()->flags_, THR_DETACHED | THR_DAEMON)
01428            || ACE_BIT_ENABLED (iter.next ()->flags_, THR_JOINABLE)))
01429         {
01430           tdb = *iter.next ();
01431           ACE_SET_BITS (iter.next ()->thr_state_, ACE_THR_JOINING);
01432           found = 1;
01433           break;
01434         }
01435 
01436     if (found == 0)
01437       return -1;
01438     // Didn't find the thread we want or the thread is not joinable.
01439   }
01440 
01441 # if defined (_AIX)
01442   // The AIX xlC compiler does not match the proper function here - it
01443   // confuses ACE_Thread::join(ACE_thread_t, ACE_thread_t *, void **=0) and
01444   // ACE_Thread::join(ACE_hthread_t, void **=0).  At least at 3.1.4.7 and .8.
01445   // The 2nd arg is ignored for pthreads anyway.
01446 
01447   // And, g++ on AIX needs the three-arg thr_join, also, to pick up the
01448   // proper version from the AIX libraries.
01449   if (ACE_Thread::join (tdb.thr_handle_, &tdb.thr_handle_, status) == -1)
01450 # else  /* ! _AIX */
01451   if (ACE_Thread::join (tdb.thr_handle_, status) == -1)
01452 # endif /* ! _AIX */
01453     return -1;
01454 
01455   return 0;
01456 }
01457 
01458 // Wait for group of threads
01459 
01460 int
01461 ACE_Thread_Manager::wait_grp (int grp_id)
01462 {
01463   ACE_TRACE ("ACE_Thread_Manager::wait_grp");
01464 
01465   int copy_count = 0;
01466   ACE_Thread_Descriptor_Base *copy_table = 0;
01467 
01468   // We have to make sure that while we wait for these threads to
01469   // exit, we do not have the lock.  Therefore we make a copy of all
01470   // interesting entries and let go of the lock.
01471   {
01472     ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
01473 
01474 #if !defined (ACE_HAS_VXTHREADS)
01475     ACE_NEW_RETURN (copy_table,
01476                     ACE_Thread_Descriptor_Base [this->thr_list_.size ()
01477                                                + this->terminated_thr_list_.size ()],
01478                     -1);
01479 #else
01480     ACE_NEW_RETURN (copy_table,
01481                     ACE_Thread_Descriptor_Base [this->thr_list_.size ()],
01482                     -1);
01483 #endif /* !ACE_HAS_VXTHREADS */
01484 
01485     for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
01486          !iter.done ();
01487          iter.advance ())
01488       // If threads are created as THR_DETACHED or THR_DAEMON, we
01489       // can't help much.
01490       if (iter.next ()->grp_id_ == grp_id &&
01491           (ACE_BIT_DISABLED (iter.next ()->flags_, THR_DETACHED | THR_DAEMON)
01492            || ACE_BIT_ENABLED (iter.next ()->flags_, THR_JOINABLE)))
01493         {
01494           ACE_SET_BITS (iter.next ()->thr_state_, ACE_THR_JOINING);
01495           copy_table[copy_count++] = *iter.next ();
01496         }
01497 
01498 #if !defined (ACE_HAS_VXTHREADS)
01499     for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor_Base> biter (this->terminated_thr_list_);
01500          !biter.done ();
01501          biter.advance ())
01502       // If threads are created as THR_DETACHED or THR_DAEMON, we
01503       // can't help much.
01504       if (biter.next ()->grp_id_ == grp_id)
01505         {
01506           ACE_Thread_Descriptor_Base *tdb = biter.advance_and_remove (0);
01507           copy_table[copy_count++] = *tdb;
01508           delete tdb;
01509         }
01510 #endif /* !ACE_HAS_VXTHREADS */
01511   }
01512 
01513   // Now actually join() with all the threads in this group.
01514   int result = 0;
01515 
01516   for (int i = 0;
01517        i < copy_count && result != -1;
01518        i++)
01519     {
01520       if (ACE_Thread::join (copy_table[i].thr_handle_) == -1)
01521         result = -1;
01522     }
01523 
01524   delete [] copy_table;
01525 
01526   return result;
01527 }
01528 
01529 // Must be called when thread goes out of scope to clean up its table
01530 // slot.
01531 
01532 ACE_THR_FUNC_RETURN
01533 ACE_Thread_Manager::exit (ACE_THR_FUNC_RETURN status, bool do_thread_exit)
01534 {
01535   ACE_TRACE ("ACE_Thread_Manager::exit");
01536 #if defined (ACE_WIN32)
01537   // Remove detached thread handle.
01538 
01539   if (do_thread_exit)
01540     {
01541 #if 0
01542       // @@ This callback is now taken care of by TSS_Cleanup.  Do we
01543       //    need it anymore?
01544 
01545       // On Win32, if we really wants to exit from a thread, we must
01546       // first  clean up the thread specific storage.  By doing so,
01547       // ACE_Thread_Manager::exit will be called again with
01548       // do_thr_exit = 0 and cleaning up the ACE_Cleanup_Info (but not
01549       // exiting the thread.)  After the following call returns, we
01550       // are safe to exit this thread.
01551       delete ACE_Thread_Exit::instance ();
01552 #endif /* 0 */
01553       ACE_Thread::exit (status);
01554     }
01555 #endif /* ACE_WIN32 */
01556 
01557   // Just hold onto the guard while finding this thread's id and
01558   {
01559     ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0));
01560 
01561     // Find the thread id, but don't use the cache.  It might have been
01562     // deleted already.
01563     ACE_thread_t const id = ACE_OS::thr_self ();
01564     ACE_Thread_Descriptor* td = this->find_thread (id);
01565     if (td != 0)
01566      {
01567        // @@ We call Thread_Descriptor terminate this realize the cleanup
01568        // process itself.
01569        td->terminate();
01570      }
01571   }
01572 
01573   if (do_thread_exit)
01574     {
01575       ACE_Thread::exit (status);
01576       // On reasonable systems <ACE_Thread::exit> should not return.
01577       // However, due to horrible semantics with Win32 thread-specific
01578       // storage this call can return (don't ask...).
01579     }
01580 
01581   return 0;
01582 }
01583 
01584 // Wait for all the threads to exit.
01585 
01586 int
01587 ACE_Thread_Manager::wait (const ACE_Time_Value *timeout,
01588                           bool abandon_detached_threads,
01589                           bool use_absolute_time)
01590 {
01591   ACE_TRACE ("ACE_Thread_Manager::wait");
01592 
01593   ACE_Time_Value local_timeout;
01594   // Check to see if we're using absolute time or not.
01595   if (use_absolute_time == false && timeout != 0)
01596     {
01597       local_timeout = *timeout;
01598       local_timeout += ACE_OS::gettimeofday ();
01599       timeout = &local_timeout;
01600     }
01601 
01602 #if !defined (ACE_HAS_VXTHREADS)
01603   ACE_Double_Linked_List<ACE_Thread_Descriptor_Base> term_thr_list_copy;
01604 #endif /* ACE_HAS_VXTHREADS */
01605 
01606 #if defined (ACE_HAS_THREADS)
01607   {
01608     // Just hold onto the guard while waiting.
01609     ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
01610 
01611     if (ACE_Object_Manager::shutting_down () != 1)
01612       {
01613         // Program is not shutting down.  Perform a normal wait on threads.
01614         if (abandon_detached_threads != 0)
01615           {
01616             ACE_ASSERT (this->thr_to_be_removed_.is_empty ());
01617             for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor>
01618                    iter (this->thr_list_);
01619                  !iter.done ();
01620                  iter.advance ())
01621               if (ACE_BIT_ENABLED (iter.next ()->flags_,
01622                                    THR_DETACHED | THR_DAEMON)
01623                   && ACE_BIT_DISABLED (iter.next ()->flags_, THR_JOINABLE))
01624                 {
01625                   this->thr_to_be_removed_.enqueue_tail (iter.next ());
01626                   ACE_SET_BITS (iter.next ()->thr_state_, ACE_THR_JOINING);
01627                 }
01628 
01629             if (! this->thr_to_be_removed_.is_empty ())
01630               {
01631                 ACE_Thread_Descriptor *td = 0;
01632                 while (this->thr_to_be_removed_.dequeue_head (td) != -1)
01633                   this->remove_thr (td, 1);
01634               }
01635           }
01636 
01637         while (this->thr_list_.size () > 0)
01638           if (this->zero_cond_.wait (timeout) == -1)
01639             return -1;
01640       }
01641     else
01642         // Program is shutting down, no chance to wait on threads.
01643         // Therefore, we'll just remove threads from the list.
01644         this->remove_thr_all ();
01645 
01646 #if !defined (ACE_HAS_VXTHREADS)
01647   ACE_Thread_Descriptor_Base* item = 0;
01648   while ((item = this->terminated_thr_list_.delete_head ()) != 0)
01649     {
01650       term_thr_list_copy.insert_tail (item);
01651     }
01652 #endif /* ACE_HAS_VXTHREADS */
01653     // Release the guard, giving other threads a chance to run.
01654   }
01655 
01656 #if !defined (ACE_HAS_VXTHREADS)
01657     // @@ VxWorks doesn't support thr_join (yet.)  We are working
01658     // on our implementation.   Chorus'es thr_join seems broken.
01659     ACE_Thread_Descriptor_Base *item = 0;
01660 
01661     while ((item = term_thr_list_copy.delete_head ()) != 0)
01662       {
01663         if (ACE_BIT_DISABLED (item->flags_, THR_DETACHED | THR_DAEMON)
01664             || ACE_BIT_ENABLED (item->flags_, THR_JOINABLE))
01665           // Detached handles shouldn't reached here.
01666           (void) ACE_Thread::join (item->thr_handle_);
01667 
01668         delete item;
01669       }
01670 
01671 #endif /* !ACE_HAS_VXTHREADS */
01672 #else
01673   ACE_UNUSED_ARG (timeout);
01674   ACE_UNUSED_ARG (abandon_detached_threads);
01675 #endif /* ACE_HAS_THREADS */
01676 
01677   return 0;
01678 }
01679 
01680 int
01681 ACE_Thread_Manager::apply_task (ACE_Task_Base *task,
01682                                 ACE_THR_MEMBER_FUNC func,
01683                                 int arg)
01684 {
01685   ACE_TRACE ("ACE_Thread_Manager::apply_task");
01686   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
01687   ACE_ASSERT (this->thr_to_be_removed_.is_empty ());
01688 
01689   int result = 0;
01690 
01691   for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
01692        !iter.done ();
01693        iter.advance ())
01694     if (iter.next ()->task_ == task
01695         && (this->*func) (iter.next (), arg) == -1)
01696       result = -1;
01697 
01698   // Must remove threads after we have traversed the thr_list_ to
01699   // prevent clobber thr_list_'s integrity.
01700 
01701   if (! this->thr_to_be_removed_.is_empty ())
01702     {
01703       // Save/restore errno.
01704       ACE_Errno_Guard error (errno);
01705 
01706       for (ACE_Thread_Descriptor *td;
01707            this->thr_to_be_removed_.dequeue_head (td) != -1;
01708            )
01709         this->remove_thr (td, 1);
01710     }
01711 
01712   return result;
01713 }
01714 
01715 // Wait for all threads to exit a task.
01716 
01717 int
01718 ACE_Thread_Manager::wait_task (ACE_Task_Base *task)
01719 {
01720   int copy_count = 0;
01721   ACE_Thread_Descriptor_Base *copy_table = 0;
01722 
01723   // We have to make sure that while we wait for these threads to
01724   // exit, we do not have the lock.  Therefore we make a copy of all
01725   // interesting entries and let go of the lock.
01726   {
01727     ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
01728 
01729 #if !defined (ACE_HAS_VXTHREADS)
01730     ACE_NEW_RETURN (copy_table,
01731                     ACE_Thread_Descriptor_Base [this->thr_list_.size ()
01732                                                 + this->terminated_thr_list_.size ()],
01733                     -1);
01734 #else
01735     ACE_NEW_RETURN (copy_table,
01736                     ACE_Thread_Descriptor_Base [this->thr_list_.size ()],
01737                     -1);
01738 #endif /* !ACE_HAS_VXTHREADS */
01739 
01740     for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
01741          !iter.done ();
01742          iter.advance ())
01743       // If threads are created as THR_DETACHED or THR_DAEMON, we
01744       // can't wait on them here.
01745       if (iter.next ()->task_ == task &&
01746           (ACE_BIT_DISABLED (iter.next ()->flags_,
01747                              THR_DETACHED | THR_DAEMON)
01748            || ACE_BIT_ENABLED (iter.next ()->flags_,
01749                                THR_JOINABLE)))
01750         {
01751           ACE_SET_BITS (iter.next ()->thr_state_,
01752                         ACE_THR_JOINING);
01753           copy_table[copy_count++] = *iter.next ();
01754         }
01755 
01756 #if !defined (ACE_HAS_VXTHREADS)
01757     for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor_Base> titer (this->terminated_thr_list_);
01758          !titer.done ();
01759          titer.advance ())
01760       // If threads are created as THR_DETACHED or THR_DAEMON, we can't help much here.
01761       if (titer.next ()->task_ == task)
01762         {
01763           ACE_Thread_Descriptor_Base *tdb =
01764             titer.advance_and_remove (0);
01765           copy_table[copy_count++] = *tdb;
01766           delete tdb;
01767         }
01768 #endif /* !ACE_HAS_VXTHREADS */
01769   }
01770 
01771   // Now to do the actual work
01772   int result = 0;
01773 
01774   for (int i = 0;
01775        i < copy_count && result != -1;
01776        i++)
01777     {
01778       if (ACE_Thread::join (copy_table[i].thr_handle_) == -1)
01779         result = -1;
01780     }
01781 
01782   delete [] copy_table;
01783 
01784   return result;
01785 }
01786 
01787 // Suspend a task
01788 
01789 int
01790 ACE_Thread_Manager::suspend_task (ACE_Task_Base *task)
01791 {
01792   ACE_TRACE ("ACE_Thread_Manager::suspend_task");
01793   return this->apply_task (task,
01794                            ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::suspend_thr));
01795 }
01796 
01797 // Resume a task.
01798 int
01799 ACE_Thread_Manager::resume_task (ACE_Task_Base *task)
01800 {
01801   ACE_TRACE ("ACE_Thread_Manager::resume_task");
01802   return this->apply_task (task,
01803                            ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::resume_thr));
01804 }
01805 
01806 // Kill a task.
01807 
01808 int
01809 ACE_Thread_Manager::kill_task (ACE_Task_Base *task, int /* signum */)
01810 {
01811   ACE_TRACE ("ACE_Thread_Manager::kill_task");
01812   return this->apply_task (task,
01813                            ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::kill_thr));
01814 }
01815 
01816 // Cancel a task.
01817 int
01818 ACE_Thread_Manager::cancel_task (ACE_Task_Base *task,
01819                                  int async_cancel)
01820 {
01821   ACE_TRACE ("ACE_Thread_Manager::cancel_task");
01822   return this->apply_task (task,
01823                            ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::cancel_thr),
01824                            async_cancel);
01825 }
01826 
01827 // Locate the index in the table associated with <task> from the
01828 // beginning of the table up to an index.  Must be called with the
01829 // lock held.
01830 
01831 ACE_Thread_Descriptor *
01832 ACE_Thread_Manager::find_task (ACE_Task_Base *task, size_t slot)
01833 {
01834   ACE_TRACE ("ACE_Thread_Manager::find_task");
01835 
01836   size_t i = 0;
01837 
01838   for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
01839        !iter.done ();
01840        iter.advance ())
01841     {
01842       if (i >= slot)
01843         break;
01844 
01845       if (task == iter.next ()->task_)
01846         return iter.next ();
01847 
01848       ++i;
01849     }
01850 
01851   return 0;
01852 }
01853 
01854 // Returns the number of ACE_Task in a group.
01855 
01856 int
01857 ACE_Thread_Manager::num_tasks_in_group (int grp_id)
01858 {
01859   ACE_TRACE ("ACE_Thread_Manager::num_tasks_in_group");
01860   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
01861 
01862   int tasks_count = 0;
01863   size_t i = 0;
01864 
01865   for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
01866        !iter.done ();
01867        iter.advance ())
01868     {
01869       if (iter.next ()->grp_id_ == grp_id
01870           && this->find_task (iter.next ()->task_, i) == 0
01871           && iter.next ()->task_ != 0)
01872         ++tasks_count;
01873 
01874       ++i;
01875     }
01876   return tasks_count;
01877 }
01878 
01879 // Returns the number of threads in an ACE_Task.
01880 
01881 int
01882 ACE_Thread_Manager::num_threads_in_task (ACE_Task_Base *task)
01883 {
01884   ACE_TRACE ("ACE_Thread_Manager::num_threads_in_task");
01885   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
01886 
01887   int threads_count = 0;
01888 
01889   for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
01890        !iter.done ();
01891        iter.advance ())
01892     if (iter.next ()->task_ == task)
01893       ++threads_count;
01894 
01895   return threads_count;
01896 }
01897 
01898 // Returns in task_list a list of ACE_Tasks registered with ACE_Thread_Manager.
01899 
01900 ssize_t
01901 ACE_Thread_Manager::task_all_list (ACE_Task_Base *task_list[],
01902                                    size_t n)
01903 {
01904   ACE_TRACE ("ACE_Thread_Manager::task_all_list");
01905   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
01906 
01907   size_t task_list_count = 0;
01908 
01909   for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
01910        !iter.done ();
01911        iter.advance ())
01912     {
01913       if (task_list_count >= n)
01914         break;
01915 
01916       ACE_Task_Base *task_p = iter.next ()->task_;
01917       if (0 != task_p)
01918         {
01919           // This thread has a task pointer; see if it's already in the
01920           // list. Don't add duplicates.
01921           size_t i = 0;
01922           for (; i < task_list_count; ++i)
01923             if (task_list[i] == task_p)
01924               break;
01925           if (i == task_list_count)        // No match - add this one
01926             task_list[task_list_count++] = task_p;
01927         }
01928     }
01929 
01930   return task_list_count;
01931 }
01932 
01933 // Returns in thread_list a list of all thread ids
01934 
01935 ssize_t
01936 ACE_Thread_Manager::thread_all_list (ACE_thread_t thread_list[],
01937                                      size_t n)
01938 {
01939   ACE_TRACE ("ACE_Thread_Manager::thread_all_list");
01940   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
01941 
01942   size_t thread_count = 0;
01943 
01944   for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
01945        !iter.done ();
01946        iter.advance ())
01947     {
01948       if (thread_count >= n)
01949         break;
01950 
01951       thread_list[thread_count] = iter.next ()->thr_id_;
01952       ++thread_count;
01953     }
01954 
01955   return thread_count;
01956 }
01957 
01958 
01959 int
01960 ACE_Thread_Manager::thr_state (ACE_thread_t id,
01961                                ACE_UINT32& state)
01962 {
01963   ACE_TRACE ("ACE_Thread_Manager::thr_state");
01964   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
01965 
01966   int const self_check = ACE_OS::thr_equal (id, ACE_OS::thr_self ());
01967 
01968   // If we're checking the state of our thread, try to get the cached
01969   // value out of TSS to avoid lookup.
01970   if (self_check)
01971     {
01972       ACE_Thread_Descriptor *desc = ACE_LOG_MSG->thr_desc ();
01973       if (desc == 0)
01974         return 0;               // Always return false.
01975       state = desc->thr_state_;
01976     }
01977   else
01978     {
01979       // Not calling from self, have to look it up from the list.
01980       ACE_FIND (this->find_thread (id), ptr);
01981       if (ptr == 0)
01982         return 0;
01983       state = ptr->thr_state_;
01984     }
01985 
01986   return 1;
01987 }
01988 
01989 // Returns in task_list a list of ACE_Tasks in a group.
01990 
01991 ssize_t
01992 ACE_Thread_Manager::task_list (int grp_id,
01993                                ACE_Task_Base *task_list[],
01994                                size_t n)
01995 {
01996   ACE_TRACE ("ACE_Thread_Manager::task_list");
01997   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
01998 
01999   ACE_Task_Base **task_list_iterator = task_list;
02000   size_t task_list_count = 0;
02001   size_t i = 0;
02002 
02003   for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
02004        !iter.done ();
02005        iter.advance ())
02006     {
02007       if (task_list_count >= n)
02008         break;
02009 
02010       if (iter.next ()->grp_id_ == grp_id
02011           && this->find_task (iter.next ()->task_, i) == 0)
02012         {
02013           task_list_iterator[task_list_count] = iter.next ()->task_;
02014           ++task_list_count;
02015         }
02016 
02017       ++i;
02018     }
02019 
02020   return task_list_count;
02021 }
02022 
02023 // Returns in thread_list a list of thread ids in an ACE_Task.
02024 
02025 ssize_t
02026 ACE_Thread_Manager::thread_list (ACE_Task_Base *task,
02027                                  ACE_thread_t thread_list[],
02028                                  size_t n)
02029 {
02030   ACE_TRACE ("ACE_Thread_Manager::thread_list");
02031   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
02032 
02033   size_t thread_count = 0;
02034 
02035   for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
02036        !iter.done ();
02037        iter.advance ())
02038     {
02039       if (thread_count >= n)
02040         break;
02041 
02042       if (iter.next ()->task_ == task)
02043         {
02044           thread_list[thread_count] = iter.next ()->thr_id_;
02045           ++thread_count;
02046         }
02047     }
02048 
02049   return thread_count;
02050 }
02051 
02052 // Returns in thread_list a list of thread handles in an ACE_Task.
02053 
02054 ssize_t
02055 ACE_Thread_Manager::hthread_list (ACE_Task_Base *task,
02056                                   ACE_hthread_t hthread_list[],
02057                                   size_t n)
02058 {
02059   ACE_TRACE ("ACE_Thread_Manager::hthread_list");
02060   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
02061 
02062   size_t hthread_count = 0;
02063 
02064   for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
02065        !iter.done ();
02066        iter.advance ())
02067     {
02068       if (hthread_count >= n)
02069         break;
02070 
02071       if (iter.next ()->task_ == task)
02072         {
02073           hthread_list[hthread_count] = iter.next ()->thr_handle_;
02074           ++hthread_count;
02075         }
02076     }
02077 
02078   return hthread_count;
02079 }
02080 
02081 ssize_t
02082 ACE_Thread_Manager::thread_grp_list (int grp_id,
02083                                      ACE_thread_t thread_list[],
02084                                      size_t n)
02085 {
02086   ACE_TRACE ("ACE_Thread_Manager::thread_grp_list");
02087   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
02088 
02089   size_t thread_count = 0;
02090 
02091   for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
02092        !iter.done ();
02093        iter.advance ())
02094     {
02095       if (thread_count >= n)
02096         break;
02097 
02098       if (iter.next ()->grp_id_ == grp_id)
02099         {
02100           thread_list[thread_count] = iter.next ()->thr_id_;
02101           thread_count++;
02102         }
02103     }
02104 
02105   return thread_count;
02106 }
02107 
02108 // Returns in thread_list a list of thread handles in an ACE_Task.
02109 
02110 ssize_t
02111 ACE_Thread_Manager::hthread_grp_list (int grp_id,
02112                                       ACE_hthread_t hthread_list[],
02113                                       size_t n)
02114 {
02115   ACE_TRACE ("ACE_Thread_Manager::hthread_grp_list");
02116   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
02117 
02118   size_t hthread_count = 0;
02119 
02120   for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
02121        !iter.done ();
02122        iter.advance ())
02123     {
02124       if (hthread_count >= n)
02125         break;
02126 
02127       if (iter.next ()->grp_id_ == grp_id)
02128         {
02129           hthread_list[hthread_count] = iter.next ()->thr_handle_;
02130           hthread_count++;
02131         }
02132     }
02133 
02134   return hthread_count;
02135 }
02136 
02137 int
02138 ACE_Thread_Manager::set_grp (ACE_Task_Base *task, int grp_id)
02139 {
02140   ACE_TRACE ("ACE_Thread_Manager::set_grp");
02141   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
02142 
02143   for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
02144        !iter.done ();
02145        iter.advance ())
02146     if (iter.next ()->task_ == task)
02147       iter.next ()->grp_id_ = grp_id;
02148 
02149   return 0;
02150 }
02151 
02152 int
02153 ACE_Thread_Manager::get_grp (ACE_Task_Base *task, int &grp_id)
02154 {
02155   ACE_TRACE ("ACE_Thread_Manager::get_grp");
02156   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
02157 
02158   ACE_FIND (this->find_task (task), ptr);
02159   grp_id = ptr->grp_id_;
02160   return 0;
02161 }
02162 
02163 ACE_END_VERSIONED_NAMESPACE_DECL

Generated on Tue Feb 2 17:18:43 2010 for ACE by  doxygen 1.4.7