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