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