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

📄 custom_event_handler.hpp

📁 新版本TR1的stl
💻 HPP
📖 第 1 页 / 共 3 页
字号:
#endif /* STLSOFT_UNITTEST */

/* /////////////////////////////////////////////////////////////////////////
 * Implementation
 */

#ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION

#ifdef STLSOFT_COMPILER_IS_MSVC
# if _MSC_VER >= 1200
#  pragma warning(push)
# endif /* compiler */
# pragma warning(disable : 4702)
#endif /* compiler */

inline custom_event_handler::event_id custom_event_handler::schedule_event_(event_info* entry, ACE_Time_Value const& delay)
{
    long timerId = m_callbackHook.reactor()->schedule_timer(&m_callbackHook, entry, delay);

    ACESTL_MESSAGE_ASSERT("Unexpected negative value", timerId >= -1 || -1 == timerId);

    return (-1 == timerId) ? NULL : reinterpret_cast<event_id>(static_cast<as_size_t>(1 + timerId));
}

inline as_int_t custom_event_handler::cancel_event_(custom_event_handler::event_id id)
{
    ACESTL_ASSERT(NULL != id);

    return m_callbackHook.reactor()->cancel_timer(static_cast<long>(reinterpret_cast<as_size_t>(id - 1)));
}

inline custom_event_handler::bool_type custom_event_handler::is_valid() const
{
    return true;
}

inline custom_event_handler::custom_event_handler(  ACE_Reactor*    reactor    /* =   ACE_Reactor::instance() */
                                                ,   int             priority    /* =   ACE_Event_Handler::LO_PRIORITY */)
    : parent_class_type(reactor, priority)
    , m_callbackHook(get_this_(), reactor, priority)
{
    ACESTL_ASSERT(NULL != reactor);
    ACESTL_MESSAGE_ASSERT("invariant violation", is_valid());
}

inline custom_event_handler::~custom_event_handler() stlsoft_throw_0()
{
    ACESTL_MESSAGE_ASSERT("invariant violation", is_valid());

    ACESTL_MESSAGE_ASSERT("Custom event handler destroyed with outstanding entries: derived classes should cancel all notifications", m_entries.empty());
}

inline custom_event_handler::event_id custom_event_handler::schedule_custom_event(long code, ACE_Time_Value const& delay, void *arg /* = 0 */)
{
    ACESTL_MESSAGE_ASSERT("invariant violation", is_valid());

    // Create an event, and then schedule it.

    event_info* entry_;

    ACE_NEW_NORETURN(entry_, event_info(code, arg));

    if(NULL == entry_)
    {
        ACESTL_MESSAGE_ASSERT("invariant violation", is_valid());

        ACE_ERROR_RETURN(   (   LM_ALERT
                            ,   ACE_TEXT("(%P|%t) out of memory"))
                        ,   0);
    }
    else
    {
        info_ptr    entry(entry_);
        event_id    timerId =   schedule_event_(entry.get(), delay);

        if(NULL == timerId)
        {
            ACESTL_MESSAGE_ASSERT("invariant violation", is_valid());

            ACE_ERROR_RETURN(   (   LM_ALERT
                                ,   ACE_TEXT("(%P|%t) timer registration failed"))
                            ,   0);
        }
        else
        {
            entry->id = timerId;

            try
            {
                // Benign if leaves code but fails to add event
                m_entries[code][timerId] = entry;
            }
            catch(std::bad_alloc &) // This clause is fine, since if bad_alloc not thrown, no foul
            {
                cancel_event_(timerId);

                ACESTL_MESSAGE_ASSERT("invariant violation", is_valid());

                ACE_OS::last_error(ENOMEM);
                ACE_ERROR_RETURN(   (   LM_ALERT
                                    ,   ACE_TEXT("(%P|%t) out of memory"))
                                ,   0);
            }
            catch(std::exception &x)
            {
                cancel_event_(timerId);

                ACESTL_MESSAGE_ASSERT("invariant violation", is_valid());

                ACE_ERROR_RETURN(   (   LM_ALERT
                                    ,   ACE_TEXT("(%P|%t) event scheduling failed: %s")
                                    ,   x.what())
                                ,   0);
            }

            ACESTL_MESSAGE_ASSERT("event not in handler", this->has_custom_event(timerId));

            ACESTL_MESSAGE_ASSERT("invariant violation", is_valid());

            return timerId;
        }
    }
}

inline custom_event_handler::event_id custom_event_handler::schedule_custom_event(long code, void *arg /* = 0 */)
{
    ACESTL_MESSAGE_ASSERT("invariant violation", is_valid());

    return schedule_custom_event(code, ACE_Time_Value(0), arg);
}

inline int custom_event_handler::cancel_custom_events(long code, custom_event_handler::cancelled_event_code_fn pfn, void* param)
{
    ACESTL_MESSAGE_ASSERT("invariant violation", is_valid());

    event_code_map_type::iterator it = m_entries.find(code);

    if(m_entries.end() == it)
    {
        ACESTL_MESSAGE_ASSERT("invariant violation", is_valid());

        return 0;
    }
    else
    {
        // Now need to cancel the timers for all the events in the code map
        event_map_type&             codes   =   (*it).second;
        event_map_type::iterator    begin   =   codes.begin();
        event_map_type::iterator    end     =   codes.end();
        as_int_t                    n;

        for(n = 0; begin != end; ++begin)
        {
            info_ptr entry = (*begin).second;

            if(NULL != pfn)
            {
                (*pfn)(param, entry->code, entry->id, entry->arg);
            }

            if(cancel_event_(entry->id))
            {
                ++n;
            }
        }

        m_entries.erase(it);

        ACESTL_MESSAGE_ASSERT("invariant violation", is_valid());

        return n;
    }
}

inline int custom_event_handler::cancel_custom_events(long code)
{
    return cancel_custom_events(code, NULL, NULL);
}

inline int custom_event_handler::cancel_custom_event(custom_event_handler::event_id event, void **parg /* = NULL */)
{
    ACESTL_MESSAGE_ASSERT("invariant violation", is_valid());

    /// TODO: Maybe improve the performance of this later, perhaps by having a second map of id=>entry

    event_code_map_type::iterator    be  =   m_entries.begin();
    event_code_map_type::iterator    ee  =   m_entries.end();

    for(; be != ee; ++be)
    {
        event_map_type&             event_map   =   (*be).second;
        event_map_type::iterator    it          =   event_map.find(event);

        if(event_map.end() != it)
        {
            if(NULL != parg)
            {
                *parg = (*it).second->arg;
            }

            event_map.erase(it);

            return cancel_event_(event);
        }
    }

    return 0;
}

inline as_int_t custom_event_handler::has_custom_events(long code) const
{
    ACESTL_MESSAGE_ASSERT("invariant violation", is_valid());

    event_code_map_type::const_iterator it = m_entries.find(code);

    return (m_entries.end() != it) ? static_cast<as_int_t>((*it).second.size()) : 0;
}

inline as_int_t custom_event_handler::has_custom_event(long code) const
{
    return this->has_custom_events(code);
}

inline as_int_t custom_event_handler::has_custom_event(event_id event) const
{
    ACESTL_MESSAGE_ASSERT("invariant violation", is_valid());

    /// TODO: Maybe improve the performance of this later, perhaps by having a second map of id=>entry

    event_code_map_type::const_iterator  be      =   m_entries.begin();
    event_code_map_type::const_iterator  ee      =   m_entries.end();

    for(; be != ee; ++be)
    {
        event_map_type const&           event_map   =   (*be).second;
        event_map_type::const_iterator  it          =   event_map.find(event);

        if(event_map.end() != it)
        {
            return 1;
        }
    }

    return 0;
}

inline int custom_event_handler::handle_callback_timeout(ACE_Time_Value const& current_time, void* arg)
{
    ACESTL_MESSAGE_ASSERT("invariant violation", is_valid());

    event_info const*               entry  =   static_cast<event_info const*>(arg);
    event_code_map_type::iterator   itc     =   m_entries.find(entry->code);

    // Is it one of ours?
    if(m_entries.end() == itc)
    {
        ACESTL_MESSAGE_ASSERT("invariant violation", is_valid());

        ACE_ERROR_RETURN(   (   LM_ALERT
                            ,   ACE_TEXT("(%P|%t) could not locate callback entry for that code"))
                        ,   0); // NOTE: returns 0, so as not to cause the event handler to be de-registered
    }
    else
    {
        ACESTL_MESSAGE_ASSERT("invariant violation", is_valid());

        // Yes it is. So ...
        event_map_type              &event_map  =   (*itc).second;
        event_map_type::iterator    ite         =   event_map.find(entry->id);

        ACESTL_ASSERT(event_map.end() != ite);

        // ... keep the entry alive, and ...
        info_ptr    ep = (*ite).second;

        // ... we erase the entry, and ...
        event_map.erase(ite);

        // ... check whether we need to erase the entries map, and ...
        if(event_map.empty())
        {
            m_entries.erase(itc);
        }

        ACESTL_MESSAGE_ASSERT("invariant violation", is_valid());

        // ... then call the handler
        return this->handle_custom_event(current_time, entry->code, entry->arg);
    }
}

#ifdef STLSOFT_COMPILER_IS_MSVC
# if _MSC_VER >= 1200
#  pragma warning(push)
# else /* ? compiler */
#  pragma warning(default : 4702)
# endif /* _MSC_VER */
#endif /* compiler */

#endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */

/* ////////////////////////////////////////////////////////////////////// */

#ifndef _ACESTL_NO_NAMESPACE
# if defined(_STLSOFT_NO_NAMESPACE) || \
     defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
} // namespace acestl
# else
} // namespace acestl_project
} // namespace stlsoft
# endif /* _STLSOFT_NO_NAMESPACE */
#endif /* !_ACESTL_NO_NAMESPACE */

/* ////////////////////////////////////////////////////////////////////// */

#endif /* ACESTL_INCL_ACESTL_REACTOR_HPP_CUSTOM_EVENT_HANDLER */

/* ////////////////////////////////////////////////////////////////////// */

⌨️ 快捷键说明

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