diff options
-rw-r--r-- | ace/Asynch_IO.cpp | 17 | ||||
-rw-r--r-- | ace/Asynch_IO.h | 8 | ||||
-rw-r--r-- | ace/Proactor.cpp | 168 | ||||
-rw-r--r-- | ace/Proactor.h | 130 |
4 files changed, 185 insertions, 138 deletions
diff --git a/ace/Asynch_IO.cpp b/ace/Asynch_IO.cpp index a350e4ce366..18d2925fb01 100644 --- a/ace/Asynch_IO.cpp +++ b/ace/Asynch_IO.cpp @@ -89,8 +89,6 @@ ACE_Asynch_Result::event (void) const return this->hEvent; } -// ************************************************************ - ACE_Asynch_Operation::ACE_Asynch_Operation (void) : handler_ (0), handle_ (ACE_INVALID_HANDLE) @@ -128,7 +126,8 @@ ACE_Asynch_Operation::open (ACE_Handler &handler, #if !defined (ACE_HAS_AIO_CALLS) // Register with the <proactor> - return this->proactor_->register_handle (this->handle_, completion_key); + return this->proactor_->register_handle (this->handle_, + completion_key); #else /* ACE_HAS_AIO_CALLS */ // AIO stuff is present. So no registering business. return 1; @@ -144,6 +143,8 @@ ACE_Asynch_Operation::cancel (void) #if (defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0)) && (defined (_MSC_VER) && (_MSC_VER > 1020)) return (int) ::CancelIo (this->handle_); #else + // @@ Alex, there should be an API for cancelling this stuff on + // POSIX! ACE_NOTSUP_RETURN (-1); #endif /* (defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0)) && (defined (_MSC_VER) && (_MSC_VER > 1020)) */ } @@ -179,9 +180,11 @@ ACE_Asynch_Read_Stream::shared_read (ACE_Asynch_Read_Stream::Result *result) #if defined (ACE_HAS_AIO_CALLS) // Make a new AIOCB and issue aio_read, if queueing is possible // store this with the Proactor, so that that can be used for - // aio_return6 and aio_error. + // <aio_return> and <aio_error>. aiocb *aiocb_ptr; - ACE_NEW_RETURN (aiocb_ptr, aiocb, -1); + ACE_NEW_RETURN (aiocb_ptr, + aiocb, + -1); // Setup AIOCB. // @@ Priority always 0? @@ -196,7 +199,9 @@ ACE_Asynch_Read_Stream::shared_read (ACE_Asynch_Read_Stream::Result *result) aiocb_ptr->aio_sigevent.sigev_value.sival_ptr = (void *) aiocb_ptr; - // Fire off the aio write. + // Fire off the aio write. @@ Alex, should this be < 0 or -1? In + // general, please try to use -1 for checking all return values if + // that's what the manual says will be returned... if (aio_read (aiocb_ptr) < 0) // Queuing failed. ACE_ERROR_RETURN ((LM_ERROR, diff --git a/ace/Asynch_IO.h b/ace/Asynch_IO.h index ba9f8370e04..ba8c151dca8 100644 --- a/ace/Asynch_IO.h +++ b/ace/Asynch_IO.h @@ -10,15 +10,17 @@ // Asynch_IO.h // // = DESCRIPTION -// This only works on Win32 platforms. +// This only works on Win32 platforms or on POSIX platforms with +// aio_ routines. // // The implementation of <ACE_Asynch_Transmit_File> and // <ACE_Asynch_Accept> are only supported if ACE_HAS_WINSOCK2 is // defined or you are on WinNT 4.0 or higher // // = AUTHOR -// Irfan Pyarali (irfan@cs.wustl.edu) -// Tim Harrison (harrison@cs.wustl.edu) +// Irfan Pyarali (irfan@cs.wustl.edu), +// Tim Harrison (harrison@cs.wustl.edu), and +// Alexander Babu Arulanthu <alex@cs.wustl.edu> // // ============================================================================ diff --git a/ace/Proactor.cpp b/ace/Proactor.cpp index 52553a5a6f8..1c05308bbef 100644 --- a/ace/Proactor.cpp +++ b/ace/Proactor.cpp @@ -1,5 +1,4 @@ -// Proactor.cpp -// $Id: Proactor.cpp,v +// $Id$ #define ACE_BUILD_DLL #include "ace/Proactor.h" @@ -28,22 +27,17 @@ int ACE_Proactor::delete_proactor_ = 0; sig_atomic_t ACE_Proactor::end_event_loop_ = 0; class ACE_Export ACE_Proactor_Timer_Handler : public ACE_Task <ACE_NULL_SYNCH> - // // = TITLE - // // A Handler for timer. It helps in the management of timers // registered with the Proactor. // // = DESCRIPTION - // - // This object has a thread that will wait on the earliest - // time in a list of timers and an event. When a timer - // expires, the thread will post a completion event on the - // port and go back to waiting on the timer queue and - // event. If the event is signaled, the thread will refresh - // the time it is currently waiting on (in case the earliest - // time has changed) - // + // This object has a thread that will wait on the earliest time + // in a list of timers and an event. When a timer expires, the + // thread will post a completion event on the port and go back + // to waiting on the timer queue and event. If the event is + // signaled, the thread will refresh the time it is currently + // waiting on (in case the earliest time has changed) { friend class ACE_Proactor; // Proactor has special privileges @@ -59,14 +53,14 @@ public: protected: virtual int svc (void); // Run by a daemon thread to handle deferred processing. In other - // words, this method will do the waiting on the earliest timer - // and event + // words, this method will do the waiting on the earliest timer and + // event. ACE_Auto_Event timer_event_; - // Event to wait on + // Event to wait on. ACE_Proactor &proactor_; - // Proactor + // Proactor. int shutting_down_; // Flag used to indicate when we are shutting down. @@ -92,12 +86,14 @@ int ACE_Proactor_Timer_Handler::svc (void) { #if defined (ACE_HAS_AIO_CALLS) + // @@ Alex, can you please document why this is a "no-op" for the + // AIO calls? return 0; #else /* ACE_HAS_AIO_CALLS */ u_long time; ACE_Time_Value absolute_time; - for (; !this->shutting_down_;) + while (this->shutting_down_ == 0) { // default value time = ACE_INFINITE; @@ -105,15 +101,15 @@ ACE_Proactor_Timer_Handler::svc (void) // If the timer queue is not empty if (!this->proactor_.timer_queue ()->is_empty ()) { - // Get the earliest absolute time + // Get the earliest absolute time. absolute_time = this->proactor_.timer_queue ()->earliest_time () - this->proactor_.timer_queue ()->gettimeofday (); - // time to wait + // Time to wait. time = absolute_time.msec (); - // Make sure the time is positive + // Make sure the time is positive. if (time < 0) time = 0; } @@ -129,7 +125,9 @@ ACE_Proactor_Timer_Handler::svc (void) break; case ACE_WAIT_FAILED: // error - ACE_ERROR_RETURN ((LM_ERROR, ASYS_TEXT ("%p\n"), ASYS_TEXT ("WaitForSingleObject")), -1); + ACE_ERROR_RETURN ((LM_ERROR, + ASYS_TEXT ("%p\n"), + ASYS_TEXT ("WaitForSingleObject")), -1); } } @@ -155,19 +153,19 @@ ACE_Proactor_Handle_Timeout_Upcall::timeout (TIMER_QUEUE &timer_queue, "(%t) No Proactor set in ACE_Proactor_Handle_Timeout_Upcall, no completion port to post timeout to?!@\n"), -1); - // Create the Asynch_Timer + // Create the Asynch_Timer. ACE_Proactor::Asynch_Timer *asynch_timer = new ACE_Proactor::Asynch_Timer (*handler, act, time); - // Post a completion + // Post a completion. if (this->proactor_->post_completion (asynch_timer) == -1) - ACE_ERROR_RETURN ((LM_ERROR, "Failure in dealing with timers: PostQueuedCompletionStatus failed\n"), -1); + ACE_ERROR_RETURN ((LM_ERROR, + "Failure in dealing with timers: PostQueuedCompletionStatus failed\n"), -1); return 0; } - int ACE_Proactor_Handle_Timeout_Upcall::cancellation (TIMER_QUEUE &timer_queue, ACE_Handler *handler) @@ -206,24 +204,21 @@ ACE_Proactor_Handle_Timeout_Upcall::proactor (ACE_Proactor &proactor) -1); } - - ACE_Proactor::ACE_Proactor (size_t number_of_threads, Timer_Queue *tq, int used_with_reactor_event_loop) : #if defined (ACE_HAS_AIO_CALLS) - #if defined (AIO_LISTIO_MAX) +#if defined (AIO_LISTIO_MAX) aiocb_list_max_size_ (AIO_LISTIO_MAX), - #else /* AIO_LISTIO_MAX */ +#else /* AIO_LISTIO_MAX */ aiocb_list_max_size_ (2), - #endif /* AIO_LISTIO_MAX */ - +#endif /* AIO_LISTIO_MAX */ aiocb_list_cur_size_ (0), #else /* ACE_HAS_AIO_CALLS */ - completion_port_ (0), // This *MUST* be 0, *NOT* ACE_INVALID_HANDLE!!!! + // This *MUST* be 0, *NOT* ACE_INVALID_HANDLE!!!! + completion_port_ (0), #endif /* ACE_HAS_AIO_CALLS */ - number_of_threads_ (number_of_threads), timer_queue_ (0), delete_timer_queue_ (0), @@ -236,8 +231,8 @@ ACE_Proactor::ACE_Proactor (size_t number_of_threads, ai < this->aiocb_list_max_size_; ai++) { - aiocb_list_ [ai] = 0; - result_list_ [ai] = 0; + aiocb_list_[ai] = 0; + result_list_[ai] = 0; } ACE_UNUSED_ARG (tq); #else /* ACE_HAS_AIO_CALLS */ @@ -247,17 +242,22 @@ ACE_Proactor::ACE_Proactor (size_t number_of_threads, 0, this->number_of_threads_); if (this->completion_port_ == 0) - ACE_ERROR ((LM_ERROR, ASYS_TEXT ("%p\n"), ASYS_TEXT ("CreateIoCompletionPort"))); + ACE_ERROR ((LM_ERROR, + ASYS_TEXT ("%p\n"), + ASYS_TEXT ("CreateIoCompletionPort"))); // set the timer queue this->timer_queue (tq); // Create the timer handler - ACE_NEW (this->timer_handler_, ACE_Proactor_Timer_Handler (*this)); + ACE_NEW (this->timer_handler_, + ACE_Proactor_Timer_Handler (*this)); // activate <timer_handler> if (this->timer_handler_->activate (THR_NEW_LWP | THR_DETACHED) == -1) - ACE_ERROR ((LM_ERROR, ASYS_TEXT ("%p Could not create thread\n"), ASYS_TEXT ("Task::activate"))); + ACE_ERROR ((LM_ERROR, + ASYS_TEXT ("%p Could not create thread\n"), + ASYS_TEXT ("Task::activate"))); #endif /* ACE_HAS_AIO_CALLS */ } @@ -270,11 +270,14 @@ ACE_Proactor::instance (size_t threads) { // Perform Double-Checked Locking Optimization. ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, - *ACE_Static_Object_Lock::instance (), 0)); + *ACE_Static_Object_Lock::instance (), + 0)); if (ACE_Proactor::proactor_ == 0) { - ACE_NEW_RETURN (ACE_Proactor::proactor_, ACE_Proactor (threads), 0); + ACE_NEW_RETURN (ACE_Proactor::proactor_, + ACE_Proactor (threads), + 0); ACE_Proactor::delete_proactor_ = 1; } } @@ -290,6 +293,7 @@ ACE_Proactor::instance (ACE_Proactor *r) *ACE_Static_Object_Lock::instance (), 0)); ACE_Proactor *t = ACE_Proactor::proactor_; + // We can't safely delete it since we don't know who created it! ACE_Proactor::delete_proactor_ = 0; @@ -328,6 +332,7 @@ ACE_Proactor::run_event_loop (void) else if (result == -1) return -1; } + /* NOTREACHED */ return 0; } @@ -339,9 +344,11 @@ ACE_Proactor::run_event_loop (ACE_Time_Value &tv) { ACE_TRACE ("ACE_Proactor::run_event_loop"); - while (ACE_Proactor::end_event_loop_ == 0 && tv != ACE_Time_Value::zero) + while (ACE_Proactor::end_event_loop_ == 0 + && tv != ACE_Time_Value::zero) { int result = ACE_Proactor::instance ()->handle_events (tv); + if (ACE_Service_Config::reconfig_occurred ()) ACE_Service_Config::reconfigure (); @@ -380,6 +387,8 @@ int ACE_Proactor::close (void) { #if defined (ACE_HAS_AIO_CALLS) + // @@ Alex, shouldn't we be handling the cleanup of the timer queue + // stuff for the POSIX version of the Proactor, as well?! return 0; #else /* ACE_HAS_AIO_CALLS */ // Take care of the timer handler @@ -418,7 +427,7 @@ ACE_Proactor::register_handle (ACE_HANDLE handle, ACE_UNUSED_ARG (completion_key); return 0; #else /* ACE_HAS_AIO_CALLS */ - // No locking is needed here as no state changes + // No locking is needed here as no state changes. ACE_HANDLE cp = ::CreateIoCompletionPort (handle, this->completion_port_, (u_long) completion_key, @@ -429,7 +438,9 @@ ACE_Proactor::register_handle (ACE_HANDLE handle, // If errno == ERROR_INVALID_PARAMETER, then this handle was // already registered. if (errno != ERROR_INVALID_PARAMETER) - ACE_ERROR_RETURN ((LM_ERROR, ASYS_TEXT ("%p\n"), ASYS_TEXT ("CreateIoCompletionPort")), -1); + ACE_ERROR_RETURN ((LM_ERROR, + ASYS_TEXT ("%p\n"), + ASYS_TEXT ("CreateIoCompletionPort")), -1); } return 0; #endif /* ACE_HAS_AIO_CALLS */ @@ -440,7 +451,10 @@ ACE_Proactor::schedule_timer (ACE_Handler &handler, const void *act, const ACE_Time_Value &time) { - return this->schedule_timer (handler, act, time, ACE_Time_Value::zero); + return this->schedule_timer (handler, + act, + time, + ACE_Time_Value::zero); } long @@ -448,7 +462,10 @@ ACE_Proactor::schedule_repeating_timer (ACE_Handler &handler, const void *act, const ACE_Time_Value &interval) { - return this->schedule_timer (handler, act, interval, interval); + return this->schedule_timer (handler, + act, + interval, + interval); } long @@ -457,8 +474,9 @@ ACE_Proactor::schedule_timer (ACE_Handler &handler, const ACE_Time_Value &time, const ACE_Time_Value &interval) { - // absolute time - ACE_Time_Value absolute_time = this->timer_queue_->gettimeofday () + time; + // absolute time. + ACE_Time_Value absolute_time = + this->timer_queue_->gettimeofday () + time; // Only one guy goes in here at a time ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->timer_queue_->mutex (), -1); @@ -491,16 +509,19 @@ ACE_Proactor::cancel_timer (long timer_id, { // No need to singal timer event here. Even if the cancel timer was // the earliest, we will have an extra wakeup. - return this->timer_queue_->cancel (timer_id, arg, dont_call_handle_close); + return this->timer_queue_->cancel (timer_id, + arg, + dont_call_handle_close); } int ACE_Proactor::cancel_timer (ACE_Handler &handler, int dont_call_handle_close) { - // No need to singal timer event here. Even if the cancel timer was + // No need to signal timer event here. Even if the cancel timer was // the earliest, we will have an extra wakeup. - return this->timer_queue_->cancel (&handler, dont_call_handle_close); + return this->timer_queue_->cancel (&handler, + dont_call_handle_close); } int @@ -530,7 +551,6 @@ ACE_Proactor::handle_close (ACE_HANDLE handle, return this->close (); } - // @@ get_handle () implementation. ACE_HANDLE ACE_Proactor::get_handle (void) const @@ -545,7 +565,6 @@ ACE_Proactor::get_handle (void) const #endif /* ACE_HAS_AIO_CALLS */ } - int ACE_Proactor::handle_events (ACE_Time_Value &wait_time) { @@ -566,20 +585,26 @@ ACE_Proactor::handle_events (unsigned long milli_seconds) #if defined (ACE_HAS_AIO_CALLS) // Is there any entries in the list. if (this->aiocb_list_cur_size_ == 0) - { - ACE_DEBUG ((LM_DEBUG, "No AIO pending")); - return 0; - } + ACE_ERROR_RETURN ((LM_ERROR, + "No AIO pending"), + 0); // Wait for asynch operation to complete. timespec timeout; timeout.tv_sec = milli_seconds; timeout.tv_nsec = 0; + + // Alex, I think we want to revise this implementation so that it + // DOESN'T need to use aio_suspend, which is going to be + // non-scalable since we need to search the aiocb_list... Instead, + // we need to use the sigtimedwait(3R) in conjunction with the POSIX + // real-time signal mechanism, which should be much more scalable. + // Let's talk about how to make this work. if (aio_suspend (this->aiocb_list_, this->aiocb_list_max_size_, &timeout) < 0) - // If failure is coz of timeout, then return *0* but set errno - // appropriately. This is what the Win proactor does. + // If failure occurs due to timeout, then return *0* but set errno + // appropriately. This is what the WinNT proactor does. if (errno == EINTR) ACE_ERROR_RETURN ((LM_ERROR, "(%p):aio_suspend"), @@ -591,29 +616,37 @@ ACE_Proactor::handle_events (unsigned long milli_seconds) // Check which aio has finished. size_t ai; + for (ai = 0; ai < this->aiocb_list_max_size_; ai++) // Analyze error and return values. - if (aio_error (aiocb_list_ [ai]) != EINPROGRESS) + if (aio_error (aiocb_list_[ai]) != EINPROGRESS) { - if (aio_return (aiocb_list_ [ai]) < 0) + // @@ Alex, should this be == -1 or < 0? + if (aio_return (aiocb_list_[ai]) < 0) ACE_ERROR_RETURN ((LM_ERROR, "(%p):AIO failed"), -1); else { - ACE_DEBUG ((LM_DEBUG, "An aio has finished\n")); + ACE_DEBUG ((LM_DEBUG, + "An aio has finished\n")); // This AIO is done. break; } } + if (ai == this->aiocb_list_max_size_) // Nothing completed. return 0; // Get the values for the completed aio. size_t bytes_transferred = aiocb_list_[ai]->aio_nbytes; - void *completion_key = (void *)aiocb_list_[ai]->aio_sigevent.sigev_value.sival_ptr; - ACE_Asynch_Result *asynch_result = this->result_list_[ai]; + + void *completion_key = + (void *) aiocb_list_[ai]->aio_sigevent.sigev_value.sival_ptr; + + ACE_Asynch_Result *asynch_result = + this->result_list_[ai]; // Invalidate entry in the aiocb list. delete this->aiocb_list_[ai]; @@ -640,7 +673,6 @@ ACE_Proactor::handle_events (unsigned long milli_seconds) &completion_key, &overlapped, milli_seconds); - if (result == FALSE && overlapped == 0) { errno = ::GetLastError (); @@ -816,15 +848,15 @@ ACE_Proactor::insert_to_aiocb_list (aiocb *aiocb_ptr, for (ai = 0; ai < this->aiocb_list_max_size_; ai++) - if (this->aiocb_list_ [ai] == 0) + if (this->aiocb_list_[ai] == 0) break; if (ai == this->aiocb_list_max_size_) return -1; // Store the pointers. - this->aiocb_list_ [ai] = aiocb_ptr; - this->result_list_ [ai] = result; + this->aiocb_list_[ai] = aiocb_ptr; + this->result_list_[ai] = result; this->aiocb_list_cur_size_ ++; return 0; } diff --git a/ace/Proactor.h b/ace/Proactor.h index cfd3d555922..179c01d34f6 100644 --- a/ace/Proactor.h +++ b/ace/Proactor.h @@ -10,8 +10,9 @@ // Proactor.h // // = AUTHOR -// Irfan Pyarali (irfan@cs.wustl.edu) -// Tim Harrison (harrison@cs.wustl.edu) +// Irfan Pyarali (irfan@cs.wustl.edu), +// Tim Harrison (harrison@cs.wustl.edu), and +// Alexander Babu Arulanthu <alex@cs.wustl.edu> // // ============================================================================ @@ -29,7 +30,6 @@ #include "ace/Timer_Wheel.h" #include "ace/Free_List.h" - #if (defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)) || \ (defined (ACE_HAS_AIO_CALLS)) // This only works on Win32 platforms and on Unix platforms supporting @@ -50,12 +50,12 @@ class ACE_Export ACE_Proactor_Handle_Timeout_Upcall // Queue to call <handle_timeout> on ACE_Handlers. public: friend class ACE_Proactor; - // Proactor has special privileges - // Access needed to: proactor () + // Proactor has special privileges, access needed to: proactor () typedef ACE_Timer_Queue_T<ACE_Handler *, ACE_Proactor_Handle_Timeout_Upcall, - ACE_SYNCH_RECURSIVE_MUTEX> TIMER_QUEUE; + ACE_SYNCH_RECURSIVE_MUTEX> + TIMER_QUEUE; ACE_Proactor_Handle_Timeout_Upcall (void); // Constructor @@ -64,17 +64,17 @@ public: ACE_Handler *handler, const void *arg, const ACE_Time_Value &cur_time); - // This method is called when the timer expires + // This method is called when the timer expires. int cancellation (TIMER_QUEUE &timer_queue, ACE_Handler *handler); - // This method is called when the timer is canceled + // This method is called when the timer is canceled. int deletion (TIMER_QUEUE &timer_queue, ACE_Handler *handler, const void *arg); - // This method is called when the timer queue is destroyed and - // the timer is still contained in it + // This method is called when the timer queue is destroyed and the + // timer is still contained in it. protected: int proactor (ACE_Proactor &proactor); @@ -97,37 +97,46 @@ public: // Access needed to: thr_mgr_ friend class ACE_Proactor_Handle_Timeout_Upcall; - // Access needed to: Asynch_Timer, and completion_port_ + // Access needed to: Asynch_Timer, and completion_port_. // = Here are the typedefs that the <ACE_Proactor> uses. + // @@ Alex, are there any reasons why these typedefs aren't + // "capitalized? In general, that's the programming style we + // typically use. Can you please take a look and see what depends + // on these typedefs to see if we can capitalize them? typedef ACE_Timer_Queue_T<ACE_Handler *, ACE_Proactor_Handle_Timeout_Upcall, - ACE_SYNCH_RECURSIVE_MUTEX> Timer_Queue; + ACE_SYNCH_RECURSIVE_MUTEX> + Timer_Queue; typedef ACE_Timer_Queue_Iterator_T<ACE_Handler *, ACE_Proactor_Handle_Timeout_Upcall, - ACE_SYNCH_RECURSIVE_MUTEX> Timer_Queue_Iterator; - + ACE_SYNCH_RECURSIVE_MUTEX> + Timer_Queue_Iterator; typedef ACE_Timer_List_T<ACE_Handler *, ACE_Proactor_Handle_Timeout_Upcall, - ACE_SYNCH_RECURSIVE_MUTEX> Timer_List; + ACE_SYNCH_RECURSIVE_MUTEX> + Timer_List; typedef ACE_Timer_List_Iterator_T<ACE_Handler *, ACE_Proactor_Handle_Timeout_Upcall, - ACE_SYNCH_RECURSIVE_MUTEX> Timer_List_Iterator; - + ACE_SYNCH_RECURSIVE_MUTEX> + Timer_List_Iterator; typedef ACE_Timer_Heap_T<ACE_Handler *, ACE_Proactor_Handle_Timeout_Upcall, - ACE_SYNCH_RECURSIVE_MUTEX> Timer_Heap; + ACE_SYNCH_RECURSIVE_MUTEX> + Timer_Heap; typedef ACE_Timer_Heap_Iterator_T<ACE_Handler *, ACE_Proactor_Handle_Timeout_Upcall, - ACE_SYNCH_RECURSIVE_MUTEX> Timer_Heap_Iterator; - + ACE_SYNCH_RECURSIVE_MUTEX> + Timer_Heap_Iterator; typedef ACE_Timer_Wheel_T<ACE_Handler *, ACE_Proactor_Handle_Timeout_Upcall, - ACE_SYNCH_RECURSIVE_MUTEX> Timer_Wheel; + ACE_SYNCH_RECURSIVE_MUTEX> + Timer_Wheel; typedef ACE_Timer_Wheel_Iterator_T<ACE_Handler *, ACE_Proactor_Handle_Timeout_Upcall, - ACE_SYNCH_RECURSIVE_MUTEX> Timer_Wheel_Iterator; + ACE_SYNCH_RECURSIVE_MUTEX> + Timer_Wheel_Iterator; ACE_Proactor (size_t number_of_threads = 0, Timer_Queue *tq = 0, @@ -139,35 +148,35 @@ public: static ACE_Proactor *instance (size_t threads = 0); // Get pointer to a process-wide <ACE_Proactor>. <threads> should - // be part of another method. It's only here because I'm just a - // grad student and not in charge. No, I'm not bitter about this. + // be part of another method. static ACE_Proactor *instance (ACE_Proactor *); // Set pointer to a process-wide <ACE_Proactor> and return existing // pointer. static void close_singleton (void); - // Delete the dynamically allocated Singleton + // Delete the dynamically allocated Singleton. // = Proactor event loop management methods. + static int run_event_loop (void); - // Run the event loop until the <ACE_Proactor::handle_events> - // method returns -1 or the <end_event_loop> method - // is invoked. + // Run the event loop until the <ACE_Proactor::handle_events> method + // returns -1 or the <end_event_loop> method is invoked. static int run_event_loop (ACE_Time_Value &tv); - // Run the event loop until the <ACE_Proactor::handle_events> - // method returns -1, the <end_event_loop> method - // is invoked, or the <ACE_Time_Value> expires. + // Run the event loop until the <ACE_Proactor::handle_events> method + // returns -1, the <end_event_loop> method is invoked, or the + // <ACE_Time_Value> expires. static int end_event_loop (void); - // Instruct the <ACE_Proactor::instance> to terminate its event loop. + // Instruct the <ACE_Proactor::instance> to terminate its event + // loop. static int event_loop_done (void); // Report if the <ACE_Proactor::instance> event loop is finished. virtual int close (void); - // Close the IO completion port + // Close the IO completion port. virtual int register_handle (ACE_HANDLE handle, const void *completion_key); @@ -220,9 +229,8 @@ public: virtual int handle_events (ACE_Time_Value &wait_time); // Dispatch a single set of events. If <wait_time> elapses before - // any events occur, return. - // Return 0 on success, non-zero (-1) on timeouts/errors and errno - // is set accordingly. + // any events occur, return. Return 0 on success, non-zero (-1) on + // timeouts/errors and errno is set accordingly. virtual int handle_events (void); // Block indefinitely until at least one event is dispatched. @@ -254,15 +262,17 @@ public: virtual ACE_HANDLE get_handle (void) const; // Get the event handle. - - int insert_to_aiocb_list (aiocb *aiocb_ptr, ACE_Asynch_Result *result); - // @@ - // This call is for Unix aio_ calls. - // This method is used by ACE_Asynch_Operation to store some - // information with the Proactor. - // Inserting this aiocb_ptr to the array so that aio_return and - // aio_error can make use of that. Inserting result so that we can - // call the application back through complete. + int insert_to_aiocb_list (aiocb *aiocb_ptr, + ACE_Asynch_Result *result); + // @@ Alex, is it possible to "hide" this better, i.e., so it's not + // in the public interface? Perhaps we could use a "friend" + // instead, or better yet, abstract away from this via some other + // technique that wouldn't be so "POSIX"-specific. + // This call is for POSIX <aio_> calls. This method is used by + // <ACE_Asynch_Operation> to store some information with the + // Proactor. Inserting this <aiocb_ptr> to the array so that + // <aio_return> and <aio_error> can make use of that. Inserting + // result so that we can call the application back through complete. // @@ Can array be full? That means, the aio issue is successful, // but there are already AIO_LIST_AIO_MAX of calls pending. I will // have to go for something other than arrays then. @@ -274,7 +284,7 @@ protected: virtual int handle_close (ACE_HANDLE handle, ACE_Reactor_Mask close_mask); - // Called when object is removed from the ACE_Reactor + // Called when object is removed from the ACE_Reactor. void application_specific_code (ACE_Asynch_Result *asynch_result, u_long bytes_transferred, @@ -282,7 +292,7 @@ protected: const void *completion_key, u_long error); // Protect against structured exceptions caused by user code when - // dispatching handles + // dispatching handles. virtual int handle_events (unsigned long milli_seconds); // Dispatch a single set of events. If <milli_seconds> elapses @@ -316,13 +326,11 @@ protected: // Time value requested by caller }; - - #if defined (ACE_HAS_AIO_CALLS) - // Let us have an array ot keep track of the all the aio's issued + // Let us have an array to keep track of the all the aio's issued // currently. My intuition is to limit the array size to Maximum - // Aios that can be issued thru' a lio_list call. - // @@ AIO_LISTIO_MAX is something else in LynxOS!!! + // Aios that can be issued thru' a lio_list call. @@ AIO_LISTIO_MAX + // is something else in LynxOS!!! #if defined (AIO_LISTIO_MAX) aiocb *aiocb_list_ [AIO_LISTIO_MAX]; ACE_Asynch_Result *result_list_ [AIO_LISTIO_MAX]; @@ -338,25 +346,26 @@ protected: size_t aiocb_list_cur_size_; // To maintain the current size of the array (list). -#else /* ACE_HAS_AIO_CALLS */ +#elif defined (ACE_WIN32) ACE_HANDLE completion_port_; // Handle for the completion port. #endif /* ACE_HAS_AIO_CALLS */ size_t number_of_threads_; - // This number is passed to the CreatIOCompletionPort() system call + // This number is passed to the <CreatIOCompletionPort> system + // call. Timer_Queue *timer_queue_; - // Timer Queue + // Timer Queue. int delete_timer_queue_; - // Flag on whether to delete the timer queue + // Flag on whether to delete the timer queue. ACE_Proactor_Timer_Handler *timer_handler_; - // Handles timeouts events + // Handles timeouts events. ACE_Thread_Manager thr_mgr_; - // This will manage the thread in the Timer_Handler + // This will manage the thread in the Timer_Handler. ACE_Auto_Event event_; // This event is used in conjunction with Reactor when we try to @@ -364,7 +373,7 @@ protected: int used_with_reactor_event_loop_; // Flag that indicates whether we are used in conjunction with - // Reactor + // Reactor. private: static ACE_Proactor *proactor_; @@ -381,8 +390,7 @@ private: #include "ace/Proactor.i" #endif /* __ACE_INLINE__ */ -#else /* NOT WIN32 */ - +#else /* NOT WIN32 or POSIX with AIO features. */ class ACE_Export ACE_Proactor { public: |