summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README4
-rw-r--r--ace/OS.cpp128
-rw-r--r--ace/OS.h123
-rw-r--r--ace/OS.i12
-rw-r--r--ace/Parse_Node.cpp3
-rw-r--r--ace/README1
-rw-r--r--ace/Strategies_T.cpp38
-rw-r--r--ace/Strategies_T.h14
-rw-r--r--ace/Synch.cpp9
-rw-r--r--ace/Synch_T.cpp2
-rw-r--r--ace/Synch_T.h9
-rw-r--r--ace/Task.cpp25
-rw-r--r--ace/Task.h10
-rw-r--r--ace/Thread.cpp34
-rw-r--r--ace/Thread.h86
-rw-r--r--ace/Thread.i14
-rw-r--r--ace/Thread_Manager.cpp32
-rw-r--r--ace/Thread_Manager.h17
-rw-r--r--ace/Timer_Hash_T.cpp19
-rw-r--r--ace/config-sco-5.0.0-fsu-pthread.h2
20 files changed, 382 insertions, 200 deletions
diff --git a/README b/README
index 0373bbb0735..4e799d40fd1 100644
--- a/README
+++ b/README
@@ -440,7 +440,9 @@ Wei Chiang <chiang@tele.nokia.fi>
Thanh Ma <tma@encore.com>
Oleg Krivosheev <kriol@fnal.gov>
Stephen Coy <stevec@wsa.com.au>
-
+Bob Laferriere <laferrie@gsao.med.ge.com>
+Satheesh Kumar MG <satheesh@india.aspectdv.com>
+
I would particularly like to thank Paul Stephenson, who worked with me
at Ericsson and is now at ObjectSpace. Paul devised the recursive
Makefile scheme that underlies this distribution and also spent
diff --git a/ace/OS.cpp b/ace/OS.cpp
index a0dd01133b3..2df9f89d4b4 100644
--- a/ace/OS.cpp
+++ b/ace/OS.cpp
@@ -1271,77 +1271,42 @@ ACE_TSS_Cleanup::dump (void)
#endif /* WIN32 */
-#if !defined (VXWORKS) && ( defined (ACE_WIN32) || defined (ACE_HAS_THR_C_FUNC) || !defined (ACE_THREADS_DONT_INHERIT_LOG_MSG))
-class ACE_Thread_Adapter
- // = TITLE
- // Converts a C++ function into a function <ace_thread_adapter>
- // function that can be called from a thread creation routine
- // (e.g., pthread_create() or _beginthreadex()) that expects an
- // extern "C" entry point.
- //
- // = DESCRIPTION
- // This is used below in <ACE_OS::thr_create> for Win32 and
- // MVS.
+void
+ACE_Thread_Adapter::inherit_log_msg (void)
{
-public:
- ACE_Thread_Adapter (ACE_THR_FUNC f, void *a);
- // Constructor.
-
- // private:
- // = Arguments to thread startup.
- ACE_THR_FUNC func_;
- // Thread startup function (C++ linkage).
-
- void *arg_;
- // Argument to thread startup function.
+ // Inherit the logging features if the parent thread has an
+ // <ACE_Log_Msg>. Note that all of the following operations occur
+ // within thread-specific storage.
+ ACE_Log_Msg *new_log = ACE_LOG_MSG;
#if !defined (ACE_THREADS_DONT_INHERIT_LOG_MSG)
- ostream *ostream_;
- // Ostream where the new TSS Log_Msg will use.
-
- u_long priority_mask_;
- // Priority_mask to be used in new TSS Log_Msg.
-
- int tracing_enabled_;
- // Are we allowing tracing in this thread?
+ if (this->ostream_)
+ {
+ new_log->msg_ostream (this->ostream_);
+ new_log->priority_mask (this->priority_mask_);
- int restart_;
- // Indicates whether we should restart system calls that are
- // interrupted.
+ if (this->tracing_enabled_)
+ new_log->start_tracing ();
- int trace_depth_;
- // Depth of the nesting for printing traces.
-#endif /* ACE_THREADS_DONT_INHERIT_LOG_MSG */
-};
-
-// Run the thread exit point. This must be an extern "C" to make
-// certain compilers happy...
+ new_log->restart (this->restart_);
+ new_log->trace_depth (this->trace_depth_);
+ }
+#endif /* ACE_THREADS_DONT_INHERIT_LOG_MSG */
+}
-extern "C" void *
-ace_thread_adapter (void *args)
+void *
+ACE_Thread_Adapter::invoke (void)
{
- // ACE_TRACE ("ace_thread_adapter");
- ACE_Thread_Adapter *thread_args = (ACE_Thread_Adapter *) args;
+ // Inherit the logging features if the parent thread has an
+ // ACE_Log_Msg instance in thread-specific storage.
+ this->inherit_log_msg ();
- ACE_THR_FUNC func = thread_args->func_;
+ // Extract the arguments.
+ ACE_THR_FUNC func = this->user_func_;
+ void *arg = this->arg_;
- // Inherit the logging feature if the parent
- // has got an ACE_Log_Msg.
- ACE_Log_Msg *new_log = ACE_LOG_MSG;
-#if !defined (ACE_THREADS_DONT_INHERIT_LOG_MSG)
- if (thread_args->ostream_)
- {
- new_log->msg_ostream (thread_args->ostream_);
- new_log->priority_mask (thread_args->priority_mask_);
- if (thread_args->tracing_enabled_)
- new_log->start_tracing ();
- new_log->restart (thread_args->restart_);
- new_log->trace_depth (thread_args->trace_depth_);
- }
-#endif /* ACE_THREADS_DONT_INHERIT_LOG_MSG */
- void *arg = thread_args->arg_;
-
- delete thread_args;
+ // Delete ourselves since we don't need <this> anymore.
+ delete (void *) this;
#if defined (ACE_WIN32)
void *status = 0;
@@ -1367,9 +1332,27 @@ ace_thread_adapter (void *args)
#endif /* ACE_WIN32 */
}
-ACE_Thread_Adapter::ACE_Thread_Adapter (ACE_THR_FUNC f, void *a)
- : func_(f),
- arg_(a)
+// Run the thread entry point for the <ACE_Thread_Adapter>. This must
+// be an extern "C" to make certain compilers happy...
+
+extern "C" void *
+ace_thread_adapter (void *args)
+{
+ // ACE_TRACE ("ace_thread_adapter");
+ ACE_Thread_Adapter *thread_args = (ACE_Thread_Adapter *) args;
+
+ // Invoke the user-supplied function with the args.
+ return thread_args->invoke ();
+}
+
+ACE_Thread_Adapter::ACE_Thread_Adapter (ACE_THR_FUNC user_func,
+ void *arg,
+ ACE_THR_C_FUNC entry_point,
+ ACE_Thread_Manager *tm)
+ : user_func_ (user_func),
+ arg_ (arg),
+ entry_point_ (entry_point),
+ thr_mgr_ (tm)
#if !defined (ACE_THREADS_DONT_INHERIT_LOG_MSG)
,
ostream_ (NULL),
@@ -1392,7 +1375,6 @@ ACE_Thread_Adapter::ACE_Thread_Adapter (ACE_THR_FUNC f, void *a)
}
#endif /* ACE_THREADS_DONT_INHERIT_LOG_MSG */
}
-#endif /* VXWORKS && ACE_THREADS_DONT_INHERIT_LOG_MSG ... */
int
ACE_OS::thr_create (ACE_THR_FUNC func,
@@ -1402,21 +1384,25 @@ ACE_OS::thr_create (ACE_THR_FUNC func,
ACE_hthread_t *thr_handle,
long priority,
void *stack,
- size_t stacksize)
+ size_t stacksize,
+ ACE_Thread_Adapter *thread_adapter)
{
// ACE_TRACE ("ACE_OS::thr_create");
-#if defined (VXWORKS) || (defined (ACE_THREADS_DONT_INHERIT_LOG_MSG) && (!defined (ACE_WIN32) || !defined (ACE_HAS_THR_C_FUNC)))
+#if defined (ACE_NO_THREAD_ADAPTER)
#define ACE_THREAD_FUNCTION func
#define ACE_THREAD_ARGUMENT args
#else
-#define ACE_THREAD_FUNCTION ace_thread_adapter
+#define ACE_THREAD_FUNCTION thread_args->entry_point ()
#define ACE_THREAD_ARGUMENT thread_args
ACE_Thread_Adapter *thread_args;
- ACE_NEW_RETURN (thread_args, ACE_Thread_Adapter (func, args), -1);
+ if (thread_adapter == 0)
+ ACE_NEW_RETURN (thread_args, ACE_Thread_Adapter (func, args, ace_thread_adapter), -1);
+ else
+ thread_args = thread_adapter;
-#endif /* VXWORKS || ACE_THREADS_DONT_INHERIT_LOG_MSG ... */
+#endif /* ACE_NO_THREAD_ADAPTER */
#if defined (ACE_HAS_THREADS)
ACE_thread_t tmp_thr;
diff --git a/ace/OS.h b/ace/OS.h
index baad4c5062b..bdb20472705 100644
--- a/ace/OS.h
+++ b/ace/OS.h
@@ -2937,6 +2937,79 @@ struct ACE_Export ACE_Str_Buf : public strbuf
#define ACE_MSB_MASK (~(1 << (NFDBITS - 1)))
#endif /* ACE_HAS_BROKEN_BITSHIFT */
+// Run the thread entry point for the <ACE_Thread_Adapter>. This must
+// be an extern "C" to make certain compilers happy...
+extern "C" void *ace_thread_adapter (void *args);
+
+// Forward decl.
+class ACE_Thread_Manager;
+
+class ACE_Thread_Adapter
+ // = TITLE
+ // Converts a C++ function into a function <ace_thread_adapter>
+ // 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>.
+ //
+ // = DESCRIPTION
+ // This class is used in <ACE_OS::thr_create>.
+{
+public:
+ 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 *tm = 0);
+ // Constructor.
+
+ void *invoke (void);
+ // Execute the <user_func_> with the <arg>.
+
+ ACE_Thread_Manager *thr_mgr (void);
+ // Accessor for the optional <Thread_Manager>.
+
+ ACE_THR_C_FUNC entry_point (void);
+ // Accessor for the C entry point function to the OS thread creation
+ // routine.
+
+private:
+ void inherit_log_msg (void);
+ // Inherit the logging features if the parent thread has an
+ // <ACE_Log_Msg>.
+
+ ACE_THR_FUNC user_func_;
+ // Thread startup function passed in by the user (C++ linkage).
+
+ void *arg_;
+ // Argument to thread startup function.
+
+ ACE_THR_C_FUNC entry_point_;
+ // Entry point to the underlying OS thread creation call (C
+ // linkage).
+
+ ACE_Thread_Manager *thr_mgr_;
+ // Optional thread manager.
+
+#if !defined (ACE_THREADS_DONT_INHERIT_LOG_MSG)
+ ostream *ostream_;
+ // Ostream where the new TSS Log_Msg will use.
+
+ u_long priority_mask_;
+ // Priority_mask to be used in new TSS Log_Msg.
+
+ int tracing_enabled_;
+ // Are we allowing tracing in this thread?
+
+ int restart_;
+ // Indicates whether we should restart system calls that are
+ // interrupted.
+
+ int trace_depth_;
+ // Depth of the nesting for printing traces.
+#endif /* ACE_THREADS_DONT_INHERIT_LOG_MSG */
+};
+
class ACE_Export ACE_OS
// = TITLE
// This class defines an operating system independent
@@ -3796,36 +3869,47 @@ public:
static int thr_cancel (ACE_Thread_ID t_id);
#endif /* 0 */
- // = A set of wrappers for threads (these are non-portable since they use ACE_thread_t and ACE_hthread_t and will go away in a future release).
+ // = A set of wrappers for threads
+
+ // These are non-portable since they use ACE_thread_t and
+ // ACE_hthread_t and will go away in a future release.
static int thr_continue (ACE_hthread_t target_thread);
- static int thr_create (ACE_THR_FUNC,
+ static int thr_create (ACE_THR_FUNC func,
void *args,
long flags,
ACE_thread_t *thr_id,
ACE_hthread_t *t_handle = 0,
long priority = ACE_DEFAULT_THREAD_PRIORITY,
void *stack = 0,
- size_t stacksize = 0);
- // Creates a new thread having <{flags}> attributes and running <{ACE_THR_FUNC}>
- // with <{args}>. <{thr_id}> and <{t_handle}> are set to the thread's ID and handle (?),
- // respectively. The thread runs at <{priority}> priority (see below).
+ size_t stacksize = 0,
+ ACE_Thread_Adapter *thread_adapter = 0);
+ // Creates a new thread having <flags> attributes and running <func>
+ // with <args> (if <thread_adapter> is non-0 then <func> and <args>
+ // are ignored and are obtained from <thread_adapter>). <thr_id>
+ // and <t_handle> are set to the thread's ID and handle (?),
+ // respectively. The thread runs at <priority> priority (see
+ // below).
//
- // The <{flags}> are a bitwise-OR of the following:
+ // The <flags> are a bitwise-OR of the following:
// = BEGIN<INDENT>
- // THR_CANCEL_DISABLE, THR_CANCEL_ENABLE, THR_CANCEL_DEFERRED, THR_CANCEL_ASYNCHRONOUS,
- // THR_BOUND, THR_NEW_LWP, THR_DETACHED, THR_SUSPENDED, THR_DAEMON, THR_JOINABLE,
- // THR_SCHED_FIFO, THR_SCHED_RR, THR_SCHED_DEFAULT
+ // THR_CANCEL_DISABLE, THR_CANCEL_ENABLE, THR_CANCEL_DEFERRED,
+ // THR_CANCEL_ASYNCHRONOUS, THR_BOUND, THR_NEW_LWP, THR_DETACHED,
+ // THR_SUSPENDED, THR_DAEMON, THR_JOINABLE, THR_SCHED_FIFO,
+ // THR_SCHED_RR, THR_SCHED_DEFAULT
// = END<INDENT>
//
- // By default, or if <{priority}> is set to ACE_DEFAULT_THREAD_PRIORITY,
- // an "appropriate"
- // priority value for the given scheduling policy (specified in
- // <{flags}>, e.g., <THR_SCHED_DEFAULT>) is used. This value is
- // calculated dynamically, and is the median value between the
- // minimum and maximum priority values for the given policy. If an
- // explicit value is given, it is used. Note that actual priority
- // values are EXTREMEMLY implementation-dependent, and are probably
- // best avoided.
+ // By default, or if <priority> is set to
+ // ACE_DEFAULT_THREAD_PRIORITY, an "appropriate" priority value for
+ // the given scheduling policy (specified in <flags}>, e.g.,
+ // <THR_SCHED_DEFAULT>) is used. This value is calculated
+ // dynamically, and is the median value between the minimum and
+ // maximum priority values for the given policy. If an explicit
+ // value is given, it is used. Note that actual priority values are
+ // EXTREMEMLY implementation-dependent, and are probably best
+ // avoided.
+ //
+ // Note that <thread_adapter> is always deleted by <thr_create>,
+ // therefore it must be allocated with global operator new.
static int thr_getprio (ACE_hthread_t thr_id,
int &prio);
@@ -4131,7 +4215,6 @@ ace_main_i
// These need to come here to avoid problems with circular dependencies.
#include "ace/Log_Msg.h"
-
// The following are some insane macros that are useful in cases when
// one has to have a string in a certain format. Both of these macros
// allow the user to create a temporary copy. If the user needs to
diff --git a/ace/OS.i b/ace/OS.i
index 9318b1b575d..295e42a7d7a 100644
--- a/ace/OS.i
+++ b/ace/OS.i
@@ -7616,3 +7616,15 @@ ACE_OS::sbrk (int brk)
#endif /* VXWORKS */
}
+ACE_INLINE ACE_Thread_Manager *
+ACE_Thread_Adapter::thr_mgr (void)
+{
+ return this->thr_mgr_;
+}
+
+ACE_INLINE ACE_THR_C_FUNC
+ACE_Thread_Adapter::entry_point (void)
+{
+ return this->entry_point_;
+}
+
diff --git a/ace/Parse_Node.cpp b/ace/Parse_Node.cpp
index f7b5158d26b..1ff0bc98863 100644
--- a/ace/Parse_Node.cpp
+++ b/ace/Parse_Node.cpp
@@ -195,7 +195,6 @@ ACE_Remove_Node::apply (void)
}
-
ACE_Dynamic_Node::ACE_Dynamic_Node (const ACE_Service_Record *sr,
char *parms)
: ACE_Static_Node (sr->name (), parms),
@@ -260,7 +259,7 @@ ACE_Static_Node::record (void) const
ACE_Service_Record *sr;
if (ACE_Service_Repository::instance()->find (this->name (),
- (const ACE_Service_Record **) &sr) == -1)
+ (const ACE_Service_Record **) &sr) == -1)
return 0;
else
return sr;
diff --git a/ace/README b/ace/README
index 915a500ee18..a1f84daf052 100644
--- a/ace/README
+++ b/ace/README
@@ -259,6 +259,7 @@ ACE_NEEDS_SYSTIME_H <time.h> doesn't automatically #include /**/ <sys/time.h>
ACE_NEEDS_WRITEV Platform doesn't define writev, so use our own
ACE_NLOGGING Turns off the LM_DEBUG and LM_ERROR logging macros...
ACE_NTRACE Turns off the tracing feature.
+ACE_NO_THREAD_ADAPTER Don't use the ACE_Thread_Adapter feature...
ACE_PAGE_SIZE Defines the page size of the system (not used on Win32 or with ACE_HAS_GETPAGESIZE).
ACE_REDEFINES_XTI_FUNCTIONS Platform redefines the t_... names (UnixWare)
ACE_SELECT_USES_INT Platform uses int for select() rather than fd_set
diff --git a/ace/Strategies_T.cpp b/ace/Strategies_T.cpp
index f7d34e859ca..990f58529be 100644
--- a/ace/Strategies_T.cpp
+++ b/ace/Strategies_T.cpp
@@ -107,23 +107,33 @@ ACE_DLL_Strategy<SVC_HANDLER>::dump (void) const
}
template <class SVC_HANDLER> int
-ACE_DLL_Strategy<SVC_HANDLER>::open (const char svc_dll_info[],
+ACE_DLL_Strategy<SVC_HANDLER>::open (const char dll_name[],
+ const char factory_function[],
+ const char svc_name[],
ACE_Service_Repository *svc_rep,
ACE_Thread_Manager *thr_mgr)
{
ACE_TRACE ("ACE_DLL_Strategy<SVC_HANDLER>::open");
this->inherited::open (thr_mgr);
+ ACE_OS::strncpy (this->dll_name_, dll_name);
+ ACE_OS::strncpy (this->factory_function_, factory_function);
+ ACE_OS::strncpy (this->svc_name_, svc_name);
this->svc_rep_ = svc_rep;
return 0;
}
template <class SVC_HANDLER>
-ACE_DLL_Strategy<SVC_HANDLER>::ACE_DLL_Strategy (const char svc_dll_info[],
+ACE_DLL_Strategy<SVC_HANDLER>::ACE_DLL_Strategy (const char dll_name[],
+ const char factory_function[],
+ const char svc_name[],
ACE_Service_Repository *svc_rep,
ACE_Thread_Manager *thr_mgr)
{
ACE_TRACE ("ACE_DLL_Strategy<SVC_HANDLER>::ACE_DLL_Strategy");
- if (this->open (svc_dll_info, svc_rep, thr_mgr) == -1)
+ if (this->open (dll_name,
+ factory_function,
+ svc_name,
+ svc_rep, thr_mgr) == -1)
ACE_ERROR ((LM_ERROR, "%p\n", "open"));
}
@@ -157,7 +167,27 @@ ACE_DLL_Strategy<SVC_HANDLER>::make_svc_handler (SVC_HANDLER *&sh)
// Create an ACE_Service_Record containing the SVC_Handler and
// insert into this->svc_rep_;
- // @@ This remains to be implemented...
+ ACE_Service_Type stp =
+ new ACE_Service_Object_Type (svc_handler, this->svc_name_);
+
+ if (stp == 0)
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ ACE_Service_Record *srp =
+ new ACE_Service_Record (this->svc_name_, stp, handle, 1);
+
+ if (srp == 0)
+ {
+ delete stp;
+ errno = ENOMEM;
+ return -1;
+ }
+
+ if (this->svc_rep_->insert (srp) == -1)
+ return -1;
// @@ Somehow, we need to deal with this->thr_mgr_...
}
diff --git a/ace/Strategies_T.h b/ace/Strategies_T.h
index 9ce8614f760..4e8fa0b111e 100644
--- a/ace/Strategies_T.h
+++ b/ace/Strategies_T.h
@@ -111,13 +111,17 @@ public:
ACE_DLL_Strategy (void);
// "Do-nothing" constructor.
- ACE_DLL_Strategy (const char svc_dll_info[],
+ ACE_DLL_Strategy (const char dll_name[],
+ const char factory_function[],
+ const char svc_name[],
ACE_Service_Repository *,
ACE_Thread_Manager * = 0);
// Initialize the DLL strategy based upon the service's DLL
// information contained in the <svc_dll_info> string.
- int open (const char svc_dll_info[],
+ int open (const char dll_name[],
+ const char factory_function[],
+ const char svc_name[],
ACE_Service_Repository *,
ACE_Thread_Manager * = 0);
// Initialize the DLL strategy based upon the service's DLL
@@ -137,14 +141,14 @@ public:
protected:
typedef ACE_Creation_Strategy<SVC_HANDLER> inherited;
- char shared_library_[MAXPATHLEN];
- // Name of the shared library to dynamically link.
+ char dll_name_[MAXPATHLEN];
+ // Name of the DLL to dynamically link.
char factory_function_[MAXPATHLEN];
// Name of the factory function in the shared library to use to
// obtain a pointer to the new SVC_HANDLER.
- char svc_name[MAXNAMELEN];
+ char svc_name_[MAXNAMELEN];
// Name of the service.
ACE_Service_Repository *svc_rep_;
diff --git a/ace/Synch.cpp b/ace/Synch.cpp
index 109cb8c109e..288ad2f434e 100644
--- a/ace/Synch.cpp
+++ b/ace/Synch.cpp
@@ -692,9 +692,7 @@ int
ACE_Condition_Thread_Mutex::wait (void)
{
// ACE_TRACE ("ACE_Condition_Thread_Mutex::wait");
- ACE_thread_mutex_t &mutex = (ACE_thread_mutex_t &) this->mutex_.lock ();
-
- return ACE_OS::cond_wait (&this->cond_, &mutex);
+ return ACE_OS::cond_wait (&this->cond_, &this->mutex_.lock_);
}
int
@@ -714,10 +712,7 @@ int
ACE_Condition_Thread_Mutex::wait (const ACE_Time_Value *abstime)
{
// ACE_TRACE ("ACE_Condition_Thread_Mutex::wait");
- if (abstime == 0)
- return this->wait ();
- else
- return this->wait (this->mutex_, abstime);
+ return this->wait (this->mutex_, abstime);
}
int
diff --git a/ace/Synch_T.cpp b/ace/Synch_T.cpp
index b0b25535a0d..4e83e43b14a 100644
--- a/ace/Synch_T.cpp
+++ b/ace/Synch_T.cpp
@@ -285,7 +285,7 @@ ACE_TSS<TYPE>::ACE_TSS (TYPE *ts_obj)
// Encapsulate a ts_obj and it's destructor in an ACE_TSS_Adapter
ACE_TSS_Adapter *tss_adapter;
ACE_NEW (tss_adapter,
- ACE_TSS_Adapter ((void *)ts_obj, ACE_TSS<TYPE>::cleanup));
+ ACE_TSS_Adapter ((void *) ts_obj, ACE_TSS<TYPE>::cleanup));
// Put the adapter in thread specific storage
if (ACE_Thread::setspecific (this->key_, (void *) tss_adapter) != 0)
diff --git a/ace/Synch_T.h b/ace/Synch_T.h
index dbe691611ad..f7f751504ef 100644
--- a/ace/Synch_T.h
+++ b/ace/Synch_T.h
@@ -211,10 +211,11 @@ public:
ACE_TSS (TYPE *ts_obj = 0);
// If caller has passed us a non-NULL ts_obj *, then we'll just use
- // this to initialize the thread-specific value. Thus, subsequent
- // calls to operator->() will return this value. This is useful
- // since it enables us to assign objects to thread-specific data
- // that have arbitrarily complex constructors!
+ // this to initialize the thread-specific value (but only for the
+ // calling thread). Thus, subsequent calls to operator->() in this
+ // thread will return this value. This is useful since it enables
+ // us to assign objects to thread-specific data that have
+ // arbitrarily complex constructors.
virtual ~ACE_TSS (void);
// Deregister with thread-key administration.
diff --git a/ace/Task.cpp b/ace/Task.cpp
index 5ecd6db209b..ed2bb3cb220 100644
--- a/ace/Task.cpp
+++ b/ace/Task.cpp
@@ -18,7 +18,6 @@
#endif /* ACE_HAS_THREADS && ACE_HAS_THREAD_SPECIFIC_STORAGE */
#endif /* ACE_HAS_EXPLICT_TEMPLATE_INSTANTIATION */
-
#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
// Lock the creation of the Singleton.
ACE_Thread_Mutex ACE_Task_Exit::ace_task_lock_;
@@ -105,8 +104,11 @@ ACE_Task_Exit::set_task (ACE_Task_Base *t)
ACE_TRACE ("ACE_Task_Exit::set_task");
this->t_ = t;
- if (t != 0)
- this->tc_.insert (t->thr_mgr ());
+ // @@ Can we remove this and the entire ACE_Thread_Control stuff now
+ // that we've moved it into the ACE_Thread_Manager::spawn() method?
+
+ // if (t != 0)
+ // this->tc_.insert (t->thr_mgr ());
}
// Set the thread exit status value.
@@ -276,11 +278,10 @@ ACE_Task_Base::svc_run (void *args)
ACE_Task_Base *t = (ACE_Task_Base *) args;
-// NOTE: this preprocessor directive should match the one in
-// above ACE_Task_Exit::instance ().
-// With the Xavier Pthreads package, the exit_hook in TSS causes
-// a seg fault. So, this works around that by creating exit_hook
-// on the stack.
+// NOTE: this preprocessor directive should match the one in above
+// ACE_Task_Exit::instance (). With the Xavier Pthreads package, the
+// exit_hook in TSS causes a seg fault. So, this works around that by
+// creating exit_hook on the stack.
#if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) && ! defined (ACE_HAS_PTHREAD_SIGMASK) && !defined (ACE_HAS_FSU_PTHEADS)
// Obtain our thread-specific exit hook and make sure that it knows
// how to clean us up! Note that we never use this pointer directly
@@ -288,12 +289,12 @@ ACE_Task_Base::svc_run (void *args)
// dereference it here and only store it as a reference.
ACE_Task_Exit &exit_hook = *ACE_Task_Exit::instance ();
#else
- // Without TSS, create an ACE_Task_Exit instance. When this
+ // Without TSS, create an <ACE_Task_Exit> instance. When this
// function returns, its destructor will be called because the
// object goes out of scope. The drawback with this appraoch is
- // that the destructor _won't_ get called if thr_exit () is called.
- // So, threads shouldn't exit that way. Instead, they should
- // return from svc ().
+ // that the destructor _won't_ get called if <thr_exit> is called.
+ // So, threads shouldn't exit that way. Instead, they should return
+ // from <svc>.
ACE_Task_Exit exit_hook;
#endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE && ! ACE_HAS_PTHREAD_SIGMASK && !ACE_HAS_FSU_PTHREADS */
diff --git a/ace/Task.h b/ace/Task.h
index 9baf34000ca..3ccd1baf287 100644
--- a/ace/Task.h
+++ b/ace/Task.h
@@ -62,7 +62,7 @@ public:
// information into <open>.
virtual int close (u_long flags = 0);
- // Hook called from ACE_Task_Exit when during thread exit and from
+ // Hook called from <ACE_Task_Exit> when during thread exit and from
// the default implemenation of <module_closed>. In general, this
// method shouldn't be called directly by an application,
// particularly if the <Task> is running as an Active Object.
@@ -75,7 +75,7 @@ public:
// implementation calls forwards the call to close(1). Please
// notice the changed value of the default argument of close().
// This allows tasks to differ between the call has been originated
- // from ACE_Task_Exit or from module_closed(). Be aware that
+ // from <ACE_Task_Exit> or from <module_closed>. Be aware that
// close(0) will be also called when a thread associated with the
// ACE_Task instance exits.
@@ -192,7 +192,7 @@ public:
class ACE_Export ACE_Task_Exit
// = TITLE
// Keep exit information for a Task in thread specific storage so
- // that the Task::close() method will get called no matter how
+ // that the <Task::close> method will get called no matter how
// the thread exits (e.g., via <Thread::exit>, C++ or Win32
// exception, "falling off the end" of <Task::svc_run>, etc.).
//
@@ -234,10 +234,6 @@ private:
void *status_;
// Exit status...
- ACE_Thread_Control tc_;
- // This is used to make sure that an ACE_Task registers and
- // deregisters with the ACE_Thread_Manager correctly.
-
#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
static ACE_Thread_Mutex ace_task_lock_;
// Lock the creation of the Singleton.
diff --git a/ace/Thread.cpp b/ace/Thread.cpp
index 4bacdc0c921..0248c39efc1 100644
--- a/ace/Thread.cpp
+++ b/ace/Thread.cpp
@@ -16,8 +16,9 @@ ACE_Thread::spawn_n (size_t n,
void *arg,
long flags,
long priority,
- void *stack[],
- size_t stack_size[])
+ void *stack[],
+ size_t stack_size[],
+ ACE_Thread_Adapter *thread_adapter)
{
ACE_TRACE ("ACE_Thread::spawn_n");
ACE_thread_t t_id;
@@ -25,9 +26,15 @@ ACE_Thread::spawn_n (size_t n,
for (i = 0; i < n; i++)
// Bail out if error occurs.
- if (ACE_OS::thr_create (func, arg, flags, &t_id, 0, priority,
+ if (ACE_OS::thr_create (func,
+ arg,
+ flags,
+ &t_id,
+ 0,
+ priority,
stack == 0 ? 0 : stack[i],
- stack_size == 0 ? 0 : stack_size[i]) != 0)
+ stack_size == 0 ? 0 : stack_size[i],
+ thread_adapter) != 0)
break;
return i;
@@ -42,7 +49,8 @@ ACE_Thread::spawn_n (ACE_thread_t thread_ids[],
long priority,
void *stack[],
size_t stack_size[],
- ACE_hthread_t thread_handles[])
+ ACE_hthread_t thread_handles[],
+ ACE_Thread_Adapter *thread_adapter)
{
ACE_TRACE ("ACE_Thread::spawn_n");
size_t i;
@@ -52,12 +60,16 @@ ACE_Thread::spawn_n (ACE_thread_t thread_ids[],
ACE_thread_t t_id;
ACE_hthread_t t_handle;
- int result = ACE_OS::thr_create
- (func, arg, flags,
- &t_id, &t_handle,
- priority,
- stack == 0 ? 0 : stack[i],
- stack_size == 0 ? 0 : stack_size[i]);
+ int result =
+ ACE_OS::thr_create (func,
+ arg,
+ flags,
+ &t_id,
+ &t_handle,
+ priority,
+ stack == 0 ? 0 : stack[i],
+ stack_size == 0 ? 0 : stack_size[i],
+ thread_adapter);
if (result == 0)
{
diff --git a/ace/Thread.h b/ace/Thread.h
index a80396b0120..ab3cfdb6bf0 100644
--- a/ace/Thread.h
+++ b/ace/Thread.h
@@ -36,13 +36,16 @@ public:
ACE_hthread_t *t_handle = 0,
long priority = ACE_DEFAULT_THREAD_PRIORITY,
void *stack = 0,
- size_t stack_size = 0);
- // Spawn a new thread having <{flags}> attributes and running
- // <{func}> with arguments <{args}>. <{thr_id}> and <{t_handle}>
- // are set to the thread's ID and handle (?), respectively. The
- // thread runs at <{priority}> priority (see below).
+ size_t stack_size = 0,
+ ACE_Thread_Adapter *thread_adapter = 0);
+ // Creates a new thread having <flags> attributes and running <func>
+ // with <args> (if <thread_adapter> is non-0 then <func> and <args>
+ // are ignored and are obtained from <thread_adapter>). <thr_id>
+ // and <t_handle> are set to the thread's ID and handle (?),
+ // respectively. The thread runs at <priority> priority (see
+ // below).
//
- // The <{flags}> are a bitwise-OR of the following:
+ // The <flags> are a bitwise-OR of the following:
// = BEGIN<INDENT>
// THR_CANCEL_DISABLE, THR_CANCEL_ENABLE, THR_CANCEL_DEFERRED,
// THR_CANCEL_ASYNCHRONOUS, THR_BOUND, THR_NEW_LWP, THR_DETACHED,
@@ -50,15 +53,18 @@ public:
// THR_SCHED_RR, THR_SCHED_DEFAULT
// = END<INDENT>
//
- // By default, or if <{priority}> is set to ACE_DEFAULT_THREAD_PRIORITY,
- // an "appropriate"
- // priority value for the given scheduling policy (specified in
- // <{flags}>, e.g., <THR_SCHED_DEFAULT>) is used. This value is
- // calculated dynamically, and is the median value between the
- // minimum and maximum priority values for the given policy. If an
- // explicit value is given, it is used. Note that actual priority
- // values are EXTREMEMLY implementation-dependent, and are probably
- // best avoided.
+ // By default, or if <priority> is set to
+ // ACE_DEFAULT_THREAD_PRIORITY, an "appropriate" priority value for
+ // the given scheduling policy (specified in <flags}>, e.g.,
+ // <THR_SCHED_DEFAULT>) is used. This value is calculated
+ // dynamically, and is the median value between the minimum and
+ // maximum priority values for the given policy. If an explicit
+ // value is given, it is used. Note that actual priority values are
+ // EXTREMEMLY implementation-dependent, and are probably best
+ // avoided.
+ //
+ // Note that <thread_adapter> is always deleted by <thr_create>,
+ // therefore it must be allocated with global operator new.
static int spawn_n (size_t n,
ACE_THR_FUNC func,
@@ -66,15 +72,18 @@ public:
long flags = THR_NEW_LWP,
long priority = ACE_DEFAULT_THREAD_PRIORITY,
void *stack[] = 0,
- size_t stack_size[] = 0);
- // Spawn N new threads, which execute <func> with argument <arg>.
- // If <stack> != 0 it is assumed to be an array of <n> pointers to
- // the base of the stacks to use for the threads being spawned.
- // Likewise, if <stack_size> != 0 it is assumed to be an array of
- // <n> values indicating how big each of the corresponding <stack>s
- // are. Returns the number of threads actually spawned (if this
- // doesn't equal the number requested then something has gone wrong
- // and <errno> will explain...).
+ size_t stack_size[] = 0,
+ ACE_Thread_Adapter *thread_adapter = 0);
+ // Spawn N new threads, which execute <func> with argument <arg> (if
+ // <thread_adapter> is non-0 then <func> and <args> are ignored and
+ // are obtained from <thread_adapter>). If <stack> != 0 it is
+ // assumed to be an array of <n> pointers to the base of the stacks
+ // to use for the threads being spawned. Likewise, if <stack_size>
+ // != 0 it is assumed to be an array of <n> values indicating how
+ // big each of the corresponding <stack>s are. Returns the number
+ // of threads actually spawned (if this doesn't equal the number
+ // requested then something has gone wrong and <errno> will
+ // explain...).
//
// See also <spawn>.
@@ -86,19 +95,22 @@ public:
long priority = ACE_DEFAULT_THREAD_PRIORITY,
void *stack[] = 0,
size_t stack_size[] = 0,
- ACE_hthread_t thread_handles[] = 0);
- // Spawn <n> new threads, which execute <func> with argument <arg>.
- // The thread_ids of successfully spawned threads will be placed
- // into the <thread_ids> buffer (which must be the same size as
- // <n>). If <stack> != 0 it is assumed to be an array of <n>
- // pointers to the base of the stacks to use for the threads being
- // spawned. If <stack_size> != 0 it is assumed to be an array of
- // <n> values indicating how big each of the corresponding <stack>s
- // are. If <thread_handles> != 0 it is assumed to be an array of
- // <n> thread_handles that will be assigned the values of the thread
- // handles being spawned. Returns the number of threads actually
- // spawned (if this doesn't equal the number requested then
- // something has gone wrong and <errno> will explain...).
+ ACE_hthread_t thread_handles[] = 0,
+ ACE_Thread_Adapter *thread_adapter = 0);
+ // Spawn <n> new threads, which execute <func> with argument <arg>
+ // (if <thread_adapter> is non-0 then <func> and <args> are ignored
+ // and are obtained from <thread_adapter>). The thread_ids of
+ // successfully spawned threads will be placed into the <thread_ids>
+ // buffer (which must be the same size as <n>). If <stack> != 0 it
+ // is assumed to be an array of <n> pointers to the base of the
+ // stacks to use for the threads being spawned. If <stack_size> !=
+ // 0 it is assumed to be an array of <n> values indicating how big
+ // each of the corresponding <stack>s are. If <thread_handles> != 0
+ // it is assumed to be an array of <n> thread_handles that will be
+ // assigned the values of the thread handles being spawned. Returns
+ // the number of threads actually spawned (if this doesn't equal the
+ // number requested then something has gone wrong and <errno> will
+ // explain...).
//
// See also <spawn>.
diff --git a/ace/Thread.i b/ace/Thread.i
index 3b22a327be8..e720946c39b 100644
--- a/ace/Thread.i
+++ b/ace/Thread.i
@@ -78,11 +78,19 @@ ACE_Thread::spawn (ACE_THR_FUNC func,
ACE_hthread_t *t_handle,
long priority,
void *stack,
- size_t stack_size)
+ size_t stack_size,
+ ACE_Thread_Adapter *thread_adapter)
{
ACE_TRACE ("ACE_Thread::spawn");
- return ACE_OS::thr_create (func, arg, flags, t_id, t_handle,
- priority, stack, stack_size);
+ return ACE_OS::thr_create (func,
+ arg,
+ flags,
+ t_id,
+ t_handle,
+ priority,
+ stack,
+ stack_size,
+ thread_adapter);
}
ACE_INLINE int
diff --git a/ace/Thread_Manager.cpp b/ace/Thread_Manager.cpp
index 1690b70a89b..d0cf3db4b6c 100644
--- a/ace/Thread_Manager.cpp
+++ b/ace/Thread_Manager.cpp
@@ -239,6 +239,21 @@ ACE_Thread_Manager::~ACE_Thread_Manager (void)
this->close ();
}
+// Run the thread entry point for the <ACE_Thread_Adapter>. This must
+// be an extern "C" to make certain compilers happy...
+
+extern "C" void *
+ace_thread_manager_adapter (void *args)
+{
+ ACE_Thread_Adapter *thread_args = (ACE_Thread_Adapter *) args;
+
+ // This really needs to go into TSS!
+ ACE_Thread_Control tc (thread_args->thr_mgr ());
+
+ // Invoke the user-supplied function with the args.
+ return thread_args->invoke ();
+}
+
// Call the appropriate OS routine to spawn a thread. Should *not* be
// called with the lock_ held...
@@ -254,6 +269,11 @@ ACE_Thread_Manager::spawn_i (ACE_THR_FUNC func,
size_t stack_size,
ACE_Task_Base *task)
{
+ ACE_Thread_Adapter *thread_args = 0;
+#if !defined (ACE_NO_THREAD_ADAPTER)
+ ACE_NEW_RETURN (thread_args, ACE_Thread_Adapter (func, args, ace_thread_manager_adapter), -1);
+#endif /* ACE_NO_THREAD_ADAPTER */
+
ACE_TRACE ("ACE_Thread_Manager::spawn_i");
ACE_thread_t thr_id;
ACE_hthread_t thr_handle;
@@ -264,9 +284,15 @@ ACE_Thread_Manager::spawn_i (ACE_THR_FUNC func,
if (t_handle == 0)
t_handle = &thr_handle;
- int result = ACE_Thread::spawn (func, args, flags,
- t_id, t_handle, priority,
- stack, stack_size);
+ int result = ACE_Thread::spawn (func,
+ args,
+ flags,
+ t_id,
+ t_handle,
+ priority,
+ stack,
+ stack_size,
+ thread_adapter);
if (result != 0)
{
// _Don't_ clobber errno here! result is either 0 or -1, and
diff --git a/ace/Thread_Manager.h b/ace/Thread_Manager.h
index ae7670c91b5..d28076b8275 100644
--- a/ace/Thread_Manager.h
+++ b/ace/Thread_Manager.h
@@ -389,11 +389,21 @@ private:
// Must delete the <thr_mgr_> if non-0.
};
-
class ACE_Export ACE_Thread_Control
// = TITLE
// Used to keep track of a thread's activities within its entry
// point function.
+ //
+ // = DESCRIPTION
+ // A <ACE_Thread_Manager> uses this class to ensure that threads
+ // it spawns automatically register and unregister themselves
+ // with it.
+ //
+ // This class can be stored in thread-specific storage using the
+ // <ACE_TSS> wrapper. When a thread exits the
+ // <ACE_TSS::cleanup> function deletes this object, thereby
+ // ensuring that it gets removed from its associated
+ // <ACE_Thread_Manager>.
{
public:
ACE_Thread_Control (ACE_Thread_Manager *tm = 0,
@@ -438,6 +448,11 @@ private:
void *status_;
// Keeps track of the exit status for the thread.
+
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+ static ACE_Thread_Mutex ace_thread_lock_;
+ // Lock the creation of the Singleton.
+#endif /* defined (ACE_MT_SAFE) */
};
#if defined (__ACE_INLINE__)
diff --git a/ace/Timer_Hash_T.cpp b/ace/Timer_Hash_T.cpp
index 48cdefbae71..326d30bded1 100644
--- a/ace/Timer_Hash_T.cpp
+++ b/ace/Timer_Hash_T.cpp
@@ -23,7 +23,7 @@ struct Hash_Token
template <class TYPE, class FUNCTOR, class LOCK>
ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, LOCK>::ACE_Timer_Hash_Upcall (void)
- : timer_hash_ (NULL)
+ : timer_hash_ (0)
{
// Nothing
}
@@ -41,8 +41,8 @@ ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, LOCK>::ACE_Timer_Hash_Upcall (ACE_Timer_Que
template <class TYPE, class FUNCTOR, class LOCK> int
ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, LOCK>::timeout (ACE_Timer_Queue_T<ACE_Event_Handler *,
- ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, LOCK>,
- ACE_Null_Mutex> &timer_queue,
+ ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, LOCK>,
+ ACE_Null_Mutex> &timer_queue,
ACE_Event_Handler *handler,
const void *arg,
const ACE_Time_Value &cur_time)
@@ -98,13 +98,12 @@ ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, LOCK>::deletion (ACE_Timer_Queue_T<ACE_Even
template <class TYPE, class FUNCTOR, class LOCK, class BUCKET>
ACE_Timer_Hash_Iterator_T<TYPE, FUNCTOR, LOCK, BUCKET>::ACE_Timer_Hash_Iterator_T (ACE_Timer_Hash_T<TYPE, FUNCTOR, LOCK, BUCKET> &hash)
- timer_hash_(hash);
+ : timer_hash_ (hash)
{
this->first();
// Nothing
}
-
// Positions the iterator at the first node in the timing hash table
template <class TYPE, class FUNCTOR, class LOCK, class BUCKET> void
@@ -124,7 +123,7 @@ ACE_Timer_Hash_Iterator_T<TYPE, FUNCTOR, LOCK, BUCKET>::first (void)
}
// Didn't find any
- this->iter_ = NULL;
+ this->iter_ = 0;
}
@@ -152,7 +151,7 @@ ACE_Timer_Hash_Iterator_T<TYPE, FUNCTOR, LOCK, BUCKET>::next (void)
}
// Didn't find any
- this->iter_ = NULL;
+ this->iter_ = 0;
}
else
this->iter_->next ();
@@ -164,7 +163,7 @@ ACE_Timer_Hash_Iterator_T<TYPE, FUNCTOR, LOCK, BUCKET>::next (void)
template <class TYPE, class FUNCTOR, class LOCK, class BUCKET> int
ACE_Timer_Hash_Iterator_T<TYPE, FUNCTOR, LOCK, BUCKET>::isdone (void)
{
- return this->iter_ == NULL;
+ return this->iter_ == 0;
}
@@ -174,7 +173,7 @@ template <class TYPE, class FUNCTOR, class LOCK, class BUCKET> ACE_Timer_Node_T<
ACE_Timer_Hash_Iterator_T<TYPE, FUNCTOR, LOCK, BUCKET>::item (void)
{
if (this->isdone ())
- return NULL;
+ return 0;
return this->iter_->item ();
}
@@ -414,7 +413,7 @@ template <class TYPE, class FUNCTOR, class LOCK, class BUCKET> ACE_Timer_Node_T<
ACE_Timer_Hash_T<TYPE, FUNCTOR, LOCK, BUCKET>::remove_first (void)
{
if (this->is_empty ())
- return NULL;
+ return 0;
ACE_Timer_Node_T<TYPE> *temp = this->table_[this->earliest_position_]->remove_first ();
diff --git a/ace/config-sco-5.0.0-fsu-pthread.h b/ace/config-sco-5.0.0-fsu-pthread.h
index ba3cfb22052..821bb9adb2f 100644
--- a/ace/config-sco-5.0.0-fsu-pthread.h
+++ b/ace/config-sco-5.0.0-fsu-pthread.h
@@ -17,7 +17,7 @@
#endif /* SCO */
#define ACE_HAS_SIG_MACROS
-
+#define ACE_LACKS_CONST_TIMESPEC_PTR
#define ACE_TEMPLATES_REQUIRE_SOURCE
#define ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION
#define ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES