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