⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 custom_event_handler.hpp

📁 新版本TR1的stl
💻 HPP
📖 第 1 页 / 共 3 页
字号:
    /** Registers the custom event.
     *
     * \param code The event code that identifies the event for this event
     * handler instance, and will be passed back to the handle_custom_event() callback
     * \param delay The interval after which the event callback will be operable
     * \param arg An optional event parameter, which will be passed back to the
     * handle_custom_event() callback
     *
     * \return NULL on failure, the event id on success
     *
     * \remarks The custom event can be cancelled via cancel_custom_event()
     *
     * \note Custom events are "one-shot". When the event delay elapses and the
     * handle_custom_event() callback is called, the event has been deregistered from
     * this handler. There is no need to call cancel_custom_event(), and doing so is
     * semantically wrong, though it has no effect.
     */
    event_id schedule_custom_event(long code, ACE_Time_Value const& delay, void* arg = 0);

    /** Registers the custom event for immediate action.
     *
     * \param code The event code that identifies the event for this event
     * handler instance, and will be passed back to the handle_custom_event() callback
     * \param arg An optional event parameter, which will be passed back to the
     * handle_custom_event() callback
     *
     * \return NULL on failure, the event id on success
     *
     * \remarks The custom event can be cancelled via cancel_custom_event()
     *
     * \note Custom events are "one-shot". When the event delay elapses and the
     * handle_custom_event() callback is called, the event has been deregistered from
     * this handler. There is no need to call cancel_custom_event(), and doing so is
     * semantically wrong, though it has no effect.
     */
    event_id schedule_custom_event(long code, void* arg = 0);

    /** Cancels the event(s) corresponding to the given event code
     *
     * \param code The code of the event(s) to be cancelled
     *
     * \return -1 on failure, 0 on success
     *
     * \note There is no need to call this function if the event handler
     * callback handle_custom_event() has been called, since the event is
     * already deregistered at that point.
     */
    int cancel_custom_events(long code);

    /** Cancels the event(s) corresponding to the given event code, invoking
     *   the given callback function with details of each cancelled event.
     *
     * \param code The code of the event(s) to be cancelled
     * \param pfn Pointer to a function that will be called for each cancelled event
     * \param param A caller-supplied parameter that will be passed back to the callback function
     *
     * \return -1 on failure, 0 on success
     *
     * It is used as shown in the following example:
\code
  class MyHandler
    : public custom_event_handler
  {
    . . .
  };

  void cancel_proc(void *param, long code, custom_event_handler::event_id id, void *arg)
  {
    ++*static_cast<int*>(arg);
  }

  MyHandler*  mh = new MyHandler(. . .);
  int         cancelCount = 0;

  id = mh->schedule_custom_event(100, NULL);

  . . .

  // cancel_proc() will be invoked for all events having event code 100 that
  // have not yet been dispatched or cancelled at the time of execution of
  // this method
  mh->cancel_custom_events(100, cancel_proc, &cancelCount);
\endcode
     */
    int cancel_custom_events(long code, cancelled_event_code_fn pfn, void* param);

#if defined(ACESTL_CUSTOM_EVENT_HANDLER_CANCEL_EVENTS_MEMBER_CLEANUP_SUPPORT)
#if 0
    /// Some compilers (i.e. VC++ 6) have a big cry here, so we define this out
    /// of the class, and use the private base type trick
    template<ss_typename_param_k C>
    struct cancel_adapter
    {
        typedef cancel_adapter<C>   class_type;

        cancel_adapter(C* obj, void (C::*pfn)(long code, event_id id, void* arg))
            : m_obj(obj)
            , m_pfn(pfn)
        {}

        static void proc(void* param, long code, event_id id, void* arg)
        {
            class_type* pThis = static_cast<class_type*>(param);

            ((pThis->m_obj)->*(pThis->m_pfn))(code, id, arg);
        }

    private:
        C* const m_obj;
        void (C::*m_pfn)(long code, event_id id, void* arg);
    };
#endif /* 0 */

    /** Specifies an instance of a cancel handler class and one of its
     *   non-static methods (which will be called back in the case of each
     *   event cancellation) and cancels all events matching the given
     *   event code.
     *
     * \param code The code of the event(s) to cancel
     * \param obj The class instance whose method will be invoked
     * \param pfn The class method to be invoked
     *
     * It is used as shown in the following example:
\code
  class MyHandler
    : public custom_event_handler
  {
    . . .
  };

  class CancelHandler
  {
  public:
    void report(long code, custom_event_handler::event_id id, void *arg);
    . . .
  };

  MyHandler*        mh = new MyHandler(. . .);
  CancelHandler     ch;

  id = mh->schedule_custom_event(100, NULL);

  . . .

  // ch->CancelHandler::report() will be invoked for all events having event
  // code 100 that have not yet been dispatched or cancelled at the time of
  // execution of this method
  mh->cancel_custom_events(100, &ch, &CancelHandler::report);
\endcode
     */
    template<ss_typename_param_k C>
    int cancel_custom_events(long code, C* obj, void (C::*pfn)(long code, event_id id, void* arg))
    {
        cancel_adapter<C>   adapter(obj, pfn);

        return this->cancel_custom_events(code, &cancel_adapter<C>::proc, &adapter);
    }
#endif /* ACESTL_CUSTOM_EVENT_HANDLER_CANCEL_EVENTS_MEMBER_CLEANUP_SUPPORT */

    /** Cancels the given event
     *
     * \param event The event to be cancelled
     * \param parg Optional pointer to a variable to receive the argument specified when the event was scheduled
     *
     * \return -1 on failure, 0 on success
     *
     * \note There is no need to call this function if the event handler
     * callback handle_custom_event() has been called, since the event is
     * already deregistered at that point.
     */
    int cancel_custom_event(event_id event, void** parg = NULL);
/// @}

/// \name Accessors
/// @{
public:
/// @}

/// \name Attributes
/// @{
public:
    /** Indicates whether the event handler has one or more custom events
     * registered for the given code.
     *
     * \param code The custom event code
     *
     * \retval 0 if no events are registered for the given code
     * \retval 1 if one or more events are registered for the hiven code
     */
    as_int_t has_custom_events(long code) const;

    /** [DEPRECATED] Analogue of has_custom_events()
     *
     * \deprecated This method is deprecated in favour of has_custom_events()
     */
    as_int_t has_custom_event(long code) const;

    /** Indicates whether the event handler has the given event registered
     *
     * \param event The event id
     *
     * \retval 0 if the event id matches an outstanding event instance
     * \retval 1 if the event id does not match an outstanding event instance
     */
    as_int_t has_custom_event(event_id event) const;
/// @}

// Overrides
#ifdef STLSOFT_DOCUMENTATION_SKIP_SECTION
public:
#else /* ? !STLSOFT_DOCUMENTATION_SKIP_SECTION */
private:
#endif /* STLSOFT_DOCUMENTATION_SKIP_SECTION */
    /** This (private) pure virtual function is implemented by derived
     *   classes to handle the custom events.
     *
     * \param current_time The time at which the event was dispatched by the
     *   reactor
     * \param code The event code
     * \param arg The argument specified to schedule_custom_event()
     */
    virtual int handle_custom_event(ACE_Time_Value const&   current_time
                                ,   long                    code
                                ,   void*                   arg)   =   0;

// Implementation
private:
    class callback_hook
        : public ACE_Event_Handler
    {
    public:
        callback_hook(custom_event_handler* ceh, ACE_Reactor* reactor, int priority)
            : ACE_Event_Handler(reactor, priority)
            , m_ceh(ceh)
        {
            ACESTL_MESSAGE_ASSERT("reactor may not be null", NULL != reactor);
        }
        ~callback_hook() stlsoft_throw_0()
        {
            reactor()->remove_handler(this, ACE_Event_Handler::ALL_EVENTS_MASK | ACE_Event_Handler::DONT_CALL);
        }

    private:
        virtual int handle_timeout( ACE_Time_Value const&   current_time
                                ,   void const*             arg)
        {
            return m_ceh->handle_callback_timeout(current_time, const_cast<void*>(arg));
        }

    private:
        custom_event_handler    *const  m_ceh;

    private:
        callback_hook(callback_hook const&);
        callback_hook& operator =(callback_hook const&);
    };

    friend class callback_hook;

    // Each entry consists of the notification code and the actual arg
    struct event_info
    {
        long        code;   //!< The event code
        void        *arg;   //!< The custom event argument
        event_id    id;     //!< The id of the event registered in the reactor

        event_info(long code_, void *arg_)
            : code(code_)
            , arg(arg_)
            , id(NULL)
        {}
    };

    typedef ::stlsoft::shared_ptr<event_info>    info_ptr;

    // receiver of the callback hook's handle_timeout call,
    int handle_callback_timeout(ACE_Time_Value const&   current_time
                            ,   void*                   arg);

    // This is used to avoid compiler warnings about using 'this' in member
    // initialiser lists
    class_type *get_this_()
    {
        return this;
    }

    // Invariant
    bool_type   is_valid() const;

    //
    event_id    schedule_event_(event_info* entry, ACE_Time_Value const& delay);
    as_int_t    cancel_event_(event_id );

// Members
private:
    // There are two maps.
    //
    // 1. The long=>event_info* map is used for registration/deregistration. Because
    // it owns the entries it uses the associative_container_veneer
    //
    // 2. The event_info*=>long map is used

    typedef ::std::map<event_id, info_ptr>      event_map_type;
    typedef ::std::map<long, event_map_type>    event_code_map_type;

    callback_hook       m_callbackHook;
    event_code_map_type m_entries;

// Not to be implemented
private:
    custom_event_handler(class_type const&);
    class_type& operator =(class_type const&);
};

////////////////////////////////////////////////////////////////////////////
// Unit-testing

#ifdef STLSOFT_UNITTEST
# include "./unittest/custom_event_handler_unittest_.h"

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -