: boost::noncopyable
{
public:
- Connector & peer(); ///< Get peer connected to this connector
- module::Module & module(); ///< Get this connectors containing module
+ Connector & peer() const; ///< Get peer connected to this connector
+ module::Module & module() const; ///< Get this connectors containing module
protected:
Connector();
operation is to be performed. */
- bool throttled(); ///< Get accumulative throttling state
- bool nativeThrottled(); ///< Get native throttling state
+ bool throttled() const; ///< Get accumulative throttling state
+ bool nativeThrottled() const; ///< Get native throttling state
void throttle(); ///< Set native throttling
void unthrottle(); ///< Revoke native throttling
- void notifyThrottle(); ///< Forward a throttling notification to this connector
- void notifyUnthrottle(); ///< Forward an unthrottling notification to this connector
-
- ActiveConnector & peer();
+ ActiveConnector & peer() const;
protected:
PassiveConnector();
void emit();
private:
+ // Called by the routing to change the remote throttling state
+ void notifyThrottle(); ///< Forward a throttling notification to this connector
+ void notifyUnthrottle(); ///< Forward an unthrottling notification to this connector
+
+ // Internal members to emit throttling notifications
+ void emitThrottle();
+ void emitUnthrottle();
+
+ // Called after unthrottling the connector
+ virtual void v_unthrottleEvent();
typedef detail::Callback<>::type Callback;
Callback callback_;
+
+ bool remoteThrottled_;
+ bool nativeThrottled_;
+
+ friend class senf::ppi::detail::ForwardForwardingRouteImplementation;
+ friend class senf::ppi::detail::BackwardForwardingRouteImplementation;
};
/** \brief Active connector baseclass
class ActiveConnector
: public virtual Connector
{
+ typedef detail::Callback<>::type Callback;
public:
template <class Handler>
- void onThrottle(Handler handle); ///< Register throttle notification handler
+ void onThrottle(Handler handler); ///< Register throttle notification handler
/**< The handler register here will be called, whenever a
throttle notification comes in. The \a handler argument
is either an arbitrary callable object or it is a
this input. In the second case, the pointer will
automatically be bound to the containing instance.
- \param[in] handle Handler to call on throttle
+ \param[in] handler Handler to call on throttle
notifications. */
+ void onThrottle();
template <class Handler>
- void onUnthrottle(Handler handle); ///< Register unthrottle notification handler
+ void onUnthrottle(Handler handler); ///< Register unthrottle notification handler
/**< The handler register here will be called, whenever an
unthrottle notification comes in. The \a handler
argument is either an arbitrary callable object or it
\param[in] handle Handler to call on unthrottle
notifications. */
+ void onUnthrottle();
- PassiveConnector & peer();
+ PassiveConnector & peer() const;
protected:
ActiveConnector();
+
+ private:
+ // called by the peer() to forward throttling notifications
+ void notifyThrottle();
+ void notifyUnthrottle();
+
+ // called by ForwardingRoute to register a new route
+ void registerRoute(ForwardingRoute & route);
+
+ Callback throttleCallback_;
+ Callback unthrottleCallback_;
+
+ typedef std::vector<ForwardingRoute*> NotifyRoutes;
+ NotifyRoutes notifyRoutes_;
+
+ friend class senf::ppi::ForwardingRoute;
+ friend class PassiveConnector;
};
/** \brief Input connector baseclass
be added to the queue before it can be processed.
*/
class InputConnector
- : public virtual Connector,
- public SafeBool<InputConnector>
+ : public virtual Connector
{
typedef std::deque<Packet> Queue;
public:
request cannot be fulfilled, this is considered to be a
logic error in the module implementation and an
exception is raised. */
- bool boolean_test (); ///< Check packet availability
- /**< Using any input connector in a boolean context will
- check, whether an input request can be fulfilled. This
- is always possible if the queue is non-empty. If the
- input is active, it also returns when the connected
- passive output is not throttled so new packets can be
- requested.
-
- Calling the operator() member is an error if this test
- returns \c false
- \returns \c true if operator() can be called, \c false
- otherwise */
+ OutputConnector & peer() const;
- OutputConnector & peer();
+ queue_iterator begin() const; ///< Access queue begin (head)
+ queue_iterator end() const; ///< Access queue past-the-end (tail)
+ Packet peek() const; ///< Return head element from the queue
- queue_iterator begin(); ///< Access queue begin (head)
- queue_iterator end(); ///< Access queue past-the-end (tail)
- Packet peek(); ///< Return head element from the queue
-
- size_type queueSize(); ///< Return number of elements in the queue
- bool empty(); ///< Return queueSize() == 0
+ size_type queueSize() const; ///< Return number of elements in the queue
+ bool empty() const; ///< Return queueSize() == 0
protected:
InputConnector();
public:
void operator()(Packet p); ///< Send out a packet
- InputConnector & peer();
+ InputConnector & peer() const;
protected:
OutputConnector();
/** \brief Combination of PassiveConnector and InputConnector
- In addition to the native and the forwarded throttling state, the PassiveInput manages a
- queue throttling state. This state is automatically managed by a queueing discipline. The
- standard queueing discipline is ThresholdQueueing, which throttles the connection whenever
- the queue length reaches the high threshold and unthrottles the connection when the queue
- reaches the low threshold. The default queueing discipline is
+ The PassiveInput automatically controls the connectors throttling state using a queueing
+ discipline. The standard queueing discipline is ThresholdQueueing, which throttles the
+ connection whenever the queue length reaches the high threshold and unthrottles the
+ connection when the queue reaches the low threshold. The default queueing discipline is
<tt>ThresholdQueueing(1,0)</tt> which will throttle the input whenever the queue is
non-empty.
*/
class PassiveInput
- : public PassiveConnector, public InputConnector
+ : public PassiveConnector, public InputConnector,
+ public SafeBool<PassiveInput>
{
public:
PassiveInput();
- ActiveOutput & peer();
+ ActiveOutput & peer() const;
+
+ bool boolean_test() const;
template <class QDisc>
void qdisc(QDisc const & disc); ///< Change the queueing discipline
private:
void v_enqueueEvent();
void v_dequeueEvent();
+ void v_unthrottleEvent();
boost::scoped_ptr<QueueingDiscipline> qdisc_;
- QueueingDiscipline::State qstate_;
};
/** \brief Combination of PassiveConnector and OutputConnector
*/
class PassiveOutput
- : public PassiveConnector, public OutputConnector
+ : public PassiveConnector, public OutputConnector,
+ public SafeBool<PassiveOutput>
{
public:
- ActiveInput & peer();
+ ActiveInput & peer() const;
+
+ bool boolean_test() const;
void connect(ActiveInput & target);
/** \brief Combination of ActiveConnector and InputConnector
*/
class ActiveInput
- : public ActiveConnector, public InputConnector
+ : public ActiveConnector, public InputConnector,
+ public SafeBool<ActiveInput>
{
public:
- PassiveOutput & peer();
+ PassiveOutput & peer() const;
+
+ bool boolean_test() const;
void request(); ///< request more packets without dequeuing any packet
/** \brief Combination of ActiveConnector and OutputConnector
*/
class ActiveOutput
- : public ActiveConnector, public OutputConnector
+ : public ActiveConnector, public OutputConnector,
+ public SafeBool<ActiveOutput>
{
public:
- ActiveInput & peer();
+ PassiveInput & peer() const;
+
+ bool boolean_test() const;
void connect(PassiveInput & target);
};