00001 // -*- C++ -*- 00002 00003 //============================================================================= 00004 /** 00005 * @file Thread_Manager.h 00006 * 00007 * $Id: Thread_Manager.h 83956 2008-12-03 07:57:38Z johnnyw $ 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 bool was_applied (void) const; 00108 00109 /// Set applied state of At_Thread_Exit. 00110 bool was_applied (bool 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 bool 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 #if 0 00332 /// Currently not used 00333 /** 00334 * Stores the cleanup info for a thread. 00335 * @note This should be generalized to be a stack of ACE_Cleanup_Info's. 00336 */ 00337 ACE_Cleanup_Info_Node_List cleanup_info_; 00338 #endif 00339 00340 /// Pointer to an ACE_Thread_Manager or NULL if there's no 00341 /// ACE_Thread_Manager> 00342 ACE_Thread_Manager* tm_; 00343 00344 /// Registration lock to prevent premature removal of thread descriptor. 00345 ACE_DEFAULT_THREAD_MANAGER_LOCK *sync_; 00346 00347 /// Keep track of termination status. 00348 bool terminated_; 00349 }; 00350 00351 // Forward declaration. 00352 class ACE_Thread_Control; 00353 00354 // This typedef should be (and used to be) inside the 00355 // ACE_Thread_Manager declaration. But, it caused compilation 00356 // problems on g++/VxWorks/i960 with -g. Note that 00357 // ACE_Thread_Manager::THR_FUNC is only used internally in 00358 // ACE_Thread_Manager, so it's not useful for anyone else. 00359 // It also caused problems on IRIX5 with g++. 00360 #if defined (__GNUG__) 00361 typedef int (ACE_Thread_Manager::*ACE_THR_MEMBER_FUNC)(ACE_Thread_Descriptor *, int); 00362 #endif /* __GNUG__ */ 00363 00364 /** 00365 * @class ACE_Thread_Manager 00366 * 00367 * @brief Manages a pool of threads. 00368 * 00369 * This class allows operations on groups of threads atomically. 00370 * The default behavior of thread manager is to wait on 00371 * all threads under it's management when it gets destructed. 00372 * Therefore, remember to remove a thread from thread manager if 00373 * you don't want it to wait for the thread. There are also 00374 * functions to disable this default wait-on-exit behavior. 00375 * However, if your program depends on turning this off to run 00376 * correctly, you are probably doing something wrong. Rule of 00377 * thumb, use ACE_Thread to manage your daemon threads. 00378 * Notice that if there're threads which live beyond the scope of 00379 * main(), you are sure to have resource leaks in your program. 00380 * Remember to wait on threads before exiting your main program if that 00381 * could happen in your programs. 00382 */ 00383 class ACE_Export ACE_Thread_Manager 00384 { 00385 public: 00386 friend class ACE_Thread_Control; 00387 00388 // Allow ACE_THread_Exit to register the global TSS instance object. 00389 friend class ACE_Thread_Exit; 00390 friend class ACE_Thread_Descriptor; 00391 00392 #if !defined (__GNUG__) 00393 typedef int (ACE_Thread_Manager::*ACE_THR_MEMBER_FUNC)(ACE_Thread_Descriptor *, int); 00394 #endif /* !__GNUG__ */ 00395 00396 /// These are the various states a thread managed by the 00397 /// ACE_Thread_Manager can be in. 00398 enum 00399 { 00400 /// Uninitialized. 00401 ACE_THR_IDLE = 0x00000000, 00402 00403 /// Created but not yet running. 00404 ACE_THR_SPAWNED = 0x00000001, 00405 00406 /// Thread is active (naturally, we don't know if it's actually 00407 /// *running* because we aren't the scheduler...). 00408 ACE_THR_RUNNING = 0x00000002, 00409 00410 /// Thread is suspended. 00411 ACE_THR_SUSPENDED = 0x00000004, 00412 00413 /// Thread has been cancelled (which is an indiction that it needs to 00414 /// terminate...). 00415 ACE_THR_CANCELLED = 0x00000008, 00416 00417 /// Thread has shutdown, but the slot in the thread manager hasn't 00418 /// been reclaimed yet. 00419 ACE_THR_TERMINATED = 0x00000010, 00420 00421 /// Join operation has been invoked on the thread by thread manager. 00422 ACE_THR_JOINING = 0x10000000 00423 }; 00424 00425 /** 00426 * @brief Initialization and termination methods. 00427 * 00428 * Internally, ACE_Thread_Manager keeps a freelist for caching 00429 * resources it uses to keep track of managed threads (not the 00430 * threads themselves.) @a prealloc, @a lwm, @a inc, @hwm 00431 * determine the initial size, the low water mark, increment step, 00432 * and high water mark of the freelist. 00433 * 00434 * @sa ACE_Free_List 00435 */ 00436 ACE_Thread_Manager (size_t preaolloc = ACE_DEFAULT_THREAD_MANAGER_PREALLOC, 00437 size_t lwm = ACE_DEFAULT_THREAD_MANAGER_LWM, 00438 size_t inc = ACE_DEFAULT_THREAD_MANAGER_INC, 00439 size_t hwm = ACE_DEFAULT_THREAD_MANAGER_HWM); 00440 ~ACE_Thread_Manager (void); 00441 00442 #if ! defined (ACE_THREAD_MANAGER_LACKS_STATICS) 00443 /// Get pointer to a process-wide ACE_Thread_Manager. 00444 static ACE_Thread_Manager *instance (void); 00445 00446 /// Set pointer to a process-wide ACE_Thread_Manager and return 00447 /// existing pointer. 00448 static ACE_Thread_Manager *instance (ACE_Thread_Manager *); 00449 00450 /// Delete the dynamically allocated Singleton 00451 static void close_singleton (void); 00452 #endif /* ! defined (ACE_THREAD_MANAGER_LACKS_STATICS) */ 00453 00454 /// No-op. Currently unused. 00455 int open (size_t size = 0); 00456 00457 /** 00458 * Release all resources. 00459 * By default, this method will wait until all threads exit. 00460 * However, when called from close_singleton(), most global resources 00461 * are destroyed and thus, close() does not try to wait; it simply cleans 00462 * up internal thread records (the thread descriptor list). 00463 */ 00464 int close (void); 00465 00466 /** 00467 * Create a new thread, which executes @a func with argument @a arg. 00468 * 00469 * @param func The function that is called in the spawned thread. 00470 * 00471 * @param arg The value passed to each spawned thread's @a func. 00472 * 00473 * @param flags Flags to control attributes of the spawned threads. 00474 * @sa ACE_OS::thr_create() for descriptions of the 00475 * possible flags values and their interactions. 00476 * 00477 * @param t_id Pointer to a location to receive the spawned thread's 00478 * ID. If 0, the ID is not returned. 00479 * 00480 * @param t_handle Pointer to a location to receive the spawned thread's 00481 * thread handle. If 0, the handle is not returned. 00482 * 00483 * @param priority The priority at which the thread is spawned. 00484 * 00485 * @param grp_id The thread group that the spawned thread is 00486 * added to. If -1 is specified, a new thread group is 00487 * created for the spawned thread. 00488 * 00489 * @param stack Pointers to the base of a pre-allocated stack space 00490 * for the thread's stack. If 0, the platform allocates 00491 * stack space for the thread. If a stack is specified, 00492 * it is recommended that @a stack_size also be supplied 00493 * to specify the size of the stack. 00494 * Not all platforms support pre-allocated stacks. If 00495 * @a stack is specified for a platform which does not 00496 * allow pre-allocated stack space this parameter is 00497 * ignored. 00498 * 00499 * @param stack_size Indicate how large the thread's stack should be, in 00500 * bytes. If a pre-allocated stack pointer is passed in 00501 * @a stack, @a stack_size indicates the size of that 00502 * stack area. If no pre-allocated stack is passed, 00503 * the stack size specified is passed to the 00504 * operating system to request that it allocate a stack 00505 * of the specified size. 00506 * 00507 * @param thr_name Pointer to a name to assign to the spawned thread. 00508 * This is only meaningful for platforms that have a 00509 * capacity to name threads (e.g., VxWorks and some 00510 * varieties of Pthreads). This argument is ignored if 00511 * specified as 0 and on platforms that do not have the 00512 * capability to name threads. 00513 * 00514 * @retval -1 on failure; @c errno contains an error value. 00515 * @retval The group id of the spawned thread. 00516 */ 00517 int spawn (ACE_THR_FUNC func, 00518 void *arg = 0, 00519 long flags = THR_NEW_LWP | THR_JOINABLE | THR_INHERIT_SCHED, 00520 ACE_thread_t *t_id = 0, 00521 ACE_hthread_t *t_handle = 0, 00522 long priority = ACE_DEFAULT_THREAD_PRIORITY, 00523 int grp_id = -1, 00524 void *stack = 0, 00525 size_t stack_size = ACE_DEFAULT_THREAD_STACKSIZE, 00526 const char** thr_name = 0); 00527 00528 /** 00529 * Spawn a specified number of threads, all of which execute @a func 00530 * with argument @a arg. 00531 * 00532 * @param n The number of threads to spawn. 00533 * 00534 * @param func The function that is called in the spawned thread. 00535 * 00536 * @param arg The value passed to each spawned thread's @a func. 00537 * 00538 * @param flags Flags to control attributes of the spawned threads. 00539 * @sa ACE_OS::thr_create() for descriptions of the 00540 * possible flags values and their interactions. 00541 * 00542 * @param priority The priority at which the threads are spawned. 00543 * 00544 * @param grp_id The thread group that the spawned threads are 00545 * added to. If -1 is specified, a new thread group is 00546 * created for the spawned threads. 00547 * 00548 * @param task The ACE_Task that the spawned threads are associated 00549 * with. If 0, the threads are not associated with an 00550 * ACE_Task. This argument is usually assigned by the 00551 * ACE_Task_Base::activate() method to associate the 00552 * spawned threads with the spawning ACE_Task object. 00553 * 00554 * @param thread_handles An array of @a n entries which will receive 00555 * the thread handles of the spawned threads. 00556 * 00557 * @param stack An array of @a n pointers to pre-allocated stack space 00558 * for each thread's stack. If specified as 0, the 00559 * platform allocates stack space for each thread. If 00560 * a stack is specified, it is recommended that a 00561 * @a stack_size element also be supplied that specifies 00562 * the size of the stack. 00563 * Not all platforms support pre-allocated stacks. If 00564 * @a stack is specified for a platform which does not 00565 * allow pre-allocated stack space this parameter is 00566 * ignored. 00567 * 00568 * @param stack_size An array of @a n values which indicate how large 00569 * each thread's stack should be, in bytes. 00570 * If pre-allocated stacks are passed in @a stacks, these 00571 * sizes are for those stacks. If no pre-allocated stacks 00572 * are passed, the stack sizes are specified to the 00573 * operating system to request that it allocate stacks 00574 * of the specified sizes. If an array entry is 0, the 00575 * platform defaults are used for the corresponding thread. 00576 * If a 0 array pointer is specified, platform defaults 00577 * are used for all thread stack sizes. 00578 * 00579 * @param thr_name An array of names to assign to the spawned threads. 00580 * This is only meaningful for platforms that have a 00581 * capacity to name threads (e.g., VxWorks and some 00582 * varieties of Pthreads). This argument is ignored if 00583 * specified as 0 and on platforms that do not have the 00584 * capability to name threads. 00585 * 00586 * ACE_Thread_Manager can manipulate threads in groups based on 00587 * @a grp_id or @a task using functions such as kill_grp() or 00588 * cancel_task(). 00589 * 00590 * @retval -1 on failure; @c errno contains an error value. 00591 * @retval The group id of the threads. 00592 */ 00593 int spawn_n (size_t n, 00594 ACE_THR_FUNC func, 00595 void *arg = 0, 00596 long flags = THR_NEW_LWP | THR_JOINABLE | THR_INHERIT_SCHED, 00597 long priority = ACE_DEFAULT_THREAD_PRIORITY, 00598 int grp_id = -1, 00599 ACE_Task_Base *task = 0, 00600 ACE_hthread_t thread_handles[] = 0, 00601 void *stack[] = 0, 00602 size_t stack_size[] = 0, 00603 const char* thr_name[] = 0); 00604 00605 /** 00606 * Spawn a specified number of threads, all of which execute @a func 00607 * with argument @a arg. 00608 * 00609 * @param thread_ids An array to receive the thread IDs of successfully 00610 * spawned buffer. If 0, the thread IDs are not returned. 00611 * If specified, the array must be at least @a n entries. 00612 * 00613 * @param n The number of threads to spawn. 00614 * 00615 * @param func The function that is called in the spawned thread. 00616 * 00617 * @param arg The value passed to each spawned thread's @a func. 00618 * 00619 * @param flags Flags to control attributes of the spawned threads. 00620 * @sa ACE_OS::thr_create() for descriptions of the 00621 * possible flags values and their interactions. 00622 * 00623 * @param priority The priority at which the threads are spawned. 00624 * 00625 * @param grp_id The thread group that the spawned threads are 00626 * added to. If -1 is specified, a new thread group is 00627 * created for the spawned threads. 00628 * 00629 * @param stack An array of @a n pointers to pre-allocated stack space 00630 * for each thread's stack. If specified as 0, the 00631 * platform allocates stack space for each thread. If 00632 * a stack is specified, it is recommended that a 00633 * @a stack_size element also be supplied that specifies 00634 * the size of the stack. 00635 * Not all platforms support pre-allocated stacks. If 00636 * @a stack is specified for a platform which does not 00637 * allow pre-allocated stack space this parameter is 00638 * ignored. 00639 * 00640 * @param stack_size An array of @a n values which indicate how large 00641 * each thread's stack should be, in bytes. 00642 * If pre-allocated stacks are passed in @a stacks, these 00643 * sizes are for those stacks. If no pre-allocated stacks 00644 * are passed, the stack sizes are specified to the 00645 * operating system to request that it allocate stacks 00646 * of the specified sizes. If an array entry is 0, the 00647 * platform defaults are used for the corresponding thread. 00648 * If a 0 array pointer is specified, platform defaults 00649 * are used for all thread stack sizes. 00650 * 00651 * @param thread_handles An array of @a n entries which will receive 00652 * the thread handles of the spawned threads. 00653 * 00654 * @param task The ACE_Task that the spawned threads are associated 00655 * with. If 0, the threads are not associated with an 00656 * ACE_Task. This argument is usually assigned by the 00657 * ACE_Task_Base::activate() method to associate the 00658 * spawned threads with the spawning ACE_Task object. 00659 * 00660 * @param thr_name An array of names to assign to the spawned threads. 00661 * This is only meaningful for platforms that have a 00662 * capacity to name threads (e.g., VxWorks and some 00663 * varieties of Pthreads). This argument is ignored if 00664 * specified as 0 and on platforms that do not have the 00665 * capability to name threads. 00666 * 00667 * ACE_Thread_Manager can manipulate threads in groups based on 00668 * @a grp_id or @a task using functions such as kill_grp() or 00669 * cancel_task(). 00670 * 00671 * @retval -1 on failure; @c errno contains an error value. 00672 * @retval The group id of the threads. 00673 00674 */ 00675 int spawn_n (ACE_thread_t thread_ids[], 00676 size_t n, 00677 ACE_THR_FUNC func, 00678 void *arg, 00679 long flags, 00680 long priority = ACE_DEFAULT_THREAD_PRIORITY, 00681 int grp_id = -1, 00682 void *stack[] = 0, 00683 size_t stack_size[] = 0, 00684 ACE_hthread_t thread_handles[] = 0, 00685 ACE_Task_Base *task = 0, 00686 const char* thr_name[] = 0); 00687 00688 /** 00689 * Called to clean up when a thread exits. 00690 * 00691 * @param do_thread_exit If non-0 then ACE_Thread::exit is called to 00692 * exit the thread 00693 * @param status If ACE_Thread_Exit is called, this is passed as 00694 * the exit value of the thread. 00695 * Should _not_ be called by main thread. 00696 */ 00697 ACE_THR_FUNC_RETURN exit (ACE_THR_FUNC_RETURN status = 0, 00698 bool do_thread_exit = true); 00699 00700 /** 00701 * Block until there are no more threads running in this thread 00702 * manager or @c timeout expires. 00703 * 00704 * @param timeout is treated as "absolute" time by default, but this 00705 * can be changed to "relative" time by setting the @c 00706 * use_absolute_time to false. 00707 * @param abandon_detached_threads If true, @c wait() will first 00708 * check thru its thread list for 00709 * threads with THR_DETACHED or 00710 * THR_DAEMON flags set and remove 00711 * these threads. Notice that 00712 * unlike other @c wait_*() methods, 00713 * by default, @c wait() does wait on 00714 * all thread spawned by this 00715 * thread manager no matter the detached 00716 * flags are set or not unless it is 00717 * called with @c 00718 * abandon_detached_threads flag set. 00719 * @param use_absolute_time If true then treat @c timeout as 00720 * absolute time, else relative time. 00721 * @return 0 on success * and -1 on failure. 00722 * 00723 * @note If this function is called while the @c 00724 * ACE_Object_Manager is shutting down (as a result of program 00725 * rundown via @c ACE::fini()), it will not wait for any threads to 00726 * complete. If you must wait for threads spawned by this thread 00727 * manager to complete and you are in a ACE rundown situation (such 00728 * as your object is being destroyed by the @c ACE_Object_Manager) 00729 * you can use @c wait_grp() instead. 00730 */ 00731 int wait (const ACE_Time_Value *timeout = 0, 00732 bool abandon_detached_threads = false, 00733 bool use_absolute_time = true); 00734 00735 /// Join a thread specified by @a tid. Do not wait on a detached thread. 00736 int join (ACE_thread_t tid, ACE_THR_FUNC_RETURN *status = 0); 00737 00738 /** 00739 * Block until there are no more threads running in a group. 00740 * Returns 0 on success and -1 on failure. Notice that wait_grp 00741 * will not wait on detached threads. 00742 */ 00743 int wait_grp (int grp_id); 00744 00745 /** 00746 * Return the "real" handle to the calling thread, caching it if 00747 * necessary in TSS to speed up subsequent lookups. This is 00748 * necessary since on some platforms (e.g., Windows) we can't get this 00749 * handle via direct method calls. Notice that you should *not* 00750 * close the handle passed back from this method. It is used 00751 * internally by Thread Manager. On the other hand, you *have to* 00752 * use this internal thread handle when working on Thread_Manager. 00753 * Return -1 if fail. 00754 */ 00755 int thr_self (ACE_hthread_t &); 00756 00757 /** 00758 * Return the unique ID of the calling thread. 00759 * Same as calling ACE_Thread::self(). 00760 */ 00761 ACE_thread_t thr_self (void); 00762 00763 /** 00764 * Returns a pointer to the current ACE_Task_Base we're executing 00765 * in if this thread is indeed running in an ACE_Task_Base, else 00766 * return 0. 00767 */ 00768 ACE_Task_Base *task (void); 00769 00770 /** 00771 * @name Suspend and resume methods 00772 * 00773 * Suspend/resume is not supported on all platforms. For example, Pthreads 00774 * does not support these functions. 00775 */ 00776 //@{ 00777 00778 /// Suspend all threads 00779 int suspend_all (void); 00780 00781 /// Suspend a single thread. 00782 int suspend (ACE_thread_t); 00783 00784 /// Suspend a group of threads. 00785 int suspend_grp (int grp_id); 00786 00787 /** 00788 * True if @a t_id is inactive (i.e., suspended), else false. Always 00789 * return false if @a t_id is not managed by the Thread_Manager. 00790 */ 00791 int testsuspend (ACE_thread_t t_id); 00792 00793 /// Resume all stopped threads 00794 int resume_all (void); 00795 00796 /// Resume a single thread. 00797 int resume (ACE_thread_t); 00798 00799 /// Resume a group of threads. 00800 int resume_grp (int grp_id); 00801 00802 /** 00803 * True if @a t_id is active (i.e., resumed), else false. Always 00804 * return false if @a t_id is not managed by the Thread_Manager. 00805 */ 00806 int testresume (ACE_thread_t t_id); 00807 00808 //@} 00809 00810 // = Send signals to one or more threads without blocking. 00811 /** 00812 * Send @a signum to all stopped threads. Not supported on platforms 00813 * that do not have advanced signal support, such as Win32. 00814 */ 00815 int kill_all (int signum); 00816 /** 00817 * Send the @a signum to a single thread. Not supported on platforms 00818 * that do not have advanced signal support, such as Win32. 00819 */ 00820 int kill (ACE_thread_t, int signum); 00821 /** 00822 * Send @a signum to a group of threads, not supported on platforms 00823 * that do not have advanced signal support, such as Win32. 00824 */ 00825 int kill_grp (int grp_id, int signum); 00826 00827 // = Cancel methods, which provides a cooperative thread-termination mechanism (will not block). 00828 /** 00829 * Cancel's all the threads. 00830 */ 00831 int cancel_all (int async_cancel = 0); 00832 00833 /** 00834 * Cancel a single thread. 00835 */ 00836 int cancel (ACE_thread_t, int async_cancel = 0); 00837 00838 /** 00839 * Cancel a group of threads. 00840 */ 00841 int cancel_grp (int grp_id, int async_cancel = 0); 00842 00843 /** 00844 * True if @a t_id is cancelled, else false. Always return false if 00845 * @a t_id is not managed by the Thread_Manager. 00846 */ 00847 int testcancel (ACE_thread_t t_id); 00848 00849 /** 00850 * True if @a t_id has terminated (i.e., is no longer running), 00851 * but the slot in the thread manager hasn't been reclaimed yet, 00852 * else false. Always return false if @a t_id is not managed by the 00853 * Thread_Manager. 00854 */ 00855 int testterminate (ACE_thread_t t_id); 00856 00857 /// Set group ids for a particular thread id. 00858 int set_grp (ACE_thread_t, 00859 int grp_id); 00860 00861 /// Get group ids for a particular thread id. 00862 int get_grp (ACE_thread_t, 00863 int &grp_id); 00864 00865 /** 00866 * @name Task-related operations 00867 */ 00868 //@{ 00869 /** 00870 * Block until there are no more threads running in a specified task. 00871 * This method will not wait for either detached or daemon threads; 00872 * the threads must have been spawned with the @c THR_JOINABLE flag. 00873 * Upon successful completion, the threads have been joined, so further 00874 * attempts to join with any of the waited-for threads will fail. 00875 * 00876 * @param task The ACE_Task_Base object whose threads are to waited for. 00877 * 00878 * @retval 0 Success. 00879 * @retval -1 Failure (consult errno for further information). 00880 */ 00881 int wait_task (ACE_Task_Base *task); 00882 00883 /** 00884 * Suspend all threads in an ACE_Task. 00885 */ 00886 int suspend_task (ACE_Task_Base *task); 00887 00888 /** 00889 * Resume all threads in an ACE_Task. 00890 */ 00891 int resume_task (ACE_Task_Base *task); 00892 00893 /** 00894 * Send a signal @a signum to all threads in an ACE_Task. 00895 */ 00896 int kill_task (ACE_Task_Base *task, int signum); 00897 00898 /** 00899 * Cancel all threads in an ACE_Task. If <async_cancel> is non-0, 00900 * then asynchronously cancel these threads if the OS platform 00901 * supports cancellation. Otherwise, perform a "cooperative" 00902 * cancellation. 00903 */ 00904 int cancel_task (ACE_Task_Base *task, int async_cancel = 0); 00905 00906 //@} 00907 00908 // = Collect thread handles in the thread manager. Notice that 00909 // the collected information is just a snapshot. 00910 /// Check if the thread is managed by the thread manager. Return true if 00911 /// the thread is found, false otherwise. 00912 int hthread_within (ACE_hthread_t handle); 00913 int thread_within (ACE_thread_t tid); 00914 00915 /// Returns the number of ACE_Task_Base in a group. 00916 int num_tasks_in_group (int grp_id); 00917 00918 /// Returns the number of threads in an ACE_Task_Base. 00919 int num_threads_in_task (ACE_Task_Base *task); 00920 00921 /** 00922 * Returns a list of ACE_Task_Base pointers corresponding to the tasks 00923 * that have active threads in a specified thread group. 00924 * 00925 * @param grp_id The thread group ID to obtain task pointers for. 00926 * 00927 * @param task_list is a pointer to an array to receive the list of pointers. 00928 * The caller is responsible for supplying an array with at 00929 * least @arg n entries. 00930 * 00931 * @param n The maximum number of ACE_Task_Base pointers to write 00932 * in @arg task_list. 00933 * 00934 * @retval If successful, the number of pointers returned, which will be 00935 * no greater than @arg n. Returns -1 on error. 00936 * 00937 * @note This method has no way to indicate if there are more than 00938 * @arg n ACE_Task_Base pointers available. Therefore, it may be 00939 * wise to guess a larger value of @arg n than one thinks in cases 00940 * where the exact number of tasks is not known. 00941 * 00942 * @sa num_tasks_in_group(), task_all_list() 00943 */ 00944 ssize_t task_list (int grp_id, 00945 ACE_Task_Base *task_list[], 00946 size_t n); 00947 00948 /** 00949 * Returns in @a thread_list a list of up to @a n thread ids in an 00950 * ACE_Task_Base. The caller must allocate the memory for 00951 * @a thread_list. In case of an error, -1 is returned. If no 00952 * requested values are found, 0 is returned, otherwise correct 00953 * number of retrieved values are returned. 00954 */ 00955 ssize_t thread_list (ACE_Task_Base *task, 00956 ACE_thread_t thread_list[], 00957 size_t n); 00958 00959 /** 00960 * Returns in @a hthread_list a list of up to @a n thread handles in 00961 * an ACE_Task_Base. The caller must allocate memory for 00962 * @a hthread_list. In case of an error, -1 is returned. If no 00963 * requested values are found, 0 is returned, otherwise correct 00964 * number of retrieved values are returned. 00965 */ 00966 ssize_t hthread_list (ACE_Task_Base *task, 00967 ACE_hthread_t hthread_list[], 00968 size_t n); 00969 00970 /** 00971 * Returns in @a thread_list a list of up to @a n thread ids in a 00972 * group @a grp_id. The caller must allocate the memory for 00973 * @a thread_list. In case of an error, -1 is returned. If no 00974 * requested values are found, 0 is returned, otherwise correct 00975 * number of retrieved values are returned. 00976 */ 00977 ssize_t thread_grp_list (int grp_id, 00978 ACE_thread_t thread_list[], 00979 size_t n); 00980 00981 /** 00982 * Returns in @a hthread_list a list of up to @a n thread handles in 00983 * a group @a grp_id. The caller must allocate memory for 00984 * @a hthread_list. 00985 */ 00986 ssize_t hthread_grp_list (int grp_id, 00987 ACE_hthread_t hthread_list[], 00988 size_t n); 00989 00990 /** 00991 * Returns a list of ACE_Task_Base pointers corresponding to the tasks 00992 * that have active threads managed by this instance. 00993 * 00994 * @param task_list is a pointer to an array to receive the list of pointers. 00995 * The caller is responsible for supplying an array with at 00996 * least @arg n entries. 00997 * 00998 * @param n The maximum number of ACE_Task_Base pointers to write 00999 * in @arg task_list. 01000 * 01001 * @retval If successful, the number of pointers returned, which will be 01002 * no greater than @arg n. Returns -1 on error. 01003 * 01004 * @note This method has no way to indicate if there are more than 01005 * @arg n ACE_Task_Base pointers available. Therefore, it may be 01006 * wise to guess a larger value of @arg n than one thinks in cases 01007 * where the exact number of tasks is not known. 01008 * 01009 * @sa count_threads() 01010 */ 01011 ssize_t task_all_list (ACE_Task_Base *task_list[], 01012 size_t n); 01013 01014 /** 01015 * Returns in @a thread_list a list of up to @a n thread ids. The 01016 * caller must allocate the memory for @a thread_list. In case of an 01017 * error, -1 is returned. If no requested values are found, 0 is 01018 * returned, otherwise correct number of retrieved values are 01019 * returned. 01020 */ 01021 ssize_t thread_all_list (ACE_thread_t thread_list[], 01022 size_t n); 01023 01024 /// Set group ids for a particular task. 01025 int set_grp (ACE_Task_Base *task, int grp_id); 01026 01027 /// Get group ids for a particular task. 01028 int get_grp (ACE_Task_Base *task, int &grp_id); 01029 01030 /// Return a count of the current number of threads active in the 01031 /// <Thread_Manager>. 01032 size_t count_threads (void) const; 01033 01034 /// Get the state of the thread. Returns false if the thread is not 01035 /// managed by this thread manager. 01036 int thr_state (ACE_thread_t id, ACE_UINT32& state); 01037 01038 /** 01039 * Register an At_Thread_Exit hook and the ownership is acquire by 01040 * Thread_Descriptor, this is the usual case when the AT is dynamically 01041 * allocated. 01042 */ 01043 int at_exit (ACE_At_Thread_Exit* cleanup); 01044 01045 /// Register an At_Thread_Exit hook and the ownership is retained for the 01046 /// caller. Normally used when the at_exit hook is created in stack. 01047 int at_exit (ACE_At_Thread_Exit& cleanup); 01048 01049 /** 01050 * 01051 ***** 01052 * @deprecated This function is deprecated. Please use the previous two 01053 * at_exit method. Notice that you should avoid mixing this method 01054 * with the previous two at_exit methods. 01055 ***** 01056 * 01057 * Register an object (or array) for cleanup at 01058 * thread termination. "cleanup_hook" points to a (global, or 01059 * static member) function that is called for the object or array 01060 * when it to be destroyed. It may perform any necessary cleanup 01061 * specific for that object or its class. "param" is passed as the 01062 * second parameter to the "cleanup_hook" function; the first 01063 * parameter is the object (or array) to be destroyed. 01064 * "cleanup_hook", for example, may delete the object (or array). 01065 * If <cleanup_hook> == 0, the <object> will _NOT_ get cleanup at 01066 * thread exit. You can use this to cancel the previously added 01067 * at_exit. 01068 */ 01069 int at_exit (void *object, 01070 ACE_CLEANUP_FUNC cleanup_hook, 01071 void *param); 01072 01073 /// Access function to determine whether the Thread_Manager will 01074 /// wait for its thread to exit or not when being closing down. 01075 void wait_on_exit (int dowait); 01076 int wait_on_exit (void); 01077 01078 /// Dump the state of an object. 01079 void dump (void); 01080 01081 /// Declare the dynamic allocation hooks. 01082 ACE_ALLOC_HOOK_DECLARE; 01083 01084 protected: 01085 // = Accessors for ACE_Thread_Descriptors. 01086 /** 01087 * Get a pointer to the calling thread's own thread_descriptor. 01088 * This must be called from a spawn thread. This function will 01089 * fetch the info from TSS. 01090 */ 01091 ACE_Thread_Descriptor *thread_desc_self (void); 01092 01093 /// Return a pointer to the thread's Thread_Descriptor, 01094 /// 0 if fail. 01095 ACE_Thread_Descriptor *thread_descriptor (ACE_thread_t); 01096 01097 /// Return a pointer to the thread's Thread_Descriptor, 01098 /// 0 if fail. 01099 ACE_Thread_Descriptor *hthread_descriptor (ACE_hthread_t); 01100 01101 /// Create a new thread (must be called with locks held). 01102 int spawn_i (ACE_THR_FUNC func, 01103 void *arg, 01104 long flags, 01105 ACE_thread_t * = 0, 01106 ACE_hthread_t *t_handle = 0, 01107 long priority = ACE_DEFAULT_THREAD_PRIORITY, 01108 int grp_id = -1, 01109 void *stack = 0, 01110 size_t stack_size = 0, 01111 ACE_Task_Base *task = 0, 01112 const char** thr_name = 0); 01113 01114 /// Run the registered hooks when the thread exits. 01115 void run_thread_exit_hooks (int i); 01116 01117 /// Locate the index of the table slot occupied by <t_id>. Returns 01118 /// -1 if <t_id> is not in the table doesn't contain <t_id>. 01119 ACE_Thread_Descriptor *find_thread (ACE_thread_t t_id); 01120 01121 /// Locate the index of the table slot occupied by <h_id>. Returns 01122 /// -1 if <h_id> is not in the table doesn't contain <h_id>. 01123 ACE_Thread_Descriptor *find_hthread (ACE_hthread_t h_id); 01124 01125 /** 01126 * Locate the thread descriptor address of the list occupied by 01127 * @a task. Returns 0 if @a task is not in the table doesn't contain 01128 * @a task. 01129 */ 01130 ACE_Thread_Descriptor *find_task (ACE_Task_Base *task, 01131 size_t slot = 0); 01132 01133 /// Insert a thread in the table (checks for duplicates). 01134 int insert_thr (ACE_thread_t t_id, 01135 ACE_hthread_t, 01136 int grp_id = -1, 01137 long flags = 0); 01138 01139 /// Append a thread in the table (adds at the end, growing the table 01140 /// if necessary). 01141 int append_thr (ACE_thread_t t_id, ACE_hthread_t, 01142 ACE_UINT32, 01143 int grp_id, 01144 ACE_Task_Base *task = 0, 01145 long flags = 0, 01146 ACE_Thread_Descriptor *td = 0); 01147 01148 /// Remove thread from the table. 01149 void remove_thr (ACE_Thread_Descriptor *td, 01150 int close_handler); 01151 01152 /// Remove all threads from the table. 01153 void remove_thr_all (void); 01154 01155 // = The following four methods implement a simple scheme for 01156 // operating on a collection of threads atomically. 01157 01158 /** 01159 * Efficiently check whether @a thread is in a particular @a state. 01160 * This call updates the TSS cache if possible to speed up 01161 * subsequent searches. 01162 */ 01163 int check_state (ACE_UINT32 state, 01164 ACE_thread_t thread, 01165 int enable = 1); 01166 01167 /// Apply @a func to all members of the table that match the @a task 01168 int apply_task (ACE_Task_Base *task, 01169 ACE_THR_MEMBER_FUNC func, 01170 int = 0); 01171 01172 /// Apply @a func to all members of the table that match the @a grp_id. 01173 int apply_grp (int grp_id, 01174 ACE_THR_MEMBER_FUNC func, 01175 int arg = 0); 01176 01177 /// Apply @a func to all members of the table. 01178 int apply_all (ACE_THR_MEMBER_FUNC, 01179 int = 0); 01180 01181 /// Join the thread described in @a td. 01182 int join_thr (ACE_Thread_Descriptor *td, 01183 int = 0); 01184 01185 /// Resume the thread described in @a td. 01186 int resume_thr (ACE_Thread_Descriptor *td, 01187 int = 0); 01188 01189 /// Suspend the thread described in @a td. 01190 int suspend_thr (ACE_Thread_Descriptor *td, 01191 int = 0); 01192 01193 /// Send signal @a signum to the thread described in @a td. 01194 int kill_thr (ACE_Thread_Descriptor *td, 01195 int signum); 01196 01197 /// Set the cancellation flag for the thread described in @a td. 01198 int cancel_thr (ACE_Thread_Descriptor *td, 01199 int async_cancel = 0); 01200 01201 /// Register a thread as terminated and put it into the <terminated_thr_list_>. 01202 int register_as_terminated (ACE_Thread_Descriptor *td); 01203 01204 /// Setting the static ACE_TSS_TYPE (ACE_Thread_Exit) *thr_exit_ pointer. 01205 static int set_thr_exit (ACE_TSS_TYPE (ACE_Thread_Exit) *ptr); 01206 01207 /** 01208 * Keeping a list of thread descriptors within the thread manager. 01209 * Double-linked list enables us to cache the entries in TSS 01210 * and adding/removing thread descriptor entries without 01211 * affecting other thread's descriptor entries. 01212 */ 01213 ACE_Double_Linked_List<ACE_Thread_Descriptor> thr_list_; 01214 01215 #if !defined (ACE_HAS_VXTHREADS) 01216 /// Collect terminated but not yet joined thread entries. 01217 ACE_Double_Linked_List<ACE_Thread_Descriptor_Base> terminated_thr_list_; 01218 #endif /* !ACE_HAS_VXTHREADS */ 01219 01220 /// Collect pointers to thread descriptors of threads to be removed later. 01221 ACE_Unbounded_Queue<ACE_Thread_Descriptor*> thr_to_be_removed_; 01222 01223 /// Keeps track of the next group id to assign. 01224 int grp_id_; 01225 01226 /// Set if we want the Thread_Manager to wait on all threads before 01227 /// being closed, reset otherwise. 01228 int automatic_wait_; 01229 01230 // = ACE_Thread_Mutex and condition variable for synchronizing termination. 01231 #if defined (ACE_HAS_THREADS) 01232 /// Serialize access to the <zero_cond_>. 01233 ACE_Thread_Mutex lock_; 01234 01235 /// Keep track of when there are no more threads. 01236 ACE_Condition_Thread_Mutex zero_cond_; 01237 #endif /* ACE_HAS_THREADS */ 01238 01239 ACE_Locked_Free_List<ACE_Thread_Descriptor, ACE_SYNCH_MUTEX> thread_desc_freelist_; 01240 01241 private: 01242 #if ! defined (ACE_THREAD_MANAGER_LACKS_STATICS) 01243 /// Pointer to a process-wide ACE_Thread_Manager. 01244 static ACE_Thread_Manager *thr_mgr_; 01245 01246 /// Must delete the thr_mgr_ if true. 01247 static bool delete_thr_mgr_; 01248 01249 /// Global ACE_TSS (ACE_Thread_Exit) object ptr. 01250 static ACE_TSS_TYPE (ACE_Thread_Exit) *thr_exit_; 01251 #endif /* ! defined (ACE_THREAD_MANAGER_LACKS_STATICS) */ 01252 }; 01253 01254 #if defined (ACE_THREAD_MANAGER_LACKS_STATICS) 01255 #define ACE_THREAD_MANAGER_SINGLETON_DEFINE \ 01256 ACE_Singleton<ACE_Thread_Manager, ACE_SYNCH_MUTEX>; 01257 typedef ACE_Singleton<ACE_Thread_Manager, ACE_SYNCH_MUTEX> ACE_THREAD_MANAGER_SINGLETON; 01258 #endif /* defined (ACE_THREAD_MANAGER_LACKS_STATICS) */ 01259 01260 ACE_END_VERSIONED_NAMESPACE_DECL 01261 01262 #if defined (__ACE_INLINE__) 01263 #include "ace/Thread_Manager.inl" 01264 #endif /* __ACE_INLINE__ */ 01265 01266 #include /**/ "ace/post.h" 01267 #endif /* ACE_THREAD_MANAGER_H */