ACE之ACE_Reactor

简介

ACE_Reactor实现了reactor模式,其使用了桥接设计模式,实现类的抽象为ACE_Reactor_Impl

结构

bind(ACE_Select_Reactor_Token)
ACE_Reactor
ACE_Reactor_Timer_Interface
ACE_Reactor_Impl
ACE_Select_Reactor_Impl
ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>
ACE_TP_Reactor
ACE_Dev_Poll_Reactor
ACE_WFMO_Reactor
ACE_Msg_WFMO_Reactor
ACE_QtReactor
ACE_Select_Reactor
ACE_Reactor_Notify
ACE_Dev_Poll_Reactor_Notify
ACE_Select_Reactor_Notify
ACE_WFMO_Reactor_Notify
ACE_Priority_Reactor
ACE_XtReactor
ACE_FlReactor
ACE_TkReactor

主要包含下面几类接口

  • 初始化
    • open
    • set_sig_handler
    • timer_queue
    • close
  • 事件循环
    • run_event_loop(静态方法)
    • run_alertable_event_loop(静态方法)
    • end_event_loop(静态方法)
    • reset_event_loop(静态方法)
    • run_reactor_event_loop
    • run_alertable_reactor_event_loop
    • end_reactor_event_loop
    • handle_events
    • alertable_handle_events
  • 管理事件
    • register_handler
    • remove_handler
    • suspend_handler
    • resume_handler
  • 定时器调度
    • schedule_timer
    • reset_timer_interval
    • cancel_timer
  • 通知
    • notify
    • max_notify_iterations
    • purge_pending_notifications

ACE_Reactor_Impl 的实现类有以下几种

  • ACE_Select_Reactor_Impl:ready_set_表示已经就绪的io句柄(不需要通过select),wait_set_表示调用select之前的io句柄集,dipatch_set_表示通过select后满足的io句柄,是在ACE_Select_Reactor_T中是如此,而在ACE_TP_Reactor是通过ready_set_
    • ACE_Select_Reactor_T:要求在Reactor持有线程内运行,suspend_handler是将句柄从wait_set_和dipatch_set_清除,添加到suspend_set_中,resume_handler是将句柄从suspend_set_删除,添加到wait_set_中
      • ACE_TP_Reactor:在没有事件时,会调用select得到事件句柄集,单个线程会处理一个事件,如果事件句柄集中还有没有处理的,则其它线程则直接从事件句柄集中分发
      • ACE_QtReactor
      • ACE_XtReactor
      • ACE_FlReactor
      • ACE_TkReactor
      • ACE_Priority_Reactor
  • ACE_Dev_Poll_Reactor:suspend_handler是使用EPOLL_CTL_DEL将句柄从内核中删除,同时设置Event_Tuple的controlled标识为false,suspended标识为true,resume_handler则是与suspend_handler相反
  • ACE_WFMO_Reactor
  • ACE_Msg_WFMO_Reactor

通知唤醒ACE_Reactor是通过ACE_Reactor_Notify,不同的ACE_Reactor_Impl实现类有各自不同的通知实现类,主要包含如下

  • ACE_Dev_Poll_Reactor_Notify
  • ACE_Select_Reactor_Notify
  • ACE_WFMO_Reactor_Notify

ACE_Reactor事件循环,以ACE_Dev_Poll_Reactor为例

ACE_Reactor ACE_Reactor_Impl ACE_Dev_Poll_Reactor run_reactor_event_loop reactor_event_loop_done handle_events handle_events_i work_pending_i dispatch result result loop [result >= 0] ACE_Reactor ACE_Reactor_Impl ACE_Dev_Poll_Reactor

什么时候handle_events返回小于0呢?

  • reactor处理未激活状态时
  • 中断时,信号处理没有处理

ACE_Reactor_Impl

抽象类

«Abstract»
ACE_Reactor_Impl
+int open(size_t size,bool restart = false,ACE_Sig_Handler * = 0,ACE_Timer_Queue * = 0,int disable_notify_pipe = 0,ACE_Reactor_Notify * = 0)
+int current_info(ACE_HANDLE, size_t & /* size */)
+int set_sig_handler(ACE_Sig_Handler *signal_handler)
+int timer_queue(ACE_Timer_Queue *tq)
+ACE_Timer_Queue *timer_queue(void)
+int close(void)
+int work_pending(const ACE_Time_Value &max_wait_time = ACE_Time_Value::zero)
+int handle_events(ACE_Time_Value *max_wait_time = 0)
+int alertable_handle_events(ACE_Time_Value *max_wait_time = 0)
+int handle_events(ACE_Time_Value &max_wait_time)
+int alertable_handle_events(ACE_Time_Value &max_wait_time)
+int deactivated(void)
+void deactivate(int do_stop)
+int register_handler(ACE_Event_Handler *event_handler,ACE_Reactor_Mask mask)
+int register_handler(ACE_HANDLE io_handle,ACE_Event_Handler *event_handler,ACE_Reactor_Mask mask)
+int register_handler(ACE_HANDLE event_handle,ACE_HANDLE io_handle,ACE_Event_Handler *event_handler,ACE_Reactor_Mask mask)
+int register_handler(const ACE_Handle_Set &handles, ACE_Event_Handler *event_handler,ACE_Reactor_Mask mask)
+int register_handler(int signum,ACE_Event_Handler *new_sh,ACE_Sig_Action *new_disp = 0,ACE_Event_Handler **old_sh = 0,ACE_Sig_Action *old_disp = 0)
+int register_handler(const ACE_Sig_Set &sigset,ACE_Event_Handler *new_sh,ACE_Sig_Action *new_disp = 0)
+int remove_handler(ACE_Event_Handler *event_handler,ACE_Reactor_Mask mask)
+int remove_handler(ACE_HANDLE handle,ACE_Reactor_Mask mask)
+int remove_handler(const ACE_Handle_Set &handle_set,ACE_Reactor_Mask mask)
+int remove_handler(int signum, ACE_Sig_Action *new_disp,ACE_Sig_Action *old_disp = 0,int sigkey = -1)
+int remove_handler(const ACE_Sig_Set &sigset)
+int suspend_handler(ACE_Event_Handler *event_handler)
+int suspend_handler(ACE_HANDLE handle)
+int suspend_handler(const ACE_Handle_Set &handles)
+int suspend_handlers(void)
+int resume_handler(ACE_Event_Handler *event_handler)
+int resume_handler(ACE_HANDLE handle)
+int resume_handler(const ACE_Handle_Set &handles)
+int resume_handlers(void)
+int resumable_handler(void)
+bool uses_event_associations(void)
+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)
+int reset_timer_interval(long timer_id,const ACE_Time_Value &interval)
+int cancel_timer(ACE_Event_Handler *event_handler,int dont_call_handle_close = 1)
+int cancel_timer(long timer_id,const void **arg = 0, int dont_call_handle_close = 1)
+int schedule_wakeup(ACE_Event_Handler *event_handler,ACE_Reactor_Mask masks_to_be_added)
+int schedule_wakeup(ACE_HANDLE handle,ACE_Reactor_Mask masks_to_be_added)
+int cancel_wakeup(ACE_Event_Handler *event_handler, ACE_Reactor_Mask masks_to_be_cleared)
+int cancel_wakeup(ACE_HANDLE handle,ACE_Reactor_Mask masks_to_be_cleared)
+int notify(ACE_Event_Handler *event_handler = 0,ACE_Reactor_Mask mask = ACE_Event_Handler::EXCEPT_MASK,ACE_Time_Value * = 0)
+void max_notify_iterations(int)
+int max_notify_iterations(void)
+int purge_pending_notifications(ACE_Event_Handler * = 0,ACE_Reactor_Mask = ACE_Event_Handler::ALL_EVENTS_MASK)
+ACE_Event_Handler *find_handler(ACE_HANDLE handle)
+int handler(ACE_HANDLE handle,ACE_Reactor_Mask mask, ACE_Event_Handler **event_handler = 0)
+int handler(int signum,ACE_Event_Handler ** = 0)
+bool initialized(void)
+size_t size(void)
+ACE_Lock &lock(void)
+void wakeup_all_threads(void)
+int owner(ACE_thread_t new_owner, ACE_thread_t *old_owner = 0)
+int owner(ACE_thread_t *owner)
+bool restart(void)
+bool restart(bool r)
+void requeue_position(int)
+int requeue_position(void)
+int mask_ops(ACE_Event_Handler *event_handler,ACE_Reactor_Mask mask, int ops)
+int mask_ops(ACE_HANDLE handle,ACE_Reactor_Mask mask,int ops)
+int ready_ops(ACE_Event_Handler *event_handler,ACE_Reactor_Mask mask, int ops)
+int ready_ops(ACE_HANDLE handle,ACE_Reactor_Mask,int ops)
+void dump(void)

ACE_Select_Reactor_Impl

使用select作为io复用的reactor

ACE_Select_Reactor_Impl
#ACE_Select_Reactor_Handler_Repository handler_rep_
#ACE_Select_Reactor_Handle_Set dispatch_set_
#ACE_Select_Reacor_Handle_Set wait_set_
#ACE_Select_Reacor_Handle_Set suspend_set_
#ACE_Select_Reactor_Handle_Set ready_set_
#ACE_Timer_Queue *timer_queue_
#ACE_Sig_Handler *signal_handler_
#ACE_Reactor_Notify *notify_handler_
# ACE_thread_t owner_
ACE_Select_Reactor_Handler_Repository
- ACE_Array_Base<ACE_Event_Handler *> event_handlers_
- ACE_Select_Reactor_Impl &select_reactor_
ACE_Select_Reactor_Handle_Set
+ ACE_Handle_Set rd_mask_
+ ACE_Handle_Set wr_mask_
+ ACE_Handle_Set ex_mask_
ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>

owner_:创建ACE_Select_Reactor_Impl 的线程
ACE_Select_Reactor_T在handle_events_i时

template <class ACE_SELECT_REACTOR_TOKEN> int
ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::handle_events_i
  (ACE_Time_Value *max_wait_time)
{
  int result = -1;

  ACE_SEH_TRY
    {
      // We use the data member dispatch_set_ as the current dispatch
      // set.

      // We need to start from a clean dispatch_set
      this->dispatch_set_.rd_mask_.reset ();
      this->dispatch_set_.wr_mask_.reset ();
      this->dispatch_set_.ex_mask_.reset ();

      int number_of_active_handles =
        this->wait_for_multiple_events (this->dispatch_set_,
                                        max_wait_time);

      result =
        this->dispatch (number_of_active_handles,
                        this->dispatch_set_);
    }
  ACE_SEH_EXCEPT (this->release_token ())
    {
      // As it stands now, we catch and then rethrow all Win32
      // structured exceptions so that we can make sure to release the
      // <token_> lock correctly.
    }

  return result;
}

template <class ACE_SELECT_REACTOR_TOKEN> int
ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::wait_for_multiple_events
  (ACE_Select_Reactor_Handle_Set &dispatch_set,
   ACE_Time_Value *max_wait_time)
{
  ACE_TRACE ("ACE_Select_Reactor_T::wait_for_multiple_events");
  ACE_Time_Value timer_buf (0);
  ACE_Time_Value *this_timeout = 0;

  int number_of_active_handles = this->any_ready (dispatch_set);

  // If there are any bits enabled in the <ready_set_> then we'll
  // handle those first, otherwise we'll block in <select>.

  if (number_of_active_handles == 0)
    {
      do
        {
          if (this->timer_queue_ == 0)
            return 0;

          this_timeout =
            this->timer_queue_->calculate_timeout (max_wait_time,
                                                   &timer_buf);
#ifdef ACE_WIN32
          // This arg is ignored on Windows and causes pointer
          // truncation warnings on 64-bit compiles.
          int const width = 0;
#else
          int const width = this->handler_rep_.max_handlep1 ();
#endif  /* ACE_WIN32 */

          dispatch_set.rd_mask_ = this->wait_set_.rd_mask_;
          dispatch_set.wr_mask_ = this->wait_set_.wr_mask_;
          dispatch_set.ex_mask_ = this->wait_set_.ex_mask_;
          number_of_active_handles = ACE_OS::select (width,
                                                     dispatch_set.rd_mask_,
                                                     dispatch_set.wr_mask_,
                                                     dispatch_set.ex_mask_,
                                                     this_timeout);
        }
      while (number_of_active_handles == -1 && this->handle_error () > 0);

      if (number_of_active_handles > 0)
        {
#if !defined (ACE_WIN32)
          // Resynchronize the fd_sets so their "max" is set properly.
          dispatch_set.rd_mask_.sync (this->handler_rep_.max_handlep1 ());
          dispatch_set.wr_mask_.sync (this->handler_rep_.max_handlep1 ());
          dispatch_set.ex_mask_.sync (this->handler_rep_.max_handlep1 ());
#endif /* ACE_WIN32 */
        }
      else if (number_of_active_handles == -1)
        {
          // Normally, select() will reset the bits in dispatch_set
          // so that only those filed descriptors that are ready will
          // have bits set.  However, when an error occurs, the bit
          // set remains as it was when the select call was first made.
          // Thus, we now have a dispatch_set that has every file
          // descriptor that was originally waited for, which is not
          // correct.  We must clear all the bit sets because we
          // have no idea if any of the file descriptors is ready.
          //
          // NOTE: We dont have a test case to reproduce this
          // problem. But pleae dont ignore this and remove it off.
          dispatch_set.rd_mask_.reset ();
          dispatch_set.wr_mask_.reset ();
          dispatch_set.ex_mask_.reset ();
        }
    }

  // Return the number of events to dispatch.
  return number_of_active_handles;
}

template <class ACE_SELECT_REACTOR_TOKEN> int
ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::any_ready
  (ACE_Select_Reactor_Handle_Set &wait_set)
{
  ACE_TRACE ("ACE_Select_Reactor_T::any_ready");

  if (this->mask_signals_)
    {
#if !defined (ACE_WIN32)
      // Make this call signal safe.
      ACE_Sig_Guard sb;
#endif /* ACE_WIN32 */

      return this->any_ready_i (wait_set);
    }
  return this->any_ready_i (wait_set);
}
template <class ACE_SELECT_REACTOR_TOKEN> int
ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::any_ready_i
  (ACE_Select_Reactor_Handle_Set &wait_set)
{
  ACE_TRACE ("ACE_Select_Reactor_T::any_ready_i");

  int const number_ready = this->ready_set_.rd_mask_.num_set ()
    + this->ready_set_.wr_mask_.num_set ()
    + this->ready_set_.ex_mask_.num_set ();

  // number_ready > 0 meaning there are handles in the ready_set
  // &wait_set != &(this->ready_set_) means that we need to copy
  // the handles from the ready_set to the wait set because the
  // wait_set_ doesn't contain all the handles in the ready_set_
  if (number_ready > 0 && &wait_set != &(this->ready_set_))
    {
      wait_set.rd_mask_ = this->ready_set_.rd_mask_;
      wait_set.wr_mask_ = this->ready_set_.wr_mask_;
      wait_set.ex_mask_ = this->ready_set_.ex_mask_;

      this->ready_set_.rd_mask_.reset ();
      this->ready_set_.wr_mask_.reset ();
      this->ready_set_.ex_mask_.reset ();
    }

  return number_ready;
}
  • 将dispatch_set_清空
  • wait_for_multiple_events 看ready_set_是否有事件(不需要select),如果有,将ready_set_复制到dispatch_set_,同时将ready_set_清空, 如果ready_set_没有事件,则将wait_set_复制到dispatch_set_,调用select得到内核的就绪事件
  • 调用dispatch分发处理就绪事件,先处理中断事件,再处理定时器事件,接着处理通知事件,最后处理io事件,对于io事件处理完后,会设置ready_mask

ACE_Select_Reactor是ACE_Select_Reactor_T模板的一个实例

#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
typedef ACE_Token ACE_SELECT_TOKEN;
#else
typedef ACE_Noop_Token ACE_SELECT_TOKEN;
#endif /* ACE_MT_SAFE && ACE_MT_SAFE != 0 */
typedef ACE_Reactor_Token_T<ACE_SELECT_TOKEN> ACE_Select_Reactor_Token;
typedef ACE_Select_Reactor_T<ACE_Select_Reactor_Token> ACE_Select_Reactor;

ACE_Select_Reactor_Handle_Set:集中管理读,写,异常三个io集

ACE_WFMO_Reactor

使用WaitForMultipleObjects或者WaitForMultipleObjectsEx

ACE_WFMO_Reactor
# ACE_Sig_Handler *signal_handler_
# ACE_Timer_Queue *timer_queue_
# ACE_Reactor_Notify *notify_handler_
# ACE_Process_Mutex lock_
# ACE_Lock_Adapter lock_adapter_
# ACE_WFMO_Reactor_Handler_Repository handler_rep_
# ACE_Manual_Event ok_to_wait_
# ACE_Manual_Event wakeup_all_threads_
# ACE_Wakeup_All_Threads_Handler wakeup_all_threads_handler_
# ACE_Auto_Event waiting_to_change_state_
# ACE_HANDLE atomic_wait_array_ [2]

atomic_wait_array_ :用于存放lock_和ok_to_wait_
handle_events:调用event_handling

ACE_INLINE int
ACE_WFMO_Reactor::handle_events (ACE_Time_Value *how_long)
{
  return this->event_handling (how_long, FALSE);
}

int
ACE_WFMO_Reactor::event_handling (ACE_Time_Value *max_wait_time,
                                  int alertable)
{
  ACE_TRACE ("ACE_WFMO_Reactor::event_handling");

  // Make sure we are not closed
  if (!this->open_for_business_ || this->deactivated_)
    {
      errno = ESHUTDOWN;
      return -1;
    }

  // 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);

  int result;
  do
    {
      // Check to see if it is ok to enter ::WaitForMultipleObjects
      // This will acquire <this->lock_> on success On failure, the
      // lock will not be acquired
      result = this->ok_to_wait (max_wait_time, alertable);
      if (result != 1)
        return result;

      // Increment the number of active threads
      ++this->active_threads_;

      // Release the <lock_>
      this->lock_.release ();

      // Update the countdown to reflect time waiting to play with the
      // mut and event.
      countdown.update ();

      // Calculate timeout
      int timeout = this->calculate_timeout (max_wait_time);

      // Wait for event to happen
      DWORD wait_status = this->wait_for_multiple_events (timeout,
                                                          alertable);

      // Upcall
      result = this->safe_dispatch (wait_status);
      if (0 == result)
        {
          // wait_for_multiple_events timed out without dispatching
          // anything.  Because of rounding and conversion errors and
          // such, it could be that the wait loop timed out, but
          // the timer queue said it wasn't quite ready to expire a
          // timer. In this case, max_wait_time won't have quite been
          // reduced to 0, and we need to go around again. If max_wait_time
          // is all the way to 0, just return, as the entire time the
          // caller wanted to wait has been used up.
          countdown.update ();     // Reflect time waiting for events
          if (0 == max_wait_time || max_wait_time->usec () == 0)
            break;
        }
    }
  while (result == 0);

  return result;
}

ok_to_wait :调用WaitForMultipleObjects等待lock_和ok_to_wait_

int timeout = max_wait_time == 0 ? INFINITE : max_wait_time->msec ();
  DWORD result = 0;
  while (1)
    {
#  if defined (ACE_HAS_PHARLAP)
      // PharLap doesn't implement WaitForMultipleObjectsEx, and doesn't
      // do async I/O, so it's not needed in this case anyway.
      result = ::WaitForMultipleObjects (sizeof this->atomic_wait_array_ / sizeof (ACE_HANDLE),
                                         this->atomic_wait_array_,
                                         TRUE,
                                         timeout);

      if (result != WAIT_IO_COMPLETION)
        break;

#  else
      result = ::WaitForMultipleObjectsEx (sizeof this->atomic_wait_array_ / sizeof (ACE_HANDLE),
                                           this->atomic_wait_array_,
                                           TRUE,
                                           timeout,
                                           alertable);

      if (result != WAIT_IO_COMPLETION)
        break;

#  endif /* ACE_HAS_PHARLAP */
    }

  switch (result)
    {
    case WAIT_TIMEOUT:
      errno = ETIME;
      return 0;
    case WAIT_FAILED:
    case WAIT_ABANDONED_0:
      ACE_OS::set_errno_to_last_error ();
      return -1;
    default:
      break;
    }

  // It is ok to enter ::WaitForMultipleObjects
  return 1;

wait_for_multiple_events:等待handler_rep_句柄仓库中的任一事件发生

DWORD
ACE_WFMO_Reactor::wait_for_multiple_events (int timeout,
                                            int alertable)
{
  // Wait for any of handles_ to be active, or until timeout expires.
  // If <alertable> is enabled allow asynchronous completion of
  // ReadFile and WriteFile operations.

#if defined (ACE_HAS_PHARLAP) || defined (ACE_HAS_WINCE)
  // PharLap doesn't do async I/O and doesn't implement
  // WaitForMultipleObjectsEx, so use WaitForMultipleObjects.
  ACE_UNUSED_ARG (alertable);
  return ::WaitForMultipleObjects (this->handler_rep_.max_handlep1 (),
                                   this->handler_rep_.handles (),
                                   FALSE,
                                   timeout);
#else
  return ::WaitForMultipleObjectsEx (this->handler_rep_.max_handlep1 (),
                                     this->handler_rep_.handles (),
                                     FALSE,
                                     timeout,
                                     alertable);
#endif /* ACE_HAS_PHARLAP */
}

safe_dispatch:事件处理,检查WaitForMultipleObjects 或者WaitForMultipleObjectsEx 的返回状态,状态可能值为

  • WAIT_FAILED
  • WAIT_TIMEOUT
  • WAIT_IO_COMPLETION
  • WAIT_OBJECT_0 到 (WAIT_OBJECT_0 + nCount – 1)
  • WAIT_ABANDONED_0 (WAIT_ABANDONED_0 + nCount – 1)
    dispatch_handles :分发事件处理
    dispatch_handler:io事件调用complex_dispatch_handler,信号事件调用simple_dispatch_handler
ACE_INLINE int
ACE_WFMO_Reactor::safe_dispatch (DWORD wait_status)
{
  int result = -1;
  ACE_SEH_TRY
    {
      result = this->dispatch (wait_status);
    }
  ACE_SEH_FINALLY
    {
      this->update_state ();
    }

  return result;
}

int
ACE_WFMO_Reactor::dispatch (DWORD wait_status)
{
  // Expire timers
  int handlers_dispatched = this->expire_timers ();

  switch (wait_status)
    {
    case WAIT_FAILED: // Failure.
      ACE_OS::set_errno_to_last_error ();
      return -1;

    case WAIT_TIMEOUT: // Timeout.
      errno = ETIME;
      return handlers_dispatched;

#ifndef ACE_HAS_WINCE
    case WAIT_IO_COMPLETION: // APC.
      return handlers_dispatched;
#endif  // ACE_HAS_WINCE

    default:  // Dispatch.
      // We'll let dispatch worry about abandoned mutes.
      handlers_dispatched += this->dispatch_handles (wait_status);
      return handlers_dispatched;
    }
}

int
ACE_WFMO_Reactor::dispatch_handles (DWORD wait_status)
{
  // dispatch_slot is the absolute slot.  Only += is used to
  // increment it.
  DWORD dispatch_slot = 0;

  // Cache this value, this is the absolute value.
  DWORD const max_handlep1 = this->handler_rep_.max_handlep1 ();

  // nCount starts off at <max_handlep1>, this is a transient count of
  // handles last waited on.
  DWORD nCount = max_handlep1;

  for (int number_of_handlers_dispatched = 1;
       ;
       ++number_of_handlers_dispatched)
    {
      const bool ok = (
#if ! defined(__BORLANDC__) \
    && !defined (__MINGW32__) \
    && !defined (_MSC_VER)
                 // wait_status is unsigned in Borland, Green Hills,
                 // mingw32 and MSVC++
                 // This >= is always true, with a warning.
                 wait_status >= WAIT_OBJECT_0 &&
#endif
                 wait_status <= (WAIT_OBJECT_0 + nCount));

      if (ok)
        dispatch_slot += wait_status - WAIT_OBJECT_0;
      else
        // Otherwise, a handle was abandoned.
        dispatch_slot += wait_status - WAIT_ABANDONED_0;

      // Dispatch handler
      if (this->dispatch_handler (dispatch_slot, max_handlep1) == -1)
        return -1;

      // Increment slot
      ++dispatch_slot;

      // We're done.
      if (dispatch_slot >= max_handlep1)
        return number_of_handlers_dispatched;

      // Readjust nCount
      nCount = max_handlep1 - dispatch_slot;

      // Check the remaining handles
      wait_status = this->poll_remaining_handles (dispatch_slot);
      switch (wait_status)
        {
        case WAIT_FAILED: // Failure.
          ACE_OS::set_errno_to_last_error ();
          /* FALLTHRU */
        case WAIT_TIMEOUT:
          // There are no more handles ready, we can return.
          return number_of_handlers_dispatched;
        }
    }
}

int
ACE_WFMO_Reactor::complex_dispatch_handler (DWORD slot,
                                            ACE_HANDLE event_handle)
{
  // This dispatch is used for I/O entires.

  ACE_WFMO_Reactor_Handler_Repository::Current_Info &current_info =
    this->handler_rep_.current_info ()[slot];

  WSANETWORKEVENTS events;
  ACE_Reactor_Mask problems = ACE_Event_Handler::NULL_MASK;
  if (::WSAEnumNetworkEvents ((SOCKET) current_info.io_handle_,
                              event_handle,
                              &events) == SOCKET_ERROR)
    problems = ACE_Event_Handler::ALL_EVENTS_MASK;
  else
    {
      // Prepare for upcalls. Clear the bits from <events> representing
      // events the handler is not interested in. If there are any left,
      // do the upcall(s). upcall will replace events.lNetworkEvents
      // with bits representing any functions that requested a repeat
      // callback before checking handles again. In this case, continue
      // to call back unless the handler is unregistered as a result of
      // one of the upcalls. The way this is written, the upcalls will
      // keep being done even if one or more upcalls reported problems.
      // In practice this may turn out not so good, but let's see. If any
      // problems, please notify Steve Huston <shuston@riverace.com>
      // before or after you change this code.
      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;
        }
    }

  if (problems != ACE_Event_Handler::NULL_MASK
      && !this->handler_rep_.scheduled_for_deletion (slot)  )
    this->handler_rep_.unbind (event_handle, problems);

  return 0;
}

ACE_Reactor_Mask
ACE_WFMO_Reactor::upcall (ACE_Event_Handler *event_handler,
                          ACE_HANDLE io_handle,
                          WSANETWORKEVENTS &events)
{
  // This method figures out what exactly has happened to the socket
  // and then calls appropriate methods.
  ACE_Reactor_Mask problems = ACE_Event_Handler::NULL_MASK;

  // Go through the events and do the indicated upcalls. If the handler
  // doesn't want to be called back, clear the bit for that event.
  // At the end, set the bits back to <events> to request a repeat call.

  long actual_events = events.lNetworkEvents;
  int action;

  if (ACE_BIT_ENABLED (actual_events, FD_WRITE))
    {
      action = event_handler->handle_output (io_handle);
      if (action <= 0)
        {
          ACE_CLR_BITS (actual_events, FD_WRITE);
          if (action == -1)
            ACE_SET_BITS (problems, ACE_Event_Handler::WRITE_MASK);
        }
    }

  if (ACE_BIT_ENABLED (actual_events, FD_CONNECT))
    {
      if (events.iErrorCode[FD_CONNECT_BIT] == 0)
        {
          // Successful connect
          action = event_handler->handle_output (io_handle);
          if (action <= 0)
            {
              ACE_CLR_BITS (actual_events, FD_CONNECT);
              if (action == -1)
                ACE_SET_BITS (problems,
                              ACE_Event_Handler::CONNECT_MASK);
            }
        }
      // Unsuccessful connect
      else
        {
          action = event_handler->handle_input (io_handle);
          if (action <= 0)
            {
              ACE_CLR_BITS (actual_events, FD_CONNECT);
              if (action == -1)
                ACE_SET_BITS (problems,
                              ACE_Event_Handler::CONNECT_MASK);
            }
        }
    }

  if (ACE_BIT_ENABLED (actual_events, FD_OOB))
    {
      action = event_handler->handle_exception (io_handle);
      if (action <= 0)
        {
          ACE_CLR_BITS (actual_events, FD_OOB);
          if (action == -1)
            ACE_SET_BITS (problems, ACE_Event_Handler::EXCEPT_MASK);
        }
    }

  if (ACE_BIT_ENABLED (actual_events, FD_READ))
    {
      action = event_handler->handle_input (io_handle);
      if (action <= 0)
        {
          ACE_CLR_BITS (actual_events, FD_READ);
          if (action == -1)
            ACE_SET_BITS (problems, ACE_Event_Handler::READ_MASK);
        }
    }

  if (ACE_BIT_ENABLED (actual_events, FD_CLOSE)
      && ACE_BIT_DISABLED (problems, ACE_Event_Handler::READ_MASK))
    {
      action = event_handler->handle_input (io_handle);
      if (action <= 0)
        {
          ACE_CLR_BITS (actual_events, FD_CLOSE);
          if (action == -1)
            ACE_SET_BITS (problems, ACE_Event_Handler::READ_MASK);
        }
    }

  if (ACE_BIT_ENABLED (actual_events, FD_ACCEPT))
    {
      action = event_handler->handle_input (io_handle);
      if (action <= 0)
        {
          ACE_CLR_BITS (actual_events, FD_ACCEPT);
          if (action == -1)
            ACE_SET_BITS (problems, ACE_Event_Handler::ACCEPT_MASK);
        }
    }

  if (ACE_BIT_ENABLED (actual_events, FD_QOS))
    {
      action = event_handler->handle_qos (io_handle);
      if (action <= 0)
        {
          ACE_CLR_BITS (actual_events, FD_QOS);
          if (action == -1)
            ACE_SET_BITS (problems, ACE_Event_Handler::QOS_MASK);
        }
    }

  if (ACE_BIT_ENABLED (actual_events, FD_GROUP_QOS))
    {
      action = event_handler->handle_group_qos (io_handle);
      if (action <= 0)
        {
          ACE_CLR_BITS (actual_events, FD_GROUP_QOS);
          if (action == -1)
            ACE_SET_BITS (problems, ACE_Event_Handler::GROUP_QOS_MASK);
        }
    }

  events.lNetworkEvents = actual_events;
  return problems;
}

int
ACE_WFMO_Reactor::simple_dispatch_handler (DWORD slot,
                                           ACE_HANDLE event_handle)
{
  // This dispatch is used for non-I/O entires

  // Assign the ``signaled'' HANDLE so that callers can get it.
  // siginfo_t is an ACE - specific fabrication. Constructor exists.
  siginfo_t sig (event_handle);

  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 (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;
}

ACE_QtReactor

QtReactor在注册事件处理器时,会通过create_notifiers_for_handle创建QSocketNotifier
并且将信号activated与read_event ,write_event,exception_event 槽函数连接起来

void
ACE_QtReactor::create_notifiers_for_handle (ACE_HANDLE handle)
{
    QSocketNotifier *qsock_notifier = 0;

    // if there is already a read socket notifier for this handle, do nothing
    // otherwise create read notifier
    if ( ( this->read_notifier_.find (handle,
               qsock_notifier) == -1) )
    {
        ACE_NEW (qsock_notifier,
            QSocketNotifier (int(handle), QSocketNotifier::Read, this));
        this->read_notifier_.bind (handle,
            qsock_notifier);
        QObject::connect (qsock_notifier,
            SIGNAL (activated (int)),
            this,
            SLOT (read_event (int))) ;
        // disable; it will be enabled by the regular register_handler_i if
        // necessary
        qsock_notifier->setEnabled (0);
    }

    qsock_notifier = 0;


    // if there is already a write socket notifier for this handle, do nothing
    // otherwise create read notifier
    if ((this->write_notifier_.find (handle,
             qsock_notifier) == -1))
    {
        ACE_NEW (qsock_notifier,
            QSocketNotifier (int(handle), QSocketNotifier::Write, this));

        this->write_notifier_.bind (handle,
            qsock_notifier);

        QObject::connect (qsock_notifier,
            SIGNAL (activated (int)),
            this,
            SLOT (write_event (int)));
        // disable; it will be enabled by the regular register_handler_i if
        // necessary
        qsock_notifier->setEnabled (0);
    }


    qsock_notifier = 0;

    // if there is already a write socket notifier for this handle, do nothing
    // otherwise create read notifier
    if ((this->exception_notifier_.find (handle,
             qsock_notifier) == -1))
    {

        ACE_NEW (qsock_notifier,
            QSocketNotifier (int(handle), QSocketNotifier::Exception, this));

        this->exception_notifier_.bind (handle,
            qsock_notifier);

        QObject::connect (qsock_notifier,
            SIGNAL (activated (int)),
            this,
            SLOT (exception_event (int))) ;
        // disable; it will be enabled by the regular register_handler_i if
        // necessary
        qsock_notifier->setEnabled (0);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kgduu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值