2 #include "ace/Module.h"
4 #if !defined (__ACE_INLINE__)
5 #include "ace/Task.inl"
6 #endif /* __ACE_INLINE__ */
8 #include "ace/OS_NS_string.h"
10 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
12 ACE_Task_Base::ACE_Task_Base (ACE_Thread_Manager
*thr_man
)
17 #if !defined (ACE_THREAD_T_IS_A_STRUCT)
19 #endif /* !ACE_THREAD_T_IS_A_STRUCT */
21 #if defined (ACE_THREAD_T_IS_A_STRUCT)
22 ACE_OS::memset( &this->last_thread_id_
, '\0', sizeof( this->last_thread_id_
));
23 #endif /* ACE_THREAD_T_IS_A_STRUCT */
26 ACE_Task_Base::~ACE_Task_Base ()
30 /// Default ACE_Task service routine
34 ACE_TRACE ("ACE_Task_Base::svc");
38 /// Default ACE_Task open routine
40 ACE_Task_Base::open (void *)
42 ACE_TRACE ("ACE_Task_Base::open");
46 /// Default ACE_Task close routine
48 ACE_Task_Base::close (u_long
)
50 ACE_TRACE ("ACE_Task_Base::close");
54 /// Forward the call to close() so that existing applications don't
57 ACE_Task_Base::module_closed ()
59 return this->close (1);
62 /// Default ACE_Task put routine.
64 ACE_Task_Base::put (ACE_Message_Block
*, ACE_Time_Value
*)
66 ACE_TRACE ("ACE_Task_Base::put");
70 /// Wait for all threads running in a task to exit.
72 ACE_Task_Base::wait ()
74 ACE_TRACE ("ACE_Task_Base::wait");
76 // If we don't have a thread manager, we probably were never
78 if (this->thr_mgr () != 0)
79 return this->thr_mgr ()->wait_task (this);
86 ACE_Task_Base::suspend ()
88 ACE_TRACE ("ACE_Task_Base::suspend");
89 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex
, ace_mon
, this->lock_
, -1));
90 if (this->thr_count_
> 0)
91 return this->thr_mgr_
->suspend_task (this);
96 /// Resume a suspended task.
98 ACE_Task_Base::resume ()
100 ACE_TRACE ("ACE_Task_Base::resume");
101 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex
, ace_mon
, this->lock_
, -1));
102 if (this->thr_count_
> 0)
103 return this->thr_mgr_
->resume_task (this);
109 ACE_Task_Base::activate (long flags
,
115 ACE_hthread_t thread_handles
[],
118 ACE_thread_t thread_ids
[],
119 const char* thr_name
[])
121 ACE_TRACE ("ACE_Task_Base::activate");
123 #if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
124 ACE_GUARD_RETURN (ACE_Thread_Mutex
, ace_mon
, this->lock_
, -1);
126 // If the task passed in is zero, we will use <this>
130 if (this->thr_count_
> 0 && force_active
== 0)
131 return 1; // Already active.
134 if ((this->thr_count_
> 0 || grp_id
== -1) &&
136 // If we're joining an existing group of threads then make
137 // sure to (re)use its group id.
138 grp_id
= this->grp_id_
;
139 else if (grp_id
!= -1)
140 // make sure to reset the cached grp_id
142 this->thr_count_
+= n_threads
;
145 // Use the ACE_Thread_Manager singleton if we're running as an
146 // active object and the caller didn't supply us with a
148 if (this->thr_mgr_
== 0)
149 # if defined (ACE_THREAD_MANAGER_LACKS_STATICS)
150 this->thr_mgr_
= ACE_THREAD_MANAGER_SINGLETON::instance ();
151 # else /* ! ACE_THREAD_MANAGER_LACKS_STATICS */
152 this->thr_mgr_
= ACE_Thread_Manager::instance ();
153 # endif /* ACE_THREAD_MANAGER_LACKS_STATICS */
155 int grp_spawned
= -1;
157 // Thread Ids were not specified
159 this->thr_mgr_
->spawn_n (n_threads
,
160 &ACE_Task_Base::svc_run
,
171 // thread names were specified
173 this->thr_mgr_
->spawn_n (thread_ids
,
175 &ACE_Task_Base::svc_run
,
185 if (grp_spawned
== -1)
187 // If spawn_n fails, restore original thread count.
188 this->thr_count_
-= n_threads
;
192 if (this->grp_id_
== -1)
193 this->grp_id_
= grp_spawned
;
195 #if defined (ACE_THREAD_T_IS_A_STRUCT)
196 ACE_OS::memcpy( &this->last_thread_id_
, '\0', sizeof(this->last_thread_id_
));
198 this->last_thread_id_
= 0; // Reset to prevent inadvertant match on ID
199 #endif /* ACE_THREAD_T_IS_A_STRUCT */
205 // Keep the compiler from complaining.
206 ACE_UNUSED_ARG (flags
);
207 ACE_UNUSED_ARG (n_threads
);
208 ACE_UNUSED_ARG (force_active
);
209 ACE_UNUSED_ARG (priority
);
210 ACE_UNUSED_ARG (grp_id
);
211 ACE_UNUSED_ARG (task
);
212 ACE_UNUSED_ARG (thread_handles
);
213 ACE_UNUSED_ARG (stack
);
214 ACE_UNUSED_ARG (stack_size
);
215 ACE_UNUSED_ARG (thread_ids
);
216 ACE_UNUSED_ARG (thr_name
);
217 ACE_NOTSUP_RETURN (-1);
219 #endif /* ACE_MT_SAFE */
223 ACE_Task_Base::cleanup (void *object
, void *)
225 ACE_Task_Base
*t
= (ACE_Task_Base
*) object
;
227 // The thread count must be decremented first in case the <close>
228 // hook does something crazy like "delete this".
230 ACE_MT (ACE_GUARD (ACE_Thread_Mutex
, ace_mon
, t
->lock_
));
232 if (0 == t
->thr_count_
)
233 t
->last_thread_id_
= ACE_Thread::self ();
236 // @@ Is it possible to pass in the exit status somehow?
238 // t is undefined here. close() could have deleted it.
242 #if defined (ACE_HAS_SIG_C_FUNC)
244 ACE_Task_Base_cleanup (void *object
, void *)
246 ACE_Task_Base::cleanup (object
, 0);
248 #endif /* ACE_HAS_SIG_C_FUNC */
251 ACE_Task_Base::svc_run (void *args
)
253 ACE_TRACE ("ACE_Task_Base::svc_run");
255 ACE_Task_Base
*t
= (ACE_Task_Base
*) args
;
257 // Register ourself with our <Thread_Manager>'s thread exit hook
258 // mechanism so that our close() hook will be sure to get invoked
259 // when this thread exits.
261 #if defined ACE_HAS_SIG_C_FUNC
262 t
->thr_mgr ()->at_exit (t
, ACE_Task_Base_cleanup
, 0);
264 t
->thr_mgr ()->at_exit (t
, ACE_Task_Base::cleanup
, 0);
265 #endif /* ACE_HAS_SIG_C_FUNC */
267 ACE_THR_FUNC_RETURN status
;
268 // Call the Task's svc() hook method.
269 int const svc_status
= t
->svc ();
271 #if defined (ACE_HAS_INTEGRAL_TYPE_THR_FUNC_RETURN)
272 // Reinterpret case between integral types is not mentioned in the C++ spec
273 status
= static_cast<ACE_THR_FUNC_RETURN
> (svc_status
);
275 status
= reinterpret_cast<ACE_THR_FUNC_RETURN
> (svc_status
);
276 #endif /* ACE_HAS_INTEGRAL_TYPE_THR_FUNC_RETURN */
278 // If we changed this zero change the other if in OS.cpp Thread_Adapter::invoke
280 // Call the <Task->close> hook.
281 ACE_Thread_Manager
*thr_mgr_ptr
= t
->thr_mgr ();
283 // This calls the Task->close () hook.
286 // This prevents a second invocation of the cleanup code
287 // (called later by <ACE_Thread_Manager::exit>.
288 thr_mgr_ptr
->at_exit (t
, 0, 0);
293 ACE_END_VERSIONED_NAMESPACE_DECL