Task.cpp

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

Generated on Thu Nov 9 09:42:06 2006 for ACE by doxygen 1.3.6