Task.h

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 
00003 //=============================================================================
00004 /**
00005  *  @file    Task.h
00006  *
00007  *  $Id: Task.h 80826 2008-03-04 14:51:23Z wotte $
00008  *
00009  *  @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
00010  */
00011 //=============================================================================
00012 
00013 #ifndef ACE_TASK_H
00014 #define ACE_TASK_H
00015 #include /**/ "ace/pre.h"
00016 
00017 #include "ace/Service_Object.h"
00018 
00019 #if !defined (ACE_LACKS_PRAGMA_ONCE)
00020 # pragma once
00021 #endif /* ACE_LACKS_PRAGMA_ONCE */
00022 
00023 #include "ace/Thread_Manager.h"
00024 
00025 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00026 
00027 /**
00028  * @class ACE_Task_Flags
00029  *
00030  * @brief These flags are used within the ACE_Task.
00031  *
00032  *    These flags should be hidden within ACE_Task.  Unfortunately, the
00033  *    HP/UX C++ compiler can't grok this...  Fortunately, there's no
00034  *    code defined here, so we don't have to worry about multiple
00035  *    definitions.
00036  */
00037 namespace ACE_Task_Flags
00038 {
00039   enum
00040   {
00041     /// Identifies a Task as being the "reader" in a Module.
00042     ACE_READER     = 01,
00043     /// Just flush data messages in the queue.
00044     ACE_FLUSHDATA  = 02,
00045     /// Flush all messages in the Queue.
00046     ACE_FLUSHALL   = 04,
00047     /// Flush read queue
00048     ACE_FLUSHR     = 010,
00049     /// Flush write queue
00050     ACE_FLUSHW     = 020,
00051     /// Flush both queues
00052     ACE_FLUSHRW    = 030
00053   };
00054 }
00055 
00056 /**
00057  * @class ACE_Task_Base
00058  *
00059  * @brief Direct base class for the ACE_Task template.
00060  *
00061  * This class factors out the non-template code in order to
00062  * reduce template bloat, as well as to make it possible for the
00063  * ACE_Thread_Manager to store ACE_Task_Base *'s
00064  * polymorphically.
00065  */
00066 class ACE_Export ACE_Task_Base : public ACE_Service_Object
00067 {
00068 public:
00069   // = Initialization and termination methods.
00070   /// Constructor.
00071   ACE_Task_Base (ACE_Thread_Manager * = 0);
00072 
00073   /// Destructor.
00074   virtual ~ACE_Task_Base (void);
00075 
00076   // = Initialization and termination hooks.
00077 
00078   // These methods should be overridden by subclasses if you'd like to
00079   // provide <Task>-specific initialization and termination behavior.
00080 
00081   /// Hook called to initialize a task and prepare it for execution.
00082   /// @a args can be used to pass arbitrary information into <open>.
00083   virtual int open (void *args = 0);
00084 
00085   /**
00086    * Hook called from ACE_Thread_Exit when during thread exit and from
00087    * the default implementation of <module_closed>.  In general, this
00088    * method shouldn't be called directly by an application,
00089    * particularly if the <Task> is running as an Active Object.
00090    * Instead, a special message should be passed into the <Task> via
00091    * the <put> method defined below, and the <svc> method should
00092    * interpret this as a flag to shut down the <Task>.
00093    */
00094   virtual int close (u_long flags = 0);
00095 
00096   /**
00097    * Hook called during <ACE_Module::close>.  The default
00098    * implementation calls forwards the call to close(1).  Please
00099    * notice the changed value of the default argument of <close>.
00100    * This allows tasks to differ between the call has been originated
00101    * from <ACE_Thread_Exit> or from <module_closed>.  Be aware that
00102    * close(0) will be also called when a thread associated with the
00103    * ACE_Task instance exits.
00104    */
00105   virtual int module_closed (void);
00106 
00107   // = Immediate and deferred processing methods, respectively.
00108 
00109   // These methods should be overridden by subclasses if you'd like to
00110   // provide <Task>-specific message processing behavior.
00111 
00112   /// A hook method that can be used to pass a message to a
00113   /// task, where it can be processed immediately or queued for subsequent
00114   /// processing in the <svc> hook method.
00115   virtual int put (ACE_Message_Block *, ACE_Time_Value * = 0);
00116 
00117   /// Run by a daemon thread to handle deferred processing.
00118   virtual int svc (void);
00119 
00120   // = Active object activation method.
00121   /**
00122    * Turn the task into an active object, i.e., having @a n_threads of
00123    * control, all running at the @a priority level (see below) with the
00124    * same @a grp_id, all of which invoke <Task::svc>.  Returns -1 if
00125    * failure occurs, returns 1 if Task is already an active object and
00126    * @a force_active is false (i.e., do *not* create a new thread in
00127    * this case), and returns 0 if Task was not already an active
00128    * object and a thread is created successfully or thread is an
00129    * active object and @a force_active is true.  Note that if
00130    * @a force_active is true and there are already threads spawned in
00131    * this <Task>, the @a grp_id parameter is ignored and the @a grp_id
00132    * of any newly activated thread(s) will inherit the existing
00133    * @a grp_id of the existing thread(s) in the <Task>.
00134    *
00135    * The <{flags}> are a bitwise-OR of the following:
00136    * = BEGIN<INDENT>
00137    * THR_CANCEL_DISABLE, THR_CANCEL_ENABLE, THR_CANCEL_DEFERRED,
00138    * THR_CANCEL_ASYNCHRONOUS, THR_BOUND, THR_NEW_LWP, THR_DETACHED,
00139    * THR_SUSPENDED, THR_DAEMON, THR_JOINABLE, THR_SCHED_FIFO,
00140    * THR_SCHED_RR, THR_SCHED_DEFAULT, THR_EXPLICIT_SCHED,
00141    * THR_SCOPE_SYSTEM, THR_SCOPE_PROCESS
00142    * = END<INDENT>
00143    * If THR_SCHED_INHERIT is not desirable, applications should
00144    * specifically pass in THR_EXPLICIT_SCHED.
00145    *
00146    *
00147    * By default, or if <{priority}> is set to
00148    * ACE_DEFAULT_THREAD_PRIORITY, an "appropriate" priority value for
00149    * the given scheduling policy (specified in <{flags}>, e.g.,
00150    * <THR_SCHED_DEFAULT>) is used.  This value is calculated
00151    * dynamically, and is the median value between the minimum and
00152    * maximum priority values for the given policy.  If an explicit
00153    * value is given, it is used.  Note that actual priority values are
00154    * EXTREMEMLY implementation-dependent, and are probably best
00155    * avoided.
00156    *
00157    * If @a thread_handles != 0 it is assumed to be an array of @a n
00158    * thread_handles that will be assigned the values of the thread
00159    * handles being spawned.  Returns -1 on failure (@c errno will
00160    * explain...), otherwise returns the group id of the threads.
00161    *
00162    * Assigning @a task allows you to associate the newly spawned
00163    * threads with an instance of ACE_Task_Base.  If @a task == 0, then
00164    * the new threads are associated automatically with @c this
00165    * ACE_Task_Base.  Setting the @a task argument to value other than
00166    * @c this makes the thread manipulating methods, such as wait(),
00167    * suspend(), resume(), useless.  Threads spawned with user
00168    * specified @a task value must therefore be manipulated thru
00169    * ACE_Thread_Manager directly.
00170    *
00171    * If @a stack != 0 it is assumed to be an array of @a n pointers to
00172    * the base of the stacks to use for the threads being spawned.
00173    * Likewise, if @a stack_size != 0 it is assumed to be an array of
00174    * @a n values indicating how big each of the corresponding @a stacks
00175    * are.
00176    *
00177    *
00178    */
00179   virtual int activate (long flags = THR_NEW_LWP | THR_JOINABLE | THR_INHERIT_SCHED,
00180                         int n_threads = 1,
00181                         int force_active = 0,
00182                         long priority = ACE_DEFAULT_THREAD_PRIORITY,
00183                         int grp_id = -1,
00184                         ACE_Task_Base *task = 0,
00185                         ACE_hthread_t thread_handles[] = 0,
00186                         void *stack[] = 0,
00187                         size_t stack_size[] = 0,
00188                         ACE_thread_t thread_ids[] = 0,
00189                         const char* thr_name[] = 0);
00190 
00191   /**
00192    * Block until there are no more threads running in this task.
00193    * This method will not wait for either detached or daemon threads;
00194    * the threads must have been spawned with the @c THR_JOINABLE flag.
00195    * Upon successful completion, the threads have been joined, so further
00196    * attempts to join with any of the waited-for threads will fail.
00197    *
00198    * @retval 0  Success.
00199    * @retval -1 Failure (consult errno for further information).
00200    */
00201   virtual int wait (void);
00202 
00203   // = Suspend/resume a Task.
00204 
00205   // Note that these methods are not portable and should be avoided
00206   // since they are inherently error-prone to use.  They are only here
00207   // for (the rare) applications that know how to use them correctly.
00208   /// Suspend a task.
00209   virtual int suspend (void);
00210   /// Resume a suspended task.
00211   virtual int resume (void);
00212 
00213   /// Get the current group id.
00214   int grp_id (void) const;
00215 
00216   /// Set the current group id.
00217   void grp_id (int);
00218 
00219   /// Get the thread manager associated with this Task.
00220   ACE_Thread_Manager *thr_mgr (void) const;
00221 
00222   /// Set the thread manager associated with this Task.
00223   void thr_mgr (ACE_Thread_Manager *);
00224 
00225   /// True if queue is a reader, else false.
00226   int is_reader (void) const;
00227 
00228   /// True if queue is a writer, else false.
00229   int is_writer (void) const;
00230 
00231   /**
00232    * Returns the number of threads currently running within a task.
00233    * If we're a passive object this value is 0, else it's greater than
00234    * 0.
00235    */
00236   size_t thr_count (void) const;
00237 
00238   /**
00239    * Returns the thread ID of the thread whose exit caused this object's
00240    * thread count to be decremented to 0.
00241    *
00242    * When a thread spawned in the context of this object (using activate())
00243    * returns from its svc() method ACE calls the close() hook. Before it does
00244    * so, it decrements the number of active threads. If the number of threads
00245    * is decremented to 0, the thread ID of the current thread is stored for
00246    * access by this method. If the returned thread ID matches the calling
00247    * thread's ID, the calling thread knows that there are no other threads
00248    * still active in the ACE_Task.
00249    *
00250    * @retval  ACE_thread_t of the last thread to close. 0 if the last thread
00251    *          is not yet known; for example, if no threads are active, or if
00252    *          multiple threads are active.
00253    */
00254   ACE_thread_t last_thread (void) const;
00255 
00256   /// Routine that runs the service routine as a daemon thread.
00257   static ACE_THR_FUNC_RETURN svc_run (void *);
00258 
00259   /// Cleanup hook that is called when a thread exits to gracefully
00260   /// shutdown an ACE_Task.
00261   static void cleanup (void *object, void *params);
00262 
00263 protected:
00264   /**
00265    * Count of the number of threads running within the task.  If this
00266    * value is greater than 0 then we're an active object and the value
00267    * of <thr_count_> is the number of active threads at this instant.
00268    * If the value == 0, then we're a passive object.
00269    */
00270   size_t thr_count_;
00271 
00272   /// Multi-threading manager.
00273   ACE_Thread_Manager *thr_mgr_;
00274 
00275   /// ACE_Task flags.
00276   u_long flags_;
00277 
00278   /// This maintains the group id of the Task.
00279   int grp_id_;
00280 
00281 #if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
00282   /// Protect the state of a Task during concurrent operations, but
00283   /// only if we're configured as MT safe...
00284   ACE_Thread_Mutex lock_;
00285 #endif /* ACE_MT_SAFE */
00286 
00287   /// Holds the thread ID of the last thread to exit svc() in this object.
00288   ACE_thread_t  last_thread_id_;
00289 
00290 private:
00291 
00292   // = Disallow these operations.
00293   ACE_Task_Base &operator= (const ACE_Task_Base &);
00294   ACE_Task_Base (const ACE_Task_Base &);
00295 };
00296 
00297 ACE_END_VERSIONED_NAMESPACE_DECL
00298 
00299 #if defined (__ACE_INLINE__)
00300 #include "ace/Task.inl"
00301 #endif /* __ACE_INLINE__ */
00302 
00303 // Include the ACE_Task templates classes at this point.
00304 #include "ace/Task_T.h"
00305 
00306 #include /**/ "ace/post.h"
00307 #endif /* ACE_TASK_H */

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