summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Cleeland <chris.cleeland@gmail.com>2006-11-08 19:17:49 +0000
committerChris Cleeland <chris.cleeland@gmail.com>2006-11-08 19:17:49 +0000
commitd9ca80311fa2b9595ae36eaadb9a8e816706f148 (patch)
tree6ff62ad738fced33a8eddaf2a95973ca3a9470cc
parent9ef3b09874c19f5586f2fe04d9a69ee816be0ecc (diff)
downloadATCD-d9ca80311fa2b9595ae36eaadb9a8e816706f148.tar.gz
Committing changes for OCI RT 8089: changes to permit specifying thread
creation flags for thread-per-consumer (TPC) dispatch strategy in the RTEC.
-rw-r--r--TAO/ChangeLog.rt808968
-rw-r--r--TAO/docs/ec_options.html31
-rw-r--r--TAO/orbsvcs/orbsvcs/Event/EC_Default_Factory.cpp38
-rw-r--r--TAO/orbsvcs/orbsvcs/Event/EC_Default_Factory.h13
-rw-r--r--TAO/orbsvcs/orbsvcs/Event/EC_Factory.cpp7
-rw-r--r--TAO/orbsvcs/orbsvcs/Event/EC_Factory.h3
-rw-r--r--TAO/orbsvcs/orbsvcs/Event/EC_TPC_Dispatching.cpp26
-rw-r--r--TAO/orbsvcs/orbsvcs/Event/EC_TPC_Dispatching.h20
-rw-r--r--TAO/orbsvcs/orbsvcs/Event/EC_TPC_Factory.cpp20
-rw-r--r--TAO/orbsvcs/orbsvcs/Event/EC_TPC_Factory.h4
-rw-r--r--TAO/orbsvcs/orbsvcs/Event/EC_TPC_ProxyConsumer.cpp4
-rw-r--r--TAO/orbsvcs/orbsvcs/Event/EC_TPC_ProxySupplier.cpp8
-rw-r--r--TAO/orbsvcs/orbsvcs/Event/EC_TPC_ProxySupplier.inl4
-rw-r--r--TAO/orbsvcs/orbsvcs/Event/EC_Thread_Flags.cpp235
-rw-r--r--TAO/orbsvcs/orbsvcs/Event/EC_Thread_Flags.h148
-rw-r--r--TAO/orbsvcs/orbsvcs/RTEvent_Serv.mpc1
-rw-r--r--TAO/orbsvcs/tests/Event/ThreadFlags/testflags.cpp225
-rw-r--r--TAO/orbsvcs/tests/Event/ThreadFlags/tftest.mpc5
18 files changed, 816 insertions, 44 deletions
diff --git a/TAO/ChangeLog.rt8089 b/TAO/ChangeLog.rt8089
new file mode 100644
index 00000000000..1dd68d97ff6
--- /dev/null
+++ b/TAO/ChangeLog.rt8089
@@ -0,0 +1,68 @@
+Wed Nov 8 18:42:03 UTC 2006 Chris Cleeland <cleeland_c@ociweb.com>
+
+ * docs/ec_options.html: Add documentation for TPC and
+ -ECDispatchingThreadFlags options.
+
+ * orbsvcs/orbsvcs/Event/EC_Default_Factory.h:
+ * orbsvcs/orbsvcs/Event/EC_Default_Factory.cpp:
+
+ Added new option, -ECDispatchingThreadsFlags, that allows the
+ user to pass in a list of thread creation flags and priority for
+ dispatching threads. These can be used for either the MT
+ dispatching strategy or the TPC dispatching strategy.
+
+ Also added -ECDebug option to enable debugging output from the
+ RTEC. Only the option and variable was added, but no messages.
+ Therefore, at the moment, this does not generate much output.
+
+ * orbsvcs/orbsvcs/Event/EC_Factory.h:
+ * orbsvcs/orbsvcs/Event/EC_Factory.cpp:
+
+ Added support for RTEC's debug level.
+
+ * orbsvcs/orbsvcs/Event/EC_TPC_Dispatching.h:
+ * orbsvcs/orbsvcs/Event/EC_TPC_Dispatching.cpp:
+
+ (CTOR) Changed so that thread flags can be passed in just like
+ with the MT dispatching strategy.
+
+ (add_consumer) Modified so that it passes the thread flags set
+ in the CTOR to the dispatching task's activate call.
+
+ * orbsvcs/orbsvcs/Event/EC_TPC_Factory.cpp (create_dispatching):
+
+ Update to reflect new CTOR args for EC_TPC_Dispatching.
+
+ * orbsvcs/orbsvcs/Event/EC_TPC_Factory.h:
+ * orbsvcs/orbsvcs/Event/EC_TPC_Factory.cpp:
+ * orbsvcs/orbsvcs/Event/EC_TPC_ProxyConsumer.cpp:
+ * orbsvcs/orbsvcs/Event/EC_TPC_ProxySupplier.inl:
+ * orbsvcs/orbsvcs/Event/EC_TPC_ProxySupplier.cpp:
+
+ Change references to EC_TPC_debug_level to
+ TAO_EC_TPC_debug_level for proper scoping.
+
+ * orbsvcs/orbsvcs/Event/EC_Thread_Flags.h:
+ * orbsvcs/orbsvcs/Event/EC_Thread_Flags.cpp:
+
+ Added new abstraction around thread flags. This also handles
+ parsing of text representation of THR_* options. Ideally this
+ is part of ACE, but such a low-level change is difficult to push
+ through in general, much less in a patch.
+
+ * orbsvcs/orbsvcs/RTEvent_Serv.mpc:
+
+ Updated with new files.
+
+ * orbsvcs/tests/Event/ThreadFlags/testflags.cpp:
+ * orbsvcs/tests/Event/ThreadFlags/tftest.mpc:
+
+ Added unit test for TAO_EC_Thread_Flags abstraction.
+ Unfortunately, due to the way that some of the thread flags
+ are encoded on some platforms, e.g., Linux, the test can
+ give false failing indications. I've left this as-is for
+ now because I haven't decided if this is a flaw in the test,
+ a flaw in the TAO_EC_Thread_Flags abstraction, or a flaw in
+ the way ACE assigns values when a THR_ symbol is not provided
+ by the platform itself.
+
diff --git a/TAO/docs/ec_options.html b/TAO/docs/ec_options.html
index 382ea349b64..efceece9965 100644
--- a/TAO/docs/ec_options.html
+++ b/TAO/docs/ec_options.html
@@ -97,11 +97,9 @@ struct RtecEventData
<code>$TAO_ROOT/orbsvcs/orbsvcs/Event/EC_Null_Factory.h</code>
and <code>$TAO_ROOT/orbsvcs/orbsvcs/Event/EC_Basic_Factory.h</code>
for details.
-</ul>
- The
- table below describes all of the options (and values) supported by
- these factories.
+ </ul>
</P>
+
<h3>Special Topic: Queue Configuration</h3>
<p>
In certain configurations such as <em>mt</em> and <em>tpc</em>,
@@ -165,6 +163,10 @@ static EC_QueueFullSimpleActions "[wait | discard]"
# (see below) to specify that object's service configurator tag.
</PRE>
+ <p>
+ The
+ table below describes all of the options (and values) supported by
+ these factories.
<P>All the event service factory options start with
<CODE>-EC</CODE></P>
@@ -206,6 +208,27 @@ static EC_QueueFullSimpleActions "[wait | discard]"
<b>Does not apply to the <em>tpc</em> factory.</b>
</TD>
</TR>
+ <!-- <TR NAME="ECDispatchingThreadFlags"> -->
+ <TR>
+ <td><code>-ECDispatchingThreadFlags</code>
+ <em>thread_flags</em><b>:</b><em>thread_priority</em>
+ </td>
+ <td>
+ Provide flags and priority used for creation of
+ dispatching threads.<br>
+ <em>thread_flags</em> is a set of
+ <code>THR_</code> flags separated by the vertical bar
+ ('|'), e.g.,
+ <code>THR_BOUND|THR_NEW_LWP|THR_SCOPE_SYSTEM</code>.
+ <br>
+ <em>thread_priority</em> is a numeric value indicating the
+ desired priority at which the thread should be created.
+ No range checking is performed on the value prior to
+ passing to the thread creation function. Also note that
+ priorities are platform-specific, so a valid value for a
+ given set of flags on one platform may not work with the
+ same flags on another platform.
+ </tr>
<!-- <TR NAME="ECQueueFullServiceObject"> -->
<tr>
diff --git a/TAO/orbsvcs/orbsvcs/Event/EC_Default_Factory.cpp b/TAO/orbsvcs/orbsvcs/Event/EC_Default_Factory.cpp
index 3579aaec4f7..ad228dbf538 100644
--- a/TAO/orbsvcs/orbsvcs/Event/EC_Default_Factory.cpp
+++ b/TAO/orbsvcs/orbsvcs/Event/EC_Default_Factory.cpp
@@ -18,6 +18,7 @@
#include "orbsvcs/Event/EC_Event_Channel_Base.h"
#include "orbsvcs/Event/EC_Reactive_ConsumerControl.h"
#include "orbsvcs/Event/EC_Reactive_SupplierControl.h"
+#include "orbsvcs/Event/EC_Thread_Flags.h"
#include "orbsvcs/ESF/ESF_Proxy_List.h"
#include "orbsvcs/ESF/ESF_Proxy_RB_Tree.h"
@@ -97,6 +98,39 @@ TAO_EC_Default_Factory::init (int argc, ACE_TCHAR* argv[])
arg_shifter.consume_arg ();
}
}
+ else if (ACE_OS::strcasecmp (arg, ACE_TEXT("-ECDispatchingThreadFlags")) == 0)
+ {
+ arg_shifter.consume_arg ();
+
+ // Need to be in the form of <flags>:<priority>
+ if (arg_shifter.is_parameter_next ())
+ {
+ const ACE_TCHAR* s = arg_shifter.get_current ();
+ // need to parse the flags...ugh
+ ACE_TCHAR* opt = ACE_OS::strdup (s);
+
+ ACE_TCHAR* aux;
+ ACE_TCHAR* flags = ACE_OS::strtok_r (opt, ACE_TEXT_CHAR_TO_TCHAR(":"), &aux);
+
+ TAO_EC_Thread_Flags tf(ACE_TEXT_ALWAYS_CHAR (flags)); // parse and set up
+ this->dispatching_threads_flags_ = tf.flags ();
+
+ ACE_TCHAR* arg = ACE_OS::strtok_r (0, ACE_TEXT_CHAR_TO_TCHAR(":"), &aux);
+ if (arg)
+ {
+ long prio = ACE_OS::strtol (arg, 0, 0);
+
+ this->dispatching_threads_priority_ = prio;
+ }
+ else
+ {
+ // Should we set the default priority?
+ this->dispatching_threads_priority_ = tf.default_priority ();
+ }
+ ACE_OS::free (opt);
+ arg_shifter.consume_arg ();
+ }
+ }
else if (ACE_OS::strcasecmp (arg, ACE_TEXT("-ECDispatchingThreads")) == 0)
{
@@ -508,7 +542,7 @@ TAO_EC_Default_Factory::find_service_object (const char* wanted,
return so;
ACE_ERROR ((LM_ERROR,
- "EC (%P|%t) EC_Default_Factory::create_dispatching "
+ "EC (%P|%t) EC_Default_Factory::find_service_object "
"unable to find queue full service object '%s'; "
"using '%s' instead\n",
wanted,
@@ -519,7 +553,7 @@ TAO_EC_Default_Factory::find_service_object (const char* wanted,
return so;
ACE_ERROR ((LM_ERROR,
- "EC (%P|%t) EC_Default_Factory::create_dispatching "
+ "EC (%P|%t) EC_Default_Factory::find_service_object "
"unable find default queue full service object '%s'; "
"aborting.\n",
fallback));
diff --git a/TAO/orbsvcs/orbsvcs/Event/EC_Default_Factory.h b/TAO/orbsvcs/orbsvcs/Event/EC_Default_Factory.h
index 291954518b3..7828d1c65a0 100644
--- a/TAO/orbsvcs/orbsvcs/Event/EC_Default_Factory.h
+++ b/TAO/orbsvcs/orbsvcs/Event/EC_Default_Factory.h
@@ -156,13 +156,12 @@ protected:
int consumer_lock_;
int supplier_lock_;
- /// The MT dispatching priority has several arguments that could be
- /// controlled here...
- int dispatching_threads_;
- int dispatching_threads_flags_;
- int dispatching_threads_priority_;
- int dispatching_threads_force_active_;
- ACE_CString queue_full_service_object_name_;
+ /// Flags used by thread-based dispatching strategies.
+ int dispatching_threads_; //! number of threads; may be ignored depending on strategy; default: TAO_EC_DEFAULT_DISPATCHING_THREADS
+ int dispatching_threads_flags_; //! flags for thread creation; default: TAO_EC_DEFAULT_DISPATCHING_THREADS_FLAGS
+ int dispatching_threads_priority_; //! dispatching thread priority; default: TAO_EC_DEFAULT_DISPATCHING_THREADS_PRIORITY
+ int dispatching_threads_force_active_; //! create threads with innocuous default values if creation with requested values fails
+ ACE_CString queue_full_service_object_name_; //! name of ACE_Service_Object which should be invoked when output queue becomes full
TAO_EC_Queue_Full_Service_Object* find_service_object (const char* wanted,
const char* fallback);
diff --git a/TAO/orbsvcs/orbsvcs/Event/EC_Factory.cpp b/TAO/orbsvcs/orbsvcs/Event/EC_Factory.cpp
index 0612521f408..4b638b69a22 100644
--- a/TAO/orbsvcs/orbsvcs/Event/EC_Factory.cpp
+++ b/TAO/orbsvcs/orbsvcs/Event/EC_Factory.cpp
@@ -5,7 +5,12 @@
ACE_RCSID(Event, EC_Factory, "$Id$")
-TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+TAO_RTEvent_Serv_Export unsigned short TAO_EC_debug_level;
+
+TAO_EC_Factory::TAO_EC_Factory (void)
+{
+ TAO_EC_debug_level = 0;
+}
TAO_EC_Factory::~TAO_EC_Factory (void)
{
diff --git a/TAO/orbsvcs/orbsvcs/Event/EC_Factory.h b/TAO/orbsvcs/orbsvcs/Event/EC_Factory.h
index a3cd903d4f4..7f4070e8d5d 100644
--- a/TAO/orbsvcs/orbsvcs/Event/EC_Factory.h
+++ b/TAO/orbsvcs/orbsvcs/Event/EC_Factory.h
@@ -69,6 +69,7 @@ class TAO_RTEvent_Serv_Export TAO_EC_Factory : public ACE_Service_Object
{
public:
/// destructor...
+ TAO_EC_Factory (void);
virtual ~TAO_EC_Factory (void);
/// Create and destroy the dispatching module.
@@ -162,6 +163,8 @@ public:
destroy_supplier_control (TAO_EC_SupplierControl*) = 0;
};
+TAO_RTEvent_Serv_Export extern unsigned short TAO_EC_debug_level;
+
TAO_END_VERSIONED_NAMESPACE_DECL
#include /**/ "ace/post.h"
diff --git a/TAO/orbsvcs/orbsvcs/Event/EC_TPC_Dispatching.cpp b/TAO/orbsvcs/orbsvcs/Event/EC_TPC_Dispatching.cpp
index 1b06a04dca7..d7351c9802f 100644
--- a/TAO/orbsvcs/orbsvcs/Event/EC_TPC_Dispatching.cpp
+++ b/TAO/orbsvcs/orbsvcs/Event/EC_TPC_Dispatching.cpp
@@ -1,5 +1,7 @@
// $Id$
+extern unsigned long TAO_EC_TPC_debug_level;
+
#include "orbsvcs/Event/EC_TPC_Dispatching.h"
#include "orbsvcs/Event/EC_Defaults.h"
@@ -13,10 +15,16 @@ ACE_RCSID(Event, EC_TPC_Dispatching, "$Id$")
TAO_BEGIN_VERSIONED_NAMESPACE_DECL
-extern unsigned long EC_TPC_debug_level;
-
-TAO_EC_TPC_Dispatching::TAO_EC_TPC_Dispatching (TAO_EC_Queue_Full_Service_Object* so)
- : consumer_task_map_(TAO_EC_TPC_DISPATCHING_DEFAULT_MAP_SIZE)
+TAO_EC_TPC_Dispatching::TAO_EC_TPC_Dispatching (int nthreads,
+ int thread_creation_flags,
+ int thread_priority,
+ int force_activate,
+ TAO_EC_Queue_Full_Service_Object* so)
+ : nthreads_(nthreads)
+ , thread_creation_flags_ (thread_creation_flags)
+ , thread_priority_ (thread_priority)
+ , force_activate_ (force_activate)
+ , consumer_task_map_(TAO_EC_TPC_DISPATCHING_DEFAULT_MAP_SIZE)
, queue_full_service_object_(so)
{
ACE_ASSERT (this->queue_full_service_object_ != 0);
@@ -40,20 +48,20 @@ TAO_EC_TPC_Dispatching::add_consumer (RtecEventComm::PushConsumer_ptr consumer
RtecEventComm::PushConsumer_var pc =
RtecEventComm::PushConsumer::_duplicate(consumer);
- if (EC_TPC_debug_level > 0)
+ if (TAO_EC_TPC_debug_level > 0)
ACE_DEBUG ((LM_DEBUG, "EC (%P|%t) TPC_Dispatching::add_consumer(%@)\n", pc.in()));
TAO_EC_Dispatching_Task* dtask =
new TAO_EC_TPC_Dispatching_Task (&this->thread_manager_,
this->queue_full_service_object_);
- if (EC_TPC_debug_level > 0)
+ if (TAO_EC_TPC_debug_level > 0)
ACE_DEBUG ((LM_DEBUG, "EC (%P|%t) TPC_Dispatching::add_consumer(%@): new task %@\n", pc.in(), dtask));
- if ((dtask->activate (TAO_EC_DEFAULT_DISPATCHING_THREADS_FLAGS,
+ if ((dtask->activate (this->thread_creation_flags_,
1, // we only want one thread to dispatch to a consumer
1, // magic number??
- TAO_EC_DEFAULT_DISPATCHING_THREADS_PRIORITY)) == -1)
+ this->thread_priority_)) == -1)
{
ACE_DEBUG ((LM_WARNING,
"EC (%P|%t): TPC_Dispatching::add_consumer unable to activate"
@@ -176,7 +184,7 @@ TAO_EC_TPC_Dispatching::push_nocopy (TAO_EC_ProxyPushSupplier* proxy,
TAO_EC_QOS_Info&
ACE_ENV_ARG_DECL)
{
- if (EC_TPC_debug_level > 0)
+ if (TAO_EC_TPC_debug_level > 0)
ACE_DEBUG ((LM_DEBUG, "EC (%P|%t) TPC_Dispatching::push_nocopy(supplier=%@,consumer=%@)\n", proxy, consumer));
ACE_GUARD (ACE_SYNCH_MUTEX, ace_mon, this->lock_);
diff --git a/TAO/orbsvcs/orbsvcs/Event/EC_TPC_Dispatching.h b/TAO/orbsvcs/orbsvcs/Event/EC_TPC_Dispatching.h
index b8c7ea49cd3..d507f3f5c1d 100644
--- a/TAO/orbsvcs/orbsvcs/Event/EC_TPC_Dispatching.h
+++ b/TAO/orbsvcs/orbsvcs/Event/EC_TPC_Dispatching.h
@@ -39,7 +39,11 @@ class TAO_EC_Event_Channel_Base;
class TAO_RTEvent_Serv_Export TAO_EC_TPC_Dispatching : public TAO_EC_Dispatching
{
public:
- TAO_EC_TPC_Dispatching (TAO_EC_Queue_Full_Service_Object* so);
+ TAO_EC_TPC_Dispatching (int nthreads,
+ int thread_creation_flags,
+ int thread_priority,
+ int force_activate,
+ TAO_EC_Queue_Full_Service_Object* so);
~TAO_EC_TPC_Dispatching ();
// = The EC_Dispatching methods.
@@ -63,6 +67,20 @@ private:
// Use our own thread manager
ACE_Thread_Manager thread_manager_;
+ /// The number of active tasks
+ int nthreads_;
+
+ /// The flags (THR_BOUND, THR_NEW_LWP, etc.) used to create the
+ /// dispatching threads.
+ int thread_creation_flags_;
+
+ /// The priority of the dispatching threads.
+ int thread_priority_;
+
+ /// If activation at the requested priority fails then we fallback on
+ /// the defaults for thread activation.
+ int force_activate_;
+
typedef ACE_Hash_Map_Manager_Ex<RtecEventComm::PushConsumer_ptr,TAO_EC_Dispatching_Task*,ACE_Pointer_Hash<RtecEventComm::PushConsumer_ptr>,ACE_Equal_To<RtecEventComm::PushConsumer_ptr>,ACE_Null_Mutex> MAPTYPE;
// Tweak the default size of this map by #defining
diff --git a/TAO/orbsvcs/orbsvcs/Event/EC_TPC_Factory.cpp b/TAO/orbsvcs/orbsvcs/Event/EC_TPC_Factory.cpp
index c8e822ed5b9..71b304fa3a4 100644
--- a/TAO/orbsvcs/orbsvcs/Event/EC_TPC_Factory.cpp
+++ b/TAO/orbsvcs/orbsvcs/Event/EC_TPC_Factory.cpp
@@ -14,13 +14,11 @@
ACE_RCSID(Event, EC_TPC_Factory, "$Id$")
-TAO_BEGIN_VERSIONED_NAMESPACE_DECL
-
-unsigned long EC_TPC_debug_level;
+unsigned long TAO_EC_TPC_debug_level;
TAO_EC_TPC_Factory::TAO_EC_TPC_Factory (void)
{
- EC_TPC_debug_level = 0;
+ TAO_EC_TPC_debug_level = 0;
}
TAO_EC_TPC_Factory::~TAO_EC_TPC_Factory (void)
@@ -63,7 +61,7 @@ TAO_EC_TPC_Factory::init (int argc, char* argv[])
if (ACE_OS::strcasecmp (arg, "-ECTPCDebug") == 0)
{
arg_shifter.consume_arg ();
- ++EC_TPC_debug_level;
+ ++TAO_EC_TPC_debug_level;
}
else
{
@@ -80,21 +78,25 @@ TAO_EC_TPC_Factory::init (int argc, char* argv[])
TAO_EC_Dispatching*
TAO_EC_TPC_Factory::create_dispatching (TAO_EC_Event_Channel_Base *)
{
- if (EC_TPC_debug_level > 0)
+ if (TAO_EC_TPC_debug_level > 0)
ACE_DEBUG ((LM_DEBUG, "EC (%P|%t) EC_TPC_Factory::create_dispatching\n"));
TAO_EC_Queue_Full_Service_Object* so =
this->find_service_object (this->queue_full_service_object_name_.fast_rep(),
TAO_EC_DEFAULT_QUEUE_FULL_SERVICE_OBJECT_NAME);
- return new TAO_EC_TPC_Dispatching (so);
+ return new TAO_EC_TPC_Dispatching (this->dispatching_threads_,
+ this->dispatching_threads_flags_,
+ this->dispatching_threads_priority_,
+ this->dispatching_threads_force_active_,
+ so);
}
TAO_EC_ProxyPushSupplier*
TAO_EC_TPC_Factory::create_proxy_push_supplier (TAO_EC_Event_Channel_Base *ec)
{
- if (EC_TPC_debug_level > 0)
+ if (TAO_EC_TPC_debug_level > 0)
ACE_DEBUG ((LM_DEBUG, "EC (%P|%t) EC_TPC_Factory::create_proxy_push_supplier\n"));
return new TAO_EC_TPC_ProxyPushSupplier (ec, this->consumer_validate_connection_);
}
@@ -103,7 +105,7 @@ TAO_EC_TPC_Factory::create_proxy_push_supplier (TAO_EC_Event_Channel_Base *ec)
TAO_EC_ProxyPushConsumer*
TAO_EC_TPC_Factory::create_proxy_push_consumer (TAO_EC_Event_Channel_Base *ec)
{
- if (EC_TPC_debug_level > 0)
+ if (TAO_EC_TPC_debug_level > 0)
ACE_DEBUG ((LM_DEBUG, "EC (%P|%t) EC_TPC_Factory::create_proxy_push_consumer\n"));
return new TAO_EC_TPC_ProxyPushConsumer (ec);
}
diff --git a/TAO/orbsvcs/orbsvcs/Event/EC_TPC_Factory.h b/TAO/orbsvcs/orbsvcs/Event/EC_TPC_Factory.h
index c65e5be61cc..fa4a96a085a 100644
--- a/TAO/orbsvcs/orbsvcs/Event/EC_TPC_Factory.h
+++ b/TAO/orbsvcs/orbsvcs/Event/EC_TPC_Factory.h
@@ -56,9 +56,7 @@ public:
create_proxy_push_consumer (TAO_EC_Event_Channel_Base*);
};
-extern unsigned long EC_TPC_debug_level;
-
-TAO_END_VERSIONED_NAMESPACE_DECL
+extern unsigned long TAO_EC_TPC_debug_level;
ACE_STATIC_SVC_DECLARE (TAO_EC_TPC_Factory)
ACE_FACTORY_DECLARE (TAO_RTEvent_Serv, TAO_EC_TPC_Factory)
diff --git a/TAO/orbsvcs/orbsvcs/Event/EC_TPC_ProxyConsumer.cpp b/TAO/orbsvcs/orbsvcs/Event/EC_TPC_ProxyConsumer.cpp
index 6a7cc347cb1..a5b23525b1e 100644
--- a/TAO/orbsvcs/orbsvcs/Event/EC_TPC_ProxyConsumer.cpp
+++ b/TAO/orbsvcs/orbsvcs/Event/EC_TPC_ProxyConsumer.cpp
@@ -9,7 +9,7 @@ ACE_RCSID(Event, EC_TPC_ProxyConsumer, "$Id$")
TAO_BEGIN_VERSIONED_NAMESPACE_DECL
-extern unsigned long EC_TPC_debug_level;
+extern unsigned long TAO_EC_TPC_debug_level;
TAO_EC_TPC_ProxyPushConsumer::TAO_EC_TPC_ProxyPushConsumer (TAO_EC_Event_Channel_Base* ec)
: TAO_EC_Default_ProxyPushConsumer (ec)
@@ -31,7 +31,7 @@ TAO_EC_TPC_ProxyPushConsumer::~TAO_EC_TPC_ProxyPushConsumer (void)
// dispatch map in here? I'm not sure... But, if I do, then I need
// to fact that "remove" code out of just the
// disconnect_push_consumer.
- if (EC_TPC_debug_level > 0)
+ if (TAO_EC_TPC_debug_level > 0)
ACE_DEBUG ((LM_DEBUG, "RTEC (%P|%t): inside ~TAO_EC_TPC_ProxyPushConsumer (%x)\n", this));
}
diff --git a/TAO/orbsvcs/orbsvcs/Event/EC_TPC_ProxySupplier.cpp b/TAO/orbsvcs/orbsvcs/Event/EC_TPC_ProxySupplier.cpp
index 651346bb32a..756de632952 100644
--- a/TAO/orbsvcs/orbsvcs/Event/EC_TPC_ProxySupplier.cpp
+++ b/TAO/orbsvcs/orbsvcs/Event/EC_TPC_ProxySupplier.cpp
@@ -13,7 +13,7 @@ ACE_RCSID(Event, EC_TPC_ProxySupplier, "$Id$")
TAO_BEGIN_VERSIONED_NAMESPACE_DECL
-extern unsigned long EC_TPC_debug_level;
+extern unsigned long TAO_EC_TPC_debug_level;
TAO_EC_TPC_ProxyPushSupplier::~TAO_EC_TPC_ProxyPushSupplier (void)
{
@@ -24,7 +24,7 @@ void
TAO_EC_TPC_ProxyPushSupplier:: disconnect_push_supplier (ACE_ENV_SINGLE_ARG_DECL)
ACE_THROW_SPEC ((CORBA::SystemException))
{
- if (EC_TPC_debug_level > 0)
+ if (TAO_EC_TPC_debug_level > 0)
ACE_DEBUG ((LM_DEBUG, "EC (%P|%t): enter EC_TPC_ProxySupplier::disconnect_push_supplier (%@): refcount=%u,consumer=%@\n",
this,
this->refcount_,
@@ -39,7 +39,7 @@ TAO_EC_TPC_ProxyPushSupplier:: disconnect_push_supplier (ACE_ENV_SINGLE_ARG_DECL
BASECLASS::disconnect_push_supplier (ACE_ENV_SINGLE_ARG_PARAMETER);
ACE_CHECK;
- if (EC_TPC_debug_level > 0)
+ if (TAO_EC_TPC_debug_level > 0)
ACE_DEBUG ((LM_DEBUG, "EC (%P|%t): leave EC_TPC_ProxySupplier::disconnect_push_supplier (%@)\n", this));
}
@@ -63,7 +63,7 @@ TAO_EC_TPC_ProxyPushSupplier::connect_push_consumer (
BASECLASS::connect_push_consumer (push_consumer, qos ACE_ENV_ARG_PARAMETER);
ACE_CHECK;
- if (EC_TPC_debug_level > 0)
+ if (TAO_EC_TPC_debug_level > 0)
ACE_DEBUG ((LM_DEBUG, "EC (%P|%t): EC_ProxySupplier(%@): refcount=%u,consumer=%@\n",
this, this->refcount_, this->consumer_.in()));
diff --git a/TAO/orbsvcs/orbsvcs/Event/EC_TPC_ProxySupplier.inl b/TAO/orbsvcs/orbsvcs/Event/EC_TPC_ProxySupplier.inl
index 6a31a5fc0d1..6e5b54fb0a3 100644
--- a/TAO/orbsvcs/orbsvcs/Event/EC_TPC_ProxySupplier.inl
+++ b/TAO/orbsvcs/orbsvcs/Event/EC_TPC_ProxySupplier.inl
@@ -4,13 +4,13 @@
TAO_BEGIN_VERSIONED_NAMESPACE_DECL
-extern unsigned long EC_TPC_debug_level;
+extern unsigned long TAO_EC_TPC_debug_level;
ACE_INLINE
TAO_EC_TPC_ProxyPushSupplier::TAO_EC_TPC_ProxyPushSupplier (TAO_EC_Event_Channel_Base* ec, int validate_connection)
: TAO_EC_Default_ProxyPushSupplier (ec, validate_connection)
{
- if (EC_TPC_debug_level > 0)
+ if (TAO_EC_TPC_debug_level > 0)
ACE_DEBUG ((LM_DEBUG, "(%P|%t) EC_TPC_ProxyPushSupplier::CTOR (%@)\n", this));
}
diff --git a/TAO/orbsvcs/orbsvcs/Event/EC_Thread_Flags.cpp b/TAO/orbsvcs/orbsvcs/Event/EC_Thread_Flags.cpp
new file mode 100644
index 00000000000..2f38e11ae1e
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/Event/EC_Thread_Flags.cpp
@@ -0,0 +1,235 @@
+#include "EC_Thread_Flags.h"
+
+ACE_RCSID(Event, EC_Thread_Flags , "$Id$");
+
+#if 0
+#include "ace/Obstack.h"
+#endif
+#include "ace/OS.h" // OS_NS_Thread.h in later versions
+#include "ace/OS_String.h" // OS_NS_String.h in later versions
+#include "ace/Sched_Params.h"
+
+#define TETFSF(flag) { #flag, flag }
+TAO_EC_Thread_Flags::Supported_Flag TAO_EC_Thread_Flags::supported_flags_[] = {
+#if defined (ACE_HAS_THREADS)
+ TETFSF(THR_CANCEL_DISABLE),
+ TETFSF(THR_CANCEL_ENABLE),
+ TETFSF(THR_CANCEL_DEFERRED),
+ TETFSF(THR_CANCEL_ASYNCHRONOUS),
+ TETFSF(THR_BOUND),
+ TETFSF(THR_NEW_LWP),
+ TETFSF(THR_DETACHED),
+ TETFSF(THR_SUSPENDED),
+ TETFSF(THR_DAEMON),
+ TETFSF(THR_JOINABLE),
+ TETFSF(THR_SCHED_FIFO),
+ TETFSF(THR_SCHED_RR),
+ TETFSF(THR_SCHED_DEFAULT),
+ TETFSF(THR_EXPLICIT_SCHED),
+ TETFSF(THR_SCOPE_SYSTEM),
+ TETFSF(THR_SCOPE_PROCESS)
+#endif /* ACE_HAS_THREADS */
+ };
+#undef TETFSF
+
+TAO_EC_Thread_Flags::~TAO_EC_Thread_Flags ()
+{
+#if 0
+ ACE_GUARD (TAO_SYNCH_MUTEX, ace_mon, this->sf_lock_);
+ delete[] this->supported_flags_;
+ this->supported_flags_ = 0;
+#endif
+}
+
+#if 0
+const char* const
+TAO_EC_Thread_Flags::supported_flags () const
+{
+ if (supported_flags_ == 0)
+ {
+ ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, ace_mon, this->sf_lock_, 0);
+
+ // Check again, b/c somebody else could have stuffed somethign
+ // there before we got the lock.
+ if (supported_flags_ == 0)
+ {
+ ACE_Obstack o;
+ size_t num_flags = sizeof(Supported_Flags)/sizeof(Supported_Flags[0]);
+ for (size_t i = 0; i < num_flags; ++i)
+ {
+ const char* sym = Supported_Flags[i].n;
+ while (*sym != 0)
+ {
+ o.grow(*sym++);
+ }
+ o.grow ('|');
+ }
+
+ char* f = o.freeze ();
+ size_t l = ACE_OS_String::strlen(f);
+ this->supported_flags_ = new char[l+1];
+ ACE_OS_String::strcpy (this->supported_flags_, f, l);
+ }
+ }
+ return this->supported_flags_;
+}
+#endif
+
+void
+TAO_EC_Thread_Flags::parse_symbols (const char* syms)
+{
+ // PRE: we assume nothing other than that syms is valid
+ // POST:
+ // 1. flags_ is bitwise-OR of all flags
+ // 2. sched_ is THR_SCHED_*, or THR_SCHED_DEFAULT if not specified
+ // 3. scope_ is THR_SCOPE_*, or THR_SCOPE_PROCESS if not specified
+
+ // NOTE: I'm not sure if #2 and #3 are consistent with what happens
+ // in ACE_Task::activate. I really need to double-check that, and
+ // make sure that they are consistent.
+
+ flags_ = scope_ = sched_ = 0; // zero out everything
+
+ // short-circuit on the trivial case
+ if (syms == 0 || *syms == '\0')
+ return;
+
+ static size_t num_flags = sizeof(supported_flags_)/sizeof(Supported_Flag);
+ char* s = ACE_OS_String::strdup (syms); // need a mutable string
+ if (s == 0)
+ return;
+
+ const char* SEPARATORS = " |"; // this should probably be at class level
+ char* ptr = 0;
+ char* tok = ACE_OS_String::strtok_r (s, SEPARATORS, &ptr);
+ while (tok != 0)
+ {
+ // This would allow for easy accomodation of flags that
+ // aren't currently supported, but is it a good idea?
+
+ if (tok[0] >= '0' && tok[0] <= '9') // Numeric, so just accept it!
+ {
+ // parse it as a long straight to the flags
+
+ // If somebody specifies the scheduler this way, then they
+ // lose range checking on the priority. Bummer, but those
+ // are the breaks.
+ this->flags_ |= ACE_OS_String::strtol (tok, 0, 0);
+ }
+ else
+ {
+ int found = 0;
+ for (size_t i = 0; !found && i < num_flags; ++i)
+ {
+ if (ACE_OS_String::strcasecmp (tok, supported_flags_[i].n) == 0)
+ {
+ this->flags_ |= supported_flags_[i].v;
+
+ // Can't use a switch for this b/c for some
+ // platforms the THR_* constants end up with
+ // the same values, and compiles get upset.
+ long &sf = supported_flags_[i].v;
+ if (sf == THR_SCHED_FIFO ||
+ sf == THR_SCHED_RR ||
+ sf == THR_SCHED_DEFAULT)
+ {
+ this->sched_ = supported_flags_[i].v;
+ }
+ else if (sf == THR_SCOPE_SYSTEM ||
+ sf == THR_SCOPE_PROCESS)
+ {
+ this->scope_ = supported_flags_[i].v;
+ }
+ found = 1;
+ }
+ }
+ if (!found)
+ {
+ // Ideally this would call some sort of on-error function...
+ // but, it doesn't.
+ ACE_ERROR ((LM_ERROR,
+ "RTEC (%P|%t) unable to parse %s as a thread flag - skipping\n",
+ tok));
+ }
+ }
+ tok = ACE_OS_String::strtok_r (0, SEPARATORS, &ptr);
+ }
+
+ ACE_OS::free (s); // clean up after ourselves
+}
+
+#if 0
+long
+TAO_EC_Thread_Flags::ace_sched_from_thr_sched (long thr_sched) const
+{
+ long ace_sched =
+ (thr_sched == THR_SCHED_FIFO) ? ACE_SCHED_FIFO :
+ (thr_sched == THR_SCHED_RR) ? ACE_SCHED_RR :
+ ACE_SCHED_OTHER;
+ return ace_sched;
+}
+
+long
+TAO_EC_Thread_Flags::ace_scope_from_thr_scope (long thr_scope) const
+{
+ long ace_scope =
+ (thr_scope == THR_SCOPE_PROCESS) ? ACE_SCOPE_PROCESS :
+ (thr_scope == THR_SCOPE_SYSTEM) ? ACE_SCOPE_SYSTEM :
+ ACE_SCOPE_THREAD;
+ return ace_scope;
+}
+
+long
+TAO_EC_Thread_Flags::thr_sched_from_ace_sched (long ace_sched) const
+{
+ long thr_sched =
+ (ace_sched == ACE_SCHED_FIFO) ? THR_SCHED_FIFO :
+ (ace_sched == ACE_SCHED_RR) ? THR_SCHED_RR :
+ THR_SCHED_DEFAULT; // there is no THR_SCHED_OTHER for some reason
+ return thr_sched;
+}
+
+long
+TAO_EC_Thread_Flags::thr_scope_from_ace_scope (long ace_scope) const
+{
+ long thr_scope =
+ (ace_scope == ACE_SCOPE_PROCESS) ? THR_SCOPE_PROCESS :
+ (ace_scope == ACE_SCOPE_THREAD) ? THR_SCOPE_THREAD :
+ THR_SCOPE_SYSTEM;
+ return thr_scope;
+}
+
+int
+TAO_EC_Thread_Flags::is_valid_priority (long priority) const
+{
+ // For some wacked out reason the THR_SCHED_* values are different from
+ // the ACE_SCHED_* values. And, more than likely, the same is true for
+ // the *_SCOPE_* values, too. So, here we convert the THR values, which
+ // are in
+ const long ace_sched = ace_sched_from_thr_sched (this->sched());
+ const long ace_scope = ace_scope_from_thr_scope (this->scope());
+ if (this->sched() != 0 && // we have a scheduler
+ priority < ACE_Sched_Params::priority_min (ace_sched, ace_scope) ||
+ priority > ACE_Sched_Params::priority_max (ace_sched, ace_scope))
+ return 0;
+ else
+ return 1;
+}
+#endif
+
+long
+TAO_EC_Thread_Flags::default_priority () const
+{
+ long priority = ACE_DEFAULT_THREAD_PRIORITY;
+
+ // use the implementation
+ if (this->sched() == 0)
+ return priority;
+
+ priority =
+ ACE_Sched_Params::priority_min (this->sched()) +
+ ACE_Sched_Params::priority_max (this->sched()) / 2;
+ priority = ACE_Sched_Params::next_priority (this->sched(), priority);
+
+ return priority;
+}
diff --git a/TAO/orbsvcs/orbsvcs/Event/EC_Thread_Flags.h b/TAO/orbsvcs/orbsvcs/Event/EC_Thread_Flags.h
new file mode 100644
index 00000000000..70613ba739b
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/Event/EC_Thread_Flags.h
@@ -0,0 +1,148 @@
+/* -*- C++ -*- */
+/**
+ * @file EC_Thread_Flags.h
+ *
+ * $Id$
+ *
+ * @author Chris Cleeland <cleeland@ociweb.com>
+ *
+ * Encapsulate flags that can be used for creating threads.
+ */
+
+#ifndef TAO_EC_THREAD_FLAGS_H
+#define TAO_EC_THREAD_FLAGS_H
+#include /**/ "ace/pre.h"
+
+#include "event_serv_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Synch.h" // for ACE_Lock
+
+/*!
+ \class TAO_EC_Thread_Flags
+
+ \brief Parse thread flags from string to a long.
+
+ Encapsulate flags used for creating threads with \a
+ ACE_OS::thr_create and \a ACE_Task::activate.
+
+ \note On platforms that do not support the thread schedulers, the
+ ACE OS adaptation layer preserves the symbols for THR_SCHED_*, but
+ defines them as zero. Thus, on such platforms, setting a scheduler
+ in the flags, then inquiring for the scheduler type will yield the
+ same result as an unknown or unset scheduler.
+
+ \bugs This should really be part of ACE or ACE_OS, and maybe someday
+ it will, but right now it's not.
+
+*/
+class TAO_RTEvent_Serv_Export TAO_EC_Thread_Flags
+{
+public:
+ TAO_EC_Thread_Flags () { }
+ /*! \brief See \a operator=() */
+ TAO_EC_Thread_Flags (const char* symbolic_flags)
+ { this->parse_symbols(symbolic_flags); }
+ ~TAO_EC_Thread_Flags ();
+
+ // Default Copy CTOR is fine.
+
+ /*!
+ \brief Assign a new set of symbolic flags, setting \a flags, \a scope, and \a sched as possible.
+
+ The flags can be symbolic, separated by the vertical bar ('|').
+ In case a platform supports a creation flag not available
+ symbolically, the user can specify a numeric value any place a
+ symbol could be used.
+
+ \sa TAO_EC_Thread_Flags::supported_flags
+
+ \note The \a sched value only gets set if the scheduler is specified using symbols.
+ */
+ const TAO_EC_Thread_Flags& operator= (const char* symbolic_flags)
+ { this->parse_symbols(symbolic_flags); return *this; }
+
+ /*!
+ \brief Returns numeric equivalent of the thread flags suitable for passing to ACE_Task::activate.
+ */
+ long flags() const { return this->flags_; }
+
+ /*!
+ \brief Returns value of THR_SCOPE_* used, or zero if unknown.
+ */
+ long scope() const { return this->scope_; }
+
+ /*!
+ \brief Returns value of THR_SCHED_* used, or zero if unknown.
+ */
+ long sched() const { return this->sched_; }
+
+ /// Synonym for flags(), i.e., syntactic sugar.
+ operator long () const { return this->flags(); }
+
+#if 0
+ /*!
+ \brief Indicate whether a priority is valid for the scheduler returned by sched().
+
+ \return non-zero if the priority is valid.
+
+ \note Always returns non-zero if sched == 0, i.e., the scheduler is unknown.
+ */
+ int is_valid_priority (long priority) const;
+
+ /*!
+ \brief Convert THR_SCHED_* values to ACE_SCHED_* values.
+
+ For some wacked out reason the THR_SCHED_* values are different from
+ the ACE_SCHED_* values, so we provide a mapping function.
+ */
+ long ace_sched_from_thr_sched (long thr_sched) const;
+ long ace_scope_from_thr_scope (long thr_scope) const;
+ long thr_sched_from_ace_sched (long ace_sched) const;
+ long thr_scope_from_ace_scope (long ace_scope) const;
+#endif
+
+ /*!
+ \brief Return an acceptable default priority for the scheduler returned by sched().
+ \return the priority, or ACE_DEFAULT_THREAD_PRIORITY if the scheduler is unknown.
+ */
+ long default_priority () const;
+
+
+
+#if 0
+ /// Return a |-separated list of all flags that we can parse.
+ const char* supported_flags () const;
+#endif
+
+ struct Supported_Flag
+ {
+ const char* n; /// Flag name, e.g., THR_NEW_LWP
+ long v; /// Flag value, i.e., actual symbol
+ };
+
+ // TETFSF == TAO_EC_THREAD_FLAGS_SUPPORTED_FLAGS
+ static Supported_Flag supported_flags_[];
+
+protected:
+ long flags_; /// Value of all flags OR'd together
+ long scope_; /// Value of THR_SCOPE_*
+ long sched_; /// Value of THR_SCHED_*
+
+ void parse_symbols (const char* syms);
+
+#if 0
+ ACE_Lock sf_lock_; // lock guarding access to supported_flags_
+ const char* supported_flags_;
+#endif
+};
+
+#if 0 && defined (__ACE_INLINE__)
+#include "EC_Thread_Flags.i"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+#endif /* TAO_EC_THREAD_FLAGS_H */
diff --git a/TAO/orbsvcs/orbsvcs/RTEvent_Serv.mpc b/TAO/orbsvcs/orbsvcs/RTEvent_Serv.mpc
index 1e9797263d9..44f368731c9 100644
--- a/TAO/orbsvcs/orbsvcs/RTEvent_Serv.mpc
+++ b/TAO/orbsvcs/orbsvcs/RTEvent_Serv.mpc
@@ -81,6 +81,7 @@ project(RTEvent_Serv) : orbsvcslib, core, rtevent_skel, svc_utils, messaging {
Event/EC_TPC_Factory.cpp
Event/EC_TPC_ProxyConsumer.cpp
Event/EC_TPC_ProxySupplier.cpp
+ Event/EC_Thread_Flags.cpp
}
Template_Files {
diff --git a/TAO/orbsvcs/tests/Event/ThreadFlags/testflags.cpp b/TAO/orbsvcs/tests/Event/ThreadFlags/testflags.cpp
new file mode 100644
index 00000000000..5bebc702298
--- /dev/null
+++ b/TAO/orbsvcs/tests/Event/ThreadFlags/testflags.cpp
@@ -0,0 +1,225 @@
+/*
+ * Test TAO_EC_Thread_Flags encapsulation.
+ */
+
+#include <orbsvcs/Event/EC_Thread_Flags.h>
+#include <ace/Log_Msg.h>
+
+ACE_RCSID(EC_Tests, testflags, "$Id$");
+
+/*
+ Here are the scenarios we need to test:
+
+ 1. Initialize/assign empty instance and validate defaults, priority, etc.
+ 2. Initialize/assign with each flag and validate value of flags.
+ 3. Initialize/assign with each scope and validate scope and flags.
+ 4. Initialize/assign with each sched and validate sched and flags.
+ 5. Initialize/assign with single numeric value and validate flags, sched, and scope values.
+ 6. Initialize/assign with bogus symbols and validate scope/flags + error.
+ 7. Initialize/assign with multiple flags and validate flags, scope, sched.
+
+ */
+struct ExpectedValues
+{
+ long flags;
+ long scope;
+ long sched;
+
+ ExpectedValues(long f = 0, long sco = 0, long sch = 0)
+ : flags(f)
+ , scope(sco)
+ , sched(sch)
+ {
+ }
+};
+
+struct ThreadFlagsTest
+{
+ enum How {
+ INIT = 0x1, // use constructor initialization
+ ASSIGN = 0x2, // use assignment operator
+ BOTH = 0x3
+ };
+
+ ThreadFlagsTest (const char* sym, How assign, ExpectedValues ev, ExpectedValues which_check);
+
+ // Execute the test and pass back an ExpectedValues struct where the
+ // values are zero if the values were not as expected or non-zero if
+ // they were as expected. Return value is zero for success, or
+ // the bitmask of the "How" version of the test that failed.
+ int runtest(ExpectedValues& results);
+
+ const char* sym_;
+ How assign_;
+ ExpectedValues expected_values_;
+ ExpectedValues which_results_to_check_;
+
+};
+
+ThreadFlagsTest::ThreadFlagsTest (const char* sym,
+ How assign,
+ ExpectedValues ev,
+ ExpectedValues which_check)
+ : sym_(sym)
+ , assign_(assign)
+ , expected_values_(ev)
+ , which_results_to_check_(which_check)
+{
+}
+
+int
+ThreadFlagsTest::runtest (ExpectedValues& results)
+{
+ int r = 0;
+ if (assign_ & INIT)
+ {
+ TAO_EC_Thread_Flags f(sym_);
+ if ( ((results.flags = f.flags()) == expected_values_.flags) &&
+ ((results.scope = f.scope()) == expected_values_.scope) &&
+ ((results.sched = f.sched()) == expected_values_.sched) )
+ ; // we succeeded, do nothing
+ else
+ r |= INIT;
+ }
+ if (assign_ & ASSIGN)
+ {
+ TAO_EC_Thread_Flags f;
+ f = sym_;
+ if ( ((results.flags = f.flags()) == expected_values_.flags) &&
+ ((results.scope = f.scope()) == expected_values_.scope) &&
+ ((results.sched = f.sched()) == expected_values_.sched) )
+ ; // we succeeded, do nothing
+ else
+ r |= ASSIGN;
+ }
+
+ return r;
+}
+
+// Common things to pass for 'which_check'
+static const ExpectedValues CHECK_ALL(1, 1, 1);
+static const ExpectedValues ONLY_FLAGS(1, 0, 0);
+// ExpectedValues set indicating the default values
+static const ExpectedValues DEFAULTS(0, 0, 0);
+
+void
+print_results (int how, ExpectedValues expected, ExpectedValues actuals)
+{
+ const char* op =
+ (how == ThreadFlagsTest::INIT) ? "INIT" :
+ (how == ThreadFlagsTest::ASSIGN) ? "ASSIGN" :
+ (how == ThreadFlagsTest::BOTH) ? "BOTH" :
+ "unk?";
+
+ ACE_DEBUG ((LM_DEBUG, " %s: expected {%x,%x,%x} got {%x,%x,%x}",
+ op,
+ expected.flags, expected.scope, expected.sched,
+ actuals.flags, actuals.scope, actuals.sched));
+}
+
+int
+main (int argc, char* argv[])
+{
+ ThreadFlagsTest static_tests[] = {
+ // Test 1
+ ThreadFlagsTest(0, ThreadFlagsTest::BOTH, DEFAULTS, CHECK_ALL),
+ // Test 2
+ ThreadFlagsTest("THR_CANCEL_DISABLE", ThreadFlagsTest::BOTH, ExpectedValues(THR_CANCEL_DISABLE), CHECK_ALL),
+ ThreadFlagsTest("THR_CANCEL_ENABLE", ThreadFlagsTest::BOTH, ExpectedValues(THR_CANCEL_ENABLE), CHECK_ALL),
+ ThreadFlagsTest("THR_CANCEL_DEFERRED", ThreadFlagsTest::BOTH, ExpectedValues(THR_CANCEL_DEFERRED), CHECK_ALL),
+ ThreadFlagsTest("THR_CANCEL_ASYNCHRONOUS", ThreadFlagsTest::BOTH, ExpectedValues(THR_CANCEL_ASYNCHRONOUS), CHECK_ALL),
+ ThreadFlagsTest("THR_BOUND", ThreadFlagsTest::BOTH, ExpectedValues(THR_BOUND), CHECK_ALL),
+ ThreadFlagsTest("THR_NEW_LWP", ThreadFlagsTest::BOTH, ExpectedValues(THR_NEW_LWP), CHECK_ALL),
+ ThreadFlagsTest("THR_DETACHED", ThreadFlagsTest::BOTH, ExpectedValues(THR_DETACHED), CHECK_ALL),
+ ThreadFlagsTest("THR_SUSPENDED", ThreadFlagsTest::BOTH, ExpectedValues(THR_SUSPENDED), CHECK_ALL),
+ ThreadFlagsTest("THR_DAEMON", ThreadFlagsTest::BOTH, ExpectedValues(THR_DAEMON), CHECK_ALL),
+ ThreadFlagsTest("THR_JOINABLE", ThreadFlagsTest::BOTH, ExpectedValues(THR_JOINABLE), CHECK_ALL),
+ // Test 3
+ ThreadFlagsTest("THR_SCHED_FIFO", ThreadFlagsTest::BOTH, ExpectedValues(THR_SCHED_FIFO, 0, THR_SCHED_FIFO), CHECK_ALL),
+ ThreadFlagsTest("THR_SCHED_RR", ThreadFlagsTest::BOTH, ExpectedValues(THR_SCHED_RR, 0, THR_SCHED_RR), CHECK_ALL),
+ ThreadFlagsTest("THR_SCHED_DEFAULT", ThreadFlagsTest::BOTH, ExpectedValues(THR_SCHED_DEFAULT, 0, THR_SCHED_DEFAULT), CHECK_ALL),
+ // Test 4
+ ThreadFlagsTest("THR_SCOPE_SYSTEM", ThreadFlagsTest::BOTH, ExpectedValues(THR_SCOPE_SYSTEM, THR_SCOPE_SYSTEM, 0), CHECK_ALL),
+ ThreadFlagsTest("THR_SCOPE_PROCESS", ThreadFlagsTest::BOTH, ExpectedValues(THR_SCOPE_PROCESS, THR_SCOPE_PROCESS, 0), CHECK_ALL),
+ // Test 5
+ ThreadFlagsTest("0x0001", ThreadFlagsTest::BOTH, ExpectedValues(1, 0, 0), CHECK_ALL),
+ // Test 6
+ ThreadFlagsTest("Zaphod|Beeblebrox|THR_BOGUS", ThreadFlagsTest::BOTH, DEFAULTS, CHECK_ALL),
+ // Test 7
+ ThreadFlagsTest("THR_BOUND|THR_JOINABLE", ThreadFlagsTest::BOTH, ExpectedValues(THR_BOUND|THR_JOINABLE), CHECK_ALL),
+ ThreadFlagsTest("THR_SCHED_FIFO|THR_DAEMON|THR_SCOPE_PROCESS", ThreadFlagsTest::BOTH, ExpectedValues(THR_SCHED_FIFO|THR_DAEMON|THR_SCOPE_PROCESS, THR_SCOPE_PROCESS, THR_SCHED_FIFO), CHECK_ALL),
+ ThreadFlagsTest("THR_SCHED_DEFAULT|THR_SCOPE_SYSTEM|THR_NEW_LWP", ThreadFlagsTest::BOTH, ExpectedValues(THR_SCHED_DEFAULT|THR_SCOPE_SYSTEM|THR_NEW_LWP, THR_SCOPE_SYSTEM, THR_SCHED_DEFAULT), CHECK_ALL),
+ ThreadFlagsTest("THR_NEW_LWP|THR_SCOPE_SYSTEM|THR_JOINABLE|THR_SCHED_FIFO",
+ ThreadFlagsTest::BOTH,
+ ExpectedValues(THR_NEW_LWP|THR_SCHED_FIFO|THR_SCOPE_SYSTEM|THR_JOINABLE, THR_SCOPE_SYSTEM, THR_SCHED_FIFO),
+ CHECK_ALL)
+ };
+
+ int returnval = 0;
+ const size_t numtests = sizeof(static_tests)/sizeof(static_tests[0]);
+ if (argc > 1)
+ {
+ char* which_test;
+ while ((which_test = *++argv))
+ {
+ size_t testnum = ACE_OS_String::strtol (which_test, 0, 0);
+ if (testnum < numtests)
+ {
+ ExpectedValues results;
+ ThreadFlagsTest& t = static_tests[testnum];
+ ACE_DEBUG ((LM_DEBUG, "Test #%d for %s...", testnum, t.sym_));
+ int r = t.runtest (results);
+ if (r != 0)
+ {
+ returnval = 1;
+ ACE_DEBUG ((LM_DEBUG, "FAILED -- details: "));
+ if (r & ThreadFlagsTest::INIT)
+ print_results (ThreadFlagsTest::INIT, t.expected_values_, results);
+
+ if (r & ThreadFlagsTest::ASSIGN)
+ print_results (ThreadFlagsTest::ASSIGN, t.expected_values_, results);
+
+ ACE_DEBUG ((LM_DEBUG, "\n"));
+ }
+ else
+ {
+ ACE_DEBUG ((LM_DEBUG, "ok.\n"));
+ }
+ }
+ else
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "%d is not a valid test number\n", testnum));
+ }
+ }
+ }
+ else
+ {
+ for(size_t i = 0; i < numtests; ++i)
+ {
+ ExpectedValues results;
+ ThreadFlagsTest& t = static_tests[i];
+ ACE_DEBUG ((LM_DEBUG, "Test #%d for %s...", i, t.sym_));
+ int r = t.runtest (results);
+ if (r != 0)
+ {
+ returnval = 1;
+ ACE_DEBUG ((LM_DEBUG, "FAILED -- details: "));
+ if (r & ThreadFlagsTest::INIT)
+ print_results (ThreadFlagsTest::INIT, t.expected_values_, results);
+
+ if (r & ThreadFlagsTest::ASSIGN)
+ print_results (ThreadFlagsTest::ASSIGN, t.expected_values_, results);
+
+ ACE_DEBUG ((LM_DEBUG, "\n"));
+ }
+ else
+ {
+ ACE_DEBUG ((LM_DEBUG, "ok.\n"));
+ }
+ }
+
+ }
+
+ return returnval;
+}
diff --git a/TAO/orbsvcs/tests/Event/ThreadFlags/tftest.mpc b/TAO/orbsvcs/tests/Event/ThreadFlags/tftest.mpc
new file mode 100644
index 00000000000..7b274ab68fe
--- /dev/null
+++ b/TAO/orbsvcs/tests/Event/ThreadFlags/tftest.mpc
@@ -0,0 +1,5 @@
+// $Id$
+project(TFTest): rteventexe {
+ exename = testflags
+ libs += TAO_RTEvent_Serv
+}