Thread_Adapter.cpp

Go to the documentation of this file.
00001 // Thread_Adapter.cpp,v 4.17 2006/05/30 13:15:25 schmidt Exp
00002 
00003 #include "ace/Thread_Adapter.h"
00004 #include "ace/Thread_Manager.h"
00005 #include "ace/Thread_Exit.h"
00006 #include "ace/Thread_Hook.h"
00007 #include "ace/Object_Manager_Base.h"
00008 
00009 ACE_RCSID (ace,
00010            Thread_Adapter,
00011            "Thread_Adapter.cpp,v 4.17 2006/05/30 13:15:25 schmidt Exp")
00012 
00013 #if !defined (ACE_HAS_INLINED_OSCALLS)
00014 # include "ace/Thread_Adapter.inl"
00015 #endif /* ACE_HAS_INLINED_OS_CALLS */
00016 
00017 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00018 
00019 ACE_Thread_Adapter::ACE_Thread_Adapter (ACE_THR_FUNC user_func,
00020                                         void *arg,
00021                                         ACE_THR_C_FUNC entry_point,
00022                                         ACE_Thread_Manager *tm,
00023                                         ACE_Thread_Descriptor *td
00024 #if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS)
00025                                         , ACE_SEH_EXCEPT_HANDLER selector,
00026                                         ACE_SEH_EXCEPT_HANDLER handler
00027 #endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */
00028                                         )
00029   : ACE_Base_Thread_Adapter (
00030         user_func
00031         , arg
00032         , entry_point
00033         , td
00034 #if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS)
00035         , selector
00036         , handler
00037 #endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */
00038         )
00039   , thr_mgr_ (tm)
00040 {
00041   ACE_OS_TRACE ("ACE_Thread_Adapter::ACE_Thread_Adapter");
00042 }
00043 
00044 ACE_Thread_Adapter::~ACE_Thread_Adapter (void)
00045 {
00046 }
00047 
00048 ACE_THR_FUNC_RETURN
00049 ACE_Thread_Adapter::invoke (void)
00050 {
00051   // Inherit the logging features if the parent thread has an
00052   // ACE_Log_Msg instance in thread-specific storage.
00053   this->inherit_log_msg ();
00054 
00055 #if !defined(ACE_USE_THREAD_MANAGER_ADAPTER)
00056   // NOTE: this preprocessor directive should match the one in above
00057   // ACE_Thread_Exit::instance ().  With the Xavier Pthreads package,
00058   // the exit_hook in TSS causes a seg fault.  So, this works around
00059   // that by creating exit_hook on the stack.
00060 # if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION)
00061   // Obtain our thread-specific exit hook and make sure that it knows
00062   // how to clean us up!  Note that we never use this pointer directly
00063   // (it's stored in thread-specific storage), so it's ok to
00064   // dereference it here and only store it as a reference.
00065 
00066   // Except if it is null, then the thr_mgr() method crashes.
00067   // -jxh
00068 
00069   ACE_Thread_Exit *exit_hook_instance = ACE_Thread_Exit::instance ();
00070   ACE_Thread_Exit_Maybe exit_hook_maybe (exit_hook_instance == 0);
00071   ACE_Thread_Exit *exit_hook_ptr = exit_hook_instance
00072                                    ? exit_hook_instance
00073                                    : exit_hook_maybe.instance ();
00074   ACE_Thread_Exit &exit_hook = *exit_hook_ptr;
00075 
00076   if (this->thr_mgr () != 0)
00077     {
00078       // Keep track of the <Thread_Manager> that's associated with this
00079       // <exit_hook>.
00080       exit_hook.thr_mgr (this->thr_mgr ());
00081     }
00082 # else
00083   // Without TSS, create an <ACE_Thread_Exit> instance.  When this
00084   // function returns, its destructor will be called because the
00085   // object goes out of scope.  The drawback with this appraoch is
00086   // that the destructor _won't_ get called if <thr_exit> is called.
00087   // So, threads shouldn't exit that way.  Instead, they should return
00088   // from <svc>.
00089   ACE_Thread_Exit exit_hook;
00090   exit_hook.thr_mgr (this->thr_mgr ());
00091 # endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE || ACE_HAS_TSS_EMULATION */
00092 
00093 #endif /* ! ACE_USE_THREAD_MANAGER_ADAPTER */
00094 
00095   return this->invoke_i ();
00096 }
00097 
00098 ACE_THR_FUNC_RETURN
00099 ACE_Thread_Adapter::invoke_i (void)
00100 {
00101   // Extract the arguments.
00102   ACE_THR_FUNC func = reinterpret_cast<ACE_THR_FUNC> (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             // Call thread entry point.
00146             status = (*func) (arg);
00147         }
00148 
00149 #if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS)
00150       ACE_SEH_EXCEPT (ACE_OS_Object_Manager::seh_except_selector ()(
00151                           (void *) GetExceptionInformation ()))
00152         {
00153           ACE_OS_Object_Manager::seh_except_handler ()(0);
00154         }
00155 #endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */
00156     }
00157 
00158   ACE_SEH_FINALLY
00159     {
00160       // If we changed this to 1, change the respective if in
00161       // Task::svc_run to 0.
00162 #if 0
00163       // Call the <Task->close> hook.
00164       if (func == reinterpret_cast<ACE_THR_FUNC_INTERNAL> (
00165             ACE_Task_Base::svc_run))
00166         {
00167           ACE_Task_Base *task_ptr = (ACE_Task_Base *) arg;
00168           ACE_Thread_Manager *thr_mgr_ptr = task_ptr->thr_mgr ();
00169 
00170           // This calls the Task->close () hook.
00171           task_ptr->cleanup (task_ptr, 0);
00172 
00173           // This prevents a second invocation of the cleanup code
00174           // (called later by <ACE_Thread_Manager::exit>.
00175           thr_mgr_ptr->at_exit (task_ptr, 0, 0);
00176         }
00177 #endif /* 0 */
00178 
00179 #if defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION)
00180 # if defined (ACE_WIN32) && defined (ACE_HAS_MFC) && (ACE_HAS_MFC != 0)
00181       int using_afx = -1;
00182       if (thr_desc)
00183         using_afx = ACE_BIT_ENABLED (thr_desc->flags (), THR_USE_AFX);
00184 # endif /* ACE_WIN32 && ACE_HAS_MFC && (ACE_HAS_MFC != 0) */
00185           // Call TSS destructors.
00186       ACE_OS::cleanup_tss (0 /* not main thread */);
00187 
00188 # if defined (ACE_WIN32)
00189       // Exit the thread.  Allow CWinThread-destructor to be invoked
00190       // from AfxEndThread.  _endthreadex will be called from
00191       // AfxEndThread so don't exit the thread now if we are running
00192       // an MFC thread.
00193 #   if defined (ACE_HAS_MFC) && (ACE_HAS_MFC != 0)
00194       if (using_afx != -1)
00195         {
00196           if (using_afx)
00197             ::AfxEndThread ((DWORD) status);
00198           else
00199             ACE_ENDTHREADEX (status);
00200         }
00201       else
00202         {
00203           // Not spawned by ACE_Thread_Manager, use the old buggy
00204           // version.  You should seriously consider using
00205           // ACE_Thread_Manager to spawn threads.  The following code
00206           // is know to cause some problem.
00207           CWinThread *pThread = ::AfxGetThread ();
00208 
00209           if (!pThread || pThread->m_nThreadID != ACE_OS::thr_self ())
00210             ACE_ENDTHREADEX (status);
00211           else
00212             ::AfxEndThread ((DWORD)status);
00213         }
00214 #   else
00215 
00216       ACE_ENDTHREADEX (status);
00217 #   endif /* ACE_HAS_MFC && ACE_HAS_MFS != 0*/
00218 # endif /* ACE_WIN32 */
00219 #endif /* ACE_WIN32 || ACE_HAS_TSS_EMULATION */
00220     }
00221 
00222   return status;
00223 }
00224 
00225 ACE_END_VERSIONED_NAMESPACE_DECL

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