Thread_Adapter.cpp

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

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