Changes to attempt to silence bcc64x
[ACE_TAO.git] / ACE / ace / Thread_Adapter.cpp
blobd72d0d2d010fa79dfbd0f2042298b2ed4bbb1616
1 #include "ace/Thread_Adapter.h"
2 #include "ace/Thread_Manager.h"
3 #include "ace/Thread_Exit.h"
4 #include "ace/Thread_Hook.h"
5 #include "ace/Object_Manager_Base.h"
6 #include "ace/Service_Config.h"
8 #if !defined (ACE_HAS_INLINED_OSCALLS)
9 # include "ace/Thread_Adapter.inl"
10 #endif /* ACE_HAS_INLINED_OSCALLS */
12 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
14 ACE_Thread_Adapter::ACE_Thread_Adapter (ACE_THR_FUNC user_func,
15 void *arg,
16 ACE_THR_C_FUNC entry_point,
17 ACE_Thread_Manager *tm,
18 ACE_Thread_Descriptor *td
19 #if defined (ACE_HAS_WIN32_STRUCTURED_EXCEPTIONS)
20 , ACE_SEH_EXCEPT_HANDLER selector,
21 ACE_SEH_EXCEPT_HANDLER handler
22 #endif /* ACE_HAS_WIN32_STRUCTURED_EXCEPTIONS */
23 , long cancel_flags)
24 : ACE_Base_Thread_Adapter (
25 user_func
26 , arg
27 , entry_point
28 , td
29 #if defined (ACE_HAS_WIN32_STRUCTURED_EXCEPTIONS)
30 , selector
31 , handler
32 #endif /* ACE_HAS_WIN32_STRUCTURED_EXCEPTIONS */
33 , cancel_flags)
34 , thr_mgr_ (tm)
36 ACE_OS_TRACE ("ACE_Thread_Adapter::ACE_Thread_Adapter");
39 ACE_Thread_Adapter::~ACE_Thread_Adapter ()
43 ACE_ALLOC_HOOK_DEFINE(ACE_Thread_Adapter);
45 ACE_THR_FUNC_RETURN
46 ACE_Thread_Adapter::invoke ()
48 // Inherit the logging features if the parent thread has an
49 // ACE_Log_Msg instance in thread-specific storage.
50 this->inherit_log_msg ();
52 ACE_Service_Config::current (ACE_Service_Config::global());
54 #if !defined(ACE_USE_THREAD_MANAGER_ADAPTER)
55 // NOTE: this preprocessor directive should match the one in above
56 // ACE_Thread_Exit::instance (). With the Xavier Pthreads package,
57 // the exit_hook in TSS causes a seg fault. So, this works around
58 // that by creating exit_hook on the stack.
59 # if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION)
60 // Obtain our thread-specific exit hook and make sure that it knows
61 // how to clean us up! Note that we never use this pointer directly
62 // (it's stored in thread-specific storage), so it's ok to
63 // dereference it here and only store it as a reference.
65 // Except if it is null, then the thr_mgr() method crashes.
66 // -jxh
68 ACE_Thread_Exit *exit_hook_instance = ACE_Thread_Exit::instance ();
69 ACE_Thread_Exit_Maybe exit_hook_maybe (exit_hook_instance == 0);
70 ACE_Thread_Exit *exit_hook_ptr = exit_hook_instance
71 ? exit_hook_instance
72 : exit_hook_maybe.instance ();
73 ACE_Thread_Exit &exit_hook = *exit_hook_ptr;
75 if (this->thr_mgr () != 0)
77 // Keep track of the <Thread_Manager> that's associated with this
78 // <exit_hook>.
79 exit_hook.thr_mgr (this->thr_mgr ());
81 # else
82 // Without TSS, create an <ACE_Thread_Exit> instance. When this
83 // function returns, its destructor will be called because the
84 // object goes out of scope. The drawback with this appraoch is
85 // that the destructor _won't_ get called if <thr_exit> is called.
86 // So, threads shouldn't exit that way. Instead, they should return
87 // from <svc>.
88 ACE_Thread_Exit exit_hook;
89 exit_hook.thr_mgr (this->thr_mgr ());
90 # endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE || ACE_HAS_TSS_EMULATION */
92 #endif /* ! ACE_USE_THREAD_MANAGER_ADAPTER */
94 return this->invoke_i ();
97 ACE_THR_FUNC_RETURN
98 ACE_Thread_Adapter::invoke_i ()
100 // Extract the arguments.
101 ACE_THR_FUNC func = reinterpret_cast<ACE_THR_FUNC> (this->user_func_);
102 void *arg = this->arg_;
104 #if defined (ACE_WIN32) && defined (ACE_HAS_MFC) && (ACE_HAS_MFC != 0)
105 ACE_OS_Thread_Descriptor *thr_desc = this->thr_desc_;
106 #endif /* ACE_WIN32 && ACE_HAS_MFC && (ACE_HAS_MFC != 0) */
108 // Pick up the cancel-related flags before deleting this.
109 long cancel_flags = this->flags_;
111 // Delete ourselves since we don't need <this> anymore. Make sure
112 // not to access <this> anywhere below this point.
113 delete this;
115 if (cancel_flags != 0)
117 // If both flags are set, ignore this.
118 int old = 0;
119 int val = cancel_flags & (THR_CANCEL_ENABLE | THR_CANCEL_DISABLE);
120 if (val == THR_CANCEL_ENABLE || val == THR_CANCEL_DISABLE)
121 ACE_OS::thr_setcancelstate (val, &old);
122 val = cancel_flags & (THR_CANCEL_DEFERRED | THR_CANCEL_ASYNCHRONOUS);
123 if (val == THR_CANCEL_DEFERRED || val == THR_CANCEL_ASYNCHRONOUS)
124 ACE_OS::thr_setcanceltype (val, &old);
127 ACE_THR_FUNC_RETURN status = 0;
129 ACE_SEH_TRY
131 ACE_SEH_TRY
133 ACE_Thread_Hook *hook =
134 ACE_OS_Object_Manager::thread_hook ();
136 if (hook)
137 // Invoke the start hook to give the user a chance to
138 // perform some initialization processing before the
139 // <func> is invoked.
140 status = hook->start (func, arg);
141 else
142 // Call thread entry point.
143 status = (*func) (arg);
146 #if defined (ACE_HAS_WIN32_STRUCTURED_EXCEPTIONS)
147 ACE_SEH_EXCEPT (ACE_OS_Object_Manager::seh_except_selector ()(
148 (void *) GetExceptionInformation ()))
150 ACE_OS_Object_Manager::seh_except_handler ()(0);
152 #endif /* ACE_HAS_WIN32_STRUCTURED_EXCEPTIONS */
155 ACE_SEH_FINALLY
157 // If we changed this to 1, change the respective if in
158 // Task::svc_run to 0.
159 #if 0
160 // Call the <Task->close> hook.
161 if (func == reinterpret_cast<ACE_THR_FUNC_INTERNAL> (
162 ACE_Task_Base::svc_run))
164 ACE_Task_Base *task_ptr = (ACE_Task_Base *) arg;
165 ACE_Thread_Manager *thr_mgr_ptr = task_ptr->thr_mgr ();
167 // This calls the Task->close () hook.
168 task_ptr->cleanup (task_ptr, 0);
170 // This prevents a second invocation of the cleanup code
171 // (called later by <ACE_Thread_Manager::exit>.
172 thr_mgr_ptr->at_exit (task_ptr, 0, 0);
174 #endif /* 0 */
176 #if defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION)
177 # if defined (ACE_WIN32) && defined (ACE_HAS_MFC) && (ACE_HAS_MFC != 0)
178 int using_afx = -1;
179 if (thr_desc)
180 using_afx = ACE_BIT_ENABLED (thr_desc->flags (), THR_USE_AFX);
181 # endif /* ACE_WIN32 && ACE_HAS_MFC && (ACE_HAS_MFC != 0) */
182 // Call TSS destructors.
183 ACE_OS::cleanup_tss (0 /* not main thread */);
185 # if defined (ACE_WIN32)
186 // Exit the thread. Allow CWinThread-destructor to be invoked
187 // from AfxEndThread. _endthreadex will be called from
188 // AfxEndThread so don't exit the thread now if we are running
189 // an MFC thread.
190 # if defined (ACE_HAS_MFC) && (ACE_HAS_MFC != 0)
191 if (using_afx != -1)
193 if (using_afx)
194 ::AfxEndThread ((DWORD) status);
195 else
196 ACE_ENDTHREADEX (status);
198 else
200 // Not spawned by ACE_Thread_Manager, use the old buggy
201 // version. You should seriously consider using
202 // ACE_Thread_Manager to spawn threads. The following code
203 // is know to cause some problem.
204 CWinThread *pThread = ::AfxGetThread ();
206 if (!pThread || pThread->m_nThreadID != ACE_OS::thr_self ())
207 ACE_ENDTHREADEX (status);
208 else
209 ::AfxEndThread ((DWORD)status);
211 # else
213 ACE_ENDTHREADEX (status);
214 # endif /* ACE_HAS_MFC && ACE_HAS_MFS != 0*/
215 # endif /* ACE_WIN32 */
216 #endif /* ACE_WIN32 || ACE_HAS_TSS_EMULATION */
219 return status;
222 ACE_END_VERSIONED_NAMESPACE_DECL