00001 // -*- C++ -*- 00002 00003 //============================================================================= 00004 /** 00005 * @file Thread_Manager.h 00006 * 00007 * $Id: Thread_Manager.h 81698 2008-05-14 20:42:15Z shuston $ 00008 * 00009 * @author Douglas C. Schmidt <schmidt@cs.wustl.edu> 00010 */ 00011 //============================================================================= 00012 00013 #ifndef ACE_THREAD_MANAGER_H 00014 #define ACE_THREAD_MANAGER_H 00015 #include /**/ "ace/pre.h" 00016 00017 #include "ace/Thread.h" 00018 #include "ace/Thread_Adapter.h" 00019 #include "ace/Thread_Exit.h" 00020 00021 #if !defined (ACE_LACKS_PRAGMA_ONCE) 00022 # pragma once 00023 #endif /* ACE_LACKS_PRAGMA_ONCE */ 00024 00025 #include "ace/Condition_Thread_Mutex.h" 00026 #include "ace/Unbounded_Queue.h" 00027 #include "ace/Containers.h" 00028 #include "ace/Free_List.h" 00029 #include "ace/Singleton.h" 00030 #include "ace/Log_Msg.h" 00031 #include "ace/Synch_Traits.h" 00032 #include "ace/Basic_Types.h" 00033 00034 // The following macros control how a Thread Manager manages a pool of 00035 // Thread_Descriptor. Currently, the default behavior is not to 00036 // preallocate any thread descriptor and never (well, almost never) 00037 // free up any thread descriptor until the Thread Manager gets 00038 // destructed. Which means, once your system is stable, you rarely 00039 // need to pay the price of memory allocation. On a deterministic 00040 // system, which means, the number of threads spawned can be 00041 // determined before hand, you can either redefine the memory pool 00042 // size macros to suit your need or constructed the Thread_Manager 00043 // accordingly. That way, you don't pay the price of memory 00044 // allocation when the system is really doing its job. OTOH, on 00045 // system with resources constraint, you may want to lower the size of 00046 // ACE_DEFAULT_THREAD_MANAGER_HWM to avoid unused memory hanging 00047 // around. 00048 00049 #if !defined (ACE_DEFAULT_THREAD_MANAGER_PREALLOC) 00050 # define ACE_DEFAULT_THREAD_MANAGER_PREALLOC 0 00051 #endif /* ACE_DEFAULT_THREAD_MANAGER_PREALLOC */ 00052 00053 #if !defined (ACE_DEFAULT_THREAD_MANAGER_LWM) 00054 # define ACE_DEFAULT_THREAD_MANAGER_LWM 1 00055 #endif /* ACE_DEFAULT_THREAD_MANAGER_LWM */ 00056 00057 #if !defined (ACE_DEFAULT_THREAD_MANAGER_INC) 00058 # define ACE_DEFAULT_THREAD_MANAGER_INC 1 00059 #endif /* ACE_DEFAULT_THREAD_MANAGER_INC */ 00060 00061 #if !defined (ACE_DEFAULT_THREAD_MANAGER_HWM) 00062 # define ACE_DEFAULT_THREAD_MANAGER_HWM ACE_DEFAULT_FREE_LIST_HWM 00063 // this is a big number 00064 #endif /* ACE_DEFAULT_THREAD_MANAGER_HWM */ 00065 00066 // This is the synchronization mechanism used to prevent a thread 00067 // descriptor gets removed from the Thread_Manager before it gets 00068 // stash into it. If you want to disable this feature (and risk of 00069 // corrupting the freelist,) you define the lock as ACE_Null_Mutex. 00070 // Usually, if you can be sure that your threads will run for an 00071 // extended period of time, you can safely disable the lock. 00072 00073 #if !defined (ACE_DEFAULT_THREAD_MANAGER_LOCK) 00074 # define ACE_DEFAULT_THREAD_MANAGER_LOCK ACE_SYNCH_MUTEX 00075 #endif /* ACE_DEFAULT_THREAD_MANAGER_LOCK */ 00076 00077 ACE_BEGIN_VERSIONED_NAMESPACE_DECL 00078 00079 // Forward declarations. 00080 class ACE_Task_Base; 00081 class ACE_Thread_Manager; 00082 class ACE_Thread_Descriptor; 00083 00084 /** 00085 * @class ACE_At_Thread_Exit 00086 * 00087 * @brief Contains a method to be applied when a thread is terminated. 00088 */ 00089 class ACE_Export ACE_At_Thread_Exit 00090 { 00091 friend class ACE_Thread_Descriptor; 00092 friend class ACE_Thread_Manager; 00093 public: 00094 /// Default constructor 00095 ACE_At_Thread_Exit (void); 00096 00097 /// The destructor 00098 virtual ~ACE_At_Thread_Exit (void); 00099 00100 /// At_Thread_Exit has the ownership? 00101 bool is_owner (void) const; 00102 00103 /// Set the ownership of the At_Thread_Exit. 00104 bool is_owner (bool owner); 00105 00106 /// This At_Thread_Exit was applied? 00107 int was_applied (void) const; 00108 00109 /// Set applied state of At_Thread_Exit. 00110 int was_applied (int applied); 00111 00112 protected: 00113 /// The next At_Thread_Exit hook in the list. 00114 ACE_At_Thread_Exit *next_; 00115 00116 /// Do the apply if necessary 00117 void do_apply (void); 00118 00119 /// The apply method. 00120 virtual void apply (void) = 0; 00121 00122 /// The Thread_Descriptor where this at is registered. 00123 ACE_Thread_Descriptor* td_; 00124 00125 /// The at was applied? 00126 int was_applied_; 00127 00128 /// The at has the ownership of this? 00129 bool is_owner_; 00130 }; 00131 00132 class ACE_Export ACE_At_Thread_Exit_Func : public ACE_At_Thread_Exit 00133 { 00134 public: 00135 /// Constructor 00136 ACE_At_Thread_Exit_Func (void *object, 00137 ACE_CLEANUP_FUNC func, 00138 void *param = 0); 00139 00140 virtual ~ACE_At_Thread_Exit_Func (void); 00141 00142 protected: 00143 /// The object to be cleanup 00144 void *object_; 00145 00146 /// The cleanup func 00147 ACE_CLEANUP_FUNC func_; 00148 00149 /// A param if required 00150 void *param_; 00151 00152 /// The apply method 00153 void apply (void); 00154 }; 00155 00156 /** 00157 * @class ACE_Thread_Descriptor_Base 00158 * 00159 * @brief Basic information for thread descriptors. These information 00160 * gets extracted out because we need it after a thread is 00161 * terminated. 00162 * 00163 * @internal 00164 */ 00165 class ACE_Export ACE_Thread_Descriptor_Base : public ACE_OS_Thread_Descriptor 00166 { 00167 00168 friend class ACE_Thread_Manager; 00169 friend class ACE_Double_Linked_List<ACE_Thread_Descriptor_Base>; 00170 friend class ACE_Double_Linked_List_Iterator_Base<ACE_Thread_Descriptor_Base>; 00171 friend class ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor_Base>; 00172 friend class ACE_Double_Linked_List<ACE_Thread_Descriptor>; 00173 friend class ACE_Double_Linked_List_Iterator_Base<ACE_Thread_Descriptor>; 00174 friend class ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor>; 00175 public: 00176 ACE_Thread_Descriptor_Base (void); 00177 ~ACE_Thread_Descriptor_Base (void); 00178 00179 // = We need the following operators to make Borland happy. 00180 00181 /// Equality operator. 00182 bool operator== (const ACE_Thread_Descriptor_Base &rhs) const; 00183 00184 /// Inequality operator. 00185 bool operator!= (const ACE_Thread_Descriptor_Base &rhs) const; 00186 00187 /// Group ID. 00188 int grp_id (void) const; 00189 00190 /// Current state of the thread. 00191 ACE_UINT32 state (void) const; 00192 00193 /// Return the pointer to an ACE_Task_Base or NULL if there's no 00194 /// ACE_Task_Base associated with this thread.; 00195 ACE_Task_Base *task (void) const; 00196 00197 protected: 00198 /// Reset this base thread descriptor. 00199 void reset (void); 00200 00201 /// Unique thread ID. 00202 ACE_thread_t thr_id_; 00203 00204 /// Unique handle to thread (used by Win32 and AIX). 00205 ACE_hthread_t thr_handle_; 00206 00207 /// Group ID. 00208 int grp_id_; 00209 00210 /// Current state of the thread. 00211 ACE_UINT32 thr_state_; 00212 00213 /// Pointer to an ACE_Task_Base or NULL if there's no 00214 /// ACE_Task_Base. 00215 ACE_Task_Base *task_; 00216 00217 /// We need these pointers to maintain the double-linked list in a 00218 /// thread managers. 00219 ACE_Thread_Descriptor_Base *next_; 00220 ACE_Thread_Descriptor_Base *prev_; 00221 }; 00222 00223 /** 00224 * @class ACE_Thread_Descriptor 00225 * 00226 * @brief Information for controlling threads that run under the control 00227 * of the <Thread_Manager>. 00228 */ 00229 class ACE_Export ACE_Thread_Descriptor : public ACE_Thread_Descriptor_Base 00230 { 00231 friend class ACE_At_Thread_Exit; 00232 friend class ACE_Thread_Manager; 00233 friend class ACE_Double_Linked_List<ACE_Thread_Descriptor>; 00234 friend class ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor>; 00235 public: 00236 // = Initialization method. 00237 ACE_Thread_Descriptor (void); 00238 00239 // = Accessor methods. 00240 /// Unique thread id. 00241 ACE_thread_t self (void) const; 00242 00243 /// Unique handle to thread (used by Win32 and AIX). 00244 void self (ACE_hthread_t &); 00245 00246 /// Dump the state of an object. 00247 void dump (void) const; 00248 00249 /** 00250 * This cleanup function must be called only for ACE_TSS_cleanup. 00251 * The ACE_TSS_cleanup delegate Log_Msg instance destruction when 00252 * Log_Msg cleanup is called before terminate. 00253 */ 00254 void log_msg_cleanup(ACE_Log_Msg* log_msg); 00255 00256 /** 00257 * Register an At_Thread_Exit hook and the ownership is acquire by 00258 * Thread_Descriptor, this is the usual case when the AT is dynamically 00259 * allocated. 00260 */ 00261 int at_exit (ACE_At_Thread_Exit* cleanup); 00262 00263 /// Register an At_Thread_Exit hook and the ownership is retained for the 00264 /// caller. Normally used when the at_exit hook is created in stack. 00265 int at_exit (ACE_At_Thread_Exit& cleanup); 00266 00267 /** 00268 * Register an object (or array) for cleanup at thread termination. 00269 * "cleanup_hook" points to a (global, or static member) function 00270 * that is called for the object or array when it to be destroyed. 00271 * It may perform any necessary cleanup specific for that object or 00272 * its class. "param" is passed as the second parameter to the 00273 * "cleanup_hook" function; the first parameter is the object (or 00274 * array) to be destroyed. Returns 0 on success, non-zero on 00275 * failure: -1 if virtual memory is exhausted or 1 if the object (or 00276 * arrayt) had already been registered. 00277 */ 00278 int at_exit (void *object, 00279 ACE_CLEANUP_FUNC cleanup_hook, 00280 void *param); 00281 00282 /// Do nothing destructor to keep some compilers happy 00283 ~ACE_Thread_Descriptor (void); 00284 00285 /** 00286 * Do nothing but to acquire the thread descriptor's lock and 00287 * release. This will first check if the thread is registered or 00288 * not. If it is already registered, there's no need to reacquire 00289 * the lock again. This is used mainly to get newly spawned thread 00290 * in synch with thread manager and prevent it from accessing its 00291 * thread descriptor before it gets fully built. This function is 00292 * only called from ACE_Log_Msg::thr_desc. 00293 */ 00294 void acquire_release (void); 00295 void acquire (void); 00296 void release (void); 00297 00298 /** 00299 * Set/get the @c next_ pointer. These are required by the 00300 * ACE_Free_List. 00301 */ 00302 void set_next (ACE_Thread_Descriptor *td); 00303 ACE_Thread_Descriptor *get_next (void) const; 00304 00305 private: 00306 /// Reset this thread descriptor. 00307 void reset (ACE_Thread_Manager *tm); 00308 00309 /// Pop an At_Thread_Exit from at thread termination list, apply the at 00310 /// if apply is true. 00311 void at_pop (int apply = 1); 00312 00313 /// Push an At_Thread_Exit to at thread termination list and set the 00314 /// ownership of at. 00315 void at_push (ACE_At_Thread_Exit* cleanup, 00316 bool is_owner = false); 00317 00318 /// Run the AT_Thread_Exit hooks. 00319 void do_at_exit (void); 00320 00321 /// Terminate realize the cleanup process to thread termination 00322 void terminate (void); 00323 00324 /// Thread_Descriptor is the ownership of ACE_Log_Msg if log_msg_!=0 00325 /// This can occur because ACE_TSS_cleanup was executed before terminate. 00326 ACE_Log_Msg *log_msg_; 00327 00328 /// The AT_Thread_Exit list 00329 ACE_At_Thread_Exit *at_exit_list_; 00330 00331 /** 00332 * Stores the cleanup info for a thread. 00333 * @note This should be generalized to be a stack of ACE_Cleanup_Info's. 00334 */ 00335 ACE_Cleanup_Info cleanup_info_; 00336 00337 /// Pointer to an ACE_Thread_Manager or NULL if there's no 00338 /// ACE_Thread_Manager> 00339 ACE_Thread_Manager* tm_; 00340 00341 /// Registration lock to prevent premature removal of thread descriptor. 00342 ACE_DEFAULT_THREAD_MANAGER_LOCK *sync_; 00343 00344 /// Keep track of termination status. 00345 bool terminated_; 00346 }; 00347 00348 // Forward declaration. 00349 class ACE_Thread_Control; 00350 00351 // This typedef should be (and used to be) inside the 00352 // ACE_Thread_Manager declaration. But, it caused compilation 00353 // problems on g++/VxWorks/i960 with -g. Note that 00354 // ACE_Thread_Manager::THR_FUNC is only used internally in 00355 // ACE_Thread_Manager, so it's not useful for anyone else. 00356 // It also caused problems on IRIX5 with g++. 00357 #if defined (__GNUG__) 00358 typedef int (ACE_Thread_Manager::*ACE_THR_MEMBER_FUNC)(ACE_Thread_Descriptor *, int); 00359 #endif /* __GNUG__ */ 00360 00361 /** 00362 * @class ACE_Thread_Manager 00363 * 00364 * @brief Manages a pool of threads. 00365 * 00366 * This class allows operations on groups of threads atomically. 00367 * The default behavior of thread manager is to wait on 00368 * all threads under it's management when it gets destructed. 00369 * Therefore, remember to remove a thread from thread manager if 00370 * you don't want it to wait for the thread. There are also 00371 * functions to disable this default wait-on-exit behavior. 00372 * However, if your program depends on turning this off to run 00373 * correctly, you are probably doing something wrong. Rule of 00374 * thumb, use ACE_Thread to manage your daemon threads. 00375 * Notice that if there're threads which live beyond the scope of 00376 * main(), you are sure to have resource leaks in your program. 00377 * Remember to wait on threads before exiting your main program if that 00378 * could happen in your programs. 00379 */ 00380 class ACE_Export ACE_Thread_Manager 00381 { 00382 public: 00383 friend class ACE_Thread_Control; 00384 00385 // Allow ACE_THread_Exit to register the global TSS instance object. 00386 friend class ACE_Thread_Exit; 00387 friend class ACE_Thread_Descriptor; 00388 00389 #if !defined (__GNUG__) 00390 typedef int (ACE_Thread_Manager::*ACE_THR_MEMBER_FUNC)(ACE_Thread_Descriptor *, int); 00391 #endif /* !__GNUG__ */ 00392 00393 /// These are the various states a thread managed by the 00394 /// ACE_Thread_Manager can be in. 00395 enum 00396 { 00397 /// Uninitialized. 00398 ACE_THR_IDLE = 0x00000000, 00399 00400 /// Created but not yet running. 00401 ACE_THR_SPAWNED = 0x00000001, 00402 00403 /// Thread is active (naturally, we don't know if it's actually 00404 /// *running* because we aren't the scheduler...). 00405 ACE_THR_RUNNING = 0x00000002, 00406 00407 /// Thread is suspended. 00408 ACE_THR_SUSPENDED = 0x00000004, 00409 00410 /// Thread has been cancelled (which is an indiction that it needs to 00411 /// terminate...). 00412 ACE_THR_CANCELLED = 0x00000008, 00413 00414 /// Thread has shutdown, but the slot in the thread manager hasn't 00415 /// been reclaimed yet. 00416 ACE_THR_TERMINATED = 0x00000010, 00417 00418 /// Join operation has been invoked on the thread by thread manager. 00419 ACE_THR_JOINING = 0x10000000 00420 }; 00421 00422 /** 00423 * @brief Initialization and termination methods. 00424 * 00425 * Internally, ACE_Thread_Manager keeps a freelist for caching 00426 * resources it uses to keep track of managed threads (not the 00427 * threads themselves.) @a prealloc, @a lwm, @a inc, @hwm 00428 * determine the initial size, the low water mark, increment step, 00429 * and high water mark of the freelist. 00430 * 00431 * @sa ACE_Free_List 00432 */ 00433 ACE_Thread_Manager (size_t preaolloc = ACE_DEFAULT_THREAD_MANAGER_PREALLOC, 00434 size_t lwm = ACE_DEFAULT_THREAD_MANAGER_LWM, 00435 size_t inc = ACE_DEFAULT_THREAD_MANAGER_INC, 00436 size_t hwm = ACE_DEFAULT_THREAD_MANAGER_HWM); 00437 ~ACE_Thread_Manager (void); 00438 00439 #if ! defined (ACE_THREAD_MANAGER_LACKS_STATICS) 00440 /// Get pointer to a process-wide ACE_Thread_Manager. 00441 static ACE_Thread_Manager *instance (void); 00442 00443 /// Set pointer to a process-wide ACE_Thread_Manager and return 00444 /// existing pointer. 00445 static ACE_Thread_Manager *instance (ACE_Thread_Manager *); 00446 00447 /// Delete the dynamically allocated Singleton 00448 static void close_singleton (void); 00449 #endif /* ! defined (ACE_THREAD_MANAGER_LACKS_STATICS) */ 00450 00451 /// No-op. Currently unused. 00452 int open (size_t size = 0); 00453 00454 /** 00455 * Release all resources. 00456 * By default, this method will wait until all threads exit. 00457 * However, when called from close_singleton(), most global resources 00458 * are destroyed and thus, close() does not try to wait; it simply cleans 00459 * up internal thread records (the thread descriptor list). 00460 */ 00461 int close (void); 00462 00463 /** 00464 * Create a new thread, which executes @a func with argument @a arg. 00465 * 00466 * @param func The function that is called in the spawned thread. 00467 * 00468 * @param arg The value passed to each spawned thread's @a func. 00469 * 00470 * @param flags Flags to control attributes of the spawned threads. 00471 * @sa ACE_OS::thr_create() for descriptions of the 00472 * possible flags values and their interactions. 00473 * 00474 * @param t_id Pointer to a location to receive the spawned thread's 00475 * ID. If 0, the ID is not returned. 00476 * 00477 * @param t_handle Pointer to a location to receive the spawned thread's 00478 * thread handle. If 0, the handle is not returned. 00479 * 00480 * @param priority The priority at which the thread is spawned. 00481 * 00482 * @param grp_id The thread group that the spawned thread is 00483 * added to. If -1 is specified, a new thread group is 00484 * created for the spawned thread. 00485 * 00486 * @param stack Pointers to the base of a pre-allocated stack space 00487 * for the thread's stack. If 0, the platform allocates 00488 * stack space for the thread. If a stack is specified, 00489 * it is recommended that @a stack_size also be supplied 00490 * to specify the size of the stack. 00491 * Not all platforms support pre-allocated stacks. If 00492 * @a stack is specified for a platform which does not 00493 * allow pre-allocated stack space this parameter is 00494 * ignored. 00495 * 00496 * @param stack_size Indicate how large the thread's stack should be, in 00497 * bytes. If a pre-allocated stack pointer is passed in 00498 * @a stack, @a stack_size indicates the size of that 00499 * stack area. If no pre-allocated stack is passed, 00500 * the stack size specified is passed to the 00501 * operating system to request that it allocate a stack 00502 * of the specified size. 00503 * 00504 * @param thr_name Pointer to a name to assign to the spawned thread. 00505 * This is only meaningful for platforms that have a 00506 * capacity to name threads (e.g., VxWorks and some 00507 * varieties of Pthreads). This argument is ignored if 00508 * specified as 0 and on platforms that do not have the 00509 * capability to name threads. 00510 * 00511 * @retval -1 on failure; @c errno contains an error value. 00512 * @retval The group id of the spawned thread. 00513 */ 00514 int spawn (ACE_THR_FUNC func, 00515 void *arg = 0, 00516 long flags = THR_NEW_LWP | THR_JOINABLE | THR_INHERIT_SCHED, 00517 ACE_thread_t *t_id = 0, 00518 ACE_hthread_t *t_handle = 0, 00519 long priority = ACE_DEFAULT_THREAD_PRIORITY, 00520 int grp_id = -1, 00521 void *stack = 0, 00522 size_t stack_size = ACE_DEFAULT_THREAD_STACKSIZE, 00523 const char** thr_name = 0); 00524 00525 /** 00526 * Spawn a specified number of threads, all of which execute @a func 00527 * with argument @a arg. 00528 * 00529 * @param n The number of threads to spawn. 00530 * 00531 * @param func The function that is called in the spawned thread. 00532 * 00533 * @param arg The value passed to each spawned thread's @a func. 00534 * 00535 * @param flags Flags to control attributes of the spawned threads. 00536 * @sa ACE_OS::thr_create() for descriptions of the 00537 * possible flags values and their interactions. 00538 * 00539 * @param priority The priority at which the threads are spawned. 00540 * 00541 * @param grp_id The thread group that the spawned threads are 00542 * added to. If -1 is specified, a new thread group is 00543 * created for the spawned threads. 00544 * 00545 * @param task The ACE_Task that the spawned threads are associated 00546 * with. If 0, the threads are not associated with an 00547 * ACE_Task. This argument is usually assigned by the 00548 * ACE_Task_Base::activate() method to associate the 00549 * spawned threads with the spawning ACE_Task object. 00550 * 00551 * @param thread_handles An array of @a n entries which will receive 00552 * the thread handles of the spawned threads. 00553 * 00554 * @param stack An array of @a n pointers to pre-allocated stack space 00555 * for each thread's stack. If specified as 0, the 00556 * platform allocates stack space for each thread. If 00557 * a stack is specified, it is recommended that a 00558 * @a stack_size element also be supplied that specifies 00559 * the size of the stack. 00560 * Not all platforms support pre-allocated stacks. If 00561 * @a stack is specified for a platform which does not 00562 * allow pre-allocated stack space this parameter is 00563 * ignored. 00564 * 00565 * @param stack_size An array of @a n values which indicate how large 00566 * each thread's stack should be, in bytes. 00567 * If pre-allocated stacks are passed in @a stacks, these 00568 * sizes are for those stacks. If no pre-allocated stacks 00569 * are passed, the stack sizes are specified to the 00570 * operating system to request that it allocate stacks 00571 * of the specified sizes. If an array entry is 0, the 00572 * platform defaults are used for the corresponding thread. 00573 * If a 0 array pointer is specified, platform defaults 00574 * are used for all thread stack sizes. 00575 * 00576 * @param thr_name An array of names to assign to the spawned threads. 00577 * This is only meaningful for platforms that have a 00578 * capacity to name threads (e.g., VxWorks and some 00579 * varieties of Pthreads). This argument is ignored if 00580 * specified as 0 and on platforms that do not have the 00581 * capability to name threads. 00582 * 00583 * ACE_Thread_Manager can manipulate threads in groups based on 00584 * @a grp_id or @a task using functions such as kill_grp() or 00585 * cancel_task(). 00586 * 00587 * @retval -1 on failure; @c errno contains an error value. 00588 * @retval The group id of the threads. 00589 */ 00590 int spawn_n (size_t n, 00591 ACE_THR_FUNC func, 00592 void *arg = 0, 00593 long flags = THR_NEW_LWP | THR_JOINABLE | THR_INHERIT_SCHED, 00594 long priority = ACE_DEFAULT_THREAD_PRIORITY, 00595 int grp_id = -1, 00596 ACE_Task_Base *task = 0, 00597 ACE_hthread_t thread_handles[] = 0, 00598 void *stack[] = 0, 00599 size_t stack_size[] = 0, 00600 const char* thr_name[] = 0); 00601 00602 /** 00603 * Spawn a specified number of threads, all of which execute @a func 00604 * with argument @a arg. 00605 * 00606 * @param thread_ids An array to receive the thread IDs of successfully 00607 * spawned buffer. If 0, the thread IDs are not returned. 00608 * If specified, the array must be at least @a n entries. 00609 * 00610 * @param n The number of threads to spawn. 00611 * 00612 * @param func The function that is called in the spawned thread. 00613 * 00614 * @param arg The value passed to each spawned thread's @a func. 00615 * 00616 * @param flags Flags to control attributes of the spawned threads. 00617 * @sa ACE_OS::thr_create() for descriptions of the 00618 * possible flags values and their interactions. 00619 * 00620 * @param priority The priority at which the threads are spawned. 00621 * 00622 * @param grp_id The thread group that the spawned threads are 00623 * added to. If -1 is specified, a new thread group is 00624 * created for the spawned threads. 00625 * 00626 * @param stack An array of @a n pointers to pre-allocated stack space 00627 * for each thread's stack. If specified as 0, the 00628 * platform allocates stack space for each thread. If 00629 * a stack is specified, it is recommended that a 00630 * @a stack_size element also be supplied that specifies 00631 * the size of the stack. 00632 * Not all platforms support pre-allocated stacks. If 00633 * @a stack is specified for a platform which does not 00634 * allow pre-allocated stack space this parameter is 00635 * ignored. 00636 * 00637 * @param stack_size An array of @a n values which indicate how large 00638 * each thread's stack should be, in bytes. 00639 * If pre-allocated stacks are passed in @a stacks, these 00640 * sizes are for those stacks. If no pre-allocated stacks 00641 * are passed, the stack sizes are specified to the 00642 * operating system to request that it allocate stacks 00643 * of the specified sizes. If an array entry is 0, the 00644 * platform defaults are used for the corresponding thread. 00645 * If a 0 array pointer is specified, platform defaults 00646 * are used for all thread stack sizes. 00647 * 00648 * @param thread_handles An array of @a n entries which will receive 00649 * the thread handles of the spawned threads. 00650 * 00651 * @param task The ACE_Task that the spawned threads are associated 00652 * with. If 0, the threads are not associated with an 00653 * ACE_Task. This argument is usually assigned by the 00654 * ACE_Task_Base::activate() method to associate the 00655 * spawned threads with the spawning ACE_Task object. 00656 * 00657 * @param thr_name An array of names to assign to the spawned threads. 00658 * This is only meaningful for platforms that have a 00659 * capacity to name threads (e.g., VxWorks and some 00660 * varieties of Pthreads). This argument is ignored if 00661 * specified as 0 and on platforms that do not have the 00662 * capability to name threads. 00663 * 00664 * ACE_Thread_Manager can manipulate threads in groups based on 00665 * @a grp_id or @a task using functions such as kill_grp() or 00666 * cancel_task(). 00667 * 00668 * @retval -1 on failure; @c errno contains an error value. 00669 * @retval The group id of the threads. 00670 00671 */ 00672 int spawn_n (ACE_thread_t thread_ids[], 00673 size_t n, 00674 ACE_THR_FUNC func, 00675 void *arg, 00676 long flags, 00677 long priority = ACE_DEFAULT_THREAD_PRIORITY, 00678 int grp_id = -1, 00679 void *stack[] = 0, 00680 size_t stack_size[] = 0, 00681 ACE_hthread_t thread_handles[] = 0, 00682 ACE_Task_Base *task = 0, 00683 const char* thr_name[] = 0); 00684 00685 /** 00686 * Called to clean up when a thread exits. 00687 * 00688 * @param do_thread_exit If non-0 then ACE_Thread::exit is called to 00689 * exit the thread 00690 * @param status If ACE_Thread_Exit is called, this is passed as 00691 * the exit value of the thread. 00692 * Should _not_ be called by main thread. 00693 */ 00694 ACE_THR_FUNC_RETURN exit (ACE_THR_FUNC_RETURN status = 0, 00695 bool do_thread_exit = true); 00696 00697 /** 00698 * Block until there are no more threads running in this thread 00699 * manager or @c timeout expires. 00700 * 00701 * @param timeout is treated as "absolute" time by default, but this 00702 * can be changed to "relative" time by setting the @c 00703 * use_absolute_time to false. 00704 * @param abandon_detached_threads If true, @c wait() will first 00705 * check thru its thread list for 00706 * threads with THR_DETACHED or 00707 * THR_DAEMON flags set and remove 00708 * these threads. Notice that 00709 * unlike other @c wait_*() methods, 00710 * by default, @c wait() does wait on 00711 * all thread spawned by this 00712 * thread manager no matter the detached 00713 * flags are set or not unless it is 00714 * called with @c 00715 * abandon_detached_threads flag set. 00716 * @param use_absolute_time If true then treat @c timeout as 00717 * absolute time, else relative time. 00718 * @return 0 on success * and -1 on failure. 00719 * 00720 * @note If this function is called while the @c 00721 * ACE_Object_Manager is shutting down (as a result of program 00722 * rundown via @c ACE::fini()), it will not wait for any threads to 00723 * complete. If you must wait for threads spawned by this thread 00724 * manager to complete and you are in a ACE rundown situation (such 00725 * as your object is being destroyed by the @c ACE_Object_Manager) 00726 * you can use @c wait_grp() instead. 00727 */ 00728 int wait (const ACE_Time_Value *timeout = 0, 00729 bool abandon_detached_threads = false, 00730 bool use_absolute_time = true); 00731 00732 /// Join a thread specified by @a tid. Do not wait on a detached thread. 00733 int join (ACE_thread_t tid, ACE_THR_FUNC_RETURN *status = 0); 00734 00735 /** 00736 * Block until there are no more threads running in a group. 00737 * Returns 0 on success and -1 on failure. Notice that wait_grp 00738 * will not wait on detached threads. 00739 */ 00740 int wait_grp (int grp_id); 00741 00742 /** 00743 * Return the "real" handle to the calling thread, caching it if 00744 * necessary in TSS to speed up subsequent lookups. This is 00745 * necessary since on some platforms (e.g., Windows) we can't get this 00746 * handle via direct method calls. Notice that you should *not* 00747 * close the handle passed back from this method. It is used 00748 * internally by Thread Manager. On the other hand, you *have to* 00749 * use this internal thread handle when working on Thread_Manager. 00750 * Return -1 if fail. 00751 */ 00752 int thr_self (ACE_hthread_t &); 00753 00754 /** 00755 * Return the unique ID of the calling thread. 00756 * Same as calling ACE_Thread::self(). 00757 */ 00758 ACE_thread_t thr_self (void); 00759 00760 /** 00761 * Returns a pointer to the current ACE_Task_Base we're executing 00762 * in if this thread is indeed running in an ACE_Task_Base, else 00763 * return 0. 00764 */ 00765 ACE_Task_Base *task (void); 00766 00767 /** 00768 * @name Suspend and resume methods 00769 * 00770 * Suspend/resume is not supported on all platforms. For example, Pthreads 00771 * does not support these functions. 00772 */ 00773 //@{ 00774 00775 /// Suspend all threads 00776 int suspend_all (void); 00777 00778 /// Suspend a single thread. 00779 int suspend (ACE_thread_t); 00780 00781 /// Suspend a group of threads. 00782 int suspend_grp (int grp_id); 00783 00784 /** 00785 * True if @a t_id is inactive (i.e., suspended), else false. Always 00786 * return false if @a t_id is not managed by the Thread_Manager. 00787 */ 00788 int testsuspend (ACE_thread_t t_id); 00789 00790 /// Resume all stopped threads 00791 int resume_all (void); 00792 00793 /// Resume a single thread. 00794 int resume (ACE_thread_t); 00795 00796 /// Resume a group of threads. 00797 int resume_grp (int grp_id); 00798 00799 /** 00800 * True if @a t_id is active (i.e., resumed), else false. Always 00801 * return false if @a t_id is not managed by the Thread_Manager. 00802 */ 00803 int testresume (ACE_thread_t t_id); 00804 00805 //@} 00806 00807 // = Send signals to one or more threads without blocking. 00808 /** 00809 * Send @a signum to all stopped threads. Not supported on platforms 00810 * that do not have advanced signal support, such as Win32. 00811 */ 00812 int kill_all (int signum); 00813 /** 00814 * Send the @a signum to a single thread. Not supported on platforms 00815 * that do not have advanced signal support, such as Win32. 00816 */ 00817 int kill (ACE_thread_t, int signum); 00818 /** 00819 * Send @a signum to a group of threads, not supported on platforms 00820 * that do not have advanced signal support, such as Win32. 00821 */ 00822 int kill_grp (int grp_id, int signum); 00823 00824 // = Cancel methods, which provides a cooperative thread-termination mechanism (will not block). 00825 /** 00826 * Cancel's all the threads. 00827 */ 00828 int cancel_all (int async_cancel = 0); 00829 00830 /** 00831 * Cancel a single thread. 00832 */ 00833 int cancel (ACE_thread_t, int async_cancel = 0); 00834 00835 /** 00836 * Cancel a group of threads. 00837 */ 00838 int cancel_grp (int grp_id, int async_cancel = 0); 00839 00840 /** 00841 * True if @a t_id is cancelled, else false. Always return false if 00842 * @a t_id is not managed by the Thread_Manager. 00843 */ 00844 int testcancel (ACE_thread_t t_id); 00845 00846 /** 00847 * True if @a t_id has terminated (i.e., is no longer running), 00848 * but the slot in the thread manager hasn't been reclaimed yet, 00849 * else false. Always return false if @a t_id is not managed by the 00850 * Thread_Manager. 00851 */ 00852 int testterminate (ACE_thread_t t_id); 00853 00854 /// Set group ids for a particular thread id. 00855 int set_grp (ACE_thread_t, 00856 int grp_id); 00857 00858 /// Get group ids for a particular thread id. 00859 int get_grp (ACE_thread_t, 00860 int &grp_id); 00861 00862 /** 00863 * @name Task-related operations 00864 */ 00865 //@{ 00866 /** 00867 * Block until there are no more threads running in a specified task. 00868 * This method will not wait for either detached or daemon threads; 00869 * the threads must have been spawned with the @c THR_JOINABLE flag. 00870 * Upon successful completion, the threads have been joined, so further 00871 * attempts to join with any of the waited-for threads will fail. 00872 * 00873 * @param task The ACE_Task_Base object whose threads are to waited for. 00874 * 00875 * @retval 0 Success. 00876 * @retval -1 Failure (consult errno for further information). 00877 */ 00878 int wait_task (ACE_Task_Base *task); 00879 00880 /** 00881 * Suspend all threads in an ACE_Task. 00882 */ 00883 int suspend_task (ACE_Task_Base *task); 00884 00885 /** 00886 * Resume all threads in an ACE_Task. 00887 */ 00888 int resume_task (ACE_Task_Base *task); 00889 00890 /** 00891 * Send a signal @a signum to all threads in an ACE_Task. 00892 */ 00893 int kill_task (ACE_Task_Base *task, int signum); 00894 00895 /** 00896 * Cancel all threads in an ACE_Task. If <async_cancel> is non-0, 00897 * then asynchronously cancel these threads if the OS platform 00898 * supports cancellation. Otherwise, perform a "cooperative" 00899 * cancellation. 00900 */ 00901 int cancel_task (ACE_Task_Base *task, int async_cancel = 0); 00902 00903 //@} 00904 00905 // = Collect thread handles in the thread manager. Notice that 00906 // the collected information is just a snapshot. 00907 /// Check if the thread is managed by the thread manager. Return true if 00908 /// the thread is found, false otherwise. 00909 int hthread_within (ACE_hthread_t handle); 00910 int thread_within (ACE_thread_t tid); 00911 00912 /// Returns the number of ACE_Task_Base in a group. 00913 int num_tasks_in_group (int grp_id); 00914 00915 /// Returns the number of threads in an ACE_Task_Base. 00916 int num_threads_in_task (ACE_Task_Base *task); 00917 00918 /** 00919 * Returns a list of ACE_Task_Base pointers corresponding to the tasks 00920 * that have active threads in a specified thread group. 00921 * 00922 * @param grp_id The thread group ID to obtain task pointers for. 00923 * 00924 * @param task_list is a pointer to an array to receive the list of pointers. 00925 * The caller is responsible for supplying an array with at 00926 * least @arg n entries. 00927 * 00928 * @param n The maximum number of ACE_Task_Base pointers to write 00929 * in @arg task_list. 00930 * 00931 * @retval If successful, the number of pointers returned, which will be 00932 * no greater than @arg n. Returns -1 on error. 00933 * 00934 * @note This method has no way to indicate if there are more than 00935 * @arg n ACE_Task_Base pointers available. Therefore, it may be 00936 * wise to guess a larger value of @arg n than one thinks in cases 00937 * where the exact number of tasks is not known. 00938 * 00939 * @sa num_tasks_in_group(), task_all_list() 00940 */ 00941 ssize_t task_list (int grp_id, 00942 ACE_Task_Base *task_list[], 00943 size_t n); 00944 00945 /** 00946 * Returns in @a thread_list a list of up to @a n thread ids in an 00947 * ACE_Task_Base. The caller must allocate the memory for 00948 * @a thread_list. In case of an error, -1 is returned. If no 00949 * requested values are found, 0 is returned, otherwise correct 00950 * number of retrieved values are returned. 00951 */ 00952 ssize_t thread_list (ACE_Task_Base *task, 00953 ACE_thread_t thread_list[], 00954 size_t n); 00955 00956 /** 00957 * Returns in @a hthread_list a list of up to @a n thread handles in 00958 * an ACE_Task_Base. The caller must allocate memory for 00959 * @a hthread_list. In case of an error, -1 is returned. If no 00960 * requested values are found, 0 is returned, otherwise correct 00961 * number of retrieved values are returned. 00962 */ 00963 ssize_t hthread_list (ACE_Task_Base *task, 00964 ACE_hthread_t hthread_list[], 00965 size_t n); 00966 00967 /** 00968 * Returns in @a thread_list a list of up to @a n thread ids in a 00969 * group @a grp_id. The caller must allocate the memory for 00970 * @a thread_list. In case of an error, -1 is returned. If no 00971 * requested values are found, 0 is returned, otherwise correct 00972 * number of retrieved values are returned. 00973 */ 00974 ssize_t thread_grp_list (int grp_id, 00975 ACE_thread_t thread_list[], 00976 size_t n); 00977 00978 /** 00979 * Returns in @a hthread_list a list of up to @a n thread handles in 00980 * a group @a grp_id. The caller must allocate memory for 00981 * @a hthread_list. 00982 */ 00983 ssize_t hthread_grp_list (int grp_id, 00984 ACE_hthread_t hthread_list[], 00985 size_t n); 00986 00987 /** 00988 * Returns a list of ACE_Task_Base pointers corresponding to the tasks 00989 * that have active threads managed by this instance. 00990 * 00991 * @param task_list is a pointer to an array to receive the list of pointers. 00992 * The caller is responsible for supplying an array with at 00993 * least @arg n entries. 00994 * 00995 * @param n The maximum number of ACE_Task_Base pointers to write 00996 * in @arg task_list. 00997 * 00998 * @retval If successful, the number of pointers returned, which will be 00999 * no greater than @arg n. Returns -1 on error. 01000 * 01001 * @note This method has no way to indicate if there are more than 01002 * @arg n ACE_Task_Base pointers available. Therefore, it may be 01003 * wise to guess a larger value of @arg n than one thinks in cases 01004 * where the exact number of tasks is not known. 01005 * 01006 * @sa count_threads() 01007 */ 01008 ssize_t task_all_list (ACE_Task_Base *task_list[], 01009 size_t n); 01010 01011 /** 01012 * Returns in @a thread_list a list of up to @a n thread ids. The 01013 * caller must allocate the memory for @a thread_list. In case of an 01014 * error, -1 is returned. If no requested values are found, 0 is 01015 * returned, otherwise correct number of retrieved values are 01016 * returned. 01017 */ 01018 ssize_t thread_all_list (ACE_thread_t thread_list[], 01019 size_t n); 01020 01021 /// Set group ids for a particular task. 01022 int set_grp (ACE_Task_Base *task, int grp_id); 01023 01024 /// Get group ids for a particular task. 01025 int get_grp (ACE_Task_Base *task, int &grp_id); 01026 01027 /// Return a count of the current number of threads active in the 01028 /// <Thread_Manager>. 01029 size_t count_threads (void) const; 01030 01031 /// Get the state of the thread. Returns false if the thread is not 01032 /// managed by this thread manager. 01033 int thr_state (ACE_thread_t id, ACE_UINT32& state); 01034 01035 /** 01036 * Register an At_Thread_Exit hook and the ownership is acquire by 01037 * Thread_Descriptor, this is the usual case when the AT is dynamically 01038 * allocated. 01039 */ 01040 int at_exit (ACE_At_Thread_Exit* cleanup); 01041 01042 /// Register an At_Thread_Exit hook and the ownership is retained for the 01043 /// caller. Normally used when the at_exit hook is created in stack. 01044 int at_exit (ACE_At_Thread_Exit& cleanup); 01045 01046 /** 01047 * 01048 ***** 01049 * @deprecated This function is deprecated. Please use the previous two 01050 * at_exit method. Notice that you should avoid mixing this method 01051 * with the previous two at_exit methods. 01052 ***** 01053 * 01054 * Register an object (or array) for cleanup at 01055 * thread termination. "cleanup_hook" points to a (global, or 01056 * static member) function that is called for the object or array 01057 * when it to be destroyed. It may perform any necessary cleanup 01058 * specific for that object or its class. "param" is passed as the 01059 * second parameter to the "cleanup_hook" function; the first 01060 * parameter is the object (or array) to be destroyed. 01061 * "cleanup_hook", for example, may delete the object (or array). 01062 * If <cleanup_hook> == 0, the <object> will _NOT_ get cleanup at 01063 * thread exit. You can use this to cancel the previously added 01064 * at_exit. 01065 */ 01066 int at_exit (void *object, 01067 ACE_CLEANUP_FUNC cleanup_hook, 01068 void *param); 01069 01070 /// Access function to determine whether the Thread_Manager will 01071 /// wait for its thread to exit or not when being closing down. 01072 void wait_on_exit (int dowait); 01073 int wait_on_exit (void); 01074 01075 /// Dump the state of an object. 01076 void dump (void); 01077 01078 /// Declare the dynamic allocation hooks. 01079 ACE_ALLOC_HOOK_DECLARE; 01080 01081 protected: 01082 // = Accessors for ACE_Thread_Descriptors. 01083 /** 01084 * Get a pointer to the calling thread's own thread_descriptor. 01085 * This must be called from a spawn thread. This function will 01086 * fetch the info from TSS. 01087 */ 01088 ACE_Thread_Descriptor *thread_desc_self (void); 01089 01090 /// Return a pointer to the thread's Thread_Descriptor, 01091 /// 0 if fail. 01092 ACE_Thread_Descriptor *thread_descriptor (ACE_thread_t); 01093 01094 /// Return a pointer to the thread's Thread_Descriptor, 01095 /// 0 if fail. 01096 ACE_Thread_Descriptor *hthread_descriptor (ACE_hthread_t); 01097 01098 /// Create a new thread (must be called with locks held). 01099 int spawn_i (ACE_THR_FUNC func, 01100 void *arg, 01101 long flags, 01102 ACE_thread_t * = 0, 01103 ACE_hthread_t *t_handle = 0, 01104 long priority = ACE_DEFAULT_THREAD_PRIORITY, 01105 int grp_id = -1, 01106 void *stack = 0, 01107 size_t stack_size = 0, 01108 ACE_Task_Base *task = 0, 01109 const char** thr_name = 0); 01110 01111 /// Run the registered hooks when the thread exits. 01112 void run_thread_exit_hooks (int i); 01113 01114 /// Locate the index of the table slot occupied by <t_id>. Returns 01115 /// -1 if <t_id> is not in the table doesn't contain <t_id>. 01116 ACE_Thread_Descriptor *find_thread (ACE_thread_t t_id); 01117 01118 /// Locate the index of the table slot occupied by <h_id>. Returns 01119 /// -1 if <h_id> is not in the table doesn't contain <h_id>. 01120 ACE_Thread_Descriptor *find_hthread (ACE_hthread_t h_id); 01121 01122 /** 01123 * Locate the thread descriptor address of the list occupied by 01124 * @a task. Returns 0 if @a task is not in the table doesn't contain 01125 * @a task. 01126 */ 01127 ACE_Thread_Descriptor *find_task (ACE_Task_Base *task, 01128 size_t slot = 0); 01129 01130 /// Insert a thread in the table (checks for duplicates). 01131 int insert_thr (ACE_thread_t t_id, 01132 ACE_hthread_t, 01133 int grp_id = -1, 01134 long flags = 0); 01135 01136 /// Append a thread in the table (adds at the end, growing the table 01137 /// if necessary). 01138 int append_thr (ACE_thread_t t_id, ACE_hthread_t, 01139 ACE_UINT32, 01140 int grp_id, 01141 ACE_Task_Base *task = 0, 01142 long flags = 0, 01143 ACE_Thread_Descriptor *td = 0); 01144 01145 /// Remove thread from the table. 01146 void remove_thr (ACE_Thread_Descriptor *td, 01147 int close_handler); 01148 01149 /// Remove all threads from the table. 01150 void remove_thr_all (void); 01151 01152 // = The following four methods implement a simple scheme for 01153 // operating on a collection of threads atomically. 01154 01155 /** 01156 * Efficiently check whether @a thread is in a particular @a state. 01157 * This call updates the TSS cache if possible to speed up 01158 * subsequent searches. 01159 */ 01160 int check_state (ACE_UINT32 state, 01161 ACE_thread_t thread, 01162 int enable = 1); 01163 01164 /// Apply @a func to all members of the table that match the @a task 01165 int apply_task (ACE_Task_Base *task, 01166 ACE_THR_MEMBER_FUNC func, 01167 int = 0); 01168 01169 /// Apply @a func to all members of the table that match the @a grp_id. 01170 int apply_grp (int grp_id, 01171 ACE_THR_MEMBER_FUNC func, 01172 int arg = 0); 01173 01174 /// Apply @a func to all members of the table. 01175 int apply_all (ACE_THR_MEMBER_FUNC, 01176 int = 0); 01177 01178 /// Join the thread described in @a td. 01179 int join_thr (ACE_Thread_Descriptor *td, 01180 int = 0); 01181 01182 /// Resume the thread described in @a td. 01183 int resume_thr (ACE_Thread_Descriptor *td, 01184 int = 0); 01185 01186 /// Suspend the thread described in @a td. 01187 int suspend_thr (ACE_Thread_Descriptor *td, 01188 int = 0); 01189 01190 /// Send signal @a signum to the thread described in @a td. 01191 int kill_thr (ACE_Thread_Descriptor *td, 01192 int signum); 01193 01194 /// Set the cancellation flag for the thread described in @a td. 01195 int cancel_thr (ACE_Thread_Descriptor *td, 01196 int async_cancel = 0); 01197 01198 /// Register a thread as terminated and put it into the <terminated_thr_list_>. 01199 int register_as_terminated (ACE_Thread_Descriptor *td); 01200 01201 /// Setting the static ACE_TSS_TYPE (ACE_Thread_Exit) *thr_exit_ pointer. 01202 static int set_thr_exit (ACE_TSS_TYPE (ACE_Thread_Exit) *ptr); 01203 01204 /** 01205 * Keeping a list of thread descriptors within the thread manager. 01206 * Double-linked list enables us to cache the entries in TSS 01207 * and adding/removing thread descriptor entries without 01208 * affecting other thread's descriptor entries. 01209 */ 01210 ACE_Double_Linked_List<ACE_Thread_Descriptor> thr_list_; 01211 01212 #if !defined (ACE_HAS_VXTHREADS) 01213 /// Collect terminated but not yet joined thread entries. 01214 ACE_Double_Linked_List<ACE_Thread_Descriptor_Base> terminated_thr_list_; 01215 #endif /* !ACE_HAS_VXTHREADS */ 01216 01217 /// Collect pointers to thread descriptors of threads to be removed later. 01218 ACE_Unbounded_Queue<ACE_Thread_Descriptor*> thr_to_be_removed_; 01219 01220 /// Keeps track of the next group id to assign. 01221 int grp_id_; 01222 01223 /// Set if we want the Thread_Manager to wait on all threads before 01224 /// being closed, reset otherwise. 01225 int automatic_wait_; 01226 01227 // = ACE_Thread_Mutex and condition variable for synchronizing termination. 01228 #if defined (ACE_HAS_THREADS) 01229 /// Serialize access to the <zero_cond_>. 01230 ACE_Thread_Mutex lock_; 01231 01232 /// Keep track of when there are no more threads. 01233 ACE_Condition_Thread_Mutex zero_cond_; 01234 #endif /* ACE_HAS_THREADS */ 01235 01236 ACE_Locked_Free_List<ACE_Thread_Descriptor, ACE_SYNCH_MUTEX> thread_desc_freelist_; 01237 01238 private: 01239 #if ! defined (ACE_THREAD_MANAGER_LACKS_STATICS) 01240 /// Pointer to a process-wide ACE_Thread_Manager. 01241 static ACE_Thread_Manager *thr_mgr_; 01242 01243 /// Must delete the thr_mgr_ if true. 01244 static bool delete_thr_mgr_; 01245 01246 /// Global ACE_TSS (ACE_Thread_Exit) object ptr. 01247 static ACE_TSS_TYPE (ACE_Thread_Exit) *thr_exit_; 01248 #endif /* ! defined (ACE_THREAD_MANAGER_LACKS_STATICS) */ 01249 }; 01250 01251 #if defined (ACE_THREAD_MANAGER_LACKS_STATICS) 01252 #define ACE_THREAD_MANAGER_SINGLETON_DEFINE \ 01253 ACE_Singleton<ACE_Thread_Manager, ACE_SYNCH_MUTEX>; 01254 typedef ACE_Singleton<ACE_Thread_Manager, ACE_SYNCH_MUTEX> ACE_THREAD_MANAGER_SINGLETON; 01255 #endif /* defined (ACE_THREAD_MANAGER_LACKS_STATICS) */ 01256 01257 ACE_END_VERSIONED_NAMESPACE_DECL 01258 01259 #if defined (__ACE_INLINE__) 01260 #include "ace/Thread_Manager.inl" 01261 #endif /* __ACE_INLINE__ */ 01262 01263 #include /**/ "ace/post.h" 01264 #endif /* ACE_THREAD_MANAGER_H */