diff options
author | irfan <irfan@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 2003-05-10 00:14:18 +0000 |
---|---|---|
committer | irfan <irfan@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 2003-05-10 00:14:18 +0000 |
commit | b823a438cefeeb2aa45b4c932446eff4295ab111 (patch) | |
tree | ef4c3b00682aeae578ba95a96f236630d8243eb5 | |
parent | c24e6ce901cf5e78cc226240da615dffd675baa1 (diff) | |
download | ATCD-b823a438cefeeb2aa45b4c932446eff4295ab111.tar.gz |
ChangeLogTag: Fri May 09 20:13:37 2003 Irfan Pyarali <irfan@oomworks.com>
59 files changed, 8860 insertions, 2657 deletions
diff --git a/ChangeLog b/ChangeLog index c6e584ac0e4..fa9801104eb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,362 @@ +Fri May 09 20:13:37 2003 Irfan Pyarali <irfan@oomworks.com> + + * ace\Event_Handler: + + Added reference counting capabilities to the event handler. + This will be used for event handler memory management by + Reactors that will call add_reference() and remove_reference() + during registrations, removals, and upcalls (similar to the + protocol between servants and POAs). + + Reference counting is configurable and can be controlled by the + Reference_Counting_Policy which is disabled by default. + + Added a ACE_Event_Handler_var auto pointer like class for + Event Handlers. This class calls + ACE_Event_Handler::remove_reference() in its destructor. + + Added reactor_timer_interface() method that returns the + Reactor's timer related interface. + + * ace\Reactor_Timer_Interface.h: + + Added a new class ACE_Reactor_Timer_Interface that contains + timer related (pure virtual) methods of the Reactor. This + allows us to make timer related calls on the Reactor from the + Timer Queue without having to include Reactor.h. + + * ace\Reactor: + + Vastly improved documentation, specially with respect to how the + reference counting works. + + Made the Reactor class inherit from ACE_Reactor_Timer_Interface + so that timer related calls can be made on the Reactor from the + Timer Queue without having to include Reactor.h + + * ace\Reactor: + * ace\Reactor_Impl: + * ace\Select_Reactor_T: + * ace\WFMO_Reactor: + + Added a new handler() method that returns the event handler + associated with a <handle>. + + * ace\Select_Reactor_Base.cpp: + + - bind(): Make sure that the user is not registering a different + handler for an existing handle in the + Reactor_Handler_Repository. Also, if new entry, call + add_reference() if reference counting is needed. + + - unbind(): Call remove_reference() if the removal is complete + and reference counting is needed. Also, Bala's change: + + Mon Apr 7 16:58:55 2003 Balachandran Natarajan <bala@dre.vanderbilt.edu> + + is no longer necessary since handle_close() is now only called + once the Reactor state has been completely updated. + + - mask_ops(): If the handle is not suspended, then set the ops + on the <wait_set_>, otherwise set the <suspend_set_>. + + - handler_i(): Add to reference count of event handler before + returning to the user if reference counting is needed. + + - ACE_Select_Reactor_Notify::dispatch_notify(): + - ACE_Select_Reactor_Notify::purge_pending_notifications(): + - ACE_Select_Reactor_Notify::notify(): + + Added reference counting for notifies. + + * ace\Select_Reactor_T: + + notify_handle(): Added reference counting to upcalls. + + * ace\TP_Reactor.cpp: + + - remove_handler(): All remove_handler() specializations can be + removed since there no longer is the requirement of calling + handle_close() from outside the Reactor lock. + + - handle_timer_events(): Call preinvoke() and postinvoke() on + the timer queue so that timer upcalls can be reference counted. + + - handle_socket_events(): Added reference counting to upcalls. + + - mask_ops(): Specialization no longer necessary since the base + class now does the right thing. + + * ace\WFMO_Reactor.cpp: + + - handler(): Original handler() method was not locked. + + - bind_i(): Call add_reference() if reference counting is + needed. + + - make_changes_in_current_infos(): + - make_changes_in_suspension_infos(): + - make_changes_in_to_be_added_infos(): + + The iteration loop was incorrect. When an entry was replaced + from the one at the end, it newly shifted entry was skipped and + not evaluated. make_changes_in_to_be_added_infos() did not need + this change since entries are not moved around in the + <to_be_added_info_> set. + + Also, call remove_reference() if reference counting if needed. + + - complex_dispatch_handler(): Added reference counting to + upcalls. + + - ACE_WFMO_Reactor_Notify::purge_pending_notifications(): + - ACE_WFMO_Reactor_Notify::notify(): + - ACE_WFMO_Reactor_Notify::handle_signal(): + + Added reference counting for notifies. + + * ace\Timer_Queue_T: + + - Not sure why we were including Test_and_Set.h when we only + needed to include Event_Handler.h. + + - dispatch_info() and dispatch_info_i(): Made these virtual so + that they can be specialized. + + - ACE_Timer_Node_Dispatch_Info_T: Added <recurring_timer_> so + that we can determine if we need to call remove_reference() if + it is not a recurring timer and if reference counting is + required. This value is passed to the timeout() method of the + upcall functor. + + - timeout(): When handle_timeout() returns -1, invoke + cancel_timer() on the reactor if the event handler has a valid + reactor, otherwise invoke cancel() on the timer queue. It is + necessary to get the same locking as was used when registering + the timer, which was potentially done holding the reactor lock + while the timer queue could have configured with a null lock. + + - schedule(): No longer a pure virtual method. It now grabs + the lock, call schedule_i(), and finally calls registration() on + the upcall functor. + + - registration(): This method is called when a timer is + registered. + + - preinvoke(): Invokes add_reference() on the event handler if + reference counting is required before making the upcall. + + - upcall(): Changed the signature to pass + ACE_Timer_Node_Dispatch_Info_T instead of the individual + parameters. + + - postinvoke(): Invokes remove_reference() on the event handler + if reference counting is required after making the upcall. + + - cancellation(): Added <dont_call> parameter to this method. + + - expire(): Call preinvoke() before calling upcall() and + postinvoke() after calling upcall(). + + - deletion(): Now calls cancellation(). + + * ace\Timer_List_T: + * ace\Timer_Wheel_T: + * ace\Timer_Heap_T: + * ace\Timer_Hash_T: + + - schedule_i(): This method replaces the old schedule() method. + Locking is not necessary anymore. + + - cancel(): Irrespective of the number of times (including zero) + the event handler was registered, cancel_i() was always called + once. This makes it very hard to do proper lifetime management + of the handler. The new semantics calls cancel_i() for each + registeration of the handler. + + - cancel_i(): Always call cancellation() on the upcall functor. + The <skip_close> check will be performed in the upcall functor. + + * ace\Timer_Heap_T: + + - ~ACE_Timer_Heap_T(): Don't use <cur_size_> for the for loop + since it reduces after free_node() is called. + + - cancel(): Not sure why this is the only cancel() where the + upcall is made outside the lock. + + * ace\Timer_Wheel_T: + + - expire(): Made this method similar to Timer_Queue_T::expire() + by (a) invoking preinvoke() before calling upcall() and invoking + postinvoke() after calling upcall() and (b) making sure that we + skip past time values that have already "expired" when + rescheduling. + + * ace\Timer_Hash_T: + + - ACE_Timer_Hash_Upcall: Updated this upcall functor to match + the new APIs. + + - ACE_Timer_Hash_Upcall::registration(): + - ACE_Timer_Hash_Upcall::cancellation(): + + Nothing to be done here since registration will be handled by + the upcall functor of the timer hash. + + - ACE_Timer_Hash_Upcall::preinvoke(): + - ACE_Timer_Hash_Upcall::postinvoke(): + - ACE_Timer_Hash_Upcall::preinvoke(): + + Assert that these methods never get invoked since we don't + invoke expire() on the buckets. + + - ACE_Timer_Hash_Upcall::deletion(): Call up to the upcall + functor of the timer hash since the timer hash does not invoke + deletion() on its upcall functor directly. This is because + entries are actually registered with the buckets, and this + method will be invoked when the buckets are cleaned up. + + - Hash_Token: Added TYPE information to the token. This + required templatizing Hash_Token since TYPE is a template + parameter. + + - reschedule(): Cancel the old timer before registering the new + one. Otherwise, the old timer will always remain in the + buckets. Also, make sure that the new bucket position is noted. + + - dispatch_info_i(): This method needs to be specialized to give + the original act and not the modified act. + + - free_node(): Needs to cancel the timer in addition to freeing + the node. + + - expire(): Only call cancel() for timers that don't need to be + rescheduled. reschedule() take care of removing the old timer + for timers that need to be rescheduled. Also, made this method + similar to Timer_Queue_T::expire() by invoking preinvoke() + before calling upcall() and invoking postinvoke() after calling + upcall(). + + * ace\Proactor: + + Updated ACE_Proactor_Handle_Timeout_Upcall upcall functor to + match the new APIs. + + * ace\Connector: + + Completely reworked the Connector to utilize the reference + counting provided by the Reactor. This new design fixes bugs + 1405 and 1408. + + - There used to be a hash map that mapped handles to service + handlers. There is no need for this map since the Reactor + already keeps this mapping. We now keep a simple handle set to + remember the non-blocking connects in progress. This will help + when the Connector is closing down and we need to cancel the + non-blocking connections in progress. + + - The Connector no longer needs to inherit from + ACE_Service_Object since it does not register with the Reactor. + We now use ACE_NonBlocking_Connect_Handler for handling + non-blocking connects. The resume(), suspend(), and init() + no-ops, and fini() and info() were removed. + + - The <mutex_> is no longer needed since we use the Reactor lock + to do all our sychronization. This will solve bug 1408. + + - We no longer need the <closing_> flag. + + - Need to add a <reactor_> field since the Connector is no + longer an event handler. + + - Reference counting of ASTs is no longer needed since event + handlers are reference counted. + + * tests\Reference_Counted_Event_Handler_Test: + + This test is used to check reference counting of the Event + Handler when it interacts with the Reactor. + + * tests\MT_Reference_Counted_Event_Handler_Test: + + This test tries to represents what happens in the ORB wrt to + event handlers, reactors, timer queues, threads, and connection + caches, minus the other complexities. The following three + Reactors are tested: Select, TP, and WFMO. + + The test checks proper use and shutting down of client-side + event handlers when it is used by invocation threads and/or + event loop threads. Server-side event handlers are either + threaded or reactive. A purger thread is introduced to check the + connection recycling and cache purging. Nested upcalls are also + tested. + + * tests\MT_Reference_Counted_Notify_Test: + + This test is used to check reference counting of the event + handlers when it interacts with the reactor notification + mechanism. + + * tests\Timer_Queue_Reference_Counting_Test: + + New test is used to check reference counting of the Event + Handler when it interacts with Timer Queues. + + * tests\NonBlocking_Conn_Test: + + This test checks for the proper working of the following: + - blocking connections + - blocking connections with timeouts + - non-blocking connections + - non-blocking connections without waiting for completions + - non-blocking connections with timeouts + + * tests\Reactor_Registration_Test: + + This is a test of registering handlers with the Reactor. + + * tests\WFMO_Reactor_Test: + + New test of the WFMO_Reactor. It makes sure that removals and + suspensions work correctly. + + * tests\Timer_Cancellation_Test: + + A test to ensure the timer cancellation works correctly. + + * tests\Makefile: + * tests\Makefile.am: + * tests\Makefile.bor: + * tests\icc.bat: + * tests\run_test.lst: + * tests\run_tests.bat: + * tests\run_tests.psosim: + * tests\tests.icp: + * tests\tests.mpc: + * tests\tests.dsw: + + Added new tests: + + - MT_Reference_Counted_Event_Handler_Test + - MT_Reference_Counted_Notify_Test + - NonBlocking_Conn_Test + - Reactor_Registration_Test + - Reference_Counted_Event_Handler_Test + - Timer_Cancellation_Test + - Timer_Queue_Reference_Counting_Test + - WFMO_Reactor_Test + + * tests\Conn_Test.cpp: + + Updated template instantiations. + + * tests\icc.bat: + * tests\run_tests.bat: + * tests\run_tests.psosim: + + Removed these files since they have become obsolete. + Mon Apr 28 11:00:13 2003 Ossama Othman <ossama@dre.vanderbilt.edu> * configure.ac: diff --git a/ace/Connector.cpp b/ace/Connector.cpp index 52651212c74..1a180846ac5 100644 --- a/ace/Connector.cpp +++ b/ace/Connector.cpp @@ -1,39 +1,194 @@ -#ifndef ACE_CONNECTOR_CPP -#define ACE_CONNECTOR_CPP +// Connector.cpp +// $Id$ + +#ifndef ACE_CONNECTOR_C +#define ACE_CONNECTOR_C #include "ace/Connector.h" -#include "ace/Svc_Handler.h" #if !defined (ACE_LACKS_PRAGMA_ONCE) # pragma once #endif /* ACE_LACKS_PRAGMA_ONCE */ -ACE_RCSID (ace, - Connector, - "$Id$") +ACE_RCSID(ace, Connector, "$Id$") ACE_ALLOC_HOOK_DEFINE(ACE_Connector) +template <class SVC_HANDLER> +ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::ACE_NonBlocking_Connect_Handler +(ACE_Connector_Base<SVC_HANDLER> &connector, + SVC_HANDLER *sh, + long id) + : connector_ (connector) + , svc_handler_ (sh) + , timer_id_ (id) +{ + ACE_TRACE ("ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::ACE_NonBlocking_Connect_Handler"); + + this->reference_counting_policy ().value + (ACE_Event_Handler::Reference_Counting_Policy::ENABLED); +} + +template <class SVC_HANDLER> SVC_HANDLER * +ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::svc_handler (void) +{ + ACE_TRACE ("ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::svc_handler"); + return this->svc_handler_; +} + +template <class SVC_HANDLER> long +ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::timer_id (void) +{ + ACE_TRACE ("ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::timer_id"); + return this->timer_id_; +} + +template <class SVC_HANDLER> void +ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::timer_id (long id) +{ + ACE_TRACE ("ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::timer_id"); + this->timer_id_ = id; +} + +template <class SVC_HANDLER> void +ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::dump (void) const +{ + ACE_TRACE ("ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("svc_handler_ = %x"), this->svc_handler_)); + ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\ntimer_id_ = %d"), this->timer_id_)); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +template <class SVC_HANDLER> SVC_HANDLER * +ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::close (void) +{ + SVC_HANDLER *svc_handler = 0; + + // Make sure that we haven't already initialized the Svc_Handler. + if (this->svc_handler_) + { + // Exclusive access to the Reactor. + ACE_GUARD_RETURN (ACE_Lock, ace_mon, this->reactor ()->lock (), 0); + + // Double check. + if (this->svc_handler_) + { + // Remember the Svc_Handler. + svc_handler = this->svc_handler_; + + // Remove from Reactor. + this->reactor ()->remove_handler + (this->svc_handler_->get_handle (), + ACE_Event_Handler::ALL_EVENTS_MASK); + + // Cancel timer. + this->reactor ()->cancel_timer + (this->timer_id (), 0, 0); + + // Remove this handle from the set of non-blocking handles + // in the Connector. + this->connector_.non_blocking_handles ().clr_bit + (this->svc_handler_->get_handle ()); + + // We are done. Don't initialize the Svc_Handler again. + this->svc_handler_ = 0; + } + } + + return svc_handler; +} + +template <class SVC_HANDLER> int +ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::handle_timeout +(const ACE_Time_Value &tv, + const void *arg) +{ + // This method is called if a connection times out before completing. + ACE_TRACE ("ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::handle_timeout"); + + SVC_HANDLER *svc_handler = + this->close (); + + if (svc_handler == 0) + return 0; + + // Forward to the SVC_HANDLER the <arg> that was passed in as a + // magic cookie during ACE_Connector::connect(). This gives the + // SVC_HANDLER an opportunity to take corrective action (e.g., wait + // a few milliseconds and try to reconnect again. + if (svc_handler->handle_timeout (tv, arg) == -1) + svc_handler->handle_close (svc_handler->get_handle (), + ACE_Event_Handler::TIMER_MASK); + + return 0; +} + + +template <class SVC_HANDLER> int +ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::handle_input (ACE_HANDLE h) +{ + // Called when a failure occurs during asynchronous connection + // establishment. + ACE_TRACE ("ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::handle_input"); + + SVC_HANDLER *svc_handler = + this->close (); + + if (svc_handler == 0) + return 0; + + // Close Svc_Handler. + svc_handler->close (0); + + return 0; +} + +template <class SVC_HANDLER> int +ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::handle_output (ACE_HANDLE handle) +{ + // Called when a connection is establishment asynchronous. + ACE_TRACE ("ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::handle_output"); + + SVC_HANDLER *svc_handler = + this->close (); + + if (svc_handler == 0) + return 0; + + this->connector_.initialize_svc_handler (handle, + svc_handler); + + return 0; +} + +template <class SVC_HANDLER> int +ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::handle_exception (ACE_HANDLE h) +{ + // On Win32, the except mask must also be set for asynchronous + // connects. + ACE_TRACE ("ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::handle_exception"); + + return this->handle_output (h); +} + +template <class SVC_HANDLER> int +ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::resume_handler (void) +{ + return ACE_Event_Handler::ACE_EVENT_HANDLER_NOT_RESUMED; +} + template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> void ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::dump (void) const { ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::dump"); ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); - ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nclosing_ = %d"), this->closing_)); ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nflags_ = %d"), this->flags_)); - this->handler_map_.dump (); ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); } -// Bridge method for creating a SVC_HANDLER. The strategy for -// creating a SVC_HANDLER are configured into the Acceptor via it's -// <creation_strategy_>. The default is to create a new SVC_HANDLER. -// However, subclasses can override this strategy to perform -// SVC_HANDLER creation in any way that they like (such as creating -// subclass instances of SVC_HANDLER, using a singleton, dynamically -// linking the handler, etc.). - template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::make_svc_handler (SVC_HANDLER *&sh) { @@ -87,14 +242,14 @@ ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connector (void) const } template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int -ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect_svc_handler ( - SVC_HANDLER *&svc_handler, - const ACE_PEER_CONNECTOR_ADDR &remote_addr, - ACE_Time_Value *timeout, - const ACE_PEER_CONNECTOR_ADDR &local_addr, - int reuse_addr, - int flags, - int perms) +ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect_svc_handler +(SVC_HANDLER *&svc_handler, + const ACE_PEER_CONNECTOR_ADDR &remote_addr, + ACE_Time_Value *timeout, + const ACE_PEER_CONNECTOR_ADDR &local_addr, + int reuse_addr, + int flags, + int perms) { ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect_svc_handler"); @@ -108,15 +263,15 @@ ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect_svc_handler ( } template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int -ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect_svc_handler ( - SVC_HANDLER *&svc_handler, - SVC_HANDLER *&sh_copy, - const ACE_PEER_CONNECTOR_ADDR &remote_addr, - ACE_Time_Value *timeout, - const ACE_PEER_CONNECTOR_ADDR &local_addr, - int reuse_addr, - int flags, - int perms) +ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect_svc_handler +(SVC_HANDLER *&svc_handler, + SVC_HANDLER *&sh_copy, + const ACE_PEER_CONNECTOR_ADDR &remote_addr, + ACE_Time_Value *timeout, + const ACE_PEER_CONNECTOR_ADDR &local_addr, + int reuse_addr, + int flags, + int perms) { ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect_svc_handler"); @@ -136,319 +291,28 @@ ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::open (ACE_Reactor *r, int flag ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::open"); this->reactor (r); this->flags_ = flags; - this->closing_ = 0; return 0; } template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> -ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::ACE_Connector (ACE_Reactor *r, int flags) - : handler_map_ (ACE_CONNECTOR_HANDLER_MAP_SIZE) - , connector_ () - , closing_ (0) - , flags_ (0) - , mutex_ () +ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::ACE_Connector (ACE_Reactor *r, + int flags) { ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::ACE_Connector"); (void) this->open (r, flags); } -template <class SVC_HANDLER> -ACE_Svc_Tuple<SVC_HANDLER>::ACE_Svc_Tuple ( - SVC_HANDLER *sh, - ACE_HANDLE handle, - const void *arg, - long id) - : svc_handler_ (sh), - handle_ (handle), - arg_ (arg), - cancellation_id_ (id), - refcount_ (1) -{ - ACE_TRACE ("ACE_Svc_Tuple<SVC_HANDLER>::ACE_Svc_Tuple"); -} - -template <class SVC_HANDLER> -ACE_Svc_Tuple<SVC_HANDLER>::~ACE_Svc_Tuple (void) -{ -} - -template <class SVC_HANDLER> SVC_HANDLER * -ACE_Svc_Tuple<SVC_HANDLER>::svc_handler (void) -{ - ACE_TRACE ("ACE_Svc_Tuple<SVC_HANDLER>::svc_handler"); - return this->svc_handler_; -} - -template <class SVC_HANDLER> const void * -ACE_Svc_Tuple<SVC_HANDLER>::arg (void) -{ - ACE_TRACE ("ACE_Svc_Tuple<SVC_HANDLER>::arg"); - return this->arg_; -} - -template <class SVC_HANDLER> void -ACE_Svc_Tuple<SVC_HANDLER>::arg (const void *v) -{ - ACE_TRACE ("ACE_Svc_Tuple<SVC_HANDLER>::arg"); - this->arg_ = v; -} - -template <class SVC_HANDLER> ACE_HANDLE -ACE_Svc_Tuple<SVC_HANDLER>::handle (void) -{ - ACE_TRACE ("ACE_Svc_Tuple<SVC_HANDLER>::handle"); - return this->handle_; -} - -template <class SVC_HANDLER> void -ACE_Svc_Tuple<SVC_HANDLER>::handle (ACE_HANDLE h) -{ - ACE_TRACE ("ACE_Svc_Tuple<SVC_HANDLER>::handle"); - this->handle_ = h; -} - -template <class SVC_HANDLER> long -ACE_Svc_Tuple<SVC_HANDLER>::cancellation_id (void) -{ - ACE_TRACE ("ACE_Svc_Tuple<SVC_HANDLER>::cancellation_id"); - return this->cancellation_id_; -} - -template <class SVC_HANDLER> void -ACE_Svc_Tuple<SVC_HANDLER>::cancellation_id (long id) -{ - ACE_TRACE ("ACE_Svc_Tuple<SVC_HANDLER>::cancellation_id"); - this->cancellation_id_ = id; -} - -template <class SVC_HANDLER> long -ACE_Svc_Tuple<SVC_HANDLER>::incr_refcount (void) -{ - ACE_TRACE ("ACE_Svc_Tuple<SVC_HANDLER>::incr_refcount"); - return ++this->refcount_; -} - -template <class SVC_HANDLER> long -ACE_Svc_Tuple<SVC_HANDLER>::decr_refcount (void) -{ - ACE_TRACE ("ACE_Svc_Tuple<SVC_HANDLER>::decr_refcount"); - if (--this->refcount_ > 0) - return this->refcount_; - - ACE_ASSERT (this->refcount_ == 0); - - delete this; - - return 0; -} - -template <class SVC_HANDLER> void -ACE_Svc_Tuple<SVC_HANDLER>::dump (void) const -{ - ACE_TRACE ("ACE_Svc_Tuple<SVC_HANDLER>::dump"); - - ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); - ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("svc_handler_ = %x"), this->svc_handler_)); - ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\narg_ = %x"), this->arg_)); - ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\ncancellation_id_ = %d"), this->cancellation_id_)); - ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); -} - -// This method is called if a connection times out before completing. -// In this case, we call our cleanup_AST() method to cleanup the -// descriptor from the ACE_Connector's table. - -template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int -ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::handle_timeout ( - const ACE_Time_Value &tv, - const void *arg) -{ - ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::handle_timeout"); - AST *ast = 0; - - if (this->cleanup_AST (((AST *) arg)->handle (), - ast) == -1) - { - // Matches the creation time refcount for AST, which is 1 - this->decr_ast_refcount ((AST *) arg); - return -1; - } - else - { - ACE_ASSERT (((AST *) arg) == ast); - - // We may need this seemingly unnecessary assignment to work - // around a bug with MSVC++? - SVC_HANDLER *sh = ast->svc_handler (); - - // Forward to the SVC_HANDLER the <arg> that was passed in as a - // magic cookie during ACE_Connector::connect(). This gives the - // SVC_HANDLER an opportunity to take corrective action (e.g., - // wait a few milliseconds and try to reconnect again. - int result = sh->handle_timeout (tv, ast->arg ()); - - // Matches the creation time refcount for AST, which is 1. - this->decr_ast_refcount (ast); - - if (result == -1) - sh->handle_close (sh->get_handle (), - ACE_Event_Handler::TIMER_MASK); - - return 0; - } -} - -template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int -ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::cleanup_AST ( - ACE_HANDLE handle, - ACE_Svc_Tuple<SVC_HANDLER> *&ast) -{ - ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::cleanup_AST"); - - ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, - ace_mon, - this->mutex_, - -1)); - - // Locate the ACE_Svc_Handler corresponding to the socket - // descriptor. - if (this->handler_map_.unbind (handle, ast) == -1) - { - // Error, entry not found in map. - errno = ENOENT; - return -1; - } - - // Matches incr_refcount () in create_AST () after registering - // with the map. - ast->decr_refcount (); - - // Try to remove from ACE_Timer_Queue but if it's not there we - // ignore the error. - if (this->reactor ()->cancel_timer (ast->cancellation_id ())) - { - // Matches incr_refcount () in create_AST () after registering - // the timer - ast->decr_refcount (); - } - - - ACE_Reactor_Mask m = - ACE_Event_Handler::ALL_EVENTS_MASK | ACE_Event_Handler::DONT_CALL; - - // Remove ACE_HANDLE from ACE_Reactor. - if (this->reactor ()->remove_handler (handle, m) == 0) - { - // Matches incr_refcount () in create_AST () after registering - // with the Reactor. - ast->decr_refcount (); - } - return 0; -} - -// Called when a failure occurs during asynchronous connection -// establishment. Simply delegate all work to this->handle_output(). - -template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int -ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::handle_input (ACE_HANDLE h) -{ - ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::handle_input"); - AST *ast = 0; - - if (this->cleanup_AST (h, ast) != -1) - { - ACE_ASSERT (ast != 0); - ast->svc_handler ()->close (0); - - // Matches the creation time refcount for AST, which is 1 - this->decr_ast_refcount (ast); - } - - return 0; // Already removed from the ACE_Reactor. -} - -// Finalize a connection established in non-blocking mode. When a -// non-blocking connect *succeeds* the descriptor becomes enabled for -// writing... Likewise, it is generally the case that when a -// non-blocking connect *fails* the descriptor becomes enabled for -// reading. - -template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int -ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::handle_output (ACE_HANDLE handle) -{ - ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::handle_output"); - AST *ast = 0; - - if (this->cleanup_AST (handle, ast) == -1) - { - return 0; - } - ACE_ASSERT (ast != 0); // This shouldn't happen! - - // Try to find out if the reactor uses event associations for the - // handles it waits on. If so we need to reset it. - int reset_new_handle = this->reactor ()->uses_event_associations (); - - if (reset_new_handle) - this->connector_.reset_new_handle (handle); - - // Transfer ownership of the ACE_HANDLE to the SVC_HANDLER. - ast->svc_handler ()->set_handle (handle); - - ACE_PEER_CONNECTOR_ADDR raddr; - - // Check to see if we're connected. - if (ast->svc_handler ()->peer ().get_remote_addr (raddr) != -1) - this->activate_svc_handler (ast->svc_handler ()); - else // Somethings gone wrong, so close down... - { -#if defined (ACE_WIN32) - // ACE_DEBUG ((LM_DEBUG, "errno %d; Sleeping to retry get_remote_addr\n", errno)); - // Win32 (at least prior to Windows 2000) has a timing problem. - // If you check to see if the connection has completed too fast, - // it will fail - so wait 35 milliseconds to let it catch up. - ACE_Time_Value tv (0, ACE_NON_BLOCKING_BUG_DELAY); - ACE_OS::sleep (tv); - if (ast->svc_handler ()->peer ().get_remote_addr (raddr) != -1) - this->activate_svc_handler (ast->svc_handler ()); - else // do the svc handler close below... -#endif /* ACE_WIN32 */ - ast->svc_handler ()->close (0); - } - // Matches the creation time refcount for AST, which is 1 - this->decr_ast_refcount (ast); - return 0; -} - template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int -ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::resume_handler (void) -{ - return ACE_Event_Handler::ACE_EVENT_HANDLER_NOT_RESUMED; -} - -template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int -ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::handle_exception (ACE_HANDLE h) -{ - ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::handle_exception"); - - // On Win32, the except mask must also be set for asynchronous - // connects. - - return this->handle_output (h); -} - -// Initiate connection to peer. - -template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int -ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect ( - SVC_HANDLER *&sh, - const ACE_PEER_CONNECTOR_ADDR &remote_addr, - const ACE_Synch_Options &synch_options, - const ACE_PEER_CONNECTOR_ADDR &local_addr, - int reuse_addr, - int flags, - int perms) -{ +ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect +(SVC_HANDLER *&sh, + const ACE_PEER_CONNECTOR_ADDR &remote_addr, + const ACE_Synch_Options &synch_options, + const ACE_PEER_CONNECTOR_ADDR &local_addr, + int reuse_addr, + int flags, + int perms) +{ + // Initiate connection to peer. return this->connect_i (sh, 0, remote_addr, @@ -460,16 +324,17 @@ ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect ( } template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int -ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect ( - SVC_HANDLER *&sh, - SVC_HANDLER *&sh_copy, - const ACE_PEER_CONNECTOR_ADDR &remote_addr, - const ACE_Synch_Options &synch_options, - const ACE_PEER_CONNECTOR_ADDR &local_addr, - int reuse_addr, - int flags, - int perms) -{ +ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect +(SVC_HANDLER *&sh, + SVC_HANDLER *&sh_copy, + const ACE_PEER_CONNECTOR_ADDR &remote_addr, + const ACE_Synch_Options &synch_options, + const ACE_PEER_CONNECTOR_ADDR &local_addr, + int reuse_addr, + int flags, + int perms) +{ + // Initiate connection to peer. return this->connect_i (sh, &sh_copy, remote_addr, @@ -481,15 +346,15 @@ ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect ( } template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int -ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect_i ( - SVC_HANDLER *&sh, - SVC_HANDLER **sh_copy, - const ACE_PEER_CONNECTOR_ADDR &remote_addr, - const ACE_Synch_Options &synch_options, - const ACE_PEER_CONNECTOR_ADDR &local_addr, - int reuse_addr, - int flags, - int perms) +ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect_i +(SVC_HANDLER *&sh, + SVC_HANDLER **sh_copy, + const ACE_PEER_CONNECTOR_ADDR &remote_addr, + const ACE_Synch_Options &synch_options, + const ACE_PEER_CONNECTOR_ADDR &local_addr, + int reuse_addr, + int flags, + int perms) { ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect_i"); @@ -526,60 +391,57 @@ ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect_i ( flags, perms); + // Activate immediately if we are connected. + if (result != -1) + return this->activate_svc_handler (sh); + // Delegate to connection strategy. - if (result == -1) + if (use_reactor && errno == EWOULDBLOCK) { - if (use_reactor && errno == EWOULDBLOCK) - { - // If the connection hasn't completed and we are using - // non-blocking semantics then register ourselves with the - // ACE_Reactor so that it will call us back when the - // connection is complete or we timeout, whichever comes - // first... - int result; - - if (sh_copy == 0) - result = this->create_AST (sh, synch_options); - else - result = this->create_AST (*sh_copy, synch_options); - - // If for some reason the <create_AST> call failed, then - // <errno> will be set to the new error. If the call - // succeeds, however, we need to make sure that <errno> - // remains set to <EWOULDBLOCK>. - if (result == 0) - errno = EWOULDBLOCK; - } + // If the connection hasn't completed and we are using + // non-blocking semantics then register + // ACE_NonBlocking_Connect_Handler with the ACE_Reactor so that + // it will call us back when the connection is complete or we + // timeout, whichever comes first... + int result; + + if (sh_copy == 0) + result = this->nonblocking_connect (sh, synch_options); else + result = this->nonblocking_connect (*sh_copy, synch_options); + + // If for some reason the <nonblocking_connect> call failed, then <errno> + // will be set to the new error. If the call succeeds, however, + // we need to make sure that <errno> remains set to + // <EWOULDBLOCK>. + if (result == 0) + errno = EWOULDBLOCK; + } + else + { + // Save/restore errno. + ACE_Errno_Guard error (errno); + // Make sure to close down the service handler to avoid handle + // leaks. + if (sh_copy == 0) { - // Save/restore errno. - ACE_Errno_Guard error (errno); - // Make sure to close down the service handler to avoid - // handle leaks. - if (sh_copy == 0) - { - if (sh) - sh->close (0); - } - else if (*sh_copy) - (*sh_copy)->close (0); + if (sh) + sh->close (0); } - return -1; + else if (*sh_copy) + (*sh_copy)->close (0); } - else - // Activate immediately if we are connected. - return this->activate_svc_handler (sh); -} -// Initiate connection to peer. + return -1; +} template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int -ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect_n ( - size_t n, - SVC_HANDLER *sh[], - ACE_PEER_CONNECTOR_ADDR remote_addrs[], - ACE_TCHAR *failed_svc_handlers, - const ACE_Synch_Options &synch_options) +ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect_n +(size_t n, + SVC_HANDLER *sh[], + ACE_PEER_CONNECTOR_ADDR remote_addrs[], + ACE_TCHAR *failed_svc_handlers, + const ACE_Synch_Options &synch_options) { int result = 0; @@ -607,266 +469,218 @@ template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::cancel (SVC_HANDLER *sh) { ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::cancel"); - MAP_ITERATOR mi (this->handler_map_); - for (MAP_ENTRY *me = 0; - mi.next (me) != 0; - mi.advance ()) - if (me->int_id_->svc_handler () == sh) - { - AST *ast = 0; + ACE_Event_Handler *handler = + this->reactor ()->handler (sh->get_handle ()); - if (this->cleanup_AST (me->ext_id_, ast) != -1) - this->decr_ast_refcount (ast); + if (handler == 0) + return -1; - return 0; - } + ACE_Event_Handler_var safe_handler (handler); - return -1; -} + NBCH *nbch = + ACE_dynamic_cast (NBCH *, handler); -// Register the pending SVC_HANDLER with the map so that it can be -// activated later on when the connection complets. + if (nbch == 0) + return -1; + + nbch->close (); + + return 0; +} template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int -ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::create_AST ( - SVC_HANDLER *sh, - const ACE_Synch_Options &synch_options) +ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::nonblocking_connect +(SVC_HANDLER *sh, + const ACE_Synch_Options &synch_options) { - ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::create_AST"); + ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::nonblocking_connect"); + + // Must have a valid Reactor for non-blocking connects to work. + if (this->reactor () == 0) + return -1; - ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, - ace_mon, - this->mutex_, - -1)); + // Register the pending SVC_HANDLER so that it can be activated + // later on when the connection completes. ACE_HANDLE handle = sh->get_handle (); - AST *ast; - - // AST is created with a refcount - ACE_NEW_RETURN (ast, - AST (sh, - handle, - synch_options.arg (), -1), + long timer_id = -1; + ACE_Time_Value *tv = 0; + NBCH *nbch = 0; + + ACE_NEW_RETURN (nbch, + NBCH (*this, + sh, + -1), -1); - // Register this with the reactor for connection events. - ACE_Reactor_Mask mask = ACE_Event_Handler::CONNECT_MASK; + ACE_Event_Handler_var safe_nbch (nbch); - // Bind ACE_Svc_Tuple with the ACE_HANDLE we're trying to connect. - if (this->handler_map_.bind (handle, ast) == -1) - goto fail1; - - // Increment the refcount of the AST to indicate registration with - // the map. - ast->incr_refcount (); + // Exclusive access to the Reactor. + ACE_GUARD_RETURN (ACE_Lock, ace_mon, this->reactor ()->lock (), -1); + // Register handle with the reactor for connection events. + ACE_Reactor_Mask mask = ACE_Event_Handler::CONNECT_MASK; if (this->reactor ()->register_handler (handle, - this, + nbch, mask) == -1) - goto fail2; - - // Increment the refcount of the AST. This increment is for access - // from the Reactor. Though we register <this> with the Reactor, - // every dispatch from the Reactor actually looks for <ast> and - // hence the refcount increment. - (void) ast->incr_refcount (); - - { - // If we're starting connection under timer control then we need to - // schedule a timeout with the ACE_Reactor. - ACE_Time_Value *tv = - ACE_const_cast (ACE_Time_Value *, - synch_options.time_value ()); - if (tv != 0) - { - int cancellation_id = - this->reactor ()->schedule_timer - (this, - (const void *) ast, - *tv); - if (cancellation_id == -1) - goto fail3; - - // Increment the refcount of the AST. This increment is for access - // from the timer queue. The same argument used for Rector - // registration holds true here too. - (void) ast->incr_refcount (); - - ast->cancellation_id (cancellation_id); - return 0; - } - } - return 0; // Ok, everything worked just fine... + goto reactor_registration_failure; + + // Add handle to non-blocking handle set. + this->non_blocking_handles ().set_bit (handle); + + // If we're starting connection under timer control then we need to + // schedule a timeout with the ACE_Reactor. + tv = ACE_const_cast (ACE_Time_Value *, + synch_options.time_value ()); + if (tv == 0) + return 0; + + timer_id = + this->reactor ()->schedule_timer (nbch, + synch_options.arg (), + *tv); + if (timer_id == -1) + goto timer_registration_failure; + + // Remember timer id. + nbch->timer_id (timer_id); + + // Everything was successful. + return 0; // Undo previous actions using the ol' "goto label and fallthru" // trick... -fail3: - this->reactor ()->remove_handler - (this, mask | ACE_Event_Handler::DONT_CALL); - /* FALLTHRU */ -fail2: - this->handler_map_.unbind (handle); + timer_registration_failure: + + // Remove from Reactor. + this->reactor ()->remove_handler (handle, mask); + + // Remove handle from the set of non-blocking handles. + this->non_blocking_handles ().clr_bit (handle); + /* FALLTHRU */ -fail1: + reactor_registration_failure: // Close the svc_handler + sh->close (0); - ast->decr_refcount (); return -1; } -// Terminate the Client ACE_Connector by iterating over any -// unconnected ACE_Svc_Handler's and removing them from the -// ACE_Reactor. Note that we can't call handle_close() back at this -// point since we own these things and we'll just get called -// recursively! - -template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int -ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::close (void) +template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> +ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::~ACE_Connector (void) { - ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::close"); - return this->handle_close (); + ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::~ACE_Connector"); + + this->close (); } -template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int -ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::handle_close (ACE_HANDLE, ACE_Reactor_Mask) +template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> void +ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::initialize_svc_handler +(ACE_HANDLE handle, + SVC_HANDLER *svc_handler) { - ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::handle_close"); - - if (this->reactor () != 0 && this->closing_ == 0) - { - // We're closing down now, so make sure not to call ourselves - // recursively via other calls to handle_close() (e.g., from the - // Timer_Queue). - this->closing_ = 1; - - for (;;) - { - // Create an iterator. - MAP_ITERATOR iterator = this->handler_map_.begin (); - - // If we reach the end of the map, break the loop. - if (iterator == this->handler_map_.end ()) - break; - - // Get the first handle. - ACE_HANDLE handle = (*iterator).ext_id_; - - // Clean it up. - AST *ast = 0; - int r = this->cleanup_AST (handle, ast); + // Try to find out if the reactor uses event associations for the + // handles it waits on. If so we need to reset it. + int reset_new_handle = + this->reactor ()->uses_event_associations (); - // Close the svc_handler. - if (r != -1) - { - ACE_ASSERT (ast != 0); - ast->svc_handler ()->close (0); + if (reset_new_handle) + this->connector_.reset_new_handle (handle); - // Zap the ast. - this->decr_ast_refcount (ast); - } + // Transfer ownership of the ACE_HANDLE to the SVC_HANDLER. + svc_handler->set_handle (handle); + ACE_PEER_CONNECTOR_ADDR raddr; - } + // Check to see if we're connected. + if (svc_handler->peer ().get_remote_addr (raddr) != -1) + this->activate_svc_handler (svc_handler); + else // Somethings gone wrong, so close down... + { +#if defined (ACE_WIN32) + // Win32 (at least prior to Windows 2000) has a timing problem. + // If you check to see if the connection has completed too fast, + // it will fail - so wait 35 milliseconds to let it catch up. + ACE_Time_Value tv (0, ACE_NON_BLOCKING_BUG_DELAY); + ACE_OS::sleep (tv); + if (svc_handler->peer ().get_remote_addr (raddr) != -1) + this->activate_svc_handler (svc_handler); + else // do the svc handler close below... +#endif /* ACE_WIN32 */ + svc_handler->close (0); } - - return 0; } -template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int -ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::fini (void) +template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> void +ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::reactor (ACE_Reactor *reactor) { - ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::fini"); - - // Make sure to call close here since our destructor might not be - // called if we're being dynamically linked via the svc.conf. - this->handler_map_.close (); - - // Make sure we call our handle_close(), not a subclass's! - return ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::handle_close (); + this->reactor_ = reactor; } -// Hook called by the explicit dynamic linking facility. - -template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int -ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::init (int, ACE_TCHAR *[]) +template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> ACE_Reactor * +ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::reactor (void) const { - ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::init"); - return -1; + return this->reactor_; } -template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int -ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::suspend (void) +template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> ACE_Handle_Set & +ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::non_blocking_handles (void) { - ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::suspend"); - return -1; + return this->non_blocking_handles_; } template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int -ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::resume (void) +ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::close (void) { - ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::resume"); - return -1; -} + // If there are no non-blocking handle pending, return immediately. + if (this->non_blocking_handles ().num_set () == 0) + return 0; -template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int -ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::info (ACE_TCHAR **strp, size_t length) const -{ - ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::info"); - ACE_TCHAR buf[BUFSIZ]; + // Exclusive access to the Reactor. + ACE_GUARD_RETURN (ACE_Lock, ace_mon, this->reactor ()->lock (), -1); - ACE_OS::sprintf (buf, - ACE_LIB_TEXT ("%s\t %s"), - ACE_LIB_TEXT ("ACE_Connector"), - ACE_LIB_TEXT ("# connector factory\n")); + // Go through all the non-blocking handles. It is necessary to + // create a new iterator each time because we remove from the handle + // set when we cancel the Svc_Handler. + while (1) + { + ACE_Handle_Set_Iterator iterator (this->non_blocking_handles ()); + ACE_HANDLE handle = iterator (); - if (*strp == 0 && (*strp = ACE_OS::strdup (buf)) == 0) - return -1; - else - ACE_OS::strsncpy (*strp, buf, length); - return ACE_static_cast (int, ACE_OS::strlen (buf)); -} + if (handle == ACE_INVALID_HANDLE) + break; -template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> -ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::~ACE_Connector (void) -{ - ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::~ACE_Connector"); - // We will call our handle_close(), not a subclass's, due to the way - // that C++ destructors work. - this->handle_close (); -} + ACE_Event_Handler *handler = + this->reactor ()->handler (handle); -template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> long -ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::incr_ast_refcount ( - ACE_Svc_Tuple<SVC_HANDLER> *ast) -{ - ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::incr_ast_refcount"); - ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, - ace_mon, - this->mutex_, - -1)); + ACE_ASSERT (handler != 0); - return ast->incr_refcount (); -} + ACE_Event_Handler_var safe_handler (handler); -template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> long -ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::decr_ast_refcount ( - ACE_Svc_Tuple<SVC_HANDLER> *ast) -{ - ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::decr_ast_refcount"); - ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, - ace_mon, - this->mutex_, - -1)); + NBCH *nbch = + ACE_dynamic_cast (NBCH *, handler); - return ast->decr_refcount (); + ACE_ASSERT (nbch != 0); + + SVC_HANDLER *svc_handler = + nbch->svc_handler (); + + // Cancel the non-blocking connection. + this->cancel (svc_handler); + + // Close the associated Svc_Handler. + svc_handler->close (0); + } + + return 0; } -/***********************************************************/ template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int -ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::open (ACE_Reactor *r, int flags) +ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::open (ACE_Reactor *r, + int flags) { ACE_TRACE ("ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::open"); return this->open (r, 0, 0, 0, flags); @@ -874,11 +688,11 @@ ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::open (ACE_Reactor *r, template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::open - (ACE_Reactor *r, - ACE_Creation_Strategy<SVC_HANDLER> *cre_s, - ACE_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2> *conn_s, - ACE_Concurrency_Strategy<SVC_HANDLER> *con_s, - int flags) +(ACE_Reactor *r, + ACE_Creation_Strategy<SVC_HANDLER> *cre_s, + ACE_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2> *conn_s, + ACE_Concurrency_Strategy<SVC_HANDLER> *con_s, + int flags) { ACE_TRACE ("ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::open"); @@ -922,15 +736,15 @@ ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::open this->delete_connect_strategy_ = 0; } - if (conn_s != 0) - this->connect_strategy_ = conn_s; - else if (this->connect_strategy_ == 0) - { - ACE_NEW_RETURN (this->connect_strategy_, - CONNECT_STRATEGY, - -1); - this->delete_connect_strategy_ = 1; - } + if (conn_s != 0) + this->connect_strategy_ = conn_s; + else if (this->connect_strategy_ == 0) + { + ACE_NEW_RETURN (this->connect_strategy_, + CONNECT_STRATEGY, + -1); + this->delete_connect_strategy_ = 1; + } // Initialize the concurrency strategy. @@ -958,17 +772,17 @@ ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::open template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::ACE_Strategy_Connector - (ACE_Reactor *reactor, - ACE_Creation_Strategy<SVC_HANDLER> *cre_s, - ACE_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2> *conn_s, - ACE_Concurrency_Strategy<SVC_HANDLER> *con_s, - int flags) - : creation_strategy_ (0), - delete_creation_strategy_ (0), - connect_strategy_ (0), - delete_connect_strategy_ (0), - concurrency_strategy_ (0), - delete_concurrency_strategy_ (0) +(ACE_Reactor *reactor, + ACE_Creation_Strategy<SVC_HANDLER> *cre_s, + ACE_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2> *conn_s, + ACE_Concurrency_Strategy<SVC_HANDLER> *con_s, + int flags) + : creation_strategy_ (0), + delete_creation_strategy_ (0), + connect_strategy_ (0), + delete_connect_strategy_ (0), + concurrency_strategy_ (0), + delete_concurrency_strategy_ (0) { ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::ACE_Strategy_Connector"); @@ -1014,13 +828,13 @@ ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::make_svc_handler (SVC template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect_svc_handler - (SVC_HANDLER *&sh, - const ACE_PEER_CONNECTOR_ADDR &remote_addr, - ACE_Time_Value *timeout, - const ACE_PEER_CONNECTOR_ADDR &local_addr, - int reuse_addr, - int flags, - int perms) +(SVC_HANDLER *&sh, + const ACE_PEER_CONNECTOR_ADDR &remote_addr, + ACE_Time_Value *timeout, + const ACE_PEER_CONNECTOR_ADDR &local_addr, + int reuse_addr, + int flags, + int perms) { return this->connect_strategy_->connect_svc_handler (sh, remote_addr, @@ -1033,14 +847,14 @@ ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect_svc_handler template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect_svc_handler - (SVC_HANDLER *&sh, - SVC_HANDLER *&sh_copy, - const ACE_PEER_CONNECTOR_ADDR &remote_addr, - ACE_Time_Value *timeout, - const ACE_PEER_CONNECTOR_ADDR &local_addr, - int reuse_addr, - int flags, - int perms) +(SVC_HANDLER *&sh, + SVC_HANDLER *&sh_copy, + const ACE_PEER_CONNECTOR_ADDR &remote_addr, + ACE_Time_Value *timeout, + const ACE_PEER_CONNECTOR_ADDR &local_addr, + int reuse_addr, + int flags, + int perms) { return this->connect_strategy_->connect_svc_handler (sh, sh_copy, diff --git a/ace/Connector.h b/ace/Connector.h index 8fd528e383a..9961cef2d93 100644 --- a/ace/Connector.h +++ b/ace/Connector.h @@ -15,35 +15,55 @@ #include "ace/pre.h" -#include "ace/Service_Object.h" +#include "ace/Event_Handler.h" #if !defined (ACE_LACKS_PRAGMA_ONCE) # pragma once #endif /* ACE_LACKS_PRAGMA_ONCE */ -#include "ace/Map_Manager.h" #include "ace/Strategies_T.h" #include "ace/Synch_Options.h" - /** - * @class ACE_Svc_Tuple + * @class ACE_Connector_Base * - * @brief Holds the ACE_Svc_Handler and its argument and - * <ACE_Timer_Handle> until an asynchronous connection completes. + * @brief This base interface allows ACE_NonBlocking_Connect_Handler + * to only care about the SVC_HANDLER template parameter of the + * ACE_Connector. Otherwise, ACE_NonBlocking_Connect_Handler would + * have to be configured with all the template parameters that + * ACE_Connector is configured with. + */ +template <class SVC_HANDLER> +class ACE_Connector_Base +{ +public: + + /// Initialize the Svc_Handler. + virtual void initialize_svc_handler (ACE_HANDLE handle, + SVC_HANDLER *svc_handler) = 0; + + /// Return the handle set representing the non-blocking connects in + /// progress. + virtual ACE_Handle_Set &non_blocking_handles (void) = 0; +}; + +/** + * @class ACE_NonBlocking_Connect_Handler * - * This is a no-brainer... + * @brief Performs non-blocking connects on behalf of the Connector. */ template <class SVC_HANDLER> -class ACE_Svc_Tuple +class ACE_NonBlocking_Connect_Handler : public ACE_Event_Handler { public: - // = Initialization methods. - ACE_Svc_Tuple (SVC_HANDLER *, - ACE_HANDLE, - const void * = 0, - long timer_id = -1); + // Constructor. + ACE_NonBlocking_Connect_Handler (ACE_Connector_Base<SVC_HANDLER> &connector, + SVC_HANDLER *, + long timer_id); + + /// Close up and return underlying SVC_HANDLER *. + SVC_HANDLER *close (void); /// Get SVC_HANDLER. SVC_HANDLER *svc_handler (void); @@ -55,25 +75,31 @@ public: /// Set handle. void handle (ACE_HANDLE); - // = Get/set argument. - /// Get argument. - const void *arg (void); + // = Set/get timer id. + /// Get timer id. + long timer_id (void); + + /// Set timer id. + void timer_id (long timer_id); - /// Set argument. - void arg (const void *); + /// Called by ACE_Reactor when asynchronous connections fail. + virtual int handle_input (ACE_HANDLE); - // = Set/get timer cancellation handle. - /// Get cancellation id. - long cancellation_id (void); + /// Called by ACE_Reactor when asynchronous connections succeed. + virtual int handle_output (ACE_HANDLE); - /// Set cancellation id. - void cancellation_id (long timer_id); + /// Called by ACE_Reactor when asynchronous connections suceeds (on + /// some platforms only). + virtual int handle_exception (ACE_HANDLE fd); - /// Increment and decrement refcount within the context of the lock - /// on the ACE_Connector - long incr_refcount (void); + /// This method is called if a connection times out before + /// completing. + virtual int handle_timeout (const ACE_Time_Value &tv, + const void *arg); - long decr_refcount (void); + /// Should Reactor resume us if we have been suspended before the + /// upcall? + virtual int resume_handler (void); /// Dump the state of an object. void dump (void) const; @@ -81,27 +107,16 @@ public: /// Declare the dynamic allocation hooks. ACE_ALLOC_HOOK_DECLARE; -protected: - /// Prevent direct deletion - ~ACE_Svc_Tuple (void); - private: - /// Associated SVC_HANDLER. - SVC_HANDLER *svc_handler_; - /// IPC <HANDLE> that we are trying to connect. - ACE_HANDLE handle_; + /// Connector base. + ACE_Connector_Base<SVC_HANDLER> &connector_; - /// Associated argument. - const void *arg_; - - /// Associated cancellation id. - long cancellation_id_; + /// Associated SVC_HANDLER. + SVC_HANDLER *svc_handler_; - /// Reference count manipulated within the context of the connector - /// lock. - /// @@ TODO: Things will change after 5.3 goes out of the way. - long refcount_; + /// Associated timer id. + long timer_id_; }; /** @@ -110,22 +125,17 @@ private: * @brief Generic factory for actively connecting clients and creating * service handlers (SVC_HANDLERs). * - * Implements the strategy for actively establishing connections - * with clients. An ACE_Connector is parameterized by concrete - * types that conform to the interfaces of PEER_CONNECTOR and - * SVC_HANDLER. The PEER_CONNECTOR is instantiated with a - * transport mechanism that passively establishes connections. - * The SVC_HANDLER is instantiated with a concrete type that - * performs the application-specific service. An ACE_Connector - * inherits from ACE_Service_Object, which in turn inherits from - * ACE_Event_Handler. This enables the ACE_Reactor to dispatch - * the ACE_Connector's handle_output method when connections - * complete asynchronously. The handle_output method performs - * the connector's active connection establishment and service - * activation strategy. + * Implements the strategy for actively establishing connections with + * clients. An ACE_Connector is parameterized by concrete types that + * conform to the interfaces of PEER_CONNECTOR and SVC_HANDLER. The + * PEER_CONNECTOR is instantiated with a transport mechanism that + * actively establishes connections. The SVC_HANDLER is instantiated + * with a concrete type that performs the application-specific + * service. Both blocking and non-blocking connects are supported. + * Further, non-blocking connects support timeouts. */ template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> -class ACE_Connector : public ACE_Service_Object +class ACE_Connector : public ACE_Connector_Base<SVC_HANDLER> { public: @@ -135,14 +145,13 @@ public: typedef SVC_HANDLER handler_type; typedef ACE_TYPENAME SVC_HANDLER::stream_type stream_type; - // typedef ACE_TYPENAME ACE_PEER_CONNECTOR_ADDR PEER_ADDR; #if defined (ACE_HAS_TYPENAME_KEYWORD) typedef ACE_PEER_CONNECTOR_ADDR ACE_PEER_ADDR_TYPEDEF; #endif /* ACE_HAS_TYPENAME_KEYWORD */ typedef ACE_TYPENAME _ACE_PEER_CONNECTOR::PEER_ADDR - ACE_TYPENAME_ACE_PEER_CONNECTOR_PEER_ADDR; + ACE_TYPENAME_ACE_PEER_CONNECTOR_PEER_ADDR; /** * Initialize a connector. @a flags indicates how <SVC_HANDLER>'s @@ -182,7 +191,7 @@ public: const ACE_PEER_CONNECTOR_ADDR &remote_addr, const ACE_Synch_Options &synch_options = ACE_Synch_Options::defaults, const ACE_PEER_CONNECTOR_ADDR &local_addr - = (ACE_TYPENAME_ACE_PEER_CONNECTOR_PEER_ADDR &) ACE_PEER_CONNECTOR_ADDR_ANY, + = (ACE_TYPENAME_ACE_PEER_CONNECTOR_PEER_ADDR &) ACE_PEER_CONNECTOR_ADDR_ANY, int reuse_addr = 0, int flags = O_RDWR, int perms = 0); @@ -202,7 +211,7 @@ public: const ACE_PEER_CONNECTOR_ADDR &remote_addr, const ACE_Synch_Options &synch_options = ACE_Synch_Options::defaults, const ACE_PEER_CONNECTOR_ADDR &local_addr - = (ACE_TYPENAME_ACE_PEER_CONNECTOR_PEER_ADDR &) ACE_PEER_CONNECTOR_ADDR_ANY, + = (ACE_TYPENAME_ACE_PEER_CONNECTOR_PEER_ADDR &) ACE_PEER_CONNECTOR_ADDR_ANY, int reuse_addr = 0, int flags = O_RDWR, int perms = 0); @@ -230,12 +239,23 @@ public: */ virtual int cancel (SVC_HANDLER *svc_handler); - /// Close down the Connector + /// Close down the Connector. All pending non-blocking connects are + /// canceled and the corresponding svc_handler is closed. virtual int close (void); /// Return the underlying PEER_CONNECTOR object. virtual ACE_PEER_CONNECTOR &connector (void) const; + /// Initialize Svc_Handler. + virtual void initialize_svc_handler (ACE_HANDLE handle, + SVC_HANDLER *svc_handler); + + /// Set Reactor. + virtual void reactor (ACE_Reactor *reactor); + + /// Get Reactor. + virtual ACE_Reactor *reactor (void) const; + /// Dump the state of an object. void dump (void) const; @@ -245,15 +265,7 @@ public: protected: // = Helpful typedefs. - typedef ACE_Svc_Tuple<SVC_HANDLER> - AST; - - typedef ACE_Map_Manager<ACE_HANDLE, ACE_Svc_Tuple<SVC_HANDLER> *, ACE_SYNCH_RW_MUTEX> - MAP_MANAGER; - typedef ACE_Map_Iterator<ACE_HANDLE, ACE_Svc_Tuple<SVC_HANDLER> *, ACE_SYNCH_RW_MUTEX> - MAP_ITERATOR; - typedef ACE_Map_Entry<ACE_HANDLE, ACE_Svc_Tuple<SVC_HANDLER> *> - MAP_ENTRY; + typedef ACE_NonBlocking_Connect_Handler<SVC_HANDLER> NBCH; // = The following two methods define the Connector's strategies for // creating, connecting, and activating SVC_HANDLER's, respectively. @@ -302,60 +314,9 @@ protected: */ virtual int activate_svc_handler (SVC_HANDLER *svc_handler); - /// Called by ACE_Reactor when asynchronous connections fail. - virtual int handle_input (ACE_HANDLE); - - /// Called by ACE_Reactor when asynchronous connections succeed. - virtual int handle_output (ACE_HANDLE); - - virtual int resume_handler (void); - - /// Called by ACE_Reactor when asynchronous connections complete (on - /// some platforms only). - virtual int handle_exception (ACE_HANDLE fd = ACE_INVALID_HANDLE); - - // = Dynamic linking hooks. - /// Default version does no work and returns -1. Must be overloaded - /// by application developer to do anything meaningful. - virtual int init (int argc, ACE_TCHAR *argv[]); - - /// Calls <handle_close> to shutdown the Connector gracefully. - virtual int fini (void); - - /// Default version returns address info in <buf>. - virtual int info (ACE_TCHAR **, size_t) const; - - // = Demultiplexing hooks. - /** - * Terminate the Client ACE_Connector by iterating over any - * unconnected ACE_Svc_Handler's and removing them from the - * ACE_Reactor. - */ - virtual int handle_close (ACE_HANDLE = ACE_INVALID_HANDLE, - ACE_Reactor_Mask = ACE_Event_Handler::ALL_EVENTS_MASK); - - /// This method is called if a connection times out before - /// completing. - virtual int handle_timeout (const ACE_Time_Value &tv, - const void *arg); - - // = Service management hooks. - /// Default version does no work and returns -1. Must be overloaded - /// by application developer to do anything meaningful. - virtual int suspend (void); - - /// Default version does no work and returns -1. Must be overloaded - /// by application developer to do anything meaningful. - virtual int resume (void); - - /// Creates and inserts an ACE_Svc_Tuple into the <handler_map_>. - /// so that we can continue accepting this connection asynchronously. - int create_AST (SVC_HANDLER *, - const ACE_Synch_Options &); - - /// Cleanup the <handler_map_> and returns the appropriate - /// ACE_Svc_Tuple (which is 0 if there is no associated tuple). - int cleanup_AST (ACE_HANDLE handle, AST *&ast); + /// Creates and registers ACE_NonBlocking_Connect_Handler. + int nonblocking_connect (SVC_HANDLER *, + const ACE_Synch_Options &); /// Implementation the <connect> methods. virtual int connect_i (SVC_HANDLER *&svc_handler, @@ -367,24 +328,14 @@ protected: int flags, int perms); + /// Return the handle set representing the non-blocking connects in + /// progress. + ACE_Handle_Set &non_blocking_handles (void); - /// Helper method for manipulating the refcount on AST. It holds the - /// lock before manipulating the refcount on AST. - /// @@ TODO: Needs to be out after 5.3 - long incr_ast_refcount (AST *ast); - long decr_ast_refcount (AST *ast); - - /// Lookup table that maps an I/O handle to a SVC_HANDLER *. - MAP_MANAGER handler_map_; private: - /// This is the concrete connector factory (it keeps no state so the - /// <ACE_Connector> is reentrant). + /// This is the peer connector factory. ACE_PEER_CONNECTOR connector_; - /// Keeps track of whether we are in the process of closing (required - /// to avoid circular calls to <handle_close>). - char closing_; - /** * Flags that indicate how <SVC_HANDLER>'s should be initialized * prior to being activated. Right now, the only flag that is @@ -393,10 +344,12 @@ private: */ int flags_; - /// Lock to synchronize access to the internal state of the - /// connector. - /// @@TODO: This needs to go after 1.3 - ACE_SYNCH_MUTEX mutex_; + /// Pointer to the Reactor. + ACE_Reactor *reactor_; + + /// Handle set representing the non-blocking connects in progress. + ACE_Handle_Set non_blocking_handles_; + }; /** @@ -421,23 +374,23 @@ public: // Useful STL-style traits. typedef ACE_Creation_Strategy<SVC_HANDLER> - creation_strategy_type; + creation_strategy_type; typedef ACE_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2> - connect_strategy_type; + connect_strategy_type; typedef ACE_Concurrency_Strategy<SVC_HANDLER> - concurrency_strategy_type; + concurrency_strategy_type; typedef ACE_Connector <SVC_HANDLER, ACE_PEER_CONNECTOR_2> - base_type; + base_type; // = Define some useful (old style) traits. typedef ACE_Creation_Strategy<SVC_HANDLER> - CREATION_STRATEGY; + CREATION_STRATEGY; typedef ACE_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2> - CONNECT_STRATEGY; + CONNECT_STRATEGY; typedef ACE_Concurrency_Strategy<SVC_HANDLER> - CONCURRENCY_STRATEGY; + CONCURRENCY_STRATEGY; typedef ACE_Connector <SVC_HANDLER, ACE_PEER_CONNECTOR_2> - SUPER; + SUPER; /** * Initialize a connector. <flags> indicates how <SVC_HANDLER>'s diff --git a/ace/Event_Handler.cpp b/ace/Event_Handler.cpp index 11b1c48b38e..aa96116f662 100644 --- a/ace/Event_Handler.cpp +++ b/ace/Event_Handler.cpp @@ -18,8 +18,10 @@ ACE_RCSID(ace, Event_Handler, "$Id$") ACE_Event_Handler::ACE_Event_Handler (ACE_Reactor *r, int p) - : priority_ (p), - reactor_ (r) + : reference_count_ (1) + , priority_ (p) + , reactor_ (r) + , reference_counting_policy_ (Reference_Counting_Policy::DISABLED) { // ACE_TRACE ("ACE_Event_Handler::ACE_Event_Handler"); } @@ -172,6 +174,58 @@ ACE_Event_Handler::reactor (void) const return this->reactor_; } +ACE_Reactor_Timer_Interface * +ACE_Event_Handler::reactor_timer_interface (void) const +{ + ACE_TRACE ("ACE_Event_Handler::reactor_timer_interface"); + return this->reactor_; +} + +ACE_Event_Handler::Reference_Count +ACE_Event_Handler::add_reference (void) +{ + return ++this->reference_count_; +} + +ACE_Event_Handler::Reference_Count +ACE_Event_Handler::remove_reference (void) +{ + Reference_Count result = + --this->reference_count_; + + if (result == 0) + delete this; + + return result; +} + +ACE_Event_Handler::Policy::~Policy (void) +{ +} + +ACE_Event_Handler::Reference_Counting_Policy::Reference_Counting_Policy (Reference_Counting_Policy::Value value) + : value_ (value) +{ +} + +ACE_Event_Handler::Reference_Counting_Policy::Value +ACE_Event_Handler::Reference_Counting_Policy::value (void) const +{ + return this->value_; +} + +void +ACE_Event_Handler::Reference_Counting_Policy::value (ACE_Event_Handler::Reference_Counting_Policy::Value value) +{ + this->value_ = value; +} + +ACE_Event_Handler::Reference_Counting_Policy & +ACE_Event_Handler::reference_counting_policy (void) +{ + return this->reference_counting_policy_; +} + #if !defined (ACE_HAS_WINCE) ACE_THR_FUNC_RETURN @@ -234,6 +288,92 @@ ACE_Event_Handler::remove_stdin_handler (ACE_Reactor *reactor, #endif /* ACE_HAS_WINCE */ +ACE_Event_Handler_var::ACE_Event_Handler_var (void) + : ptr_ (0) +{ +} + +ACE_Event_Handler_var::ACE_Event_Handler_var (ACE_Event_Handler *p) + : ptr_ (p) +{ +} + +ACE_Event_Handler_var::ACE_Event_Handler_var (const ACE_Event_Handler_var &b) + : ptr_ (b.ptr_) +{ + if (this->ptr_ != 0) + { + this->ptr_->add_reference (); + } +} + +ACE_Event_Handler_var::~ACE_Event_Handler_var (void) +{ + if (this->ptr_ != 0) + { + this->ptr_->remove_reference (); + } +} + +ACE_Event_Handler_var & +ACE_Event_Handler_var::operator= (ACE_Event_Handler *p) +{ + if (this->ptr_ == p) + return *this; + + if (this->ptr_ != 0) + this->ptr_->remove_reference (); + + this->ptr_ = p; + + return *this; +} + +ACE_Event_Handler_var & +ACE_Event_Handler_var::operator= (const ACE_Event_Handler_var &b) +{ + if (this->ptr_ != b.ptr_) + { + if (this->ptr_ != 0) + { + this->ptr_->remove_reference (); + } + + if ((this->ptr_ = b.ptr_) != 0) + { + this->ptr_->add_reference (); + } + } + + return *this; +} + +ACE_Event_Handler * +ACE_Event_Handler_var::operator->() const +{ + return this->ptr_; +} + +ACE_Event_Handler * +ACE_Event_Handler_var::handler (void) const +{ + return this->ptr_; +} + +ACE_Event_Handler * +ACE_Event_Handler_var::release (void) +{ + ACE_Event_Handler *old = this->ptr_; + this->ptr_ = 0; + return old; +} + +void +ACE_Event_Handler_var::reset (ACE_Event_Handler *p) +{ + *this = p; +} + ACE_Notification_Buffer::ACE_Notification_Buffer (void) { ACE_TRACE ("ACE_Notification_Buffer::ACE_Notification_Buffer"); diff --git a/ace/Event_Handler.h b/ace/Event_Handler.h index e5f0df47427..c29ee1e44d8 100644 --- a/ace/Event_Handler.h +++ b/ace/Event_Handler.h @@ -21,10 +21,12 @@ #endif /* ACE_LACKS_PRAGMA_ONCE */ #include "ace/OS.h" +#include "ace/Atomic_Op.h" // Forward declaration. class ACE_Message_Block; class ACE_Reactor; +class ACE_Reactor_Timer_Interface; class ACE_Thread_Manager; class ACE_Process; @@ -162,6 +164,9 @@ public: /// Get the event demultiplexors. virtual ACE_Reactor *reactor (void) const; + /// Get only the reactor's timer related interface. + virtual ACE_Reactor_Timer_Interface *reactor_timer_interface (void) const; + #if !defined (ACE_HAS_WINCE) /** * Used to read from non-socket ACE_HANDLEs in our own thread to @@ -190,11 +195,100 @@ public: ACE_Thread_Manager *thr_mgr); #endif /* ACE_HAS_WINCE */ + /// Reference count type. + typedef long Reference_Count; + + /// Increment reference count on the handler. + /** + * This method is called when the handler is registered with the + * Reactor and when the Reactor makes an upcall on the handler. + * Reference count is 1 when the handler is created. + * + * @return Current reference count. + */ + virtual Reference_Count add_reference (void); + + /// Decrement reference count on the handler. + /** + * This method is called when the handler is removed from the + * Reactor and when an upcall made on the handler by the Reactor + * completes. Handler is deleted when the reference count reaches + * 0. + * + * @return Current reference count. + */ + virtual Reference_Count remove_reference (void); + + /** + * @class Policy + * + * @brief Base class for all handler policies. + */ + class ACE_Export Policy + { + + public: + + /// Virtual destructor. + virtual ~Policy (void); + }; + + /** + * @class Reference_Counting_Policy + * + * @brief This policy dictates the reference counting requirements + * for the handler. + * + * This policy allows applications to configure whether it wants the + * Reactor to call add_reference() and remove_reference() during + * registrations, removals, and upcalls. + * + * <B>Default:</B> DISABLED. + */ + class ACE_Export Reference_Counting_Policy : public Policy + { + /// This policy can only be created by the handler. + friend class ACE_Event_Handler; + + public: + + enum Value + { + /// Perform reference counting. + ENABLED, + /// Don't perform reference counting. + DISABLED + }; + + /// Current Reference_Counting_Policy. + Value value (void) const; + + /// Update Reference_Counting_Policy. + void value (Value value); + + private: + + /// Private constructor. + Reference_Counting_Policy (Value value); + + /// The value of the policy. + Value value_; + }; + + /// Current Reference_Counting_Policy. + Reference_Counting_Policy &reference_counting_policy (void); + protected: /// Force ACE_Event_Handler to be an abstract base class. ACE_Event_Handler (ACE_Reactor * = 0, int priority = ACE_Event_Handler::LO_PRIORITY); + /// Typedef for implementation of reference counting. + typedef ACE_Atomic_Op<ACE_SYNCH_MUTEX, Reference_Count> Atomic_Reference_Count; + + /// Reference count. + Atomic_Reference_Count reference_count_; + private: /// Priority of this Event_Handler. @@ -202,6 +296,58 @@ private: /// Pointer to the various event demultiplexors. ACE_Reactor *reactor_; + + /// Reference counting requirements. + Reference_Counting_Policy reference_counting_policy_; +}; + +/** + * @class ACE_Event_Handler_var + * + * @brief Auto pointer like class for Event Handlers. + * + * Used to manage lifecycle of handlers. This class calls + * ACE_Event_Handler::remove_reference() in its destructor. + */ +class ACE_Export ACE_Event_Handler_var +{ + +public: + + /// Default constructor. + ACE_Event_Handler_var (void); + + /// Construct with a handler. + ACE_Event_Handler_var (ACE_Event_Handler *p); + + /// Copy constructor. + ACE_Event_Handler_var (const ACE_Event_Handler_var &b); + + /// Destructor. + ~ACE_Event_Handler_var (void); + + /// Assignment to a handler. + ACE_Event_Handler_var &operator= (ACE_Event_Handler *p); + + /// Assignment to a ACE_Event_Handler_var. + ACE_Event_Handler_var &operator= (const ACE_Event_Handler_var &b); + + /// Overloaded "->". + ACE_Event_Handler *operator-> () const; + + /// Access the handler. + ACE_Event_Handler *handler (void) const; + + /// Release the handler. + ACE_Event_Handler *release (void); + + /// Reset the handler. + void reset (ACE_Event_Handler *p = 0); + +private: + + /// Handler. + ACE_Event_Handler *ptr_; }; /** diff --git a/ace/Proactor.cpp b/ace/Proactor.cpp index 85ea994f9b0..cd708199606 100644 --- a/ace/Proactor.cpp +++ b/ace/Proactor.cpp @@ -164,13 +164,42 @@ ACE_Proactor_Handle_Timeout_Upcall::ACE_Proactor_Handle_Timeout_Upcall (void) } int -ACE_Proactor_Handle_Timeout_Upcall::timeout (TIMER_QUEUE &timer_queue, +ACE_Proactor_Handle_Timeout_Upcall::registration (TIMER_QUEUE &, + ACE_Handler *, + const void *) +{ + return 0; +} + +int +ACE_Proactor_Handle_Timeout_Upcall::preinvoke (TIMER_QUEUE &, + ACE_Handler *, + const void *, + int, + const ACE_Time_Value &, + const void *&) +{ + return 0; +} + +int +ACE_Proactor_Handle_Timeout_Upcall::postinvoke (TIMER_QUEUE &, + ACE_Handler *, + const void *, + int, + const ACE_Time_Value &, + const void *) +{ + return 0; +} + +int +ACE_Proactor_Handle_Timeout_Upcall::timeout (TIMER_QUEUE &, ACE_Handler *handler, const void *act, + int, const ACE_Time_Value &time) { - ACE_UNUSED_ARG (timer_queue); - if (this->proactor_ == 0) ACE_ERROR_RETURN ((LM_ERROR, ACE_LIB_TEXT ("(%t) No Proactor set in ACE_Proactor_Handle_Timeout_Upcall,") @@ -202,10 +231,12 @@ ACE_Proactor_Handle_Timeout_Upcall::timeout (TIMER_QUEUE &timer_queue, int ACE_Proactor_Handle_Timeout_Upcall::cancellation (TIMER_QUEUE &timer_queue, - ACE_Handler *handler) + ACE_Handler *handler, + int dont_call_handle_close) { ACE_UNUSED_ARG (timer_queue); ACE_UNUSED_ARG (handler); + ACE_UNUSED_ARG (dont_call_handle_close); // Do nothing return 0; diff --git a/ace/Proactor.h b/ace/Proactor.h index 53ddb9d1d39..53414a70074 100644 --- a/ace/Proactor.h +++ b/ace/Proactor.h @@ -66,15 +66,38 @@ public: /// Constructor. ACE_Proactor_Handle_Timeout_Upcall (void); + /// This method is called when a timer is registered. + int registration (TIMER_QUEUE &timer_queue, + ACE_Handler *handler, + const void *arg); + + /// This method is called before the timer expires. + int preinvoke (TIMER_QUEUE &timer_queue, + ACE_Handler *handler, + const void *arg, + int recurring_timer, + const ACE_Time_Value &cur_time, + const void *&upcall_act); + /// This method is called when the timer expires. int timeout (TIMER_QUEUE &timer_queue, - ACE_Handler *handler, - const void *arg, - const ACE_Time_Value &cur_time); + ACE_Handler *handler, + const void *arg, + int recurring_timer, + const ACE_Time_Value &cur_time); + + /// This method is called after the timer expires. + int postinvoke (TIMER_QUEUE &timer_queue, + ACE_Handler *handler, + const void *arg, + int recurring_timer, + const ACE_Time_Value &cur_time, + const void *upcall_act); /// This method is called when the timer is canceled. int cancellation (TIMER_QUEUE &timer_queue, - ACE_Handler *handler); + ACE_Handler *handler, + int dont_call_handle_close); /// This method is called when the timer queue is destroyed and the /// timer is still contained in it. @@ -270,7 +293,7 @@ public: /// This method adds the <handle> to the I/O completion port. This /// function is a no-op function for Unix systems and returns 0; virtual int register_handle (ACE_HANDLE handle, - const void *completion_key); + const void *completion_key); // = Timer management. /** @@ -285,12 +308,12 @@ public: * failure (which is guaranteed never to be a valid <timer_id>). */ virtual long schedule_timer (ACE_Handler &handler, - const void *act, - const ACE_Time_Value &time); + const void *act, + const ACE_Time_Value &time); virtual long schedule_repeating_timer (ACE_Handler &handler, - const void *act, - const ACE_Time_Value &interval); + const void *act, + const ACE_Time_Value &interval); // Same as above except <interval> it is used to reschedule the // <handler> automatically. @@ -298,14 +321,14 @@ public: /// This combines the above two methods into one. Mostly for backward /// compatibility. virtual long schedule_timer (ACE_Handler &handler, - const void *act, - const ACE_Time_Value &time, - const ACE_Time_Value &interval); + const void *act, + const ACE_Time_Value &time, + const ACE_Time_Value &interval); /// Cancel all timers associated with this <handler>. Returns number /// of timers cancelled. virtual int cancel_timer (ACE_Handler &handler, - int dont_call_handle_close = 1); + int dont_call_handle_close = 1); /** * Cancel the single <ACE_Handler> that matches the <timer_id> value @@ -317,8 +340,8 @@ public: * wasn't found. */ virtual int cancel_timer (long timer_id, - const void **act = 0, - int dont_call_handle_close = 1); + const void **act = 0, + int dont_call_handle_close = 1); /** * Dispatch a single set of events, waiting up to a specified time limit @@ -616,7 +639,7 @@ class ACE_Export ACE_Proactor public: class Timer_Queue {}; ACE_Proactor (size_t /* number_of_threads */ = 0, - Timer_Queue * /* tq */ = 0) {} + Timer_Queue * /* tq */ = 0) {} virtual int handle_events (void) { return -1; } virtual int handle_events (ACE_Time_Value &) { return -1; } diff --git a/ace/Reactor.h b/ace/Reactor.h index d7f91a6df46..6f8c38f1267 100644 --- a/ace/Reactor.h +++ b/ace/Reactor.h @@ -29,6 +29,9 @@ class ACE_Reactor_Impl; // declaration will not work #include "ace/Timer_Queue.h" +// Contains the timer related interface for the Reactor. +#include "ace/Reactor_Timer_Interface.h" + // Event_Handler.h contains the definition of ACE_Reactor_Mask #include "ace/Event_Handler.h" @@ -44,7 +47,7 @@ class ACE_Reactor_Impl; * its delegation/implementation class, e.g., * <ACE_Select_Reactor> or <ACE_WFMO_Reactor>. */ -class ACE_Export ACE_Reactor +class ACE_Export ACE_Reactor : public ACE_Reactor_Timer_Interface { public: /// Operations on the "ready" mask and the "dispatch" mask. @@ -295,56 +298,98 @@ public: virtual int handle_events (ACE_Time_Value &max_wait_time); virtual int alertable_handle_events (ACE_Time_Value &max_wait_time); - // = Register and remove Handlers. + // = Register and remove handlers. - /// Register <event_handler> with <mask>. The I/O handle will always - /// come from <get_handle> on the <event_handler>. + /** + * Register handler for I/O events. + * + * A handler can be associated with multiple handles. A handle + * cannot be associated with multiple handlers. + * + * The handle will come from ACE_Event_Handler::get_handle(). + * + * Reactor will call ACE_Event_Handler::add_reference() for a new + * handler/handle pair. + * + * If this handler/handle pair has already been registered, any new + * masks specified will be added. In this case, + * ACE_Event_Handler::add_reference() will not be called. + * + * If the registered handler is currently suspended, it will remain + * suspended. When the handler is resumed, it will have the + * existing masks plus any masks added through this call. Handlers + * do not have partial suspensions. + */ virtual int register_handler (ACE_Event_Handler *event_handler, ACE_Reactor_Mask mask); - /// Register <event_handler> with <mask>. The I/O handle is provided - /// through the <io_handle> parameter. + /** + * Register handler for I/O events. + * + * Same as register_handler(ACE_Event_Handler*,ACE_Reactor_Mask), + * except handle is explicitly specified. + */ virtual int register_handler (ACE_HANDLE io_handle, ACE_Event_Handler *event_handler, ACE_Reactor_Mask mask); #if defined (ACE_WIN32) + /** + * Register handler for OS events. + * * Register an <event_handler> that will be notified when - * <event_handle> is signaled. Since no event mask is passed - * through this interface, it is assumed that the <event_handle> - * being passed in is an event handle and not an I/O handle. + * <event_handle> is signaled. * - * Originally this interface was available for all platforms, but - * because ACE_HANDLE is an int on non-Win32 platforms, compilers - * are not able to tell the difference between + * Reactor will call ACE_Event_Handler::add_reference() for a new + * handler/handle pair. + * + * This interface is only available Win32 platforms because + * ACE_HANDLE is an int on non-Win32 platforms and compilers are not + * able to tell the difference between * register_handler(ACE_Event_Handler*,ACE_Reactor_Mask) and - * register_handler(ACE_Event_Handler*,ACE_HANDLE). Therefore, we - * have restricted this method to Win32 only. + * register_handler(ACE_Event_Handler*,ACE_HANDLE). */ virtual int register_handler (ACE_Event_Handler *event_handler, ACE_HANDLE event_handle = ACE_INVALID_HANDLE); + #endif /* ACE_WIN32 */ /** - * Register an <event_handler> that will be notified when - * <event_handle> is signaled. <mask> specifies the network events - * that the <event_handler> is interested in. + * Register handler for I/O events. + * + * Similar to + * register_handler(ACE_HANDLE,ACE_Event_Handler*,ACE_Reactor_Mask), + * except that the user gets to specify the event handle that will + * be used for this registration. This only applies to Reactors + * that use event handles for I/O registrations. */ virtual int register_handler (ACE_HANDLE event_handle, ACE_HANDLE io_handle, ACE_Event_Handler *event_handler, ACE_Reactor_Mask mask); - /// Register <event_handler> with all the <handles> in the <Handle_Set>. + /** + * Register handler for multiple I/O events. + * + * Shorthand for calling + * register_handler(ACE_HANDLE,ACE_Event_Handler*,ACE_Reactor_Mask), + * multiple times for the same <event_handler> and <masks> but + * different <handles>. + */ virtual int register_handler (const ACE_Handle_Set &handles, ACE_Event_Handler *event_handler, - ACE_Reactor_Mask mask); + ACE_Reactor_Mask masks); /** + * Register handler for signals. + * * Register <new_sh> to handle the signal <signum> using the * <new_disp>. Returns the <old_sh> that was previously registered * (if any), along with the <old_disp> of the signal handler. + * + * Reactor will call ACE_Event_Handler::add_reference() on <new_sh> + * and ACE_Event_Handler::remove_reference() on <old_sh>. */ virtual int register_handler (int signum, ACE_Event_Handler *new_sh, @@ -352,78 +397,129 @@ public: ACE_Event_Handler **old_sh = 0, ACE_Sig_Action *old_disp = 0); - /// Registers <new_sh> to handle a set of signals <sigset> using the - /// <new_disp>. - virtual int register_handler (const ACE_Sig_Set &sigset, - ACE_Event_Handler *new_sh, - ACE_Sig_Action *new_disp = 0); - /** - * Removes <event_handler>. Note that the I/O handle will be - * obtained using <get_handle> method of <event_handler> . If - * <mask> includes <ACE_Event_Handler::DONT_CALL> then the - * <handle_close> method of the <event_handler> is not invoked. + * Register handler for multiple signals. + * + * Shorthand for calling + * register_handler(int,ACE_Event_Handler*,ACE_Sig_Action*,ACE_Event_Handler**,ACE_Sig_Action*) + * multiple times for the same <event_handler> and <sig_action> but + * different <signals>. */ - virtual int remove_handler (ACE_Event_Handler *event_handler, - ACE_Reactor_Mask mask); + virtual int register_handler (const ACE_Sig_Set &signals, + ACE_Event_Handler *event_handler, + ACE_Sig_Action *sig_action = 0); /** - * Removes the <ACE_Event_Handler> associated with <handle>. If - * <mask> includes <ACE_Event_Handler::DONT_CALL> then the - * <handle_close> method of the associated <event_handler> is not - * invoked. + * Remove <masks> from <handle> registration. + * + * For I/O handles, <masks> are removed from the Reactor. Unless + * <masks> includes <ACE_Event_Handler::DONT_CALL>, + * ACE_Event_Handler::handle_close() will be called with the <masks> + * that have been removed. If all masks have been removed, + * ACE_Event_Handler::remove_reference() will be called. + * + * For OS handles, the <handle> is removed from the Reactor. Unless + * <masks> includes <ACE_Event_Handler::DONT_CALL>, + * ACE_Event_Handler::handle_close() will be called with + * <ACE_Event_Handler::NULL_MASK>. + * ACE_Event_Handler::remove_reference() will also be called. */ virtual int remove_handler (ACE_HANDLE handle, - ACE_Reactor_Mask mask); + ACE_Reactor_Mask masks); /** - * Removes all handles in <handle_set>. If <mask> == - * <ACE_Event_Handler::DONT_CALL> then the <handle_close> method of - * the associated <event_handler>s is not invoked. + * Remove <masks> from <event_handler> registration. + * + * Same as remove_handler(ACE_HANDLE,ACE_Reactor_Mask), except + * <handle> comes from ACE_Event_Handler::get_handle(). */ - virtual int remove_handler (const ACE_Handle_Set &handle_set, - ACE_Reactor_Mask mask); + virtual int remove_handler (ACE_Event_Handler *event_handler, + ACE_Reactor_Mask masks); /** + * Remove <masks> from multiple <handle> registrations. + * + * Shorthand for calling remove_handler(ACE_HANDLE,ACE_Reactor_Mask) + * multiple times for the same <masks> but different <handles>. + */ + virtual int remove_handler (const ACE_Handle_Set &handles, + ACE_Reactor_Mask masks); + + /** + * Remove signal handler registration. + * * Remove the ACE_Event_Handler currently associated with <signum>. * Install the new disposition (if given) and return the previous - * disposition (if desired by the caller). Returns 0 on success and - * -1 if <signum> is invalid. + * disposition (if desired by the caller). + * + * ACE_Event_Handler::handle_close() will be called with + * <ACE_Event_Handler::SIGNAL_MASK>. + * ACE_Event_Handler::remove_reference() will also be called. */ virtual int remove_handler (int signum, ACE_Sig_Action *new_disp, ACE_Sig_Action *old_disp = 0, int sigkey = -1); - /// Calls <remove_handler> for every signal in <sigset>. + /** + * Remove multiple signal handler registrations. + * + * Shorthand for calling + * remove_handler(int,ACE_Sig_Action*,ACE_Sig_Action*,int) multiple + * times for every signal in <sigset>. + */ virtual int remove_handler (const ACE_Sig_Set &sigset); // = Suspend and resume Handlers. - /// Suspend <event_handler> temporarily. Use - /// <ACE_Event_Handler::get_handle> to get the handle. - virtual int suspend_handler (ACE_Event_Handler *event_handler); - - /// Suspend <handle> temporarily. + /** + * Suspend <handle> temporarily. + */ virtual int suspend_handler (ACE_HANDLE handle); - /// Suspend all <handles> in handle set temporarily. + /** + * Suspend <event_handler> temporarily. + * + * Handle is obtained from ACE_Event_Handler::get_handle(). + */ + virtual int suspend_handler (ACE_Event_Handler *event_handler); + + /** + * Suspend <handles> temporarily. + * + * Shorthand for calling suspend_handler(ACE_HANDLE) with multiple + * <handles>. + */ virtual int suspend_handler (const ACE_Handle_Set &handles); - /// Suspend all <handles> temporarily. + /** + * Suspend all registered handles temporarily. + */ virtual int suspend_handlers (void); - /// Resume <event_handler>. Use <ACE_Event_Handler::get_handle> to - /// get the handle. - virtual int resume_handler (ACE_Event_Handler *event_handler); - - /// Resume <handle>. + /** + * Resume <handle>. + */ virtual int resume_handler (ACE_HANDLE handle); - /// Resume all <handles> in handle set. + /** + * Resume <event_handler>. + * + * Handle is obtained from ACE_Event_Handler::get_handle(). + */ + virtual int resume_handler (ACE_Event_Handler *event_handler); + + /** + * Resume <handles>. + * + * Shorthand for calling resume_handler(ACE_HANDLE) with multiple + * <handles>. + */ virtual int resume_handler (const ACE_Handle_Set &handles); - /// Resume all <handles>. + /** + * Resume all registered handles. + */ virtual int resume_handlers (void); /// Does the reactor allow the application to resume the handle on @@ -435,12 +531,19 @@ public: // = Timer management. /** - * Schedule an ACE_Event_Handler that will expire after an amount + * Schedule a timer event. + * + * Schedule a timer event that will expire after an <delay> amount * of time. The return value of this method, a timer_id value, - * uniquely identifies the event_handler in the ACE_Reactor's - * internal list of timers. - * This timer_id value can be used to cancel the timer - * with the cancel_timer() call. + * uniquely identifies the <event_handler> in the ACE_Reactor's + * internal list of timers. This timer_id value can be used to + * cancel the timer with the cancel_timer() call. + * + * Reactor will call ACE_Event_Handler::add_reference() on the + * handler. After the timeout occurs and + * ACE_Event_Handler::handle_timeout() has completed, the handler + * will be implicitly removed from the Reactor and + * ACE_Event_Handler::remove_reference() will be called. * * @see cancel_timer() * @see reset_timer_interval() @@ -457,33 +560,48 @@ public: const ACE_Time_Value &interval = ACE_Time_Value::zero); /** + * Reset recurring timer interval. + * * Resets the interval of the timer represented by <timer_id> to * <interval>, which is specified in relative time to the current * <gettimeofday>. If <interval> is equal to * <ACE_Time_Value::zero>, the timer will become a non-rescheduling * timer. Returns 0 if successful, -1 if not. + * + * This change will not take effect until the next timeout. */ virtual int reset_timer_interval (long timer_id, const ACE_Time_Value &interval); - /// Cancel all <Event_Handler>s that match the address of - /// <event_handler>. Returns number of handlers cancelled. - virtual int cancel_timer (ACE_Event_Handler *event_handler, - int dont_call_handle_close = 1); - /** - * Cancel the single <Event_Handler> that matches the <timer_id> - * value, which was returned from the schedule method. If arg is - * non-NULL then it will be set to point to the ``magic cookie'' - * argument passed in when the Event_Handler was registered. This - * makes it possible to free up the memory and avoid memory leaks. - * Returns 1 if cancellation succeeded and 0 if the <timer_id> - * wasn't found. + * Cancel timer. + * + * Cancel timer associated with <timer_id> that was returned from + * the schedule_timer() method. If arg is non-NULL then it will be + * set to point to the ``magic cookie'' argument passed in when the + * handler was registered. This makes it possible to free up the + * memory and avoid memory leaks. Returns 1 if cancellation + * succeeded and 0 if the <timer_id> wasn't found. + * + * ACE_Event_Handler::handle_close() will be called with + * <ACE_Event_Handler::TIMER_MASK>. + * ACE_Event_Handler::remove_reference() will also be called. */ virtual int cancel_timer (long timer_id, const void **arg = 0, int dont_call_handle_close = 1); + /** + * Cancel all timers associated with event handler. + * + * Shorthand for calling cancel_timer(long,const void **,int) + * multiple times for all timer associated with <event_handler>. + * + * Returns number of handlers cancelled. + */ + virtual int cancel_timer (ACE_Event_Handler *event_handler, + int dont_call_handle_close = 1); + // = High-level Event_Handler scheduling operations /// Add <masks_to_be_added> to the <event_handler>'s entry. @@ -491,9 +609,9 @@ public: /// Note that this call does not cause the Reactor to re-examine /// its set of handlers - the new masks will be noticed the next /// time the Reactor waits for activity. If there is no other - /// activity expected, or you need immediate re-examination of - /// the wait masks, either call ACE_Reactor::notify after this - /// call, or use ACE_Reactor::register_handler instead. + /// activity expected, or you need immediate re-examination of the + /// wait masks, either call ACE_Reactor::notify after this call, or + /// use ACE_Reactor::register_handler instead. virtual int schedule_wakeup (ACE_Event_Handler *event_handler, ACE_Reactor_Mask masks_to_be_added); @@ -503,8 +621,8 @@ public: /// its set of handlers - the new masks will be noticed the next /// time the Reactor waits for activity. If there is no other /// activity expected, or you need immediate re-examination of - /// the wait masks, either call ACE_Reactor::notify after this - /// call, or use ACE_Reactor::register_handler instead. + /// the wait masks, either call ACE_Reactor::notify after this call, + /// or use ACE_Reactor::register_handler instead. virtual int schedule_wakeup (ACE_HANDLE handle, ACE_Reactor_Mask masks_to_be_added); @@ -531,16 +649,35 @@ public: // = Notification methods. /** - * Notify <event_handler> of <mask> event. The <ACE_Time_Value> - * indicates how long to blocking trying to notify. If <timeout> == - * 0, the caller will block until action is possible, else will wait - * until the relative time specified in <timeout> elapses). Note that - * <mask> can only be one of the pre-defined <ACE_Event_Handler> - * masks, e.g., <READ_MASK>, <WRITE_MASK>, or <EXCEPT_MASK>. + * Dispatch user specified events. + * + * Handler will be dispatched irrespective of whether it is + * registered, not registered, or suspended in the Reactor. + * + * If user specified event is successfully queued, + * ACE_Event_Handler::add_reference() will be called. After the + * notify occurs and the upcall to the handler completes, the + * handler will be implicitly removed from the Reactor and + * ACE_Event_Handler::remove_reference() will be called. No other + * upcall reference counting is done. + * + * For I/O or OS events, the upcall is invoked with an + * ACE_INVALID_HANDLE. + * + * For timer events, the upcall is invoked with a null ACT. + * + * @param event_handler: IN - Handler on which the event will be + * dispatched. + * @param masks: IN - Events to be dispatched - multiple events can + * be OR'd together. + * @param timeout: INOUT - Relative time up to which to wait for + * user specified event to be queued. If tv is 0, wait + * indefinitely. When the call returns, tv has the time remaining + * after the call completes. */ virtual int notify (ACE_Event_Handler *event_handler = 0, - ACE_Reactor_Mask mask = ACE_Event_Handler::EXCEPT_MASK, - ACE_Time_Value *tv = 0); + ACE_Reactor_Mask masks = ACE_Event_Handler::EXCEPT_MASK, + ACE_Time_Value *timeout = 0); /** * Set the maximum number of times that ACE_Reactor will @@ -564,10 +701,14 @@ public: /** * Purge any notifications pending in this reactor for the specified - * <ACE_Event_Handler> object. If <eh> == 0, all notifications for all - * handlers are removed (but not any notifications posted just to wake up - * the reactor itself). Returns the number of notifications purged. - * Returns -1 on error. + * <ACE_Event_Handler> object. If <eh> == 0, all notifications for + * all handlers are removed (but not any notifications posted just + * to wake up the reactor itself). Returns the number of + * notifications purged. Returns -1 on error. + * + * After the purging occurs, the handler will be implicitly removed + * from the Reactor and ACE_Event_Handler::remove_reference() will + * be called. */ virtual int purge_pending_notifications (ACE_Event_Handler *, ACE_Reactor_Mask = ACE_Event_Handler::ALL_EVENTS_MASK); @@ -575,9 +716,21 @@ public: // = Assorted helper methods. /** + * Return the Event_Handler associated with <handle>. Return 0 if + * <handle> is not registered. + * + * Reactor will call ACE_Event_Handler::add_reference() on the + * handler before returning it. + */ + virtual ACE_Event_Handler *handler (ACE_HANDLE handle); + + /** * Check to see if <handle> is associated with a valid Event_Handler * bound to <mask>. Return the <event_handler> associated with this * <handler> if <event_handler> != 0. + * + * Reactor will call ACE_Event_Handler::add_reference() on the + * handler before returning it if <event_handler> != 0. */ virtual int handler (ACE_HANDLE handle, ACE_Reactor_Mask mask, diff --git a/ace/Reactor.i b/ace/Reactor.i index 9324bdcfe43..7f554c99bc7 100644 --- a/ace/Reactor.i +++ b/ace/Reactor.i @@ -51,7 +51,7 @@ ACE_Reactor::run_event_loop (ACE_Time_Value &tv) if (r == 0) return -1; - return r->run_reactor_event_loop + return r->run_reactor_event_loop (tv, ACE_Reactor::check_reconfiguration); } @@ -83,7 +83,7 @@ ACE_Reactor::run_alertable_event_loop (ACE_Time_Value &tv) if (r == 0) return -1; - return r->run_alertable_reactor_event_loop + return r->run_alertable_reactor_event_loop (tv, ACE_Reactor::check_reconfiguration); } @@ -544,6 +544,12 @@ ACE_Reactor::purge_pending_notifications (ACE_Event_Handler *eh, return this->implementation ()->purge_pending_notifications (eh, mask); } +ACE_INLINE ACE_Event_Handler * +ACE_Reactor::handler (ACE_HANDLE handle) +{ + return this->implementation ()->handler (handle); +} + ACE_INLINE int ACE_Reactor::handler (ACE_HANDLE handle, ACE_Reactor_Mask mask, @@ -670,6 +676,3 @@ ACE_Reactor::uses_event_associations (void) { return this->implementation ()->uses_event_associations (); } - - - diff --git a/ace/Reactor_Impl.h b/ace/Reactor_Impl.h index 5ff0d2bcfb0..b730a4df7cf 100644 --- a/ace/Reactor_Impl.h +++ b/ace/Reactor_Impl.h @@ -477,6 +477,12 @@ public: ACE_Reactor_Mask = ACE_Event_Handler::ALL_EVENTS_MASK) = 0; /** + * Return the Event_Handler associated with <handle>. Return 0 if + * <handle> is not registered. + */ + virtual ACE_Event_Handler *handler (ACE_HANDLE handle) = 0; + + /** * Check to see if <handle> is associated with a valid Event_Handler * bound to <mask>. Return the <event_handler> associated with this * <handler> if <event_handler> != 0. diff --git a/ace/Reactor_Timer_Interface.h b/ace/Reactor_Timer_Interface.h new file mode 100644 index 00000000000..f94bedc0993 --- /dev/null +++ b/ace/Reactor_Timer_Interface.h @@ -0,0 +1,50 @@ +/* -*- C++ -*- */ + +//============================================================================= +/** + * @file Reactor_Timer_Interface.h + * + * $Id$ + * + * @author Irfan Pyarali <irfan@oomworks.com> + */ +//============================================================================= + +#ifndef ACE_REACTOR_TIMER_INTERFACE_H +#define ACE_REACTOR_TIMER_INTERFACE_H +#include "ace/pre.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +class ACE_Event_Handler; + +/** + * @class ACE_Reactor_Timer_Interface + * + * @brief Interface for timer related methods on the Reactor. + */ +class ACE_Export ACE_Reactor_Timer_Interface +{ +public: + + virtual long schedule_timer (ACE_Event_Handler *event_handler, + const void *arg, + const ACE_Time_Value &delay, + const ACE_Time_Value &interval = ACE_Time_Value::zero) = 0; + + virtual int reset_timer_interval (long timer_id, + const ACE_Time_Value &interval) = 0; + + virtual int cancel_timer (long timer_id, + const void **arg = 0, + int dont_call_handle_close = 1) = 0; + + virtual int cancel_timer (ACE_Event_Handler *event_handler, + int dont_call_handle_close = 1) = 0; + +}; + +#include "ace/post.h" +#endif /* ACE_REACTOR_TIMER_INTERFACE_H */ diff --git a/ace/Select_Reactor_Base.cpp b/ace/Select_Reactor_Base.cpp index f0e71bcffc3..af18c5bc97f 100644 --- a/ace/Select_Reactor_Base.cpp +++ b/ace/Select_Reactor_Base.cpp @@ -207,25 +207,44 @@ ACE_Select_Reactor_Handler_Repository::bind (ACE_HANDLE handle, if (this->invalid_handle (handle)) return -1; + // Is this handle already in the Reactor? + int existing_handle = 0; + #if defined (ACE_WIN32) + int assigned_slot = -1; for (ssize_t i = 0; i < this->max_handlep1_; i++) { - // Found it, so let's just reuse this location. + // If handle is already registered. if (ACE_SELECT_REACTOR_HANDLE (i) == handle) { + // Cannot use a different handler for an existing handle. + if (ACE_SELECT_REACTOR_EVENT_HANDLER (this, i) != + event_handler) + return -1; + + // Remember location. assigned_slot = i; + + // Remember that this handle is already registered in the + // Reactor. + existing_handle = 1; + + // We can stop looking now. break; } - // Here's the first free slot, so let's take it. - else if (ACE_SELECT_REACTOR_HANDLE (i) == ACE_INVALID_HANDLE - && assigned_slot == -1) - assigned_slot = i; + else + // Here's the first free slot, so let's take it. + if (ACE_SELECT_REACTOR_HANDLE (i) == ACE_INVALID_HANDLE && + assigned_slot == -1) + { + assigned_slot = i; + } } if (assigned_slot > -1) - // We found a free spot, let's reuse it. + // We found a spot. { ACE_SELECT_REACTOR_HANDLE (assigned_slot) = handle; ACE_SELECT_REACTOR_EVENT_HANDLER (this, assigned_slot) = event_handler; @@ -243,11 +262,28 @@ ACE_Select_Reactor_Handler_Repository::bind (ACE_HANDLE handle, errno = ENOMEM; return -1; } + #else + + // Check if this handle is already registered. + if (ACE_SELECT_REACTOR_HANDLE (this, handle) != + ACE_INVALID_HANDLE) + { + // Cannot use a different handler for an existing handle. + if (ACE_SELECT_REACTOR_EVENT_HANDLER (this, handle) != + event_handler) + return -1; + + // Remember that this handle is already registered in the + // Reactor. + existing_handle = 1; + } + ACE_SELECT_REACTOR_EVENT_HANDLER (this, handle) = event_handler; if (this->max_handlep1_ < handle + 1) this->max_handlep1_ = handle + 1; + #endif /* ACE_WIN32 */ if (this->select_reactor_.is_suspended_i (handle)) @@ -270,15 +306,18 @@ ACE_Select_Reactor_Handler_Repository::bind (ACE_HANDLE handle, this->select_reactor_.state_changed_ = 1; } - /* - // @@NOTE: We used to do this in earlier versions of ACE+TAO. But - // this is totally wrong.. - // Clear any suspend masks for it too. - this->select_reactor_.bit_ops (handle, - mask, - this->select_reactor_.suspend_set_, - ACE_Reactor::CLR_MASK); - */ + // If new entry, call add_reference() if needed. + if (!existing_handle) + { + int requires_reference_counting = + event_handler->reference_counting_policy ().value () == + ACE_Event_Handler::Reference_Counting_Policy::ENABLED; + + if (requires_reference_counting) + { + event_handler->add_reference (); + } + } return 0; } @@ -292,9 +331,9 @@ ACE_Select_Reactor_Handler_Repository::unbind (ACE_HANDLE handle, ACE_TRACE ("ACE_Select_Reactor_Handler_Repository::unbind"); size_t slot; - ACE_Event_Handler *eh = this->find (handle, &slot); + ACE_Event_Handler *event_handler = this->find (handle, &slot); - if (eh == 0) + if (event_handler == 0) return -1; // Clear out the <mask> bits in the Select_Reactor's wait_set. @@ -314,11 +353,6 @@ ACE_Select_Reactor_Handler_Repository::unbind (ACE_HANDLE handle, // keep going or if it needs to reconsult select(). this->select_reactor_.state_changed_ = 1; - // Close down the <Event_Handler> unless we've been instructed not - // to. - if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::DONT_CALL) == 0) - eh->handle_close (handle, mask); - // If there are no longer any outstanding events on this <handle> // then we can totally shut down the Event_Handler. @@ -331,14 +365,18 @@ ACE_Select_Reactor_Handler_Repository::unbind (ACE_HANDLE handle, || this->select_reactor_.suspend_set_.wr_mask_.is_set (handle) || this->select_reactor_.suspend_set_.ex_mask_.is_set (handle)); - if (!has_any_wait_mask - && !has_any_suspend_mask - && (this->find (handle, &slot) == eh)) -#if defined (ACE_WIN32) + int complete_removal = 0; + + if (!has_any_wait_mask && !has_any_suspend_mask) { + // The handle has been completed removed. + complete_removal = 1; + ACE_SELECT_REACTOR_HANDLE (slot) = ACE_INVALID_HANDLE; ACE_SELECT_REACTOR_EVENT_HANDLER (this, slot) = 0; +#if defined (ACE_WIN32) + if (this->max_handlep1_ == (int) slot + 1) { // We've deleted the last entry (i.e., i + 1 == the current @@ -355,43 +393,60 @@ ACE_Select_Reactor_Handler_Repository::unbind (ACE_HANDLE handle, this->max_handlep1_ = i + 1; } - } + #else - { - ACE_SELECT_REACTOR_EVENT_HANDLER (this, handle) = 0; - if (this->max_handlep1_ == handle + 1) - { - // We've deleted the last entry, so we need to figure out - // the last valid place in the array that is worth looking - // at. - ACE_HANDLE wait_rd_max = this->select_reactor_.wait_set_.rd_mask_.max_set (); - ACE_HANDLE wait_wr_max = this->select_reactor_.wait_set_.wr_mask_.max_set (); - ACE_HANDLE wait_ex_max = this->select_reactor_.wait_set_.ex_mask_.max_set (); - - ACE_HANDLE suspend_rd_max = this->select_reactor_.suspend_set_.rd_mask_.max_set (); - ACE_HANDLE suspend_wr_max = this->select_reactor_.suspend_set_.wr_mask_.max_set (); - ACE_HANDLE suspend_ex_max = this->select_reactor_.suspend_set_.ex_mask_.max_set (); - - // Compute the maximum of six values. - this->max_handlep1_ = wait_rd_max; - if (this->max_handlep1_ < wait_wr_max) - this->max_handlep1_ = wait_wr_max; - if (this->max_handlep1_ < wait_ex_max) - this->max_handlep1_ = wait_ex_max; - - if (this->max_handlep1_ < suspend_rd_max) - this->max_handlep1_ = suspend_rd_max; - if (this->max_handlep1_ < suspend_wr_max) - this->max_handlep1_ = suspend_wr_max; - if (this->max_handlep1_ < suspend_ex_max) - this->max_handlep1_ = suspend_ex_max; - - this->max_handlep1_++; - } - } + if (this->max_handlep1_ == handle + 1) + { + // We've deleted the last entry, so we need to figure out + // the last valid place in the array that is worth looking + // at. + ACE_HANDLE wait_rd_max = this->select_reactor_.wait_set_.rd_mask_.max_set (); + ACE_HANDLE wait_wr_max = this->select_reactor_.wait_set_.wr_mask_.max_set (); + ACE_HANDLE wait_ex_max = this->select_reactor_.wait_set_.ex_mask_.max_set (); + + ACE_HANDLE suspend_rd_max = this->select_reactor_.suspend_set_.rd_mask_.max_set (); + ACE_HANDLE suspend_wr_max = this->select_reactor_.suspend_set_.wr_mask_.max_set (); + ACE_HANDLE suspend_ex_max = this->select_reactor_.suspend_set_.ex_mask_.max_set (); + + // Compute the maximum of six values. + this->max_handlep1_ = wait_rd_max; + if (this->max_handlep1_ < wait_wr_max) + this->max_handlep1_ = wait_wr_max; + if (this->max_handlep1_ < wait_ex_max) + this->max_handlep1_ = wait_ex_max; + + if (this->max_handlep1_ < suspend_rd_max) + this->max_handlep1_ = suspend_rd_max; + if (this->max_handlep1_ < suspend_wr_max) + this->max_handlep1_ = suspend_wr_max; + if (this->max_handlep1_ < suspend_ex_max) + this->max_handlep1_ = suspend_ex_max; + + this->max_handlep1_++; + } + #endif /* ACE_WIN32 */ + } + + int requires_reference_counting = + event_handler->reference_counting_policy ().value () == + ACE_Event_Handler::Reference_Counting_Policy::ENABLED; + + // Close down the <Event_Handler> unless we've been instructed not + // to. + if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::DONT_CALL) == 0) + event_handler->handle_close (handle, mask); + + // Call remove_reference() if the removal is complete and reference + // counting is needed. + if (complete_removal && + requires_reference_counting) + { + event_handler->remove_reference (); + } + return 0; } @@ -466,13 +521,13 @@ ACE_Select_Reactor_Handler_Repository::dump (void) const this->max_handlep1_, this->max_size_)); ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("["))); - ACE_Event_Handler *eh = 0; + ACE_Event_Handler *event_handler = 0; for (ACE_Select_Reactor_Handler_Repository_Iterator iter (this); - iter.next (eh) != 0; + iter.next (event_handler) != 0; iter.advance ()) - ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT (" (eh = %x, eh->handle_ = %d)"), - eh, eh->get_handle ())); + ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT (" (event_handler = %x, event_handler->handle_ = %d)"), + event_handler, event_handler->get_handle ())); ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT (" ]"))); ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); @@ -549,6 +604,18 @@ ACE_Select_Reactor_Notify::purge_pending_notifications (ACE_Event_Handler *eh, ACE_LIB_TEXT ("%p\n"), ACE_LIB_TEXT ("enqueue_head")), -1); + + ACE_Event_Handler *event_handler = eh; + + int requires_reference_counting = + event_handler->reference_counting_policy ().value () == + ACE_Event_Handler::Reference_Counting_Policy::ENABLED; + + if (requires_reference_counting) + { + event_handler->remove_reference (); + } + ++number_purged; } else @@ -696,7 +763,7 @@ ACE_Select_Reactor_Notify::close (void) } int -ACE_Select_Reactor_Notify::notify (ACE_Event_Handler *eh, +ACE_Select_Reactor_Notify::notify (ACE_Event_Handler *event_handler, ACE_Reactor_Mask mask, ACE_Time_Value *timeout) { @@ -707,7 +774,22 @@ ACE_Select_Reactor_Notify::notify (ACE_Event_Handler *eh, if (this->select_reactor_ == 0) return 0; - ACE_Notification_Buffer buffer (eh, mask); + ACE_Event_Handler_var safe_handler; + + if (event_handler) + { + int requires_reference_counting = + event_handler->reference_counting_policy ().value () == + ACE_Event_Handler::Reference_Counting_Policy::ENABLED; + + if (requires_reference_counting) + { + event_handler->add_reference (); + safe_handler = event_handler; + } + } + + ACE_Notification_Buffer buffer (event_handler, mask); #if defined (ACE_HAS_REACTOR_NOTIFICATION_QUEUE) // Artificial scope to limit the duration of the mutex. @@ -765,6 +847,9 @@ ACE_Select_Reactor_Notify::notify (ACE_Event_Handler *eh, if (n == -1) return -1; + // No failures. + safe_handler.release (); + return 0; } @@ -866,7 +951,9 @@ int ACE_Select_Reactor_Notify::dispatch_notify (ACE_Notification_Buffer &buffer) { int result = 0; + #if defined (ACE_HAS_REACTOR_NOTIFICATION_QUEUE) + // Dispatch all messages that are in the <notify_queue_>. { // We acquire the lock in a block to make sure we're not @@ -890,35 +977,8 @@ ACE_Select_Reactor_Notify::dispatch_notify (ACE_Notification_Buffer &buffer) -1); } - // If eh == 0 then another thread is unblocking the - // <ACE_Select_Reactor> to update the <ACE_Select_Reactor>'s - // internal structures. Otherwise, we need to dispatch the - // appropriate handle_* method on the <ACE_Event_Handler> - // pointer we've been passed. - if (buffer.eh_ != 0) - { +#endif /* ACE_HAS_REACTOR_NOTIFICATION_QUEUE */ - switch (buffer.mask_) - { - case ACE_Event_Handler::READ_MASK: - case ACE_Event_Handler::ACCEPT_MASK: - result = buffer.eh_->handle_input (ACE_INVALID_HANDLE); - break; - case ACE_Event_Handler::WRITE_MASK: - result = buffer.eh_->handle_output (ACE_INVALID_HANDLE); - break; - case ACE_Event_Handler::EXCEPT_MASK: - result = buffer.eh_->handle_exception (ACE_INVALID_HANDLE); - break; - default: - // Should we bail out if we get an invalid mask? - ACE_ERROR ((LM_ERROR, ACE_LIB_TEXT ("invalid mask = %d\n"), buffer.mask_)); - } - if (result == -1) - buffer.eh_->handle_close (ACE_INVALID_HANDLE, - ACE_Event_Handler::EXCEPT_MASK); - } -#else // If eh == 0 then another thread is unblocking the // <ACE_Select_Reactor> to update the <ACE_Select_Reactor>'s // internal structures. Otherwise, we need to dispatch the @@ -926,23 +986,30 @@ ACE_Select_Reactor_Notify::dispatch_notify (ACE_Notification_Buffer &buffer) // pointer we've been passed. if (buffer.eh_ != 0) { + ACE_Event_Handler *event_handler = + buffer.eh_; + + int requires_reference_counting = + event_handler->reference_counting_policy ().value () == + ACE_Event_Handler::Reference_Counting_Policy::ENABLED; + switch (buffer.mask_) { case ACE_Event_Handler::READ_MASK: case ACE_Event_Handler::ACCEPT_MASK: - result = buffer.eh_->handle_input (ACE_INVALID_HANDLE); + result = event_handler->handle_input (ACE_INVALID_HANDLE); break; case ACE_Event_Handler::WRITE_MASK: - result = buffer.eh_->handle_output (ACE_INVALID_HANDLE); + result = event_handler->handle_output (ACE_INVALID_HANDLE); break; case ACE_Event_Handler::EXCEPT_MASK: - result = buffer.eh_->handle_exception (ACE_INVALID_HANDLE); + result = event_handler->handle_exception (ACE_INVALID_HANDLE); break; case ACE_Event_Handler::QOS_MASK: - result = buffer.eh_->handle_qos (ACE_INVALID_HANDLE); + result = event_handler->handle_qos (ACE_INVALID_HANDLE); break; case ACE_Event_Handler::GROUP_QOS_MASK: - result = buffer.eh_->handle_group_qos (ACE_INVALID_HANDLE); + result = event_handler->handle_group_qos (ACE_INVALID_HANDLE); break; default: // Should we bail out if we get an invalid mask? @@ -950,12 +1017,16 @@ ACE_Select_Reactor_Notify::dispatch_notify (ACE_Notification_Buffer &buffer) ACE_LIB_TEXT ("invalid mask = %d\n"), buffer.mask_)); } + if (result == -1) - buffer.eh_->handle_close (ACE_INVALID_HANDLE, - ACE_Event_Handler::EXCEPT_MASK); - } + event_handler->handle_close (ACE_INVALID_HANDLE, + ACE_Event_Handler::EXCEPT_MASK); -#endif /* ACE_HAS_REACTOR_NOTIFICATION_QUEUE */ + if (requires_reference_counting) + { + event_handler->remove_reference (); + } + } return 1; } diff --git a/ace/Select_Reactor_T.cpp b/ace/Select_Reactor_T.cpp index 78c3a3ada1f..4873cc0d2b4 100644 --- a/ace/Select_Reactor_T.cpp +++ b/ace/Select_Reactor_T.cpp @@ -343,6 +343,15 @@ ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::register_handler return this->register_handler_i (handles, handler, mask); } +template <class ACE_SELECT_REACTOR_TOKEN> ACE_Event_Handler * +ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::handler + (ACE_HANDLE handle) +{ + ACE_TRACE ("ACE_Select_Reactor_T::handler"); + ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, 0)); + return this->handler_i (handle); +} + template <class ACE_SELECT_REACTOR_TOKEN> int ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::handler (ACE_HANDLE handle, @@ -835,12 +844,28 @@ ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::notify_handle if (event_handler == 0) return; + int reference_counting_required = + event_handler->reference_counting_policy ().value () == + ACE_Event_Handler::Reference_Counting_Policy::ENABLED; + + // Call add_reference() if needed. + if (reference_counting_required) + { + event_handler->add_reference (); + } + int status = (event_handler->*ptmf) (handle); if (status < 0) this->remove_handler_i (handle, mask); else if (status > 0) ready_mask.set_bit (handle); + + // Call remove_reference() if needed. + if (reference_counting_required) + { + event_handler->remove_reference (); + } } // Perform GET, CLR, SET, and ADD operations on the select() @@ -863,9 +888,42 @@ ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::mask_ops { ACE_TRACE ("ACE_Select_Reactor_T::mask_ops"); ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1)); - return this->bit_ops (handle, mask, - this->wait_set_, - ops); + + // If the handle is not suspended, then set the ops on the + // <wait_set_>, otherwise set the <suspend_set_>. + + if (this->is_suspended_i (handle)) + return this->bit_ops (handle, mask, + this->suspend_set_, + ops); + else + return this->bit_ops (handle, mask, + this->wait_set_, + ops); +} + +template <class ACE_SELECT_REACTOR_TOKEN> ACE_Event_Handler * +ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::handler_i + (ACE_HANDLE handle) +{ + ACE_TRACE ("ACE_Select_Reactor_T::handler_i"); + + ACE_Event_Handler *event_handler = + this->handler_rep_.find (handle); + + if (event_handler) + { + int requires_reference_counting = + event_handler->reference_counting_policy ().value () == + ACE_Event_Handler::Reference_Counting_Policy::ENABLED; + + if (requires_reference_counting) + { + event_handler->add_reference (); + } + } + + return event_handler; } // Must be called with locks held. @@ -874,12 +932,13 @@ template <class ACE_SELECT_REACTOR_TOKEN> int ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::handler_i (ACE_HANDLE handle, ACE_Reactor_Mask mask, - ACE_Event_Handler **handler) + ACE_Event_Handler **eh) { ACE_TRACE ("ACE_Select_Reactor_T::handler_i"); - ACE_Event_Handler *h = this->handler_rep_.find (handle); + ACE_Event_Handler *event_handler = + this->handler_rep_.find (handle); - if (h == 0) + if (event_handler == 0) return -1; else { @@ -895,8 +954,20 @@ ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::handler_i return -1; } - if (handler != 0) - *handler = h; + if (eh != 0) + { + *eh = event_handler; + + int requires_reference_counting = + event_handler->reference_counting_policy ().value () == + ACE_Event_Handler::Reference_Counting_Policy::ENABLED; + + if (requires_reference_counting) + { + event_handler->add_reference (); + } + } + return 0; } diff --git a/ace/Select_Reactor_T.h b/ace/Select_Reactor_T.h index ca51ff20d0d..3251a135b54 100644 --- a/ace/Select_Reactor_T.h +++ b/ace/Select_Reactor_T.h @@ -559,6 +559,13 @@ public: virtual int owner (ACE_thread_t *); // = Miscellaneous Handler operations. + + /** + * Return the Event_Handler associated with <handle>. Return 0 if + * <handle> is not registered. + */ + virtual ACE_Event_Handler *handler (ACE_HANDLE handle); + /** * Check to see if <handle> is associated with a valid Event_Handler * bound to <mask>. Return the <eh> associated with this <handler> @@ -635,6 +642,9 @@ protected: virtual int resume_i (ACE_HANDLE handle); /// Implement the public <handler> method. + virtual ACE_Event_Handler *handler_i (ACE_HANDLE handle); + + /// Implement the public <handler> method. virtual int handler_i (ACE_HANDLE handle, ACE_Reactor_Mask, ACE_Event_Handler ** = 0); diff --git a/ace/TP_Reactor.cpp b/ace/TP_Reactor.cpp index 8c58233a391..2e24ce5582a 100644 --- a/ace/TP_Reactor.cpp +++ b/ace/TP_Reactor.cpp @@ -11,7 +11,6 @@ ACE_RCSID(ace, TP_Reactor, "$Id$") - ACE_ALLOC_HOOK_DEFINE (ACE_TP_Reactor) int @@ -39,7 +38,6 @@ ACE_TP_Token_Guard::grab_token (ACE_Time_Value *max_wait_time) ACE_MT (result = this->token_.acquire_read (&ACE_TP_Reactor::no_op_sleep_hook)); } - // Now that this thread owns the token let us make // Check for timeouts and errors. if (result == -1) { @@ -55,7 +53,6 @@ ACE_TP_Token_Guard::grab_token (ACE_Time_Value *max_wait_time) return result; } - int ACE_TP_Token_Guard::acquire_token (ACE_Time_Value *max_wait_time) { @@ -79,7 +76,6 @@ ACE_TP_Token_Guard::acquire_token (ACE_Time_Value *max_wait_time) ACE_MT (result = this->token_.acquire ()); } - // Now that this thread owns the token let us make // Check for timeouts and errors. if (result == -1) { @@ -148,14 +144,14 @@ ACE_TP_Reactor::handle_events (ACE_Time_Value *max_wait_time) // called. ACE_Countdown_Time countdown (max_wait_time); + // // The order of these events is very subtle, modify with care. - + // // Instantiate the token guard which will try grabbing the token for // this thread. ACE_TP_Token_Guard guard (this->token_); - int result = guard.grab_token (max_wait_time); // If the guard is NOT the owner just return the retval @@ -169,161 +165,10 @@ ACE_TP_Reactor::handle_events (ACE_Time_Value *max_wait_time) // Update the countdown to reflect time waiting for the token. countdown.update (); - return this->dispatch_i (max_wait_time, guard); } - -int -ACE_TP_Reactor::remove_handler (ACE_Event_Handler *eh, - ACE_Reactor_Mask mask) -{ - int result = 0; - // Artificial scoping for grabbing and releasing the token - { - ACE_TP_Token_Guard guard (this->token_); - - // Acquire the token - result = guard.acquire_token (); - - if (!guard.is_owner ()) - return result; - - // Call the remove_handler_i () with a DONT_CALL mask. We dont - // want to call the handle_close with the token held. - result = this->remove_handler_i (eh->get_handle (), - mask | ACE_Event_Handler::DONT_CALL); - - if (result == -1) - return -1; - } - - // Close down the <Event_Handler> unless we've been instructed not - // to. - if (result == 0 && (ACE_BIT_ENABLED (mask, ACE_Event_Handler::DONT_CALL) == 0)) - eh->handle_close (ACE_INVALID_HANDLE, mask); - - return 0; -} - -int -ACE_TP_Reactor::remove_handler (ACE_HANDLE handle, - ACE_Reactor_Mask mask) -{ - - ACE_Event_Handler *eh = 0; - int result = 0; - // Artificial scoping for grabbing and releasing the token - { - ACE_TP_Token_Guard guard (this->token_); - - // Acquire the token - result = guard.acquire_token (); - - if (!guard.is_owner ()) - return result; - - size_t slot = 0; - eh = this->handler_rep_.find (handle, &slot); - - if (eh == 0) - return -1; - - // Call the remove_handler_i () with a DONT_CALL mask. We dont - // want to call the handle_close with the token held. - result = this->remove_handler_i (handle, - mask | ACE_Event_Handler::DONT_CALL); - - if (result == -1) - return -1; - } - - // Close down the <Event_Handler> unless we've been instructed not - // to. - // @@ Note: The check for result ==0 may be redundant, but shouldnt - // be a problem. - if (result ==0 && (ACE_BIT_ENABLED (mask, ACE_Event_Handler::DONT_CALL) == 0)) - eh->handle_close (handle, mask); - - return 0; -} - - -int -ACE_TP_Reactor::remove_handler (const ACE_Handle_Set &handles, - ACE_Reactor_Mask m) -{ - // Array of <Event_Handlers> corresponding to <handles> - ACE_Event_Handler **aeh = 0; - - // Allocate memory for the size of the handle set - ACE_NEW_RETURN (aeh, - ACE_Event_Handler *[handles.num_set ()], - -1); - - size_t index = 0; - - // Artificial scoping for grabbing and releasing the token - { - ACE_TP_Token_Guard guard (this->token_); - - // Acquire the token - int result = guard.acquire_token (); - - if (!guard.is_owner ()) - return result; - - ACE_HANDLE h; - - ACE_Handle_Set_Iterator handle_iter (handles); - - while ((h = handle_iter ()) != ACE_INVALID_HANDLE) - { - size_t slot = 0; - ACE_Event_Handler *eh = - this->handler_rep_.find (h, &slot); - - if (this->remove_handler_i (h, - m | ACE_Event_Handler::DONT_CALL) == -1) - { - delete [] aeh; - return -1; - } - - aeh [index] = eh; - index ++; - } - } - - // Close down the <Event_Handler> unless we've been instructed not - // to. - if (ACE_BIT_ENABLED (m, ACE_Event_Handler::DONT_CALL) == 0) - { - for (size_t i = 0; i < index; i++) - aeh[i]->handle_close (ACE_INVALID_HANDLE, m); - } - - delete [] aeh; - return 0; -} - -int -ACE_TP_Reactor::remove_handler (int /*signum*/, - ACE_Sig_Action * /*new_disp*/, - ACE_Sig_Action * /*old_disp*/, - int /*sigkey*/) -{ - ACE_NOTSUP_RETURN (-1); -} - -int -ACE_TP_Reactor::remove_handler (const ACE_Sig_Set & /*sigset*/) -{ - ACE_NOTSUP_RETURN (-1); -} - - int ACE_TP_Reactor::dispatch_i (ACE_Time_Value *max_wait_time, ACE_TP_Token_Guard &guard) @@ -344,6 +189,7 @@ ACE_TP_Reactor::dispatch_i (ACE_Time_Value *max_wait_time, // a later point of time, we decide to handle signals we have to // release the lock before we make any upcalls.. What is here // now is not the right thing... + // // @@ We need to do better.. return this->handle_signals (event_count, guard); @@ -352,8 +198,8 @@ ACE_TP_Reactor::dispatch_i (ACE_Time_Value *max_wait_time, // If there are no signals and if we had received a proper // event_count then first look at dispatching timeouts. We need to // handle timers early since they may have higher latency - // constraints than I/O handlers. Ideally, the order of - // dispatching should be a strategy... + // constraints than I/O handlers. Ideally, the order of dispatching + // should be a strategy... // NOTE: The event count does not have the number of timers that // needs dispatching. But we are still passing this along. We dont @@ -366,14 +212,13 @@ ACE_TP_Reactor::dispatch_i (ACE_Time_Value *max_wait_time, if (result > 0) return result; - - // Else justgo ahead fall through for further handling + // Else just go ahead fall through for further handling. if (event_count > 0) { // Next dispatch the notification handlers (if there are any to - // dispatch). These are required to handle multiple-threads that - // are trying to update the <Reactor>. + // dispatch). These are required to handle multiple-threads + // that are trying to update the <Reactor>. result = this->handle_notify_events (event_count, guard); @@ -391,12 +236,8 @@ ACE_TP_Reactor::dispatch_i (ACE_Time_Value *max_wait_time, } return 0; - } - - - int ACE_TP_Reactor::handle_signals (int & /*event_count*/, ACE_TP_Token_Guard & /*guard*/) @@ -427,7 +268,7 @@ ACE_TP_Reactor::handle_signals (int & /*event_count*/, // result of signals they should be dispatched since // they may be time critical... active_handle_count = this->any_ready (dispatch_set); - #else +#else // active_handle_count = 0; #endif @@ -456,14 +297,25 @@ ACE_TP_Reactor::handle_timer_events (int & /*event_count*/, if (this->timer_queue_->dispatch_info (cur_time, info)) { + const void *upcall_act = 0; + + // Preinvoke. + this->timer_queue_->preinvoke (info, + cur_time, + upcall_act); + // Release the token before dispatching notifies... guard.release_token (); // call the functor - this->timer_queue_->upcall (info.type_, - info.act_, + this->timer_queue_->upcall (info, cur_time); + // Postinvoke + this->timer_queue_->postinvoke (info, + cur_time, + upcall_act); + // We have dispatched a timer return 1; } @@ -471,8 +323,6 @@ ACE_TP_Reactor::handle_timer_events (int & /*event_count*/, return 0; } - - int ACE_TP_Reactor::handle_notify_events (int & /*event_count*/, ACE_TP_Token_Guard &guard) @@ -499,7 +349,7 @@ ACE_TP_Reactor::handle_notify_events (int & /*event_count*/, while (this->notify_handler_->read_notify_pipe (notify_handle, buffer) > 0) { - // Just figure out whether we can read any buffer that has + // Just figure out whether we can read any buffer that has // dispatchable info. If not we have just been unblocked by // another thread trying to update the reactor. If we get any // buffer that needs dispatching we will dispatch that after @@ -543,109 +393,54 @@ ACE_TP_Reactor::handle_socket_events (int &event_count, return 0; } - // Suspend the handler so that other threads don't start - // dispatching it. + // Suspend the handler so that other threads don't start dispatching + // it. + // // NOTE: This check was performed in older versions of the // TP_Reactor. Looks like it is a waste.. if (dispatch_info.event_handler_ != this->notify_handler_) this->suspend_i (dispatch_info.handle_); - // Release the lock. Others threads can start waiting. - guard.release_token (); - - int result = 0; + int resume_flag = + dispatch_info.event_handler_->resume_handler (); - // If there was an event handler ready, dispatch it. - // Decrement the event left - --event_count; + int reference_counting_required = + dispatch_info.event_handler_->reference_counting_policy ().value () == + ACE_Event_Handler::Reference_Counting_Policy::ENABLED; - if (this->dispatch_socket_event (dispatch_info) == 0) - ++result; // Dispatched an event - - // This is to get around a problem/ which is well described in - // 1361. This is just a work around that would help applications - // from resuming handles at the most inopportune moment. - int flag = - ACE_Event_Handler::ACE_EVENT_HANDLER_NOT_RESUMED; - - // Acquire the token since we want to access the handler - // repository. The call to find () does not hold a lock and hence - // this is required. - guard.acquire_token (); - - // Get the handler for the handle that we have dispatched to. - ACE_Event_Handler *eh = - this->handler_rep_.find (dispatch_info.handle_); - - // This check is required for the following reasons - // 1. If dispatch operation returned a -1, then there is a - // possibility that the event handler could be deleted. In such - // cases the pointer to the event_handler that <dispatch_info> - // holds is set to 0. - // - // 2. If the application did its own memory management, a return - // value of 0 cannot be believed since the event handler could - // be deleted by the application based on some conditions. This - // is *bad*. But we dont have much of a choice with the existing - // reactor setup. To get around this, we can make a check for - // the handler registered with the repository for the handle - // that we have and compare with the handler that we - // posses. Yeah, I know it is like touching your nose by taking - // your hand around your head. But that is the way it is. This - // is a fix for [BUGID 1231] - - if (dispatch_info.event_handler_ != 0 && - eh == dispatch_info.event_handler_) + // Call add_reference() if needed. + if (reference_counting_required) { - flag = - dispatch_info.event_handler_->resume_handler (); + dispatch_info.event_handler_->add_reference (); } - // Use resume_i () since we hold the token already. - if (dispatch_info.handle_ != ACE_INVALID_HANDLE && - dispatch_info.event_handler_ != this->notify_handler_ && - flag == ACE_Event_Handler::ACE_REACTOR_RESUMES_HANDLER) - this->resume_i (dispatch_info.handle_); - - // Let me release the token here. This is not required since the - // destruction of the object on the stack will take care of this. + // Release the lock. Others threads can start waiting. guard.release_token (); - return result; -} - -int -ACE_TP_Reactor::mask_ops (ACE_HANDLE handle, - ACE_Reactor_Mask mask, - int ops) -{ - ACE_TRACE ("ACE_TP_Reactor::mask_ops"); - ACE_MT (ACE_GUARD_RETURN (ACE_Select_Reactor_Token, - ace_mon, this->token_, -1)); - int result = 0; - // If it looks like the handle isn't suspended, then - // set the ops on the wait_set_, otherwise set the suspend_set_. + // If there was an event handler ready, dispatch it. + // Decrement the event left + --event_count; - if (this->suspend_set_.rd_mask_.is_set (handle) == 0 - && this->suspend_set_.wr_mask_.is_set (handle) == 0 - && this->suspend_set_.ex_mask_.is_set (handle) == 0) + // Dispatched an event + if (this->dispatch_socket_event (dispatch_info) == 0) + ++result; - result = this->bit_ops (handle, mask, - this->wait_set_, - ops); - else + // Resume handler if required. + if (dispatch_info.event_handler_ != this->notify_handler_ && + resume_flag == ACE_Event_Handler::ACE_REACTOR_RESUMES_HANDLER) + this->resume_handler (dispatch_info.handle_); - result = this->bit_ops (handle, mask, - this->suspend_set_, - ops); + // Call remove_reference() if needed. + if (reference_counting_required) + { + dispatch_info.event_handler_->remove_reference (); + } return result; } - - int ACE_TP_Reactor::get_event_for_dispatching (ACE_Time_Value *max_wait_time) { @@ -687,7 +482,8 @@ ACE_TP_Reactor::get_event_for_dispatching (ACE_Time_Value *max_wait_time) int ACE_TP_Reactor::get_socket_event_info (ACE_EH_Dispatch_Info &event) { - event.reset (); // Nothing to dispatch yet + // Nothing to dispatch yet + event.reset (); // Check for dispatch in write, except, read. Only catch one, but if // one is caught, be sure to clear the handle from each mask in case @@ -794,10 +590,6 @@ ACE_TP_Reactor::dispatch_socket_event (ACE_EH_Dispatch_Info &dispatch_info) int retval = this->remove_handler (handle, mask); - // As the handler is no longer valid, invalidate the handle - dispatch_info.event_handler_ = 0; - dispatch_info.handle_ = ACE_INVALID_HANDLE; - return retval; } @@ -817,14 +609,6 @@ ACE_TP_Reactor::handle_events (ACE_Time_Value &max_wait_time) return this->handle_events (&max_wait_time); } -int -ACE_TP_Reactor::mask_ops (ACE_Event_Handler *eh, - ACE_Reactor_Mask mask, - int ops) -{ - return this->mask_ops (eh->get_handle (), mask, ops); -} - void ACE_TP_Reactor::notify_handle (ACE_HANDLE, ACE_Reactor_Mask, diff --git a/ace/TP_Reactor.h b/ace/TP_Reactor.h index 2b08d87936d..c53f63407b4 100644 --- a/ace/TP_Reactor.h +++ b/ace/TP_Reactor.h @@ -133,34 +133,33 @@ private: /** * @class ACE_TP_Reactor * - * @brief Specialization of Select Reactor to support thread-pool based - * event dispatching. + * @brief Specialization of Select Reactor to support thread-pool + * based event dispatching. * - * One of the short comings of the Select_Reactor in ACE is that - * it did not support a thread pool based event dispatching - * model, similar to the one in WFMO_Reactor. In - * Select_Reactor, only thread can be blocked in <handle_events> - * at any given time. - * A new Reactor has been added to ACE that removes this - * short-coming. TP_Reactor is a specialization of Select - * Reactor to support thread-pool based event dispatching. This - * Reactor takes advantage of the fact that events reported by - * <select> are persistent if not acted upon immediately. It - * works by remembering the event handler that just got - * activated, releasing the internal lock (so that some other - * thread can start waiting in the event loop) and then - * dispatching the event handler outside the context of the - * Reactor lock. - * This Reactor is best suited for situations when the callbacks - * to event handlers can take arbitrarily long and/or a number - * of threads are available to run the event loops. - * Note that callback code in Event Handlers - * (e.g. Event_Handler::handle_input) does not have to be - * modified or made thread-safe for this Reactor. This is - * because an activated Event Handler is suspended in the - * Reactor before the upcall is made and resumed after the - * upcall completes. Therefore, one Event Handler cannot be - * called by multiple threads simultaneously. + * One of the short comings of the Select_Reactor in ACE is that it + * did not support a thread pool based event dispatching model, + * similar to the one in WFMO_Reactor. In Select_Reactor, only thread + * can be blocked in <handle_events> at any given time. + * + * A new Reactor has been added to ACE that removes this short-coming. + * TP_Reactor is a specialization of Select Reactor to support + * thread-pool based event dispatching. This Reactor takes advantage + * of the fact that events reported by <select> are persistent if not + * acted upon immediately. It works by remembering the event handler + * that just got activated, releasing the internal lock (so that some + * other thread can start waiting in the event loop) and then + * dispatching the event handler outside the context of the Reactor + * lock. + * + * This Reactor is best suited for situations when the callbacks to + * event handlers can take arbitrarily long and/or a number of threads + * are available to run the event loops. Note that callback code in + * Event Handlers (e.g. Event_Handler::handle_input) does not have to + * be modified or made thread-safe for this Reactor. This is because + * an activated Event Handler is suspended in the Reactor before the + * upcall is made and resumed after the upcall completes. Therefore, + * one Event Handler cannot be called by multiple threads + * simultaneously. */ class ACE_Export ACE_TP_Reactor : public ACE_Select_Reactor { @@ -212,75 +211,12 @@ public: virtual int handle_events (ACE_Time_Value &max_wait_time); - - /// The following two overloaded methods are necessary as we dont - /// want the TP_Reactor to call handle_close () with the token - /// held. - /** - * Removes the <mask> binding of <eh> from the Select_Reactor. If - * there are no more bindings for this <eh> then it is removed from - * the Select_Reactor. Note that the Select_Reactor will call - * <ACE_Event_Handler::get_handle> to extract the underlying I/O - * handle. - */ - virtual int remove_handler (ACE_Event_Handler *eh, - ACE_Reactor_Mask mask); - - /** - * Removes the <mask> bind of <Event_Handler> whose handle is - * <handle> from the Select_Reactor. If there are no more bindings - * for this <eh> then it is removed from the Select_Reactor. - */ - virtual int remove_handler (ACE_HANDLE handle, - ACE_Reactor_Mask); - - /** - * Removes all the <mask> bindings for handles in the <handle_set> - * bind of <Event_Handler>. If there are no more bindings for any - * of these handlers then they are removed from the Select_Reactor. - */ - virtual int remove_handler (const ACE_Handle_Set &handle_set, - ACE_Reactor_Mask); - - /* @todo The following methods are not supported. Support for - * signals is not available in the TP_Reactor. These methods will be - * supported once signal handling is supported. We have to include - * these two methods in the TP_Reactor to keep some compilers - * silent. - */ - /** - * Remove the ACE_Event_Handler currently associated with <signum>. - * <sigkey> is ignored in this implementation since there is only - * one instance of a signal handler. Install the new disposition - * (if given) and return the previous disposition (if desired by the - * caller). Returns 0 on success and -1 if <signum> is invalid. - */ - virtual int remove_handler (int signum, - ACE_Sig_Action *new_disp, - ACE_Sig_Action *old_disp = 0, - int sigkey = -1); - - /// Calls <remove_handler> for every signal in <sigset>. - virtual int remove_handler (const ACE_Sig_Set &sigset); - /// Does the reactor allow the application to resume the handle on /// its own ie. can it pass on the control of handle resumption to /// the application. The TP reactor has can allow applications to /// resume handles. So return a +ve value. virtual int resumable_handler (void); - /// GET/SET/ADD/CLR the dispatch mask "bit" bound with the <eh> and - /// <mask>. - virtual int mask_ops (ACE_Event_Handler *eh, - ACE_Reactor_Mask mask, - int ops); - - /// GET/SET/ADD/CLR the dispatch mask "bit" bound with the <handle> - /// and <mask>. - virtual int mask_ops (ACE_HANDLE handle, - ACE_Reactor_Mask mask, - int ops); - /// Called from handle events static void no_op_sleep_hook (void *); @@ -297,8 +233,8 @@ public: ACE_ALLOC_HOOK_DECLARE; protected: - // = Internal methods that do the actual work. + // = Internal methods that do the actual work. /// Dispatch just 1 signal, timer, notification handlers int dispatch_i (ACE_Time_Value *max_wait_time, @@ -336,7 +272,7 @@ protected: private: /// Get the handle of the notify pipe from the ready set if there is - /// an event in the notify pipe. + /// an event in the notify pipe. ACE_HANDLE get_notify_handle (void); /// Get socket event dispatch information. diff --git a/ace/TP_Reactor.i b/ace/TP_Reactor.i index bfb3f02e2dd..a3a9de3d1de 100644 --- a/ace/TP_Reactor.i +++ b/ace/TP_Reactor.i @@ -50,8 +50,8 @@ ACE_EH_Dispatch_Info::dispatch (void) const ACE_INLINE ACE_TP_Token_Guard::ACE_TP_Token_Guard (ACE_Select_Reactor_Token &token) - :token_ (token), - owner_ (0) + : token_ (token), + owner_ (0) { } @@ -87,6 +87,7 @@ ACE_TP_Token_Guard::is_owner (void) /************************************************************************/ // Methods for ACE_TP_Reactor /************************************************************************/ + ACE_INLINE void ACE_TP_Reactor::no_op_sleep_hook (void *) { diff --git a/ace/Timer_Hash_T.cpp b/ace/Timer_Hash_T.cpp index a83a5e3acb6..7c94c437f94 100644 --- a/ace/Timer_Hash_T.cpp +++ b/ace/Timer_Hash_T.cpp @@ -16,19 +16,23 @@ ACE_RCSID(ace, Timer_Hash_T, "$Id$") +template <class TYPE> struct Hash_Token { Hash_Token (const void *act, size_t pos, - long orig_id) + long orig_id, + const TYPE &type) : act_ (act), pos_ (pos), - orig_id_ (orig_id) + orig_id_ (orig_id), + type_ (type) {} const void *act_; size_t pos_; long orig_id_; + TYPE type_; }; // Default constructor @@ -49,63 +53,91 @@ ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, ACE_LOCK>::ACE_Timer_Hash_Upcall (ACE_Timer // Nothing } -// Calls up to timer_hash's upcall functor - template <class TYPE, class FUNCTOR, class ACE_LOCK> int -ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, ACE_LOCK>::timeout (TIMER_QUEUE &timer_queue, - ACE_Event_Handler *handler, - const void *arg, - const ACE_Time_Value &cur_time) +ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, ACE_LOCK>::registration (TIMER_QUEUE &, + ACE_Event_Handler *, + const void *) { - ACE_UNUSED_ARG (timer_queue); + // Registration will be handled by the upcall functor of the timer + // hash. + return 0; +} - Hash_Token *h = ACE_reinterpret_cast (Hash_Token *, - ACE_const_cast (void *, - arg)); - int result = - this->timer_hash_->upcall_functor ().timeout (*this->timer_hash_, - handler, - h->act_, - cur_time); - delete h; - return result; +template <class TYPE, class FUNCTOR, class ACE_LOCK> int +ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, ACE_LOCK>::preinvoke (TIMER_QUEUE & /* timer_queue */, + ACE_Event_Handler *event_handler, + const void *arg, + int recurring_timer, + const ACE_Time_Value &cur_time, + const void *&upcall_act) +{ + // This method should never be invoked since we don't invoke + // expire() on the buckets. + ACE_ASSERT (0); + return 0; } +template <class TYPE, class FUNCTOR, class ACE_LOCK> int +ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, ACE_LOCK>::postinvoke (TIMER_QUEUE &, + ACE_Event_Handler *event_handler, + const void *arg, + int recurring_timer, + const ACE_Time_Value &cur_time, + const void *upcall_act) +{ + // This method should never be invoked since we don't invoke + // expire() on the buckets. + ACE_ASSERT (0); + return 0; +} // Calls up to timer_hash's upcall functor - template <class TYPE, class FUNCTOR, class ACE_LOCK> int -ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, ACE_LOCK>::cancellation (TIMER_QUEUE &timer_queue, - ACE_Event_Handler *handler) +ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, ACE_LOCK>::timeout (TIMER_QUEUE &, + ACE_Event_Handler *event_handler, + const void *arg, + int recurring_timer, + const ACE_Time_Value &cur_time) { - ACE_UNUSED_ARG (timer_queue); - return this->timer_hash_->upcall_functor ().cancellation (*this->timer_hash_, - handler); + // This method should never be invoked since we don't invoke + // expire() on the buckets. + ACE_ASSERT (0); + return 0; } - -// Calls up to timer_hash's upcall functor +template <class TYPE, class FUNCTOR, class ACE_LOCK> int +ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, ACE_LOCK>::cancellation (TIMER_QUEUE &, + ACE_Event_Handler *event_handler, + int dont_call) +{ + // Cancellation will be handled by the upcall functor of the timer + // hash. + return 0; +} template <class TYPE, class FUNCTOR, class ACE_LOCK> int -ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, ACE_LOCK>::deletion (TIMER_QUEUE &timer_queue, - ACE_Event_Handler *handler, +ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, ACE_LOCK>::deletion (TIMER_QUEUE &, + ACE_Event_Handler *event_handler, const void *arg) { - ACE_UNUSED_ARG (timer_queue); + // Call up to the upcall functor of the timer hash since the timer + // hash does not invoke deletion() on its upcall functor directly. + Hash_Token<TYPE> *h = + ACE_reinterpret_cast (Hash_Token<TYPE> *, + ACE_const_cast (void *, + arg)); - Hash_Token *h = ACE_reinterpret_cast (Hash_Token *, - ACE_const_cast (void *, - arg)); int result = - this->timer_hash_->upcall_functor ().deletion (*this->timer_hash_, - handler, - h->act_); + this->timer_hash_->upcall_functor (). + deletion (*this->timer_hash_, + event_handler, + h->act_); + delete h; + return result; } - - template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> ACE_Timer_Hash_Iterator_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::ACE_Timer_Hash_Iterator_T (ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET> &hash) : timer_hash_ (hash) @@ -325,45 +357,52 @@ ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::reschedule (ACE_Timer_Node_T< { ACE_TRACE ("ACE_Timer_Hash_T::reschedule"); - size_t position = - expired->get_timer_value ().sec () % this->table_size_; + Hash_Token<TYPE> *h = + ACE_reinterpret_cast (Hash_Token<TYPE> *, + ACE_const_cast (void *, + expired->get_act ())); - Hash_Token *h = ACE_reinterpret_cast (Hash_Token *, - ACE_const_cast (void *, - expired->get_act ())); + // Cancel the old timer. Make sure not to call handle_close(). + this->table_[h->pos_]->cancel (h->orig_id_, + 0, + 1); - h->orig_id_ = this->table_[position]->schedule (expired->get_type (), - h, - expired->get_timer_value (), - expired->get_interval ()); + h->pos_ = + expired->get_timer_value ().sec () % this->table_size_; + + h->orig_id_ = + this->table_[h->pos_]->schedule (expired->get_type (), + h, + expired->get_timer_value (), + expired->get_interval ()); if (this->table_[this->earliest_position_]->is_empty () - || this->table_[position]->earliest_time () + || this->table_[h->pos_]->earliest_time () < this->table_[this->earliest_position_]->earliest_time ()) - this->earliest_position_ = position; + this->earliest_position_ = h->pos_; } // Insert a new handler that expires at time future_time; if interval // is > 0, the handler will be reinvoked periodically. template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> long -ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::schedule (const TYPE &type, - const void *act, - const ACE_Time_Value &future_time, - const ACE_Time_Value &interval) +ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::schedule_i (const TYPE &type, + const void *act, + const ACE_Time_Value &future_time, + const ACE_Time_Value &interval) { - ACE_TRACE ("ACE_Timer_Hash_T::schedule"); - ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1)); + ACE_TRACE ("ACE_Timer_Hash_T::schedule_i"); size_t position = future_time.sec () % this->table_size_; - Hash_Token *h; + Hash_Token<TYPE> *h; ACE_NEW_RETURN (h, - Hash_Token (act, - position, - 0), + Hash_Token<TYPE> (act, + position, + 0, + type), -1); h->orig_id_ = this->table_[position]->schedule (type, @@ -413,11 +452,13 @@ ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::reset_interval (long timer_id #if defined (ACE_WIN64) unsigned long timer_offset = ACE_static_cast (unsigned long, timer_id); - Hash_Token *h = ACE_reinterpret_cast (Hash_Token *, - (this->pointer_base_ + timer_offset)); + Hash_Token<TYPE> *h = + ACE_reinterpret_cast (Hash_Token<TYPE> *, + (this->pointer_base_ + timer_offset)); #else - Hash_Token *h = ACE_reinterpret_cast (Hash_Token *, - timer_id); + Hash_Token<TYPE> *h = + ACE_reinterpret_cast (Hash_Token<TYPE> *, + timer_id); #endif /* ACE_WIN64 */ return this->table_[h->pos_]->reset_interval (h->orig_id_, @@ -442,17 +483,23 @@ ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::cancel (long timer_id, #if defined (ACE_WIN64) unsigned long timer_offset = ACE_static_cast (unsigned long, timer_id); - Hash_Token *h = ACE_reinterpret_cast (Hash_Token *, - (this->pointer_base_ + timer_offset)); + Hash_Token<TYPE> *h = + ACE_reinterpret_cast (Hash_Token<TYPE> *, + (this->pointer_base_ + timer_offset)); #else - Hash_Token *h = ACE_reinterpret_cast (Hash_Token *, - timer_id); + Hash_Token<TYPE> *h = + ACE_reinterpret_cast (Hash_Token<TYPE> *, + timer_id); #endif /* ACE_WIN64 */ int result = this->table_[h->pos_]->cancel (h->orig_id_, act, dont_call); + this->upcall_functor ().cancellation (*this, + h->type_, + dont_call); + if (h->pos_ == this->earliest_position_) this->find_new_earliest (); @@ -478,10 +525,10 @@ ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::cancel (const TYPE &type, size_t i; // loop variable. - Hash_Token **timer_ids; + Hash_Token<TYPE> **timer_ids; ACE_NEW_RETURN (timer_ids, - Hash_Token *[this->size_], + Hash_Token<TYPE> *[this->size_], -1); size_t pos = 0; @@ -499,7 +546,7 @@ ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::cancel (const TYPE &type, iter.next ()) if (iter.item ()->get_type () == type) timer_ids[pos++] = - ACE_reinterpret_cast (Hash_Token *, + ACE_reinterpret_cast (Hash_Token<TYPE> *, ACE_const_cast (void *, iter.item ()->get_act ())); } @@ -511,16 +558,19 @@ ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::cancel (const TYPE &type, { this->table_[timer_ids[i]->pos_]->cancel (timer_ids[i]->orig_id_, 0, - 1); + dont_call); + + this->upcall_functor ().cancellation (*this, + timer_ids[i]->type_, + dont_call); + delete timer_ids[i]; + --this->size_; } delete [] timer_ids; - if (dont_call == 0) - this->upcall_functor ().cancellation (*this, - type); this->find_new_earliest (); return ACE_static_cast (int, pos); @@ -570,6 +620,43 @@ ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::get_first (void) return this->table_[this->earliest_position_]->get_first (); } +template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> int +ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::dispatch_info_i (const ACE_Time_Value &cur_time, + ACE_Timer_Node_Dispatch_Info_T<TYPE> &info) +{ + int result = + ACE_Timer_Queue_T<TYPE,FUNCTOR,ACE_LOCK>::dispatch_info_i (cur_time, + info); + + if (result == 1) + { + Hash_Token<TYPE> *h = + ACE_reinterpret_cast (Hash_Token<TYPE> *, + ACE_const_cast (void *, + info.act_)); + + info.act_ = h->act_; + } + + return result; +} + +template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> void +ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::free_node (ACE_Timer_Node_T<TYPE> *node) +{ + Hash_Token<TYPE> *h = + ACE_reinterpret_cast (Hash_Token<TYPE> *, + ACE_const_cast (void *, + node->get_act ())); + + // Now remove the timer from the original table... + this->table_[h->pos_]->cancel (node->get_timer_id (), + 0, + 1); + + ACE_Timer_Queue_T<TYPE,FUNCTOR,ACE_LOCK>::free_node (node); +} + // Dummy version of expire to get rid of warnings in Sun CC 4.2 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> int @@ -596,7 +683,7 @@ ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::expire (const ACE_Time_Value i < this->table_size_; i++) { - while (!this->table_[i]->is_empty () + while (!this->table_[i]->is_empty () && this->table_[i]->earliest_time () <= cur_time) { expired = this->table_[i]->get_first (); @@ -610,7 +697,7 @@ ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::expire (const ACE_Time_Value // Make sure that we skip past values that have already // "expired". do - expired->set_timer_value (expired->get_timer_value () + expired->set_timer_value (expired->get_timer_value () + expired->get_interval ()); while (expired->get_timer_value () <= cur_time); @@ -619,28 +706,42 @@ ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::expire (const ACE_Time_Value this->reschedule (expired); reclaim = 0; } + else + { + // Now remove the timer from the original table... + this->table_[i]->cancel (expired->get_timer_id (), + 0, + 1); + } + + Hash_Token<TYPE> *h = + ACE_reinterpret_cast (Hash_Token<TYPE> *, + ACE_const_cast (void *, + act)); + + ACE_Timer_Node_Dispatch_Info_T<TYPE> info; + + // Get the dispatch info + expired->get_dispatch_info (info); + + info.act_ = h->act_; + + const void *upcall_act = 0; + + this->preinvoke (info, cur_time, upcall_act); + + this->upcall (info, cur_time); + + this->postinvoke (info, cur_time, upcall_act); - // Now remove the timer from the original table... if - // it's a simple, non-recurring timer, it's got to be - // removed anyway. If it was rescheduled, it's been - // scheduled into the correct table (regardless of whether - // it's the same one or not) already. - this->table_[i]->cancel (expired->get_timer_id ()); - - Hash_Token *h = ACE_reinterpret_cast (Hash_Token *, - ACE_const_cast (void *, - act)); - // Call the functor. - this->upcall (type, - h->act_, - cur_time); if (reclaim) { --this->size_; delete h; } + number_of_timers_expired++; - } + } } return number_of_timers_expired; diff --git a/ace/Timer_Hash_T.h b/ace/Timer_Hash_T.h index 3e0d0548427..98e91bb2d57 100644 --- a/ace/Timer_Hash_T.h +++ b/ace/Timer_Hash_T.h @@ -50,15 +50,38 @@ public: /// Constructor that specifies a Timer_Hash to call up to ACE_Timer_Hash_Upcall (ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK> *timer_hash); - /// This method is called when the timer expires + /// This method is called when a timer is registered. + int registration (TIMER_QUEUE &timer_queue, + ACE_Event_Handler *handler, + const void *arg); + + /// This method is called before the timer expires. + int preinvoke (TIMER_QUEUE &timer_queue, + ACE_Event_Handler *handler, + const void *arg, + int recurring_timer, + const ACE_Time_Value &cur_time, + const void *&upcall_act); + + /// This method is called when the timer expires. int timeout (TIMER_QUEUE &timer_queue, ACE_Event_Handler *handler, const void *arg, + int recurring_timer, const ACE_Time_Value &cur_time); + /// This method is called after the timer expires. + int postinvoke (TIMER_QUEUE &timer_queue, + ACE_Event_Handler *handler, + const void *arg, + int recurring_timer, + const ACE_Time_Value &cur_time, + const void *upcall_act); + /// This method is called when the timer is cancelled int cancellation (TIMER_QUEUE &timer_queue, - ACE_Event_Handler *handler); + ACE_Event_Handler *handler, + int dont_call); /// This method is called when the timer queue is destroyed and /// the timer is still contained in it @@ -169,22 +192,6 @@ public: virtual const ACE_Time_Value &earliest_time (void) const; /** - * Schedule <type> that will expire at <future_time>, - * which is specified in absolute time. If it expires then <act> is - * passed in as the value to the <functor>. If <interval> is != to - * <ACE_Time_Value::zero> then it is used to reschedule the <type> - * automatically, using relative time to the current <gettimeofday>. - * This method returns a <timer_id> that is a pointer to a token - * which stores information about the event. This <timer_id> can be - * used to cancel the timer before it expires. Returns -1 on - * failure. - */ - virtual long schedule (const TYPE &type, - const void *act, - const ACE_Time_Value &future_time, - const ACE_Time_Value &interval = ACE_Time_Value::zero); - - /** * Resets the interval of the timer represented by <timer_id> to * <interval>, which is specified in relative time to the current * <gettimeofday>. If <interval> is equal to @@ -242,6 +249,30 @@ public: virtual ACE_Timer_Node_T<TYPE> *get_first (void); private: + + /** + * Schedule <type> that will expire at <future_time>, + * which is specified in absolute time. If it expires then <act> is + * passed in as the value to the <functor>. If <interval> is != to + * <ACE_Time_Value::zero> then it is used to reschedule the <type> + * automatically, using relative time to the current <gettimeofday>. + * This method returns a <timer_id> that is a pointer to a token + * which stores information about the event. This <timer_id> can be + * used to cancel the timer before it expires. Returns -1 on + * failure. + */ + virtual long schedule_i (const TYPE &type, + const void *act, + const ACE_Time_Value &future_time, + const ACE_Time_Value &interval); + + /// Non-locking version of dispatch_info () + virtual int dispatch_info_i (const ACE_Time_Value ¤t_time, + ACE_Timer_Node_Dispatch_Info_T<TYPE> &info); + + /// Factory method that frees a previously allocated node. + virtual void free_node (ACE_Timer_Node_T<TYPE> *); + /// Reschedule an "interval" <ACE_Timer_Node>. virtual void reschedule (ACE_Timer_Node_T<TYPE> *); diff --git a/ace/Timer_Heap_T.cpp b/ace/Timer_Heap_T.cpp index a9aae8639fc..fdac8c9a463 100644 --- a/ace/Timer_Heap_T.cpp +++ b/ace/Timer_Heap_T.cpp @@ -174,8 +174,11 @@ ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::~ACE_Timer_Heap_T (void) delete iterator_; + size_t current_size = + this->cur_size_; + // Clean up all the nodes still in the queue - for (size_t i = 0; i < this->cur_size_; i++) + for (size_t i = 0; i < current_size; i++) { this->upcall_functor ().deletion (*this, this->heap_[i]->get_type (), @@ -374,7 +377,7 @@ ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::remove (size_t slot) // parent it needs be moved down the heap. size_t parent = ACE_HEAP_PARENT (slot); - if (moved_node->get_timer_value () + if (moved_node->get_timer_value () >= this->heap_[parent]->get_timer_value ()) this->reheap_down (moved_node, slot, @@ -401,13 +404,13 @@ ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::reheap_down (ACE_Timer_Node_T<TYPE> * { // Choose the smaller of the two children. if (child + 1 < this->cur_size_ - && this->heap_[child + 1]->get_timer_value () + && this->heap_[child + 1]->get_timer_value () < this->heap_[child]->get_timer_value ()) child++; // Perform a <copy> if the child has a larger timeout value than // the <moved_node>. - if (this->heap_[child]->get_timer_value () + if (this->heap_[child]->get_timer_value () < moved_node->get_timer_value ()) { this->copy (slot, @@ -434,7 +437,7 @@ ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::reheap_up (ACE_Timer_Node_T<TYPE> *mo { // If the parent node is greater than the <moved_node> we need // to copy it down. - if (moved_node->get_timer_value () + if (moved_node->get_timer_value () < this->heap_[parent]->get_timer_value ()) { this->copy (slot, this->heap_[parent]); @@ -490,7 +493,7 @@ ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::grow_heap (void) ssize_t *new_timer_ids = 0; - ACE_NEW (new_timer_ids, + ACE_NEW (new_timer_ids, ssize_t[new_size]); ACE_OS::memcpy (new_timer_ids, @@ -594,7 +597,6 @@ ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::alloc_node (void) template <class TYPE, class FUNCTOR, class ACE_LOCK> void ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::free_node (ACE_Timer_Node_T<TYPE> *node) { - // Return this timer id to the freelist. this->push_freelist (node->get_timer_id ()); @@ -612,15 +614,13 @@ ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::free_node (ACE_Timer_Node_T<TYPE> *no // > 0, the handler will be reinvoked periodically. template <class TYPE, class FUNCTOR, class ACE_LOCK> long -ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::schedule (const TYPE &type, - const void *act, - const ACE_Time_Value &future_time, - const ACE_Time_Value &interval) +ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::schedule_i (const TYPE &type, + const void *act, + const ACE_Time_Value &future_time, + const ACE_Time_Value &interval) { ACE_TRACE ("ACE_Timer_Heap_T::schedule"); - ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1)); - if ((this->cur_size_ + this->cur_limbo_) < this->max_size_) { // Obtain the next unique sequence number. @@ -660,14 +660,14 @@ ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::cancel (long timer_id, // Locate the ACE_Timer_Node that corresponds to the timer_id. // Check to see if the timer_id is out of range - if (timer_id < 0 + if (timer_id < 0 || (size_t) timer_id > this->max_size_) return 0; ssize_t timer_node_slot = this->timer_ids_[timer_id]; // Check to see if timer_id is still valid. - if (timer_node_slot < 0) + if (timer_node_slot < 0) return 0; if (timer_id != this->heap_[timer_node_slot]->get_timer_id ()) @@ -680,10 +680,10 @@ ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::cancel (long timer_id, ACE_Timer_Node_T<TYPE> *temp = this->remove (timer_node_slot); - if (dont_call == 0) - // Call the close hook. - this->upcall_functor ().cancellation (*this, - temp->get_type ()); + // Call the close hook. + this->upcall_functor ().cancellation (*this, + temp->get_type (), + dont_call); if (act != 0) *act = temp->get_act (); @@ -695,8 +695,8 @@ ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::cancel (long timer_id, // Locate and update the inteval on the timer_id -template <class TYPE, class FUNCTOR, class ACE_LOCK> int -ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::reset_interval (long timer_id, +template <class TYPE, class FUNCTOR, class ACE_LOCK> int +ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::reset_interval (long timer_id, const ACE_Time_Value &interval) { ACE_TRACE ("ACE_Timer_Heap_T::reset_interval"); @@ -705,14 +705,14 @@ ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::reset_interval (long timer_id, // Locate the ACE_Timer_Node that corresponds to the timer_id. // Check to see if the timer_id is out of range - if (timer_id < 0 + if (timer_id < 0 || (size_t) timer_id > this->max_size_) return -1; ssize_t timer_node_slot = this->timer_ids_[timer_id]; // Check to see if timer_id is still valid. - if (timer_node_slot < 0) + if (timer_node_slot < 0) return -1; if (timer_id != this->heap_[timer_node_slot]->get_timer_id ()) @@ -735,30 +735,29 @@ ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::cancel (const TYPE &type, int dont_call) { ACE_TRACE ("ACE_Timer_Heap_T::cancel"); + ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1)); int number_of_cancellations = 0; // Try to locate the ACE_Timer_Node that matches the timer_id. - { - ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1)); - - for (size_t i = 0; i < this->cur_size_; ) - { - if (this->heap_[i]->get_type () == type) - { - ACE_Timer_Node_T<TYPE> *temp = this->remove (i); - - number_of_cancellations++; - - this->free_node (temp); - } - else - i++; - } - } - - if (dont_call == 0) - this->upcall_functor ().cancellation (*this, type); + + for (size_t i = 0; i < this->cur_size_; ) + { + if (this->heap_[i]->get_type () == type) + { + ACE_Timer_Node_T<TYPE> *temp = this->remove (i); + + number_of_cancellations++; + + this->free_node (temp); + + this->upcall_functor ().cancellation (*this, + type, + dont_call); + } + else + i++; + } return number_of_cancellations; } diff --git a/ace/Timer_Heap_T.h b/ace/Timer_Heap_T.h index 73ba57dd3e2..6633bb848c7 100644 --- a/ace/Timer_Heap_T.h +++ b/ace/Timer_Heap_T.h @@ -130,27 +130,6 @@ public: virtual const ACE_Time_Value &earliest_time (void) const; /** - * Schedule a timer that may optionally auto-reset. - * Schedule <type> that will expire at <future_time>, - * which is specified in absolute time. If it expires then <act> is - * passed in as the value to the <functor>. If <interval> is != to - * <ACE_Time_Value::zero> then it is used to reschedule the <type> - * automatically, using relative time to the current <gettimeofday>. - * This method returns a <timer_id> that uniquely identifies the the - * <type> entry in an internal list. This <timer_id> can be used to - * cancel the timer before it expires. The cancellation ensures - * that <timer_ids> are unique up to values of greater than 2 - * billion timers. As long as timers don't stay around longer than - * this there should be no problems with accidentally deleting the - * wrong timer. Returns -1 on failure (which is guaranteed never to - * be a valid <timer_id>). - */ - virtual long schedule (const TYPE &type, - const void *act, - const ACE_Time_Value &future_time, - const ACE_Time_Value &interval = ACE_Time_Value::zero); - - /** * Resets the interval of the timer represented by <timer_id> to * <interval>, which is specified in relative time to the current * <gettimeofday>. If <interval> is equal to @@ -201,6 +180,28 @@ public: virtual ACE_Timer_Node_T<TYPE> *get_first (void); protected: + + /** + * Schedule a timer that may optionally auto-reset. + * Schedule <type> that will expire at <future_time>, + * which is specified in absolute time. If it expires then <act> is + * passed in as the value to the <functor>. If <interval> is != to + * <ACE_Time_Value::zero> then it is used to reschedule the <type> + * automatically, using relative time to the current <gettimeofday>. + * This method returns a <timer_id> that uniquely identifies the the + * <type> entry in an internal list. This <timer_id> can be used to + * cancel the timer before it expires. The cancellation ensures + * that <timer_ids> are unique up to values of greater than 2 + * billion timers. As long as timers don't stay around longer than + * this there should be no problems with accidentally deleting the + * wrong timer. Returns -1 on failure (which is guaranteed never to + * be a valid <timer_id>). + */ + virtual long schedule_i (const TYPE &type, + const void *act, + const ACE_Time_Value &future_time, + const ACE_Time_Value &interval); + /// Reschedule an "interval" <ACE_Timer_Node>. virtual void reschedule (ACE_Timer_Node_T<TYPE> *); diff --git a/ace/Timer_List_T.cpp b/ace/Timer_List_T.cpp index ecf2d71544d..f1a65fa48a8 100644 --- a/ace/Timer_List_T.cpp +++ b/ace/Timer_List_T.cpp @@ -126,14 +126,24 @@ ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK>::~ACE_Timer_List_T (void) delete iterator_; - if (! this->is_empty()) { - for (ACE_Timer_Node_T<TYPE>* n = this->get_first(); n != this->head_;) { - ACE_Timer_Node_T<TYPE>* next = n->get_next(); - this->upcall_functor ().deletion (*this, n->get_type(), n->get_act()); - this->free_node(n); - n = next; + if (!this->is_empty()) + { + for (ACE_Timer_Node_T<TYPE>* n = this->get_first(); + n != this->head_; + ) + { + this->upcall_functor ().deletion (*this, + n->get_type(), + n->get_act()); + + ACE_Timer_Node_T<TYPE> *next = + n->get_next (); + + this->free_node (n); + + n = next; + } } - } // delete the dummy node delete this->head_; @@ -174,13 +184,12 @@ ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK>::reschedule (ACE_Timer_Node_T<TYPE>* n // is > 0, the handler will be reinvoked periodically. template <class TYPE, class FUNCTOR, class ACE_LOCK> long -ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK>::schedule (const TYPE &type, - const void *act, - const ACE_Time_Value &future_time, - const ACE_Time_Value &interval) +ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK>::schedule_i (const TYPE &type, + const void *act, + const ACE_Time_Value &future_time, + const ACE_Time_Value &interval) { ACE_TRACE ("ACE_Timer_List_T::schedule"); - ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1)); ACE_Timer_Node_T<TYPE>* n = this->alloc_node(); @@ -203,7 +212,7 @@ ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK>::schedule (const TYPE &type, /// The shared scheduling functionality between schedule() and reschedule() template <class TYPE, class FUNCTOR, class ACE_LOCK> void ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK>::schedule_i (ACE_Timer_Node_T<TYPE>* n, - const ACE_Time_Value& expire) + const ACE_Time_Value& expire) { if (this->is_empty()) { n->set_prev(this->head_); @@ -230,7 +239,7 @@ ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK>::schedule_i (ACE_Timer_Node_T<TYPE>* n template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_Timer_Node_T<TYPE>* -ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK>::find_node(long timer_id) const +ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK>::find_node (long timer_id) const { ACE_Timer_Node_T<TYPE>* n = this->get_first_i(); if (n == 0) @@ -269,12 +278,14 @@ ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK>::cancel (long timer_id, ACE_TRACE ("ACE_Timer_List_T::cancel"); ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1)); ACE_Timer_Node_T<TYPE>* n = this->find_node(timer_id); - if (n != 0) { - if (act != 0) - *act = n->get_act(); - this->cancel_i(n, skip_close); - return 1; - } + if (n != 0) + { + if (act != 0) + *act = n->get_act (); + this->cancel_i (n, skip_close); + + return 1; + } return 0; } @@ -287,30 +298,28 @@ ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK>::cancel (const TYPE &type, int skip_cl int num_canceled = 0; // Note : Technically this can overflow. - if (! this->is_empty()) { + if (this->is_empty()) + return 0; - for (ACE_Timer_Node_T<TYPE>* n = this->get_first(); n != this->head_;) + for (ACE_Timer_Node_T<TYPE>* n = this->get_first(); + n != this->head_; + ) { if (n->get_type() == type) // Note: Typically Type is an ACE_Event_Handler* - { - ++num_canceled; - - ACE_Timer_Node_T<TYPE>* tmp = n; - n = n->get_next(); - int always_skip_close = 1; // todo : Is this correct? - this->cancel_i(tmp, always_skip_close); - } + { + ++num_canceled; + + ACE_Timer_Node_T<TYPE>* tmp = n; + n = n->get_next(); + + this->cancel_i (tmp, skip_close); + } else - { - n = n->get_next(); - } + { + n = n->get_next(); + } } - } - - if (! skip_close) { // && num_canceled > 0) { - this->upcall_functor().cancellation (*this, type); - } return num_canceled; } @@ -325,13 +334,15 @@ ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK>::unlink (ACE_Timer_Node_T<TYPE>* n) /// Shared subset of the two cancel() methods. template <class TYPE, class FUNCTOR, class ACE_LOCK> void -ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK>::cancel_i (ACE_Timer_Node_T<TYPE>* n, int skip_close) +ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK>::cancel_i (ACE_Timer_Node_T<TYPE>* n, + int skip_close) { - this->unlink(n); + this->unlink (n); this->free_node (n); - if (! skip_close) { - this->upcall_functor().cancellation (*this, n->get_type()); - } + + this->upcall_functor ().cancellation (*this, + n->get_type(), + skip_close); } // Reads the first node on the list and returns it. diff --git a/ace/Timer_List_T.h b/ace/Timer_List_T.h index 0f13647e591..42ce2a2eab0 100644 --- a/ace/Timer_List_T.h +++ b/ace/Timer_List_T.h @@ -33,7 +33,7 @@ class ACE_Timer_List_T; * node of a timer queue. */ template <class TYPE, class FUNCTOR, class ACE_LOCK> -class ACE_Timer_List_Iterator_T +class ACE_Timer_List_Iterator_T : public ACE_Timer_Queue_Iterator_T <TYPE, FUNCTOR, ACE_LOCK> { public: @@ -116,26 +116,6 @@ public: virtual const ACE_Time_Value& earliest_time (void) const; /** - * Schedule <type> that will expire at <future_time>, - * which is specified in absolute time. If it expires then <act> is - * passed in as the value to the <functor>. If <interval> is != to - * <ACE_Time_Value::zero> then it is used to reschedule the <type> - * automatically, using relative time to the current <gettimeofday>. - * This method returns a <timer_id> that uniquely identifies the the - * <type> entry in an internal list. This <timer_id> can be used to - * cancel the timer before it expires. The cancellation ensures - * that <timer_ids> are unique up to values of greater than 2 - * billion timers. As long as timers don't stay around longer than - * this there should be no problems with accidentally deleting the - * wrong timer. Returns -1 on failure (which is guaranteed never to - * be a valid <timer_id>). - */ - virtual long schedule (const TYPE& type, - const void* act, - const ACE_Time_Value& future_time, - const ACE_Time_Value& interval = ACE_Time_Value::zero); - - /** * Resets the interval of the timer represented by <timer_id> to * <interval>, which is specified in relative time to the current * <gettimeofday>. If <interval> is equal to @@ -184,10 +164,34 @@ public: private: + /** + * Schedule <type> that will expire at <future_time>, which is + * specified in absolute time. If it expires then <act> is passed + * in as the value to the <functor>. If <interval> is != to + * <ACE_Time_Value::zero> then it is used to reschedule the <type> + * automatically, using relative time to the current <gettimeofday>. + * This method returns a <timer_id> that uniquely identifies the the + * <type> entry in an internal list. This <timer_id> can be used to + * cancel the timer before it expires. The cancellation ensures + * that <timer_ids> are unique up to values of greater than 2 + * billion timers. As long as timers don't stay around longer than + * this there should be no problems with accidentally deleting the + * wrong timer. Returns -1 on failure (which is guaranteed never to + * be a valid <timer_id>). + */ + virtual long schedule_i (const TYPE& type, + const void* act, + const ACE_Time_Value& future_time, + const ACE_Time_Value& interval); + void schedule_i(ACE_Timer_Node_T<TYPE>* n, const ACE_Time_Value& exp); + ACE_Timer_Node_T<TYPE>* find_node(long timer_id) const; + void cancel_i (ACE_Timer_Node_T<TYPE>* n, int skip_close); + void unlink (ACE_Timer_Node_T<TYPE>* n); + ACE_Timer_Node_T<TYPE>* get_first_i(void) const; private: diff --git a/ace/Timer_Queue.h b/ace/Timer_Queue.h index 54a0a8f1137..999dc5ac7d5 100644 --- a/ace/Timer_Queue.h +++ b/ace/Timer_Queue.h @@ -6,7 +6,7 @@ * * $Id$ * - * @author Douglas C. Schmidt <schmidt@cs.wustl.edu> and + * @author Douglas C. Schmidt <schmidt@cs.wustl.edu> and * Irfan Pyarali <irfan@cs.wustl.edu>. */ //============================================================================= diff --git a/ace/Timer_Queue_T.cpp b/ace/Timer_Queue_T.cpp index e63c618c0d4..44ce2d61121 100644 --- a/ace/Timer_Queue_T.cpp +++ b/ace/Timer_Queue_T.cpp @@ -12,6 +12,7 @@ #include "ace/Signal.h" #include "ace/Timer_Queue_T.h" #include "ace/Log_Msg.h" +#include "ace/Reactor_Timer_Interface.h" #if !defined (__ACE_INLINE__) #include "ace/Timer_Queue_T.i" @@ -45,8 +46,6 @@ ACE_Timer_Node_T<TYPE>::~ACE_Timer_Node_T (void) ACE_TRACE ("ACE_Timer_Node_T::~ACE_Timer_Node_T"); } - - template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::ACE_Timer_Queue_Iterator_T (void) { @@ -201,6 +200,33 @@ ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::mutex (void) return this->mutex_; } +template <class TYPE, class FUNCTOR, class ACE_LOCK> long +ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::schedule (const TYPE &type, + const void *act, + const ACE_Time_Value &future_time, + const ACE_Time_Value &interval) +{ + ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1)); + + // Schedule the timer. + int result = + this->schedule_i (type, + act, + future_time, + interval); + + // Return on failure. + if (result == -1) + return result; + + // Inform upcall functor of successful registration. + this->upcall_functor ().registration (*this, + type, + act); + + // Return result; + return result; +} // Run the <handle_timeout> method for all Timers whose values are <= // <cur_time>. @@ -224,8 +250,13 @@ ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::expire (const ACE_Time_Value &cur_ti while ((result = this->dispatch_info_i (cur_time, info)) != 0) { - // call the functor - this->upcall (info.type_, info.act_, cur_time); + const void *upcall_act = 0; + + this->preinvoke (info, cur_time, upcall_act); + + this->upcall (info, cur_time); + + this->postinvoke (info, cur_time, upcall_act); number_of_timers_expired++; @@ -235,7 +266,6 @@ ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::expire (const ACE_Time_Value &cur_ti return number_of_timers_expired; } - template <class TYPE, class FUNCTOR, class ACE_LOCK> int ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::dispatch_info_i (const ACE_Time_Value &cur_time, ACE_Timer_Node_Dispatch_Info_T<TYPE> &info) @@ -260,7 +290,8 @@ ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::dispatch_info_i (const ACE_Time_Valu // Make sure that we skip past values that have already // "expired". do - expired->set_timer_value (expired->get_timer_value () + expired->get_interval ()); + expired->set_timer_value (expired->get_timer_value () + + expired->get_interval ()); while (expired->get_timer_value () <= cur_time); // Since this is an interval timer, we need to reschedule @@ -279,7 +310,6 @@ ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::dispatch_info_i (const ACE_Time_Valu return 0; } - template <class TYPE, class FUNCTOR, class ACE_LOCK> void ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::return_node (ACE_Timer_Node_T<TYPE> *node) { @@ -299,52 +329,122 @@ ACE_Event_Handler_Handle_Timeout_Upcall<ACE_LOCK>::~ACE_Event_Handler_Handle_Tim } template <class ACE_LOCK> int +ACE_Event_Handler_Handle_Timeout_Upcall<ACE_LOCK>::registration (TIMER_QUEUE &, + ACE_Event_Handler *event_handler, + const void *) +{ + int requires_reference_counting = + event_handler->reference_counting_policy ().value () == + ACE_Event_Handler::Reference_Counting_Policy::ENABLED; + + if (requires_reference_counting) + { + event_handler->add_reference (); + } + + return 0; +} + +template <class ACE_LOCK> int +ACE_Event_Handler_Handle_Timeout_Upcall<ACE_LOCK>::preinvoke (TIMER_QUEUE & /* timer_queue */, + ACE_Event_Handler *event_handler, + const void * /* timer_act */, + int /* recurring_timer */, + const ACE_Time_Value & /* cur_time */, + const void *&upcall_act) +{ + int requires_reference_counting = + event_handler->reference_counting_policy ().value () == + ACE_Event_Handler::Reference_Counting_Policy::ENABLED; + + if (requires_reference_counting) + { + event_handler->add_reference (); + + upcall_act = &this->requires_reference_counting_; + } + + return 0; +} + +template <class ACE_LOCK> int +ACE_Event_Handler_Handle_Timeout_Upcall<ACE_LOCK>::postinvoke (TIMER_QUEUE & /* timer_queue */, + ACE_Event_Handler *event_handler, + const void * /* timer_act */, + int /* recurring_timer */, + const ACE_Time_Value & /* cur_time */, + const void *upcall_act) +{ + if (upcall_act == &this->requires_reference_counting_) + { + event_handler->remove_reference (); + } + + return 0; +} + +template <class ACE_LOCK> int ACE_Event_Handler_Handle_Timeout_Upcall<ACE_LOCK>::timeout (TIMER_QUEUE &timer_queue, - ACE_Event_Handler *handler, + ACE_Event_Handler *event_handler, const void *act, + int recurring_timer, const ACE_Time_Value &cur_time) { - // Upcall to the <handler>s handle_timeout() method. - if (handler->handle_timeout (cur_time, act) == -1) + int requires_reference_counting = 0; + + if (!recurring_timer) { -#if 0 - // Commented out until we figure out how to break the coupling that results... - if (handler->reactor ()) - // Call the reactor's cancel_timer() method to minimize locking. - handler->reactor ()->cancel_timer (handler, 0); // 0 means "call handle_close()". + requires_reference_counting = + event_handler->reference_counting_policy ().value () == + ACE_Event_Handler::Reference_Counting_Policy::ENABLED; + } + + // Upcall to the <handler>s handle_timeout method. + if (event_handler->handle_timeout (cur_time, act) == -1) + { + if (event_handler->reactor ()) + event_handler->reactor_timer_interface ()->cancel_timer (event_handler, 0); else -#endif - // Upcall to the handler's handle_timeout method. - timer_queue.cancel (handler, 0); + timer_queue.cancel (event_handler, 0); // 0 means "call handle_close()". + } + + if (!recurring_timer && + requires_reference_counting) + { + event_handler->remove_reference (); } return 0; } template <class ACE_LOCK> int -ACE_Event_Handler_Handle_Timeout_Upcall<ACE_LOCK>::cancellation (TIMER_QUEUE &timer_queue, - ACE_Event_Handler *handler) +ACE_Event_Handler_Handle_Timeout_Upcall<ACE_LOCK>::cancellation (TIMER_QUEUE &, + ACE_Event_Handler *event_handler, + int dont_call) { - ACE_UNUSED_ARG (timer_queue); + int requires_reference_counting = + event_handler->reference_counting_policy ().value () == + ACE_Event_Handler::Reference_Counting_Policy::ENABLED; // Upcall to the <handler>s handle_close method - handler->handle_close (ACE_INVALID_HANDLE, - ACE_Event_Handler::TIMER_MASK); + if (dont_call == 0) + event_handler->handle_close (ACE_INVALID_HANDLE, + ACE_Event_Handler::TIMER_MASK); + + if (requires_reference_counting) + event_handler->remove_reference (); + return 0; } template <class ACE_LOCK> int ACE_Event_Handler_Handle_Timeout_Upcall<ACE_LOCK>::deletion (TIMER_QUEUE &timer_queue, - ACE_Event_Handler *handler, - const void *arg) + ACE_Event_Handler *event_handler, + const void *) { - ACE_UNUSED_ARG (timer_queue); - ACE_UNUSED_ARG (handler); - ACE_UNUSED_ARG (arg); - - // Does nothing - - return 0; + return this->cancellation (timer_queue, + event_handler, + 0); } -#endif /* ACE_TIMER_QUEUE_T_C*/ +#endif /* ACE_TIMER_QUEUE_T_C */ diff --git a/ace/Timer_Queue_T.h b/ace/Timer_Queue_T.h index 1cae4f56e8d..d0a10ccf3ec 100644 --- a/ace/Timer_Queue_T.h +++ b/ace/Timer_Queue_T.h @@ -22,7 +22,7 @@ # pragma once #endif /* ACE_LACKS_PRAGMA_ONCE */ -#include "ace/Test_and_Set.h" +#include "ace/Event_Handler.h" /** * @class ACE_Timer_Node_Dispatch_Info_T @@ -39,6 +39,9 @@ public: /// Asynchronous completion token associated with the timer. const void *act_; + + /// Flag to check if the timer is recurring. + int recurring_timer_; }; /** @@ -226,9 +229,9 @@ public: virtual const ACE_Time_Value &earliest_time (void) const = 0; /** - * Schedule <type> that will expire at <future_time>, - * which is specified in absolute time. If it expires then <act> is - * passed in as the value to the <functor>. If <interval> is != to + * Schedule <type> that will expire at <future_time>, which is + * specified in absolute time. If it expires then <act> is passed + * in as the value to the <functor>. If <interval> is != to * <ACE_Time_Value::zero> then it is used to reschedule the <type> * automatically, using relative time to the current <gettimeofday>. * This method returns a <timer_id> that uniquely identifies the the @@ -243,7 +246,7 @@ public: virtual long schedule (const TYPE &type, const void *act, const ACE_Time_Value &future_time, - const ACE_Time_Value &interval = ACE_Time_Value::zero) = 0; + const ACE_Time_Value &interval = ACE_Time_Value::zero); /** * Resets the interval of the timer represented by <timer_id> to @@ -291,8 +294,8 @@ public: * there is a node whose value <= <cur_time> else returns a 0. * */ - int dispatch_info (const ACE_Time_Value ¤t_time, - ACE_Timer_Node_Dispatch_Info_T<TYPE> &info); + virtual int dispatch_info (const ACE_Time_Value ¤t_time, + ACE_Timer_Node_Dispatch_Info_T<TYPE> &info); /** * Run the <functor> for all timers whose values are <= @@ -346,7 +349,7 @@ public: /// Determine the next event to timeout. Returns <max> if there are /// no pending timers or if all pending timers are longer than max. - /// This method acquires a lock internally since it modifies internal state. + /// This method acquires a lock internally since it modifies internal state. virtual ACE_Time_Value *calculate_timeout (ACE_Time_Value *max); /** @@ -354,7 +357,7 @@ public: * no pending timers or if all pending timers are longer than max. * <the_timeout> should be a pointer to storage for the timeout value, * and this value is also returned. This method does not acquire a - * lock internally since it doesn't modify internal state. If you + * lock internally since it doesn't modify internal state. If you * need to call this method when the queue is being modified * concurrently, however, you should make sure to acquire the <mutex()> * externally before making the call. @@ -390,14 +393,28 @@ public: /// after it is returned by a method like <remove_first>. virtual void return_node (ACE_Timer_Node_T<TYPE> *); + /// This method will call the preinvoke() on <functor>. + void preinvoke (ACE_Timer_Node_Dispatch_Info_T<TYPE> &info, + const ACE_Time_Value &cur_time, + const void *&upcall_act); + + /// This method will call the timeout() on <functor>. + void upcall (ACE_Timer_Node_Dispatch_Info_T<TYPE> &info, + const ACE_Time_Value &cur_time); - /// This method will call the <functor> with the <type>, <act> and - /// <cur_time> - /* virtual */ void upcall (TYPE &type, - const void *act, - const ACE_Time_Value &cur_time); + /// This method will call the postinvoke() on <functor>. + void postinvoke (ACE_Timer_Node_Dispatch_Info_T<TYPE> &info, + const ACE_Time_Value &cur_time, + const void *upcall_act); protected: + + /// Schedule a timer. + virtual long schedule_i (const TYPE &type, + const void *act, + const ACE_Time_Value &future_time, + const ACE_Time_Value &interval) = 0; + /// Reschedule an "interval" <ACE_Timer_Node>. virtual void reschedule (ACE_Timer_Node_T<TYPE> *) = 0; @@ -408,8 +425,8 @@ protected: virtual void free_node (ACE_Timer_Node_T<TYPE> *); /// Non-locking version of dispatch_info () - int dispatch_info_i (const ACE_Time_Value ¤t_time, - ACE_Timer_Node_Dispatch_Info_T<TYPE> &info); + virtual int dispatch_info_i (const ACE_Time_Value ¤t_time, + ACE_Timer_Node_Dispatch_Info_T<TYPE> &info); /// Synchronization variable for <ACE_Timer_Queue>. /// NOTE: the right name would be lock_, but HP/C++ will choke on that! @@ -467,22 +484,51 @@ public: /// Destructor. ~ACE_Event_Handler_Handle_Timeout_Upcall (void); - /// This method is called when the timer expires + /// This method is called when a timer is registered. + int registration (TIMER_QUEUE &timer_queue, + ACE_Event_Handler *handler, + const void *arg); + + /// This method is called before the timer expires. + int preinvoke (TIMER_QUEUE &timer_queue, + ACE_Event_Handler *handler, + const void *arg, + int recurring_timer, + const ACE_Time_Value &cur_time, + const void *&upcall_act); + + /// This method is called when the timer expires. int timeout (TIMER_QUEUE &timer_queue, ACE_Event_Handler *handler, const void *arg, + int recurring_timer, const ACE_Time_Value &cur_time); + /// This method is called after the timer expires. + int postinvoke (TIMER_QUEUE &timer_queue, + ACE_Event_Handler *handler, + const void *arg, + int recurring_timer, + const ACE_Time_Value &cur_time, + const void *upcall_act); + /// This method is called when the timer is cancelled int cancellation (TIMER_QUEUE &timer_queue, - ACE_Event_Handler *handler); + ACE_Event_Handler *handler, + int dont_call); /// This method is called when the timer queue is destroyed and /// the timer is still contained in it int deletion (TIMER_QUEUE &timer_queue, ACE_Event_Handler *handler, const void *arg); + private: + + /// Flag indicating that reference counting is required for this + /// event handler upcall. + int requires_reference_counting_; + // = Don't allow these operations for now. ACE_UNIMPLEMENTED_FUNC (ACE_Event_Handler_Handle_Timeout_Upcall (const ACE_Event_Handler_Handle_Timeout_Upcall<ACE_LOCK> &)) ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_Event_Handler_Handle_Timeout_Upcall<ACE_LOCK> &)) diff --git a/ace/Timer_Queue_T.i b/ace/Timer_Queue_T.i index 8af63669a6f..5a72678f105 100644 --- a/ace/Timer_Queue_T.i +++ b/ace/Timer_Queue_T.i @@ -126,6 +126,8 @@ ACE_Timer_Node_T<TYPE>::get_dispatch_info (ACE_Timer_Node_Dispatch_Info_T<TYPE> // Yes, do a copy info.type_ = this->type_; info.act_ = this->act_; + info.recurring_timer_ = + this->interval_ > ACE_Time_Value::zero; } template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_INLINE void @@ -160,13 +162,41 @@ ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::dispatch_info (const ACE_Time_Value } template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_INLINE void -ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::upcall (TYPE &type, - const void *act, - const ACE_Time_Value &cur_time) +ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::upcall (ACE_Timer_Node_Dispatch_Info_T<TYPE> &info, + const ACE_Time_Value &cur_time) { - this->upcall_functor ().timeout (*this, type, act, cur_time); + this->upcall_functor ().timeout (*this, + info.type_, + info.act_, + info.recurring_timer_, + cur_time); } +template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_INLINE void +ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::preinvoke (ACE_Timer_Node_Dispatch_Info_T<TYPE> &info, + const ACE_Time_Value &cur_time, + const void *&upcall_act) +{ + this->upcall_functor ().preinvoke (*this, + info.type_, + info.act_, + info.recurring_timer_, + cur_time, + upcall_act); +} + +template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_INLINE void +ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::postinvoke (ACE_Timer_Node_Dispatch_Info_T<TYPE> &info, + const ACE_Time_Value &cur_time, + const void *upcall_act) +{ + this->upcall_functor ().postinvoke (*this, + info.type_, + info.act_, + info.recurring_timer_, + cur_time, + upcall_act); +} template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_INLINE ACE_Time_Value ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::gettimeofday (void) diff --git a/ace/Timer_Wheel_T.cpp b/ace/Timer_Wheel_T.cpp index 2272210f92f..cd4e91cc103 100644 --- a/ace/Timer_Wheel_T.cpp +++ b/ace/Timer_Wheel_T.cpp @@ -92,24 +92,24 @@ ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::ACE_Timer_Wheel_T template <class TYPE, class FUNCTOR, class ACE_LOCK> int ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::power2bits (int n, - int min_bits, + int min_bits, int max_bits) { int max = (1 << max_bits) - 1; - if (n > max) + if (n > max) return max_bits; // count the bits in n. int i = 0; int tmp = n; - do + do { tmp >>= 1; ++i; - } + } while (tmp != 0); - if (i <= min_bits) + if (i <= min_bits) return min_bits; // Which is nearest? @@ -177,7 +177,9 @@ ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::~ACE_Timer_Wheel_T (void) for (ACE_Timer_Node_T<TYPE>* n = root->get_next (); n != root;) { ACE_Timer_Node_T<TYPE>* next = n->get_next (); - this->upcall_functor ().deletion (*this, n->get_type (), n->get_act ()); + this->upcall_functor ().deletion (*this, + n->get_type (), + n->get_act ()); this->free_node (n); n = next; } @@ -380,15 +382,12 @@ ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::generate_timer_id (u_int spoke) * -1 on failure. */ template <class TYPE, class FUNCTOR, class ACE_LOCK> long -ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::schedule ( - const TYPE& type, - const void* act, - const ACE_Time_Value& future_time, - const ACE_Time_Value& interval - ) +ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::schedule_i (const TYPE& type, + const void* act, + const ACE_Time_Value& future_time, + const ACE_Time_Value& interval) { ACE_TRACE ("ACE_Timer_Wheel_T::schedule"); - ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1)); ACE_Timer_Node_T<TYPE>* n = this->alloc_node (); @@ -533,8 +532,8 @@ ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::cancel (const TYPE& type, int skip_c ACE_Timer_Node_T<TYPE>* tmp = n; n = n->get_next (); - int always_skip_close = 1; // todo : Is this correct? - this->cancel_i (tmp, always_skip_close); + + this->cancel_i (tmp, skip_close); } else { @@ -547,9 +546,6 @@ ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::cancel (const TYPE& type, int skip_c this->recalc_earliest (last); } - if (!skip_close) // && num_canceled > 0) - this->upcall_functor().cancellation (*this, type); - return num_canceled; } @@ -600,14 +596,16 @@ ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::cancel_i (ACE_Timer_Node_T<TYPE>* n, //ACE_ERROR((LM_ERROR, "Canceling %x\n", (long) n)); this->unlink (n); this->free_node (n); - if (!skip_close) - this->upcall_functor ().cancellation (*this, n->get_type ()); + + this->upcall_functor ().cancellation (*this, + n->get_type (), + skip_close); } /// There are a few places where we have to figure out which timer /// will expire next. This method makes the assumption that spokes /// are always sorted, and that timers are always in the correct spoke -/// determined from their expiration time. +/// determined from their expiration time. /// The last time is always passed in, even though you can often calculate /// it as get_first()->get_timer_value(). template <class TYPE, class FUNCTOR, class ACE_LOCK> void @@ -619,7 +617,7 @@ ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::recalc_earliest return; ACE_Time_Value et = ACE_Time_Value::zero; - + u_int spoke = this->earliest_spoke_; // We will have to go around the wheel at most one time. @@ -655,14 +653,14 @@ ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::dump (void) const { ACE_TRACE ("ACE_Timer_Wheel_T::dump"); ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); - + ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nspoke_count_ = %d"), this->spoke_count_)); ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nresolution_ = %d"), 1 << this->res_bits_)); ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nwheel_ = \n"))); - + for (u_int i = 0; i < this->spoke_count_; ++i) { ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("%d\n"), i)); @@ -674,7 +672,7 @@ ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::dump (void) const n->dump (); } } - + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); } @@ -720,7 +718,7 @@ ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::remove_first_expired (const ACE_Time * * @return The earliest timer node. */ -template <class TYPE, class FUNCTOR, class ACE_LOCK> +template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_Timer_Node_T<TYPE>* ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::get_first (void) { @@ -728,7 +726,7 @@ ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::get_first (void) return this->get_first_i (); } -template <class TYPE, class FUNCTOR, class ACE_LOCK> +template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_Timer_Node_T<TYPE>* ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::get_first_i (void) const { @@ -743,7 +741,7 @@ ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::get_first_i (void) const /** * @return The iterator */ -template <class TYPE, class FUNCTOR, class ACE_LOCK> +template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>& ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::iter (void) { @@ -763,7 +761,7 @@ ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::expire () /** * This is a specialized version of expire that is more suited for the -* internal data representation. +* internal data representation. * * @param cur_time The time to expire timers up to. * @@ -780,15 +778,32 @@ ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::expire (const ACE_Time_Value& cur_ti while (n != 0) { - ++ expcount; + ++expcount; //ACE_ERROR((LM_ERROR, "Expiring %x\n", (long) n)); - this->upcall (n->get_type (), n->get_act (), cur_time); + ACE_Timer_Node_Dispatch_Info_T<TYPE> info; + + // Get the dispatch info + n->get_dispatch_info (info); + + const void *upcall_act = 0; + + this->preinvoke (info, cur_time, upcall_act); + + this->upcall (info, cur_time); + + this->postinvoke (info, cur_time, upcall_act); if (n->get_interval () > ACE_Time_Value::zero) { - n->set_timer_value (cur_time + n->get_interval ()); + // Make sure that we skip past values that have already + // "expired". + do + n->set_timer_value (n->get_timer_value () + + n->get_interval ()); + while (n->get_timer_value () <= cur_time); + this->reschedule (n); } else @@ -806,7 +821,7 @@ ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::expire (const ACE_Time_Value& cur_ti /////////////////////////////////////////////////////////////////////////// // ACE_Timer_Wheel_Iterator_T - + /** * Just initializes the iterator with a ACE_Timer_Wheel_T and then calls * first() to initialize the rest of itself. @@ -814,7 +829,7 @@ ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::expire (const ACE_Time_Value& cur_ti * @param wheel A reference for a timer queue to iterate over */ template <class TYPE, class FUNCTOR, class ACE_LOCK> -ACE_Timer_Wheel_Iterator_T<TYPE,FUNCTOR,ACE_LOCK>::ACE_Timer_Wheel_Iterator_T +ACE_Timer_Wheel_Iterator_T<TYPE,FUNCTOR,ACE_LOCK>::ACE_Timer_Wheel_Iterator_T (Wheel& wheel) : timer_wheel_ (wheel) { diff --git a/ace/Timer_Wheel_T.h b/ace/Timer_Wheel_T.h index 9505d918741..62f7ab916f1 100644 --- a/ace/Timer_Wheel_T.h +++ b/ace/Timer_Wheel_T.h @@ -119,13 +119,6 @@ public: /// Must be called on a non-empty queue. virtual const ACE_Time_Value& earliest_time (void) const; - /// Schedules a timer. - virtual long schedule (const TYPE& type, - const void* act, - const ACE_Time_Value& future_time, - const ACE_Time_Value& interval - = ACE_Time_Value::zero); - /// Changes the interval of a timer (and can make it periodic or non /// periodic by setting it to ACE_Time_Value::zero or not). virtual int reset_interval (long timer_id, @@ -165,7 +158,15 @@ public: /// Reads the earliest node from the queue and returns it. virtual ACE_Timer_Node_T<TYPE>* get_first (void); - + +protected: + + /// Schedules a timer. + virtual long schedule_i (const TYPE& type, + const void* act, + const ACE_Time_Value& future_time, + const ACE_Time_Value& interval); + private: // The following are documented in the .cpp file. ACE_Timer_Node_T<TYPE>* get_first_i (void) const; diff --git a/ace/WFMO_Reactor.cpp b/ace/WFMO_Reactor.cpp index 3f55ad7a693..76ab94911ec 100644 --- a/ace/WFMO_Reactor.cpp +++ b/ace/WFMO_Reactor.cpp @@ -652,6 +652,15 @@ ACE_WFMO_Reactor_Handler_Repository::bind_i (int io_entry, this->handles_to_be_added_++; + int requires_reference_counting = + event_handler->reference_counting_policy ().value () == + ACE_Event_Handler::Reference_Counting_Policy::ENABLED; + + if (requires_reference_counting) + { + event_handler->add_reference (); + } + // Wake up all threads in WaitForMultipleObjects so that they can // reconsult the handle set this->wfmo_reactor_.wakeup_all_threads (); @@ -672,7 +681,8 @@ ACE_WFMO_Reactor_Handler_Repository::make_changes_in_current_infos (void) // have been schedule for deletion if (this->handles_to_be_deleted_ > 0 || this->handles_to_be_suspended_ > 0) { - for (size_t i = 0; i < this->max_handlep1_; i++) + size_t i = 0; + while (i < this->max_handlep1_) { // This stuff is necessary here, since we should not make // the upcall until all the internal data structures have @@ -747,11 +757,29 @@ ACE_WFMO_Reactor_Handler_Repository::make_changes_in_current_infos (void) this->current_handles_[last_valid_slot] = ACE_INVALID_HANDLE; this->max_handlep1_--; } + else + { + // This current entry is not up for deletion or + // suspension. Proceed to the next entry in the current + // handles. + ++i; + } // Now that all internal structures have been updated, make // the upcall. if (event_handler != 0) - event_handler->handle_close (handle, masks); + { + int requires_reference_counting = + event_handler->reference_counting_policy ().value () == + ACE_Event_Handler::Reference_Counting_Policy::ENABLED; + + event_handler->handle_close (handle, masks); + + if (requires_reference_counting) + { + event_handler->remove_reference (); + } + } } } @@ -764,7 +792,8 @@ ACE_WFMO_Reactor_Handler_Repository::make_changes_in_suspension_infos (void) // Go through the <suspended_handle> array if (this->handles_to_be_deleted_ > 0 || this->handles_to_be_resumed_ > 0) { - for (size_t i = 0; i < this->suspended_handles_; i++) + size_t i = 0; + while (i < this->suspended_handles_) { // This stuff is necessary here, since we should not make // the upcall until all the internal data structures have @@ -836,11 +865,29 @@ ACE_WFMO_Reactor_Handler_Repository::make_changes_in_suspension_infos (void) this->current_suspended_info_[last_valid_slot].reset (); this->suspended_handles_--; } + else + { + // This current entry is not up for deletion or + // resumption. Proceed to the next entry in the + // suspended handles. + ++i; + } // Now that all internal structures have been updated, make // the upcall. if (event_handler != 0) - event_handler->handle_close (handle, masks); + { + int requires_reference_counting = + event_handler->reference_counting_policy ().value () == + ACE_Event_Handler::Reference_Counting_Policy::ENABLED; + + event_handler->handle_close (handle, masks); + + if (requires_reference_counting) + { + event_handler->remove_reference (); + } + } } } @@ -920,7 +967,18 @@ ACE_WFMO_Reactor_Handler_Repository::make_changes_in_to_be_added_infos (void) // Now that all internal structures have been updated, make the // upcall. if (event_handler != 0) - event_handler->handle_close (handle, masks); + { + int requires_reference_counting = + event_handler->reference_counting_policy ().value () == + ACE_Event_Handler::Reference_Counting_Policy::ENABLED; + + event_handler->handle_close (handle, masks); + + if (requires_reference_counting) + { + event_handler->remove_reference (); + } + } } // Since all to be added handles have been taken care of, reset the @@ -1282,12 +1340,15 @@ ACE_WFMO_Reactor::register_handler_i (ACE_HANDLE event_handle, // If this is a Winsock 1 system, the underlying event assignment will // not work, so don't try. Winsock 1 must use ACE_Select_Reactor for // reacting to socket activity. + #if !defined (ACE_HAS_WINSOCK2) || (ACE_HAS_WINSOCK2 == 0) + ACE_UNUSED_ARG (event_handle); ACE_UNUSED_ARG (io_handle); ACE_UNUSED_ARG (event_handler); ACE_UNUSED_ARG (new_masks); ACE_NOTSUP_RETURN (-1); + #else // Make sure that the <handle> is valid @@ -1361,7 +1422,9 @@ ACE_WFMO_Reactor::register_handler_i (ACE_HANDLE event_handle, } else return -1; -#endif /* ACE_HAS_PHARLAP */ + +#endif /* ACE_HAS_WINSOCK2 || ACE_HAS_WINSOCK2 == 0 */ + } int @@ -1467,15 +1530,22 @@ ACE_WFMO_Reactor_Handler_Repository::modify_network_events_i (ACE_HANDLE io_hand return found; } -int +ACE_Event_Handler * +ACE_WFMO_Reactor_Handler_Repository::handler (ACE_HANDLE handle) +{ + long existing_masks_ignored = 0; + return this->handler (handle, + existing_masks_ignored); +} + +ACE_Event_Handler * ACE_WFMO_Reactor_Handler_Repository::handler (ACE_HANDLE handle, - ACE_Reactor_Mask user_masks, - ACE_Event_Handler **user_event_handler) + long &existing_masks) { int found = 0; size_t i = 0; ACE_Event_Handler *event_handler = 0; - long existing_masks = 0; + existing_masks = 0; // Look for the handle first @@ -1521,7 +1591,36 @@ ACE_WFMO_Reactor_Handler_Repository::handler (ACE_HANDLE handle, existing_masks = this->to_be_added_info_[i].network_events_; } - // If the handle is not found, return failure. + if (event_handler) + { + int requires_reference_counting = + event_handler->reference_counting_policy ().value () == + ACE_Event_Handler::Reference_Counting_Policy::ENABLED; + + if (requires_reference_counting) + { + event_handler->add_reference (); + } + } + + return event_handler; +} + +int +ACE_WFMO_Reactor_Handler_Repository::handler (ACE_HANDLE handle, + ACE_Reactor_Mask user_masks, + ACE_Event_Handler **user_event_handler) +{ + long existing_masks = 0; + int found = 0; + + ACE_Event_Handler_var safe_event_handler = + this->handler (handle, + existing_masks); + + if (safe_event_handler.handler ()) + found = 1; + if (!found) return -1; @@ -1529,8 +1628,8 @@ ACE_WFMO_Reactor_Handler_Repository::handler (ACE_HANDLE handle, // are on. if (found && ACE_BIT_ENABLED (user_masks, ACE_Event_Handler::READ_MASK)) - if (!ACE_BIT_ENABLED (existing_masks, FD_READ) - && !ACE_BIT_ENABLED (existing_masks, FD_CLOSE)) + if (!ACE_BIT_ENABLED (existing_masks, FD_READ) && + !ACE_BIT_ENABLED (existing_masks, FD_CLOSE)) found = 0; if (found && @@ -1565,7 +1664,7 @@ ACE_WFMO_Reactor_Handler_Repository::handler (ACE_HANDLE handle, if (found && user_event_handler) - *user_event_handler = event_handler; + *user_event_handler = safe_event_handler.release (); if (found) return 0; @@ -1899,14 +1998,29 @@ ACE_WFMO_Reactor::simple_dispatch_handler (DWORD slot, // siginfo_t is an ACE - specific fabrication. Constructor exists. siginfo_t sig (event_handle); - ACE_Event_Handler *eh = + ACE_Event_Handler *event_handler = this->handler_rep_.current_info ()[slot].event_handler_; + int requires_reference_counting = + event_handler->reference_counting_policy ().value () == + ACE_Event_Handler::Reference_Counting_Policy::ENABLED; + + if (requires_reference_counting) + { + event_handler->add_reference (); + } + // Upcall - if (eh->handle_signal (0, &sig) == -1) + if (event_handler->handle_signal (0, &sig) == -1) this->handler_rep_.unbind (event_handle, ACE_Event_Handler::NULL_MASK); + // Call remove_reference() if needed. + if (requires_reference_counting) + { + event_handler->remove_reference (); + } + return 0; } @@ -1941,10 +2055,30 @@ ACE_WFMO_Reactor::complex_dispatch_handler (DWORD slot, events.lNetworkEvents &= current_info.network_events_; while (events.lNetworkEvents != 0) { + ACE_Event_Handler *event_handler = + current_info.event_handler_; + + int reference_counting_required = + event_handler->reference_counting_policy ().value () == + ACE_Event_Handler::Reference_Counting_Policy::ENABLED; + + // Call add_reference() if needed. + if (reference_counting_required) + { + event_handler->add_reference (); + } + // Upcall problems |= this->upcall (current_info.event_handler_, current_info.io_handle_, events); + + // Call remove_reference() if needed. + if (reference_counting_required) + { + event_handler->remove_reference (); + } + if (this->handler_rep_.scheduled_for_deletion (slot)) break; } @@ -2276,25 +2410,32 @@ ACE_WFMO_Reactor_Notify::handle_signal (int signum, if (buffer->eh_ != 0) { + ACE_Event_Handler *event_handler = + buffer->eh_; + + int requires_reference_counting = + event_handler->reference_counting_policy ().value () == + ACE_Event_Handler::Reference_Counting_Policy::ENABLED; + int result = 0; switch (buffer->mask_) { case ACE_Event_Handler::READ_MASK: case ACE_Event_Handler::ACCEPT_MASK: - result = buffer->eh_->handle_input (ACE_INVALID_HANDLE); + result = event_handler->handle_input (ACE_INVALID_HANDLE); break; case ACE_Event_Handler::WRITE_MASK: - result = buffer->eh_->handle_output (ACE_INVALID_HANDLE); + result = event_handler->handle_output (ACE_INVALID_HANDLE); break; case ACE_Event_Handler::EXCEPT_MASK: - result = buffer->eh_->handle_exception (ACE_INVALID_HANDLE); + result = event_handler->handle_exception (ACE_INVALID_HANDLE); break; case ACE_Event_Handler::QOS_MASK: - result = buffer->eh_->handle_qos (ACE_INVALID_HANDLE); + result = event_handler->handle_qos (ACE_INVALID_HANDLE); break; case ACE_Event_Handler::GROUP_QOS_MASK: - result = buffer->eh_->handle_group_qos (ACE_INVALID_HANDLE); + result = event_handler->handle_group_qos (ACE_INVALID_HANDLE); break; default: ACE_ERROR ((LM_ERROR, @@ -2302,9 +2443,15 @@ ACE_WFMO_Reactor_Notify::handle_signal (int signum, buffer->mask_)); break; } + if (result == -1) - buffer->eh_->handle_close (ACE_INVALID_HANDLE, - ACE_Event_Handler::EXCEPT_MASK); + event_handler->handle_close (ACE_INVALID_HANDLE, + ACE_Event_Handler::EXCEPT_MASK); + + if (requires_reference_counting) + { + event_handler->remove_reference (); + } } // Make sure to delete the memory regardless of success or @@ -2333,11 +2480,11 @@ ACE_WFMO_Reactor_Notify::handle_signal (int signum, // thread of control. int -ACE_WFMO_Reactor_Notify::notify (ACE_Event_Handler *eh, +ACE_WFMO_Reactor_Notify::notify (ACE_Event_Handler *event_handler, ACE_Reactor_Mask mask, ACE_Time_Value *timeout) { - if (eh != 0) + if (event_handler != 0) { ACE_Message_Block *mb = 0; ACE_NEW_RETURN (mb, @@ -2346,7 +2493,7 @@ ACE_WFMO_Reactor_Notify::notify (ACE_Event_Handler *eh, ACE_Notification_Buffer *buffer = (ACE_Notification_Buffer *) mb->base (); - buffer->eh_ = eh; + buffer->eh_ = event_handler; buffer->mask_ = mask; // Convert from relative time to absolute time by adding the @@ -2361,6 +2508,15 @@ ACE_WFMO_Reactor_Notify::notify (ACE_Event_Handler *eh, mb->release (); return -1; } + + int requires_reference_counting = + event_handler->reference_counting_policy ().value () == + ACE_Event_Handler::Reference_Counting_Policy::ENABLED; + + if (requires_reference_counting) + { + event_handler->add_reference (); + } } return this->wakeup_one_thread_.signal (); @@ -2433,22 +2589,33 @@ ACE_WFMO_Reactor_Notify::purge_pending_notifications (ACE_Event_Handler *eh, ACE_BIT_DISABLED (buffer->mask_, ~mask)) // the existing notification mask // is left with nothing when // applying the mask - { - mb->release (); - ++number_purged; - } + { + ACE_Event_Handler *event_handler = eh; + + int requires_reference_counting = + event_handler->reference_counting_policy ().value () == + ACE_Event_Handler::Reference_Counting_Policy::ENABLED; + + if (requires_reference_counting) + { + event_handler->remove_reference (); + } + + mb->release (); + ++number_purged; + } else - { - // To preserve it, move it to the local_queue. But first, if - // this is not a Reactor notify (it is for a - // particularhandler), and it matches the specified handler - // (or purging all), then apply the mask - if ((0 != buffer->eh_) && - (0 == eh || eh == buffer->eh_)) - ACE_CLR_BITS(buffer->mask_, mask); - if (-1 == local_queue.enqueue_head (mb)) - return -1; - } + { + // To preserve it, move it to the local_queue. But first, if + // this is not a Reactor notify (it is for a + // particularhandler), and it matches the specified handler + // (or purging all), then apply the mask + if ((0 != buffer->eh_) && + (0 == eh || eh == buffer->eh_)) + ACE_CLR_BITS(buffer->mask_, mask); + if (-1 == local_queue.enqueue_head (mb)) + return -1; + } } if (this->message_queue_.message_count ()) diff --git a/ace/WFMO_Reactor.h b/ace/WFMO_Reactor.h index e8c81546c09..77d46eb25db 100644 --- a/ace/WFMO_Reactor.h +++ b/ace/WFMO_Reactor.h @@ -403,6 +403,12 @@ public: ACE_Reactor_Mask to_be_removed_masks); /** + * Return the Event_Handler associated with <handle>. Return 0 if + * <handle> is not registered. + */ + ACE_Event_Handler *handler (ACE_HANDLE handle); + + /** * Check to see if <handle> is associated with a valid Event_Handler * bound to <mask>. Return the <event_handler> associated with this * <handler> if <event_handler> != 0. @@ -411,6 +417,13 @@ public: ACE_Reactor_Mask mask, ACE_Event_Handler **event_handler = 0); + /** + * Check to see if <handle> is associated with a valid + * Event_Handler. Return Event_Handler and associated masks. + */ + ACE_Event_Handler *handler (ACE_HANDLE handle, + long &existing_masks); + /// Dump the state of an object. void dump (void) const; @@ -1057,6 +1070,12 @@ public: // = Assorted helper methods. /** + * Return the Event_Handler associated with <handle>. Return 0 if + * <handle> is not registered. + */ + ACE_Event_Handler *handler (ACE_HANDLE handle); + + /** * Check to see if <handle> is associated with a valid Event_Handler * bound to <mask>. Return the <event_handler> associated with this * <handler> if <event_handler> != 0. diff --git a/ace/WFMO_Reactor.i b/ace/WFMO_Reactor.i index 98c6c5d81ba..291463c39d6 100644 --- a/ace/WFMO_Reactor.i +++ b/ace/WFMO_Reactor.i @@ -1082,11 +1082,21 @@ ACE_WFMO_Reactor::ready_ops (ACE_HANDLE handle, ACE_NOTSUP_RETURN (-1); } +ACE_INLINE ACE_Event_Handler * +ACE_WFMO_Reactor::handler (ACE_HANDLE handle) +{ + ACE_GUARD_RETURN (ACE_Process_Mutex, ace_mon, this->lock_, 0); + + return this->handler_rep_.handler (handle); +} + ACE_INLINE int ACE_WFMO_Reactor::handler (ACE_HANDLE handle, ACE_Reactor_Mask mask, ACE_Event_Handler **event_handler) { + ACE_GUARD_RETURN (ACE_Process_Mutex, ace_mon, this->lock_, -1); + return this->handler_rep_.handler (handle, mask, event_handler); diff --git a/tests/Conn_Test.cpp b/tests/Conn_Test.cpp index 7dd4842f45f..a54c913e6ef 100644 --- a/tests/Conn_Test.cpp +++ b/tests/Conn_Test.cpp @@ -123,16 +123,11 @@ template class ACE_Hash_Map_Reverse_Iterator<REFCOUNTED_HASH_RECYCLABLE_ADDR, Sv template class ACE_Hash_Map_Reverse_Iterator_Ex<REFCOUNTED_HASH_RECYCLABLE_ADDR, Svc_Handler *, ACE_Hash<REFCOUNTED_HASH_RECYCLABLE_ADDR>, ACE_Equal_To<REFCOUNTED_HASH_RECYCLABLE_ADDR>, ACE_SYNCH_RW_MUTEX>; template class ACE_LOCK_SOCK_Acceptor<ACCEPTOR_LOCKING>; template class ACE_Oneshot_Acceptor<Svc_Handler, LOCK_SOCK_ACCEPTOR>; -template class ACE_Map_Entry<ACE_HANDLE, ACE_Svc_Tuple<Svc_Handler> *>; -template class ACE_Map_Manager<ACE_HANDLE, ACE_Svc_Tuple<Svc_Handler> *, ACE_SYNCH_RW_MUTEX>; -template class ACE_Map_Iterator_Base<ACE_HANDLE, ACE_Svc_Tuple<Svc_Handler> *, ACE_SYNCH_RW_MUTEX>; -template class ACE_Map_Iterator<ACE_HANDLE, ACE_Svc_Tuple<Svc_Handler> *, ACE_SYNCH_RW_MUTEX>; -template class ACE_Map_Reverse_Iterator<ACE_HANDLE, ACE_Svc_Tuple<Svc_Handler> *, ACE_SYNCH_RW_MUTEX>; template class ACE_NOOP_Concurrency_Strategy<Svc_Handler>; template class ACE_Recycling_Strategy<Svc_Handler>; template class ACE_Strategy_Connector<Svc_Handler, ACE_SOCK_CONNECTOR>; template class ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH>; -template class ACE_Svc_Tuple<Svc_Handler>; +template class ACE_NonBlocking_Connect_EH<Svc_Handler, ACE_SYNCH_MUTEX>; template class ACE_Auto_Basic_Array_Ptr<pid_t>; #if defined (__BORLANDC__) @@ -179,16 +174,11 @@ template class ACE_Unbounded_Queue<ACE_Thread_Descriptor*>; #pragma instantiate ACE_Hash_Map_Reverse_Iterator_Ex<REFCOUNTED_HASH_RECYCLABLE_ADDR, Svc_Handler *, ACE_Hash<REFCOUNTED_HASH_RECYCLABLE_ADDR>, ACE_Equal_To<REFCOUNTED_HASH_RECYCLABLE_ADDR>, ACE_SYNCH_RW_MUTEX> #pragma instantiate ACE_LOCK_SOCK_Acceptor<ACCEPTOR_LOCKING> #pragma instantiate ACE_Oneshot_Acceptor<Svc_Handler, LOCK_SOCK_ACCEPTOR> -#pragma instantiate ACE_Map_Entry<ACE_HANDLE, ACE_Svc_Tuple<Svc_Handler> *> -#pragma instantiate ACE_Map_Manager<ACE_HANDLE, ACE_Svc_Tuple<Svc_Handler> *, ACE_SYNCH_RW_MUTEX> -#pragma instantiate ACE_Map_Iterator_Base<ACE_HANDLE, ACE_Svc_Tuple<Svc_Handler> *, ACE_SYNCH_RW_MUTEX> -#pragma instantiate ACE_Map_Iterator<ACE_HANDLE, ACE_Svc_Tuple<Svc_Handler> *, ACE_SYNCH_RW_MUTEX> -#pragma instantiate ACE_Map_Reverse_Iterator<ACE_HANDLE, ACE_Svc_Tuple<Svc_Handler> *, ACE_SYNCH_RW_MUTEX> #pragma instantiate ACE_NOOP_Concurrency_Strategy<Svc_Handler> #pragma instantiate ACE_Recycling_Strategy<Svc_Handler> #pragma instantiate ACE_Strategy_Connector<Svc_Handler, ACE_SOCK_CONNECTOR> #pragma instantiate ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH> -#pragma instantiate ACE_Svc_Tuple<Svc_Handler> +#pragma instantiate ACE_NonBlocking_Connect_EH<Svc_Handler, ACE_SYNCH_MUTEX> #pragma instantiate ACE_Auto_Basic_Array_Ptr<pid_t> #if defined (__BORLANDC__) diff --git a/tests/MT_Reference_Counted_Event_Handler_Test.cpp b/tests/MT_Reference_Counted_Event_Handler_Test.cpp new file mode 100644 index 00000000000..7069b61a1ff --- /dev/null +++ b/tests/MT_Reference_Counted_Event_Handler_Test.cpp @@ -0,0 +1,1240 @@ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// tests +// +// = FILENAME +// MT_Reference_Counted_Event_Handler_Test.cpp +// +// = DESCRIPTION +// +// This test tries to represents what happens in the ORB wrt to +// event handlers, reactors, timer queues, threads, and connection +// caches, minus the other complexities. The following three +// Reactors are tested: Select, TP, and WFMO. +// +// The test checks proper use and shutting down of client-side +// event handlers when it is used by invocation threads and/or +// event loop threads. Server-side event handlers are either +// threaded or reactive. A purger thread is introduced to check the +// connection recycling and cache purging. Nested upcalls are also +// tested. +// +// = AUTHOR +// Irfan Pyarali <irfan@oomworks.com> +// +// ============================================================================ + +#include "test_config.h" +#include "ace/Select_Reactor.h" +#include "ace/TP_Reactor.h" +#include "ace/WFMO_Reactor.h" +#include "ace/Get_Opt.h" +#include "ace/Task.h" + +ACE_RCSID(tests, MT_Reference_Counted_Event_Handler_Test, "$Id$") + +#if defined (ACE_HAS_THREADS) + +static const char message[] = "abcdefghijklmnopqrstuvwxyz"; +static const int message_size = 26; +static int test_select_reactor = 1; +static int test_tp_reactor = 1; +static int test_wfmo_reactor = 1; +static int debug = 0; +static int number_of_connections = 5; +static int max_nested_upcall_level = 10; +static int close_timeout = 500; +static int pipe_open_attempts = 10; +static int pipe_retry_timeout = 1; +static int make_invocations = -1; +static int run_event_loop_thread = -1; +static int run_purger_thread = -1; +static int run_receiver_thread = -1; +static int nested_upcalls = -1; + +static ACE_HANDLE server_handle = ACE_INVALID_HANDLE; +static ACE_HANDLE client_handle = ACE_INVALID_HANDLE; + +static int number_of_options = 5; +static int test_configs[][5] = + { + // + // make_invocations, run_event_loop_thread, run_purger_thread, run_receiver_thread, nested_upcalls + // + + // 0, 0, 0, 0, 0, // At least one thread should be running. + // 0, 0, 0, 1, 0, // If event_loop_thread is not running and invocation_thread is not making invocations, + // no thread will know that the socket is closed. + // 0, 0, 1, 0, 0, // If invocation_thread is not making invocations and if receiver is not threaded, + // we cannot decide which socket to close. + // 0, 0, 1, 1, 0, // If event_loop_thread is not running and invocation_thread is not making invocations, + // no thread will know that the socket is closed. + // 0, 1, 0, 0, 0, // If invocation_thread is not making invocations and if receiver is not threaded, + // we cannot decide which socket to close. + 0, 1, 0, 1, 0, + // 0, 1, 0, 1, 1, // No need for nested upcalls without invocations. + // 0, 1, 1, 0, 0, // If invocation_thread is not making invocations and if receiver is not threaded, + // we cannot decide which socket to close. + 0, 1, 1, 1, 0, + // 0, 1, 1, 1, 1, // No need for nested upcalls without invocations. + // 1, 0, 0, 0, 0, // If both event_loop_thread and receiver are not threaded, + // no thread can receive the messages. + 1, 0, 0, 1, 0, + // 1, 0, 0, 1, 1, // No need for nested upcalls without event loop being used by the receiver. + // 1, 0, 1, 0, 0, // If both event_loop_thread and receiver are not threaded, + // no thread can receive the messages. + 1, 0, 1, 1, 0, + // 1, 0, 1, 1, 1, // No need for nested upcalls without event loop being used by the receiver. + 1, 1, 0, 0, 0, + 1, 1, 0, 0, 1, + 1, 1, 0, 1, 0, + // 1, 1, 0, 1, 1, // No need for nested upcalls without event loop being used by the receiver. + 1, 1, 1, 0, 0, + 1, 1, 1, 0, 1, + 1, 1, 1, 1, 0, + // 1, 1, 1, 1, 1, // No need for nested upcalls without event loop being used by the receiver. + }; + +class Connection_Cache; +class Event_Loop_Thread; + +static Event_Loop_Thread *global_event_loop_thread_variable = 0; + +class Sender : public ACE_Event_Handler +{ +public: + + Sender (ACE_HANDLE handle, + Connection_Cache &connection_cache); + + ~Sender (void); + + int handle_input (ACE_HANDLE); + + ssize_t send_message (void); + + void close (void); + + ACE_HANDLE handle_; + + Connection_Cache &connection_cache_; + +}; + +class Connection_Cache +{ +public: + + Connection_Cache (void); + + ~Connection_Cache (void); + + void add_connection (Sender *sender); + + void remove_connection (Sender *sender); + + Sender *acquire_connection (void); + + void release_connection (Sender *sender); + + int find (Sender *sender); + + ACE_SYNCH_MUTEX &lock (void); + + enum State + { + IDLE, + BUSY, + NOT_IN_CACHE + }; + + struct Entry + { + Sender *sender_; + State state_; + }; + + Entry *entries_; + + ACE_SYNCH_MUTEX lock_; +}; + +Sender::Sender (ACE_HANDLE handle, + Connection_Cache &connection_cache) + : handle_ (handle), + connection_cache_ (connection_cache) +{ + // Enable reference counting. + this->reference_counting_policy ().value + (ACE_Event_Handler::Reference_Counting_Policy::ENABLED); + + if (debug) + ACE_DEBUG ((LM_DEBUG, + "Reference count in Sender::Sender() is %d\n", + this->reference_count_.value ())); +} + +Sender::~Sender (void) +{ + if (debug) + ACE_DEBUG ((LM_DEBUG, + "Reference count in ~Sender::Sender() is %d\n", + this->reference_count_.value ())); + + // Close the socket that we are responsible for. + ACE_OS::closesocket (this->handle_); +} + +int +Sender::handle_input (ACE_HANDLE) +{ + if (debug) + ACE_DEBUG ((LM_DEBUG, + "Reference count in Sender::handle_input() is %d\n", + this->reference_count_.value ())); + + // + // In this test, this method is only called when the connection has + // been closed. Remove self from Reactor. + // + + ACE_DEBUG ((LM_DEBUG, + "Event loop thread calling Sender::close() for handle %d\n", + this->handle_)); + + this->close (); + + return 0; +} + +void +Sender::close (void) +{ + // Remove socket from Reactor (may fail if another thread has already + // removed the handle from the Reactor). + this->reactor ()->remove_handler (this->handle_, + ACE_Event_Handler::ALL_EVENTS_MASK); + + // Remove self from connection cache (may fail if another thread has + // already removed "this" from the cache). + this->connection_cache_.remove_connection (this); +} + +ssize_t +Sender::send_message (void) +{ + return ACE::send_n (this->handle_, + message, + message_size); +} + +class Event_Loop_Thread : public ACE_Task_Base +{ +public: + + Event_Loop_Thread (ACE_Thread_Manager &thread_manager, + ACE_Reactor &reactor); + + int svc (void); + + ACE_Reactor &reactor_; + +}; + +class Receiver : public ACE_Task_Base +{ +public: + + Receiver (ACE_Thread_Manager &thread_manager, + ACE_HANDLE handle, + int nested_upcalls); + + ~Receiver (void); + + int svc (void); + + int close (u_long flags); + + int handle_input (ACE_HANDLE); + + int resume_handler (void); + + ACE_HANDLE handle_; + + int counter_; + + int nested_upcalls_; + + int nested_upcalls_level_; + +}; + +Receiver::Receiver (ACE_Thread_Manager &thread_manager, + ACE_HANDLE handle, + int nested_upcalls) + : handle_ (handle), + counter_ (1), + nested_upcalls_ (nested_upcalls), + nested_upcalls_level_ (0), + ACE_Task_Base (&thread_manager) +{ + // Enable reference counting. + this->reference_counting_policy ().value + (ACE_Event_Handler::Reference_Counting_Policy::ENABLED); + + if (debug) + ACE_DEBUG ((LM_DEBUG, + "Reference count in Receiver::Receiver() is %d\n", + this->reference_count_.value ())); +} + +Receiver::~Receiver (void) +{ + if (debug) + ACE_DEBUG ((LM_DEBUG, + "Reference count in ~Receiver::Receiver() is %d\n", + this->reference_count_.value ())); + + // Close the socket that we are responsible for. + ACE_OS::closesocket (this->handle_); +} + +int +Receiver::svc (void) +{ + // + // Continuously receive messages from the Sender. On error, exit + // thread. + // + + int result = 0; + + while (result != -1) + { + result = + this->handle_input (this->handle_); + } + + return 0; +} + +int +Receiver::handle_input (ACE_HANDLE handle) +{ + char buf[message_size + 1]; + + // Receive message. + ssize_t result = + ACE::recv_n (handle, + buf, + sizeof buf - 1); + + if (this->reactor ()) + this->reactor ()->resume_handler (handle); + + if (result == message_size) + { + if (debug) + ACE_DEBUG ((LM_DEBUG, + "Message %d received on handle %d\n", + this->counter_++, + handle)); + + if (this->thr_count () == 0 && + this->nested_upcalls_) + { + this->nested_upcalls_level_++; + + if (debug) + ACE_DEBUG ((LM_DEBUG, + "Nesting level %d\n", + this->nested_upcalls_level_)); + + if (this->nested_upcalls_level_ != max_nested_upcall_level) + global_event_loop_thread_variable->svc (); + + this->nested_upcalls_level_--; + return 0; + } + else + return 0; + } + else + { + if (debug) + ACE_DEBUG ((LM_DEBUG, + "/*** Problem in receiving message %d on handle %d: shutting down receiving thread ***/\n", + this->counter_, + handle)); + + return -1; + } +} + +int +Receiver::resume_handler (void) +{ + /// The application takes responsibility of resuming the handler. + return ACE_APPLICATION_RESUMES_HANDLER; +} + +int +Receiver::close (u_long) +{ + // If threaded, we are responsible for deleting this instance when + // the thread completes. If not threaded, Reactor reference + // counting will handle the deletion of this instance. + delete this; + return 0; +} + +class Connector +{ +public: + + Connector (ACE_Thread_Manager &thread_manager, + ACE_Reactor &reactor, + int nested_upcalls); + + int connect (ACE_HANDLE &client_handle, + ACE_HANDLE &server_handle, + int run_receiver_thread); + + ACE_Thread_Manager &thread_manager_; + + ACE_Reactor &reactor_; + + int nested_upcalls_; + +}; + +Connector::Connector (ACE_Thread_Manager &thread_manager, + ACE_Reactor &reactor, + int nested_upcalls) + : thread_manager_ (thread_manager), + reactor_ (reactor), + nested_upcalls_ (nested_upcalls) +{ +} + +int +Connector::connect (ACE_HANDLE &client_handle, + ACE_HANDLE &server_handle, + int run_receiver_thread) +{ + // + // Create a connection and a receiver to receive messages on the + // connection. + // + + ACE_Pipe pipe; + int result = 0; + + for (int i = 0; i < pipe_open_attempts; ++i) + { + result = + pipe.open (); + + if (result == 0) + break; + + if (result == -1) + ACE_OS::sleep (pipe_retry_timeout); + } + + ACE_ASSERT (result == 0); + ACE_UNUSED_ARG (result); + + Receiver *receiver = + new Receiver (this->thread_manager_, + pipe.write_handle (), + this->nested_upcalls_); + + // Either the receiver is threaded or register it with the Reactor. + if (run_receiver_thread) + result = + receiver->activate (); + else + { + result = + this->reactor_.register_handler (pipe.write_handle (), + receiver, + ACE_Event_Handler::READ_MASK); + + // The reference count on the receiver was increased by the + // Reactor. + ACE_Event_Handler_var safe_receiver (receiver); + } + + ACE_ASSERT (result == 0); + ACE_UNUSED_ARG (result); + + client_handle = + pipe.read_handle (); + + server_handle = + pipe.write_handle (); + + if (debug) + ACE_DEBUG ((LM_DEBUG, + "New connection: server handle = %d, client handle = %d\n", + server_handle, client_handle)); + + return 0; +} + +Connection_Cache::Connection_Cache (void) +{ + // Initialize the connection cache. + this->entries_ = + new Entry[number_of_connections]; + + for (int i = 0; i < number_of_connections; ++i) + { + this->entries_[i].sender_ = 0; + this->entries_[i].state_ = NOT_IN_CACHE; + } +} + +int +Connection_Cache::find (Sender *sender) +{ + for (int i = 0; i < number_of_connections; ++i) + { + if (this->entries_[i].sender_ == sender) + return i; + } + + return -1; +} + +void +Connection_Cache::add_connection (Sender *sender) +{ + ACE_GUARD (ACE_SYNCH_MUTEX, ace_mon, this->lock_); + + // Make sure that the state of the connection cache is as + // expected. <sender> should not be already in the cache. + ACE_ASSERT (this->find (sender) == -1); + + int empty_index = + this->find (0); + + sender->add_reference (); + this->entries_[empty_index].sender_ = sender; + this->entries_[empty_index].state_ = BUSY; +} + +void +Connection_Cache::remove_connection (Sender *sender) +{ + ACE_GUARD (ACE_SYNCH_MUTEX, ace_mon, this->lock_); + + // Make sure that the state of the connection cache is as expected. + // remove_connection() may already have been called. + int index = + this->find (sender); + + if (index == -1) + return; + + // If we still have the sender, remove it. + sender->remove_reference (); + this->entries_[index].sender_ = 0; + this->entries_[index].state_ = NOT_IN_CACHE; +} + +Sender * +Connection_Cache::acquire_connection (void) +{ + ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, 0); + + // Find a valid and IDLE sender. + + int index = -1; + + for (int i = 0; i < number_of_connections; ++i) + { + if (this->entries_[i].sender_ && + this->entries_[i].state_ == IDLE) + index = i; + } + + if (index == -1) + return 0; + + this->entries_[index].sender_->add_reference (); + this->entries_[index].state_ = BUSY; + + return this->entries_[index].sender_; +} + +void +Connection_Cache::release_connection (Sender *sender) +{ + ACE_GUARD (ACE_SYNCH_MUTEX, ace_mon, this->lock_); + + // Make sure that the state of the connection cache is as expected. + // remove_connection() may have already removed the connection from + // the cache. + int index = + this->find (sender); + + if (index == -1) + return; + + // If we still have the sender, idle it. + this->entries_[index].state_ = IDLE; +} + +ACE_SYNCH_MUTEX & +Connection_Cache::lock (void) +{ + return this->lock_; +} + +Connection_Cache::~Connection_Cache (void) +{ + for (int i = 0; i < number_of_connections; ++i) + { + if (this->entries_[i].sender_) + this->remove_connection (this->entries_[i].sender_); + } + + delete[] this->entries_; +} + +class Invocation_Thread : public ACE_Task_Base +{ +public: + + Invocation_Thread (ACE_Thread_Manager &thread_manager, + ACE_Reactor &reactor, + Connection_Cache &connection_cache, + ACE_Auto_Event &new_connection_event, + int make_invocations, + int run_receiver_thread, + int nested_upcalls); + + int svc (void); + + Sender *create_connection (void); + + Connection_Cache &connection_cache_; + + ACE_Reactor &reactor_; + + ACE_Thread_Manager &thread_manager_; + + ACE_Auto_Event &new_connection_event_; + + int make_invocations_; + + int run_receiver_thread_; + + int nested_upcalls_; + +}; + +Invocation_Thread::Invocation_Thread (ACE_Thread_Manager &thread_manager, + ACE_Reactor &reactor, + Connection_Cache &connection_cache, + ACE_Auto_Event &new_connection_event, + int make_invocations, + int run_receiver_thread, + int nested_upcalls) + : connection_cache_ (connection_cache), + reactor_ (reactor), + thread_manager_ (thread_manager), + new_connection_event_ (new_connection_event), + make_invocations_ (make_invocations), + run_receiver_thread_ (run_receiver_thread), + nested_upcalls_ (nested_upcalls), + ACE_Task_Base (&thread_manager) +{ +} + +Sender * +Invocation_Thread::create_connection (void) +{ + int result = 0; + + // Connector for creating new connections. + Connector connector (this->thread_manager_, + this->reactor_, + this->nested_upcalls_); + + // <server_handle> is a global variable. It will be used later by + // the Close_Socket_Thread. + result = + connector.connect (client_handle, + server_handle, + this->run_receiver_thread_); + + ACE_ASSERT (result == 0); + ACE_UNUSED_ARG (result); + + // Create a new sender. + Sender *sender = + new Sender (client_handle, + this->connection_cache_); + + // Register it with the cache. + this->connection_cache_.add_connection (sender); + + // + // There might be a race condition here. The sender has been added + // to the cache and is potentially available to other threads + // accessing the cache. Therefore, the other thread may use this + // sender and potentially close the sender before it even gets + // registered with the Reactor. + // + // This is resolved by marking the connection as busy when it is + // first added to the cache. And only once the thread creating the + // connection is done with it, it is marked a available in the + // cache. + // + // This order of registration is important. + // + + // Register the handle with the Reactor. + result = + this->reactor_.register_handler (client_handle, + sender, + ACE_Event_Handler::READ_MASK); + ACE_ASSERT (result == 0); + + return sender; +} + +int +Invocation_Thread::svc (void) +{ + int connection_counter = 0; + for (int message_counter = 1;; ++message_counter) + { + // Get a connection from the cache. + Sender *sender = + this->connection_cache_.acquire_connection (); + + // If no connection is available in the cache, create a new one. + if (sender == 0) + { + if (connection_counter < number_of_connections) + { + sender = this->create_connection (); + + // This lets the Close_Socket_Thread know that the new + // connection has been created. + this->new_connection_event_.signal (); + + ++connection_counter; + message_counter = 1; + } + else + // Stop the thread, if the maximum number of connections + // for the test has been reached. + break; + } + + // The reference count on the sender was increased by the cache + // before it was returned to us. + ACE_Event_Handler_var safe_sender (sender); + + // If the test does not require making invocations, immediately + // release the connection. + if (!this->make_invocations_) + { + this->connection_cache_.release_connection (sender); + + // Sleep for a short while + ACE_OS::sleep (ACE_Time_Value (0, 10 * 1000)); + } + else + { + // Make invocation. + ssize_t result = + sender->send_message (); + + // If successful, release connection. + if (result == message_size) + { + if (debug) + ACE_DEBUG ((LM_DEBUG, + "Message %d:%d delivered on handle %d\n", + connection_counter, + message_counter, + sender->handle_)); + + this->connection_cache_.release_connection (sender); + } + else + { + // If failure in making invocation, close the sender. + if (debug) + ACE_DEBUG ((LM_DEBUG, + "/*** Problem in delivering message %d:%d on handle %d: shutting down invocation thread ***/\n", + connection_counter, + message_counter, + sender->handle_)); + + ACE_DEBUG ((LM_DEBUG, + "Invocation thread calling Sender::close() for handle %d\n", + sender->handle_)); + + sender->close (); + } + } + } + + // Close the Reactor event loop. + this->reactor_.end_reactor_event_loop (); + + return 0; +} + +class Close_Socket_Thread : public ACE_Task_Base +{ +public: + + Close_Socket_Thread (ACE_Thread_Manager &thread_manager, + ACE_Reactor &reactor, + ACE_Auto_Event &new_connection, + int make_invocations, + int run_receiver_thread); + + int svc (void); + + ACE_Auto_Event &new_connection_; + + ACE_Reactor &reactor_; + + int make_invocations_; + + int run_receiver_thread_; + +}; + +Close_Socket_Thread::Close_Socket_Thread (ACE_Thread_Manager &thread_manager, + ACE_Reactor &reactor, + ACE_Auto_Event &new_connection, + int make_invocations, + int run_receiver_thread) + : new_connection_ (new_connection), + reactor_ (reactor), + ACE_Task_Base (&thread_manager), + make_invocations_ (make_invocations), + run_receiver_thread_ (run_receiver_thread) +{ +} + +int +Close_Socket_Thread::svc (void) +{ + ACE_OS::srand ((u_int) ACE_OS::time ()); + ACE_Time_Value timeout (0, close_timeout * 1000); + + for (; !this->reactor_.reactor_event_loop_done ();) + { + // Wait for the new connection to be established. + int result = + this->new_connection_.wait (&timeout, + 0); + if (result == -1 && + errno == ETIME) + continue; + + // Sleep for half a second. + ACE_OS::sleep (timeout); + + int close_client = 0; + + // If the invocation thread is making invocations and if the + // receiver is threaded, either socket can be closed. + if (this->make_invocations_ && + this->run_receiver_thread_) + // Randomize which socket to close. + close_client = ACE_OS::rand () % 2; + + // If the invocation thread is making invocations, only close + // the client socket. + else if (this->make_invocations_) + close_client = 1; + else + // If the receiver is threaded, only close the server socket. + close_client = 0; + + if (close_client) + { + // Close the client socket. + if (debug) + ACE_DEBUG ((LM_DEBUG, + "Close socket thread closing client handle %d\n", + client_handle)); + ACE_OS::closesocket (client_handle); + } + else + { + // Close the server socket. + if (debug) + ACE_DEBUG ((LM_DEBUG, + "Close socket thread closing server handle %d\n", + server_handle)); + ACE_OS::closesocket (server_handle); + } + } + + return 0; +} + +Event_Loop_Thread::Event_Loop_Thread (ACE_Thread_Manager &thread_manager, + ACE_Reactor &reactor) + : reactor_ (reactor), + ACE_Task_Base (&thread_manager) +{ +} + +int +Event_Loop_Thread::svc (void) +{ + // Simply run the event loop. + this->reactor_.owner (ACE_Thread::self ()); + + while (!this->reactor_.reactor_event_loop_done ()) + { + this->reactor_.handle_events (); + } + + return 0; +} + +class Purger_Thread : public ACE_Task_Base +{ +public: + + Purger_Thread (ACE_Thread_Manager &thread_manager, + ACE_Reactor &reactor, + Connection_Cache &connection_cache); + + int svc (void); + + ACE_Reactor &reactor_; + + Connection_Cache &connection_cache_; + +}; + +Purger_Thread::Purger_Thread (ACE_Thread_Manager &thread_manager, + ACE_Reactor &reactor, + Connection_Cache &connection_cache) + : reactor_ (reactor), + connection_cache_ (connection_cache), + ACE_Task_Base (&thread_manager) +{ +} + +int +Purger_Thread::svc (void) +{ + for (; !this->reactor_.reactor_event_loop_done ();) + { + // Get a connection from the cache. + Sender *sender = + this->connection_cache_.acquire_connection (); + + // If no connection is available in the cache, sleep for a while. + if (sender == 0) + ACE_OS::sleep (ACE_Time_Value (0, 10 * 1000)); + else + { + // The reference count on the sender was increased by the + // cache before it was returned to us. + ACE_Event_Handler_var safe_sender (sender); + + // Actively close the connection. + ACE_DEBUG ((LM_DEBUG, + "Purger thread calling Sender::close() for handle %d\n", + sender->handle_)); + + sender->close (); + } + } + + return 0; +} + +void +testing (ACE_Reactor *reactor, + int make_invocations, + int run_event_loop_thread, + int run_purger_thread, + int run_receiver_thread, + int nested_upcalls) +{ + ACE_DEBUG ((LM_DEBUG, + "\nConfiguration: \n" + "\tInvocation thread = %d\n" + "\tEvent Loop thread = %d\n" + "\tPurger thread = %d\n" + "\tReceiver thread = %d\n" + "\tNested Upcalls = %d\n\n", + make_invocations, + run_event_loop_thread, + run_purger_thread, + run_receiver_thread, + nested_upcalls)); + + ACE_Thread_Manager thread_manager; + + int result = 0; + + // Create the connection cache. + Connection_Cache connection_cache; + ACE_Auto_Event new_connection_event; + + // Create the invocation thread. + Invocation_Thread invocation_thread (thread_manager, + *reactor, + connection_cache, + new_connection_event, + make_invocations, + run_receiver_thread, + nested_upcalls); + + result = + invocation_thread.activate (); + ACE_ASSERT (result == 0); + + // Create the thread for closing the server socket. + Close_Socket_Thread close_socket_thread (thread_manager, + *reactor, + new_connection_event, + make_invocations, + run_receiver_thread); + result = + close_socket_thread.activate (); + ACE_ASSERT (result == 0); + + global_event_loop_thread_variable = 0; + + // Create a thread to run the event loop. + Event_Loop_Thread event_loop_thread (thread_manager, + *reactor); + if (run_event_loop_thread) + { + result = + event_loop_thread.activate (); + ACE_ASSERT (result == 0); + + global_event_loop_thread_variable = + &event_loop_thread; + } + + // Create a thread to run the purger. + Purger_Thread purger_thread (thread_manager, + *reactor, + connection_cache); + if (run_purger_thread) + { + result = + purger_thread.activate (); + ACE_ASSERT (result == 0); + } + + // Wait for threads to exit. + thread_manager.wait (); +} + +void +test (ACE_Reactor_Impl *impl, + int ignore_nested_upcalls, + int require_event_loop_thread) +{ + for (int i = 0; + i < sizeof test_configs / (sizeof (int) * number_of_options); + i++) + { + if ((make_invocations == -1 || + make_invocations == test_configs[i][0]) && + (run_event_loop_thread == -1 || + run_event_loop_thread == test_configs[i][1]) && + (run_purger_thread == -1 || + run_purger_thread == test_configs[i][2]) && + (run_receiver_thread == -1 || + run_receiver_thread == test_configs[i][3]) && + (nested_upcalls == -1 || + nested_upcalls == test_configs[i][4])) + { + if (test_configs[i][4] && ignore_nested_upcalls) + continue; + + if (!test_configs[i][1] && require_event_loop_thread) + continue; + + ACE_Reactor reactor (impl, + 1); + + testing (&reactor, + test_configs[i][0], + test_configs[i][1], + test_configs[i][2], + test_configs[i][3], + test_configs[i][4]); + } + } +} + +static int +parse_args (int argc, ACE_TCHAR *argv[]) +{ + ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("a:b:c:f:g:k:l:m:n:o:uz:")); + + int cc; + while ((cc = get_opt ()) != -1) + { + switch (cc) + { + case 'a': + test_select_reactor = ACE_OS::atoi (get_opt.opt_arg ()); + break; + case 'b': + test_tp_reactor = ACE_OS::atoi (get_opt.opt_arg ()); + break; + case 'c': + test_wfmo_reactor = ACE_OS::atoi (get_opt.opt_arg ()); + break; + case 'f': + number_of_connections = ACE_OS::atoi (get_opt.opt_arg ()); + break; + case 'g': + close_timeout = ACE_OS::atoi (get_opt.opt_arg ()); + break; + case 'k': + make_invocations = ACE_OS::atoi (get_opt.opt_arg ()); + break; + case 'l': + run_event_loop_thread = ACE_OS::atoi (get_opt.opt_arg ()); + break; + case 'm': + run_purger_thread = ACE_OS::atoi (get_opt.opt_arg ()); + break; + case 'n': + run_receiver_thread = ACE_OS::atoi (get_opt.opt_arg ()); + break; + case 'o': + nested_upcalls = ACE_OS::atoi (get_opt.opt_arg ()); + break; + case 'z': + debug = ACE_OS::atoi (get_opt.opt_arg ()); + break; + case 'u': + default: + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("\nusage: %s \n\n") + ACE_TEXT ("\t[-a test Select Reactor] (defaults to %d)\n") + ACE_TEXT ("\t[-b test TP Reactor] (defaults to %d)\n") + ACE_TEXT ("\t[-c test WFMO Reactor] (defaults to %d)\n") + ACE_TEXT ("\t[-f number of connections] (defaults to %d)\n") + ACE_TEXT ("\t[-g close timeout] (defaults to %d)\n") + ACE_TEXT ("\t[-k make invocations] (defaults to %d)\n") + ACE_TEXT ("\t[-l run event loop thread] (defaults to %d)\n") + ACE_TEXT ("\t[-m run purger thread] (defaults to %d)\n") + ACE_TEXT ("\t[-n run receiver thread] (defaults to %d)\n") + ACE_TEXT ("\t[-o nested upcalls] (defaults to %d)\n") + ACE_TEXT ("\t[-z debug] (defaults to %d)\n") + ACE_TEXT ("\n"), + argv[0], + test_select_reactor, + test_tp_reactor, + test_wfmo_reactor, + number_of_connections, + close_timeout, + make_invocations, + run_event_loop_thread, + run_purger_thread, + run_receiver_thread, + nested_upcalls, + debug)); + return -1; + } + } + + return 0; +} + +int +ACE_TMAIN (int argc, ACE_TCHAR *argv[]) +{ + ACE_START_TEST (ACE_TEXT ("MT_Reference_Counted_Event_Handler_Test")); + + // Validate options. + int result = + parse_args (argc, argv); + if (result != 0) + return result; + + int ignore_nested_upcalls = 1; + int perform_nested_upcalls = 0; + + int event_loop_thread_required = 1; + int event_loop_thread_not_required = 0; + + + if (test_select_reactor) + { + ACE_DEBUG ((LM_DEBUG, + "\n\nTesting Select Reactor....\n\n")); + + test (new ACE_Select_Reactor, + ignore_nested_upcalls, + event_loop_thread_not_required); + } + + if (test_tp_reactor) + { + ACE_DEBUG ((LM_DEBUG, + "\n\nTesting TP Reactor....\n\n")); + + test (new ACE_TP_Reactor, + perform_nested_upcalls, + event_loop_thread_not_required); + } + +#if defined (ACE_WIN32) + + if (test_wfmo_reactor) + { + ACE_DEBUG ((LM_DEBUG, + "\n\nTesting WFMO Reactor....\n\n")); + + test (new ACE_WFMO_Reactor, + ignore_nested_upcalls, + event_loop_thread_required); + } + +#endif /* ACE_WIN32 */ + + ACE_END_TEST; + + return 0; +} + +#else /* ACE_HAS_THREADS */ + +int +ACE_TMAIN (int, ACE_TCHAR *[]) +{ + ACE_START_TEST (ACE_TEXT ("Timer_Cancellation_Test")); + + ACE_ERROR ((LM_INFO, + ACE_TEXT ("threads not supported on this platform\n"))); + + ACE_END_TEST; + + return 0; +} + +#endif /* ACE_HAS_THREADS */ diff --git a/tests/MT_Reference_Counted_Event_Handler_Test.dsp b/tests/MT_Reference_Counted_Event_Handler_Test.dsp new file mode 100644 index 00000000000..1417b7c3fcf --- /dev/null +++ b/tests/MT_Reference_Counted_Event_Handler_Test.dsp @@ -0,0 +1,158 @@ +# Microsoft Developer Studio Project File - Name="MT_Reference_Counted_Event_Handler_Test" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=MT_Reference_Counted_Event_Handler_Test - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "MT_Reference_Counted_Event_Handler_Test.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "MT_Reference_Counted_Event_Handler_Test.mak" CFG="MT_Reference_Counted_Event_Handler_Test - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "MT_Reference_Counted_Event_Handler_Test - Win32 Static Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE "MT_Reference_Counted_Event_Handler_Test - Win32 Static Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "MT_Reference_Counted_Event_Handler_Test - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "MT_Reference_Counted_Event_Handler_Test - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "MT_Reference_Counted_Event_Handler_Test - Win32 Static Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Static_Debug"
+# PROP BASE Intermediate_Dir "Static_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Static_Debug"
+# PROP Intermediate_Dir "Static_Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "../" /D "_DEBUG" /D ACE_AS_STATIC_LIBS /D "WIN32" /D "_CONSOLE" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386
+# ADD LINK32 acesd.lib advapi32.lib user32.lib /nologo /subsystem:console /debug /machine:I386 /libpath:"..\ace"
+
+!ELSEIF "$(CFG)" == "MT_Reference_Counted_Event_Handler_Test - Win32 Static Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Static_Release"
+# PROP BASE Intermediate_Dir "Static_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Static_Release"
+# PROP Intermediate_Dir "Static_Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "../" /D "NDEBUG" /D ACE_AS_STATIC_LIBS /D "WIN32" /D "_CONSOLE" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 aces.lib advapi32.lib user32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\ace"
+
+!ELSEIF "$(CFG)" == "MT_Reference_Counted_Event_Handler_Test - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "../" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 ace.lib /nologo /subsystem:console /machine:I386 /libpath:"..\ace"
+
+!ELSEIF "$(CFG)" == "MT_Reference_Counted_Event_Handler_Test - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "../" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 aced.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\ace"
+
+!ENDIF
+
+# Begin Target
+
+# Name "MT_Reference_Counted_Event_Handler_Test - Win32 Static Debug"
+# Name "MT_Reference_Counted_Event_Handler_Test - Win32 Static Release"
+# Name "MT_Reference_Counted_Event_Handler_Test - Win32 Release"
+# Name "MT_Reference_Counted_Event_Handler_Test - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter ".cpp"
+# Begin Source File
+
+SOURCE=.\MT_Reference_Counted_Event_Handler_Test.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter ".h"
+# Begin Source File
+
+SOURCE=.\test_config.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/tests/MT_Reference_Counted_Notify_Test.cpp b/tests/MT_Reference_Counted_Notify_Test.cpp new file mode 100644 index 00000000000..50bbf3a411c --- /dev/null +++ b/tests/MT_Reference_Counted_Notify_Test.cpp @@ -0,0 +1,438 @@ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// tests +// +// = FILENAME +// MT_Reference_Counted_Notify_Test.cpp +// +// = DESCRIPTION +// This test is used to check reference counting of the event +// handlers when it interacts with the reactor notification +// mechanism. +// +// = AUTHOR +// Irfan Pyarali <irfan@oomworks.com> +// +// ============================================================================ + +#include "test_config.h" +#include "ace/Select_Reactor.h" +#include "ace/TP_Reactor.h" +#include "ace/WFMO_Reactor.h" +#include "ace/Task.h" +#include "ace/Get_Opt.h" + +ACE_RCSID(tests, MT_Reference_Counted_Notify_Test, "$Id$") + +#if defined (ACE_HAS_THREADS) + +static int test_select_reactor = 1; +static int test_tp_reactor = 1; +static int test_wfmo_reactor = 1; +static int test_empty_notify = 1; +static int test_simple_notify = 1; +static int test_reference_counted_notify = 1; +static int iterations = 5; +static int debug = 1; + +class Reference_Counted_Event_Handler : public ACE_Event_Handler +{ +public: + + Reference_Counted_Event_Handler (void); + + ~Reference_Counted_Event_Handler (void); + + int handle_input (ACE_HANDLE); + + ACE_Event_Handler::Reference_Count add_reference (void); + + ACE_Event_Handler::Reference_Count remove_reference (void); + +}; + +Reference_Counted_Event_Handler::Reference_Counted_Event_Handler (void) +{ + this->reference_counting_policy ().value + (ACE_Event_Handler::Reference_Counting_Policy::ENABLED); + + if (debug) + ACE_DEBUG ((LM_DEBUG, + "Reference count in Reference_Counted_Event_Handler() is %d\n", + this->reference_count_.value ())); +} + +Reference_Counted_Event_Handler::~Reference_Counted_Event_Handler (void) +{ + if (debug) + ACE_DEBUG ((LM_DEBUG, + "Reference count in ~Reference_Counted_Event_Handler() is %d\n", + this->reference_count_.value ())); +} + +int +Reference_Counted_Event_Handler::handle_input (ACE_HANDLE) +{ + if (debug) + ACE_DEBUG ((LM_DEBUG, + "Reference count in Reference_Counted_Event_Handler::handle_input() is %d\n", + this->reference_count_.value ())); + + return 0; +} + +ACE_Event_Handler::Reference_Count +Reference_Counted_Event_Handler::add_reference (void) +{ + ACE_Event_Handler::Reference_Count reference_count = + this->ACE_Event_Handler::add_reference (); + + if (debug) + ACE_DEBUG ((LM_DEBUG, + "Reference count after add_reference() is %d\n", + this->reference_count_.value ())); + + return reference_count; +} + +ACE_Event_Handler::Reference_Count +Reference_Counted_Event_Handler::remove_reference (void) +{ + ACE_Event_Handler::Reference_Count reference_count = + this->ACE_Event_Handler::remove_reference (); + + if (debug) + ACE_DEBUG ((LM_DEBUG, + "Reference count after remove_reference() is %d\n", + reference_count)); + + return reference_count; +} + +class Simple_Event_Handler : public ACE_Event_Handler +{ +public: + + Simple_Event_Handler (int notifies); + + ~Simple_Event_Handler (void); + + int handle_input (ACE_HANDLE); + + ACE_Event_Handler::Reference_Count add_reference (void); + + ACE_Event_Handler::Reference_Count remove_reference (void); + + int notifies_; +}; + +Simple_Event_Handler::Simple_Event_Handler (int notifies) + : notifies_ (notifies) +{ + if (debug) + ACE_DEBUG ((LM_DEBUG, + "Simple_Event_Handler()\n")); +} + +Simple_Event_Handler::~Simple_Event_Handler (void) +{ + if (debug) + ACE_DEBUG ((LM_DEBUG, + "~Simple_Event_Handler()\n")); +} + +int +Simple_Event_Handler::handle_input (ACE_HANDLE) +{ + if (debug) + ACE_DEBUG ((LM_DEBUG, + "Simple_Event_Handler::handle_input()\n")); + + this->notifies_--; + + if (this->notifies_ == 0) + delete this; + + return 0; +} + +ACE_Event_Handler::Reference_Count +Simple_Event_Handler::add_reference (void) +{ + // This should not get called. + ACE_ASSERT (0); + return 0; +} + +ACE_Event_Handler::Reference_Count +Simple_Event_Handler::remove_reference (void) +{ + // This should not get called. + ACE_ASSERT (0); + return 0; +} + +class Event_Loop_Thread : public ACE_Task_Base +{ +public: + + Event_Loop_Thread (ACE_Thread_Manager &thread_manager, + ACE_Reactor &reactor, + int extra_iterations_needed); + + int svc (void); + + ACE_Reactor &reactor_; + + int extra_iterations_needed_; +}; + +Event_Loop_Thread::Event_Loop_Thread (ACE_Thread_Manager &thread_manager, + ACE_Reactor &reactor, + int extra_iterations_needed) + : ACE_Task_Base (&thread_manager), + reactor_ (reactor), + extra_iterations_needed_ (extra_iterations_needed) +{ +} + +int +Event_Loop_Thread::svc (void) +{ + int counter = 0; + + // Simply run the event loop. + this->reactor_.owner (ACE_Thread::self ()); + + while (1) + { + counter++; + + if (debug) + ACE_DEBUG ((LM_DEBUG, + "Event Loop iteration %d....\n", + counter)); + + this->reactor_.handle_events (); + + if (counter == + iterations + this->extra_iterations_needed_) + break; + } + + return 0; +} + +void +notify (ACE_Reactor &reactor, + ACE_Event_Handler *event_handler, + int extra_iterations_needed) +{ + ACE_Thread_Manager thread_manager; + + // Create a thread to run the event loop. + Event_Loop_Thread event_loop_thread (thread_manager, + reactor, + extra_iterations_needed); + + int result = + event_loop_thread.activate (); + ACE_ASSERT (result == 0); + + for (int i = 0; + i < iterations; + ++i) + { + ACE_OS::sleep (ACE_Time_Value (0, 500 * 1000)); + + result = reactor.notify (event_handler, + ACE_Event_Handler::READ_MASK); + + ACE_ASSERT (result == 0); + } + + thread_manager.wait (); +} + +template <class REACTOR_IMPLEMENTATION> +class test +{ +public: + test (int extra_iterations_needed); +}; + +template <class REACTOR_IMPLEMENTATION> +test<REACTOR_IMPLEMENTATION>::test (int extra_iterations_needed) +{ + if (test_empty_notify) + { + ACE_DEBUG ((LM_DEBUG, + "\n\nTesting empty notifies....\n\n")); + + REACTOR_IMPLEMENTATION impl; + ACE_Reactor reactor (&impl, 0); + + notify (reactor, + 0, + extra_iterations_needed); + } + + + if (test_simple_notify) + { + ACE_DEBUG ((LM_DEBUG, + "\n\nTesting simple notifies....\n\n")); + + REACTOR_IMPLEMENTATION impl; + ACE_Reactor reactor (&impl, 0); + + Simple_Event_Handler *simple_event_handler = + new Simple_Event_Handler (iterations); + + notify (reactor, + simple_event_handler, + extra_iterations_needed); + } + + if (test_reference_counted_notify) + { + ACE_DEBUG ((LM_DEBUG, + "\n\nTesting reference counted notifies....\n\n")); + + REACTOR_IMPLEMENTATION impl; + ACE_Reactor reactor (&impl, 0); + + Reference_Counted_Event_Handler *reference_counted_event_handler = + new Reference_Counted_Event_Handler; + + ACE_Event_Handler_var safe_event_handler (reference_counted_event_handler); + + notify (reactor, + reference_counted_event_handler, + extra_iterations_needed); + } +} + +static int +parse_args (int argc, ACE_TCHAR *argv[]) +{ + ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("a:b:c:e:f:g:z:")); + + int cc; + while ((cc = get_opt ()) != -1) + { + switch (cc) + { + case 'a': + test_select_reactor = ACE_OS::atoi (get_opt.opt_arg ()); + break; + case 'b': + test_tp_reactor = ACE_OS::atoi (get_opt.opt_arg ()); + break; + case 'c': + test_wfmo_reactor = ACE_OS::atoi (get_opt.opt_arg ()); + break; + case 'e': + test_empty_notify = ACE_OS::atoi (get_opt.opt_arg ()); + break; + case 'f': + test_simple_notify = ACE_OS::atoi (get_opt.opt_arg ()); + break; + case 'g': + test_reference_counted_notify = ACE_OS::atoi (get_opt.opt_arg ()); + break; + case 'z': + debug = ACE_OS::atoi (get_opt.opt_arg ()); + break; + default: + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("\nusage: %s \n\n") + ACE_TEXT ("\t[-a test Select Reactor] (defaults to %d)\n") + ACE_TEXT ("\t[-b test TP Reactor] (defaults to %d)\n") + ACE_TEXT ("\t[-c test WFMO Reactor] (defaults to %d)\n") + ACE_TEXT ("\t[-e test empty notify] (defaults to %d)\n") + ACE_TEXT ("\t[-f test simple notify] (defaults to %d)\n") + ACE_TEXT ("\t[-g test reference counted notify] (defaults to %d)\n") + ACE_TEXT ("\t[-z debug] (defaults to %d)\n") + ACE_TEXT ("\n"), + argv[0], + test_select_reactor, + test_tp_reactor, + test_wfmo_reactor, + test_empty_notify, + test_simple_notify, + test_reference_counted_notify, + debug)); + return -1; + } + } + + return 0; +} + +int +ACE_TMAIN (int argc, ACE_TCHAR *argv[]) +{ + ACE_START_TEST (ACE_TEXT ("MT_Reference_Counted_Notify_Test")); + + // Validate options. + int result = + parse_args (argc, argv); + if (result != 0) + return result; + + int extra_iterations_needed = 1; + int extra_iterations_not_needed = 0; + + if (test_select_reactor) + { + ACE_DEBUG ((LM_DEBUG, + "\n\nTesting Select Reactor....\n\n")); + + test<ACE_Select_Reactor> test_select_reactor (extra_iterations_not_needed); + } + + if (test_tp_reactor) + { + ACE_DEBUG ((LM_DEBUG, + "\n\nTesting TP Reactor....\n\n")); + + test<ACE_TP_Reactor> test_tp_reactor (extra_iterations_not_needed); + } + +#if defined (ACE_WIN32) + + if (test_wfmo_reactor) + { + ACE_DEBUG ((LM_DEBUG, + "\n\nTesting WFMO Reactor....\n\n")); + + test<ACE_WFMO_Reactor> test_wfmo_reactor (extra_iterations_needed); + } + +#endif /* ACE_WIN32 */ + + ACE_END_TEST; + + return 0; +} + +#else /* ACE_HAS_THREADS */ + +int +ACE_TMAIN (int, ACE_TCHAR *[]) +{ + ACE_START_TEST (ACE_TEXT ("MT_Reference_Counted_Notify_Test")); + + ACE_ERROR ((LM_INFO, + ACE_TEXT ("threads not supported on this platform\n"))); + + ACE_END_TEST; + + return 0; +} + +#endif /* ACE_HAS_THREADS */ diff --git a/tests/MT_Reference_Counted_Notify_Test.dsp b/tests/MT_Reference_Counted_Notify_Test.dsp new file mode 100644 index 00000000000..69261c91ca0 --- /dev/null +++ b/tests/MT_Reference_Counted_Notify_Test.dsp @@ -0,0 +1,158 @@ +# Microsoft Developer Studio Project File - Name="MT_Reference_Counted_Notify_Test" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=MT_Reference_Counted_Notify_Test - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "MT_Reference_Counted_Notify_Test.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "MT_Reference_Counted_Notify_Test.mak" CFG="MT_Reference_Counted_Notify_Test - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "MT_Reference_Counted_Notify_Test - Win32 Static Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE "MT_Reference_Counted_Notify_Test - Win32 Static Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "MT_Reference_Counted_Notify_Test - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "MT_Reference_Counted_Notify_Test - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "MT_Reference_Counted_Notify_Test - Win32 Static Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Static_Debug"
+# PROP BASE Intermediate_Dir "Static_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Static_Debug"
+# PROP Intermediate_Dir "Static_Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "../" /D "_DEBUG" /D ACE_AS_STATIC_LIBS /D "WIN32" /D "_CONSOLE" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386
+# ADD LINK32 acesd.lib advapi32.lib user32.lib /nologo /subsystem:console /debug /machine:I386 /libpath:"..\ace"
+
+!ELSEIF "$(CFG)" == "MT_Reference_Counted_Notify_Test - Win32 Static Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Static_Release"
+# PROP BASE Intermediate_Dir "Static_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Static_Release"
+# PROP Intermediate_Dir "Static_Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "../" /D "NDEBUG" /D ACE_AS_STATIC_LIBS /D "WIN32" /D "_CONSOLE" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 aces.lib advapi32.lib user32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\ace"
+
+!ELSEIF "$(CFG)" == "MT_Reference_Counted_Notify_Test - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "../" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 ace.lib /nologo /subsystem:console /machine:I386 /libpath:"..\ace"
+
+!ELSEIF "$(CFG)" == "MT_Reference_Counted_Notify_Test - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "../" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 aced.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\ace"
+
+!ENDIF
+
+# Begin Target
+
+# Name "MT_Reference_Counted_Notify_Test - Win32 Static Debug"
+# Name "MT_Reference_Counted_Notify_Test - Win32 Static Release"
+# Name "MT_Reference_Counted_Notify_Test - Win32 Release"
+# Name "MT_Reference_Counted_Notify_Test - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter ".cpp"
+# Begin Source File
+
+SOURCE=.\MT_Reference_Counted_Notify_Test.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter ".h"
+# Begin Source File
+
+SOURCE=.\test_config.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/tests/Makefile b/tests/Makefile index e36cabc00be..f862c3307ad 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -10,7 +10,8 @@ #---------------------------------------------------------------------------- DIRS_PARALLEL = 1 -BIN = ACE_Test \ +BIN = \ + ACE_Test \ Aio_Platform_Test \ Arg_Shifter_Test \ ARGV_Test \ @@ -18,7 +19,7 @@ BIN = ACE_Test \ Auto_IncDec_Test \ Barrier_Test \ Basic_Types_Test \ - Bound_Ptr_Test \ + Bound_Ptr_Test \ Buffer_Stream_Test \ Cache_Map_Manager_Test \ Cached_Accept_Conn_Test \ @@ -28,81 +29,86 @@ BIN = ACE_Test \ CDR_File_Test \ CDR_Test \ Collection_Test \ - Config_Test \ + Config_Test \ Conn_Test \ Date_Time_Test \ - Dev_Poll_Reactor_Test \ - Dirent_Test \ - DLList_Test \ + Dev_Poll_Reactor_Test \ + Dirent_Test \ DLL_Test\ + DLList_Test \ + Dynamic_Priority_Test \ Enum_Interfaces_Test \ Env_Value_Test \ FIFO_Test \ - Future_Test \ Future_Set_Test \ - Get_Opt_Test \ + Future_Test \ + Get_Opt_Test \ Handle_Set_Test \ - High_Res_Timer_Test \ - Hash_Map_Manager_Test \ Hash_Map_Bucket_Iterator_Test \ + Hash_Map_Manager_Test \ + High_Res_Timer_Test \ INET_Addr_Test \ IOStream_Test \ Lazy_Map_Manager_Test \ Log_Msg_Test \ - Logging_Strategy_Test \ + Logging_Strategy_Test \ Malloc_Test \ - Map_Test \ Map_Manager_Test \ + Map_Test \ Max_Default_Port_Test \ - MEM_Stream_Test \ Mem_Map_Test \ + MEM_Stream_Test \ + Message_Block_Test \ + Message_Queue_Notifications_Test \ + Message_Queue_Test \ + Message_Queue_Test_Ex \ MM_Shared_Memory_Test \ MT_Reactor_Timer_Test \ MT_Reactor_Upcall_Test \ + MT_Reference_Counted_Event_Handler_Test \ + MT_Reference_Counted_Notify_Test \ MT_SOCK_Test \ - Message_Block_Test \ - Message_Queue_Test \ - Message_Queue_Test_Ex \ - Message_Queue_Notifications_Test \ Multicast_Test \ Multihomed_INET_Addr_Test \ + NonBlocking_Conn_Test \ Notify_Performance_Test \ Object_Manager_Test \ Obstack_Test \ OrdMultiSet_Test \ OS_Test \ - Proactor_Scatter_Gather_Test \ - Proactor_Test \ - Proactor_Timer_Test \ - Process_Mutex_Test \ - Process_Strategy_Test \ + Pipe_Test \ Priority_Buffer_Test \ - Dynamic_Priority_Test \ - Priority_Task_Test \ Priority_Reactor_Test \ + Priority_Task_Test \ + Proactor_Scatter_Gather_Test \ + Proactor_Test \ + Proactor_Timer_Test \ Process_Manager_Test \ - Pipe_Test \ + Process_Mutex_Test \ + Process_Strategy_Test \ RB_Tree_Test \ - Reactors_Test \ + Reactor_Dispatch_Order_Test \ Reactor_Exceptions_Test \ Reactor_Notify_Test \ - Reactor_Dispatch_Order_Test \ Reactor_Performance_Test \ + Reactor_Registration_Test \ Reactor_Timer_Test \ + Reactors_Test \ Reader_Writer_Test \ - Recursive_Condition_Test \ Recursive_Condition_Bug_Test \ + Recursive_Condition_Test \ Recursive_Mutex_Test \ - Refcounted_Auto_Ptr_Test \ + Refcounted_Auto_Ptr_Test \ + Reference_Counted_Event_Handler_Test \ Reverse_Lock_Test \ Semaphore_Test \ Signal_Test \ Sigset_Ops_Test \ Simple_Message_Block_Test \ - SOCK_Test \ SOCK_Connector_Test \ - SOCK_SEQPACK_Association_Test \ SOCK_Send_Recv_Test \ + SOCK_SEQPACK_Association_Test \ + SOCK_Test \ SPIPE_Test \ SString_Test \ SV_Shared_Memory_Test \ @@ -111,17 +117,20 @@ BIN = ACE_Test \ Thread_Manager_Test \ Thread_Mutex_Test \ Thread_Pool_Test \ - Timeprobe_Test \ Time_Service_Test \ Time_Value_Test \ + Timeprobe_Test \ + Timer_Cancellation_Test \ + Timer_Queue_Reference_Counting_Test \ Timer_Queue_Test \ - Token_Strategy_Test \ + Token_Strategy_Test \ TP_Reactor_Test \ TSS_Test \ - Vector_Test \ - UPIPE_SAP_Test \ Unbounded_Set_Test_Ex \ - Upgradable_RW_Test + Upgradable_RW_Test \ + UPIPE_SAP_Test \ + Vector_Test \ + WFMO_Reactor_Test BIN2 = Naming_Test \ Thread_Pool_Reactor_Test \ @@ -231,26 +240,26 @@ endif #---------------------------------------------------------------------------- libFramework_Component_DLL.$(SOEXT): Framework_Component_DLL.cpp Framework_Component_DLL.h - @$(MAKE) -f Makefile.Framework_Component_DLL + @$(MAKE) -f Makefile.Framework_Component_DLL libDLL_Test.$(SOEXT): DLL_Test_Impl.cpp DLL_Test_Impl.h - @$(MAKE) -f Makefile.DLL_Test + @$(MAKE) -f Makefile.DLL_Test libService_Config_DLL.$(SOEXT): Service_Config_DLL.cpp Service_Config_DLL.h - @$(MAKE) -f Makefile.Service_Config_DLL + @$(MAKE) -f Makefile.Service_Config_DLL ifdef VXWORKS all: run_test.vxworks run_test.vxworks: run_test.lst - run_test.pl -v -Config STATIC -Config CHECK_RESOURCES -o run_test.vxworks + run_test.pl -v -Config STATIC -Config CHECK_RESOURCES -o run_test.vxworks endif realclean: clean - -$(MAKE) -f Makefile.Framework_Component_DLL realclean - -$(MAKE) -f Makefile.DLL_Test realclean - -$(MAKE) -f Makefile.Service_Config_DLL realclean - -$(RM) log/compilations.log* + -$(MAKE) -f Makefile.Framework_Component_DLL realclean + -$(MAKE) -f Makefile.DLL_Test realclean + -$(MAKE) -f Makefile.Service_Config_DLL realclean + -$(RM) log/compilations.log* #---------------------------------------------------------------------------- # Dependencies diff --git a/tests/Makefile.am b/tests/Makefile.am index 8d43d159bfd..d8a585386b4 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -89,58 +89,61 @@ noinst_PROGRAMS = \ Basic_Types_Test \ Bound_Ptr_Test \ Buffer_Stream_Test \ - CDR_File_Test \ - CDR_Test \ Cache_Map_Manager_Test \ Cached_Accept_Conn_Test \ Cached_Allocator_Test \ Cached_Conn_Test \ Capabilities_Test \ + CDR_File_Test \ + CDR_Test \ Collection_Test \ Config_Test \ Conn_Test \ - DLL_Test\ - DLList_Test \ Date_Time_Test \ Dev_Poll_Reactor_Test \ Dirent_Test \ + DLL_Test\ + DLList_Test \ Dynamic_Priority_Test \ Enum_Interfaces_Test \ Env_Value_Test \ FIFO_Test \ - Future_Test \ Future_Set_Test \ + Future_Test \ Get_Opt_Test \ Handle_Set_Test \ - Hash_Map_Manager_Test \ Hash_Map_Bucket_Iterator_Test \ + Hash_Map_Manager_Test \ High_Res_Timer_Test \ INET_Addr_Test \ IOStream_Test \ Lazy_Map_Manager_Test \ Log_Msg_Test \ Logging_Strategy_Test \ - MEM_Stream_Test \ - MM_Shared_Memory_Test \ - MT_Reactor_Timer_Test \ - MT_Reactor_Upcall_Test \ - MT_SOCK_Test \ Malloc_Test \ Map_Manager_Test \ Map_Test \ Max_Default_Port_Test \ Mem_Map_Test \ + MEM_Stream_Test \ Message_Block_Test \ Message_Queue_Notifications_Test \ Message_Queue_Test \ Message_Queue_Test_Ex \ + MM_Shared_Memory_Test \ + MT_Reactor_Timer_Test \ + MT_Reactor_Upcall_Test \ + MT_Reference_Counted_Event_Handler_Test \ + MT_Reference_Counted_Notify_Test \ + MT_SOCK_Test \ Multicast_Test \ Multihomed_INET_Addr_Test \ + NonBlocking_Conn_Test \ Notify_Performance_Test \ - OS_Test \ Object_Manager_Test \ Obstack_Test \ OrdMultiSet_Test \ + OS_Test \ Pipe_Test \ Priority_Buffer_Test \ Priority_Reactor_Test \ @@ -148,35 +151,35 @@ noinst_PROGRAMS = \ Proactor_Scatter_Gather_Test \ Proactor_Test \ Proactor_Timer_Test \ + Process_Manager_Test \ Process_Mutex_Test \ Process_Strategy_Test \ - Process_Manager_Test \ RB_Tree_Test \ Reactor_Dispatch_Order_Test \ Reactor_Exceptions_Test \ Reactor_Notify_Test \ Reactor_Performance_Test \ + Reactor_Registration_Test \ Reactor_Timer_Test \ Reactors_Test \ Reader_Writer_Test \ Recursive_Condition_Test \ Recursive_Mutex_Test \ Refcounted_Auto_Ptr_Test \ + Reference_Counted_Event_Handler_Test \ Reverse_Lock_Test \ + Semaphore_Test \ + Service_Config_Test \ + Signal_Test \ + Sigset_Ops_Test \ + Simple_Message_Block_Test \ SOCK_Connector_Test \ SOCK_Send_Recv_Test \ SOCK_Test \ SPIPE_Test \ SString_Test \ SV_Shared_Memory_Test \ - Semaphore_Test \ - Service_Config_Test \ - Signal_Test \ - Sigset_Ops_Test \ - Simple_Message_Block_Test \ Svc_Handler_Test \ - TP_Reactor_Test \ - TSS_Test \ Task_Test \ Thread_Manager_Test \ Thread_Mutex_Test \ @@ -184,12 +187,17 @@ noinst_PROGRAMS = \ Time_Service_Test \ Time_Value_Test \ Timeprobe_Test \ + Timer_Cancellation_Test \ + Timer_Queue_Reference_Counting_Test \ Timer_Queue_Test \ Token_Strategy_Test \ - UPIPE_SAP_Test \ + TP_Reactor_Test \ + TSS_Test \ Unbounded_Set_Test_Ex \ Upgradable_RW_Test \ + UPIPE_SAP_Test \ Vector_Test \ + WFMO_Reactor_Test \ \ Naming_Test \ \ diff --git a/tests/Makefile.bor b/tests/Makefile.bor index 9d9f06aff4a..72fcdafc413 100644 --- a/tests/Makefile.bor +++ b/tests/Makefile.bor @@ -5,130 +5,138 @@ NAMES = \ ACE_Test \ - Aio_Platform_Test \ + Aio_Platform_Test \ Arg_Shifter_Test \ - ARGV_Test \ - Atomic_Op_Test \ - Auto_IncDec_Test \ - Barrier_Test \ - Basic_Types_Test \ + ARGV_Test \ + Atomic_Op_Test \ + Auto_IncDec_Test \ + Barrier_Test \ + Basic_Types_Test \ Bound_Ptr_Test \ - Buffer_Stream_Test \ - Cache_Map_Manager_Test \ - Cached_Accept_Conn_Test \ + Buffer_Stream_Test \ + Cache_Map_Manager_Test \ + Cached_Accept_Conn_Test \ Cached_Allocator_Test \ - Cached_Conn_Test \ - Capabilities_Test \ - CDR_Array_Test \ - CDR_File_Test \ - CDR_Test \ - Codecs_Test \ - Collection_Test \ - Conn_Test \ - Config_Test \ + Cached_Conn_Test \ + Capabilities_Test \ + CDR_Array_Test \ + CDR_File_Test \ + CDR_Test \ + Codecs_Test \ + Collection_Test \ + Config_Test \ + Conn_Test \ Date_Time_Test \ - Dirent_Test \ - DLL_Test \ - DLList_Test \ - Dynamic_Priority_Test \ - Enum_Interfaces_Test \ - Env_Value_Test \ - FlReactor_Test \ + Dirent_Test \ + DLL_Test \ + DLList_Test \ + Dynamic_Priority_Test \ + Enum_Interfaces_Test \ + Env_Value_Test \ + FlReactor_Test \ Framework_Component_Test \ - Future_Set_Test \ - Future_Test \ + Future_Set_Test \ + Future_Test \ Get_Opt_Test \ - Handle_Set_Test \ - Hash_Map_Bucket_Iterator_Test \ - Hash_Map_Manager_Test \ - High_Res_Timer_Test \ + Handle_Set_Test \ + Hash_Map_Bucket_Iterator_Test \ + Hash_Map_Manager_Test \ + High_Res_Timer_Test \ INET_Addr_Test \ - IOStream_Test \ - Lazy_Map_Manager_Test \ - Log_Msg_Test \ - Logging_Strategy_Test \ - Malloc_Test \ - Map_Manager_Test \ - Map_Test \ + IOStream_Test \ + Lazy_Map_Manager_Test \ + Log_Msg_Test \ + Logging_Strategy_Test \ + Malloc_Test \ + Map_Manager_Test \ + Map_Test \ Max_Default_Port_Test \ + Mem_Map_Test \ MEM_Stream_Test \ - Mem_Map_Test \ - Message_Block_Test \ - Message_Queue_Notifications_Test \ - Message_Queue_Test \ - Message_Queue_Test_Ex \ - MM_Shared_Memory_Test \ - MT_Reactor_Timer_Test \ - MT_Reactor_Upcall_Test \ - MT_SOCK_Test \ + Message_Block_Test \ + Message_Queue_Notifications_Test \ + Message_Queue_Test \ + Message_Queue_Test_Ex \ + MM_Shared_Memory_Test \ + MT_Reactor_Timer_Test \ + MT_Reactor_Upcall_Test \ + MT_Reference_Counted_Event_Handler_Test \ + MT_Reference_Counted_Notify_Test \ + MT_SOCK_Test \ Multicast_Test \ Multihomed_INET_Addr_Test \ - Naming_Test \ - New_Fail_Test \ - Notify_Performance_Test \ - Object_Manager_Test \ - Obstack_Test \ - OrdMultiSet_Test \ - OS_Test \ - Pipe_Test \ - Proactor_Scatter_Gather_Test \ - Proactor_Test \ - Proactor_Timer_Test \ - Priority_Buffer_Test \ - Priority_Reactor_Test \ - Priority_Task_Test \ - Process_Manager_Test \ - Process_Mutex_Test \ - Process_Strategy_Test \ - RB_Tree_Test \ - Reactor_Exceptions_Test \ - Reactor_Notify_Test \ - Reactor_Dispatch_Order_Test \ - Reactor_Performance_Test \ - Reactor_Timer_Test \ - Reactors_Test \ - Reader_Writer_Test \ - Recursive_Condition_Test \ - Recursive_Condition_Bug_Test \ - Recursive_Mutex_Test \ + Naming_Test \ + New_Fail_Test \ + NonBlocking_Conn_Test \ + Notify_Performance_Test \ + Object_Manager_Test \ + Obstack_Test \ + OrdMultiSet_Test \ + OS_Test \ + Pipe_Test \ + Priority_Buffer_Test \ + Priority_Reactor_Test \ + Priority_Task_Test \ + Proactor_Scatter_Gather_Test \ + Proactor_Test \ + Proactor_Timer_Test \ + Process_Manager_Test \ + Process_Mutex_Test \ + Process_Strategy_Test \ + RB_Tree_Test \ + Reactor_Dispatch_Order_Test \ + Reactor_Exceptions_Test \ + Reactor_Notify_Test \ + Reactor_Performance_Test \ + Reactor_Registration_Test \ + Reactor_Timer_Test \ + Reactors_Test \ + Reader_Writer_Test \ + Recursive_Condition_Bug_Test \ + Recursive_Condition_Test \ + Recursive_Mutex_Test \ Refcounted_Auto_Ptr_Test \ + Reference_Counted_Event_Handler_Test \ Reverse_Lock_Test \ - Semaphore_Test \ - Service_Config_Test \ - Signal_Test \ - Sigset_Ops_Test \ - Simple_Message_Block_Test \ - SOCK_Connector_Test \ - SOCK_Send_Recv_Test \ - SOCK_Test \ - SPIPE_Test \ - SString_Test \ - SV_Shared_Memory_Test \ - Svc_Handler_Test \ - Task_Test \ - Thread_Manager_Test \ - Thread_Mutex_Test \ - Thread_Pool_Reactor_Test \ - Thread_Pool_Reactor_Resume_Test \ - Thread_Pool_Test \ - Time_Service_Test \ - Time_Value_Test \ - Timeprobe_Test \ - Timer_Queue_Test \ - TkReactor_Test \ - Tokens_Test \ + Semaphore_Test \ + Service_Config_Test \ + Signal_Test \ + Sigset_Ops_Test \ + Simple_Message_Block_Test \ + SOCK_Connector_Test \ + SOCK_Send_Recv_Test \ + SOCK_Test \ + SPIPE_Test \ + SString_Test \ + SV_Shared_Memory_Test \ + Svc_Handler_Test \ + Task_Test \ + Thread_Manager_Test \ + Thread_Mutex_Test \ + Thread_Pool_Reactor_Resume_Test \ + Thread_Pool_Reactor_Test \ + Thread_Pool_Test \ + Time_Service_Test \ + Time_Value_Test \ + Timeprobe_Test \ + Timer_Cancellation_Test \ + Timer_Queue_Reference_Counting_Test \ + Timer_Queue_Test \ + TkReactor_Test \ Token_Strategy_Test \ - TP_Reactor_Test \ - TSS_Test \ - Vector_Test \ + Tokens_Test \ + TP_Reactor_Test \ + TSS_Test \ Unbounded_Set_Test_Ex \ - Upgradable_RW_Test \ - UPIPE_SAP_Test \ - XtReactor_Test + Upgradable_RW_Test \ + UPIPE_SAP_Test \ + Vector_Test \ + WFMO_Reactor_Test \ + XtReactor_Test !ifdef SSL_ROOT DIRS = RMCast \ - SSL + SSL !else DIRS = RMCast !endif diff --git a/tests/NonBlocking_Conn_Test.cpp b/tests/NonBlocking_Conn_Test.cpp new file mode 100644 index 00000000000..c26dd49e8aa --- /dev/null +++ b/tests/NonBlocking_Conn_Test.cpp @@ -0,0 +1,339 @@ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// tests +// +// = FILENAME +// NonBlocking_Conn_Test.cpp +// +// = DESCRIPTION +// This test checks for the proper working of the following: +// - blocking connections +// - blocking connections with timeouts +// - non-blocking connections +// - non-blocking connections without waiting for completions +// - non-blocking connections with timeouts +// +// = AUTHOR +// Irfan Pyarali <irfan@oomworks.com> +// +// ============================================================================ + +#include "test_config.h" +#include "ace/Connector.h" +#include "ace/Svc_Handler.h" +#include "ace/SOCK_Stream.h" +#include "ace/SOCK_Connector.h" +#include "ace/Select_Reactor.h" +#include "ace/TP_Reactor.h" +#include "ace/WFMO_Reactor.h" +#include "ace/Get_Opt.h" + +static int test_select_reactor = 1; +static int test_tp_reactor = 1; +static int test_wfmo_reactor = 1; + +class Svc_Handler : public ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH> +{ +public: + + enum Connection_Status + { + SUCCEEDED, + FAILED + }; + + Svc_Handler (void); + + void connection_status (Connection_Status &status, + int &completion_counter); + + int open (void *); + + int handle_close (ACE_HANDLE handle, + ACE_Reactor_Mask mask); + + Connection_Status *status_; + int *completion_counter_; +}; + +Svc_Handler::Svc_Handler (void) + : status_ (0), + completion_counter_ (0) +{ +} + +void +Svc_Handler::connection_status (Connection_Status &status, + int &completion_counter) +{ + this->status_ = &status; + this->completion_counter_ = &completion_counter; +} + +int +Svc_Handler::open (void *) +{ + *this->status_ = SUCCEEDED; + (*this->completion_counter_)++; + + return 0; +} + +int +Svc_Handler::handle_close (ACE_HANDLE handle, + ACE_Reactor_Mask mask) +{ + *this->status_ = FAILED; + (*this->completion_counter_)++; + + return ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH>::handle_close (handle, + mask); +} + +typedef ACE_Connector<Svc_Handler, + ACE_SOCK_CONNECTOR> + CONNECTOR; + +static const char* hosts[] = { + "www.russiantvguide.com:80", + "www.pakarmy.gov.pk:80", + "www.cnn.com:80", + "www.waca.com.au:80", + "www.uganda.co.ug:80", + "www.cs.wustl.edu:80", + "www.affa-az.com:80", + "www.dhm.gov.np:80", + "www.msn.com:80", + "www.presidencymaldives.gov.mv:80" }; + +static int number_of_connections = 0; + +void +test_connect (ACE_Reactor &reactor, + ACE_INET_Addr *addresses, + ACE_Synch_Options &synch_options, + int complete_nonblocking_connections) +{ + CONNECTOR connector (&reactor); + + int i = 0; + + int completion_counter = 0; + Svc_Handler::Connection_Status *connection_status = + new Svc_Handler::Connection_Status[number_of_connections]; + + Svc_Handler **svc_handlers = + new Svc_Handler *[number_of_connections]; + + for (i = 0; i < number_of_connections; ++i) + { + svc_handlers[i] = + new Svc_Handler; + + svc_handlers[i]->connection_status (connection_status[i], + completion_counter); + } + + connector.connect_n (number_of_connections, + svc_handlers, + addresses, + 0, + synch_options); + + if (!synch_options[ACE_Synch_Options::USE_REACTOR]) + ACE_ASSERT (completion_counter == number_of_connections); + + if (complete_nonblocking_connections) + { + while (completion_counter != number_of_connections) + { + connector.reactor ()->handle_events (); + } + } + + connector.close (); + + for (i = 0; i < number_of_connections; ++i) + { + ACE_TCHAR buffer[1024]; + addresses[i].addr_to_string (buffer, + sizeof buffer, + 1); + + ACE_DEBUG ((LM_DEBUG, + "Connection to %s %s\n", + buffer, + connection_status[i] == Svc_Handler::SUCCEEDED ? + "succeeded" : "failed")); + + if (connection_status[i] == Svc_Handler::SUCCEEDED) + { + svc_handlers[i]->close (); + } + } + + delete[] svc_handlers; + delete[] connection_status; +} + +void +test (ACE_Reactor_Impl *impl) +{ + number_of_connections = sizeof hosts / sizeof (char *); + + ACE_INET_Addr *addresses = + new ACE_INET_Addr[number_of_connections]; + + for (int i = 0; i < number_of_connections; ++i) + { + addresses[i] = ACE_INET_Addr (hosts[i]); + } + + ACE_Reactor reactor (impl, + 1); + + int complete_nonblocking_connections = 1; + int dont_wait_for_nonblocking_connections = 0; + int ignored = 99; + + ACE_Synch_Options blocking_connect = + ACE_Synch_Options::defaults; + + ACE_DEBUG ((LM_DEBUG, + "\nBlocking connections...\n\n")); + + test_connect (reactor, + addresses, + blocking_connect, + ignored); + + blocking_connect.set (ACE_Synch_Options::USE_TIMEOUT, + ACE_Time_Value (0, 50 * 1000)); + + ACE_DEBUG ((LM_DEBUG, + "\nBlocking connections (with timeouts)...\n\n")); + + test_connect (reactor, + addresses, + blocking_connect, + ignored); + + ACE_Synch_Options nonblocking_connect + (ACE_Synch_Options::USE_REACTOR); + + ACE_DEBUG ((LM_DEBUG, + "\nNon-blocking connections...\n\n")); + + test_connect (reactor, + addresses, + nonblocking_connect, + complete_nonblocking_connections); + + ACE_DEBUG ((LM_DEBUG, + "\nNon-blocking connections (without waiting for completions)...\n\n")); + + test_connect (reactor, + addresses, + nonblocking_connect, + dont_wait_for_nonblocking_connections); + + nonblocking_connect.set (ACE_Synch_Options::USE_REACTOR | + ACE_Synch_Options::USE_TIMEOUT, + ACE_Time_Value (0, 500 * 1000)); + + ACE_DEBUG ((LM_DEBUG, + "\nNon-blocking connections (with timeouts)...\n\n")); + + test_connect (reactor, + addresses, + nonblocking_connect, + complete_nonblocking_connections); + + delete[] addresses; +} + +static int +parse_args (int argc, ACE_TCHAR *argv[]) +{ + ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("a:b:c:")); + + int cc; + while ((cc = get_opt ()) != -1) + { + switch (cc) + { + case 'a': + test_select_reactor = ACE_OS::atoi (get_opt.opt_arg ()); + break; + case 'b': + test_tp_reactor = ACE_OS::atoi (get_opt.opt_arg ()); + break; + case 'c': + test_wfmo_reactor = ACE_OS::atoi (get_opt.opt_arg ()); + break; + case '?': + case 'u': + default: + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("\nusage: %s \n\n") + ACE_TEXT ("\t[-a test Select Reactor] (defaults to %d)\n") + ACE_TEXT ("\t[-b test TP Reactor] (defaults to %d)\n") + ACE_TEXT ("\t[-c test WFMO Reactor] (defaults to %d)\n") + ACE_TEXT ("\n"), + argv[0], + test_select_reactor, + test_tp_reactor, + test_wfmo_reactor)); + return -1; + } + } + + return 0; +} + +int +ACE_TMAIN (int argc, ACE_TCHAR *argv[]) +{ + ACE_START_TEST (ACE_TEXT ("NonBlocking_Conn_Test")); + + // Validate options. + int result = + parse_args (argc, argv); + if (result != 0) + return result; + + if (test_select_reactor) + { + ACE_DEBUG ((LM_DEBUG, + "\n\nTesting Select Reactor....\n\n")); + + test (new ACE_Select_Reactor); + } + + if (test_tp_reactor) + { + ACE_DEBUG ((LM_DEBUG, + "\n\nTesting TP Reactor....\n\n")); + + test (new ACE_TP_Reactor); + } + +#if defined (ACE_WIN32) + + if (test_wfmo_reactor) + { + ACE_DEBUG ((LM_DEBUG, + "\n\nTesting WFMO Reactor....\n\n")); + + test (new ACE_WFMO_Reactor); + } + +#endif /* ACE_WIN32 */ + + ACE_END_TEST; + + return 0; +} diff --git a/tests/NonBlocking_Conn_Test.dsp b/tests/NonBlocking_Conn_Test.dsp new file mode 100644 index 00000000000..06aa128d24a --- /dev/null +++ b/tests/NonBlocking_Conn_Test.dsp @@ -0,0 +1,162 @@ +# Microsoft Developer Studio Project File - Name="NonBlocking_Conn_Test" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=NonBlocking_Conn_Test - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "NonBlocking_Conn_Test.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "NonBlocking_Conn_Test.mak" CFG="NonBlocking_Conn_Test - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "NonBlocking_Conn_Test - Win32 Static Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE "NonBlocking_Conn_Test - Win32 Static Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "NonBlocking_Conn_Test - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "NonBlocking_Conn_Test - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "NonBlocking_Conn_Test - Win32 Static Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Static_Debug"
+# PROP BASE Intermediate_Dir "Static_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Static_Debug"
+# PROP Intermediate_Dir "Static_Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "../" /D "_DEBUG" /D ACE_AS_STATIC_LIBS /D "WIN32" /D "_CONSOLE" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386
+# ADD LINK32 acesd.lib advapi32.lib user32.lib /nologo /subsystem:console /debug /machine:I386 /libpath:"..\ace"
+
+!ELSEIF "$(CFG)" == "NonBlocking_Conn_Test - Win32 Static Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Static_Release"
+# PROP BASE Intermediate_Dir "Static_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Static_Release"
+# PROP Intermediate_Dir "Static_Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "../" /D "NDEBUG" /D ACE_AS_STATIC_LIBS /D "WIN32" /D "_CONSOLE" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 aces.lib advapi32.lib user32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\ace"
+
+!ELSEIF "$(CFG)" == "NonBlocking_Conn_Test - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "../" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 ace.lib /nologo /subsystem:console /machine:I386 /libpath:"..\ace"
+
+!ELSEIF "$(CFG)" == "NonBlocking_Conn_Test - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "../" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 aced.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\ace"
+
+!ENDIF
+
+# Begin Target
+
+# Name "NonBlocking_Conn_Test - Win32 Static Debug"
+# Name "NonBlocking_Conn_Test - Win32 Static Release"
+# Name "NonBlocking_Conn_Test - Win32 Release"
+# Name "NonBlocking_Conn_Test - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90"
+# Begin Source File
+
+SOURCE=.\NonBlocking_Conn_Test.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
+# Begin Source File
+
+SOURCE=.\test_config.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/tests/Reactor_Registration_Test.cpp b/tests/Reactor_Registration_Test.cpp new file mode 100644 index 00000000000..26f744623d7 --- /dev/null +++ b/tests/Reactor_Registration_Test.cpp @@ -0,0 +1,180 @@ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// tests +// +// = FILENAME +// Reactor_Registration_Test.cpp +// +// = DESCRIPTION +// This is a test of registering handlers with the Reactor. +// +// = AUTHOR +// Irfan Pyarali <irfan@oomworks.com> +// +// ============================================================================ + +#include "tests/test_config.h" +#include "ace/Pipe.h" +#include "ace/Select_Reactor.h" +#include "ace/TP_Reactor.h" +#include "ace/WFMO_Reactor.h" + +ACE_RCSID(tests, Reactor_Registration_Test, "$Id$") + +static const char message[] = "abcdefghijklmnopqrstuvwxyz"; +static const int message_size = 26; +static int iteration = 1; + +class Event_Handler : public ACE_Event_Handler +{ +public: + + Event_Handler (ACE_Reactor &reactor, + ACE_HANDLE read, + ACE_HANDLE write); + + ~Event_Handler (void); + + int handle_input (ACE_HANDLE fd = ACE_INVALID_HANDLE); + + int handle_close (ACE_HANDLE handle, + ACE_Reactor_Mask close_mask); + + ACE_Pipe pipe_; +}; + +Event_Handler::Event_Handler (ACE_Reactor &reactor, + ACE_HANDLE read, + ACE_HANDLE write) + : ACE_Event_Handler (&reactor), + pipe_ (read, write) +{ + int result = 0; + + if (read == ACE_INVALID_HANDLE) + { + result = + this->pipe_.open (); + ACE_ASSERT (result == 0); + ACE_UNUSED_ARG (result); + } + + result = + this->reactor ()->register_handler (this->pipe_.read_handle (), + this, + ACE_Event_Handler::READ_MASK); + ACE_ASSERT (result == 0); + ACE_UNUSED_ARG (result); + + result = + ACE::send_n (this->pipe_.write_handle (), + message, + message_size); + ACE_ASSERT (result == message_size); + ACE_UNUSED_ARG (result); + + ACE_DEBUG ((LM_DEBUG, + "Event_Handler::Event_Handler for %x\n", + this)); +} + +Event_Handler::~Event_Handler (void) +{ + ACE_DEBUG ((LM_DEBUG, + "Event_Handler::~Event_Handler for %x\n", + this)); +} + +int +Event_Handler::handle_input (ACE_HANDLE handle) +{ + char buf[message_size + 1]; + + int result = + ACE::recv_n (handle, + buf, + sizeof buf - 1); + ACE_ASSERT (result == message_size); + ACE_UNUSED_ARG (result); + + buf[message_size] = '\0'; + + ACE_DEBUG ((LM_DEBUG, + "Message %s received for %x\n", + buf, + this)); + + return -1; +} + +int +Event_Handler::handle_close (ACE_HANDLE handle, + ACE_Reactor_Mask close_mask) +{ + switch (iteration) + { + case 1: + new Event_Handler (*this->reactor (), + ACE_INVALID_HANDLE, + ACE_INVALID_HANDLE); + break; + case 2: + new Event_Handler (*this->reactor (), + this->pipe_.read_handle (), + this->pipe_.write_handle ()); + break; + case 3: + this->reactor ()->end_reactor_event_loop (); + break; + } + + iteration++; + delete this; + + return 0; +} + +void +test (ACE_Reactor_Impl &reactor_impl, + const char *reactor_type) +{ + ACE_DEBUG ((LM_DEBUG, + "\nTesting with %s\n\n", + reactor_type)); + + ACE_Reactor reactor (&reactor_impl, + 0); + + new Event_Handler (reactor, + ACE_INVALID_HANDLE, + ACE_INVALID_HANDLE); + + reactor.run_reactor_event_loop (); +} + +int +ACE_TMAIN (int, ACE_TCHAR *[]) +{ + ACE_START_TEST (ACE_TEXT ("Reactor_Registration_Test")); + + iteration = 1; + ACE_Select_Reactor select_reactor; + test (select_reactor, "ACE_Select_Reactor"); + + iteration = 1; + ACE_TP_Reactor tp_reactor; + test (tp_reactor, "ACE_TP_Reactor"); + +#if defined (ACE_WIN32) + iteration = 1; + ACE_WFMO_Reactor wfmo_reactor; + test (wfmo_reactor, "ACE_WFMO_Reactor"); +#endif /* ACE_WIN32 */ + + ACE_END_TEST; + + return 0; +} diff --git a/tests/Reactor_Registration_Test.dsp b/tests/Reactor_Registration_Test.dsp new file mode 100644 index 00000000000..bca004be3f4 --- /dev/null +++ b/tests/Reactor_Registration_Test.dsp @@ -0,0 +1,158 @@ +# Microsoft Developer Studio Project File - Name="Reactor_Registration_Test" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=Reactor_Registration_Test - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "Reactor_Registration_Test.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "Reactor_Registration_Test.mak" CFG="Reactor_Registration_Test - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "Reactor_Registration_Test - Win32 Static Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE "Reactor_Registration_Test - Win32 Static Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "Reactor_Registration_Test - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "Reactor_Registration_Test - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "Reactor_Registration_Test - Win32 Static Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Static_Debug"
+# PROP BASE Intermediate_Dir "Static_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Static_Debug"
+# PROP Intermediate_Dir "Static_Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "../" /D "_DEBUG" /D ACE_AS_STATIC_LIBS /D "WIN32" /D "_CONSOLE" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386
+# ADD LINK32 acesd.lib advapi32.lib user32.lib /nologo /subsystem:console /debug /machine:I386 /libpath:"..\ace"
+
+!ELSEIF "$(CFG)" == "Reactor_Registration_Test - Win32 Static Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Static_Release"
+# PROP BASE Intermediate_Dir "Static_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Static_Release"
+# PROP Intermediate_Dir "Static_Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "../" /D "NDEBUG" /D ACE_AS_STATIC_LIBS /D "WIN32" /D "_CONSOLE" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 aces.lib advapi32.lib user32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\ace"
+
+!ELSEIF "$(CFG)" == "Reactor_Registration_Test - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "../" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 ace.lib /nologo /subsystem:console /machine:I386 /libpath:"..\ace"
+
+!ELSEIF "$(CFG)" == "Reactor_Registration_Test - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "../" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 aced.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\ace"
+
+!ENDIF
+
+# Begin Target
+
+# Name "Reactor_Registration_Test - Win32 Static Debug"
+# Name "Reactor_Registration_Test - Win32 Static Release"
+# Name "Reactor_Registration_Test - Win32 Release"
+# Name "Reactor_Registration_Test - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter ".cpp"
+# Begin Source File
+
+SOURCE=.\Reactor_Registration_Test.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter ".h"
+# Begin Source File
+
+SOURCE=.\test_config.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/tests/Reference_Counted_Event_Handler_Test.cpp b/tests/Reference_Counted_Event_Handler_Test.cpp new file mode 100644 index 00000000000..2296d2fa42f --- /dev/null +++ b/tests/Reference_Counted_Event_Handler_Test.cpp @@ -0,0 +1,923 @@ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// tests +// +// = FILENAME +// Reference_Counted_Event_Handler_Test.cpp +// +// = DESCRIPTION +// This test is used to check reference counting of the Event +// Handler when it interacts with the Reactor. +// +// = AUTHOR +// Irfan Pyarali <irfan@oomworks.com> +// +// ============================================================================ + +#include "test_config.h" +#include "ace/Select_Reactor.h" +#include "ace/TP_Reactor.h" +#include "ace/WFMO_Reactor.h" +#include "ace/Get_Opt.h" + +ACE_RCSID(tests, Reference_Counted_Event_Handler_Test, "$Id$") + +static const char message[] = "abcdefghijklmnopqrstuvwxyz"; +static const int message_size = 26; +static int test_select_reactor = 1; +static int test_tp_reactor = 1; +static int test_wfmo_reactor = 1; +static int test_io = 1; +static int test_timers = 1; +static int test_simple_event_handler = 1; +static int test_reference_counted_event_handler_1 = 1; +static int test_reference_counted_event_handler_2 = 1; +static int test_closed_in_upcall_event_handler = 1; +static int debug = 1; +static const char *one_second_timeout = "one second timeout"; +static const char *two_second_timeout = "two second timeout"; + +class Reference_Counted_Event_Handler : public ACE_Event_Handler +{ +public: + + Reference_Counted_Event_Handler (int &events); + + ~Reference_Counted_Event_Handler (void); + + int handle_input (ACE_HANDLE); + + int handle_output (ACE_HANDLE); + + int handle_timeout (const ACE_Time_Value &, + const void *); + + int handle_signal (int, siginfo_t *, ucontext_t *); + + int handle_close (ACE_HANDLE, + ACE_Reactor_Mask); + + ACE_Event_Handler::Reference_Count add_reference (void); + + ACE_Event_Handler::Reference_Count remove_reference (void); + + ACE_Pipe pipe_; + + int &events_; + +}; + +Reference_Counted_Event_Handler::Reference_Counted_Event_Handler (int &events) + : events_ (events) +{ + int result = + this->pipe_.open (); + + ACE_ASSERT (result == 0); + ACE_UNUSED_ARG (result); + + this->reference_counting_policy ().value + (ACE_Event_Handler::Reference_Counting_Policy::ENABLED); + + ACE_DEBUG ((LM_DEBUG, + "Reference count in Reference_Counted_Event_Handler() is %d\n", + this->reference_count_.value ())); +} + +Reference_Counted_Event_Handler::~Reference_Counted_Event_Handler (void) +{ + ACE_DEBUG ((LM_DEBUG, + "Reference count in ~Reference_Counted_Event_Handler() is %d\n", + this->reference_count_.value ())); +} + +int +Reference_Counted_Event_Handler::handle_input (ACE_HANDLE) +{ + ACE_DEBUG ((LM_DEBUG, + "Reference count in Reference_Counted_Event_Handler::handle_input() is %d\n", + this->reference_count_.value ())); + + --this->events_; + + char buf[message_size + 1]; + + ssize_t result = + ACE::recv_n (this->pipe_.read_handle (), + buf, + sizeof buf - 1); + + ACE_ASSERT (result == message_size); + + buf[message_size] = '\0'; + + ACE_DEBUG ((LM_DEBUG, + "Message received: %s\n", + buf)); + + return 0; +} + +int +Reference_Counted_Event_Handler::handle_output (ACE_HANDLE) +{ + ACE_DEBUG ((LM_DEBUG, + "Reference count in Reference_Counted_Event_Handler::handle_output() is %d\n", + this->reference_count_.value ())); + + --this->events_; + + ssize_t result = + ACE::send_n (this->pipe_.write_handle (), + message, + message_size); + + ACE_ASSERT (result == message_size); + + // No longer interested in output. + return -1; +} + +int +Reference_Counted_Event_Handler::handle_timeout (const ACE_Time_Value &, + const void *arg) +{ + ACE_DEBUG ((LM_DEBUG, + "Reference count in Reference_Counted_Event_Handler::handle_timeout() for arg = %s is %d\n", + (const char *) arg, + this->reference_count_.value ())); + + --this->events_; + + return 0; +} + +int +Reference_Counted_Event_Handler::handle_signal (int, + siginfo_t *, + ucontext_t *) +{ + return 0; +} + +int +Reference_Counted_Event_Handler::handle_close (ACE_HANDLE handle, + ACE_Reactor_Mask masks) +{ + ACE_DEBUG ((LM_DEBUG, + "Reference_Counted_Event_Handler::handle_close() called with handle = %d and masks = %d. " + "Reference count is %d\n", + handle, + masks, + this->reference_count_.value ())); + + return 0; +} + +ACE_Event_Handler::Reference_Count +Reference_Counted_Event_Handler::add_reference (void) +{ + ACE_Event_Handler::Reference_Count reference_count = + this->ACE_Event_Handler::add_reference (); + + ACE_DEBUG ((LM_DEBUG, + "Reference count after add_reference() is %d\n", + this->reference_count_.value ())); + + return reference_count; +} + +ACE_Event_Handler::Reference_Count +Reference_Counted_Event_Handler::remove_reference (void) +{ + ACE_Event_Handler::Reference_Count reference_count = + this->ACE_Event_Handler::remove_reference (); + + ACE_DEBUG ((LM_DEBUG, + "Reference count after remove_reference() is %d\n", + reference_count)); + + return reference_count; +} + +void +reference_counted_event_handler_test_1 (ACE_Reactor *reactor) +{ + int events = 0; + int result = 0; + + Reference_Counted_Event_Handler *handler = + new Reference_Counted_Event_Handler (events); + + ACE_Event_Handler_var safe_handler (handler); + + if (test_io) + { + result = + reactor->register_handler (handler->pipe_.read_handle (), + handler, + ACE_Event_Handler::READ_MASK); + ACE_ASSERT (result == 0); + + result = + reactor->register_handler (handler->pipe_.write_handle (), + handler, + ACE_Event_Handler::WRITE_MASK); + ACE_ASSERT (result == 0); + + events += 2; + } + + if (test_timers) + { + long timer_id = + reactor->schedule_timer (handler, + one_second_timeout, + 1, + 1); + ACE_ASSERT (timer_id != -1); + + result = + reactor->cancel_timer (timer_id, + 0, + 0); + ACE_ASSERT (result == 1); + + timer_id = + reactor->schedule_timer (handler, + one_second_timeout, + 1, + 1); + ACE_ASSERT (timer_id != -1); + + timer_id = + reactor->schedule_timer (handler, + two_second_timeout, + 2); + ACE_ASSERT (result != -1); + + events += 3; + } + + while (events > 0) + { + result = + reactor->handle_events (); + + ACE_ASSERT (result > 0); + } +} + +void +reference_counted_event_handler_test_2 (ACE_Reactor *reactor) +{ + int events = 0; + int result = 0; + + if (test_io) + { + Reference_Counted_Event_Handler *handler = + new Reference_Counted_Event_Handler (events); + + ACE_Event_Handler_var safe_handler (handler); + + result = + reactor->register_handler (handler->pipe_.read_handle (), + handler, + ACE_Event_Handler::READ_MASK); + ACE_ASSERT (result == 0); + + result = + reactor->register_handler (handler->pipe_.write_handle (), + handler, + ACE_Event_Handler::WRITE_MASK); + ACE_ASSERT (result == 0); + + events += 2; + } + + if (test_timers) + { + Reference_Counted_Event_Handler *handler = + new Reference_Counted_Event_Handler (events); + + ACE_Event_Handler_var safe_handler (handler); + + long timer_id = + reactor->schedule_timer (handler, + one_second_timeout, + 1, + 1); + ACE_ASSERT (timer_id != -1); + + result = + reactor->cancel_timer (timer_id, + 0, + 0); + ACE_ASSERT (result == 1); + } + + if (test_timers) + { + Reference_Counted_Event_Handler *handler = + new Reference_Counted_Event_Handler (events); + + ACE_Event_Handler_var safe_handler (handler); + + long timer_id = + reactor->schedule_timer (handler, + one_second_timeout, + 1, + 1); + ACE_ASSERT (timer_id != -1); + + timer_id = + reactor->schedule_timer (handler, + two_second_timeout, + 2); + ACE_ASSERT (result != -1); + + events += 3; + } + + while (events > 0) + { + result = + reactor->handle_events (); + + ACE_ASSERT (result > 0); + } +} + +void +reference_count_1 (ACE_Reactor_Impl *impl) +{ + ACE_Reactor reactor (impl, 1); + + ACE_DEBUG ((LM_DEBUG, + "\nTesting Reference Counted Event Handler Test 1....\n\n")); + + reference_counted_event_handler_test_1 (&reactor); +} + +void +reference_count_2 (ACE_Reactor_Impl *impl) +{ + ACE_Reactor reactor (impl, 1); + + ACE_DEBUG ((LM_DEBUG, + "\nTesting Reference Counted Event Handler Test 2....\n\n")); + + reference_counted_event_handler_test_2 (&reactor); +} + +class Simple_Event_Handler : public ACE_Event_Handler +{ +public: + + Simple_Event_Handler (int &events, + int close_count); + + ~Simple_Event_Handler (void); + + int handle_input (ACE_HANDLE); + + int handle_output (ACE_HANDLE); + + int handle_timeout (const ACE_Time_Value &, + const void *); + + int handle_signal (int, siginfo_t *, ucontext_t *); + + int handle_close (ACE_HANDLE, + ACE_Reactor_Mask); + + ACE_Event_Handler::Reference_Count add_reference (void); + + ACE_Event_Handler::Reference_Count remove_reference (void); + + ACE_Pipe pipe_; + + int close_count_; + + int &events_; + +}; + +Simple_Event_Handler::Simple_Event_Handler (int &events, + int close_count) + : events_ (events), + close_count_ (close_count) +{ + int result = + this->pipe_.open (); + + ACE_ASSERT (result == 0); + ACE_UNUSED_ARG (result); + + ACE_DEBUG ((LM_DEBUG, + "Simple_Event_Handler()\n")); +} + +Simple_Event_Handler::~Simple_Event_Handler (void) +{ + ACE_DEBUG ((LM_DEBUG, + "~Simple_Event_Handler()\n")); +} + +int +Simple_Event_Handler::handle_input (ACE_HANDLE) +{ + ACE_DEBUG ((LM_DEBUG, + "Simple_Event_Handler::handle_input()\n")); + + --this->events_; + + char buf[message_size + 1]; + + ssize_t result = + ACE::recv_n (this->pipe_.read_handle (), + buf, + sizeof buf - 1); + + ACE_ASSERT (result == message_size); + + buf[message_size] = '\0'; + + ACE_DEBUG ((LM_DEBUG, + "Message received: %s\n", + buf)); + + return 0; +} + +int +Simple_Event_Handler::handle_output (ACE_HANDLE) +{ + ACE_DEBUG ((LM_DEBUG, + "Simple_Event_Handler::handle_output()\n")); + + --this->events_; + + ssize_t result = + ACE::send_n (this->pipe_.write_handle (), + message, + message_size); + + ACE_ASSERT (result == message_size); + + // No longer interested in output. + return -1; +} + +int +Simple_Event_Handler::handle_timeout (const ACE_Time_Value &, + const void *arg) +{ + ACE_DEBUG ((LM_DEBUG, + "Simple_Event_Handler::handle_timeout() for arg = %s\n", + (const char *) arg)); + + --this->events_; + + return 0; +} + +int +Simple_Event_Handler::handle_signal (int, + siginfo_t *, + ucontext_t *) +{ + return 0; +} + +int +Simple_Event_Handler::handle_close (ACE_HANDLE handle, + ACE_Reactor_Mask masks) +{ + ACE_DEBUG ((LM_DEBUG, + "Simple_Event_Handler::handle_close() called with handle = %d and masks = %d with close count = %d.\n", + handle, + masks, + --this->close_count_)); + + if (this->close_count_ == 0) + delete this; + + return 0; +} + +ACE_Event_Handler::Reference_Count +Simple_Event_Handler::add_reference (void) +{ + // This should not get called. + ACE_ASSERT (0); + return 0; +} + +ACE_Event_Handler::Reference_Count +Simple_Event_Handler::remove_reference (void) +{ + // This should not get called. + ACE_ASSERT (0); + return 0; +} + +void +simple_event_handler (ACE_Reactor *reactor) +{ + int events = 0; + int result = 0; + + if (test_io) + { + Simple_Event_Handler *handler = + new Simple_Event_Handler (events, + 2); + + result = + reactor->register_handler (handler->pipe_.read_handle (), + handler, + ACE_Event_Handler::READ_MASK); + ACE_ASSERT (result == 0); + + result = + reactor->register_handler (handler->pipe_.write_handle (), + handler, + ACE_Event_Handler::WRITE_MASK); + ACE_ASSERT (result == 0); + + events += 2; + } + + if (test_timers) + { + Simple_Event_Handler *handler = + new Simple_Event_Handler (events, + 1); + + long timer_id = + reactor->schedule_timer (handler, + one_second_timeout, + 1, + 1); + ACE_ASSERT (timer_id != -1); + + result = + reactor->cancel_timer (timer_id, + 0, + 0); + ACE_ASSERT (result == 1); + } + + if (test_timers) + { + Simple_Event_Handler *handler = + new Simple_Event_Handler (events, + 1); + + long timer_id = + reactor->schedule_timer (handler, + one_second_timeout, + 1, + 1); + ACE_ASSERT (timer_id != -1); + + timer_id = + reactor->schedule_timer (handler, + two_second_timeout, + 2); + ACE_ASSERT (result != -1); + + events += 3; + } + + while (events > 0) + { + result = + reactor->handle_events (); + + ACE_ASSERT (result > 0); + } +} + +void +simple (ACE_Reactor_Impl *impl) +{ + ACE_Reactor reactor (impl, 1); + + ACE_DEBUG ((LM_DEBUG, + "\nTesting Simple Event Handler....\n\n")); + + simple_event_handler (&reactor); +} + +class Closed_In_Upcall_Event_Handler : public ACE_Event_Handler +{ +public: + + Closed_In_Upcall_Event_Handler (int &events); + + ~Closed_In_Upcall_Event_Handler (void); + + int handle_input (ACE_HANDLE); + + int handle_close (ACE_HANDLE, + ACE_Reactor_Mask); + + ACE_Event_Handler::Reference_Count add_reference (void); + + ACE_Event_Handler::Reference_Count remove_reference (void); + + ACE_Pipe pipe_; + + int &events_; + +}; + +Closed_In_Upcall_Event_Handler::Closed_In_Upcall_Event_Handler (int &events) + : events_ (events) +{ + int result = + this->pipe_.open (); + + ACE_ASSERT (result == 0); + ACE_UNUSED_ARG (result); + + this->reference_counting_policy ().value + (ACE_Event_Handler::Reference_Counting_Policy::ENABLED); + + ACE_DEBUG ((LM_DEBUG, + "Closed_In_Upcall_Event_Handler()\n")); +} + +Closed_In_Upcall_Event_Handler::~Closed_In_Upcall_Event_Handler (void) +{ + ACE_DEBUG ((LM_DEBUG, + "~Closed_In_Upcall_Event_Handler()\n")); +} + +int +Closed_In_Upcall_Event_Handler::handle_input (ACE_HANDLE) +{ + ACE_DEBUG ((LM_DEBUG, + "Closed_In_Upcall_Event_Handler::handle_input()\n")); + + this->events_--; + + int result = + this->reactor ()->remove_handler (this->pipe_.read_handle (), + ACE_Event_Handler::ALL_EVENTS_MASK); + ACE_ASSERT (result == 0); + ACE_UNUSED_ARG (result); + + char buf[message_size + 1]; + + ssize_t recv_result = + ACE::recv_n (this->pipe_.read_handle (), + buf, + sizeof buf - 1); + + ACE_ASSERT (recv_result == message_size); + + buf[message_size] = '\0'; + + ACE_DEBUG ((LM_DEBUG, + "Message received: %s\n", + buf)); + + return 0; +} + +int +Closed_In_Upcall_Event_Handler::handle_close (ACE_HANDLE handle, + ACE_Reactor_Mask masks) +{ + ACE_DEBUG ((LM_DEBUG, + "Closed_In_Upcall_Event_Handler::handle_close() called with handle = %d and masks = %d. " + "Reference count is %d\n", + handle, + masks, + this->reference_count_.value ())); + + return 0; +} + +ACE_Event_Handler::Reference_Count +Closed_In_Upcall_Event_Handler::add_reference (void) +{ + ACE_Event_Handler::Reference_Count reference_count = + this->ACE_Event_Handler::add_reference (); + + ACE_DEBUG ((LM_DEBUG, + "Reference count after add_reference() is %d\n", + this->reference_count_.value ())); + + return reference_count; +} + +ACE_Event_Handler::Reference_Count +Closed_In_Upcall_Event_Handler::remove_reference (void) +{ + ACE_Event_Handler::Reference_Count reference_count = + this->ACE_Event_Handler::remove_reference (); + + ACE_DEBUG ((LM_DEBUG, + "Reference count after remove_reference() is %d\n", + reference_count)); + + return reference_count; +} + +void +closed_in_upcall_event_handler (ACE_Reactor *reactor) +{ + int events = 0; + int result = 0; + + if (test_io) + { + Closed_In_Upcall_Event_Handler *handler = + new Closed_In_Upcall_Event_Handler (events); + + ACE_Event_Handler_var safe_handler (handler); + + ssize_t result = + ACE::send_n (handler->pipe_.write_handle (), + message, + message_size); + + ACE_ASSERT (result == message_size); + + result = + reactor->register_handler (handler->pipe_.read_handle (), + handler, + ACE_Event_Handler::READ_MASK); + ACE_ASSERT (result == 0); + + events += 1; + } + + while (events > 0) + { + result = + reactor->handle_events (); + + ACE_ASSERT (result > 0); + } +} + +void +closed_in_upcall (ACE_Reactor_Impl *impl) +{ + ACE_Reactor reactor (impl, 1); + + ACE_DEBUG ((LM_DEBUG, + "\nTesting Closed in Upcall Event Handler....\n\n")); + + closed_in_upcall_event_handler (&reactor); +} + +template <class REACTOR_IMPLEMENTATION> +class test +{ +public: + test (void); +}; + +template <class REACTOR_IMPLEMENTATION> +test<REACTOR_IMPLEMENTATION>::test (void) +{ + if (test_simple_event_handler) + simple (new REACTOR_IMPLEMENTATION); + + if (test_reference_counted_event_handler_1) + reference_count_1 (new REACTOR_IMPLEMENTATION); + + if (test_reference_counted_event_handler_2) + reference_count_2 (new REACTOR_IMPLEMENTATION); + + if (test_closed_in_upcall_event_handler) + closed_in_upcall (new REACTOR_IMPLEMENTATION); +} + +static int +parse_args (int argc, ACE_TCHAR *argv[]) +{ + ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("a:b:c:f:g:h:i:k:l:z:")); + + int cc; + while ((cc = get_opt ()) != -1) + { + switch (cc) + { + case 'a': + test_select_reactor = ACE_OS::atoi (get_opt.opt_arg ()); + break; + case 'b': + test_tp_reactor = ACE_OS::atoi (get_opt.opt_arg ()); + break; + case 'c': + test_wfmo_reactor = ACE_OS::atoi (get_opt.opt_arg ()); + break; + case 'f': + test_simple_event_handler = ACE_OS::atoi (get_opt.opt_arg ()); + break; + case 'g': + test_reference_counted_event_handler_1 = ACE_OS::atoi (get_opt.opt_arg ()); + break; + case 'h': + test_reference_counted_event_handler_2 = ACE_OS::atoi (get_opt.opt_arg ()); + break; + case 'i': + test_closed_in_upcall_event_handler = ACE_OS::atoi (get_opt.opt_arg ()); + break; + case 'k': + test_io = ACE_OS::atoi (get_opt.opt_arg ()); + break; + case 'l': + test_timers = ACE_OS::atoi (get_opt.opt_arg ()); + break; + case 'z': + debug = ACE_OS::atoi (get_opt.opt_arg ()); + break; + case '?': + case 'u': + default: + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("\nusage: %s \n\n") + ACE_TEXT ("\t[-a test Select Reactor] (defaults to %d)\n") + ACE_TEXT ("\t[-b test TP Reactor] (defaults to %d)\n") + ACE_TEXT ("\t[-c test WFMO Reactor] (defaults to %d)\n") + ACE_TEXT ("\t[-f test simple event handler] (defaults to %d)\n") + ACE_TEXT ("\t[-g test reference counted event handler (first test)] (defaults to %d)\n") + ACE_TEXT ("\t[-h test reference counted event handler (second test)] (defaults to %d)\n") + ACE_TEXT ("\t[-i test closed in upcall event handler] (defaults to %d)\n") + ACE_TEXT ("\t[-k test io] (defaults to %d)\n") + ACE_TEXT ("\t[-l test timers] (defaults to %d)\n") + ACE_TEXT ("\t[-z debug] (defaults to %d)\n") + ACE_TEXT ("\n"), + argv[0], + test_select_reactor, + test_tp_reactor, + test_wfmo_reactor, + test_simple_event_handler, + test_reference_counted_event_handler_1, + test_reference_counted_event_handler_2, + test_closed_in_upcall_event_handler, + test_io, + test_timers, + debug)); + return -1; + } + } + + return 0; +} + +int +ACE_TMAIN (int argc, ACE_TCHAR *argv[]) +{ + ACE_START_TEST (ACE_TEXT ("Reference_Counted_Event_Handler_Test")); + + // Validate options. + int result = + parse_args (argc, argv); + if (result != 0) + return result; + + if (test_select_reactor) + { + ACE_DEBUG ((LM_DEBUG, + "\n\nTesting Select Reactor....\n\n")); + + test<ACE_Select_Reactor> test_select_reactor; + } + + if (test_tp_reactor) + { + ACE_DEBUG ((LM_DEBUG, + "\n\nTesting TP Reactor....\n\n")); + + test<ACE_TP_Reactor> test_tp_reactor; + } + +#if defined (ACE_WIN32) + + if (test_wfmo_reactor) + { + ACE_DEBUG ((LM_DEBUG, + "\n\nTesting WFMO Reactor....\n\n")); + + test<ACE_WFMO_Reactor> test_wfmo_reactor; + } + +#endif /* ACE_WIN32 */ + + ACE_END_TEST; + + return 0; +} diff --git a/tests/Reference_Counted_Event_Handler_Test.dsp b/tests/Reference_Counted_Event_Handler_Test.dsp new file mode 100644 index 00000000000..74c1432e724 --- /dev/null +++ b/tests/Reference_Counted_Event_Handler_Test.dsp @@ -0,0 +1,158 @@ +# Microsoft Developer Studio Project File - Name="Reference_Counted_Event_Handler_Test" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=Reference_Counted_Event_Handler_Test - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "Reference_Counted_Event_Handler_Test.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "Reference_Counted_Event_Handler_Test.mak" CFG="Reference_Counted_Event_Handler_Test - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "Reference_Counted_Event_Handler_Test - Win32 Static Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE "Reference_Counted_Event_Handler_Test - Win32 Static Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "Reference_Counted_Event_Handler_Test - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "Reference_Counted_Event_Handler_Test - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "Reference_Counted_Event_Handler_Test - Win32 Static Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Static_Debug"
+# PROP BASE Intermediate_Dir "Static_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Static_Debug"
+# PROP Intermediate_Dir "Static_Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "../" /D "_DEBUG" /D ACE_AS_STATIC_LIBS /D "WIN32" /D "_CONSOLE" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386
+# ADD LINK32 acesd.lib advapi32.lib user32.lib /nologo /subsystem:console /debug /machine:I386 /libpath:"..\ace"
+
+!ELSEIF "$(CFG)" == "Reference_Counted_Event_Handler_Test - Win32 Static Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Static_Release"
+# PROP BASE Intermediate_Dir "Static_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Static_Release"
+# PROP Intermediate_Dir "Static_Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "../" /D "NDEBUG" /D ACE_AS_STATIC_LIBS /D "WIN32" /D "_CONSOLE" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 aces.lib advapi32.lib user32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\ace"
+
+!ELSEIF "$(CFG)" == "Reference_Counted_Event_Handler_Test - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "../" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 ace.lib /nologo /subsystem:console /machine:I386 /libpath:"..\ace"
+
+!ELSEIF "$(CFG)" == "Reference_Counted_Event_Handler_Test - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "../" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 aced.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\ace"
+
+!ENDIF
+
+# Begin Target
+
+# Name "Reference_Counted_Event_Handler_Test - Win32 Static Debug"
+# Name "Reference_Counted_Event_Handler_Test - Win32 Static Release"
+# Name "Reference_Counted_Event_Handler_Test - Win32 Release"
+# Name "Reference_Counted_Event_Handler_Test - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter ".cpp"
+# Begin Source File
+
+SOURCE=.\Reference_Counted_Event_Handler_Test.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter ".h"
+# Begin Source File
+
+SOURCE=.\test_config.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/tests/Timer_Cancellation_Test.cpp b/tests/Timer_Cancellation_Test.cpp new file mode 100644 index 00000000000..997e9b59114 --- /dev/null +++ b/tests/Timer_Cancellation_Test.cpp @@ -0,0 +1,159 @@ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// tests +// +// = FILENAME +// Timer_Cancellation_Test.cpp +// +// = DESCRIPTION +// A test to ensure the timer cancellation works correctly. +// +// = AUTHOR +// Irfan Pyarali <irfan@oomworks.com> +// +// ============================================================================ + +#include "tests/test_config.h" +#include "ace/TP_Reactor.h" +#include "ace/Task.h" + +ACE_RCSID(tests, Timer_Cancellation_Test, "$Id$") + +#if defined (ACE_HAS_THREADS) + +class Deadlock : public ACE_Task_Base +{ +public: + + int svc (void); + + int handle_timeout (const ACE_Time_Value ¤t_time, + const void *act); +}; + +int +Deadlock::svc (void) +{ + ACE_DEBUG ((LM_DEBUG, + "Deadlock starts accessing Reactor and Timer Queue....\n")); + + this->reactor ()->schedule_timer (this, + 0, + ACE_Time_Value (1)); + + ACE_DEBUG ((LM_DEBUG, + "Deadlock completes accessing Reactor and Timer Queue....\n")); + + return 0; +} + +int +Deadlock::handle_timeout (const ACE_Time_Value &, + const void *) +{ + ACE_DEBUG ((LM_DEBUG, + "Deadlock timeout\n")); + + return 0; +} + +class Event_Handler : public ACE_Event_Handler +{ +public: + + Event_Handler (Deadlock &deadlock); + + int handle_timeout (const ACE_Time_Value ¤t_time, + const void *act); + + int handle_close (ACE_HANDLE handle, + ACE_Reactor_Mask close_mask); + + Deadlock &deadlock_; +}; + +Event_Handler::Event_Handler (Deadlock &deadlock) + : deadlock_ (deadlock) +{ +} + +int +Event_Handler::handle_timeout (const ACE_Time_Value ¤t_time, + const void *act) +{ + ACE_DEBUG ((LM_DEBUG, + "Event_Handler timeout\n")); + + return -1; +} + +int +Event_Handler::handle_close (ACE_HANDLE handle, + ACE_Reactor_Mask close_mask) +{ + ACE_DEBUG ((LM_DEBUG, + "Event_Handler closed\n")); + + // Activate Deadlock. + this->deadlock_.activate (); + + // Give Deadlock a chance to deadlock... ;-) + ACE_OS::sleep (1); + + ACE_DEBUG ((LM_DEBUG, + "Event Handler starts accessing Reactor....\n")); + + // This is a superfluous call to the Reactor to acquire its lock. + this->reactor ()->max_notify_iterations (); + + ACE_DEBUG ((LM_DEBUG, + "Event Handler completes accessing Reactor....\n")); + + return 0; +} + +int +ACE_TMAIN (int, ACE_TCHAR *[]) +{ + ACE_START_TEST (ACE_TEXT ("Timer_Cancellation_Test")); + + ACE_Reactor reactor (new ACE_TP_Reactor, + 1); + + Deadlock deadlock; + deadlock.reactor (&reactor); + + Event_Handler handler (deadlock); + + // Scheduler a timer to kick things off. + reactor.schedule_timer (&handler, + 0, + ACE_Time_Value (1)); + + // Run the event loop for a while. + reactor.run_reactor_event_loop (ACE_Time_Value (4)); + + ACE_END_TEST; + + return 0; +} + +#else /* ACE_HAS_THREADS */ + +int +ACE_TMAIN (int, ACE_TCHAR *[]) +{ + ACE_START_TEST (ACE_TEXT ("Timer_Cancellation_Test")); + + ACE_ERROR ((LM_INFO, + ACE_TEXT ("threads not supported on this platform\n"))); + + ACE_END_TEST; + + return 0; +} + +#endif /* ACE_HAS_THREADS */ diff --git a/tests/Timer_Cancellation_Test.dsp b/tests/Timer_Cancellation_Test.dsp new file mode 100644 index 00000000000..e77caebb275 --- /dev/null +++ b/tests/Timer_Cancellation_Test.dsp @@ -0,0 +1,158 @@ +# Microsoft Developer Studio Project File - Name="Timer_Cancellation_Test" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=Timer_Cancellation_Test - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "Timer_Cancellation_Test.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "Timer_Cancellation_Test.mak" CFG="Timer_Cancellation_Test - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "Timer_Cancellation_Test - Win32 Static Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE "Timer_Cancellation_Test - Win32 Static Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "Timer_Cancellation_Test - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "Timer_Cancellation_Test - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "Timer_Cancellation_Test - Win32 Static Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Static_Debug"
+# PROP BASE Intermediate_Dir "Static_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Static_Debug"
+# PROP Intermediate_Dir "Static_Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "../" /D "_DEBUG" /D ACE_AS_STATIC_LIBS /D "WIN32" /D "_CONSOLE" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386
+# ADD LINK32 acesd.lib advapi32.lib user32.lib /nologo /subsystem:console /debug /machine:I386 /libpath:"..\ace"
+
+!ELSEIF "$(CFG)" == "Timer_Cancellation_Test - Win32 Static Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Static_Release"
+# PROP BASE Intermediate_Dir "Static_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Static_Release"
+# PROP Intermediate_Dir "Static_Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "../" /D "NDEBUG" /D ACE_AS_STATIC_LIBS /D "WIN32" /D "_CONSOLE" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 aces.lib advapi32.lib user32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\ace"
+
+!ELSEIF "$(CFG)" == "Timer_Cancellation_Test - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "../" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 ace.lib /nologo /subsystem:console /machine:I386 /libpath:"..\ace"
+
+!ELSEIF "$(CFG)" == "Timer_Cancellation_Test - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "../" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 aced.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\ace"
+
+!ENDIF
+
+# Begin Target
+
+# Name "Timer_Cancellation_Test - Win32 Static Debug"
+# Name "Timer_Cancellation_Test - Win32 Static Release"
+# Name "Timer_Cancellation_Test - Win32 Release"
+# Name "Timer_Cancellation_Test - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter ".cpp"
+# Begin Source File
+
+SOURCE=.\Timer_Cancellation_Test.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter ".h"
+# Begin Source File
+
+SOURCE=.\test_config.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/tests/Timer_Queue_Reference_Counting_Test.cpp b/tests/Timer_Queue_Reference_Counting_Test.cpp new file mode 100644 index 00000000000..6a4f662674b --- /dev/null +++ b/tests/Timer_Queue_Reference_Counting_Test.cpp @@ -0,0 +1,680 @@ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// tests +// +// = FILENAME +// Timer_Queue_Reference_Counting_Test.cpp +// +// = DESCRIPTION +// This test is used to check reference counting of the Event +// Handler when it interacts with Timer Queues. +// +// = AUTHOR +// Irfan Pyarali <irfan@oomworks.com> +// +// ============================================================================ + +#include "test_config.h" +#include "ace/Get_Opt.h" +#include "ace/Timer_Queue.h" +#include "ace/Timer_Heap.h" +#include "ace/Timer_List.h" +#include "ace/Timer_Hash.h" +#include "ace/Timer_Wheel.h" +#include "ace/Reactor.h" + +ACE_RCSID(tests, Timer_Queue_Reference_Counting_Test, "$Id$") + +static int debug = 0; +static const char *one_second_timeout = "one second timeout"; +static const char *two_second_timeout = "two second timeout"; + +class Reference_Counted_Event_Handler : public ACE_Event_Handler +{ +public: + + Reference_Counted_Event_Handler (int expected_number_of_handle_close_calls); + + ~Reference_Counted_Event_Handler (void); + + int handle_timeout (const ACE_Time_Value &, + const void *); + + int handle_close (ACE_HANDLE handle, + ACE_Reactor_Mask masks); + + int expected_number_of_handle_close_calls_; + int number_of_handle_close_calls_; +}; + +Reference_Counted_Event_Handler::Reference_Counted_Event_Handler (int expected_number_of_handle_close_calls) + : expected_number_of_handle_close_calls_ (expected_number_of_handle_close_calls), + number_of_handle_close_calls_ (0) +{ + this->reference_counting_policy ().value + (ACE_Event_Handler::Reference_Counting_Policy::ENABLED); + + if (debug) + ACE_DEBUG ((LM_DEBUG, + "Reference count in Reference_Counted_Event_Handler() is %d\n", + this->reference_count_.value ())); +} + +Reference_Counted_Event_Handler::~Reference_Counted_Event_Handler (void) +{ + if (debug) + ACE_DEBUG ((LM_DEBUG, + "Reference count in ~Reference_Counted_Event_Handler() is %d\n", + this->reference_count_.value ())); + + if (this->expected_number_of_handle_close_calls_ != -1) + ACE_ASSERT (this->number_of_handle_close_calls_ == + this->expected_number_of_handle_close_calls_); +} + +int +Reference_Counted_Event_Handler::handle_timeout (const ACE_Time_Value &, + const void *arg) +{ + if (debug) + ACE_DEBUG ((LM_DEBUG, + "Reference count in Reference_Counted_Event_Handler::handle_timeout() for arg = %s is %d\n", + (const char *) arg, + this->reference_count_.value ())); + + return 0; +} + +int +Reference_Counted_Event_Handler::handle_close (ACE_HANDLE handle, + ACE_Reactor_Mask masks) +{ + if (debug) + ACE_DEBUG ((LM_DEBUG, + "Reference_Counted_Event_Handler::handle_close() called with handle = %d and masks = %d. " + "Reference count is %d\n", + handle, + masks, + this->reference_count_.value ())); + + ++this->number_of_handle_close_calls_; + + return 0; +} + +void +cancellation (ACE_Timer_Queue &timer_queue, + int repeat_timer, + int cancel_timers, + int cancel_handler, + int second_timer, + int dont_call_handle_close) +{ + int result = 0; + + int expected_number_of_handle_close_calls = -1; + if (!dont_call_handle_close) + { + if (second_timer) + expected_number_of_handle_close_calls = 2; + else + expected_number_of_handle_close_calls = 1; + } + + Reference_Counted_Event_Handler *handler = + new Reference_Counted_Event_Handler (expected_number_of_handle_close_calls); + + ACE_Event_Handler_var safe_handler (handler); + + long first_timer_id = -1; + long second_timer_id = -1; + + if (repeat_timer) + { + first_timer_id = + timer_queue.schedule (handler, + one_second_timeout, + ACE_Time_Value (1) + timer_queue.gettimeofday (), + ACE_Time_Value (1)); + ACE_ASSERT (first_timer_id != -1); + } + else + { + first_timer_id = + timer_queue.schedule (handler, + one_second_timeout, + ACE_Time_Value (1) + timer_queue.gettimeofday ()); + ACE_ASSERT (first_timer_id != -1); + } + + if (second_timer) + { + second_timer_id = + timer_queue.schedule (handler, + two_second_timeout, + ACE_Time_Value (2) + timer_queue.gettimeofday (), + ACE_Time_Value (2)); + ACE_ASSERT (second_timer_id != -1); + } + + if (!cancel_timers) + return; + + if (cancel_handler) + { + result = + timer_queue.cancel (handler, + dont_call_handle_close); + + if (second_timer) + ACE_ASSERT (result == 2); + else + ACE_ASSERT (result == 1); + } + else + { + result = + timer_queue.cancel (first_timer_id, + 0, + dont_call_handle_close); + ACE_ASSERT (result == 1); + + if (second_timer) + { + result = + timer_queue.cancel (second_timer_id, + 0, + dont_call_handle_close); + ACE_ASSERT (result == 1); + } + } +} + +template <class TIMER_QUEUE> +class cancellation_test +{ +public: + cancellation_test (const char *); +}; + +template <class TIMER_QUEUE> +cancellation_test<TIMER_QUEUE>::cancellation_test (const char *timer_queue_type) +{ + ACE_DEBUG ((LM_DEBUG, + "\nCancellation test for %s\n\n", + timer_queue_type)); + + int configs[][5] = { + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, + 0, 0, 0, 1, 0, + 0, 0, 0, 1, 1, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 1, + 0, 0, 1, 1, 0, + 0, 0, 1, 1, 1, + 0, 1, 0, 0, 0, + 0, 1, 0, 0, 1, + 0, 1, 0, 1, 0, + 0, 1, 0, 1, 1, + 0, 1, 1, 0, 0, + 0, 1, 1, 0, 1, + 0, 1, 1, 1, 0, + 0, 1, 1, 1, 1, + 1, 0, 0, 0, 0, + 1, 0, 0, 0, 1, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 1, + 1, 0, 1, 0, 0, + 1, 0, 1, 0, 1, + 1, 0, 1, 1, 0, + 1, 0, 1, 1, 1, + 1, 1, 0, 0, 0, + 1, 1, 0, 0, 1, + 1, 1, 0, 1, 0, + 1, 1, 0, 1, 1, + 1, 1, 1, 0, 0, + 1, 1, 1, 0, 1, + 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, + }; + + for (int i = 0; + i < sizeof configs / (sizeof (int) * 5); + i++) + { + TIMER_QUEUE timer_queue; + + cancellation (timer_queue, + configs[i][0], + configs[i][1], + configs[i][2], + configs[i][3], + configs[i][4]); + } +} + +typedef int (*Expire_Function) (ACE_Timer_Queue &timer_queue); + +int +invoke_expire (ACE_Timer_Queue &timer_queue) +{ + return timer_queue.expire (); +} + +int +invoke_one_upcall (ACE_Timer_Queue &timer_queue) +{ + // Get the current time + ACE_Time_Value current_time (timer_queue.gettimeofday () + + timer_queue.timer_skew ()); + + // Look for a node in the timer queue whose timer <= the present + // time. + ACE_Timer_Node_Dispatch_Info dispatch_info; + + if (timer_queue.dispatch_info (current_time, + dispatch_info)) + { + const void *upcall_act = 0; + + // Preinvoke. + timer_queue.preinvoke (dispatch_info, + current_time, + upcall_act); + + // Call the functor + timer_queue.upcall (dispatch_info, + current_time); + + // Postinvoke + timer_queue.postinvoke (dispatch_info, + current_time, + upcall_act); + + // We have dispatched a timer + return 1; + } + + return 0; +} + +void +expire (ACE_Timer_Queue &timer_queue, + Expire_Function expire_function) +{ + int events = 0; + int result = 0; + + Reference_Counted_Event_Handler *handler = + new Reference_Counted_Event_Handler (1); + + ACE_Event_Handler_var safe_handler (handler); + + long timer_id = + timer_queue.schedule (handler, + one_second_timeout, + ACE_Time_Value (1) + timer_queue.gettimeofday (), + ACE_Time_Value (1)); + ACE_ASSERT (timer_id != -1); + + timer_id = + timer_queue.schedule (handler, + two_second_timeout, + ACE_Time_Value (2) + timer_queue.gettimeofday ()); + ACE_ASSERT (result != -1); + + events += 4; + + for (int i = 0; i < events;) + { + ACE_Time_Value sleep_time; + + ACE_Time_Value earliest_time = + timer_queue.earliest_time (); + + ACE_Time_Value time_of_day = + timer_queue.gettimeofday (); + + if (earliest_time > time_of_day) + sleep_time = + earliest_time - time_of_day; + else + sleep_time = ACE_Time_Value::zero; + + ACE_OS::sleep (sleep_time); + + result = + expire_function (timer_queue); + + ACE_ASSERT (result >= 0); + + i += result; + } +} + +template<class TIMER_QUEUE> +class expire_test +{ +public: + expire_test (const char *); +}; + +template <class TIMER_QUEUE> +expire_test<TIMER_QUEUE>::expire_test (const char *timer_queue_type) +{ + ACE_DEBUG ((LM_DEBUG, + "\nExpire test for %s\n\n", + timer_queue_type)); + + TIMER_QUEUE timer_queue; + + expire (timer_queue, + invoke_expire); +} + +template<class TIMER_QUEUE> +class upcall_test +{ +public: + upcall_test (const char *); +}; + +template <class TIMER_QUEUE> +upcall_test<TIMER_QUEUE>::upcall_test (const char *timer_queue_type) +{ + ACE_DEBUG ((LM_DEBUG, + "\nOne upcall test for %s\n\n", + timer_queue_type)); + + TIMER_QUEUE timer_queue; + + expire (timer_queue, + invoke_one_upcall); +} + +class Simple_Event_Handler : public ACE_Event_Handler +{ +public: + + Simple_Event_Handler (void); + + ~Simple_Event_Handler (void); + + int handle_timeout (const ACE_Time_Value &, + const void *); + + int handle_close (ACE_HANDLE, + ACE_Reactor_Mask); + + ACE_Event_Handler::Reference_Count add_reference (void); + + ACE_Event_Handler::Reference_Count remove_reference (void); + +}; + +Simple_Event_Handler::Simple_Event_Handler (void) +{ + if (debug) + ACE_DEBUG ((LM_DEBUG, + "Simple_Event_Handler()\n")); +} + +Simple_Event_Handler::~Simple_Event_Handler (void) +{ + if (debug) + ACE_DEBUG ((LM_DEBUG, + "~Simple_Event_Handler()\n")); +} + +int +Simple_Event_Handler::handle_timeout (const ACE_Time_Value &, + const void *arg) +{ + if (debug) + ACE_DEBUG ((LM_DEBUG, + "Simple_Event_Handler::handle_timeout() for arg = %s\n", + (const char *) arg)); + return 0; +} + +int +Simple_Event_Handler::handle_close (ACE_HANDLE handle, + ACE_Reactor_Mask masks) +{ + if (debug) + ACE_DEBUG ((LM_DEBUG, + "Simple_Event_Handler::handle_close() called with handle = %d and masks = %d.\n", + handle, + masks)); + + delete this; + + return 0; +} + +ACE_Event_Handler::Reference_Count +Simple_Event_Handler::add_reference (void) +{ + // This should not get called. + ACE_ASSERT (0); + return 0; +} + +ACE_Event_Handler::Reference_Count +Simple_Event_Handler::remove_reference (void) +{ + // This should not get called. + ACE_ASSERT (0); + return 0; +} + +void +simple (ACE_Timer_Queue &timer_queue) +{ + int events = 0; + int result = 0; + + { + Simple_Event_Handler *handler = + new Simple_Event_Handler; + + long timer_id = + timer_queue.schedule (handler, + one_second_timeout, + ACE_Time_Value (1) + timer_queue.gettimeofday (), + ACE_Time_Value (1)); + ACE_ASSERT (timer_id != -1); + + result = + timer_queue.cancel (timer_id, + 0, + 0); + ACE_ASSERT (result == 1); + } + + { + Simple_Event_Handler *handler = + new Simple_Event_Handler; + + long timer_id = + timer_queue.schedule (handler, + one_second_timeout, + ACE_Time_Value (1) + timer_queue.gettimeofday (), + ACE_Time_Value (1)); + ACE_ASSERT (timer_id != -1); + + events += 3; + } + + for (int i = 0; i < events;) + { + ACE_OS::sleep (timer_queue.earliest_time () - + timer_queue.gettimeofday ()); + + result = + timer_queue.expire (); + + ACE_ASSERT (result >= 0); + + i += result; + } +} + +template <class TIMER_QUEUE> +class simple_test +{ +public: + simple_test (const char *); +}; + +template <class TIMER_QUEUE> +simple_test<TIMER_QUEUE>::simple_test (const char *timer_queue_type) +{ + ACE_DEBUG ((LM_DEBUG, + "\nSimple test for %s\n\n", + timer_queue_type)); + + TIMER_QUEUE timer_queue; + + simple (timer_queue); +} + +static int heap = 1; +static int list = 1; +static int hash = 1; +static int wheel = 1; +static int test_cancellation = 1; +static int test_expire = 1; +static int test_one_upcall = 1; +static int test_simple = 1; + +static int +parse_args (int argc, ACE_TCHAR *argv[]) +{ + ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("a:b:c:d:l:m:n:o:z:")); + + int cc; + while ((cc = get_opt ()) != -1) + { + switch (cc) + { + case 'a': + heap = ACE_OS::atoi (get_opt.opt_arg ()); + break; + case 'b': + list = ACE_OS::atoi (get_opt.opt_arg ()); + break; + case 'c': + hash = ACE_OS::atoi (get_opt.opt_arg ()); + break; + case 'd': + wheel = ACE_OS::atoi (get_opt.opt_arg ()); + break; + case 'l': + test_cancellation = ACE_OS::atoi (get_opt.opt_arg ()); + break; + case 'm': + test_expire = ACE_OS::atoi (get_opt.opt_arg ()); + break; + case 'n': + test_one_upcall = ACE_OS::atoi (get_opt.opt_arg ()); + break; + case 'o': + test_simple = ACE_OS::atoi (get_opt.opt_arg ()); + break; + case 'z': + debug = ACE_OS::atoi (get_opt.opt_arg ()); + break; + default: + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("\nusage: %s \n\n") + ACE_TEXT ("\t[-a heap] (defaults to %d)\n") + ACE_TEXT ("\t[-b list] (defaults to %d)\n") + ACE_TEXT ("\t[-c hash] (defaults to %d)\n") + ACE_TEXT ("\t[-d wheel] (defaults to %d)\n") + ACE_TEXT ("\t[-l test_cancellation] (defaults to %d)\n") + ACE_TEXT ("\t[-m test_expire] (defaults to %d)\n") + ACE_TEXT ("\t[-n test_one_upcall] (defaults to %d)\n") + ACE_TEXT ("\t[-o test_simple] (defaults to %d)\n") + ACE_TEXT ("\t[-z debug] (defaults to %d)\n") + ACE_TEXT ("\n"), + argv[0], + heap, + list, + hash, + wheel, + test_cancellation, + test_expire, + test_one_upcall, + test_simple, + debug)); + return -1; + } + } + + return 0; +} + +int +ACE_TMAIN (int argc, ACE_TCHAR *argv[]) +{ + ACE_START_TEST (ACE_TEXT ("Timer_Queue_Reference_Counting_Test")); + + // Validate options. + int result = + parse_args (argc, argv); + if (result != 0) + return result; + + if (test_cancellation) + { + ACE_DEBUG ((LM_DEBUG, + "\nCancellation test...\n\n")); + + if (heap) cancellation_test<ACE_Timer_Heap> timer_heap ("ACE_Timer_Heap"); + if (list) cancellation_test<ACE_Timer_List> timer_list ("ACE_Timer_List"); + if (hash) cancellation_test<ACE_Timer_Hash> timer_hash ("ACE_Timer_Hash"); + if (wheel) cancellation_test<ACE_Timer_Wheel> timer_wheel ("ACE_Timer_Wheel"); + } + + if (test_expire) + { + ACE_DEBUG ((LM_DEBUG, + "\nExpire test...\n\n")); + + if (heap) expire_test<ACE_Timer_Heap> timer_heap ("ACE_Timer_Heap"); + if (list) expire_test<ACE_Timer_List> timer_list ("ACE_Timer_List"); + if (hash) expire_test<ACE_Timer_Hash> timer_hash ("ACE_Timer_Hash"); + if (wheel) expire_test<ACE_Timer_Wheel> timer_wheel ("ACE_Timer_Wheel"); + } + + if (test_one_upcall) + { + ACE_DEBUG ((LM_DEBUG, + "\nOne upcall at a time test...\n\n")); + + if (heap) upcall_test<ACE_Timer_Heap> timer_heap ("ACE_Timer_Heap"); + if (list) upcall_test<ACE_Timer_List> timer_list ("ACE_Timer_List"); + if (hash) upcall_test<ACE_Timer_Hash> timer_hash ("ACE_Timer_Hash"); + if (wheel) upcall_test<ACE_Timer_Wheel> timer_wheel ("ACE_Timer_Wheel"); + } + + if (test_simple) + { + ACE_DEBUG ((LM_DEBUG, + "\nSimple test...\n\n")); + + if (heap) simple_test<ACE_Timer_Heap> timer_heap ("ACE_Timer_Heap"); + if (list) simple_test<ACE_Timer_List> timer_list ("ACE_Timer_List"); + if (hash) simple_test<ACE_Timer_Hash> timer_hash ("ACE_Timer_Hash"); + if (wheel) simple_test<ACE_Timer_Wheel> timer_wheel ("ACE_Timer_Wheel"); + } + + ACE_END_TEST; + + return 0; +} diff --git a/tests/Timer_Queue_Reference_Counting_Test.dsp b/tests/Timer_Queue_Reference_Counting_Test.dsp new file mode 100644 index 00000000000..9b8cdb68337 --- /dev/null +++ b/tests/Timer_Queue_Reference_Counting_Test.dsp @@ -0,0 +1,162 @@ +# Microsoft Developer Studio Project File - Name="Timer_Queue_Reference_Counting_Test" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=Timer_Queue_Reference_Counting_Test - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "Timer_Queue_Reference_Counting_Test.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "Timer_Queue_Reference_Counting_Test.mak" CFG="Timer_Queue_Reference_Counting_Test - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "Timer_Queue_Reference_Counting_Test - Win32 Static Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE "Timer_Queue_Reference_Counting_Test - Win32 Static Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "Timer_Queue_Reference_Counting_Test - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "Timer_Queue_Reference_Counting_Test - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "Timer_Queue_Reference_Counting_Test - Win32 Static Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Static_Debug"
+# PROP BASE Intermediate_Dir "Static_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Static_Debug"
+# PROP Intermediate_Dir "Static_Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "../" /D "_DEBUG" /D ACE_AS_STATIC_LIBS /D "WIN32" /D "_CONSOLE" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386
+# ADD LINK32 acesd.lib advapi32.lib user32.lib /nologo /subsystem:console /debug /machine:I386 /libpath:"..\ace"
+
+!ELSEIF "$(CFG)" == "Timer_Queue_Reference_Counting_Test - Win32 Static Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Static_Release"
+# PROP BASE Intermediate_Dir "Static_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Static_Release"
+# PROP Intermediate_Dir "Static_Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "../" /D "NDEBUG" /D ACE_AS_STATIC_LIBS /D "WIN32" /D "_CONSOLE" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 aces.lib advapi32.lib user32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\ace"
+
+!ELSEIF "$(CFG)" == "Timer_Queue_Reference_Counting_Test - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "../" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 ace.lib /nologo /subsystem:console /machine:I386 /libpath:"..\ace"
+
+!ELSEIF "$(CFG)" == "Timer_Queue_Reference_Counting_Test - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "../" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 aced.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\ace"
+
+!ENDIF
+
+# Begin Target
+
+# Name "Timer_Queue_Reference_Counting_Test - Win32 Static Debug"
+# Name "Timer_Queue_Reference_Counting_Test - Win32 Static Release"
+# Name "Timer_Queue_Reference_Counting_Test - Win32 Release"
+# Name "Timer_Queue_Reference_Counting_Test - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90"
+# Begin Source File
+
+SOURCE=.\Timer_Queue_Reference_Counting_Test.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
+# Begin Source File
+
+SOURCE=.\test_config.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/tests/WFMO_Reactor_Test.cpp b/tests/WFMO_Reactor_Test.cpp new file mode 100644 index 00000000000..6bea596a615 --- /dev/null +++ b/tests/WFMO_Reactor_Test.cpp @@ -0,0 +1,157 @@ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// tests +// +// = FILENAME +// WFMO_Reactor_Test.cpp +// +// = DESCRIPTION +// This is a simple test of the WFMO_Reactor. It makes sure that +// removals and suspensions work correctly. +// +// = AUTHOR +// Irfan Pyarali <irfan@oomworks.com> +// +// ============================================================================ + +#include "tests/test_config.h" +#include "ace/Reactor.h" +#include "ace/WFMO_Reactor.h" +#include "ace/Pipe.h" + +ACE_RCSID(tests, WFMO_Reactor_Test, "$Id$") + +#if defined (ACE_WIN32) + +static int number_of_handlers = 6; +static int number_of_closes = 0; + +class Event_Handler : public ACE_Event_Handler +{ +public: + + Event_Handler (ACE_Reactor &reactor); + + ~Event_Handler (void); + + ACE_Pipe pipe_; + +}; + +Event_Handler::Event_Handler (ACE_Reactor &reactor) +{ + this->reference_counting_policy ().value + (ACE_Event_Handler::Reference_Counting_Policy::ENABLED); + + ACE_DEBUG ((LM_DEBUG, + "Reference count in Event_Handler() is %d\n", + this->reference_count_.value ())); + + this->reactor (&reactor); + + int result = + this->pipe_.open (); + + ACE_ASSERT (result == 0); + ACE_UNUSED_ARG (result); + + this->reactor ()->register_handler (this->pipe_.read_handle (), + this, + ACE_Event_Handler::READ_MASK); + ACE_ASSERT (result == 0); + + this->reactor ()->register_handler (this->pipe_.write_handle (), + this, + ACE_Event_Handler::READ_MASK); + ACE_ASSERT (result == 0); +} + +Event_Handler::~Event_Handler (void) +{ + ACE_DEBUG ((LM_DEBUG, + "Reference count in ~Event_Handler() is %d\n", + this->reference_count_.value ())); + + ++number_of_closes; +} + +void +test (void) +{ + int result = 0; + int i = 0; + + ACE_Reactor reactor (new ACE_WFMO_Reactor, 1); + + ACE_Event_Handler_var *safe_event_handlers = + new ACE_Event_Handler_var[number_of_handlers]; + + Event_Handler **event_handlers = + new Event_Handler*[number_of_handlers]; + + for (i = 0; i < number_of_handlers; ++i) + { + event_handlers[i] = + new Event_Handler (reactor); + + safe_event_handlers[i] = + event_handlers[i]; + } + + ACE_Time_Value timeout (0, 500 * 1000); + + result = reactor.run_reactor_event_loop (timeout); + ACE_ASSERT (result != -1); + + for (i = 0; i < number_of_handlers; ++i) + { + if (i % 2 == 0) + continue; + + result = reactor.suspend_handler (event_handlers[i]->pipe_.read_handle ()); + ACE_ASSERT (result == 0); + + result = reactor.suspend_handler (event_handlers[i]->pipe_.write_handle ()); + ACE_ASSERT (result == 0); + } + + result = reactor.run_reactor_event_loop (timeout); + ACE_ASSERT (result != -1); + + delete[] safe_event_handlers; + delete[] event_handlers; +} + +int +ACE_TMAIN (int, ACE_TCHAR *[]) +{ + ACE_START_TEST (ACE_TEXT ("WFMO_Reactor_Test")); + + test (); + + ACE_ASSERT (number_of_closes == number_of_handlers); + + ACE_END_TEST; + + return 0; +} + +#else /* ACE_WIN32 */ + +int +ACE_TMAIN (int, ACE_TCHAR *[]) +{ + ACE_START_TEST (ACE_TEXT ("WFMO_Reactor_Test")); + + ACE_ERROR ((LM_INFO, + ACE_TEXT ("WFMO_Reactor not supported on this platform\n"))); + + ACE_END_TEST; + + return 0; +} + +#endif /* ACE_WIN32 */ diff --git a/tests/WFMO_Reactor_Test.dsp b/tests/WFMO_Reactor_Test.dsp new file mode 100644 index 00000000000..59c0b4aa874 --- /dev/null +++ b/tests/WFMO_Reactor_Test.dsp @@ -0,0 +1,158 @@ +# Microsoft Developer Studio Project File - Name="WFMO_Reactor_Test" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=WFMO_Reactor_Test - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "WFMO_Reactor_Test.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "WFMO_Reactor_Test.mak" CFG="WFMO_Reactor_Test - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "WFMO_Reactor_Test - Win32 Static Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE "WFMO_Reactor_Test - Win32 Static Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "WFMO_Reactor_Test - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "WFMO_Reactor_Test - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "WFMO_Reactor_Test - Win32 Static Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Static_Debug"
+# PROP BASE Intermediate_Dir "Static_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Static_Debug"
+# PROP Intermediate_Dir "Static_Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "../" /D "_DEBUG" /D ACE_AS_STATIC_LIBS /D "WIN32" /D "_CONSOLE" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386
+# ADD LINK32 acesd.lib advapi32.lib user32.lib /nologo /subsystem:console /debug /machine:I386 /libpath:"..\ace"
+
+!ELSEIF "$(CFG)" == "WFMO_Reactor_Test - Win32 Static Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Static_Release"
+# PROP BASE Intermediate_Dir "Static_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Static_Release"
+# PROP Intermediate_Dir "Static_Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "../" /D "NDEBUG" /D ACE_AS_STATIC_LIBS /D "WIN32" /D "_CONSOLE" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 aces.lib advapi32.lib user32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\ace"
+
+!ELSEIF "$(CFG)" == "WFMO_Reactor_Test - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "../" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 ace.lib /nologo /subsystem:console /machine:I386 /libpath:"..\ace"
+
+!ELSEIF "$(CFG)" == "WFMO_Reactor_Test - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "../" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 aced.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\ace"
+
+!ENDIF
+
+# Begin Target
+
+# Name "WFMO_Reactor_Test - Win32 Static Debug"
+# Name "WFMO_Reactor_Test - Win32 Static Release"
+# Name "WFMO_Reactor_Test - Win32 Release"
+# Name "WFMO_Reactor_Test - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter ".cpp"
+# Begin Source File
+
+SOURCE=.\WFMO_Reactor_Test.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter ".h"
+# Begin Source File
+
+SOURCE=.\test_config.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/tests/icc.bat b/tests/icc.bat deleted file mode 100644 index f38ce61d7b4..00000000000 --- a/tests/icc.bat +++ /dev/null @@ -1,80 +0,0 @@ -vacbld -SEV=E Aio_Platform_Test.icc -vacbld -SEV=E Atomic_Op_Test.icc -vacbld -SEV=E Barrier_Test.icc -vacbld -SEV=E Basic_Types_Test.icc -vacbld -SEV=E Buffer_Stream_Test.icc -vacbld -SEV=E CDR_Test.icc -vacbld -SEV=E CLASSIX_Addr_Test.icc -vacbld -SEV=E CLASSIX_CLD_Connector_Test.icc -vacbld -SEV=E CLASSIX_Con_Acc_Test.icc -vacbld -SEV=E CLASSIX_Group_Test.icc -vacbld -SEV=E CLASSIX_Notify_Test.icc -vacbld -SEV=E CLASSIX_OS_Test.icc -vacbld -SEV=E CLASSIX_Reactor_Test.icc -vacbld -SEV=E CLASSIX_Select_Reactor_Test.icc -vacbld -SEV=E CLASSIX_Stream_Test.icc -vacbld -SEV=E Collection_Test.icc -vacbld -SEV=E Conn_Test.icc -vacbld -SEV=E DLL_Test.icc -vacbld -SEV=E DLList_Test.icc -vacbld -SEV=E Dynamic_Priority_Test.icc -vacbld -SEV=E Enum_Interfaces_Test.icc -vacbld -SEV=E Env_Value_Test.icc -vacbld -SEV=E Future_Set_Test.icc -vacbld -SEV=E Future_Test.icc -vacbld -SEV=E Handle_Set_Test.icc -vacbld -SEV=E Hash_Map_Manager_Test.icc -vacbld -SEV=E High_Res_Timer_Test.icc -vacbld -SEV=E IOStream_Test.icc -vacbld -SEV=E MM_Shared_Memory_Test.icc -vacbld -SEV=E MT_Reactor_Timer_Test.icc -vacbld -SEV=E MT_Reactor_Upcall_Test.icc -vacbld -SEV=E MT_SOCK_Test.icc -vacbld -SEV=E Map_Manager_Test.icc -vacbld -SEV=E Map_Test.icc -vacbld -SEV=E Mem_Map_Test.icc -vacbld -SEV=E Message_Block_Test.icc -vacbld -SEV=E Message_Queue_Notifications_Test.icc -vacbld -SEV=E Message_Queue_Test.icc -vacbld -SEV=E Naming_Test.icc -vacbld -SEV=E Notify_Performance_Test.icc -vacbld -SEV=E Object_Manager_Test.icc -vacbld -SEV=E OrdMultiSet_Test.icc -vacbld -SEV=E Pipe_Test.icc -vacbld -SEV=E Priority_Buffer_Test.icc -vacbld -SEV=E Priority_Reactor_Test.icc -vacbld -SEV=E Priority_Task_Test.icc -vacbld -SEV=E Process_Mutex_Test.icc -vacbld -SEV=E Process_Strategy_Test.icc -vacbld -SEV=E RB_Tree_Test.icc -vacbld -SEV=E Reactor_Dispatch_Order_Test.icc -vacbld -SEV=E Reactor_Exceptions_Test.icc -vacbld -SEV=E Reactor_Notify_Test.icc -vacbld -SEV=E Reactor_Performance_Test.icc -vacbld -SEV=E Reactor_Timer_Test.icc -vacbld -SEV=E Reactors_Test.icc -vacbld -SEV=E Reader_Writer_Test.icc -vacbld -SEV=E Recursive_Mutex_Test.icc -vacbld -SEV=E SOCK_Connector_Test.icc -vacbld -SEV=E SOCK_Test.icc -vacbld -SEV=E SPIPE_Test.icc -vacbld -SEV=E SString_Test.icc -vacbld -SEV=E SV_Shared_Memory_Test.icc -vacbld -SEV=E Semaphore_Test.icc -vacbld -SEV=E Service_Config_Test.icc -vacbld -SEV=E Sigset_Ops_Test.icc -vacbld -SEV=E Simple_Message_Block_Test.icc -vacbld -SEV=E TSS_Test.icc -vacbld -SEV=E Task_Test.icc -vacbld -SEV=E Thread_Manager_Test.icc -vacbld -SEV=E Thread_Mutex_Test.icc -vacbld -SEV=E Thread_Pool_Reactor_Test.icc -vacbld -SEV=E Thread_Pool_Test.icc -vacbld -SEV=E Time_Service_Test.icc -vacbld -SEV=E Time_Value_Test.icc -vacbld -SEV=E Timeprobe_Test.icc -vacbld -SEV=E Timer_Queue_Test.icc -vacbld -SEV=E Tokens_Test.icc -vacbld -SEV=E UPIPE_SAP_Test.icc -vacbld -SEV=E Upgradable_RW_Test.icc -vacbld -SEV=E XtReactor_Test.icc diff --git a/tests/run_test.lst b/tests/run_test.lst index 73eacad34b7..a7ea6aa9498 100644 --- a/tests/run_test.lst +++ b/tests/run_test.lst @@ -25,13 +25,13 @@ Basic_Types_Test Bound_Ptr_Test Buffer_Stream_Test Cache_Map_Manager_Test -Cached_Conn_Test: !LynxOS !VxWorks Cached_Accept_Conn_Test: !VxWorks Cached_Allocator_Test +Cached_Conn_Test: !LynxOS !VxWorks Capabilities_Test -CDR_Test -CDR_File_Test CDR_Array_Test +CDR_File_Test +CDR_Test Codecs_Test Collection_Test Config_Test @@ -45,23 +45,24 @@ Enum_Interfaces_Test Env_Value_Test: !chorus !WinCE FIFO_Test: !Win32 Framework_Component_Test: !STATIC -Future_Test Future_Set_Test +Future_Test Get_Opt_Test Handle_Set_Test -Hash_Map_Manager_Test Hash_Map_Bucket_Iterator_Test +Hash_Map_Manager_Test High_Res_Timer_Test INET_Addr_Test IOStream_Test Lazy_Map_Manager_Test Log_Msg_Test Logging_Strategy_Test: !STATIC !ST +Malloc_Test: !VxWorks Map_Manager_Test Map_Test Max_Default_Port_Test: !ST -MEM_Stream_Test: !VxWorks Mem_Map_Test: !chorus !Unicos !VxWorks +MEM_Stream_Test: !VxWorks Message_Block_Test: !chorus Message_Queue_Notifications_Test Message_Queue_Test: !chorus @@ -69,12 +70,14 @@ Message_Queue_Test_Ex: !chorus MM_Shared_Memory_Test: !chorus !Unicos !VxWorks MT_Reactor_Timer_Test: !VxWorks MT_Reactor_Upcall_Test: !VxWorks +MT_Reference_Counted_Event_Handler_Test +MT_Reference_Counted_Notify_Test MT_SOCK_Test: !chorus -Malloc_Test: !VxWorks Multicast_Test: !ST Multihomed_INET_Addr_Test Naming_Test: OTHER !chorus !LynxOS !Unicos !VxWorks New_Fail_Test: ALL !DISABLED +NonBlocking_Conn_Test Notify_Performance_Test Object_Manager_Test Obstack_Test @@ -91,44 +94,49 @@ Process_Manager_Test: !chorus !VxWorks Process_Mutex_Test: !chorus !VxWorks Process_Strategy_Test: !chorus !LynxOS !VxWorks RB_Tree_Test -Reactors_Test +Reactor_Dispatch_Order_Test Reactor_Exceptions_Test Reactor_Notify_Test: !ST -Reactor_Dispatch_Order_Test Reactor_Performance_Test: !chorus +Reactor_Registration_Test Reactor_Timer_Test +Reactors_Test Reader_Writer_Test -Recursive_Condition_Test: !ST Recursive_Condition_Bug_Test: !ST +Recursive_Condition_Test: !ST Recursive_Mutex_Test: !ST Refcounted_Auto_Ptr_Test: !VxWorks +Reference_Counted_Event_Handler_Test Reverse_Lock_Test Semaphore_Test Service_Config_Test: !STATIC Sigset_Ops_Test Simple_Message_Block_Test: !chorus -Svc_Handler_Test -SOCK_Test: !chorus SOCK_Connector_Test SOCK_Send_Recv_Test: !LynxOS +SOCK_Test: !chorus SPIPE_Test: !VxWorks SString_Test SV_Shared_Memory_Test: !MSVC !Unicos !VxWorks !RH_7.1 +Svc_Handler_Test Task_Test Thread_Manager_Test: !Unicos Thread_Mutex_Test: !chorus -Thread_Pool_Reactor_Test: OTHER Thread_Pool_Reactor_Resume_Test: OTHER !ST +Thread_Pool_Reactor_Test: OTHER Thread_Pool_Test: !LynxOS !VxWorks -Timer_Queue_Test -Timeprobe_Test Time_Service_Test: ALL !STATIC !DISABLED !missing_netsvcs TOKEN !chorus !Unicos Time_Value_Test +Timeprobe_Test +Timer_Cancellation_Test +Timer_Queue_Reference_Counting_Test +Timer_Queue_Test Token_Strategy_Test: !ST Tokens_Test: ALL MSVC !DISABLED TOKEN !chorus !Unicos TP_Reactor_Test: ALL TSS_Test -Vector_Test Unbounded_Set_Test_Ex -UPIPE_SAP_Test: !VxWorks Upgradable_RW_Test: !chorus +UPIPE_SAP_Test: !VxWorks +Vector_Test +WFMO_Reactor_Test diff --git a/tests/run_tests.bat b/tests/run_tests.bat deleted file mode 100644 index cf51b2f4389..00000000000 --- a/tests/run_tests.bat +++ /dev/null @@ -1,223 +0,0 @@ -@echo off -rem run_tests.bat,v 4.71 1999/11/08 05:39:06 nanbor Exp - -rem -rem Note this batch file will not work on Win9X, so we suggest that -rem you install/use perl on Win9x and run the run_test.pl file. -rem - -rem To run this script, the first argument must be either bor -rem or msc. This will determine if the borland tests are run, or -rem msvc tests are run. -rem You can provide an optional second parameter, the name of -rem the test to be run. -rem An optional first argument of "purify" can be provided as well. -rem If you specify that the borland tests are to run you must also -rem specify the build configuration to be tested. There are three -rem options that may be set: DEBUG, STATIC, and PASCAL. Each is Off -rem by default. These options may be switched on by using environment -rem variables, for example: set DEBUG=1 and turned off again: -rem set DEBUG=. -rem * DEBUG - if defined means run tests built with debug info -rem * STATIC - if defined means run statically linked tests -rem * PASCAL - if defined means run the VCL-compatible runtime -rem library tests - -setlocal - -set arg= -set deco= -set exedir= -set dopure= - -set run_cmd=%0 - -if "%1" == "help" goto usage -if "%1" == "?" goto usage -if "%1" == "/?" goto usage -if "%1" == "purify" goto setuppurify -if "%1" == "bor" goto setupbor_arg -if "%1" == "msc" goto setupmsc_arg -goto setupmsc - -:setuppurify -shift -set dopure=purify -if "%1" == "bor" goto setupbor_arg -if "%1" == "msc" goto setupmsc_arg -goto setupmsc - -:setupbor_arg -shift -:setupbor -set arg=%1 - -set STATIC_DIR=Dynamic -if not "%STATIC%" == "" set STATIC_DIR=Static -set DEBUG_DIR=Release -if not "%DEBUG%" == "" set DEBUG_DIR=Debug -set PASCAL_DIR=. -if not "%PASCAL%" == "" set PASCAL_DIR=Pascal -if "%STATIC_DIR%" == "Static" goto continue_setupbor -set corebindir=%ACE_ROOT%\bin\%STATIC_DIR%\%DEBUG_DIR%\%PASCAL_DIR% -set PATH=%PATH%;%corebindir% - -:continue_setupbor -set exedir=.\%STATIC_DIR%\%DEBUG_DIR%\%PASCAL_DIR%\ - -set PATH=%PATH%;%exedir% -rem Set deco to whatever decoration you have for the executables -set deco= -set platform=bor -goto endsetup - -:setupmsc_arg -shift -:setupmsc -set arg=%1 -set exedir= -set deco= -set platform= -goto endsetup - -:usage -echo "usage: run_tests [purify] bor|msc [program-name]" -goto done - -:endsetup - -if not "%arg%" == "" goto runtest - -:runall - -if not "%platform%" == "bor" call %run_cmd% %dopure% %platform% ACE_Init_Test -call %run_cmd% %dopure% %platform% Atomic_Op_Test -call %run_cmd% %dopure% %platform% Auto_IncDec_Test -call %run_cmd% %dopure% %platform% Barrier_Test -call %run_cmd% %dopure% %platform% Basic_Types_Test -call %run_cmd% %dopure% %platform% Buffer_Stream_Test -call %run_cmd% %dopure% %platform% Cache_Map_Manager_Test -call %run_cmd% %dopure% %platform% Cached_Conn_Test -call %run_cmd% %dopure% %platform% Cached_Accept_Conn_Test -call %run_cmd% %dopure% %platform% Capabilities_Test -call %run_cmd% %dopure% %platform% CDR_Test -call %run_cmd% %dopure% %platform% CDR_File_Test -call %run_cmd% %dopure% %platform% CDR_Array_Test -call %run_cmd% %dopure% %platform% Collection_Test -call %run_cmd% %dopure% %platform% Conn_Test -call %run_cmd% %dopure% %platform% Dirent_Test -call %run_cmd% %dopure% %platform% DLL_Test -call %run_cmd% %dopure% %platform% DLList_Test -call %run_cmd% %dopure% %platform% Dynamic_Priority_Test -call %run_cmd% %dopure% %platform% Enum_Interfaces_Test -call %run_cmd% %dopure% %platform% Env_Value_Test -call %run_cmd% %dopure% %platform% Future_Test -call %run_cmd% %dopure% %platform% Future_Set_Test -call %run_cmd% %dopure% %platform% Handle_Set_Test -call %run_cmd% %dopure% %platform% Hash_Map_Manager_Test -call %run_cmd% %dopure% %platform% Hash_Map_Bucket_Iterator_Test -call %run_cmd% %dopure% %platform% High_Res_Timer_Test -call %run_cmd% %dopure% %platform% IOStream_Test -call %run_cmd% %dopure% %platform% Lazy_Map_Manager_Test -call %run_cmd% %dopure% %platform% Map_Manager_Test -call %run_cmd% %dopure% %platform% Map_Test -call %run_cmd% %dopure% %platform% Max_Default_Port_Test -call %run_cmd% %dopure% %platform% Mem_Map_Test -call %run_cmd% %dopure% %platform% MEM_Stream_Test -call %run_cmd% %dopure% %platform% Message_Block_Test -call %run_cmd% %dopure% %platform% Message_Queue_Notifications_Test -call %run_cmd% %dopure% %platform% Message_Queue_Test -call %run_cmd% %dopure% %platform% MM_Shared_Memory_Test -call %run_cmd% %dopure% %platform% MT_Reactor_Timer_Test -call %run_cmd% %dopure% %platform% MT_Reactor_Upcall_Test -call %run_cmd% %dopure% %platform% MT_SOCK_Test -call %run_cmd% %dopure% %platform% Malloc_Test -call %run_cmd% %dopure% %platform% Multihomed_INET_Addr_Test -call %run_cmd% %dopure% %platform% Naming_Test -rem call %run_cmd% %dopure% %platform% New_Fail_Test -call %run_cmd% %dopure% %platform% Notify_Performance_Test -call %run_cmd% %dopure% %platform% Object_Manager_Test -call %run_cmd% %dopure% %platform% OrdMultiSet_Test -call %run_cmd% %dopure% %platform% Pipe_Test -call %run_cmd% %dopure% %platform% Priority_Buffer_Test -call %run_cmd% %dopure% %platform% Priority_Reactor_Test -call %run_cmd% %dopure% %platform% Priority_Task_Test -call %run_cmd% %dopure% %platform% Process_Manager_Test -call %run_cmd% %dopure% %platform% Process_Mutex_Test -call %run_cmd% %dopure% %platform% Process_Strategy_Test -call %run_cmd% %dopure% %platform% RB_Tree_Test -call %run_cmd% %dopure% %platform% Reactors_Test -call %run_cmd% %dopure% %platform% Reactor_Exceptions_Test -call %run_cmd% %dopure% %platform% Reactor_Notify_Test -call %run_cmd% %dopure% %platform% Reactor_Dispatch_Order_Test -call %run_cmd% %dopure% %platform% Reactor_Performance_Test -call %run_cmd% %dopure% %platform% Reactor_Timer_Test -call %run_cmd% %dopure% %platform% Reader_Writer_Test -call %run_cmd% %dopure% %platform% Recursive_Mutex_Test -call %run_cmd% %dopure% %platform% Reverse_Lock_Test -call %run_cmd% %dopure% %platform% Semaphore_Test -call %run_cmd% %dopure% %platform% Service_Config_Test -call %run_cmd% %dopure% %platform% Sigset_Ops_Test -call %run_cmd% %dopure% %platform% Simple_Message_Block_Test -call %run_cmd% %dopure% %platform% Svc_Handler_Test -call %run_cmd% %dopure% %platform% SOCK_Test -call %run_cmd% %dopure% %platform% SOCK_Connector_Test -call %run_cmd% %dopure% %platform% SOCK_Send_Recv_Test -call %run_cmd% %dopure% %platform% SPIPE_Test -call %run_cmd% %dopure% %platform% SString_Test -call %run_cmd% %dopure% %platform% SV_Shared_Memory_Test -call %run_cmd% %dopure% %platform% Task_Test -call %run_cmd% %dopure% %platform% Thread_Manager_Test -call %run_cmd% %dopure% %platform% Thread_Mutex_Test -call %run_cmd% %dopure% %platform% Thread_Pool_Reactor_Test -call %run_cmd% %dopure% %platform% Thread_Pool_Test -call %run_cmd% %dopure% %platform% Timer_Queue_Test -call %run_cmd% %dopure% %platform% Timeprobe_Test -if exist ..\netsvcs\servers\main.exe call %run_cmd% %dopure% %platform% Time_Service_Test -call %run_cmd% %dopure% %platform% Time_Value_Test -call %run_cmd% %dopure% %platform% Tokens_Test -call %run_cmd% %dopure% %platform% TSS_Test -call %run_cmd% %dopure% %platform% UPIPE_SAP_Test -call %run_cmd% %dopure% %platform% Upgradable_RW_Test - -goto done - -:runtest - -if not "%dopure%"=="purify" goto justrun - -if not exist purify_results mkdir purify_results - -echo Purifying %arg% -purify /run /save-data=purify_results\%arg%.pfy /save-text-data=purify_results\%arg%.txt /AllocCallStackLength=20 /ErrorCallStackLength=20 /HandlesInUseAtExit /InUseAtExit /LeaksAtExit %arg%.exe - -goto done - -:justrun - -set exefile=%exedir%%arg%%deco% -echo Running %exefile% -if not exist %exefile%.exe goto nofile - -%exefile%.exe -if errorlevel 0 goto fine -echo. -echo %exefile% has FAILED!!! -echo. -type log\%arg%.log | find /I "LM_ERROR" -echo. - -goto done - -:nofile -echo %exefile%.exe not found -goto done - -:fine - -rem We should check the log files here to make sure the test ended correctly -rem type log\%arg%.log | find "Ending" - -:done - -endlocal diff --git a/tests/run_tests.psosim b/tests/run_tests.psosim deleted file mode 100755 index 33a7ce59fce..00000000000 --- a/tests/run_tests.psosim +++ /dev/null @@ -1,200 +0,0 @@ -#!/bin/sh -f -# $Id$ -# -# This is the UNIX version of the one-button ACE tests. -# Contributed by Michael Rueger <m_rueger@SYSCOMP.DE> - -IFS="|" -tmp=/tmp - -run() -{ - echo running $1 - /bin/rm -f core log/$1.log - - ./$1 - status=$? - - if [ $status -ne 0 ]; then - echo \"$1\" FAILED with exit status $status!!!! - fi - - if [ -f core ]; then - echo \"$1\" dumped core!!!! - fi - - if [ -f log/$1.log ]; then - ./run_tests.check log/$1.log - else - echo "No log file (log/$1.log) is present" - fi -} - -echo "Starting tests..." - -run Basic_Types_Test - -run DLList_Test - -#Atomic_Op_Test: threads not supported on this platform -#run Atomic_Op_Test # uses Atomic_Op - -run Object_Manager_Test - -#TSS_Test: threads are not supported on this platform -#run TSS_Test # uses Task, Mutex, Guard - -run Time_Value_Test -run High_Res_Timer_Test -run SString_Test -run Collection_Test - -# SYS V IPC not supported -#run Naming_Test # uses Naming_Context, WString - -run Handle_Set_Test # uses Handle_Set - -run OrdMultiSet_Test - -#Mem_Map_Test: mmap: Operation not applicable -#run Mem_Map_Test # uses Mem_Map - -run MEM_Stream_Test - -#SV_Shared_Memory_Test: SYSV IPC is not supported on this platform -#run SV_Shared_Memory_Test # uses SV_Shared_Memory, fork - -#MM_Shared_Memory_Test: requires either fork or threads -#run MM_Shared_Memory_Test - -run Sigset_Ops_Test # uses sigset*() functions - -run Timer_Queue_Test # uses Event_Handler, Timer_Queue - -run SOCK_Connector_Test # uses SOCK_Connector - -#Task_Test: threads not supported on this platform -#run Task_Test # uses Thread_Manager, Task - -#Thread_Manager_Test: threads not supported on this platform -#run Thread_Manager_Test # uses Thread_Manager, Task - -#Thread_Pool_Test: threads not supported on this platform -#run Thread_Pool_Test # uses Thread_Manager, Task - -#Future_Test: threads not supported on this platform -#run Future_Test # uses Thread_Manager, Task - -#Future_Set_Test: threads not supported on this platform -#run Future_Set_Test # uses Thread_Manager, Task - -#Reactors_Test: threads not supported on this platform -#run Reactors_Test # uses Task, Mutex, Reactor - -#Reactor_Exceptions_Test: not correctly implemented without threads -#run Reactor_Exceptions_Test # uses Reactor and C++ exceptions - -#Reactor_Notify_Test: threads not supported on this platform -#run Reactor_Notify_Test # uses Reactor's notify() method, Task - -run Reactor_Timer_Test # uses Event_Handler, Reactor - -run Reactor_Dispatch_Order_Test # uses Event_Handler, Reactor - -#Reactor_Performance_Test: threads not supported on this platform -#run Reactor_Performance_Test # uses Event_Handler, Reactor - -#Notify_Performance_Test: threads not supported on this platform -#run Notify_Performance_Test # uses Event_Handler, Reactor - -#Reader_Writer_Test: threads not supported on this platform -#run Reader_Writer_Test # uses Thread_Manager, Mutex - -run Priority_Reactor_Test # uses Priority_Reactor, Acceptor/Connector... -run SOCK_Test # uses Thread_Manager, SOCK_SAP -run MT_SOCK_Test # uses Thread_Manager, Acceptor/Connector - -# ifdef ACE_HAS_STREAM_PIPES -#SPIPE_Test: SPIPE is not supported on this platform -#run SPIPE_Test # uses SPIPE_Acceptor/Connector, Thread_Manager - -#UPIPE_SAP_Test: threads not supported on this platform -#run UPIPE_SAP_Test # uses UPIPE, Thread, Thread_Manager - -#Barrier_Test: threads not supported on this platform -#run Barrier_Test # uses Service_Config, Barrier - -#run CDR_Test - -#Buffer_Stream_Test: threads not supported on this platform -#run Buffer_Stream_Test # uses Service_Config, Module (Stream,Task, Message_Queue) - -#Priority_Buffer_Test: threads not supported on this platform -#run Priority_Buffer_Test # uses Service_Config, Message_Queue - -run Recursive_Mutex_Test # uses Service_Config, Recursive_Thread_Mutex - -run Reverse_Lock_Test # uses ACE_Reverse_Lock - -#Time_Service_Test: uses fork -#run Time_Service_Test # uses libnetsvcs - -#Tokens_Test: threads not supported on this platform -#run Tokens_Test - -run Map_Manager_Test # uses Map Manager and Hash Map Manager + Forward and Reverse Map Iterators. - -run Hash_Map_Manager_Test # uses Hash Map Manager + Forward and Reverse Map Iterators. - -run Lazy_Map_Manager_Test # uses Lazy Map Manager + Forward and Reverse Map Iterators. - -run Hash_Map_Bucket_Iterator_Test # uses Hash Map Bucket iterator. - -run Cache_Map_Manager_Test # uses Cache Map Manager and Hash Cache Map Manager + Forward and Reverse Map Iterators. - -run Cached_Conn_Test # uses Cached connection management (with OneShot Acceptor). - -run Cached_Accept_Conn_Test # uses Cached connection management (with regular Acceptor). - -run Map_Test # uses Map + Forward and Reverse Map Iterators. - -#Message_Queue_Notifications_Test.cpp: threads not supported on this platform -#run Message_Queue_Notifications_Test.cpp # uses Message_Queue + Reactor. - -run Message_Queue_Test # uses Message_Queue + Forward and Reverse Message Queue Iterators. -run Simple_Message_Block_Test # uses Message_Block - -#Message_Block_Test: threads not supported on this platform -#run Message_Block_Test # uses Message_Block and Message_Queue - -#Pipe_Test: uses fork -#run Pipe_Test # uses Pipe - -#Process_Mutex_Test: uses fork -#run Process_Mutex_Test # uses Process_Mutex - -#Thread_Mutex_Test: threads not supported on this platform -#run Thread_Mutex_Test # uses Thread_Process_Mutex - -run Process_Strategy_Test # uses ACE_Strategy_Acceptor -run Service_Config_Test # uses Service_Config - -#Priority_Task_Test: threads not supported on this platform -#run Priority_Task_Test # uses Task with priorities - -run IOStream_Test # uses ACE_IOStream and ACE_SOCK_Stream -run Enum_Interfaces_Test # uses ACE::get_ip_interfaces() - -run Conn_Test # uses Thread_Manager, Acceptor/Connector, SOCK_SAP - -run Upgradable_RW_Test # uses RW locks - -run Svc_Handler_Test - -echo "Tests complete..." - -/bin/rm -f ace_pipe_name pattern $tmp/ace_temp_file $tmp/ace_temp_file2 $tmp/ace_test_file $tmp/Naming_Test* -echo; echo -ipcs - -# EOF diff --git a/tests/tests.dsw b/tests/tests.dsw index 620dd60b946..fcd02406a80 100644 --- a/tests/tests.dsw +++ b/tests/tests.dsw @@ -3,7 +3,7 @@ Microsoft Developer Studio Workspace File, Format Version 6.00 ###############################################################################
-Project: "ACE_Init_Test"=".\ACE_Init_Test.dsp" - Package Owner=<4>
+Project: "ACE_Init_Test"=.\ACE_Init_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -15,7 +15,7 @@ Package=<4> ###############################################################################
-Project: "ACE_Test"=".\ACE_Test.dsp" - Package Owner=<4>
+Project: "ACE_Test"=.\ACE_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -27,7 +27,7 @@ Package=<4> ###############################################################################
-Project: "ARGV_Test"=".\ARGV_Test.dsp" - Package Owner=<4>
+Project: "ARGV_Test"=.\ARGV_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -39,7 +39,7 @@ Package=<4> ###############################################################################
-Project: "Arg_Shifter_Test"=".\Arg_Shifter_Test.dsp" - Package Owner=<4>
+Project: "Arg_Shifter_Test"=.\Arg_Shifter_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -51,7 +51,7 @@ Package=<4> ###############################################################################
-Project: "Atomic_Op_Test"=".\Atomic_Op_Test.dsp" - Package Owner=<4>
+Project: "Atomic_Op_Test"=.\Atomic_Op_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -63,7 +63,7 @@ Package=<4> ###############################################################################
-Project: "Auto_IncDec_Test"=".\Auto_IncDec_Test.dsp" - Package Owner=<4>
+Project: "Auto_IncDec_Test"=.\Auto_IncDec_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -75,7 +75,7 @@ Package=<4> ###############################################################################
-Project: "Barrier_Test"=".\Barrier_Test.dsp" - Package Owner=<4>
+Project: "Barrier_Test"=.\Barrier_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -87,7 +87,7 @@ Package=<4> ###############################################################################
-Project: "Basic_Types_Test"=".\Basic_Types_Test.dsp" - Package Owner=<4>
+Project: "Basic_Types_Test"=.\Basic_Types_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -99,7 +99,7 @@ Package=<4> ###############################################################################
-Project: "Bound_Ptr_Test"=".\Bound_Ptr_Test.dsp" - Package Owner=<4>
+Project: "Bound_Ptr_Test"=.\Bound_Ptr_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -111,7 +111,7 @@ Package=<4> ###############################################################################
-Project: "Buffer_Stream_Test"=".\Buffer_Stream_Test.dsp" - Package Owner=<4>
+Project: "Buffer_Stream_Test"=.\Buffer_Stream_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -123,7 +123,7 @@ Package=<4> ###############################################################################
-Project: "CDR_Array_Test"=".\CDR_Array_Test.dsp" - Package Owner=<4>
+Project: "CDR_Array_Test"=.\CDR_Array_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -135,7 +135,7 @@ Package=<4> ###############################################################################
-Project: "CDR_File_Test"=".\CDR_File_Test.dsp" - Package Owner=<4>
+Project: "CDR_File_Test"=.\CDR_File_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -147,7 +147,7 @@ Package=<4> ###############################################################################
-Project: "CDR_Test"=".\CDR_Test.dsp" - Package Owner=<4>
+Project: "CDR_Test"=.\CDR_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -159,7 +159,7 @@ Package=<4> ###############################################################################
-Project: "Cache_Map_Manager_Test"=".\Cache_Map_Manager_Test.dsp" - Package Owner=<4>
+Project: "Cache_Map_Manager_Test"=.\Cache_Map_Manager_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -171,7 +171,7 @@ Package=<4> ###############################################################################
-Project: "Cached_Accept_Conn_Test"=".\Cached_Accept_Conn_Test.dsp" - Package Owner=<4>
+Project: "Cached_Accept_Conn_Test"=.\Cached_Accept_Conn_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -183,7 +183,7 @@ Package=<4> ###############################################################################
-Project: "Cached_Allocator_Test"=".\Cached_Allocator_Test.dsp" - Package Owner=<4>
+Project: "Cached_Allocator_Test"=.\Cached_Allocator_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -195,7 +195,7 @@ Package=<4> ###############################################################################
-Project: "Cached_Conn_Test"=".\Cached_Conn_Test.dsp" - Package Owner=<4>
+Project: "Cached_Conn_Test"=.\Cached_Conn_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -207,7 +207,7 @@ Package=<4> ###############################################################################
-Project: "Capabilities_Test"=".\Capabilities_Test.dsp" - Package Owner=<4>
+Project: "Capabilities_Test"=.\Capabilities_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -219,7 +219,7 @@ Package=<4> ###############################################################################
-Project: "Codecs_Test"=".\Codecs_Test.dsp" - Package Owner=<4>
+Project: "Codecs_Test"=.\Codecs_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -231,7 +231,7 @@ Package=<4> ###############################################################################
-Project: "Collection_Test"=".\Collection_Test.dsp" - Package Owner=<4>
+Project: "Collection_Test"=.\Collection_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -243,7 +243,7 @@ Package=<4> ###############################################################################
-Project: "Config_Test"=".\Config_Test.dsp" - Package Owner=<4>
+Project: "Config_Test"=.\Config_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -255,7 +255,7 @@ Package=<4> ###############################################################################
-Project: "Conn_Test"=".\Conn_Test.dsp" - Package Owner=<4>
+Project: "Conn_Test"=.\Conn_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -267,7 +267,7 @@ Package=<4> ###############################################################################
-Project: "DLL_Test"=".\DLL_Test.dsp" - Package Owner=<4>
+Project: "DLL_Test"=.\DLL_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -282,7 +282,7 @@ Package=<4> ###############################################################################
-Project: "DLL_Test DLL"=".\DLL_Test_Impl.dsp" - Package Owner=<4>
+Project: "DLL_Test DLL"=.\DLL_Test_Impl.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -294,7 +294,7 @@ Package=<4> ###############################################################################
-Project: "DLList_Test"=".\DLList_Test.dsp" - Package Owner=<4>
+Project: "DLList_Test"=.\DLList_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -306,7 +306,7 @@ Package=<4> ###############################################################################
-Project: "Date_Time_Test"=".\Date_Time_Test.dsp" - Package Owner=<4>
+Project: "Date_Time_Test"=.\Date_Time_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -318,7 +318,7 @@ Package=<4> ###############################################################################
-Project: "Dirent_Test"=".\Dirent_Test.dsp" - Package Owner=<4>
+Project: "Dirent_Test"=.\Dirent_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -330,7 +330,7 @@ Package=<4> ###############################################################################
-Project: "Dynamic_Priority_Test"=".\Dynamic_Priority_Test.dsp" - Package Owner=<4>
+Project: "Dynamic_Priority_Test"=.\Dynamic_Priority_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -342,7 +342,7 @@ Package=<4> ###############################################################################
-Project: "Enum_Interfaces_Test"=".\Enum_Interfaces_Test.dsp" - Package Owner=<4>
+Project: "Enum_Interfaces_Test"=.\Enum_Interfaces_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -354,7 +354,7 @@ Package=<4> ###############################################################################
-Project: "Env_Value_Test"=".\Env_Value_Test.dsp" - Package Owner=<4>
+Project: "Env_Value_Test"=.\Env_Value_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -366,7 +366,7 @@ Package=<4> ###############################################################################
-Project: "Framework_Component_Test"=".\Framework_Component_Test.dsp" - Package Owner=<4>
+Project: "Framework_Component_Test"=.\Framework_Component_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -381,7 +381,7 @@ Package=<4> ###############################################################################
-Project: "Framework_Component_Test DLL"=".\Framework_Component_DLL.dsp" - Package Owner=<4>
+Project: "Framework_Component_Test DLL"=.\Framework_Component_DLL.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -393,7 +393,7 @@ Package=<4> ###############################################################################
-Project: "Future_Set_Test"=".\Future_Set_Test.dsp" - Package Owner=<4>
+Project: "Future_Set_Test"=.\Future_Set_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -405,7 +405,7 @@ Package=<4> ###############################################################################
-Project: "Future_Test"=".\Future_Test.dsp" - Package Owner=<4>
+Project: "Future_Test"=.\Future_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -417,7 +417,7 @@ Package=<4> ###############################################################################
-Project: "Get_Opt_Test"=".\Get_Opt_Test.dsp" - Package Owner=<4>
+Project: "Get_Opt_Test"=.\Get_Opt_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -429,7 +429,7 @@ Package=<4> ###############################################################################
-Project: "Handle_Set_Test"=".\Handle_Set_Test.dsp" - Package Owner=<4>
+Project: "Handle_Set_Test"=.\Handle_Set_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -441,7 +441,7 @@ Package=<4> ###############################################################################
-Project: "Hash_Map_Bucket_Iterator_Test"=".\Hash_Map_Bucket_Iterator_Test.dsp" - Package Owner=<4>
+Project: "Hash_Map_Bucket_Iterator_Test"=.\Hash_Map_Bucket_Iterator_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -453,7 +453,7 @@ Package=<4> ###############################################################################
-Project: "Hash_Map_Manager_Test"=".\Hash_Map_Manager_Test.dsp" - Package Owner=<4>
+Project: "Hash_Map_Manager_Test"=.\Hash_Map_Manager_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -465,7 +465,7 @@ Package=<4> ###############################################################################
-Project: "High_Res_Timer_Test"=".\High_Res_Timer_Test.dsp" - Package Owner=<4>
+Project: "High_Res_Timer_Test"=.\High_Res_Timer_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -477,7 +477,7 @@ Package=<4> ###############################################################################
-Project: "INET_Addr_Test"=".\INET_Addr_Test.dsp" - Package Owner=<4>
+Project: "INET_Addr_Test"=.\INET_Addr_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -489,7 +489,7 @@ Package=<4> ###############################################################################
-Project: "IOStream_Test"=".\IOStream_Test.dsp" - Package Owner=<4>
+Project: "IOStream_Test"=.\IOStream_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -501,7 +501,7 @@ Package=<4> ###############################################################################
-Project: "Lazy_Map_Manager_Test"=".\Lazy_Map_Manager_Test.dsp" - Package Owner=<4>
+Project: "Lazy_Map_Manager_Test"=.\Lazy_Map_Manager_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -513,7 +513,7 @@ Package=<4> ###############################################################################
-Project: "Log_Msg_Test"=".\Log_Msg_Test.dsp" - Package Owner=<4>
+Project: "Log_Msg_Test"=.\Log_Msg_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -525,7 +525,7 @@ Package=<4> ###############################################################################
-Project: "Logging_Strategy_Test"=".\Logging_Strategy_Test.dsp" - Package Owner=<4>
+Project: "Logging_Strategy_Test"=.\Logging_Strategy_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -537,7 +537,7 @@ Package=<4> ###############################################################################
-Project: "MEM_Stream_Test"=".\MEM_Stream_Test.dsp" - Package Owner=<4>
+Project: "MEM_Stream_Test"=.\MEM_Stream_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -549,7 +549,7 @@ Package=<4> ###############################################################################
-Project: "MM_Shared_Memory_Test"=".\MM_Shared_Memory_Test.dsp" - Package Owner=<4>
+Project: "MM_Shared_Memory_Test"=.\MM_Shared_Memory_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -561,7 +561,7 @@ Package=<4> ###############################################################################
-Project: "MT_Reactor_Timer_Test"=".\MT_Reactor_Timer_Test.dsp" - Package Owner=<4>
+Project: "MT_Reactor_Timer_Test"=.\MT_Reactor_Timer_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -573,7 +573,7 @@ Package=<4> ###############################################################################
-Project: "MT_Reactor_Upcall_Test"=".\MT_Reactor_Upcall_Test.dsp" - Package Owner=<4>
+Project: "MT_Reactor_Upcall_Test"=.\MT_Reactor_Upcall_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -585,7 +585,7 @@ Package=<4> ###############################################################################
-Project: "MT_SOCK_Test"=".\MT_SOCK_Test.dsp" - Package Owner=<4>
+Project: "MT_Reference_Counted_Event_Handler_Test"=.\MT_Reference_Counted_Event_Handler_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -597,7 +597,7 @@ Package=<4> ###############################################################################
-Project: "Malloc_Test"=".\Malloc_Test.dsp" - Package Owner=<4>
+Project: "MT_Reference_Counted_Notify_Test"=.\MT_Reference_Counted_Notify_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -609,7 +609,7 @@ Package=<4> ###############################################################################
-Project: "Map_Manager_Test"=".\Map_Manager_Test.dsp" - Package Owner=<4>
+Project: "MT_SOCK_Test"=.\MT_SOCK_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -621,7 +621,7 @@ Package=<4> ###############################################################################
-Project: "Map_Test"=".\Map_Test.dsp" - Package Owner=<4>
+Project: "Malloc_Test"=.\Malloc_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -633,7 +633,7 @@ Package=<4> ###############################################################################
-Project: "Max_Default_Port_Test"=".\Max_Default_Port_Test.dsp" - Package Owner=<4>
+Project: "Map_Manager_Test"=.\Map_Manager_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -645,7 +645,7 @@ Package=<4> ###############################################################################
-Project: "Mem_Map_Test"=".\Mem_Map_Test.dsp" - Package Owner=<4>
+Project: "Map_Test"=.\Map_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -657,7 +657,7 @@ Package=<4> ###############################################################################
-Project: "Message_Block_Test"=".\Message_Block_Test.dsp" - Package Owner=<4>
+Project: "Max_Default_Port_Test"=.\Max_Default_Port_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -669,7 +669,7 @@ Package=<4> ###############################################################################
-Project: "Message_Queue_Notifications_Test"=".\Message_Queue_Notifications_Test.dsp" - Package Owner=<4>
+Project: "Mem_Map_Test"=.\Mem_Map_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -681,7 +681,7 @@ Package=<4> ###############################################################################
-Project: "Message_Queue_Test"=".\Message_Queue_Test.dsp" - Package Owner=<4>
+Project: "Message_Block_Test"=.\Message_Block_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -693,7 +693,7 @@ Package=<4> ###############################################################################
-Project: "Multicast_Test"=".\Multicast_Test.dsp" - Package Owner=<4>
+Project: "Message_Queue_Notifications_Test"=.\Message_Queue_Notifications_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -705,7 +705,7 @@ Package=<4> ###############################################################################
-Project: "Multihomed_INET_Addr_Test"=".\Multihomed_INET_Addr_Test.dsp" - Package Owner=<4>
+Project: "Message_Queue_Test"=.\Message_Queue_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -717,7 +717,7 @@ Package=<4> ###############################################################################
-Project: "Message_Queue_Test_Ex"=".\Message_Queue_Test_Ex.dsp" - Package Owner=<4>
+Project: "Message_Queue_Test_Ex"=.\Message_Queue_Test_Ex.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -729,7 +729,7 @@ Package=<4> ###############################################################################
-Project: "Naming_Test"=".\Naming_Test.dsp" - Package Owner=<4>
+Project: "Multicast_Test"=.\Multicast_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -741,7 +741,7 @@ Package=<4> ###############################################################################
-Project: "New_Fail_Test"=".\New_Fail_Test.dsp" - Package Owner=<4>
+Project: "Multihomed_INET_Addr_Test"=.\Multihomed_INET_Addr_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -753,7 +753,7 @@ Package=<4> ###############################################################################
-Project: "Notify_Performance_Test"=".\Notify_Performance_Test.dsp" - Package Owner=<4>
+Project: "Naming_Test"=.\Naming_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -765,7 +765,7 @@ Package=<4> ###############################################################################
-Project: "OS_Test"=".\OS_Test.dsp" - Package Owner=<4>
+Project: "New_Fail_Test"=.\New_Fail_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -777,7 +777,7 @@ Package=<4> ###############################################################################
-Project: "Object_Manager_Test"=".\Object_Manager_Test.dsp" - Package Owner=<4>
+Project: "NonBlocking_Conn_Test"=.\NonBlocking_Conn_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -789,7 +789,7 @@ Package=<4> ###############################################################################
-Project: "Obstack_Test"=".\Obstack_Test.dsp" - Package Owner=<4>
+Project: "Notify_Performance_Test"=.\Notify_Performance_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -801,7 +801,7 @@ Package=<4> ###############################################################################
-Project: "OrdMultiSet_Test"=".\OrdMultiSet_Test.dsp" - Package Owner=<4>
+Project: "OS_Test"=.\OS_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -813,7 +813,7 @@ Package=<4> ###############################################################################
-Project: "Pipe_Test"=".\Pipe_Test.dsp" - Package Owner=<4>
+Project: "Object_Manager_Test"=.\Object_Manager_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -825,7 +825,7 @@ Package=<4> ###############################################################################
-Project: "Priority_Buffer_Test"=".\Priority_Buffer_Test.dsp" - Package Owner=<4>
+Project: "Obstack_Test"=.\Obstack_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -837,7 +837,7 @@ Package=<4> ###############################################################################
-Project: "Priority_Reactor_Test"=".\Priority_Reactor_Test.dsp" - Package Owner=<4>
+Project: "OrdMultiSet_Test"=.\OrdMultiSet_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -849,7 +849,7 @@ Package=<4> ###############################################################################
-Project: "Priority_Task_Test"=".\Priority_Task_Test.dsp" - Package Owner=<4>
+Project: "Pipe_Test"=.\Pipe_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -861,7 +861,7 @@ Package=<4> ###############################################################################
-Project: "Proactor_Scatter_Gather_Test"=".\Proactor_Scatter_Gather_Test.dsp" - Package Owner=<4>
+Project: "Priority_Buffer_Test"=.\Priority_Buffer_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -873,7 +873,7 @@ Package=<4> ###############################################################################
-Project: "Proactor_Test"=".\Proactor_Test.dsp" - Package Owner=<4>
+Project: "Priority_Reactor_Test"=.\Priority_Reactor_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -885,7 +885,7 @@ Package=<4> ###############################################################################
-Project: "Proactor_Timer_Test"=".\Proactor_Timer_Test.dsp" - Package Owner=<4>
+Project: "Priority_Task_Test"=.\Priority_Task_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -897,7 +897,7 @@ Package=<4> ###############################################################################
-Project: "Process_Manager_Test"=".\Process_Manager_Test.dsp" - Package Owner=<4>
+Project: "Proactor_Scatter_Gather_Test"=.\Proactor_Scatter_Gather_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -909,7 +909,7 @@ Package=<4> ###############################################################################
-Project: "Process_Mutex_Test"=".\Process_Mutex_Test.dsp" - Package Owner=<4>
+Project: "Proactor_Test"=.\Proactor_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -921,7 +921,7 @@ Package=<4> ###############################################################################
-Project: "Process_Strategy_Test"=".\Process_Strategy_Test.dsp" - Package Owner=<4>
+Project: "Proactor_Timer_Test"=.\Proactor_Timer_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -933,7 +933,7 @@ Package=<4> ###############################################################################
-Project: "RB_Tree_Test"=".\RB_Tree_Test.dsp" - Package Owner=<4>
+Project: "Process_Manager_Test"=.\Process_Manager_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -945,7 +945,7 @@ Package=<4> ###############################################################################
-Project: "Reactor_Dispatch_Order_Test"=".\Reactor_Dispatch_Order_Test.dsp" - Package Owner=<4>
+Project: "Process_Mutex_Test"=.\Process_Mutex_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -957,7 +957,7 @@ Package=<4> ###############################################################################
-Project: "Reactor_Exceptions_Test"=".\Reactor_Exceptions_Test.dsp" - Package Owner=<4>
+Project: "Process_Strategy_Test"=.\Process_Strategy_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -969,7 +969,7 @@ Package=<4> ###############################################################################
-Project: "Reactor_Notify_Test"=".\Reactor_Notify_Test.dsp" - Package Owner=<4>
+Project: "RB_Tree_Test"=.\RB_Tree_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -981,7 +981,7 @@ Package=<4> ###############################################################################
-Project: "Reactor_Performance_Test"=".\Reactor_Performance_Test.dsp" - Package Owner=<4>
+Project: "Reactor_Dispatch_Order_Test"=.\Reactor_Dispatch_Order_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -993,7 +993,7 @@ Package=<4> ###############################################################################
-Project: "Reactor_Timer_Test"=".\Reactor_Timer_Test.dsp" - Package Owner=<4>
+Project: "Reactor_Exceptions_Test"=.\Reactor_Exceptions_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -1005,7 +1005,7 @@ Package=<4> ###############################################################################
-Project: "Reactors_Test"=".\Reactors_Test.dsp" - Package Owner=<4>
+Project: "Reactor_Notify_Test"=.\Reactor_Notify_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -1017,7 +1017,7 @@ Package=<4> ###############################################################################
-Project: "Reader_Writer_Test"=".\Reader_Writer_Test.dsp" - Package Owner=<4>
+Project: "Reactor_Performance_Test"=.\Reactor_Performance_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -1029,7 +1029,7 @@ Package=<4> ###############################################################################
-Project: "Recursive_Condition_Test"=".\Recursive_Condition_Test.dsp" - Package Owner=<4>
+Project: "Reactor_Registration_Test"=.\Reactor_Registration_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -1041,7 +1041,7 @@ Package=<4> ###############################################################################
-Project: "Recursive_Condition_Bug_Test"=".\Recursive_Condition_Bug_Test.dsp" - Package Owner=<4>
+Project: "Reactor_Timer_Test"=.\Reactor_Timer_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -1053,7 +1053,7 @@ Package=<4> ###############################################################################
-Project: "Recursive_Mutex_Test"=".\Recursive_Mutex_Test.dsp" - Package Owner=<4>
+Project: "Reactors_Test"=.\Reactors_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -1065,7 +1065,7 @@ Package=<4> ###############################################################################
-Project: "Refcounted_Auto_Ptr_Test"=".\Refcounted_Auto_Ptr_Test.dsp" - Package Owner=<4>
+Project: "Reader_Writer_Test"=.\Reader_Writer_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -1077,7 +1077,7 @@ Package=<4> ###############################################################################
-Project: "Reverse_Lock_Test"=".\Reverse_Lock_Test.dsp" - Package Owner=<4>
+Project: "Recursive_Condition_Bug_Test"=.\Recursive_Condition_Bug_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -1089,7 +1089,7 @@ Package=<4> ###############################################################################
-Project: "SOCK_Connector_Test"=".\SOCK_Connector_Test.dsp" - Package Owner=<4>
+Project: "Recursive_Condition_Test"=.\Recursive_Condition_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -1101,7 +1101,7 @@ Package=<4> ###############################################################################
-Project: "SOCK_Send_Recv_Test"=".\SOCK_Send_Recv_Test.dsp" - Package Owner=<4>
+Project: "Recursive_Mutex_Test"=.\Recursive_Mutex_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -1113,7 +1113,7 @@ Package=<4> ###############################################################################
-Project: "SOCK_SEQPACK_Association_Test"=".\SOCK_SEQPACK_Association_Test.dsp" - Package Owner=<4>
+Project: "Refcounted_Auto_Ptr_Test"=.\Refcounted_Auto_Ptr_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -1125,7 +1125,7 @@ Package=<4> ###############################################################################
-Project: "SOCK_Test"=".\SOCK_Test.dsp" - Package Owner=<4>
+Project: "Reference_Counted_Event_Handler_Test"=.\Reference_Counted_Event_Handler_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -1137,7 +1137,7 @@ Package=<4> ###############################################################################
-Project: "SPIPE_Test"=".\SPIPE_Test.dsp" - Package Owner=<4>
+Project: "Reverse_Lock_Test"=.\Reverse_Lock_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -1149,7 +1149,7 @@ Package=<4> ###############################################################################
-Project: "SString_Test"=".\SString_Test.dsp" - Package Owner=<4>
+Project: "SOCK_Connector_Test"=.\SOCK_Connector_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -1161,7 +1161,7 @@ Package=<4> ###############################################################################
-Project: "SV_Shared_Memory_Test"=".\SV_Shared_Memory_Test.dsp" - Package Owner=<4>
+Project: "SOCK_SEQPACK_Association_Test"=.\SOCK_SEQPACK_Association_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -1173,7 +1173,7 @@ Package=<4> ###############################################################################
-Project: "Semaphore_Test"=".\Semaphore_Test.dsp" - Package Owner=<4>
+Project: "SOCK_Send_Recv_Test"=.\SOCK_Send_Recv_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -1185,7 +1185,7 @@ Package=<4> ###############################################################################
-Project: "Service_Config_DLL"=".\Service_Config_DLL.dsp" - Package Owner=<4>
+Project: "SOCK_Test"=.\SOCK_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -1197,7 +1197,67 @@ Package=<4> ###############################################################################
-Project: "Service_Config_Test"=".\Service_Config_Test.dsp" - Package Owner=<4>
+Project: "SPIPE_Test"=.\SPIPE_Test.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "SString_Test"=.\SString_Test.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "SV_Shared_Memory_Test"=.\SV_Shared_Memory_Test.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "Semaphore_Test"=.\Semaphore_Test.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "Service_Config_DLL"=.\Service_Config_DLL.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "Service_Config_Test"=.\Service_Config_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -1212,7 +1272,43 @@ Package=<4> ###############################################################################
-Project: "Sigset_Ops_Test"=".\Sigset_Ops_Test.dsp" - Package Owner=<4>
+Project: "Sigset_Ops_Test"=.\Sigset_Ops_Test.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "Simple_Message_Block_Test"=.\Simple_Message_Block_Test.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "Svc_Handler_Test"=.\Svc_Handler_Test.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "TP_Reactor_Test"=.\TP_Reactor_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -1224,7 +1320,7 @@ Package=<4> ###############################################################################
-Project: "Simple_Message_Block_Test"=".\Simple_Message_Block_Test.dsp" - Package Owner=<4>
+Project: "TSS_Test"=.\TSS_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -1236,7 +1332,7 @@ Package=<4> ###############################################################################
-Project: "Svc_Handler_Test"=".\Svc_Handler_Test.dsp" - Package Owner=<4>
+Project: "Task_Test"=.\Task_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -1248,7 +1344,7 @@ Package=<4> ###############################################################################
-Project: "TP_Reactor_Test"=".\TP_Reactor_Test.dsp" - Package Owner=<4>
+Project: "Thread_Manager_Test"=.\Thread_Manager_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -1260,7 +1356,7 @@ Package=<4> ###############################################################################
-Project: "TSS_Test"=".\TSS_Test.dsp" - Package Owner=<4>
+Project: "Thread_Mutex_Test"=.\Thread_Mutex_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -1272,7 +1368,7 @@ Package=<4> ###############################################################################
-Project: "Task_Test"=".\Task_Test.dsp" - Package Owner=<4>
+Project: "Thread_Pool_Reactor_Resume_Test"=.\Thread_Pool_Reactor_Resume_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -1284,7 +1380,7 @@ Package=<4> ###############################################################################
-Project: "Thread_Mutex_Test"=".\Thread_Mutex_Test.dsp" - Package Owner=<4>
+Project: "Thread_Pool_Reactor_Test"=.\Thread_Pool_Reactor_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -1296,7 +1392,7 @@ Package=<4> ###############################################################################
-Project: "Thread_Manager_Test"=".\Thread_Manager_Test.dsp" - Package Owner=<4>
+Project: "Thread_Pool_Test"=.\Thread_Pool_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -1308,7 +1404,7 @@ Package=<4> ###############################################################################
-Project: "Thread_Pool_Reactor_Resume_Test"=".\Thread_Pool_Reactor_Resume_Test.dsp" - Package Owner=<4>
+Project: "Time_Service_Test"=.\Time_Service_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -1320,7 +1416,7 @@ Package=<4> ###############################################################################
-Project: "Thread_Pool_Reactor_Test"=".\Thread_Pool_Reactor_Test.dsp" - Package Owner=<4>
+Project: "Time_Value_Test"=.\Time_Value_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -1332,7 +1428,7 @@ Package=<4> ###############################################################################
-Project: "Thread_Pool_Test"=".\Thread_Pool_Test.dsp" - Package Owner=<4>
+Project: "Timeprobe_Test"=.\Timeprobe_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -1344,7 +1440,7 @@ Package=<4> ###############################################################################
-Project: "Time_Service_Test"=".\Time_Service_Test.dsp" - Package Owner=<4>
+Project: "Timer_Cancellation_Test"=.\Timer_Cancellation_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -1356,7 +1452,7 @@ Package=<4> ###############################################################################
-Project: "Time_Value_Test"=".\Time_Value_Test.dsp" - Package Owner=<4>
+Project: "Timer_Queue_Reference_Counting_Test"=.\Timer_Queue_Reference_Counting_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -1368,7 +1464,7 @@ Package=<4> ###############################################################################
-Project: "Timeprobe_Test"=".\Timeprobe_Test.dsp" - Package Owner=<4>
+Project: "Timer_Queue_Test"=.\Timer_Queue_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -1380,7 +1476,7 @@ Package=<4> ###############################################################################
-Project: "Timer_Queue_Test"=".\Timer_Queue_Test.dsp" - Package Owner=<4>
+Project: "Token_Strategy_Test"=.\Token_Strategy_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -1392,7 +1488,7 @@ Package=<4> ###############################################################################
-Project: "Token_Strategy_Test"=".\Token_Strategy_Test.dsp" - Package Owner=<4>
+Project: "Tokens_Test"=.\Tokens_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -1404,7 +1500,7 @@ Package=<4> ###############################################################################
-Project: "Tokens_Test"=".\Tokens_Test.dsp" - Package Owner=<4>
+Project: "UPIPE_SAP_Test"=.\UPIPE_SAP_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -1416,7 +1512,7 @@ Package=<4> ###############################################################################
-Project: "UPIPE_SAP_Test"=".\UPIPE_SAP_Test.dsp" - Package Owner=<4>
+Project: "Unbounded_Set_Test_Ex"=.\Unbounded_Set_Test_Ex.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -1428,7 +1524,7 @@ Package=<4> ###############################################################################
-Project: "Unbounded_Set_Test_Ex"=".\Unbounded_Set_Test_Ex.dsp" - Package Owner=<4>
+Project: "Upgradable_RW_Test"=.\Upgradable_RW_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -1440,7 +1536,7 @@ Package=<4> ###############################################################################
-Project: "Upgradable_RW_Test"=".\Upgradable_RW_Test.dsp" - Package Owner=<4>
+Project: "Vector_Test"=.\Vector_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -1452,7 +1548,7 @@ Package=<4> ###############################################################################
-Project: "Vector_Test"=".\Vector_Test.dsp" - Package Owner=<4>
+Project: "WFMO_Reactor_Test"=.\WFMO_Reactor_Test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -1475,3 +1571,4 @@ Package=<3> }}}
###############################################################################
+
diff --git a/tests/tests.icp b/tests/tests.icp index 9d592631c25..1c72f37e61f 100644 --- a/tests/tests.icp +++ b/tests/tests.icp @@ -2,15 +2,15 @@ // // Visual Age C++ 5 Project file for building all the tests. -subproject Arg_Shifter_Test icc "Arg_Shifter_Test.icc", ics "Arg_Shifter_Test.ics" +subproject Aio_Platform_Test icc "Aio_Platform_Test.icc", ics "Aio_Platform_Test.ics" { } -subproject ARGV_Test icc "ARGV_Test.icc", ics "ARGV_Test.ics" +subproject Arg_Shifter_Test icc "Arg_Shifter_Test.icc", ics "Arg_Shifter_Test.ics" { } -subproject Aio_Platform_Test icc "Aio_Platform_Test.icc", ics "Aio_Platform_Test.ics" +subproject ARGV_Test icc "ARGV_Test.icc", ics "ARGV_Test.ics" { } @@ -38,31 +38,31 @@ subproject Buffer_Stream_Test icc "Buffer_Stream_Test.icc", ics "Buffer_Stream_T { } -subproject CDR_Array_Test icc "CDR_Array_Test.icc", ics "CDR_Array_Test.ics" +subproject Cache_Map_Manager_Test icc "Cache_Map_Manager_Test.icc", ics "Cache_Map_Manager_Test.ics" { } -subproject CDR_File_Test icc "CDR_File_Test.icc", ics "CDR_File_Test.ics" +subproject Cached_Accept_Conn_Test icc "Cached_Accept_Conn_Test.icc", ics "Cached_Accept_Conn_Test.ics" { } -subproject CDR_Test icc "CDR_Test.icc", ics "CDR_Test.ics" +subproject Cached_Conn_Test icc "Cached_Conn_Test.icc", ics "Cached_Conn_Test.ics" { } -subproject Cache_Map_Manager_Test icc "Cache_Map_Manager_Test.icc", ics "Cache_Map_Manager_Test.ics" +subproject Capabilities_Test icc "Capabilities_Test.icc", ics "Capabilities_Test.ics" { } -subproject Cached_Accept_Conn_Test icc "Cached_Accept_Conn_Test.icc", ics "Cached_Accept_Conn_Test.ics" +subproject CDR_Array_Test icc "CDR_Array_Test.icc", ics "CDR_Array_Test.ics" { } -subproject Cached_Conn_Test icc "Cached_Conn_Test.icc", ics "Cached_Conn_Test.ics" +subproject CDR_File_Test icc "CDR_File_Test.icc", ics "CDR_File_Test.ics" { } -subproject Capabilities_Test icc "Capabilities_Test.icc", ics "Capabilities_Test.ics" +subproject CDR_Test icc "CDR_Test.icc", ics "CDR_Test.ics" { } @@ -82,11 +82,11 @@ subproject Date_Time_Test icc "Date_Time_Test.icc", ics "Date_Time_Test.ics" { } -subproject DLL_Test icc "DLL_Test.icc", ics "DLL_Test.ics" +subproject Dirent_Test icc "Dirent_Test.icc", ics "Dirent_Test.ics" { } -subproject libDLL_Test icc "libDLL_Test.icc", ics "libDLL_Test.ics" +subproject DLL_Test icc "DLL_Test.icc", ics "DLL_Test.ics" { } @@ -94,10 +94,6 @@ subproject DLList_Test icc "DLList_Test.icc", ics "DLList_Test.ics" { } -subproject Dirent_Test icc "Dirent_Test.icc", ics "Dirent_Test.ics" -{ -} - subproject Dynamic_Priority_Test icc "Dynamic_Priority_Test.icc", ics "Dynamic_Priority_Test.ics" { } @@ -158,6 +154,14 @@ subproject Lazy_Map_Manager_Test icc "Lazy_Map_Manager_Test.icc", ics "Lazy_Map_ { } +subproject libDLL_Test icc "libDLL_Test.icc", ics "libDLL_Test.ics" +{ +} + +subproject libService_Config_DLL icc "libService_Config_DLL.icc", ics "libService_Config_DLL.ics" +{ +} + subproject Log_Msg_Test icc "Log_Msg_Test.icc", ics "Log_Msg_Test.ics" { } @@ -166,59 +170,67 @@ subproject Logging_Strategy_Test icc "Logging_Strategy_Test.icc", ics "Logging_S { } -subproject MEM_Stream_Test icc "MEM_Stream_Test.icc", ics "MEM_Stream_Test.ics" +subproject Malloc_Test icc "Malloc_Test.icc", ics "Malloc_Test.ics" { } -subproject MM_Shared_Memory_Test icc "MM_Shared_Memory_Test.icc", ics "MM_Shared_Memory_Test.ics" +subproject Map_Manager_Test icc "Map_Manager_Test.icc", ics "Map_Manager_Test.ics" { } -subproject MT_Reactor_Timer_Test icc "MT_Reactor_Timer_Test.icc", ics "MT_Reactor_Timer_Test.ics" +subproject Map_Test icc "Map_Test.icc", ics "Map_Test.ics" { } -subproject MT_Reactor_Upcall_Test icc "MT_Reactor_Upcall_Test.icc", ics "MT_Reactor_Upcall_Test.ics" +subproject Max_Default_Port_Test icc "Max_Default_Port_Test.icc", ics "Max_Default_Port_Test.ics" { } -subproject MT_SOCK_Test icc "MT_SOCK_Test.icc", ics "MT_SOCK_Test.ics" +subproject Mem_Map_Test icc "Mem_Map_Test.icc", ics "Mem_Map_Test.ics" { } -subproject Malloc_Test icc "Malloc_Test.icc", ics "Malloc_Test.ics" +subproject MEM_Stream_Test icc "MEM_Stream_Test.icc", ics "MEM_Stream_Test.ics" { } -subproject Map_Manager_Test icc "Map_Manager_Test.icc", ics "Map_Manager_Test.ics" +subproject Message_Block_Test icc "Message_Block_Test.icc", ics "Message_Block_Test.ics" { } -subproject Map_Test icc "Map_Test.icc", ics "Map_Test.ics" +subproject Message_Queue_Notifications_Test icc "Message_Queue_Notifications_Test.icc", ics "Message_Queue_Notifications_Test.ics" { } -subproject Max_Default_Port_Test icc "Max_Default_Port_Test.icc", ics "Max_Default_Port_Test.ics" +subproject Message_Queue_Test icc "Message_Queue_Test.icc", ics "Message_Queue_Test.ics" { } -subproject Mem_Map_Test icc "Mem_Map_Test.icc", ics "Mem_Map_Test.ics" +subproject Message_Queue_Test_Ex icc "Message_Queue_Test_Ex.icc", ics "Message_Queue_Test_Ex.ics" { } -subproject Message_Block_Test icc "Message_Block_Test.icc", ics "Message_Block_Test.ics" +subproject MM_Shared_Memory_Test icc "MM_Shared_Memory_Test.icc", ics "MM_Shared_Memory_Test.ics" { } -subproject Message_Queue_Notifications_Test icc "Message_Queue_Notifications_Test.icc", ics "Message_Queue_Notifications_Test.ics" +subproject MT_Reactor_Timer_Test icc "MT_Reactor_Timer_Test.icc", ics "MT_Reactor_Timer_Test.ics" { } -subproject Message_Queue_Test icc "Message_Queue_Test.icc", ics "Message_Queue_Test.ics" +subproject MT_Reactor_Upcall_Test icc "MT_Reactor_Upcall_Test.icc", ics "MT_Reactor_Upcall_Test.ics" { } -subproject Message_Queue_Test_Ex icc "Message_Queue_Test_Ex.icc", ics "Message_Queue_Test_Ex.ics" +subproject MT_Reference_Counted_Event_Handler_Test icc "MT_Reference_Counted_Event_Handler_Test.icc", ics "MT_Reference_Counted_Event_Handler_Test.ics" +{ +} + +subproject MT_Reference_Counted_Notify_Test icc "MT_Reference_Counted_Nofity_Test.icc", ics "MT_Reference_Counted_Notify_Test.ics" +{ +} + +subproject MT_SOCK_Test icc "MT_SOCK_Test.icc", ics "MT_SOCK_Test.ics" { } @@ -234,11 +246,11 @@ subproject New_Fail_Test icc "New_Fail_Test.icc", ics "New_Fail_Test.ics" { } -subproject Notify_Performance_Test icc "Notify_Performance_Test.icc", ics "Notify_Performance_Test.ics" +subproject NonBlocking_Conn_Test icc "NonBlocking_Conn_Test.icc", ics "NonBlocking_Conn_Test.ics" { } -subproject OS_Test icc "OS_Test.icc", ics "OS_Test.ics" +subproject Notify_Performance_Test icc "Notify_Performance_Test.icc", ics "Notify_Performance_Test.ics" { } @@ -254,6 +266,10 @@ subproject OrdMultiSet_Test icc "OrdMultiSet_Test.icc", ics "OrdMultiSet_Test.ic { } +subproject OS_Test icc "OS_Test.icc", ics "OS_Test.ics" +{ +} + subproject Pipe_Test icc "Pipe_Test.icc", ics "Pipe_Test.ics" { } @@ -286,6 +302,10 @@ subproject RB_Tree_Test icc "RB_Tree_Test.icc", ics "RB_Tree_Test.ics" { } +subproject Reactor_Dispatch_Order_Test icc "Reactor_Dispatch_Order_Test.icc", ics "Reactor_Dispatch_Order_Test.ics" +{ +} + subproject Reactor_Exceptions_Test icc "Reactor_Exceptions_Test.icc", ics "Reactor_Exceptions_Test.ics" { } @@ -294,11 +314,11 @@ subproject Reactor_Notify_Test icc "Reactor_Notify_Test.icc", ics "Reactor_Notif { } -subproject Reactor_Dispatch_Order_Test icc "Reactor_Dispatch_Order_Test.icc", ics "Reactor_Dispatch_Order_Test.ics" +subproject Reactor_Performance_Test icc "Reactor_Performance_Test.icc", ics "Reactor_Performance_Test.ics" { } -subproject Reactor_Performance_Test icc "Reactor_Performance_Test.icc", ics "Reactor_Performance_Test.ics" +subproject Reactor_Registration_Test icc "Reactor_Registration_Test.icc", ics "Reactor_Registration_Test.ics" { } @@ -326,59 +346,59 @@ subproject Refcounted_Auto_Ptr_Test icc "Refcounted_Auto_Ptr_Test.icc", ics "Ref { } -subproject Reverse_Lock_Test icc "Reverse_Lock_Test.icc", ics "Reverse_Lock_Test.ics" +subproject Reference_Counted_Event_Handler_Test icc "Reference_Counted_Event_Handler_Test.icc", ics "Reference_Counted_Event_Handler_Test.ics" { } -subproject Service_Config_Test icc "Service_Config_Test.icc", ics "Service_Config_Test.ics" +subproject Reverse_Lock_Test icc "Reverse_Lock_Test.icc", ics "Reverse_Lock_Test.ics" { } -subproject libService_Config_DLL icc "libService_Config_DLL.icc", ics "libService_Config_DLL.ics" +subproject Semaphore_Test icc "Semaphore_Test.icc", ics "Semaphore_Test.ics" { } -subproject SOCK_Connector_Test icc "SOCK_Connector_Test.icc", ics "SOCK_Connector_Test.ics" +subproject Service_Config_Test icc "Service_Config_Test.icc", ics "Service_Config_Test.ics" { } -subproject SOCK_Send_Recv_Test icc "SOCK_Send_Recv_Test.icc", ics "SOCK_Send_Recv_Test.ics" +subproject Service_Config_Test icc "Service_Config_Test.icc", ics "Service_Config_Test.ics" { } -subproject SOCK_Test icc "SOCK_Test.icc", ics "SOCK_Test.ics" +subproject Signal_Test icc "Signal_Test.icc", ics "Signal_Test.ics" { } -subproject SPIPE_Test icc "SPIPE_Test.icc", ics "SPIPE_Test.ics" +subproject Sigset_Ops_Test icc "Sigset_Ops_Test.icc", ics "Sigset_Ops_Test.ics" { } -subproject SString_Test icc "SString_Test.icc", ics "SString_Test.ics" +subproject Simple_Message_Block_Test icc "Simple_Message_Block_Test.icc", ics "Simple_Message_Block_Test.ics" { } -subproject SV_Shared_Memory_Test icc "SV_Shared_Memory_Test.icc", ics "SV_Shared_Memory_Test.ics" +subproject SOCK_Connector_Test icc "SOCK_Connector_Test.icc", ics "SOCK_Connector_Test.ics" { } -subproject Semaphore_Test icc "Semaphore_Test.icc", ics "Semaphore_Test.ics" +subproject SOCK_Send_Recv_Test icc "SOCK_Send_Recv_Test.icc", ics "SOCK_Send_Recv_Test.ics" { } -subproject Service_Config_Test icc "Service_Config_Test.icc", ics "Service_Config_Test.ics" +subproject SOCK_Test icc "SOCK_Test.icc", ics "SOCK_Test.ics" { } -subproject Signal_Test icc "Signal_Test.icc", ics "Signal_Test.ics" +subproject SPIPE_Test icc "SPIPE_Test.icc", ics "SPIPE_Test.ics" { } -subproject Sigset_Ops_Test icc "Sigset_Ops_Test.icc", ics "Sigset_Ops_Test.ics" +subproject SString_Test icc "SString_Test.icc", ics "SString_Test.ics" { } -subproject Simple_Message_Block_Test icc "Simple_Message_Block_Test.icc", ics "Simple_Message_Block_Test.ics" +subproject SV_Shared_Memory_Test icc "SV_Shared_Memory_Test.icc", ics "SV_Shared_Memory_Test.ics" { } @@ -386,10 +406,6 @@ subproject Svc_Handler_Test icc "Svc_Handler_Test.icc", ics "Svc_Handler_Test.ic { } -subproject TSS_Test icc "TSS_Test.icc", ics "TSS_Test.ics" -{ -} - subproject Task_Test icc "Task_Test.icc", ics "Task_Test.ics" { } @@ -402,11 +418,11 @@ subproject Thread_Mutex_Test icc "Thread_Mutex_Test.icc", ics "Thread_Mutex_Test { } -subproject Thread_Pool_Reactor_Test icc "Thread_Pool_Reactor_Test.icc", ics "Thread_Pool_Reactor_Test.ics" +subproject Thread_Pool_Reactor_Resume_Test icc "Thread_Pool_Reactor_Resume_Test.icc", ics "Thread_Pool_Reactor_Resume_Test.ics" { } -subproject Thread_Pool_Reactor_Resume_Test icc "Thread_Pool_Reactor_Resume_Test.icc", ics "Thread_Pool_Reactor_Resume_Test.ics" +subproject Thread_Pool_Reactor_Test icc "Thread_Pool_Reactor_Test.icc", ics "Thread_Pool_Reactor_Test.ics" { } @@ -426,6 +442,14 @@ subproject Timeprobe_Test icc "Timeprobe_Test.icc", ics "Timeprobe_Test.ics" { } +subproject Timer_Cancellation_Test icc "Timer_Cancellation_Test.icc", ics "Timer_Cancellation_Test.ics" +{ +} + +subproject Timer_Queue_Reference_Counting_Test icc "Timer_Queue_Reference_Counting_Test.icc", ics "Timer_Queue_Reference_Counting_Test.ics" +{ +} + subproject Timer_Queue_Test icc "Timer_Queue_Test.icc", ics "Timer_Queue_Test.ics" { } @@ -438,7 +462,7 @@ subproject Tokens_Test icc "Tokens_Test.icc", ics "Tokens_Test.ics" { } -subproject UPIPE_SAP_Test icc "UPIPE_SAP_Test.icc", ics "UPIPE_SAP_Test.ics" +subproject TSS_Test icc "TSS_Test.icc", ics "TSS_Test.ics" { } @@ -450,10 +474,18 @@ subproject Upgradable_RW_Test icc "Upgradable_RW_Test.icc", ics "Upgradable_RW_T { } +subproject UPIPE_SAP_Test icc "UPIPE_SAP_Test.icc", ics "UPIPE_SAP_Test.ics" +{ +} + subproject Vector_Test icc "Vector_Test.icc", ics "Vector_Test.ics" { } +subproject WFMO_Reactor_Test icc "WFMO_Reactor_Test.icc", ics "WFMO_Reactor_Test.ics" +{ +} + subproject XtReactor_Test icc "XtReactor_Test.icc", ics "XtReactor_Test.ics" { } @@ -461,27 +493,26 @@ subproject XtReactor_Test icc "XtReactor_Test.icc", ics "XtReactor_Test.ics" build all { -use ARGV_Test use Aio_Platform_Test +use ARGV_Test use Atomic_Op_Test use Auto_IncDec_Test use Barrier_Test use Basic_Types_Test use Buffer_Stream_Test -use CDR_Array_Test -use CDR_File_Test -use CDR_Test use Cache_Map_Manager_Test use Cached_Accept_Conn_Test use Cached_Conn_Test use Capabilities_Test +use CDR_Array_Test +use CDR_File_Test +use CDR_Test use Collection_Test use Config_Test use Conn_Test +use Dirent_Test use DLL_Test -use libDLL_Test use DLList_Test -use Dirent_Test use Dynamic_Priority_Test use Enum_Interfaces_Test use Env_Value_Test @@ -495,27 +526,31 @@ use Hash_Map_Manager_Test use High_Res_Timer_Test use IOStream_Test use Lazy_Map_Manager_Test +use libDLL_Test use Log_Msg_Test use Logging_Strategy_Test -use MEM_Stream_Test -use MM_Shared_Memory_Test -use MT_Reactor_Timer_Test -use MT_Reactor_Upcall_Test -use MT_SOCK_Test use Malloc_Test use Map_Manager_Test use Map_Test use Mem_Map_Test +use MEM_Stream_Test use Message_Block_Test use Message_Queue_Notifications_Test use Message_Queue_Test use Message_Queue_Test_Ex +use MM_Shared_Memory_Test +use MT_Reactor_Timer_Test +use MT_Reactor_Upcall_Test +use MT_Reference_Counted_Event_Handler_Test +use MT_Reference_Counted_Notify_Test +use MT_SOCK_Test use Naming_Test use New_Fail_Test +use NonBlocking_Conn_Test use Notify_Performance_Test -use OS_Test use Object_Manager_Test use OrdMultiSet_Test +use OS_Test use Pipe_Test use Priority_Buffer_Test use Priority_Reactor_Test @@ -524,29 +559,30 @@ use Process_Manager_Test use Process_Mutex_Test use Process_Strategy_Test use RB_Tree_Test +use Reactor_Dispatch_Order_Test use Reactor_Exceptions_Test use Reactor_Notify_Test -use Reactor_Dispatch_Order_Test use Reactor_Performance_Test +use Reactor_Registration_Test use Reactor_Timer_Test use Reactors_Test use Reader_Writer_Test use Recursive_Mutex_Test use Refcounted_Auto_Ptr_Test +use Reference_Counted_Event_Handler_Test use Reverse_Lock_Test +use Semaphore_Test +use Service_Config_Test +use Signal_Test +use Sigset_Ops_Test +use Simple_Message_Block_Test use SOCK_Connector_Test use SOCK_Send_Recv_Test use SOCK_Test use SPIPE_Test use SString_Test use SV_Shared_Memory_Test -use Semaphore_Test -use Service_Config_Test -use Signal_Test -use Sigset_Ops_Test -use Simple_Message_Block_Test use Svc_Handler_Test -use TSS_Test use Task_Test use Thread_Manager_Test use Thread_Mutex_Test @@ -555,12 +591,16 @@ use Thread_Pool_Test use Time_Service_Test use Time_Value_Test use Timeprobe_Test +use Timer_Cancellation_Test +use Timer_Queue_Reference_Counting_Test use Timer_Queue_Test use TkReactor_Test use Tokens_Test -use UPIPE_SAP_Test +use TSS_Test use Unbounded_Set_Test_Ex use Upgradable_RW_Test +use UPIPE_SAP_Test use Vector_Test +use WFMO_Reactor_Test use XtReactor_Test } diff --git a/tests/tests.mpc b/tests/tests.mpc index 54c4fdcb69c..d8417252c46 100644 --- a/tests/tests.mpc +++ b/tests/tests.mpc @@ -1158,3 +1158,75 @@ project(Unbounded Set Ex Test) : aceexe { Header_Files { } } + +project(WFMO Reactor Test) : aceexe { + exename = WFMO_Reactor_Test + Source_Files { + WFMO_Reactor_Test.cpp + } + Header_Files { + } +} + +project(NonBlocking Conn Test) : aceexe { + exename = NonBlocking_Conn_Test + Source_Files { + NonBlocking_Conn_Test.cpp + } + Header_Files { + } +} + +project(Reference Counted Event Handler Test) : aceexe { + exename = Reference_Counted_Event_Handler_Test + Source_Files { + Reference_Counted_Event_Handler_Test.cpp + } + Header_Files { + } +} + +project(MT Reference Counted Event Handler Test) : aceexe { + exename = MT_Reference_Counted_Event_Handler_Test + Source_Files { + MT_Reference_Counted_Event_Handler_Test.cpp + } + Header_Files { + } +} + +project(MT Reference Counted Notify Test) : aceexe { + exename = MT_Reference_Counted_Notify_Test + Source_Files { + MT_Reference_Counted_Notify_Test.cpp + } + Header_Files { + } +} + +project(Timer Cancellation Test) : aceexe { + exename = Timer_Cancellation_Test + Source_Files { + Timer_Cancellation_Test.cpp + } + Header_Files { + } +} + +project(Timer Queue Reference Counting Test) : aceexe { + exename = Timer_Queue_Reference_Counting_Test + Source_Files { + Timer_Queue_Reference_Counting_Test.cpp + } + Header_Files { + } +} + +project(Reactor Registration Test) : aceexe { + exename = Reactor_Registration_Test + Source_Files { + Reactor_Registration_Test.cpp + } + Header_Files { + } +} |