diff options
author | schmidt <douglascraigschmidt@users.noreply.github.com> | 1998-05-02 21:06:34 +0000 |
---|---|---|
committer | schmidt <douglascraigschmidt@users.noreply.github.com> | 1998-05-02 21:06:34 +0000 |
commit | b74bafd352dd39e23cebb872edfe695f26b1d654 (patch) | |
tree | 9caa429c55ba240d9efe6e546abe4ac3272c1bfe | |
parent | 4572a838719f9f085942fda9ce4a574408c6e3c1 (diff) | |
download | ATCD-b74bafd352dd39e23cebb872edfe695f26b1d654.tar.gz |
*** empty log message ***
-rw-r--r-- | ChangeLog-98a | 27 | ||||
-rw-r--r-- | ace/Reactor.h | 17 | ||||
-rw-r--r-- | ace/Reactor_Impl.h | 3 | ||||
-rw-r--r-- | ace/Select_Reactor.cpp | 118 | ||||
-rw-r--r-- | ace/Select_Reactor.h | 21 | ||||
-rw-r--r-- | ace/WFMO_Reactor.h | 3 | ||||
-rw-r--r-- | tests/Reactor_Notify_Test.cpp | 141 |
7 files changed, 214 insertions, 116 deletions
diff --git a/ChangeLog-98a b/ChangeLog-98a index 3caabc3671b..e1bd13435d8 100644 --- a/ChangeLog-98a +++ b/ChangeLog-98a @@ -1,7 +1,22 @@ +Sat May 2 14:35:04 1998 Douglas C. Schmidt <schmidt@flamenco.cs.wustl.edu> + + * tests/Reactor_Notify_Test.cpp: Factored out some common code to + make the test more concise. + + * tests/Reactor_Notify_Test.cpp: Modified the test to check + whether our new mechanism for disabling the notify pipe works + correctly. + + * ace/{WFMO,Select}_Reactor[_Impl]: Added the + "disable_notify_pipe" flag in the constructor in order to + disable this feature and save on descriptors if they aren't + required. Thanks to Tom Venturella <tventurell@mdc.com> for + motivating this. + Sat May 02 Alexander Babu Arulanthu <alex@merengue.cs.wustl.edu> * tests/Aio_Platform_Test.cpp: Included this test program for - testing a platform for Asynchronous I/O options. + testing an OS platform for Asynchronous I/O options. Fri May 01 17:52:32 1998 Nanbor Wang <nanbor@cs.wustl.edu> @@ -2358,11 +2373,11 @@ Sun Mar 01 08:38:00 1998 David L. Levine <levine@cs.wustl.edu> Sat Feb 28 12:20:57 1998 Douglas C. Schmidt <schmidt@flamenco.cs.wustl.edu> * ace/Message_Queue.cpp: Fixed the implementation of - wait_not_{full,empty}_cond() so that they utilize the - ACE_Time_Value it's passed. In addition, revised the - implementation of peek_dequeue_head() so that it uses the new - wait_not_empty_cond() implementation. Thanks to Thanks to Tom - Venturella <tventurell@mdc.com> for reporting this. + wait_not_{full,empty}_cond() so that they utilize the + ACE_Time_Value it's passed. In addition, revised the + implementation of peek_dequeue_head() so that it uses the new + wait_not_empty_cond() implementation. Thanks to Tom Venturella + <tventurell@mdc.com> for reporting this. Fri Feb 27 15:47:15 1998 David L. Levine <levine@cs.wustl.edu> diff --git a/ace/Reactor.h b/ace/Reactor.h index fc7133d290e..6f2aaf982e5 100644 --- a/ace/Reactor.h +++ b/ace/Reactor.h @@ -46,13 +46,16 @@ public: { // = Operations on the "ready" mask and the "dispatch" mask. GET_MASK = 1, - // Retrieve current value of the the "ready" mask or the "dispatch" mask. + // Retrieve current value of the the "ready" mask or the + // "dispatch" mask. SET_MASK = 2, // Set value of bits to new mask (changes the entire mask). ADD_MASK = 3, - // Bitwise "or" the value into the mask (only changes enabled bits). + // Bitwise "or" the value into the mask (only changes enabled + // bits). CLR_MASK = 4 - // Bitwise "and" the negation of the value out of the mask (only changes enabled bits). + // Bitwise "and" the negation of the value out of the mask (only + // changes enabled bits). }; static ACE_Reactor *instance (void); @@ -74,10 +77,10 @@ public: static int run_event_loop (ACE_Time_Value &tv); static int run_alertable_event_loop (ACE_Time_Value &tv); - // Run the event loop until the - // <ACE_Reactor::handle_events/ACE_Reactor::alertable_handle_events> - // returns -1, the <end_event_loop> method is invoked, or the - // <ACE_Time_Value> expires. + // Run the event loop until the <ACE_Reactor::handle_events> or + // <ACE_Reactor::alertable_handle_events> methods returns -1, the + // <end_event_loop> method is invoked, or the <ACE_Time_Value> + // expires. static int end_event_loop (void); // Instruct the <ACE_Reactor::instance> to terminate its event loop diff --git a/ace/Reactor_Impl.h b/ace/Reactor_Impl.h index f9ee3799041..31c106efda6 100644 --- a/ace/Reactor_Impl.h +++ b/ace/Reactor_Impl.h @@ -42,7 +42,8 @@ public: virtual int open (size_t size, int restart = 0, ACE_Sig_Handler * = 0, - ACE_Timer_Queue * = 0) = 0; + ACE_Timer_Queue * = 0, + int disable_notify_pipe = 0) = 0; // Initialization. virtual int set_sig_handler (ACE_Sig_Handler *signal_handler) = 0; diff --git a/ace/Select_Reactor.cpp b/ace/Select_Reactor.cpp index da95e2db279..91321a4f48f 100644 --- a/ace/Select_Reactor.cpp +++ b/ace/Select_Reactor.cpp @@ -639,25 +639,34 @@ ACE_Select_Reactor_Notify::dump (void) const } int -ACE_Select_Reactor_Notify::open (ACE_Select_Reactor *r) +ACE_Select_Reactor_Notify::open (ACE_Select_Reactor *r, + int disable_notify_pipe) { ACE_TRACE ("ACE_Select_Reactor_Notify::open"); - this->select_reactor_ = r; + if (disable_notify_pipe == 0) + { + this->select_reactor_ = r; - if (this->notification_pipe_.open () == -1) - return -1; + if (this->notification_pipe_.open () == -1) + return -1; - // There seems to be a Win32 bug with this... Set this into - // non-blocking mode. - if (ACE::set_flags (this->notification_pipe_.read_handle (), - ACE_NONBLOCK) == -1) - return -1; + // There seems to be a Win32 bug with this... Set this into + // non-blocking mode. + if (ACE::set_flags (this->notification_pipe_.read_handle (), + ACE_NONBLOCK) == -1) + return -1; + else + return this->select_reactor_->register_handler + (this->notification_pipe_.read_handle (), + this, + ACE_Event_Handler::READ_MASK); + } else - return this->select_reactor_->register_handler - (this->notification_pipe_.read_handle (), - this, - ACE_Event_Handler::READ_MASK); + { + this->select_reactor_ = 0; + return 0; + } } int @@ -674,13 +683,23 @@ ACE_Select_Reactor_Notify::notify (ACE_Event_Handler *eh, { ACE_TRACE ("ACE_Select_Reactor_Notify::notify"); - ACE_Notification_Buffer buffer (eh, mask); + // Just consider this method a "no-op" if there's no + // <ACE_Select_Reactor> configured. + if (this->select_reactor_ == 0) + return 0; + else + { + ACE_Notification_Buffer buffer (eh, mask); - ssize_t n = ACE::send (this->notification_pipe_.write_handle (), - (char *) &buffer, - sizeof buffer, - timeout); - return n == -1 ? -1 : 0; + ssize_t n = ACE::send (this->notification_pipe_.write_handle (), + (char *) &buffer, + sizeof buffer, + timeout); + if (n == -1) + return -1; + else + return 0; + } } // Handles pending threads (if any) that are waiting to unblock the @@ -695,7 +714,8 @@ ACE_Select_Reactor_Notify::dispatch_notifications (int &number_of_active_handles ACE_HANDLE read_handle = this->notification_pipe_.read_handle (); - if (rd_mask.is_set (read_handle)) + if (read_handle != ACE_INVALID_HANDLE + && rd_mask.is_set (read_handle)) { number_of_active_handles--; return this->handle_input (read_handle); @@ -704,10 +724,10 @@ ACE_Select_Reactor_Notify::dispatch_notifications (int &number_of_active_handles return 0; } -// Special trick to unblock select() when updates occur in somewhere -// other than the main ACE_Select_Reactor thread. All we do is write data to -// a pipe that the ACE_Select_Reactor is listening on. Thanks to Paul -// Stephenson for suggesting this approach. +// Special trick to unblock <select> when updates occur in somewhere +// other than the main <ACE_Select_Reactor> thread. All we do is +// write data to a pipe that the <ACE_Select_Reactor> is listening on. +// Thanks to Paul Stephenson for suggesting this approach. int ACE_Select_Reactor_Notify::handle_input (ACE_HANDLE handle) @@ -727,18 +747,21 @@ ACE_Select_Reactor_Notify::handle_input (ACE_HANDLE handle) { ssize_t remainder = sizeof buffer - n; - // If so, try to recover by reading the remainder. If this doesn't - // work we're in big trouble since the input stream won't be aligned - // correctly. I'm not sure quite what to do at this point. It's - // probably best just to return -1. - if (ACE::recv (handle, ((char *) &buffer) + n, remainder) != remainder) + // If so, try to recover by reading the remainder. If this + // doesn't work we're in big trouble since the input stream + // won't be aligned correctly. I'm not sure quite what to + // do at this point. It's probably best just to return -1. + if (ACE::recv (handle, + ((char *) &buffer) + n, + remainder) != remainder) return -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 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) { int result = 0; @@ -936,7 +959,8 @@ int ACE_Select_Reactor::open (size_t size, int restart, ACE_Sig_Handler *sh, - ACE_Timer_Queue *tq) + ACE_Timer_Queue *tq, + int disable_notify_pipe) { ACE_TRACE ("ACE_Select_Reactor::open"); ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_MUTEX, ace_mon, this->token_, -1)); @@ -975,7 +999,7 @@ ACE_Select_Reactor::open (size_t size, if (result != -1 && this->handler_rep_.open (size) == -1) result = -1; - else if (this->notify_handler_.open (this) == -1) + else if (this->notify_handler_.open (this, disable_notify_pipe) == -1) result = -1; if (result != -1) @@ -1009,7 +1033,8 @@ ACE_Select_Reactor::set_timer_queue (ACE_Timer_Queue *timer_queue) } ACE_Select_Reactor::ACE_Select_Reactor (ACE_Sig_Handler *sh, - ACE_Timer_Queue *tq) + ACE_Timer_Queue *tq, + int disable_notify_pipe) : handler_rep_ (*this), timer_queue_ (0), delete_timer_queue_ (0), @@ -1025,8 +1050,13 @@ ACE_Select_Reactor::ACE_Select_Reactor (ACE_Sig_Handler *sh, { ACE_TRACE ("ACE_Select_Reactor::ACE_Select_Reactor"); - if (this->open (ACE_Select_Reactor::DEFAULT_SIZE, 0, sh, tq) == -1) - ACE_ERROR ((LM_ERROR, ASYS_TEXT ("%p\n"), + if (this->open (ACE_Select_Reactor::DEFAULT_SIZE, + 0, + sh, + tq, + disable_notify_pipe) == -1) + ACE_ERROR ((LM_ERROR, + ASYS_TEXT ("%p\n"), ASYS_TEXT ("ACE_Select_Reactor::open failed inside ACE_Select_Reactor::CTOR"))); } @@ -1035,7 +1065,8 @@ ACE_Select_Reactor::ACE_Select_Reactor (ACE_Sig_Handler *sh, ACE_Select_Reactor::ACE_Select_Reactor (size_t size, int rs, ACE_Sig_Handler *sh, - ACE_Timer_Queue *tq) + ACE_Timer_Queue *tq, + int disable_notify_pipe) : handler_rep_ (*this), timer_queue_ (0), delete_timer_queue_ (0), @@ -1051,8 +1082,13 @@ ACE_Select_Reactor::ACE_Select_Reactor (size_t size, { ACE_TRACE ("ACE_Select_Reactor::ACE_Select_Reactor"); - if (this->open (size, rs, sh, tq) == -1) - ACE_ERROR ((LM_ERROR, ASYS_TEXT ("%p\n"), + if (this->open (size, + rs, + sh, + tq, + disable_notify_pipe) == -1) + ACE_ERROR ((LM_ERROR, + ASYS_TEXT ("%p\n"), ASYS_TEXT ("ACE_Select_Reactor::open failed inside ACE_Select_Reactor::CTOR"))); } diff --git a/ace/Select_Reactor.h b/ace/Select_Reactor.h index fb268c8f977..9457d529546 100644 --- a/ace/Select_Reactor.h +++ b/ace/Select_Reactor.h @@ -176,7 +176,7 @@ class ACE_Export ACE_Select_Reactor_Notify : public ACE_Event_Handler // dispatched in the context of the <ACE_Select_Reactor> thread. public: // = Initialization and termination methods. - int open (ACE_Select_Reactor *); + int open (ACE_Select_Reactor *, int disable_notify_pipe); int close (void); int dispatch_notifications (int &number_of_active_handles, @@ -208,12 +208,14 @@ public: private: ACE_Select_Reactor *select_reactor_; - // Keep a back pointer to the Select_Reactor. + // Keep a back pointer to the <ACE_Select_Reactor>. If this value + // if NULL then the <ACE_Select_Reactor> has been initialized with + // <disable_notify_pipe>. ACE_Pipe notification_pipe_; - // Contains the HANDLE the Select_Reactor is listening on, as well - // as the HANDLE that threads wanting the attention of the - // Select_Reactor will write to. + // Contains the <ACE_HANDLE> the <ACE_Select_Reactor> is listening + // on, as well as the <ACE_HANDLE> that threads wanting the + // attention of the <ACE_Select_Reactor> will write to. }; class ACE_Export ACE_Select_Reactor_Handler_Repository @@ -372,19 +374,22 @@ public: // = Initialization and termination methods. ACE_Select_Reactor (ACE_Sig_Handler * = 0, - ACE_Timer_Queue * = 0); + ACE_Timer_Queue * = 0, + int disable_notify_pipe = 0); // Initialize <ACE_Select_Reactor> with the default size. ACE_Select_Reactor (size_t size, int restart = 0, ACE_Sig_Handler * = 0, - ACE_Timer_Queue * = 0); + ACE_Timer_Queue * = 0, + int disable_notify_pipe = 0); // Initialize <ACE_Select_Reactor> with size <size>. virtual int open (size_t size = DEFAULT_SIZE, int restart = 0, ACE_Sig_Handler * = 0, - ACE_Timer_Queue * = 0); + ACE_Timer_Queue * = 0, + int disable_notify_pipe = 0); // Initialize <ACE_Select_Reactor> with size <size>. virtual int set_sig_handler (ACE_Sig_Handler *signal_handler); diff --git a/ace/WFMO_Reactor.h b/ace/WFMO_Reactor.h index 36938edc02a..2b793f7e6fc 100644 --- a/ace/WFMO_Reactor.h +++ b/ace/WFMO_Reactor.h @@ -527,7 +527,8 @@ public: virtual int open (size_t size = DEFAULT_SIZE, int restart = 0, ACE_Sig_Handler * = 0, - ACE_Timer_Queue * = 0); + ACE_Timer_Queue * = 0, + int disable_notify_pipe = 0); // Initialize <ACE_WFMO_Reactor> with size <size>. Two slots will // be added to the <size> parameter which will store handles used // for internal management purposes. diff --git a/tests/Reactor_Notify_Test.cpp b/tests/Reactor_Notify_Test.cpp index ae01d4dac87..eb69526a053 100644 --- a/tests/Reactor_Notify_Test.cpp +++ b/tests/Reactor_Notify_Test.cpp @@ -9,8 +9,10 @@ // Reactors_Test.cpp // // = DESCRIPTION -// This is a test that illustrates how the Reactor's notify() -// method works under various settings of max_notify_iterations(). +// This is a test that illustrates how the <ACE_Reactor>'s <notify> +// method works under various <max_notify_iterations> settings. +// It also tests that the <disable_notify_pipe> option works +// correctly. // // = AUTHOR // Douglas C. Schmidt @@ -20,6 +22,7 @@ #include "ace/Synch.h" #include "ace/Task.h" #include "ace/Pipe.h" +#include "ace/Select_Reactor.h" #include "test_config.h" #if defined (ACE_HAS_THREADS) @@ -27,7 +30,7 @@ class Supplier_Task : public ACE_Task<ACE_MT_SYNCH> { public: - Supplier_Task (void); + Supplier_Task (int disable_notify_pipe); // Constructor. ~Supplier_Task (void); @@ -48,11 +51,14 @@ public: // notify handler. virtual int handle_output (ACE_HANDLE); - // Called every time through the main Reactor event loop to + // Called every time through the main <ACE_Reactor> event loop to // illustrate the difference between "limited" and "unlimited" // notification. private: + int perform_notifications (int notifications); + // Perform the notifications. + ACE_Thread_Semaphore waiter_; // Used to hand-shake between the <Supplier_Task> and the // <Reactor>'s notify mechanism. @@ -60,10 +66,15 @@ private: ACE_Pipe pipe_; // We use this pipe just so we can get a handle that is always // "active." + + int disable_notify_pipe_; + // Keeps track of whether the notification pipe in the <ACE_Reactor> + // has been diabled or not. }; -Supplier_Task::Supplier_Task (void) - : waiter_ (0) // Make semaphore "locked" by default. +Supplier_Task::Supplier_Task (int disable_notify_pipe) + : waiter_ (0), // Make semaphore "locked" by default. + disable_notify_pipe_ (disable_notify_pipe) { } @@ -117,18 +128,11 @@ Supplier_Task::~Supplier_Task (void) } int -Supplier_Task::svc (void) +Supplier_Task::perform_notifications (int notifications) { - size_t i; - - ACE_DEBUG ((LM_DEBUG, - "(%t) **** starting unlimited notifications test\n")); - - // Allow an unlimited number of iterations per - // <ACE_Reactor::notify>. - ACE_Reactor::instance ()->max_notify_iterations (-1); + ACE_Reactor::instance ()->max_notify_iterations (notifications); - for (i = 0; i < ACE_MAX_ITERATIONS; i++) + for (size_t i = 0; i < ACE_MAX_ITERATIONS; i++) { ACE_DEBUG ((LM_DEBUG, "(%t) notifying reactor\n")); @@ -141,38 +145,34 @@ Supplier_Task::svc (void) // Wait for our <handle_exception> method to release the // semaphore. - else if (this->waiter_.acquire () == -1) + else if (this->disable_notify_pipe_ == 0 + && this->waiter_.acquire () == -1) ACE_ERROR_RETURN ((LM_ERROR, "(%t) %p\n", "acquire"), -1); } + return 0; +} + +int +Supplier_Task::svc (void) +{ + ACE_DEBUG ((LM_DEBUG, + "(%t) **** starting unlimited notifications test\n")); + + // Allow an unlimited number of iterations per + // <ACE_Reactor::notify>. + if (this->perform_notifications (-1) == -1) + return -1; ACE_DEBUG ((LM_DEBUG, "(%t) **** starting limited notifications test\n")); // Only allow 1 iteration per <ACE_Reactor::notify> - ACE_Reactor::instance ()->max_notify_iterations (1); - for (i = 0; i < ACE_MAX_ITERATIONS; i++) - { - ACE_DEBUG ((LM_DEBUG, - "(%t) notifying reactor\n")); - // Notify the Reactor. - if (ACE_Reactor::instance ()->notify (this) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "(%t) %p\n", - "notify"), - -1); - - // Wait for our <handle_exception> method to release the - // semaphore. - else if (this->waiter_.acquire () == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "(%t) %p\n", - "acquire"), - -1); - } + if (this->perform_notifications (1) == -1) + return -1; ACE_DEBUG ((LM_DEBUG, "(%t) **** exiting thread test\n")); @@ -199,7 +199,7 @@ Supplier_Task::handle_output (ACE_HANDLE handle) // This function is called by the main thread, believe it or not :-) // That's because the pipe's write handle is always active. So, - // give the Supplier_Task a chance to run. + // give the <Supplier_Task> a chance to run. ACE_OS::thr_yield (); return 0; @@ -207,25 +207,41 @@ Supplier_Task::handle_output (ACE_HANDLE handle) #endif /* ACE_HAS_THREADS */ -int -main (int, char *[]) +static void +run_test (int disable_notify_pipe) { - ACE_START_TEST ("Reactor_Notify_Test"); + // Create special reactors with the appropriate flags enabled. + + ACE_Select_Reactor *reactor_impl; + if (disable_notify_pipe) + ACE_NEW (reactor_impl, + ACE_Select_Reactor (0, 0, 1)); + else + ACE_NEW (reactor_impl, + ACE_Select_Reactor); + + ACE_Reactor *reactor; + ACE_NEW (reactor, + ACE_Reactor (reactor_impl)); + + // Set the Singleton Reactor. + ACE_Reactor::instance (reactor); -#if defined (ACE_HAS_THREADS) ACE_ASSERT (ACE_LOG_MSG->op_status () != -1); + ACE_ASSERT (ACE_Reactor::instance () == reactor); - Supplier_Task task; + Supplier_Task task (disable_notify_pipe); ACE_ASSERT (ACE_LOG_MSG->op_status () != -1); if (task.open () == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "(%t) open failed\n"), - -1); + ACE_ERROR ((LM_ERROR, + "(%t) open failed\n")); else { int shutdown = 0; + // Run the event loop that handles the <handle_output> and + // <handle_exception> notifications. for (int iteration = 1; shutdown == 0; iteration++) { ACE_Time_Value timeout (2); @@ -234,21 +250,42 @@ main (int, char *[]) switch (ACE_Reactor::instance ()->handle_events (timeout)) { case -1: - ACE_ERROR_RETURN ((LM_ERROR, - "(%t) %p\n", - "reactor"), - -1); + ACE_ERROR ((LM_ERROR, + "(%t) %p\n", + "reactor")); + shutdown = 1; + break; /* NOTREACHED */ case 0: shutdown = 1; break; + /* NOTREACHED */ default: - break;; + break; + /* NOTREACHED */ } } } + + delete reactor_impl; + delete reactor; +} + +int +main (int, char *[]) +{ + ACE_START_TEST ("Reactor_Notify_Test"); + +#if defined (ACE_HAS_THREADS) + ACE_DEBUG ((LM_DEBUG, + "(%t) running tests with notify pipe enabled\n")); + run_test (0); + ACE_DEBUG ((LM_DEBUG, + "(%t) running tests with notify pipe disabled\n")); + run_test (1); #else - ACE_ERROR ((LM_ERROR, "threads not supported on this platform\n")); + ACE_ERROR ((LM_ERROR, + "threads not supported on this platform\n")); #endif /* ACE_HAS_THREADS */ ACE_END_TEST; return 0; |