Thread_Manager.h

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

Generated on Thu Nov 9 09:42:06 2006 for ACE by doxygen 1.3.6