Thread_Manager.cpp

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

Generated on Thu Nov 9 09:42:06 2006 for ACE by doxygen 1.3.6