3 //=============================================================================
7 * @author Douglas C. Schmidt <d.schmidt@vanderbilt.edu>
9 //=============================================================================
13 #include /**/ "ace/pre.h"
15 #include "ace/Service_Object.h"
17 #if !defined (ACE_LACKS_PRAGMA_ONCE)
19 #endif /* ACE_LACKS_PRAGMA_ONCE */
21 #include "ace/Thread_Manager.h"
23 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
26 * @class ACE_Task_Flags
28 * @brief These flags are used within the ACE_Task.
30 * These flags should be hidden within ACE_Task. Unfortunately, the
31 * HP/UX C++ compiler can't grok this... Fortunately, there's no
32 * code defined here, so we don't have to worry about multiple
35 namespace ACE_Task_Flags
39 /// Identifies a Task as being the "reader" in a Module.
41 /// Just flush data messages in the queue.
43 /// Flush all messages in the Queue.
55 * @class ACE_Task_Base
57 * @brief Direct base class for the ACE_Task template.
59 * This class factors out the non-template code in order to
60 * reduce template bloat, as well as to make it possible for the
61 * ACE_Thread_Manager to store ACE_Task_Base *'s
64 class ACE_Export ACE_Task_Base
: public ACE_Service_Object
68 ACE_Task_Base (ACE_Thread_Manager
* = 0);
71 virtual ~ACE_Task_Base ();
73 // These methods should be overridden by subclasses if you'd like to
74 // provide <Task>-specific initialization and termination behavior.
76 /// Hook called to initialize a task and prepare it for execution.
77 /// @a args can be used to pass arbitrary information into <open>.
78 virtual int open (void *args
= 0);
81 * Hook called from ACE_Thread_Exit when during thread exit and from
82 * the default implementation of @c module_closed(). In general, this
83 * method shouldn't be called directly by an application,
84 * particularly if the Task is running as an Active Object.
85 * Instead, a special message should be passed into the Task via
86 * the put() method defined below, and the svc() method should
87 * interpret this as a flag to shut down the Task.
89 virtual int close (u_long flags
= 0);
92 * Hook called during ACE_Module::close(). The default
93 * implementation calls forwards the call to close(1). Please
94 * notice the changed value of the default argument of close().
95 * This allows tasks to differ between the call has been originated
96 * from ACE_Thread_Exit or from module_closed(). Be aware that
97 * close(0) will be also called when a thread associated with the
98 * ACE_Task instance exits.
100 virtual int module_closed ();
102 // = Immediate and deferred processing methods, respectively.
104 // These methods should be overridden by subclasses if you'd like to
105 // provide <Task>-specific message processing behavior.
107 /// A hook method that can be used to pass a message to a
108 /// task, where it can be processed immediately or queued for subsequent
109 /// processing in the svc() hook method.
110 virtual int put (ACE_Message_Block
*, ACE_Time_Value
* = 0);
112 /// Run by a daemon thread to handle deferred processing.
115 // = Active object activation method.
117 * Turn the task into an active object, i.e., having @a n_threads of
118 * control, all running at the @a priority level (see below) with the
119 * same @a grp_id, all of which invoke <Task::svc>. Returns -1 if
120 * failure occurs, returns 1 if Task is already an active object and
121 * @a force_active is false (i.e., do *not* create a new thread in
122 * this case), and returns 0 if Task was not already an active
123 * object and a thread is created successfully or thread is an
124 * active object and @a force_active is true. Note that if
125 * @a force_active is true and there are already threads spawned in
126 * this <Task>, the @a grp_id parameter is ignored and the @a grp_id
127 * of any newly activated thread(s) will inherit the existing
128 * @a grp_id of the existing thread(s) in the <Task>.
130 * The <{flags}> are a bitwise-OR of the following:
132 * THR_CANCEL_DISABLE, THR_CANCEL_ENABLE, THR_CANCEL_DEFERRED,
133 * THR_CANCEL_ASYNCHRONOUS, THR_BOUND, THR_NEW_LWP, THR_DETACHED,
134 * THR_SUSPENDED, THR_DAEMON, THR_JOINABLE, THR_SCHED_FIFO,
135 * THR_SCHED_RR, THR_SCHED_DEFAULT, THR_EXPLICIT_SCHED,
136 * THR_SCOPE_SYSTEM, THR_SCOPE_PROCESS
138 * If THR_SCHED_INHERIT is not desirable, applications should
139 * specifically pass in THR_EXPLICIT_SCHED.
142 * By default, or if <{priority}> is set to
143 * ACE_DEFAULT_THREAD_PRIORITY, an "appropriate" priority value for
144 * the given scheduling policy (specified in <{flags}>, e.g.,
145 * <THR_SCHED_DEFAULT>) is used. This value is calculated
146 * dynamically, and is the median value between the minimum and
147 * maximum priority values for the given policy. If an explicit
148 * value is given, it is used. Note that actual priority values are
149 * EXTREMEMLY implementation-dependent, and are probably best
152 * If @a thread_handles != 0 it is assumed to be an array of @a n
153 * thread_handles that will be assigned the values of the thread
154 * handles being spawned. Returns -1 on failure (@c errno will
155 * explain...), otherwise returns the group id of the threads.
157 * Assigning @a task allows you to associate the newly spawned
158 * threads with an instance of ACE_Task_Base. If @a task == 0, then
159 * the new threads are associated automatically with @c this
160 * ACE_Task_Base. Setting the @a task argument to value other than
161 * @c this makes the thread manipulating methods, such as wait(),
162 * suspend(), resume(), useless. Threads spawned with user
163 * specified @a task value must therefore be manipulated thru
164 * ACE_Thread_Manager directly.
166 * If @a stack != 0 it is assumed to be an array of @a n pointers to
167 * the base of the stacks to use for the threads being spawned.
168 * Likewise, if @a stack_size != 0 it is assumed to be an array of
169 * @a n values indicating how big each of the corresponding @a stacks
174 virtual int activate (long flags
= THR_NEW_LWP
| THR_JOINABLE
| THR_INHERIT_SCHED
,
176 int force_active
= 0,
177 long priority
= ACE_DEFAULT_THREAD_PRIORITY
,
179 ACE_Task_Base
*task
= 0,
180 ACE_hthread_t thread_handles
[] = 0,
182 size_t stack_size
[] = 0,
183 ACE_thread_t thread_ids
[] = 0,
184 const char* thr_name
[] = 0);
187 * Block until there are no more threads running in this task.
188 * This method will not wait for either detached or daemon threads;
189 * the threads must have been spawned with the @c THR_JOINABLE flag.
190 * Upon successful completion, the threads have been joined, so further
191 * attempts to join with any of the waited-for threads will fail.
194 * @retval -1 Failure (consult errno for further information).
198 // = Suspend/resume a Task.
200 // Note that these methods are not portable and should be avoided
201 // since they are inherently error-prone to use. They are only here
202 // for (the rare) applications that know how to use them correctly.
204 virtual int suspend ();
205 /// Resume a suspended task.
206 virtual int resume ();
208 /// Get the current group id.
211 /// Set the current group id.
214 /// Get the thread manager associated with this Task.
215 ACE_Thread_Manager
*thr_mgr () const;
217 /// Set the thread manager associated with this Task.
218 void thr_mgr (ACE_Thread_Manager
*);
220 /// True if queue is a reader, else false.
221 int is_reader () const;
223 /// True if queue is a writer, else false.
224 int is_writer () const;
227 * Returns the number of threads currently running within a task.
228 * If we're a passive object this value is 0, else it's greater than
231 size_t thr_count () const;
234 * Returns the thread ID of the thread whose exit caused this object's
235 * thread count to be decremented to 0.
237 * When a thread spawned in the context of this object (using activate())
238 * returns from its svc() method ACE calls the close() hook. Before it does
239 * so, it decrements the number of active threads. If the number of threads
240 * is decremented to 0, the thread ID of the current thread is stored for
241 * access by this method. If the returned thread ID matches the calling
242 * thread's ID, the calling thread knows that there are no other threads
243 * still active in the ACE_Task.
245 * @retval ACE_thread_t of the last thread to close. 0 if the last thread
246 * is not yet known; for example, if no threads are active, or if
247 * multiple threads are active.
249 ACE_thread_t
last_thread () const;
251 /// Routine that runs the service routine as a daemon thread.
252 static ACE_THR_FUNC_RETURN
svc_run (void *);
254 /// Cleanup hook that is called when a thread exits to gracefully
255 /// shutdown an ACE_Task.
256 static void cleanup (void *object
, void *params
);
260 * Count of the number of threads running within the task. If this
261 * value is greater than 0 then we're an active object and the value
262 * of <thr_count_> is the number of active threads at this instant.
263 * If the value == 0, then we're a passive object.
267 /// Multi-threading manager.
268 ACE_Thread_Manager
*thr_mgr_
;
273 /// This maintains the group id of the Task.
276 #if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
277 /// Protect the state of a Task during concurrent operations, but
278 /// only if we're configured as MT safe...
279 mutable ACE_Thread_Mutex lock_
;
280 #endif /* ACE_MT_SAFE */
282 /// Holds the thread ID of the last thread to exit svc() in this object.
283 ACE_thread_t last_thread_id_
;
285 ACE_Task_Base
&operator= (const ACE_Task_Base
&) = delete;
286 ACE_Task_Base (const ACE_Task_Base
&) = delete;
289 ACE_END_VERSIONED_NAMESPACE_DECL
291 #if defined (__ACE_INLINE__)
292 #include "ace/Task.inl"
293 #endif /* __ACE_INLINE__ */
295 // Include the ACE_Task templates classes at this point.
296 #include "ace/Task_T.h"
298 #include /**/ "ace/post.h"
299 #endif /* ACE_TASK_H */