diff options
author | Chris Cleeland <chris.cleeland@gmail.com> | 2006-11-08 19:17:49 +0000 |
---|---|---|
committer | Chris Cleeland <chris.cleeland@gmail.com> | 2006-11-08 19:17:49 +0000 |
commit | d9ca80311fa2b9595ae36eaadb9a8e816706f148 (patch) | |
tree | 6ff62ad738fced33a8eddaf2a95973ca3a9470cc | |
parent | 9ef3b09874c19f5586f2fe04d9a69ee816be0ecc (diff) | |
download | ATCD-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.rt8089 | 68 | ||||
-rw-r--r-- | TAO/docs/ec_options.html | 31 | ||||
-rw-r--r-- | TAO/orbsvcs/orbsvcs/Event/EC_Default_Factory.cpp | 38 | ||||
-rw-r--r-- | TAO/orbsvcs/orbsvcs/Event/EC_Default_Factory.h | 13 | ||||
-rw-r--r-- | TAO/orbsvcs/orbsvcs/Event/EC_Factory.cpp | 7 | ||||
-rw-r--r-- | TAO/orbsvcs/orbsvcs/Event/EC_Factory.h | 3 | ||||
-rw-r--r-- | TAO/orbsvcs/orbsvcs/Event/EC_TPC_Dispatching.cpp | 26 | ||||
-rw-r--r-- | TAO/orbsvcs/orbsvcs/Event/EC_TPC_Dispatching.h | 20 | ||||
-rw-r--r-- | TAO/orbsvcs/orbsvcs/Event/EC_TPC_Factory.cpp | 20 | ||||
-rw-r--r-- | TAO/orbsvcs/orbsvcs/Event/EC_TPC_Factory.h | 4 | ||||
-rw-r--r-- | TAO/orbsvcs/orbsvcs/Event/EC_TPC_ProxyConsumer.cpp | 4 | ||||
-rw-r--r-- | TAO/orbsvcs/orbsvcs/Event/EC_TPC_ProxySupplier.cpp | 8 | ||||
-rw-r--r-- | TAO/orbsvcs/orbsvcs/Event/EC_TPC_ProxySupplier.inl | 4 | ||||
-rw-r--r-- | TAO/orbsvcs/orbsvcs/Event/EC_Thread_Flags.cpp | 235 | ||||
-rw-r--r-- | TAO/orbsvcs/orbsvcs/Event/EC_Thread_Flags.h | 148 | ||||
-rw-r--r-- | TAO/orbsvcs/orbsvcs/RTEvent_Serv.mpc | 1 | ||||
-rw-r--r-- | TAO/orbsvcs/tests/Event/ThreadFlags/testflags.cpp | 225 | ||||
-rw-r--r-- | TAO/orbsvcs/tests/Event/ThreadFlags/tftest.mpc | 5 |
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 +} |