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