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