📄 custom_event_handler.hpp
字号:
#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 + -