summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOssama Othman <ossama-othman@users.noreply.github.com>2002-05-02 20:29:34 +0000
committerOssama Othman <ossama-othman@users.noreply.github.com>2002-05-02 20:29:34 +0000
commitd3581fe4d84c284914e5abe342a51cd4ea78f1f2 (patch)
tree3f36484142eb05652696018ce1e63f822618c4b8
parent7357ae2b7b412d9ee9fcb09e405299614e085291 (diff)
downloadATCD-d3581fe4d84c284914e5abe342a51cd4ea78f1f2.tar.gz
ChangeLogTag:Thu May 2 13:28:01 2002 Ossama Othman <ossama@uci.edu>
-rw-r--r--ChangeLog67
-rw-r--r--ChangeLogs/ChangeLog-02a67
-rw-r--r--ChangeLogs/ChangeLog-03a67
-rw-r--r--ace/Dev_Poll_Reactor.cpp296
-rw-r--r--ace/Dev_Poll_Reactor.h66
-rw-r--r--ace/Dev_Poll_Reactor.inl30
6 files changed, 465 insertions, 128 deletions
diff --git a/ChangeLog b/ChangeLog
index 241a940b237..6549be36697 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,70 @@
+Thu May 2 13:28:01 2002 Ossama Othman <ossama@uci.edu>
+
+ * ace/Dev_Poll_Reactor.h:
+
+ Updated some documentation.
+
+ * ace/Dev_Poll_Reactor.inl (upcall):
+
+ New method containing common upcall operations for all types of
+ IO events.
+
+ * ace/Dev_Poll_Reactor.cpp:
+
+ Commented out "ready set" code since the upcall will simply loop
+ until the event handler no longer desires callbacks. This is
+ okay since multiple threads may dispatch event handlers (similar
+ to what the TP_Reactor does).
+
+ (close):
+
+ Cleaned up memory and resource leaks.
+
+ (handle_events_i, work_pending_i):
+
+ Moved "event polling" code to the new work_pending_i() method.
+ handle_events_i() now calls that method to determine if any
+ events must be dispatched.
+
+ If the underlying ioctl() call was interrupted (e.g. via the
+ INTR signal), i.e. returns -1 with errno set to EINTR, then
+ automatically restart the event loop if so desired by the user.
+
+ (work_pending):
+
+ Implemented this method. It simply grabs the reactor lock and
+ calls the new work_pending_i() method.
+
+ (dispatch_io_events):
+
+ Call the remove_handler() method that acquires the lock instead
+ of the one doesn't. The lock must be reacquired since reactor
+ state will potentially change during an upcall and since the
+ lock was released prior to dispatching the upcall. Fixes a race
+ condition.
+
+ Directly use pollfd pointers as the loop variables instead of an
+ integer. No need for the additional indirection.
+
+ Since the underlying event demultiplexing mechansim (`/dev/poll'
+ or '/dev/epoll') is stateful, and since only one result buffer
+ is used, all pending events (i.e. those retrieved from a
+ previous poll) must be dispatched before any additional event
+ can be polled. As such, the Dev_Poll_Reactor keeps track of the
+ progress of events that have been dispatched.
+
+ The semantics of the event loop in the presence of multiple
+ threads is non-trivial. The "start point" of the loop will be
+ incremented each time an event handler is dispatched, which may
+ be done across multiple threads. Multiple threads may change
+ the loop variables. Care must be taken to only change those
+ variables with the reactor lock held.
+
+ (dispatch_timer_handlers):
+
+ Release the reactor lock during the upcall. Fixes a potential
+ deadlock.
+
Thu May 2 10:35:25 2002 Phil Mesnier <mesnier_p@ociweb.com>
* ace/Log_Msg.cpp: ACE_Log_Msg::open() did not properly initialize a
diff --git a/ChangeLogs/ChangeLog-02a b/ChangeLogs/ChangeLog-02a
index 241a940b237..6549be36697 100644
--- a/ChangeLogs/ChangeLog-02a
+++ b/ChangeLogs/ChangeLog-02a
@@ -1,3 +1,70 @@
+Thu May 2 13:28:01 2002 Ossama Othman <ossama@uci.edu>
+
+ * ace/Dev_Poll_Reactor.h:
+
+ Updated some documentation.
+
+ * ace/Dev_Poll_Reactor.inl (upcall):
+
+ New method containing common upcall operations for all types of
+ IO events.
+
+ * ace/Dev_Poll_Reactor.cpp:
+
+ Commented out "ready set" code since the upcall will simply loop
+ until the event handler no longer desires callbacks. This is
+ okay since multiple threads may dispatch event handlers (similar
+ to what the TP_Reactor does).
+
+ (close):
+
+ Cleaned up memory and resource leaks.
+
+ (handle_events_i, work_pending_i):
+
+ Moved "event polling" code to the new work_pending_i() method.
+ handle_events_i() now calls that method to determine if any
+ events must be dispatched.
+
+ If the underlying ioctl() call was interrupted (e.g. via the
+ INTR signal), i.e. returns -1 with errno set to EINTR, then
+ automatically restart the event loop if so desired by the user.
+
+ (work_pending):
+
+ Implemented this method. It simply grabs the reactor lock and
+ calls the new work_pending_i() method.
+
+ (dispatch_io_events):
+
+ Call the remove_handler() method that acquires the lock instead
+ of the one doesn't. The lock must be reacquired since reactor
+ state will potentially change during an upcall and since the
+ lock was released prior to dispatching the upcall. Fixes a race
+ condition.
+
+ Directly use pollfd pointers as the loop variables instead of an
+ integer. No need for the additional indirection.
+
+ Since the underlying event demultiplexing mechansim (`/dev/poll'
+ or '/dev/epoll') is stateful, and since only one result buffer
+ is used, all pending events (i.e. those retrieved from a
+ previous poll) must be dispatched before any additional event
+ can be polled. As such, the Dev_Poll_Reactor keeps track of the
+ progress of events that have been dispatched.
+
+ The semantics of the event loop in the presence of multiple
+ threads is non-trivial. The "start point" of the loop will be
+ incremented each time an event handler is dispatched, which may
+ be done across multiple threads. Multiple threads may change
+ the loop variables. Care must be taken to only change those
+ variables with the reactor lock held.
+
+ (dispatch_timer_handlers):
+
+ Release the reactor lock during the upcall. Fixes a potential
+ deadlock.
+
Thu May 2 10:35:25 2002 Phil Mesnier <mesnier_p@ociweb.com>
* ace/Log_Msg.cpp: ACE_Log_Msg::open() did not properly initialize a
diff --git a/ChangeLogs/ChangeLog-03a b/ChangeLogs/ChangeLog-03a
index 241a940b237..6549be36697 100644
--- a/ChangeLogs/ChangeLog-03a
+++ b/ChangeLogs/ChangeLog-03a
@@ -1,3 +1,70 @@
+Thu May 2 13:28:01 2002 Ossama Othman <ossama@uci.edu>
+
+ * ace/Dev_Poll_Reactor.h:
+
+ Updated some documentation.
+
+ * ace/Dev_Poll_Reactor.inl (upcall):
+
+ New method containing common upcall operations for all types of
+ IO events.
+
+ * ace/Dev_Poll_Reactor.cpp:
+
+ Commented out "ready set" code since the upcall will simply loop
+ until the event handler no longer desires callbacks. This is
+ okay since multiple threads may dispatch event handlers (similar
+ to what the TP_Reactor does).
+
+ (close):
+
+ Cleaned up memory and resource leaks.
+
+ (handle_events_i, work_pending_i):
+
+ Moved "event polling" code to the new work_pending_i() method.
+ handle_events_i() now calls that method to determine if any
+ events must be dispatched.
+
+ If the underlying ioctl() call was interrupted (e.g. via the
+ INTR signal), i.e. returns -1 with errno set to EINTR, then
+ automatically restart the event loop if so desired by the user.
+
+ (work_pending):
+
+ Implemented this method. It simply grabs the reactor lock and
+ calls the new work_pending_i() method.
+
+ (dispatch_io_events):
+
+ Call the remove_handler() method that acquires the lock instead
+ of the one doesn't. The lock must be reacquired since reactor
+ state will potentially change during an upcall and since the
+ lock was released prior to dispatching the upcall. Fixes a race
+ condition.
+
+ Directly use pollfd pointers as the loop variables instead of an
+ integer. No need for the additional indirection.
+
+ Since the underlying event demultiplexing mechansim (`/dev/poll'
+ or '/dev/epoll') is stateful, and since only one result buffer
+ is used, all pending events (i.e. those retrieved from a
+ previous poll) must be dispatched before any additional event
+ can be polled. As such, the Dev_Poll_Reactor keeps track of the
+ progress of events that have been dispatched.
+
+ The semantics of the event loop in the presence of multiple
+ threads is non-trivial. The "start point" of the loop will be
+ incremented each time an event handler is dispatched, which may
+ be done across multiple threads. Multiple threads may change
+ the loop variables. Care must be taken to only change those
+ variables with the reactor lock held.
+
+ (dispatch_timer_handlers):
+
+ Release the reactor lock during the upcall. Fixes a potential
+ deadlock.
+
Thu May 2 10:35:25 2002 Phil Mesnier <mesnier_p@ociweb.com>
* ace/Log_Msg.cpp: ACE_Log_Msg::open() did not properly initialize a
diff --git a/ace/Dev_Poll_Reactor.cpp b/ace/Dev_Poll_Reactor.cpp
index 019975b174c..d357701098f 100644
--- a/ace/Dev_Poll_Reactor.cpp
+++ b/ace/Dev_Poll_Reactor.cpp
@@ -1032,117 +1032,178 @@ ACE_Dev_Poll_Reactor::close (void)
result = ACE_OS::close (this->poll_fd_);
}
+ if (this->delete_signal_handler_)
+ {
+ delete this->signal_handler_;
+ this->signal_handler_ = 0;
+ this->delete_signal_handler_ = 0;
+ }
+
+ (void) this->handler_rep_.close ();
+
+ if (this->delete_timer_queue_)
+ {
+ delete this->timer_queue_;
+ this->timer_queue_ = 0;
+ this->delete_timer_queue_ = 0;
+ }
+
+ if (this->notify_handler_ != 0)
+ this->notify_handler_->close ();
+
+ if (this->delete_notify_handler_)
+ {
+ delete this->notify_handler_;
+ this->notify_handler_ = 0;
+ this->delete_notify_handler_ = 0;
+ }
+
this->poll_fd_ = ACE_INVALID_HANDLE;
+ this->start_pfds_ = 0;
+ this->end_pfds_ = 0;
+ this->initialized_ = 0;
return result;
}
int
-ACE_Dev_Poll_Reactor::work_pending (const ACE_Time_Value & /* max_wait_time */)
+ACE_Dev_Poll_Reactor::work_pending (const ACE_Time_Value & max_wait_time)
{
ACE_TRACE ("ACE_Dev_Poll_Reactor::work_pending");
- // /dev/epoll is a "state change" interface, not a "state
- // monitoring" interface. This means that it is not possible to
- // provide the semantics required by this method.
- ACE_NOTSUP_RETURN (-1);
-}
-
-int
-ACE_Dev_Poll_Reactor::handle_events (ACE_Time_Value *max_wait_time)
-{
- ACE_TRACE ("ACE_Dev_Poll_Reactor::handle_events");
-
// Stash the current time
//
// The destructor of this object will automatically compute how much
// time elapsed since this method was called.
- ACE_Countdown_Time countdown (max_wait_time);
+ ACE_Time_Value mwt (max_wait_time);
+ ACE_MT (ACE_Countdown_Time countdown (&mwt));
ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, -1));
- if (this->deactivated_)
- return -1;
-
// Update the countdown to reflect time waiting for the mutex.
ACE_MT (countdown.update ());
- return this->handle_events_i (max_wait_time);
+ return this->work_pending_i (mwt);
}
int
-ACE_Dev_Poll_Reactor::handle_events_i (ACE_Time_Value *max_wait_time)
+ACE_Dev_Poll_Reactor::work_pending_i (ACE_Time_Value & max_wait_time)
{
- ACE_TRACE ("ACE_Dev_Poll_Reactor::handle_events_i");
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::work_pending_i");
- int io_handlers_dispatched = 0;
+ if (this->deactivated_)
+ return 0;
- // Dispatch all "ready" events before polling for events.
- if (this->ready_set_.nfds > 0
- && this->dispatch_io_events (this->ready_set_.pfds,
- this->ready_set_.nfds,
- io_handlers_dispatched) != 0)
- return -1;
+ if (this->start_pfds_ != this->end_pfds_)
+ return 1; // We still have work_pending() do not poll for
+ // additional events.
- // Check if additional events are "ready" before polling.
- if (this->ready_set_.nfds == 0)
- {
- ACE_Time_Value timer_buf (0);
- ACE_Time_Value *this_timeout = 0;
+ ACE_Time_Value timer_buf (0);
+ ACE_Time_Value *this_timeout = 0;
- this_timeout = this->timer_queue_->calculate_timeout (max_wait_time,
- &timer_buf);
+ this_timeout = this->timer_queue_->calculate_timeout (&max_wait_time,
+ &timer_buf);
- long timeout =
- (this_timeout == 0 ? -1 /* Infinity */ : this_timeout->msec ());
+ long timeout =
+ (this_timeout == 0 ? -1 /* Infinity */ : this_timeout->msec ());
#if defined (ACE_HAS_EVENT_POLL)
- struct evpoll evp;
+ struct evpoll evp;
- evp.ep_timeout = timeout; // Milliseconds
- evp.ep_resoff = 0;
+ evp.ep_timeout = timeout; // Milliseconds
+ evp.ep_resoff = 0;
- // Poll for events
- int nfds = ACE_OS::ioctl (this->poll_fd_, EP_POLL, &evp);
+ // Poll for events
+ int nfds = ACE_OS::ioctl (this->poll_fd_, EP_POLL, &evp);
- if (nfds > 0)
- ACE_DEBUG ((LM_DEBUG, "%%%%%% RECEIVED EVENTS ON %d handles.\n",
- nfds));
+ if (nfds > 0)
+ ACE_DEBUG ((LM_DEBUG, "%%%%%% RECEIVED EVENTS ON %d handles.\n",
+ nfds));
- // Retrieve the results from the memory map.
- struct pollfd *pfds =
- ACE_reinterpret_cast (struct pollfd *,
- this->mmap_ + evp.ep_resoff);
+ // Retrieve the results from the memory map.
+ this->start_pfds_ =
+ ACE_reinterpret_cast (struct pollfd *,
+ this->mmap_ + evp.ep_resoff);
#else
- struct dvpoll dvp;
+ struct dvpoll dvp;
- dvp.dp_fds = this->dp_fds_;
- dvp.dp_nfds = this->size_;
- dvp.dp_timeout = timeout; // Milliseconds
+ dvp.dp_fds = this->dp_fds_;
+ dvp.dp_nfds = this->size_;
+ dvp.dp_timeout = timeout; // Milliseconds
- // Poll for events
- int nfds = ACE_OS::ioctl (this->poll_fd_, DP_POLL, &dvp);
+ // Poll for events
+ int nfds = ACE_OS::ioctl (this->poll_fd_, DP_POLL, &dvp);
- // Retrieve the results from the pollfd array.
- struct pollfd *pfds = dvp.dp_fds;
+ // Retrieve the results from the pollfd array.
+ this->start_pfds_ = dvp.dp_fds;
#endif /* ACE_HAS_EVENT_POLL */
- return this->dispatch (pfds,
- nfds);
+ // If nfds == 0 then end_pfds_ == start_pfds_ meaning that there is
+ // no work pending. If nfds > 0 then there is work pending.
+ // Otherwise an error occurred.
+ if (nfds > -1)
+ this->end_pfds_ = this->start_pfds_ + nfds;
+
+ return (nfds > 0 ? 1 : nfds);
+}
+
+
+int
+ACE_Dev_Poll_Reactor::handle_events (ACE_Time_Value *max_wait_time)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::handle_events");
+
+ // Stash the current time
+ //
+ // The destructor of this object will automatically compute how much
+ // time elapsed since this method was called.
+ ACE_MT (ACE_Countdown_Time countdown (max_wait_time));
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, -1));
+
+ if (this->deactivated_)
+ return -1;
+
+ // Update the countdown to reflect time waiting for the mutex.
+ ACE_MT (countdown.update ());
+
+ return this->handle_events_i (max_wait_time);
+}
+
+int
+ACE_Dev_Poll_Reactor::handle_events_i (ACE_Time_Value *max_wait_time)
+{
+ ACE_TRACE ("ACE_Dev_Poll_Reactor::handle_events_i");
+
+ int result = 0;
+ int active_handle_count = 0;
+
+ // Poll for events
+ //
+ // If the underlying ioctl() call was interrupted via the interrupt
+ // signal (i.e. returned -1 with errno == EINTR) then the loop will
+ // be restarted if so desired.
+ do
+ {
+ result = this->work_pending_i (*max_wait_time);
}
+ while (result == -1 && this->restart_ != 0 && errno == EINTR);
- // this->state_changed_ = 1;
+ if (result == 0 || (result == -1 && errno == ETIME))
+ return 0;
+ else if (result == -1)
+ return -1;
- return io_handlers_dispatched;
+ // Dispatch the events, if any.
+ return this->dispatch ();
}
int
-ACE_Dev_Poll_Reactor::dispatch (struct pollfd *pfds,
- int active_handle_count)
+ACE_Dev_Poll_Reactor::dispatch (int active_handle_count)
{
ACE_TRACE ("ACE_Dev_Poll_Reactor::dispatch");
@@ -1224,9 +1285,7 @@ ACE_Dev_Poll_Reactor::dispatch (struct pollfd *pfds,
#endif /* 0 */
// Finally, dispatch the I/O handlers.
- else if (this->dispatch_io_events (pfds,
- active_handle_count,
- io_handlers_dispatched) == -1)
+ else if (this->dispatch_io_events (io_handlers_dispatched) == -1)
// State has changed, so exit loop.
break;
}
@@ -1237,14 +1296,18 @@ ACE_Dev_Poll_Reactor::dispatch (struct pollfd *pfds,
int
ACE_Dev_Poll_Reactor::dispatch_timer_handlers (
- int &number_of_handlers_dispatched)
+ int &number_of_timers_cancelled)
{
- number_of_handlers_dispatched += this->timer_queue_->expire ();
+ // Release the lock during the upcall.
+ ACE_Reverse_Lock<ACE_SYNCH_MUTEX> reverse_lock (this->lock_);
+ ACE_GUARD_RETURN (ACE_Reverse_Lock<ACE_SYNCH_MUTEX>,
+ reverse_guard,
+ reverse_lock,
+ -1);
-// if (this->state_changed_)
-// return -1;
-// else
- return 0;
+ number_of_timers_cancelled += this->timer_queue_->expire ();
+
+ return 0;
}
#if 0
@@ -1275,35 +1338,37 @@ ACE_Dev_Poll_Reactor::dispatch_notification_handlers (
#endif /* 0 */
int
-ACE_Dev_Poll_Reactor::dispatch_io_events (struct pollfd *pfds,
- int nfds,
- int &io_handlers_dispatched)
+ACE_Dev_Poll_Reactor::dispatch_io_events (int &io_handlers_dispatched)
{
- // nfds == 0 : timeout
- // nfds > 0 : number of file descriptors (all received events)
- // nfds < 0 : error
- if (nfds < 0)
- return -1;
-
- // Prepare the ready set to use the result buffer set by the ioctl()
- // poll call.
- this->ready_set_.pfds = pfds;
-
- // Reset the "ready" file descriptor count.
- this->ready_set_.nfds = 0;
+ // Since the underlying event demultiplexing mechansim (`/dev/poll'
+ // or '/dev/epoll') is stateful, and since only one result buffer is
+ // used, all pending events (i.e. those retrieved from a previous
+ // poll) must be dispatched before any additional event can be
+ // polled. As such, the Dev_Poll_Reactor keeps track of the
+ // progress of events that have been dispatched.
// Dispatch the events.
//
+ // The semantics of this loop in the presence of multiple threads is
+ // non-trivial. this->start_pfds_ will be incremented each time an
+ // event handler is dispatched, which may be done across multiple
+ // threads. Multiple threads may change the loop variables. Care
+ // must be taken to only change those variables with the reactor
+ // lock held.
+ //
// Notice that pfds only contains file descriptors that have
// received events.
- for (int i = 0; i < nfds; ++i, ++pfds)
+ for (struct pollfd *& pfds = this->start_pfds_;
+ pfds < this->end_pfds_;
+ /* Nothing to do before next loop iteration */)
{
const ACE_HANDLE handle = pfds->fd;
const short revents = pfds->revents;
- // Events to be dispatched the next time the ready set is
- // processed.
- short ready_set_events = 0;
+ // Increment the pointer to the next pollfd element before we
+ // release the lock. Otherwise event handlers end up being
+ // dispatched multiple times for the same poll.
+ ++pfds;
ACE_Event_Handler *eh = this->handler_rep_.find (handle);
@@ -1325,13 +1390,16 @@ ACE_Dev_Poll_Reactor::dispatch_io_events (struct pollfd *pfds,
{
ACE_DEBUG ((LM_DEBUG, "GOT POLLOUT EVENT\n"));
- status = eh->handle_output (handle);
+ int status =
+ this->upcall (eh, ACE_Event_Handler::handle_output, handle);
if (status < 0)
- return this->remove_handler_i (handle,
+ {
+ // Note that the lock is reacquired in
+ // remove_handler().
+ return this->remove_handler (handle,
ACE_Event_Handler::WRITE_MASK);
- else if (status > 0)
- ACE_SET_BITS (ready_set_events, POLLOUT);
+ }
io_handlers_dispatched++;
}
@@ -1341,13 +1409,16 @@ ACE_Dev_Poll_Reactor::dispatch_io_events (struct pollfd *pfds,
{
ACE_DEBUG ((LM_DEBUG, "GOT POLLPRI EVENT\n"));
- status = eh->handle_exception (handle);
+ int status =
+ this->upcall (eh, ACE_Event_Handler::handle_exception, handle);
if (status < 0)
- return this->remove_handler_i (handle,
+ {
+ // Note that the lock is reacquired in
+ // remove_handler().
+ return this->remove_handler (handle,
ACE_Event_Handler::EXCEPT_MASK);
- else if (status > 0)
- ACE_SET_BITS (ready_set_events, POLLPRI);
+ }
io_handlers_dispatched++;
}
@@ -1359,26 +1430,20 @@ ACE_Dev_Poll_Reactor::dispatch_io_events (struct pollfd *pfds,
// "GOT POLLIN EVENT ON HANDLE <%d>\n",
// handle));
- status = eh->handle_input (handle);
+ int status =
+ this->upcall (eh, ACE_Event_Handler::handle_input, handle);
if (status < 0)
- return this->remove_handler_i (handle,
+ {
+ // Note that the lock is reacquired in
+ // remove_handler().
+ return this->remove_handler (handle,
ACE_Event_Handler::READ_MASK);
- else if (status > 0)
- ACE_SET_BITS (ready_set_events, POLLIN);
+ }
io_handlers_dispatched++;
}
- }
-
- if (ready_set_events != 0)
- {
- // Notice that all events for pfds have been dispatched
- // at this point in time so overwriting its revents field is
- // safe.
- pfds->revents = ready_set_events;
- this->ready_set_.pfds[this->ready_set_.nfds++] = *pfds;
- }
+ } // The reactor lock is reacquired upon leaving this scope.
}
return 0;
@@ -1525,7 +1590,7 @@ ACE_Dev_Poll_Reactor::register_handler (const ACE_Handle_Set &handle_set,
return 0;
}
-
+
int
ACE_Dev_Poll_Reactor::register_handler (int signum,
ACE_Event_Handler *new_sh,
@@ -2128,6 +2193,9 @@ ACE_Dev_Poll_Reactor::owner (ACE_thread_t /* new_owner */,
{
ACE_TRACE ("ACE_Dev_Poll_Reactor::owner");
+ // There is no need to set the owner of the event loop. Multiple
+ // threads may invoke the event loop simulataneously.
+
return 0;
}
@@ -2136,6 +2204,9 @@ ACE_Dev_Poll_Reactor::owner (ACE_thread_t * /* owner */)
{
ACE_TRACE ("ACE_Dev_Poll_Reactor::owner");
+ // There is no need to set the owner of the event loop. Multiple
+ // threads may invoke the event loop simulataneously.
+
return 0;
}
@@ -2321,6 +2392,7 @@ ACE_Dev_Poll_Reactor::dump (void) const
ACE_TRACE ("ACE_Dev_Poll_Reactor::dump");
ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("restart_ = %d\n"), this->restart_));
ACE_DEBUG ((LM_DEBUG,
ACE_LIB_TEXT ("initialized_ = %d"),
this->initialized_));
diff --git a/ace/Dev_Poll_Reactor.h b/ace/Dev_Poll_Reactor.h
index 662d437d7cd..5a3615ee2e7 100644
--- a/ace/Dev_Poll_Reactor.h
+++ b/ace/Dev_Poll_Reactor.h
@@ -88,12 +88,13 @@ public:
* counted event handlers need not pay for reference counting
* resources.
*/
- size_t refcount;
+ unsigned long refcount;
};
// ---------------------------------------------------------------------
+#if 0
/**
* @class ACE_Dev_Poll_Ready_Set
*
@@ -135,6 +136,7 @@ public:
int nfds;
};
+#endif /* 0 */
// ---------------------------------------------------------------------
@@ -376,14 +378,14 @@ public:
/**
* @return Returns the updated reference count.
*/
- size_t add_ref (ACE_HANDLE handle);
+ unsigned long add_ref (ACE_HANDLE handle);
/// Decrease the reference count on the event handler corresponding
/// to the given file descriptor.
/**
* @return Returns the updated reference count.
*/
- size_t remove_ref (ACE_HANDLE handle);
+ unsigned long remove_ref (ACE_HANDLE handle);
//@}
/**
@@ -864,25 +866,50 @@ public:
/// Returns a reference to the Reactor's internal lock.
virtual ACE_Lock &lock (void);
- /// Wake up all threads in waiting in the event loop
+ /// Wake up all threads waiting in the event loop.
virtual void wakeup_all_threads (void);
/// Transfers ownership of Reactor_Impl to the new_owner.
+ /**
+ * @note There is no need to set the owner of the event loop for the
+ * ACE_Dev_Poll_Reactor. Multiple threads may invoke the
+ * event loop simulataneously. As such, this method is a
+ * no-op.
+ */
virtual int owner (ACE_thread_t new_owner, ACE_thread_t *old_owner = 0);
/// Return the ID of the "owner" thread.
+ /**
+ * @note There is no need to set the owner of the event loop for the
+ * ACE_Dev_Poll_Reactor. Multiple threads may invoke the
+ * event loop simulataneously. As such, this method is a
+ * no-op.
+ */
virtual int owner (ACE_thread_t *owner);
/// Get the existing restart value.
virtual int restart (void);
/// Set a new value for restart and return the original value.
+ /**
+ * @param r If zero, then the event loop will not be automatically
+ * restarted if the underlying poll is interrupted via the
+ * INTR (interrupt) signal.
+ *
+ * @return Returns the previous "restart" value.
+ */
virtual int restart (int r);
/// Set position of the owner thread.
+ /**
+ * @note This is currently a no-op.
+ */
virtual void requeue_position (int);
/// Get position of the owner thread.
+ /**
+ * @note This is currently a no-op.
+ */
virtual int requeue_position (void);
/**
@@ -914,9 +941,6 @@ public:
* @name Low-level ready_set mask manipulation methods
*
* These methods are unimplemented.
- * @par
- * As implemented, the ready_set may only be indirectly manipulated
- * by returning a value greater than zero from an event handler.
*/
//@{
@@ -941,6 +965,17 @@ public:
protected:
+ /// Non-locking version of wait_pending().
+ /**
+ * Returns non-zero if there are I/O events "ready" for dispatching,
+ * but does not actually dispatch the event handlers. By default,
+ * don't block while checking this, i.e., "poll".
+ *
+ * @note It is only possible to achieve millisecond timeout
+ * resolutions with the ACE_Dev_Poll_Reactor.
+ */
+ int work_pending_i (ACE_Time_Value &max_wait_time);
+
/// Poll for events and return the number of event handlers that
/// were dispatched.
/**
@@ -948,8 +983,13 @@ protected:
*/
int handle_events_i (ACE_Time_Value *max_wait_time);
+ /// Perform the upcall with the given event handler method.
+ int upcall (ACE_Event_Handler *event_handler,
+ int (ACE_Event_Handler::*callback)(ACE_HANDLE),
+ ACE_HANDLE handle);
+
/**
- * Dispatche ACE_Event_Handlers for time events, I/O events, and
+ * Dispatch ACE_Event_Handlers for time events, I/O events, and
* signal events. Returns the total number of ACE_Event_Handlers
* that were dispatched or -1 if something goes wrong.
*/
@@ -1009,17 +1049,19 @@ protected:
/// Track HANDLES we are interested in for various events that must
/// be dispatched *without* polling.
- ACE_Dev_Poll_Ready_Set ready_set_;
+ /// ACE_Dev_Poll_Ready_Set ready_set_;
#if defined (ACE_HAS_EVENT_POLL)
- /// The memory map to which `/dev/poll' or `/dev/poll' will feed its
- /// results.
+ /// The memory map that `/dev/epoll' will feed its results to.
char *mmap_;
#else
- ///
+ /// The pollfd array that `/dev/poll' will feed its results to.
struct pollfd *dp_fds_;
#endif /* ACE_HAS_EVENT_POLL */
+ /// Pointer to the array
+ struct pollfd *pfds_;
+
/// This flag is used to keep track of whether we are actively handling
/// events or not.
sig_atomic_t deactivated_;
diff --git a/ace/Dev_Poll_Reactor.inl b/ace/Dev_Poll_Reactor.inl
index d7642eede2a..74ff5c2dc2a 100644
--- a/ace/Dev_Poll_Reactor.inl
+++ b/ace/Dev_Poll_Reactor.inl
@@ -13,13 +13,14 @@ ACE_Dev_Poll_Event_Tuple::ACE_Dev_Poll_Event_Tuple (void)
// ---------------------------------------------------------------------
-
+#if 0
ACE_INLINE
ACE_Dev_Poll_Ready_Set::ACE_Dev_Poll_Ready_Set (void)
: pfds (0),
nfds (0)
{
}
+#endif /* 0 */
// ---------------------------------------------------------------------
@@ -90,7 +91,7 @@ ACE_Dev_Poll_Reactor_Handler_Repository::size (void) const
return this->max_size_;
}
-ACE_INLINE size_t
+ACE_INLINE unsigned long
ACE_Dev_Poll_Reactor_Handler_Repository::add_ref (ACE_HANDLE handle)
{
// ACE_TRACE ("ACE_Dev_Poll_Reactor_Handler_Repository::add_ref");
@@ -103,7 +104,7 @@ ACE_Dev_Poll_Reactor_Handler_Repository::add_ref (ACE_HANDLE handle)
return 0;
}
-ACE_INLINE size_t
+ACE_INLINE unsigned long
ACE_Dev_Poll_Reactor_Handler_Repository::remove_ref (ACE_HANDLE handle)
{
// ACE_TRACE ("ACE_Dev_Poll_Reactor_Handler_Repository::remove_ref");
@@ -112,7 +113,7 @@ ACE_Dev_Poll_Reactor_Handler_Repository::remove_ref (ACE_HANDLE handle)
if (this->handle_in_range (handle))
{
- size_t & refcount = this->handlers_[handle].refcount;
+ unsigned long & refcount = this->handlers_[handle].refcount;
ACE_ASSERT (refcount > 0);
@@ -177,3 +178,24 @@ ACE_Dev_Poll_Handler_Guard::~ACE_Dev_Poll_Handler_Guard (void)
* dispatch the handler.
*/
}
+
+// ---------------------------------------------------------------------
+
+ACE_INLINE int
+ACE_Dev_Poll_Reactor::upcall (ACE_Event_Handler *event_handler,
+ int (ACE_Event_Handler::*callback)(ACE_HANDLE),
+ ACE_HANDLE handle)
+{
+ // If the handler returns positive value (requesting a reactor
+ // callback) just call back as many times as the handler requests
+ // it. Other threads are off handling other things.
+ int status = 0;
+
+ do
+ {
+ status = (event_handler->*callback) (handle);
+ }
+ while (status > 0);
+
+ return status;
+}