📄 custom_event_handler.hpp
字号:
/* /////////////////////////////////////////////////////////////////////////
* File: acestl/reactor/custom_event_handler.hpp
*
* Purpose: Event handler class for custom event notifications.
*
* Created: 1st October 2004
* Updated: 2nd June 2007
*
* Home: http://stlsoft.org/
*
* Copyright (c) 2004-2007, 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/reactor/custom_event_handler.hpp
*
* \brief [C++ only] Definition of the acestl::custom_event_handler
* class template
* (\ref group__library__ace_reactor "ACE Reactor" Library).
*/
#ifndef ACESTL_INCL_ACESTL_REACTOR_HPP_CUSTOM_EVENT_HANDLER
#define ACESTL_INCL_ACESTL_REACTOR_HPP_CUSTOM_EVENT_HANDLER
#ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
# define ACESTL_VER_ACESTL_REACTOR_HPP_CUSTOM_EVENT_HANDLER_MAJOR 2
# define ACESTL_VER_ACESTL_REACTOR_HPP_CUSTOM_EVENT_HANDLER_MINOR 1
# define ACESTL_VER_ACESTL_REACTOR_HPP_CUSTOM_EVENT_HANDLER_REVISION 1
# define ACESTL_VER_ACESTL_REACTOR_HPP_CUSTOM_EVENT_HANDLER_EDIT 16
#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_SMARTPTR_HPP_SHARED_PTR
# include <stlsoft/smartptr/shared_ptr.hpp>
#endif /* !STLSOFT_INCL_STLSOFT_SMARTPTR_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 */
/* ////////////////////////////////////////////////////////////////////// */
#ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
/** Utility class that establishes a root type for the
* acestl::cancel_adaptor and acestl::custom_event_handler classes.
* \ingroup group__library__ace_reactor
*/
struct ceh_root
{
private:
struct event_id_ {};
public:
typedef event_id_* event_id;
};
/** Adaptor class that facilitates the
* acestl::custom_event_handler::cancel_custom_events() member function
* template.
* \ingroup group__library__ace_reactor
*/
template<ss_typename_param_k C>
struct cancel_adapter
#ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
: public ceh_root
#endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
{
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 /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
/* /////////////////////////////////////////////////////////////////////////
* Classes
*/
/** This class enhances
* the \ref group__library__ace_reactor "ACE Reactor" framework by
* providing custom event notifications for event handlers, with zero
* interference with existing reactor/handler functionality.
*
* \ingroup group__library__ace_reactor
*
* 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
*
\code
using acestl::custom_event_handler;
// 1. Our custom event handler class
class MyHandler
: public custom_event_handler
{
private:
// 2. This method required by acestl::custom_event_handler
virtual int handle_custom_event(ACE_Time_Value const& current_time
, long code
, void* arg)
{
fprintf(stdout, "Received custom event: %ld, %p\n", code, arg);
if(300 == code)
{
std::string* str = static_cast<std::string*>(arg);
delete str;
}
return 0;
}
. . .
// 3. This is one of several methods required by ACE_Event_Handler
virtual int handle_timeout( const ACE_Time_Value ¤t_time
, const void *arg)
{
return 0;
}
};
// 4. A cleanup function to ensure that the custom data associated with
// 300 events is not lost; see step 10.
void cleanup_300_proc(void *param, long code, custom_event_handler::event_id id, void *arg)
{
assert(300 == code);
int& num300sCancelled = *static_cast<int*>(param);
std::string* str = static_cast<std::string*>(arg);
++num300sCancelled;
delete str;
}
// 5. Create an instance of MyHandler
custom_event_handler* mh = new MyHandler();
// 6. Schedule an event with id 100, testing the return to ensure it's
// been scheduled without error
if(NULL == mh->schedule_custom_event(100))
{
std::err << "Failed to scheduled event (code=100)!" << std::endl;
}
else
{
// It's been scheduled ok
//
// This assert simply enforces what we know: that there is 1 or more
// (1 in this case) pending events whose event code is 100
//
// Note: we can only assert this here because we have not yet
// started the reactor event loop; see step 11.
assert(mh->has_custom_events(100));
}
// 7. Schedule an event with id 200 to be dispatched in 10 seconds
custom_event_handler::event_id id200 = mh->schedule_custom_event(200, ACE_Time_Value(10));
// 8. Schedule an event with id 300 to be dispatched in 20 seconds, with
// a custom argument (an instance of std::string)
mh->schedule_custom_event(300, ACE_Time_Value(20), new std::string("300"));
// 9. Cancel the 200 event
//
// Note: you can only cancel a single event via its unique event id.
mh->cancel_custom_event(id200);
// 10. Cancel all 300 events
//
// Remarks: this has to use a cancel handler to 'release' the resource
// associated with the custom argument. If this is not done, then
// the std::string instance would not be destroyed, and we'd have a
// memory leak
//
// Note: Cancelling via an event code cancels *all* pending events with
// that code.
int num300sCancelled = 0;
mh->cancel_custom_events(300, cleanup_300_proc, &num300sCancelled);
assert(1 == num300sCancelled); // Again, this is only valid because event loop not yet started
// 11. Start the reactor loop. Events will be dispatched from here on in
ACE_Reactor::instance()->run_reactor_event_loop();
\endcode
*
*/
// [[synesis:class: acestl::custom_event_handler]]
class custom_event_handler
: public ACE_Event_Handler
#ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
, public ceh_root
#endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
{
/// \name Types
/// @{
private:
struct event_id_ {};
public:
typedef ACE_Event_Handler parent_class_type;
typedef custom_event_handler class_type;
typedef as_bool_t bool_type;
#ifdef STLSOFT_DOCUMENTATION_SKIP_SECTION
/// An opaque type that identifies pending event instances
///
/// The only well-known value is \c NULL, which indicates no-event.
typedef event_id_ *event_id;
#endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
/// Type of the callback function that may be passed to
/// custom_event_handler::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);
/// @}
// Construction
protected:
/** This protected constructor is used to pass initialisation parameters
* throught to the parent (\c ACE_Event_Handler) class from the
* concrete handler class.
*
* \param reactor The reactor instance with which this event-handler will interact
* \param priority The priority for this handler
*
* \exception - Does not throw an exception
*/
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:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -