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

Generated on Sun Jan 27 12:05:41 2008 for ACE by doxygen 1.3.6