Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

Thread_Adapter.cpp

Go to the documentation of this file.
00001 #include "ace_pch.h"
00002 // $Id: Thread_Adapter.cpp,v 1.1.1.2.2.1 2003/03/13 19:44:22 chad Exp $
00003 
00004 #include "ace/Thread_Adapter.h"
00005 #include "ace/OS.h"
00006 #include "ace/Thread_Manager.h"
00007 #include "ace/Thread_Exit.h"
00008 #include "ace/Thread_Hook.h"
00009 
00010 ACE_RCSID (ace,
00011            Thread_Adapter,
00012            "$Id: Thread_Adapter.cpp,v 1.1.1.2.2.1 2003/03/13 19:44:22 chad Exp $")
00013 
00014 #if !defined (ACE_HAS_INLINED_OSCALLS)
00015 # include "ace/Thread_Adapter.inl"
00016 #endif /* ACE_HAS_INLINED_OS_CALLS */
00017 
00018 ACE_Thread_Adapter::ACE_Thread_Adapter (ACE_THR_FUNC user_func,
00019                                         void *arg,
00020                                         ACE_THR_C_FUNC entry_point,
00021                                         ACE_Thread_Manager *tm,
00022                                         ACE_Thread_Descriptor *td
00023 #if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS)
00024                                         , ACE_SEH_EXCEPT_HANDLER selector,
00025                                         ACE_SEH_EXCEPT_HANDLER handler
00026 #endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */
00027                                         )
00028   : ACE_Base_Thread_Adapter (
00029         user_func
00030         , arg
00031         , entry_point
00032         , td
00033 #if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS)
00034         , selector
00035         , handler
00036 #endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */
00037         )
00038   , thr_mgr_ (tm)
00039 {
00040   ACE_OS_TRACE ("ACE_Thread_Adapter::ACE_Thread_Adapter");
00041 }
00042 
00043 ACE_Thread_Adapter::~ACE_Thread_Adapter (void)
00044 {
00045 }
00046 
00047 ACE_THR_FUNC_RETURN
00048 ACE_Thread_Adapter::invoke (void)
00049 {
00050   // Inherit the logging features if the parent thread has an
00051   // ACE_Log_Msg instance in thread-specific storage.
00052   this->inherit_log_msg ();
00053 
00054 #if !defined(ACE_USE_THREAD_MANAGER_ADAPTER)
00055   // NOTE: this preprocessor directive should match the one in above
00056   // ACE_Thread_Exit::instance ().  With the Xavier Pthreads package,
00057   // the exit_hook in TSS causes a seg fault.  So, this works around
00058   // that by creating exit_hook on the stack.
00059 # if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION)
00060   // Obtain our thread-specific exit hook and make sure that it knows
00061   // how to clean us up!  Note that we never use this pointer directly
00062   // (it's stored in thread-specific storage), so it's ok to
00063   // dereference it here and only store it as a reference.
00064 
00065   // Except if it is null, then the thr_mgr() method crashes.
00066   // -jxh
00067 
00068   ACE_Thread_Exit *exit_hook_instance = ACE_Thread_Exit::instance ();
00069   ACE_Thread_Exit_Maybe exit_hook_maybe (exit_hook_instance == 0);
00070   ACE_Thread_Exit *exit_hook_ptr = exit_hook_instance
00071                                    ? exit_hook_instance
00072                                    : exit_hook_maybe.instance ();
00073   ACE_Thread_Exit &exit_hook = *exit_hook_ptr;
00074 
00075   if (this->thr_mgr () != 0)
00076     {
00077       // Keep track of the <Thread_Manager> that's associated with this
00078       // <exit_hook>.
00079       exit_hook.thr_mgr (this->thr_mgr ());
00080     }
00081 # else
00082   // Without TSS, create an <ACE_Thread_Exit> instance.  When this
00083   // function returns, its destructor will be called because the
00084   // object goes out of scope.  The drawback with this appraoch is
00085   // that the destructor _won't_ get called if <thr_exit> is called.
00086   // So, threads shouldn't exit that way.  Instead, they should return
00087   // from <svc>.
00088   ACE_Thread_Exit exit_hook;
00089   exit_hook.thr_mgr (this->thr_mgr ());
00090 # endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE || ACE_HAS_TSS_EMULATION */
00091 
00092 #endif /* ! ACE_USE_THREAD_MANAGER_ADAPTER */
00093 
00094   return this->invoke_i ();
00095 }
00096 
00097 ACE_THR_FUNC_RETURN
00098 ACE_Thread_Adapter::invoke_i (void)
00099 {
00100   // Extract the arguments.
00101   ACE_THR_FUNC func = ACE_reinterpret_cast (ACE_THR_FUNC,
00102                                             this->user_func_);
00103   void *arg = this->arg_;
00104 
00105 #if defined (ACE_WIN32) && defined (ACE_HAS_MFC) && (ACE_HAS_MFC != 0)
00106   ACE_OS_Thread_Descriptor *thr_desc = this->thr_desc_;
00107 #endif /* ACE_WIN32 && ACE_HAS_MFC && (ACE_HAS_MFC != 0) */
00108 
00109   // Delete ourselves since we don't need <this> anymore.  Make sure
00110   // not to access <this> anywhere below this point.
00111   delete this;
00112 
00113 #if defined (ACE_NEEDS_LWP_PRIO_SET)
00114   // On SunOS, the LWP priority needs to be set in order to get
00115   // preemption when running in the RT class.  This is the ACE way to
00116   // do that . . .
00117   ACE_hthread_t thr_handle;
00118   ACE_OS::thr_self (thr_handle);
00119   int prio;
00120 
00121   // thr_getprio () on the current thread should never fail.
00122   ACE_OS::thr_getprio (thr_handle, prio);
00123 
00124   // ACE_OS::thr_setprio () has the special logic to set the LWP priority,
00125   // if running in the RT class.
00126   ACE_OS::thr_setprio (prio);
00127 
00128 #endif /* ACE_NEEDS_LWP_PRIO_SET */
00129 
00130   ACE_THR_FUNC_RETURN status = 0;
00131 
00132   ACE_SEH_TRY
00133     {
00134       ACE_SEH_TRY
00135         {
00136           ACE_Thread_Hook *hook =
00137             ACE_OS_Object_Manager::thread_hook ();
00138 
00139           if (hook)
00140             // Invoke the start hook to give the user a chance to
00141             // perform some initialization processing before the
00142             // <func> is invoked.
00143             status = hook->start (func, arg);
00144           else
00145             {
00146               // Call thread entry point.
00147 #if defined (ACE_PSOS)
00148               status = 0;
00149               (*func) (arg);
00150 #else /* ! ACE_PSOS */
00151               status = (*func) (arg);
00152 #endif /* ACE_PSOS */
00153             }
00154         }
00155 
00156 #if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS)
00157       ACE_SEH_EXCEPT (ACE_OS_Object_Manager::seh_except_selector ()(
00158                           (void *) GetExceptionInformation ()))
00159         {
00160           ACE_OS_Object_Manager::seh_except_handler ()(0);
00161         }
00162 #endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */
00163     }
00164 
00165   ACE_SEH_FINALLY
00166     {
00167       // If we changed this to 1, change the respective if in
00168       // Task::svc_run to 0.
00169 #if 0
00170       // Call the <Task->close> hook.
00171       if (func == ACE_reinterpret_cast (ACE_THR_FUNC_INTERNAL,
00172                                         ACE_Task_Base::svc_run))
00173         {
00174           ACE_Task_Base *task_ptr = (ACE_Task_Base *) arg;
00175           ACE_Thread_Manager *thr_mgr_ptr = task_ptr->thr_mgr ();
00176 
00177           // This calls the Task->close () hook.
00178           task_ptr->cleanup (task_ptr, 0);
00179 
00180           // This prevents a second invocation of the cleanup code
00181           // (called later by <ACE_Thread_Manager::exit>.
00182           thr_mgr_ptr->at_exit (task_ptr, 0, 0);
00183         }
00184 #endif /* 0 */
00185 
00186 #if defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION)
00187 # if defined (ACE_WIN32) && defined (ACE_HAS_MFC) && (ACE_HAS_MFC != 0)
00188       int using_afx = -1;
00189       if (thr_desc)
00190         using_afx = ACE_BIT_ENABLED (thr_desc->flags (), THR_USE_AFX);
00191 # endif /* ACE_WIN32 && ACE_HAS_MFC && (ACE_HAS_MFC != 0) */
00192           // Call TSS destructors.
00193       ACE_OS::cleanup_tss (0 /* not main thread */);
00194 
00195 # if defined (ACE_WIN32)
00196       // Exit the thread.  Allow CWinThread-destructor to be invoked
00197       // from AfxEndThread.  _endthreadex will be called from
00198       // AfxEndThread so don't exit the thread now if we are running
00199       // an MFC thread.
00200 #   if defined (ACE_HAS_MFC) && (ACE_HAS_MFC != 0)
00201       if (using_afx != -1)
00202         {
00203           if (using_afx)
00204             ::AfxEndThread ((DWORD) status);
00205           else
00206             ACE_ENDTHREADEX (status);
00207         }
00208       else
00209         {
00210           // Not spawned by ACE_Thread_Manager, use the old buggy
00211           // version.  You should seriously consider using
00212           // ACE_Thread_Manager to spawn threads.  The following code
00213           // is know to cause some problem.
00214           CWinThread *pThread = ::AfxGetThread ();
00215 
00216           if (!pThread || pThread->m_nThreadID != ACE_OS::thr_self ())
00217             ACE_ENDTHREADEX (status);
00218           else
00219             ::AfxEndThread ((DWORD)status);
00220         }
00221 #   else
00222 
00223       ACE_ENDTHREADEX (status);
00224 #   endif /* ACE_HAS_MFC && ACE_HAS_MFS != 0*/
00225 # endif /* ACE_WIN32 */
00226 #endif /* ACE_WIN32 || ACE_HAS_TSS_EMULATION */
00227 
00228 #if defined (ACE_PSOS)
00229       // This sequence of calls is documented by ISI as the proper way to
00230       // clean up a pSOS task. They affect different components, so only
00231       // try the ones for components that are built with ACE.
00232 #  if defined (SC_PREPC) && (SC_PREPC == YES)
00233       ::fclose (0);   // Return pREPC+ resources
00234 #  endif /* SC_PREPC */
00235 #  if defined (SC_PHILE) && (SC_PHILE == YES)
00236       ::close_f (0);  // Return pHILE+ resources
00237 #  endif /* SC_PHILE */
00238 #  if defined (SC_PNA) && (SC_PNA == YES)
00239       ::close (0);    // Return pNA+ resources
00240 #  endif /* SC_PNA */
00241 #  if defined (SC_SC_PREPC) && (SC_PREPC == YES)
00242       ::free (-1);    // Return pREPC+ memory
00243 #  endif /* SC_PREPC */
00244       status = ::t_delete (0); // Suicide - only returns on error
00245 #endif /* ACE_PSOS */
00246     }
00247 
00248   return status;
00249 }

Generated on Mon Jun 16 11:21:45 2003 for ACE by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002