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 ACE_Thread_Manager.

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 20 of file Thread_Adapter.cpp.

References ACE_OS_TRACE.

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 }

ACE_Thread_Adapter::~ACE_Thread_Adapter ( void   )  [protected]

Ensure that this object must be allocated on the heap.

Definition at line 45 of file Thread_Adapter.cpp.

00046 {
00047 }


Member Function Documentation

ACE_THR_FUNC_RETURN ACE_Thread_Adapter::invoke ( void   )  [virtual]

Execute the <user_func_> with the <arg>. This function deletes this, thereby rendering the object useless after the call returns.

Implements ACE_Base_Thread_Adapter.

Definition at line 50 of file Thread_Adapter.cpp.

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

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 }

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 102 of file Thread_Adapter.cpp.

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

Referenced by invoke().

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 }

ACE_BEGIN_VERSIONED_NAMESPACE_DECL ACE_INLINE ACE_Thread_Manager * ACE_Thread_Adapter::thr_mgr ( void   ) 

Accessor for the optional ACE_Thread_Manager.

Definition at line 8 of file Thread_Adapter.inl.

References thr_mgr_.

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.

Referenced by thr_mgr().


The documentation for this class was generated from the following files:
Generated on Tue Feb 2 17:35:44 2010 for ACE by  doxygen 1.4.7