Thread_Manager.h

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

Generated on Tue Feb 2 17:18:43 2010 for ACE by  doxygen 1.4.7