Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

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

Generated on Mon Jun 16 11:21:47 2003 for ACE by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002