ACE_Thread_Adapter Class Reference

Converts a C++ function into a function that can be called from a thread creation routine (e.g., pthread_create() or _beginthreadex()) that expects an extern "C" entry point. This class also makes it possible to transparently provide hooks to register a thread with an ACE_Thread_Manager. More...

#include <Thread_Adapter.h>

Inheritance diagram for ACE_Thread_Adapter:

Inheritance graph
[legend]
Collaboration diagram for ACE_Thread_Adapter:

Collaboration graph
[legend]
List of all members.

Public Member Functions

 ACE_Thread_Adapter (ACE_THR_FUNC user_func, void *arg, ACE_THR_C_FUNC entry_point=(ACE_THR_C_FUNC) ACE_THREAD_ADAPTER_NAME, ACE_Thread_Manager *thr_mgr=0, ACE_Thread_Descriptor *td=0)
 Constructor.

virtual ACE_THR_FUNC_RETURN invoke (void)
ACE_Thread_Managerthr_mgr (void)
 Accessor for the optional .


Protected Member Functions

 ~ACE_Thread_Adapter (void)
 Ensure that this object must be allocated on the heap.


Private Member Functions

virtual ACE_THR_FUNC_RETURN invoke_i (void)

Private Attributes

ACE_Thread_Managerthr_mgr_
 Optional thread manager.


Detailed Description

Converts a C++ function into a function that can be called from a thread creation routine (e.g., pthread_create() or _beginthreadex()) that expects an extern "C" entry point. This class also makes it possible to transparently provide hooks to register a thread with an ACE_Thread_Manager.

This class is used in ACE_OS::thr_create(). In general, the thread that creates an object of this class is different from the thread that calls invoke() on this object. Therefore, the invoke() method is responsible for deleting itself.

Definition at line 46 of file Thread_Adapter.h.


Constructor & Destructor Documentation

ACE_BEGIN_VERSIONED_NAMESPACE_DECL ACE_Thread_Adapter::ACE_Thread_Adapter ACE_THR_FUNC  user_func,
void *  arg,
ACE_THR_C_FUNC  entry_point = (ACE_THR_C_FUNC) ACE_THREAD_ADAPTER_NAME,
ACE_Thread_Manager thr_mgr = 0,
ACE_Thread_Descriptor td = 0
 

Constructor.

Definition at line 19 of file Thread_Adapter.cpp.

References ACE_OS_TRACE.

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 }

ACE_Thread_Adapter::~ACE_Thread_Adapter void   )  [protected]
 

Ensure that this object must be allocated on the heap.

Definition at line 44 of file Thread_Adapter.cpp.

00045 {
00046 }


Member Function Documentation

ACE_THR_FUNC_RETURN ACE_Thread_Adapter::invoke void   )  [virtual]
 

Execute the with the . This function deletes , thereby rendering the object useless after the call returns.

Implements ACE_Base_Thread_Adapter.

Definition at line 49 of file Thread_Adapter.cpp.

References ACE_Base_Thread_Adapter::inherit_log_msg(), ACE_Thread_Exit_Maybe::instance(), ACE_Thread_Exit::instance(), invoke_i(), ACE_Thread_Exit::thr_mgr(), and thr_mgr().

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 }

ACE_THR_FUNC_RETURN ACE_Thread_Adapter::invoke_i void   )  [private, virtual]
 

Called by invoke, mainly here to separate the SEH stuff because SEH on Win32 doesn't compile with local vars with destructors.

Definition at line 99 of file Thread_Adapter.cpp.

References ACE_BIT_ENABLED, ACE_hthread_t, ACE_SEH_EXCEPT, ACE_SEH_FINALLY, ACE_SEH_TRY, ACE_Thread_Manager::at_exit(), ACE_Task_Base::cleanup(), ACE_OS::cleanup_tss(), ACE_OS_Thread_Descriptor::flags(), ACE_Thread_Hook::start(), ACE_OS::thr_getprio(), ACE_Task_Base::thr_mgr(), ACE_OS::thr_self(), ACE_OS::thr_setprio(), and ACE_OS_Object_Manager::thread_hook().

Referenced by invoke().

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 }

ACE_BEGIN_VERSIONED_NAMESPACE_DECL ACE_INLINE ACE_Thread_Manager * ACE_Thread_Adapter::thr_mgr void   ) 
 

Accessor for the optional .

Definition at line 8 of file Thread_Adapter.inl.

Referenced by invoke().

00009 {
00010   return this->thr_mgr_;
00011 }


Member Data Documentation

ACE_Thread_Manager* ACE_Thread_Adapter::thr_mgr_ [private]
 

Optional thread manager.

Definition at line 85 of file Thread_Adapter.h.


The documentation for this class was generated from the following files:
Generated on Thu Nov 9 11:30:48 2006 for ACE by doxygen 1.3.6