ACE_TAO 014 ACE_Event_Handler

ACE_Event_Handler接口是Reactor框架的事件处理器接口,它为应用程序的事件处理提供模板函数。它是框架五元素中的元素2。在示例ACE_TAO 008 Reactor基本原理与说明中,实际上Handle_data类和Acceptor类都是框架五元素中的元素3。ACE_Event_Handler接口的定义如下:

/* -*- C++ -*- */

//==========================================================================
/**
 *  @file    Event_Handler.h
 *
 *  @author Douglas C. Schmidt <d.schmidt@vanderbilt.edu>
 */
//==========================================================================

#ifndef ACE_EVENT_HANDLER_H
#define ACE_EVENT_HANDLER_H
#include /**/ "ace/pre.h"

#include /**/ "ace/ACE_export.h"

#if !defined (ACE_LACKS_PRAGMA_ONCE)
# pragma once
#endif /* ACE_LACKS_PRAGMA_ONCE */

#include "ace/os_include/os_signal.h"
#include "ace/OS_NS_Thread.h"
#include <atomic>

ACE_BEGIN_VERSIONED_NAMESPACE_DECL

// Forward declaration.
class ACE_Message_Block;
class ACE_Reactor;
class ACE_Reactor_Timer_Interface;
class ACE_Thread_Manager;
class ACE_Process;

typedef unsigned long ACE_Reactor_Mask;

/**
 * @class ACE_Event_Handler
 *
 * @brief
 * Provides an abstract interface for handling various types of
 * I/O, timer, and signal events.
 *
 * Subclasses read/write input/output on an I/O descriptor,
 * handle an exception raised on an I/O descriptor, handle a
 * timer's expiration, or handle a signal.
 */
class ACE_Export ACE_Event_Handler
{
public:
  enum
  {
    LO_PRIORITY = 0,
    HI_PRIORITY = 10,
    NULL_MASK = 0,
#if defined (ACE_USE_POLL)
    READ_MASK = POLLIN,
    WRITE_MASK = POLLOUT,
    EXCEPT_MASK = POLLPRI,
#else /* USE SELECT */
    READ_MASK = (1 << 0),
    WRITE_MASK = (1 << 1),
    EXCEPT_MASK = (1 << 2),
#endif /* ACE_USE_POLL */
    ACCEPT_MASK = (1 << 3),
    CONNECT_MASK = (1 << 4),
    TIMER_MASK = (1 << 5),
    QOS_MASK = (1 << 6),
    GROUP_QOS_MASK = (1 << 7),
    SIGNAL_MASK = (1 << 8),
    ALL_EVENTS_MASK = READ_MASK |
                      WRITE_MASK |
                      EXCEPT_MASK |
                      ACCEPT_MASK |
                      CONNECT_MASK |
                      TIMER_MASK |
                      QOS_MASK |
                      GROUP_QOS_MASK |
                      SIGNAL_MASK,
    RWE_MASK = READ_MASK |
               WRITE_MASK |
               EXCEPT_MASK,
    DONT_CALL = (1 << 9)
  };

  /// Destructor is virtual to enable proper cleanup.
  virtual ~ACE_Event_Handler ();

  /// Get the I/O handle.
  virtual ACE_HANDLE get_handle () const;

  /// Set the I/O handle.
  virtual void set_handle (ACE_HANDLE);

  // = Get/set priority

  /// Get the priority of the Event_Handler.
  /// @note Priorities run from MIN_PRIORITY (which is the "lowest priority")
  /// to MAX_PRIORITY (which is the "highest priority").
  virtual int priority () const;

  /// Set the priority of the Event_Handler.
  virtual void priority (int priority);

  /// Called when input events occur (e.g., connection or data).
  virtual int handle_input (ACE_HANDLE fd = ACE_INVALID_HANDLE);

  /// Called when output events are possible (e.g., when flow control
  /// abates or non-blocking connection completes).
  virtual int handle_output (ACE_HANDLE fd = ACE_INVALID_HANDLE);

  /// Called when an exceptional events occur (e.g., SIGURG).
  virtual int handle_exception (ACE_HANDLE fd = ACE_INVALID_HANDLE);

  /**
   * Called when timer expires.  @a current_time represents the current
   * time that the Event_Handler was selected for timeout
   * dispatching and @a act is the asynchronous completion token that
   * was passed in when <schedule_timer> was invoked.
   */
  virtual int handle_timeout (const ACE_Time_Value &current_time,
                              const void *act = 0);

  /// Called when a process exits.
  virtual int handle_exit (ACE_Process *);

  /// Called when a handle_*() method returns -1 or when the
  /// remove_handler() method is called on an ACE_Reactor.  The
  /// @a close_mask indicates which event has triggered the
  /// handle_close() method callback on a particular @a handle.
  virtual int handle_close (ACE_HANDLE handle,
                            ACE_Reactor_Mask close_mask);

  /// Called when object is signaled by OS (either via UNIX signals or
  /// when a Win32 object becomes signaled).
  virtual int handle_signal (int signum, siginfo_t * = 0, ucontext_t * = 0);

  enum
    {
      /// The handler is not resumed at all. Could lead to deadlock..
      ACE_EVENT_HANDLER_NOT_RESUMED = -1,
      /// The reactor takes responsibility of resuming the handler and
      /// is the default
      ACE_REACTOR_RESUMES_HANDLER = 0,
      /// The application takes responsibility of resuming the handler
      ACE_APPLICATION_RESUMES_HANDLER
    };

  /**
   * Called to figure out whether the handler needs to resumed by the
   * reactor or the application can take care of it. The default
   * value of 0 would be returned which would allow the reactor to
   * take care of resumption of the handler. The application can
   * return a value more than zero and decide to resume the handler
   * themselves.
   *
   * @note This method has an affect only when used with the
   * ACE_Dev_Poll_Reactor (and then, only on Linux) or the ACE_TP_Reactor.
   */
  virtual int resume_handler ();

  virtual int handle_qos (ACE_HANDLE = ACE_INVALID_HANDLE);
  virtual int handle_group_qos (ACE_HANDLE = ACE_INVALID_HANDLE);

  // = Accessors to set/get the various event demultiplexors.
  /// Set the event demultiplexors.
  virtual void reactor (ACE_Reactor *reactor);

  /// Get the event demultiplexors.
  virtual ACE_Reactor *reactor () const;

  /// Get only the reactor's timer related interface.
  virtual ACE_Reactor_Timer_Interface *reactor_timer_interface () const;

  /**
   * Used to read from non-socket ACE_HANDLEs in our own thread to
   * work around Win32 limitations that don't allow us to <select> on
   * non-sockets (such as ACE_STDIN).  This is commonly used in
   * situations where the Reactor is used to demultiplex read events
   * on ACE_STDIN on UNIX.  Note that @a event_handler must be a
   * subclass of ACE_Event_Handler.  If the get_handle() method of
   * this event handler returns ACE_INVALID_HANDLE we default to
   * reading from ACE_STDIN.
   */
  static ACE_THR_FUNC_RETURN read_adapter (void *event_handler);

  /**
   * Abstracts away from the differences between Win32 and ACE with
   * respect to reading from ACE_STDIN, which is non-<select>'able on
   * Win32.
   */
  static int register_stdin_handler (ACE_Event_Handler *eh,
                                     ACE_Reactor *reactor,
                                     ACE_Thread_Manager *thr_mgr,
                                     int flags = THR_DETACHED);

  /// Performs the inverse of the register_stdin_handler() method.
  static int remove_stdin_handler (ACE_Reactor *reactor,
                                   ACE_Thread_Manager *thr_mgr);

  /// Reference count type.
  typedef long Reference_Count;

  /// Increment reference count on the handler.
  /**
   * This method is called when the handler is registered with the
   * Reactor and when the Reactor makes an upcall on the handler.
   * Reference count is 1 when the handler is created.
   *
   * @return Current reference count.
   */
  virtual Reference_Count add_reference ();

  /// Decrement reference count on the handler.
  /**
   * This method is called when the handler is removed from the
   * Reactor and when an upcall made on the handler by the Reactor
   * completes.  Handler is deleted when the reference count reaches
   * 0.
   *
   * @return Current reference count.
   */
  virtual Reference_Count remove_reference ();

  /**
   * @class Policy
   *
   * @brief Base class for all handler policies.
   */
  class ACE_Export Policy
  {
  public:

    /// Virtual destructor.
    virtual ~Policy ();
  };

  /**
   * @class Reference_Counting_Policy
   *
   * @brief
   * This policy dictates the reference counting requirements
   * for the handler.
   *
   * This policy allows applications to configure whether it wants the
   * Reactor to call add_reference() and remove_reference() during
   * registrations, removals, and upcalls.
   *
   * <B>Default:</B> DISABLED.
   */
  class ACE_Export Reference_Counting_Policy : public Policy
  {
    /// This policy can only be created by the handler.
    friend class ACE_Event_Handler;

  public:
    enum Value
      {
        /// Perform reference counting.
        ENABLED,
        /// Don't perform reference counting.
        DISABLED
      };

    /// Current Reference_Counting_Policy.
    Value value () const;

    /// Update Reference_Counting_Policy.
    void value (Value value);

  private:
    /// Private constructor.
    Reference_Counting_Policy (Value value);

    /// The value of the policy.
    Value value_;
   };

  /// Current Reference_Counting_Policy.
  Reference_Counting_Policy &reference_counting_policy ();

protected:
  /// Force ACE_Event_Handler to be an abstract base class.
  ACE_Event_Handler (ACE_Reactor * = 0,
                     int priority = ACE_Event_Handler::LO_PRIORITY);

  /// Typedef for implementation of reference counting.
  typedef std::atomic<Reference_Count> Atomic_Reference_Count;

  /// Reference count.
  Atomic_Reference_Count reference_count_;

private:
  /// Priority of this Event_Handler.
  int priority_;

  /// Pointer to the various event demultiplexors.
  ACE_Reactor *reactor_;

  /// Reference counting requirements.
  Reference_Counting_Policy reference_counting_policy_;
};

/**
 * @class ACE_Event_Handler_var
 *
 * @brief Auto pointer like class for Event Handlers.
 *
 * Used to manage lifecycle of handlers. This class calls
 * ACE_Event_Handler::remove_reference() in its destructor.
 */
class ACE_Export ACE_Event_Handler_var
{
public:
  /// Default constructor.
  ACE_Event_Handler_var ();

  /// Construct with a handler.
  ACE_Event_Handler_var (ACE_Event_Handler *p);

  /// Copy constructor.
  ACE_Event_Handler_var (const ACE_Event_Handler_var &b);

  /// Destructor.
  ~ACE_Event_Handler_var ();

  /// Assignment to a handler.
  ACE_Event_Handler_var &operator= (ACE_Event_Handler *p);

  /// Assignment to a ACE_Event_Handler_var.
  ACE_Event_Handler_var &operator= (const ACE_Event_Handler_var &b);

  /// Overloaded "->".
  ACE_Event_Handler *operator-> () const;

  /// Access the handler.
  ACE_Event_Handler *handler () const;

  /// Release the handler.
  ACE_Event_Handler *release ();

  /// Reset the handler.
  void reset (ACE_Event_Handler *p = 0);

  /// Bool operator to check if the ACE_Event_Handler_var has a value
  explicit operator bool() const;
  /// Equality operator to compare with nullptr_t
  bool operator ==(std::nullptr_t) const;
  /// Not equal operator to compare with nullptr_t
  bool operator !=(std::nullptr_t) const;

private:
  /// Handler.
  ACE_Event_Handler *ptr_;
};

/// Define that we can use in user code to check if this
/// helper factory method is there
#define ACE_HAS_ACE_MAKE_EVENT_HANDLER

namespace ACE
{
  /// With C++11 it is common to not use C++ new and delete, but
  /// use std::make_shared and std::make_unique. This will not
  /// work for ACE event handlers so we introduce a new
  /// ACE::make_event_handler which can be used in user code to
  /// allocate a new ACE event handler instance and directly assign
  /// it to a ACE_Event_Handler_var
  /// As user this now makes it for example possible to implement
  /// the following when Simple_Handler is derived from ACE_Event_Handler
  /// ACE_Event_Handler_var v =
  ///   ACE::make_event_handler<Simple_Handler> (reactor.get());
  template<class T,
           typename = typename
             std::enable_if<std::is_base_of<ACE_Event_Handler, T>::value>::type,
           typename ...Args> inline
  ACE_Event_Handler_var make_event_handler (Args&& ...args)
  {
    return ACE_Event_Handler_var (new T (std::forward<Args> (args)...));
  }
}

/**
 * @class ACE_Notification_Buffer
 *
 * @brief Simple wrapper for passing ACE_Event_Handler *s and
 * ACE_Reactor_Masks between threads.
 */
class ACE_Export ACE_Notification_Buffer
{
public:
  ACE_Notification_Buffer ();

  ACE_Notification_Buffer (ACE_Event_Handler *eh,
                           ACE_Reactor_Mask mask);

  /// Default destructor.
  ~ACE_Notification_Buffer () = default;

  /// Pointer to the Event_Handler that will be dispatched
  /// by the main event loop.
  ACE_Event_Handler *eh_;

  /// Mask that indicates which method to call.
  ACE_Reactor_Mask mask_;
};

ACE_END_VERSIONED_NAMESPACE_DECL

#include /**/ "ace/post.h"
#endif /* ACE_EVENT_HANDLER_H */

ACE_Event_Handler是一个接口,用于封装Reactor框架支持的IO事件、信号量事件、定时器事件和Notify事件。每一个事件处理器都有一个优先级,用于支持有优先级的事件调度器。事件处理器具有引用计数功能,这是因为同一个事件处理器可以被多次使用,比如一个处理IO的事件处理器可以用作一个定时器。引用计数可以追踪事件处理器的使用计数,当使用计数为0时,框架会删除事件处理器。是否启用引用计数功能,取决于应用程序。在默认情况下,引用计数功能是关闭的,引用计数功能是否开启的属性保存在一个Policy中。

ACE_Event_Handler接口还定义了各类事件的类型和属性,代码如下:

  enum
  {
    LO_PRIORITY = 0,
    HI_PRIORITY = 10,
    NULL_MASK = 0,
#if defined (ACE_USE_POLL)
    READ_MASK = POLLIN,
    WRITE_MASK = POLLOUT,
    EXCEPT_MASK = POLLPRI,
#else /* USE SELECT */
    READ_MASK = (1 << 0),
    WRITE_MASK = (1 << 1),
    EXCEPT_MASK = (1 << 2),
#endif /* ACE_USE_POLL */
    ACCEPT_MASK = (1 << 3),
    CONNECT_MASK = (1 << 4),
    TIMER_MASK = (1 << 5),
    QOS_MASK = (1 << 6),
    GROUP_QOS_MASK = (1 << 7),
    SIGNAL_MASK = (1 << 8),
    ALL_EVENTS_MASK = READ_MASK |
                      WRITE_MASK |
                      EXCEPT_MASK |
                      ACCEPT_MASK |
                      CONNECT_MASK |
                      TIMER_MASK |
                      QOS_MASK |
                      GROUP_QOS_MASK |
                      SIGNAL_MASK,
    RWE_MASK = READ_MASK |
               WRITE_MASK |
               EXCEPT_MASK,
    DONT_CALL = (1 << 9)
  };

对这些事件的类型和属性的描述,如下表:

LO_PRIORITY事件低优先级,用于有优先级调度的Reactor管理器
HI_PRIORITY事件高优先级,用于有优先级调度的Reactor管理器
READ_MASK读事件
WRITE_MASK写事件
EXCEPT_MASK异常事件
ACCEPT_MASKACCEPT事件
CONNECT_MASKCONNECT事件
TIMER_MASK定时器事件
QOS_MASK
GROUP_QOS_MASK
SIGNAL_MASK信号量事件
ALL_EVENTS_MASK事件组合值,表示所有事件
RWE_MASK事件组合值,表示分离函数支持的事件
DONT_CALL指示框架在删除事件处理器时是否调用handle_cloase函数

ACE_Event_Handler接口的主要功能是提供事件处理的模板函数,它们用于处理不同的事件,这些模板函数的功能如下表所示。应用程序可以根据事件的类型实现其中的部分或者全部的处理函数。应用程序只有实现了处理函数,并且把它注册到框架中,框架才能实现调度,框架的Hollywood原则才能得以实现。

处理函数处理事件
handle_signal处理信号量事件,当注册的信号发生时,框架会自动调用该处理函数
handle_input处理IO事件,当注册的描述符有数据输入时,框架会自动调用该函数
handle_exception处理异常事件
handle_timeout处理定时器事件
handle_output处理IO事件,当IO设备的输出队列非满时,框架会自动调用该处理函数

事件处理器接口的使用规范

既然使用Reactor框架,就需要遵守Reactor框架的一些约束。

1。应用程序的事件处理器必须继承ACE_Event_Handler接口,然后注册到框架中,才能被框架调度;

2。ACE_Event_Handler接口的模板函数会被Reactor管理器调用。对于handle_xxx()函数(handle_close除外),框架为它们预设了返回值;小于0,等于0和大于0。

 小于0表示处理失败,或者虽然处理成功但需要执行关闭操作。如果使用了DONT_CAIL标志, Reactor处理器在不调用handle_close函数的情况下,将该事件处理器从Reactor管理器中删除;否则Reactor管理器会调用handle_close函数,同时将该事件处理器从Reactor管理器中删除。

等于0表示处理正常,Reactor管理器继续等待事件。

大于0表示在不等待下一个事件的情况下,继续调度事件处理器。

3。Reactor框架建议应用程序使用handle_close而不是delete来释放资源。Reactor框架并不知道用户使用的是动态内存还是静态内存,它只知道在删除事件处理器时,调用handle_close函数,将具体的操作留给应用程序在handle_close中完成,所以handle_close可以用来关闭Socket释放内存等。

4。为了提供更大的灵活性,Reactor框架还在ACE_Event_Handler中使用了引用计数功能。如果应用程序使能了事件处理器的引用计数功能,那么一旦事件处理器的引用计数为0,Reactor管理器会自动删除事件处理器。

多谢,亲爱的美美。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值