📄 custom_event_handler.hpp
字号:
/* /////////////////////////////////////////////////////////////////////////
* File: acestl/custom_event_handler.hpp
*
* Purpose: Event handler class for custom event notifications.
*
* Created: 1st October 2004
* Updated: 10th June 2006
*
* Home: http://stlsoft.org/
*
* Copyright (c) 2004-2006, Matthew Wilson and Synesis Software
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name(s) of Matthew Wilson and Synesis Software nor the names of
* any contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* ////////////////////////////////////////////////////////////////////// */
/// \file acestl/custom_event_handler.hpp
///
/// Event handler class for custom event notifications.
#ifndef ACESTL_INCL_ACESTL_HPP_CUSTOM_EVENT_HANDLER
#define ACESTL_INCL_ACESTL_HPP_CUSTOM_EVENT_HANDLER
#ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
# define ACESTL_VER_ACESTL_HPP_CUSTOM_EVENT_HANDLER_MAJOR 1
# define ACESTL_VER_ACESTL_HPP_CUSTOM_EVENT_HANDLER_MINOR 5
# define ACESTL_VER_ACESTL_HPP_CUSTOM_EVENT_HANDLER_REVISION 8
# define ACESTL_VER_ACESTL_HPP_CUSTOM_EVENT_HANDLER_EDIT 39
#endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
/* /////////////////////////////////////////////////////////////////////////
* Includes
*/
#ifndef ACESTL_INCL_ACESTL_HPP_ACESTL
# include <acestl/acestl.hpp>
#endif /* !ACESTL_INCL_ACESTL_HPP_ACESTL */
#include <ace/Event_Handler.h> // for ACE_Event_Handler
#include <ace/Reactor.h> // for ACE_Reactor
#ifndef STLSOFT_INCL_STLSOFT_HPP_SHARED_PTR
# include <stlsoft/shared_ptr.hpp>
#endif /* !STLSOFT_INCL_STLSOFT_HPP_SHARED_PTR */
#include <map>
/* /////////////////////////////////////////////////////////////////////////
* Compatibility
*/
#if defined(STLSOFT_COMPILER_IS_INTEL) || \
( defined(STLSOFT_COMPILER_IS_MSVC) && \
_MSC_VER >= 1200)
# define ACESTL_CUSTOM_EVENT_HANDLER_CANCEL_EVENTS_MEMBER_CLEANUP_SUPPORT
#endif /* compiler */
/* /////////////////////////////////////////////////////////////////////////
* Namespace
*/
#ifndef _ACESTL_NO_NAMESPACE
# if defined(_STLSOFT_NO_NAMESPACE) || \
defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
/* There is no stlsoft namespace, so must define ::acestl */
namespace acestl
{
# else
/* Define stlsoft::acestl_project */
namespace stlsoft
{
namespace acestl_project
{
# endif /* _STLSOFT_NO_NAMESPACE */
#endif /* !_ACESTL_NO_NAMESPACE */
/* ////////////////////////////////////////////////////////////////////// */
/// \weakgroup libraries STLSoft Libraries
/// \brief The individual libraries
/// \weakgroup libraries_messaging Messaging Library
/// \ingroup libraries
/// \brief This library provides facilities for defining and manipulating messaging constructs
/// \defgroup acestl_messaging_library Messaging Library (ACESTL)
/// \ingroup ACESTL libraries_messaging
/// \brief This library provides facilities for defining and manipulating messaging constructs with ACE
/// @{
/* ////////////////////////////////////////////////////////////////////// */
/// Utility class that establishes a root type for the cancel_adaptor and the
/// custom_event_handler classes
struct ceh_root
{
private:
struct event_id_ {};
public:
typedef event_id_ *event_id;
};
/// Adaptor class that facilitates the
/// custom_event_handler::cancel_custom_events() member function template.
template<ss_typename_param_k C>
struct cancel_adapter
: public ceh_root
{
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);
};
/* /////////////////////////////////////////////////////////////////////////
* Classes
*/
/// \brief This class provides custom event notification for the ACE Reactor
/// framework
///
/// It provides the ability to schedule a custom event with a code, an optional
/// delay, and an optional argument
///
/// To use, derive from it as you would from ACE_Event_Handler, and override the
/// handle_custom_event() method, e.g
///
/// \htmlonly
/// <pre>
///
/// class MyHandler
/// : public acestl::custom_event_handler
/// {
/// private:
/// virtual int handle_custom_event(ACE_Time_Value const ¤t_time
/// , long event_code
/// , void *arg)
/// {
/// fprintf(stdout, "Received custom event: %ld, %p\n", event_code, arg);
///
/// return 0;
/// }
/// . . .
/// };
///
/// acestl::custom_event_handler *eh = new MyHandler();
///
/// // Schedule an event with id 100
/// eh->schedule_custom_event(100);
///
/// // Schedule an event for 10 seconds hence, with id 200
/// eh->schedule_custom_event(200, ACE_Time_Value(10));
///
/// // Schedule an event for 10 seconds hence, with id 300, and an argument in a string instance
/// eh->schedule_custom_event(300, ACE_Time_Value(10), new std::string("300"));
///
/// // Start the reactor loop. Events will be dispatched from here on in
/// ACE_Reactor::instance()->run_reactor_event_loop();
///
/// </pre>
/// \endhtmlonly
class custom_event_handler
: public ACE_Event_Handler
, public ceh_root
{
/// \name Types
/// @{
private:
struct event_id_ {};
public:
typedef ACE_Event_Handler parent_class_type;
typedef custom_event_handler class_type;
/// The type that represents a pending event instance
// typedef event_id_ *event_id;
/// Type of the callback function that may be passed to cancel_custom_events, which will
/// receive information on each cancelled event instance.
typedef void (*cancelled_event_code_fn)(void *param, long code, event_id id, void *arg);
/// @}
/// \name Construction
/// @{
protected:
/// Constructor
///
/// \param reactor The reactor instance with which this event-handler will interact
/// \param priority The priority for this handler
ss_explicit_k custom_event_handler( ACE_Reactor *reactor = ACE_Reactor::instance()
, int priority = ACE_Event_Handler::LO_PRIORITY);
public:
/// Destructor
virtual ~custom_event_handler() stlsoft_throw_0();
/// @}
/// \name Operations
/// @{
public:
/// 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
///
/// \note 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
///
/// \note 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 events 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
///
/// \param code The code of the events 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
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 */
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:
/// \brief 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_event(long code) const;
/// \brief 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
private:
// The callback function, to be implemented by derived classes
virtual int handle_custom_event(ACE_Time_Value const ¤t_time
, long event_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 ¤t_time
, const void *arg)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -