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

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 Methods

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

virtual ACE_THR_FUNC_RETURN invoke (void)
ACE_Thread_Managerthr_mgr (void)
 Accessor for the optional <Thread_Manager>. More...


Private Methods

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

virtual ACE_THR_FUNC_RETURN invoke_i (void)
 Called by invoke, mainly here to separate the SEH stuff because SEH on Win32 doesn't compile with local vars with destructors. More...


Private Attributes

ACE_Thread_Managerthr_mgr_
 Optional thread manager. More...


Friends

class ACE_Thread_Adapter_Has_Private_Destructor
 Friend declaration to avoid compiler warning: only defines a private destructor and has no friends. More...


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 43 of file Thread_Adapter.h.


Constructor & Destructor Documentation

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,
ACE_Thread_Manager   thr_mgr = 0,
ACE_Thread_Descriptor   td = 0
 

Constructor.

Definition at line 18 of file Thread_Adapter.cpp.

References ACE_OS_TRACE.

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 }

ACE_Thread_Adapter::~ACE_Thread_Adapter void    [private]
 

Ensure that this object must be allocated on the heap.

Definition at line 43 of file Thread_Adapter.cpp.

00044 {
00045 }


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

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 }

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

References ACE_BIT_ENABLED, ACE_hthread_t, 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, and ACE_OS_Object_Manager::thread_hook.

Referenced by invoke.

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 }

ACE_INLINE ACE_Thread_Manager * ACE_Thread_Adapter::thr_mgr void   
 

Accessor for the optional <Thread_Manager>.

Definition at line 4 of file Thread_Adapter.inl.

References thr_mgr_.

Referenced by invoke.

00005 {
00006   return this->thr_mgr_;
00007 }


Friends And Related Function Documentation

friend class ACE_Thread_Adapter_Has_Private_Destructor [friend]
 

Friend declaration to avoid compiler warning: only defines a private destructor and has no friends.

Reimplemented from ACE_Base_Thread_Adapter.

Definition at line 82 of file Thread_Adapter.h.


Member Data Documentation

ACE_Thread_Manager* ACE_Thread_Adapter::thr_mgr_ [private]
 

Optional thread manager.

Definition at line 78 of file Thread_Adapter.h.

Referenced by thr_mgr.


The documentation for this class was generated from the following files:
Generated on Mon Jun 16 12:57:25 2003 for ACE by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002