prefix_ void senf::ppi::connector::Connector::connect(Connector & target)
{
- SENF_ASSERT( module_ && ! peer_ && target.module_ && ! target.peer_ );
+ // The connector is not registered -> route() or noroute() statement missing
+ SENF_ASSERT( module_ );
+ // The connector is already connected
+ SENF_ASSERT( ! peer_ );
+ // The target connector is not registered -> route() or noroute() statement missing
+ SENF_ASSERT( target.module_ );
+ // The target connector is already connected
+ SENF_ASSERT( ! target.peer_ );
if (! (packetTypeID() == typeid(void) ||
target.packetTypeID() == typeid(void) ||
packetTypeID() == target.packetTypeID()) )
prefix_ void senf::ppi::connector::Connector::disconnect()
{
+ // Cannot disconnected a non-connected connector
SENF_ASSERT( peer_ );
Connector & peer (*peer_);
peer_ = 0;
prefix_ senf::ppi::connector::Connector & senf::ppi::connector::Connector::peer()
const
{
+ // The connector is not connected
SENF_ASSERT(peer_);
return *peer_;
}
prefix_ senf::ppi::module::Module & senf::ppi::connector::Connector::module()
const
{
+ // The connector is not registered in the module -> probably a route() or noroute() statement is
+ // missing.
SENF_ASSERT(module_);
return *module_;
}
prefix_ void senf::ppi::connector::PassiveConnector::emit()
{
+ // No event callback has been registered (onEvent() call missing)
SENF_ASSERT(callback_);
if (!throttled())
callback_();
prefix_ senf::Packet senf::ppi::connector::InputConnector::peek()
const
{
+ // Cannot peek() head of empty queue
SENF_ASSERT( ! queue_.empty() );
return queue_.back();
}
throttled.
\note ActiveFeederSink does \e not have a termination condition like ActiveFeederSource, it
- relies on the network to throttle it's input. Also, the same not as for
- ActiveFeederSource applies here too: You need to ensure, that no events are active
- eventually or senf::ppi::run will not return.
+ relies on the network to throttle it's input. Additionally, the restrictions of
+ ActiveFeederSource apply here too: You need to ensure, that no (additional) events are
+ active (eventually) or senf::ppi::run will not return.
ActiveFeederSink is not a module but a collection of two modules: a PassiveSink and an
ActiveFeeder.
event.enable();
}
+ void v_init() {
+ // Optional. Called after before running the module but after connections have been
+ // set up. This is either directly before senf::ppi::run() or senf::ppi::init() is
+ // called or, for modules created while the PPI is already running, after returning
+ // from all event handlers but before going back to the event loop.
+ }
+
};
\endcode
private:
#endif
- virtual void v_init();
+ virtual void v_init(); ///< Called after module setup
+ /**< This member is called directly before the PPI (resumes)
+ execution. It is called after connections have been
+ setup before entering the PPI main loop.
+
+ You may overload this member. Your overload should
+ always call the base-class implementation. */
#ifndef DOXYGEN
public:
prefix_ senf::ppi::ModuleManager::ModuleManager()
: running_(false), terminate_(false),
initRunner_ ("senf::ppi::init", membind(&ModuleManager::init, this), false,
- scheduler::EventEvent::PRIORITY_LOW)
+ scheduler::EventHook::POST)
{}
///////////////////////////////cc.e////////////////////////////////////////
InitQueue initQueue_;
- scheduler::EventEvent initRunner_;
+ scheduler::EventHook initRunner_;
friend class module::Module;
friend class Initializable;
senf::ArrayParser<elements,ElementParser>::operator[](difference_type i)
const
{
+ // Access out of range element
SENF_ASSERT( i>=0 && i < difference_type(elements) );
return begin()[i];
}
itself but gives us some information about the packet: A timestamp, the interface the packet was
received on or other processing related information.
- This type of information can be stored using the annotation interface.
+ This type of information can be stored using the annotation interface. The following example
+ will read packet data and will store the read timestamp as a packet annotation.
\code
struct Timestamp {
}
\endcode
- It is very important to define a specific structure (or class) type for each type of
+ It is very important to define a specific structure (or class or enum) type for each type of
annotation. \e Never directly store a fundamental type as an annotation: The name of the type is
used to look up the annotation, so you can store only one annotation for each built-in type. \c
typedef does not help since \c typedef does not introduce new type names, it only defines an
}
\endcode
+ Every annotation is automatically default-initialized, there is no way to query, whether a
+ packet holds a specific annotation -- every packet conceptually always holds all annotations.
+
You should use annotations economically: Every annotation type used in your program will
allocate an annotation slot in \e all packet data structures. So don't use hundreds of different
annotation types if this is not really necessary: Reuse annotation types where possible or
\endcode
(This type is not POD since \c std::string is not POD)
+ \see \ref packet_usage_annotation
+
\implementation The annotation system is implemented
quite efficiently since annotations are stored
within a packet embedded vector of fixed size (the
# Create Doxyfile.local otherwise doxygen will barf on this non-existent file
# Create it even when cleaning, to silence the doxygen builder warnings
-if not env.GetOption('clean') and not os.path.exists("Doxyfile.local"):
+if not os.path.exists("Doxyfile.local"):
Execute(Touch("Doxyfile.local"))
# Create local_config.h
// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
/** \file
- \brief EventEvent non-inline non-template implementation */
+ \brief EventHook non-inline non-template implementation */
-#include "EventEvent.hh"
-#include "EventEvent.ih"
+#include "EventHook.hh"
+#include "EventHook.ih"
// Custom includes
-//#include "EventEvent.mpp"
+//#include "EventHook.mpp"
#define prefix_
///////////////////////////////cc.p////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
-// senf::scheduler::EventEvent
+// senf::scheduler::EventHook
-prefix_ void senf::scheduler::EventEvent::v_run()
+prefix_ void senf::scheduler::EventHook::v_run()
{
cb_();
}
-prefix_ char const * senf::scheduler::EventEvent::v_type()
+prefix_ char const * senf::scheduler::EventHook::v_type()
const
{
return "ee";
}
-prefix_ std::string senf::scheduler::EventEvent::v_info()
+prefix_ std::string senf::scheduler::EventHook::v_info()
const
{
return "";
}
///////////////////////////////////////////////////////////////////////////
-// senf::scheduler::detail::EventEventDispatcher
+// senf::scheduler::detail::EventHookDispatcher
-prefix_ senf::scheduler::detail::EventEventDispatcher::~EventEventDispatcher()
+prefix_ senf::scheduler::detail::EventHookDispatcher::~EventHookDispatcher()
{
for (EventList::iterator i (events_.begin()); i != events_.end(); ++i)
FIFORunner::instance().dequeue(&(*i));
}
-prefix_ prefix_ void senf::scheduler::detail::EventEventDispatcher::remove(EventEvent & event)
+prefix_ prefix_ void senf::scheduler::detail::EventHookDispatcher::remove(EventHook & event)
{
EventList::iterator i (EventList::current(event));
if (i == events_.end())
events_.erase(i);
}
-prefix_ void senf::scheduler::detail::EventEventDispatcher::prepareRun()
+prefix_ void senf::scheduler::detail::EventHookDispatcher::prepareRun()
{
for (EventList::iterator i (events_.begin()); i != events_.end(); ++i)
i->setRunnable();
///////////////////////////////cc.e////////////////////////////////////////
#undef prefix_
-//#include "EventEvent.mpp"
+//#include "EventHook.mpp"
\f
// Local Variables:
// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
/** \file
- \brief EventEvent inline non-template implementation */
+ \brief EventHook inline non-template implementation */
-#include "EventEvent.ih"
+#include "EventHook.ih"
// Custom includes
///////////////////////////////cci.p///////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
-// senf::scheduler::EventEvent
+// senf::scheduler::EventHook
-prefix_ senf::scheduler::EventEvent::EventEvent(std::string const & name, Callback const & cb,
+prefix_ senf::scheduler::EventHook::EventHook(std::string const & name, Callback const & cb,
bool initiallyEnabled,
detail::FIFORunner::TaskInfo::Priority priority)
: detail::FIFORunner::TaskInfo(name, priority), cb_ (cb)
enable();
}
-prefix_ senf::scheduler::EventEvent::~EventEvent()
+prefix_ senf::scheduler::EventHook::~EventHook()
{
- if (detail::EventEventDispatcher::alive())
+ if (detail::EventHookDispatcher::alive())
disable();
}
-prefix_ void senf::scheduler::EventEvent::disable()
+prefix_ void senf::scheduler::EventHook::disable()
{
if (enabled())
- detail::EventEventDispatcher::instance().remove(*this);
+ detail::EventHookDispatcher::instance().remove(*this);
}
-prefix_ void senf::scheduler::EventEvent::enable()
+prefix_ void senf::scheduler::EventHook::enable()
{
if (! enabled())
- detail::EventEventDispatcher::instance().add(*this);
+ detail::EventHookDispatcher::instance().add(*this);
}
-prefix_ void senf::scheduler::EventEvent::action(Callback const & cb)
+prefix_ void senf::scheduler::EventHook::action(Callback const & cb)
{
cb_ = cb;
}
///////////////////////////////////////////////////////////////////////////
-// senf::scheduler::detail::EventEventDispatcher
+// senf::scheduler::detail::EventHookDispatcher
-prefix_ void senf::scheduler::detail::EventEventDispatcher::add(EventEvent & event)
+prefix_ void senf::scheduler::detail::EventHookDispatcher::add(EventHook & event)
{
events_.push_back(event);
FIFORunner::instance().enqueue(&event);
}
-prefix_ bool senf::scheduler::detail::EventEventDispatcher::empty()
+prefix_ bool senf::scheduler::detail::EventHookDispatcher::empty()
const
{
return events_.empty();
}
-prefix_ senf::scheduler::detail::EventEventDispatcher::EventEventDispatcher()
+prefix_ senf::scheduler::detail::EventHookDispatcher::EventHookDispatcher()
{}
///////////////////////////////cci.e///////////////////////////////////////
// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
/** \file
- \brief EventEvent public header */
+ \brief EventHook public header */
-#ifndef HH_EventEvent_
-#define HH_EventEvent_ 1
+#ifndef HH_EventHook_
+#define HH_EventHook_ 1
// Custom includes
#include <boost/function.hpp>
#include "../boost/intrusive/ilist_hook.hpp"
#include "FIFORunner.hh"
-//#include "EventEvent.mpp"
+//#include "EventHook.mpp"
///////////////////////////////hh.p////////////////////////////////////////
namespace senf {
namespace scheduler {
namespace detail {
- struct EventEventListTag;
- typedef boost::intrusive::ilist_base_hook<EventEventListTag> EventEventListBase;
- class EventEventDispatcher;
+ struct EventHookListTag;
+ typedef boost::intrusive::ilist_base_hook<EventHookListTag> EventHookListBase;
+ class EventHookDispatcher;
}
/** \brief Event hook event
void beforeEventHook();
void afterEventHook();
- senf::scheduler::EventEvent beforeEventHookEvent (
- "beforeEventHook", beforeEventHook, true, senf::scheduler::EventEvent::PRIORITY_LOW);
- senf::scheduler::EventEvent afterEventHookEvent (
- "afterEventHook", afterEventHook, true, senf::scheduler::EventEvent::PRIORITY_HIGH);
+ senf::scheduler::EventHook beforeEventHookEvent (
+ "beforeEventHook", beforeEventHook, true, senf::scheduler::EventHook::POST);
+ senf::scheduler::EventHook afterEventHookEvent (
+ "afterEventHook", afterEventHook, true, senf::scheduler::EventHook::PRE);
\endcode
- This usage assumes, that all ordinary events are registered with \c PRIORITY_NORMAL.
-
- The EventEvent class is an implementation of the RAII idiom: The event will be automatically
- unregistered in the EventEvent destructor. The EventEvent instance should be created within
+ The EventHook class is an implementation of the RAII idiom: The event will be automatically
+ unregistered in the EventHook destructor. The EventHook instance should be created within
the same scope or on a scope below where the callback is defined (e.g. if the callback is a
member function it should be defined as a class member).
*/
- class EventEvent
+ class EventHook
: public detail::FIFORunner::TaskInfo,
- public detail::EventEventListBase
+ public detail::EventHookListBase
{
public:
///////////////////////////////////////////////////////////////////////////
typedef boost::function<void ()> Callback;
+ static Priority const PRE = PRIORITY_HIGH; ///< Execute hook BEFORE all other events
+ static Priority const POST = PRIORITY_LOW; ///< Execute hook AFTER all other events
+
///////////////////////////////////////////////////////////////////////////
///\name Structors and default members
///@{
- EventEvent(std::string const & name, Callback const & cb,
- bool initiallyEnabled = true, Priority priority = PRIORITY_NORMAL);
+ EventHook(std::string const & name, Callback const & cb,
+ bool initiallyEnabled = true, Priority priority = POST);
///< Register an event hook
/**< Registers \a cb to be called whenever any other event
is signaled by the scheduler. If \a initiallyEnabled is
\param[in] initiallyEnabled if set \c false, do not
enable callback automatically.
\param[in] priority event priority, defaults to
- PRIORITY_NORMAL */
- ~EventEvent();
+ POST */
+ ~EventHook();
///@}
///////////////////////////////////////////////////////////////////////////
Callback cb_;
- friend class detail::EventEventDispatcher;
+ friend class detail::EventHookDispatcher;
};
}}
///////////////////////////////hh.e////////////////////////////////////////
-#include "EventEvent.cci"
-//#include "EventEvent.ct"
-//#include "EventEvent.cti"
+#include "EventHook.cci"
+//#include "EventHook.ct"
+//#include "EventHook.cti"
#endif
\f
// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
/** \file
- \brief EventEvent internal header */
+ \brief EventHook internal header */
-#ifndef IH_EventEvent_
-#define IH_EventEvent_ 1
+#ifndef IH_EventHook_
+#define IH_EventHook_ 1
// Custom includes
#include "../Utils/singleton.hh"
namespace detail {
- class EventEventDispatcher
- : public singleton<EventEventDispatcher>
+ class EventHookDispatcher
+ : public singleton<EventHookDispatcher>
{
public:
- using singleton<EventEventDispatcher>::instance;
- using singleton<EventEventDispatcher>::alive;
+ using singleton<EventHookDispatcher>::instance;
+ using singleton<EventHookDispatcher>::alive;
- void add(EventEvent & event);
- void remove(EventEvent & event);
+ void add(EventHook & event);
+ void remove(EventHook & event);
void prepareRun();
bool empty() const;
private:
- EventEventDispatcher();
- ~EventEventDispatcher();
+ EventHookDispatcher();
+ ~EventHookDispatcher();
typedef boost::intrusive::ilist<
- EventEventListBase::value_traits<EventEvent>, false > EventList;
+ EventHookListBase::value_traits<EventHook>, false > EventList;
EventList events_;
friend void senf::scheduler::restart();
- friend class singleton<EventEventDispatcher>;
+ friend class singleton<EventHookDispatcher>;
};
}}}
prefix_ senf::ReadHelper<Handle>::ReadHelper(Handle handle, std::string::size_type maxSize,
InternalPredicate * predicate, Callback cb)
: handle_(handle),
- fde_("ReadHelper", boost::bind(&ReadHelper::dispatchProcess,ptr(this), handle, _1),
+ fde_("senf::ReadHelper", boost::bind(&ReadHelper::dispatchProcess,ptr(this), handle, _1),
handle, senf::scheduler::FdEvent::EV_READ),
maxSize_(maxSize), predicate_(predicate), callback_(cb), errno_(0), complete_(false)
{
detail::TimerDispatcher::instance().blockSignals();
detail::SignalDispatcher::instance().blockSignals();
detail::FileDispatcher::instance().prepareRun();
- detail::EventEventDispatcher::instance().prepareRun();
+ detail::EventHookDispatcher::instance().prepareRun();
detail::FIFORunner::instance().run();
}
}
detail::TimerDispatcher* tdd (&detail::TimerDispatcher::instance());
detail::SignalDispatcher* sdd (&detail::SignalDispatcher::instance());
detail::FileDispatcher* fld (&detail::FileDispatcher::instance());
- detail::EventEventDispatcher* eed (&detail::EventEventDispatcher::instance());
+ detail::EventHookDispatcher* eed (&detail::EventHookDispatcher::instance());
- eed->~EventEventDispatcher();
+ eed->~EventHookDispatcher();
fld->~FileDispatcher();
sdd->~SignalDispatcher();
tdd->~TimerDispatcher();
new (tdd) detail::TimerDispatcher();
new (sdd) detail::SignalDispatcher();
new (fld) detail::FileDispatcher();
- new (eed) detail::EventEventDispatcher();
+ new (eed) detail::EventHookDispatcher();
}
prefix_ bool senf::scheduler::empty()
&& detail::TimerDispatcher::instance().empty()
&& detail::FileDispatcher::instance().empty()
&& detail::SignalDispatcher::instance().empty()
- && detail::EventEventDispatcher::instance().empty();
+ && detail::EventHookDispatcher::instance().empty();
}
///////////////////////////////////////////////////////////////////////////
#include "FdEvent.hh"
#include "TimerEvent.hh"
#include "SignalEvent.hh"
-#include "EventEvent.hh"
+#include "EventHook.hh"
//#include "scheduler.mpp"
///////////////////////////////hh.p////////////////////////////////////////
\li senf::scheduler::FdEvent for file descriptor events
\li senf::scheduler::TimerEvent for single-shot deadline timer events
\li senf::scheduler::SignalEvent for UNIX signal events
- \li senf::scheduler::EventEvent for a special event hook
+ \li senf::scheduler::EventHook for a special event hook
These instance are owned and managed by the user of the scheduler \e not by the scheduler so the
RAII concept can be used.
///////////////////////////////////////////////////////////////////////////
- senf::scheduler::EventEvent evev ("eventCounter", eventeventhandler, true,
- senf::scheduler::EventEvent::PRIORITY_HIGH);
+ senf::scheduler::EventHook evev ("eventCounter", eventeventhandler, true,
+ senf::scheduler::EventHook::PRE);
{
senf::scheduler::FdEvent fde1 ("testFdEvent", boost::bind(&callback, sock, _1),