summaryrefslogtreecommitdiff
path: root/ace/XtReactor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ace/XtReactor.cpp')
-rw-r--r--ace/XtReactor.cpp327
1 files changed, 327 insertions, 0 deletions
diff --git a/ace/XtReactor.cpp b/ace/XtReactor.cpp
new file mode 100644
index 00000000000..ac497c64e40
--- /dev/null
+++ b/ace/XtReactor.cpp
@@ -0,0 +1,327 @@
+// XtReactor.cpp
+// $Id$
+
+#define ACE_BUILD_DLL
+#include "ace/Log_Msg.h"
+#include "ace/Synch_T.h"
+#include "ace/SOCK_Acceptor.h"
+#include "ace/SOCK_Connector.h"
+#include "ace/XtReactor.h"
+
+#if defined (ACE_HAS_XT)
+
+struct ACE_XtReactorID
+{
+ XtInputId id;
+ int good_id;
+};
+
+ACE_ALLOC_HOOK_DEFINE (ACE_XtReactor)
+
+// Must be called with lock held
+ACE_XtReactor::ACE_XtReactor (XtAppContext context,
+ size_t size,
+ int restart,
+ ACE_Sig_Handler *h)
+ : ACE_Reactor (size, restart, h),
+ context_ (context),
+ id_len_ (0),
+ ids_ (0)
+{
+}
+
+ACE_XtReactor::~ACE_XtReactor (void)
+{
+ delete this->ids_;
+}
+
+// This is just the wait_for_multiple_events from ace/Reactor.cpp but
+// we use the Xt functions to wait for an event, not select ()
+//
+// FIXME - someday re-write this to use poll as well.
+
+int
+ACE_XtReactor::wait_for_multiple_events (ACE_Handle_Set &rmask,
+ ACE_Handle_Set &wmask,
+ ACE_Handle_Set &emask,
+ ACE_Time_Value *max_wait_time)
+{
+ ACE_TRACE ("ACE_Reactor::wait_for_multiple_events");
+#if defined (ACE_USE_POLL)
+ u_long width = 0;
+#endif /* ACE_USE_POLL */
+ int nfound;
+
+ do
+ {
+ max_wait_time = this->timer_queue_->calculate_timeout (max_wait_time);
+
+#if defined (ACE_USE_POLL)
+ pollfd *phandles = this->handle_sets_to_poll_fds (width);
+ nfound = ACE_OS::poll (phandles, width, max_wait_time);
+#else /* USE SELECT */
+ size_t width = this->handler_rep_.max_handlep1 ();
+ rmask = this->rd_handle_mask_;
+ wmask = this->wr_handle_mask_;
+ emask = this->ex_handle_mask_;
+#if 0
+ nfound = ACE_OS::select (int (width), rmask, wmask, emask, max_wait_time);
+#else
+ nfound = XtWaitForMultipleEvents (width, rmask, wmask, emask, max_wait_time);
+#endif
+#endif /* ACE_USE_POLL */
+ } while (nfound == -1 && this->handle_error () > 0);
+
+#if defined (ACE_USE_POLL)
+ this->poll_fds_to_handle_sets (width, rmask, wmask, emask, nfound);
+#endif /* ACE_USE_POLL */
+
+ if (nfound > 0)
+ {
+#if !defined (ACE_WIN32)
+ rmask.sync (this->handler_rep_.max_handlep1 ());
+ wmask.sync (this->handler_rep_.max_handlep1 ());
+ emask.sync (this->handler_rep_.max_handlep1 ());
+#endif /* ACE_REACTOR_ALTERANTIVE_IMPL */
+ }
+ return nfound; // Timed out or input available
+}
+
+void
+ACE_XtReactor::TimerCallbackProc (XtPointer closure, XtIntervalId *id)
+{
+ ACE_XtReactor *self = (ACE_XtReactor*)closure;
+ self->timeout_ = 0;
+
+ ACE_DEBUG ((LM_DEBUG, "ACE_XtReactor::Timer on id %d\n", (int) *id));
+
+ ACE_Time_Value zero = ACE_Time_Value::zero; // my copy isn't const
+
+ // Deal with any timer events
+ ACE_Handle_Set r, w, e;
+ self->dispatch (0, r, w, e);
+ self->reset_timeout ();
+}
+
+// This could be made shorter if we know which *kind* of event we
+// were about to get. Here we use select () to find out which one
+// might be available.
+
+void ACE_XtReactor::InputCallbackProc (XtPointer closure,
+ int * source,
+ XtInputId *id)
+{
+ ACE_XtReactor * self = (ACE_XtReactor*)closure;
+
+ ACE_DEBUG ((LM_DEBUG, "ACE_XtReactor::Input on fd %d\n", *source));
+
+ ACE_Time_Value zero = ACE_Time_Value::zero; // my copy isn't const
+
+ ACE_Handle_Set r, w, e;
+ ACE_Handle_Set r2, w2, e2;
+
+ // Deal with one file event
+
+ // - read which kind of event
+ if (self->rd_handle_mask_.is_set (*source))
+ r.set_bit (*source);
+ if (self->wr_handle_mask_.is_set (*source))
+ w.set_bit (*source);
+ if (self->ex_handle_mask_.is_set (*source))
+ e.set_bit (*source);
+
+ int result = ACE_OS::select (*source+1, r, w, e, &zero);
+
+ // - Use only that one file event (removes events for other files)
+ if (result > 0)
+ {
+ if (r.is_set (*source))
+ r2.set_bit (*source);
+ if (w.is_set (*source))
+ w2.set_bit (*source);
+ if (e.is_set (*source))
+ e2.set_bit (*source);
+
+ self->dispatch (1, r2, w2, e2);
+ }
+}
+
+int ACE_XtReactor::XtWaitForMultipleEvents (int width,
+ ACE_Handle_Set &rmask,
+ ACE_Handle_Set &wmask,
+ ACE_Handle_Set &emask,
+ ACE_Time_Value *max_wait_time)
+{
+ // Check to make sure our fd's are all usable
+
+ ACE_Handle_Set r (rmask), w (wmask), e (emask);
+ ACE_Time_Value zero = ACE_Time_Value::zero; // my copy isn't const
+ int result = ACE_OS::select (width, r, w, e, &zero);
+
+ if (result < 0) // Bad file arguments...
+ return result;
+
+ // Instead of waiting using select, just use the Xt mechanism to wait
+ // for a single event.
+
+ // Wait for something to happen.
+ XtAppProcessEvent (context_, XtIMAll);
+
+ // Now actually read the result needed by the Reactor using select.
+ result = ACE_OS::select (int (width), rmask, wmask, emask, &zero);
+ return result;
+}
+
+XtAppContext ACE_XtReactor::context (void)
+{
+ return this->context_;
+}
+
+int
+ACE_XtReactor::attach (ACE_HANDLE handle,
+ ACE_Event_Handler *handler,
+ ACE_Reactor_Mask mask)
+{
+ ACE_TRACE ("ACE_XtReactor::attach");
+
+ ACE_DEBUG ((LM_DEBUG, "+++%d\n", handle));
+
+ int result = ACE_Reactor::attach (handle, handler, mask);
+
+ if (result < 0)
+ return -1;
+
+ // Ensure the list of InputId's is big enough
+ if (ids_ == 0 || id_len_ < handle + 1)
+ {
+ ACE_XtReactorID *more;
+ ACE_NEW_RETURN (more, ACE_XtReactorID[handle + 1], -1);
+ int i;
+ for (i = 0; i < this->id_len_; i++)
+ more[i] = ids_[i];
+ for (i = this->id_len_; i < handle + 1; i++)
+ more[i].good_id = 0;
+ id_len_ = handle + 1;
+ delete this->ids_;
+ ids_ = more;
+ }
+
+ int condition = 0;
+ if (mask & ACE_Event_Handler::READ_MASK)
+ condition |= XtInputReadMask;
+ if (mask & ACE_Event_Handler::WRITE_MASK)
+ condition |= XtInputWriteMask;
+ if (mask & ACE_Event_Handler::EXCEPT_MASK)
+ condition |= XtInputExceptMask;
+ if (condition != 0)
+ {
+ if (ids_[handle].good_id)
+ XtRemoveInput (ids_[handle].id);
+
+ ids_[handle].id = XtAppAddInput (context_,
+ handle,
+ (XtPointer)condition,
+ InputCallbackProc,
+ (XtPointer)this);
+ ids_[handle].good_id = 1;
+ }
+ return 0;
+}
+
+
+int
+ACE_XtReactor::detach (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask)
+{
+ ACE_TRACE ("ACE_XtReactor::detach");
+ ACE_DEBUG ((LM_DEBUG, "---%d\n", handle));
+
+ int result = ACE_Reactor::detach (handle, mask);
+
+ if (handle <= id_len_)
+ {
+ if (ids_[handle].good_id)
+ XtRemoveInput (ids_[handle].id);
+ else
+ ACE_DEBUG ((LM_DEBUG, "Handle id is not good %d\n", handle));
+ ids_[handle].good_id = 0;
+ }
+ else
+ ACE_DEBUG ((LM_DEBUG, "Handle out of range %d\n", handle));
+
+ if (result < 0)
+ return result;
+ else
+ return 0;
+}
+
+// The following functions ensure that there is an Xt timeout for the
+// first timeout in the Reactor's Timer_Queue.
+
+void ACE_XtReactor::reset_timeout (void)
+{
+ if (timeout_)
+ XtRemoveTimeOut (timeout_);
+ timeout_ = 0;
+
+ ACE_Time_Value *max_wait_time;
+ max_wait_time = this->timer_queue_->calculate_timeout (0);
+
+ if (max_wait_time)
+ {
+ ACE_DEBUG ((LM_DEBUG, " %ld\n", max_wait_time->msec ()));
+
+ timeout_ =
+ XtAppAddTimeOut (context_, max_wait_time->msec (),
+ TimerCallbackProc, (XtPointer) this);
+ }
+}
+
+int
+ACE_XtReactor::schedule_timer (ACE_Event_Handler *handler,
+ const void *arg,
+ const ACE_Time_Value &delta_time,
+ const ACE_Time_Value &interval)
+{
+ ACE_TRACE ("ACE_XtReactor::schedule_timer");
+ ACE_GUARD_RETURN (ACE_REACTOR_MUTEX, ace_mon, this->token_, -1);
+
+ int result =
+ ACE_Reactor::schedule_timer (handler, arg, delta_time, interval);
+
+ if (result < 0)
+ return result;
+
+ this->reset_timeout ();
+ return 0;
+}
+
+int
+ACE_XtReactor::cancel_timer (ACE_Event_Handler *handler)
+{
+ ACE_TRACE ("ACE_XtReactor::cancel_timer");
+
+ int result = ACE_Reactor::cancel_timer (handler);
+
+ if (result < 0)
+ return -1;
+
+ this->reset_timeout ();
+ return 0;
+}
+
+int
+ACE_XtReactor::cancel_timer (int timer_id, const void **arg)
+{
+ ACE_TRACE ("ACE_XtReactor::cancel_timer");
+
+ int result = ACE_Reactor::cancel_timer (timer_id, arg);
+
+ if (result < 0)
+ return -1;
+
+ this->reset_timeout ();
+ return 0;
+}
+
+#endif /* ACE_HAS_XT */