Task.cpp

Go to the documentation of this file.
00001 // $Id: Task.cpp 80826 2008-03-04 14:51:23Z wotte $
00002 
00003 #include "ace/Task.h"
00004 #include "ace/Module.h"
00005 
00006 #if !defined (__ACE_INLINE__)
00007 #include "ace/Task.inl"
00008 #endif /* __ACE_INLINE__ */
00009 
00010 
00011 ACE_RCSID (ace,
00012            Task,
00013            "$Id: Task.cpp 80826 2008-03-04 14:51:23Z wotte $")
00014 
00015 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00016 
00017 ACE_Task_Base::ACE_Task_Base (ACE_Thread_Manager *thr_man)
00018   : thr_count_ (0),
00019     thr_mgr_ (thr_man),
00020     flags_ (0),
00021     grp_id_ (-1)
00022 #if !(defined (ACE_MVS) || defined(__TANDEM))
00023     ,last_thread_id_ (0)
00024 #endif /* !defined (ACE_MVS) */
00025 {
00026 #if (defined (ACE_MVS) || defined(__TANDEM))
00027    ACE_OS::memset( &this->last_thread_id_, '\0', sizeof( this->last_thread_id_ ));
00028 #endif /* defined (ACE_MVS) */
00029 }
00030 
00031 ACE_Task_Base::~ACE_Task_Base (void)
00032 {
00033 }
00034 
00035 // Default ACE_Task service routine
00036 
00037 int
00038 ACE_Task_Base::svc (void)
00039 {
00040   ACE_TRACE ("ACE_Task_Base::svc");
00041   return 0;
00042 }
00043 
00044 // Default ACE_Task open routine
00045 
00046 int
00047 ACE_Task_Base::open (void *)
00048 {
00049   ACE_TRACE ("ACE_Task_Base::open");
00050   return 0;
00051 }
00052 
00053 // Default ACE_Task close routine
00054 
00055 int
00056 ACE_Task_Base::close (u_long)
00057 {
00058   ACE_TRACE ("ACE_Task_Base::close");
00059   return 0;
00060 }
00061 
00062 // Forward the call to close() so that existing applications don't
00063 // break.
00064 
00065 int
00066 ACE_Task_Base::module_closed (void)
00067 {
00068   return this->close (1);
00069 }
00070 
00071 // Default ACE_Task put routine.
00072 
00073 int
00074 ACE_Task_Base::put (ACE_Message_Block *, ACE_Time_Value *)
00075 {
00076   ACE_TRACE ("ACE_Task_Base::put");
00077   return 0;
00078 }
00079 
00080 // Wait for all threads running in a task to exit.
00081 
00082 int
00083 ACE_Task_Base::wait (void)
00084 {
00085   ACE_TRACE ("ACE_Task_Base::wait");
00086 
00087   // If we don't have a thread manager, we probably were never
00088   // activated.
00089   if (this->thr_mgr () != 0)
00090     return this->thr_mgr ()->wait_task (this);
00091   else
00092     return 0;
00093 }
00094 
00095 // Suspend a task.
00096 int
00097 ACE_Task_Base::suspend (void)
00098 {
00099   ACE_TRACE ("ACE_Task_Base::suspend");
00100   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
00101   if (this->thr_count_ > 0)
00102     return this->thr_mgr_->suspend_task (this);
00103 
00104   return 0;
00105 }
00106 
00107 // Resume a suspended task.
00108 int
00109 ACE_Task_Base::resume (void)
00110 {
00111   ACE_TRACE ("ACE_Task_Base::resume");
00112   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
00113   if (this->thr_count_ > 0)
00114     return this->thr_mgr_->resume_task (this);
00115 
00116   return 0;
00117 }
00118 
00119 int
00120 ACE_Task_Base::activate (long flags,
00121                          int n_threads,
00122                          int force_active,
00123                          long priority,
00124                          int grp_id,
00125                          ACE_Task_Base *task,
00126                          ACE_hthread_t thread_handles[],
00127                          void *stack[],
00128                          size_t stack_size[],
00129                          ACE_thread_t thread_ids[],
00130                          const char* thr_name[])
00131 {
00132   ACE_TRACE ("ACE_Task_Base::activate");
00133 
00134 #if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
00135   ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1);
00136 
00137   // If the task passed in is zero, we will use <this>
00138   if (task == 0)
00139     task = this;
00140 
00141   if (this->thr_count_ > 0 && force_active == 0)
00142     return 1; // Already active.
00143   else
00144     {
00145       if (this->thr_count_ > 0 && this->grp_id_ != -1)
00146         // If we're joining an existing group of threads then make
00147         // sure to use its group id.
00148         grp_id = this->grp_id_;
00149       this->thr_count_ += n_threads;
00150     }
00151 
00152   // Use the ACE_Thread_Manager singleton if we're running as an
00153   // active object and the caller didn't supply us with a
00154   // Thread_Manager.
00155   if (this->thr_mgr_ == 0)
00156 # if defined (ACE_THREAD_MANAGER_LACKS_STATICS)
00157     this->thr_mgr_ = ACE_THREAD_MANAGER_SINGLETON::instance ();
00158 # else /* ! ACE_THREAD_MANAGER_LACKS_STATICS */
00159     this->thr_mgr_ = ACE_Thread_Manager::instance ();
00160 # endif /* ACE_THREAD_MANAGER_LACKS_STATICS */
00161 
00162   int grp_spawned = -1;
00163   if (thread_ids == 0)
00164     // Thread Ids were not specified
00165     grp_spawned =
00166       this->thr_mgr_->spawn_n (n_threads,
00167                                &ACE_Task_Base::svc_run,
00168                                (void *) this,
00169                                flags,
00170                                priority,
00171                                grp_id,
00172                                task,
00173                                thread_handles,
00174                                stack,
00175                                stack_size,
00176                                thr_name);
00177   else
00178     // thread names were specified
00179     grp_spawned =
00180       this->thr_mgr_->spawn_n (thread_ids,
00181                                n_threads,
00182                                &ACE_Task_Base::svc_run,
00183                                (void *) this,
00184                                flags,
00185                                priority,
00186                                grp_id,
00187                                stack,
00188                                stack_size,
00189                                thread_handles,
00190                                task,
00191                                thr_name);
00192   if (grp_spawned == -1)
00193     {
00194       // If spawn_n fails, restore original thread count.
00195       this->thr_count_ -= n_threads;
00196       return -1;
00197     }
00198 
00199   if (this->grp_id_ == -1)
00200     this->grp_id_ = grp_spawned;
00201 
00202 #if defined (ACE_MVS) || defined(__TANDEM)
00203   ACE_OS::memcpy( &this->last_thread_id_, '\0', sizeof(this->last_thread_id_));
00204 #else
00205   this->last_thread_id_ = 0;    // Reset to prevent inadvertant match on ID
00206 #endif /* defined (ACE_MVS) */
00207 
00208   return 0;
00209 
00210 #else
00211   {
00212     // Keep the compiler from complaining.
00213     ACE_UNUSED_ARG (flags);
00214     ACE_UNUSED_ARG (n_threads);
00215     ACE_UNUSED_ARG (force_active);
00216     ACE_UNUSED_ARG (priority);
00217     ACE_UNUSED_ARG (grp_id);
00218     ACE_UNUSED_ARG (task);
00219     ACE_UNUSED_ARG (thread_handles);
00220     ACE_UNUSED_ARG (stack);
00221     ACE_UNUSED_ARG (stack_size);
00222     ACE_UNUSED_ARG (thread_ids);
00223     ACE_UNUSED_ARG (thr_name);
00224     ACE_NOTSUP_RETURN (-1);
00225   }
00226 #endif /* ACE_MT_SAFE */
00227 }
00228 
00229 void
00230 ACE_Task_Base::cleanup (void *object, void *)
00231 {
00232   ACE_Task_Base *t = (ACE_Task_Base *) object;
00233 
00234   // The thread count must be decremented first in case the <close>
00235   // hook does something crazy like "delete this".
00236   {
00237     ACE_MT (ACE_GUARD (ACE_Thread_Mutex, ace_mon, t->lock_));
00238     t->thr_count_--;
00239     if (0 == t->thr_count_)
00240       t->last_thread_id_ = ACE_Thread::self ();
00241   }
00242 
00243   // @@ Is it possible to pass in the exit status somehow?
00244   t->close ();
00245   // t is undefined here. close() could have deleted it.
00246 }
00247 
00248 
00249 #if defined (ACE_HAS_SIG_C_FUNC)
00250 extern "C" void
00251 ACE_Task_Base_cleanup (void *object, void *)
00252 {
00253   ACE_Task_Base::cleanup (object, 0);
00254 }
00255 #endif /* ACE_HAS_SIG_C_FUNC */
00256 
00257 ACE_THR_FUNC_RETURN
00258 ACE_Task_Base::svc_run (void *args)
00259 {
00260   ACE_TRACE ("ACE_Task_Base::svc_run");
00261 
00262   ACE_Task_Base *t = (ACE_Task_Base *) args;
00263 
00264   // Register ourself with our <Thread_Manager>'s thread exit hook
00265   // mechanism so that our close() hook will be sure to get invoked
00266   // when this thread exits.
00267 
00268 #if defined ACE_HAS_SIG_C_FUNC
00269   t->thr_mgr ()->at_exit (t, ACE_Task_Base_cleanup, 0);
00270 #else
00271   t->thr_mgr ()->at_exit (t, ACE_Task_Base::cleanup, 0);
00272 #endif /* ACE_HAS_SIG_C_FUNC */
00273 
00274   // Call the Task's svc() hook method.
00275   int const svc_status = t->svc ();
00276   ACE_THR_FUNC_RETURN status;
00277 #if defined (ACE_HAS_INTEGRAL_TYPE_THR_FUNC_RETURN)
00278   // Reinterpret case between integral types is not mentioned in the C++ spec
00279   status = static_cast<ACE_THR_FUNC_RETURN> (svc_status);
00280 #else
00281   status = reinterpret_cast<ACE_THR_FUNC_RETURN> (svc_status);
00282 #endif /* ACE_HAS_INTEGRAL_TYPE_THR_FUNC_RETURN */
00283 
00284 // If we changed this zero change the other if in OS.cpp Thread_Adapter::invoke
00285 #if 1
00286   // Call the <Task->close> hook.
00287   ACE_Thread_Manager *thr_mgr_ptr = t->thr_mgr ();
00288 
00289   // This calls the Task->close () hook.
00290   t->cleanup (t, 0);
00291 
00292   // This prevents a second invocation of the cleanup code
00293   // (called later by <ACE_Thread_Manager::exit>.
00294   thr_mgr_ptr->at_exit (t, 0, 0);
00295 #endif
00296   return status;
00297 }
00298 
00299 ACE_END_VERSIONED_NAMESPACE_DECL

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