PPI: optimized internal connector packet handling (queuing only if necessary, pass...
tho [Wed, 19 Oct 2011 08:15:09 +0000 (08:15 +0000)]
git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1815 270642c3-0616-0410-b53a-bc976706d245

senf/PPI/AnnotationRouter.ct
senf/PPI/Connectors.cc
senf/PPI/Connectors.cci
senf/PPI/Connectors.cti
senf/PPI/Connectors.hh
senf/PPI/Connectors.ih
senf/PPI/Connectors.test.cc
senf/PPI/ThrottleBarrier.cc
site_scons/SparseTestHack.py

index 2b3fade..8cc6ea1 100644 (file)
@@ -56,7 +56,7 @@ connectorSetup(connector::ActiveOutput<> & conn, AnnotationType const & key)
 template <class AnnotationType>
 prefix_ void senf::ppi::module::AnnotationRouter<AnnotationType>::request()
 {
-    Packet p (input());
+    Packet const & p (input());
     typename AnnotationRouter::ContainerType::iterator i (
         this->connectors().find(p.annotation<AnnotationType>()));
     if (i == this->connectors().end())
index 90c593c..7290e01 100644 (file)
@@ -364,19 +364,28 @@ prefix_ void senf::ppi::connector::ActiveConnector::unregisterRoute(ForwardingRo
 //-/////////////////////////////////////////////////////////////////////////////////////////////////
 // senf::ppi::connector::InputConnector
 
-prefix_ senf::Packet senf::ppi::connector::InputConnector::operator()()
+prefix_ senf::Packet const & senf::ppi::connector::InputConnector::operator()()
 {
+    static Packet nullPacket;
+
     if (empty())
         v_requestEvent();
-    if (! empty()) {
-        Packet p ( queue_.back());
+    if (fastPacket_) {
+        Packet const * p = fastPacket_;
+        fastPacket_ = NULL;
+        v_dequeueEvent();
+        SENF_PPI_TRACE(*p, "IN ");
+        return *p;
+    }
+    if (! queue_.empty()) {
+        slowPacket_ = queue_.back();
         queue_.pop_back();
         v_dequeueEvent();
-        SENF_PPI_TRACE(p, "IN ");
-        return p;
+        SENF_PPI_TRACE(slowPacket_, "IN ");
+        return slowPacket_;
     } else {
-        SENF_PPI_TRACE(Packet(), "IN ");
-        return Packet();
+        SENF_PPI_TRACE(nullPacket, "IN ");
+        return nullPacket;
     }
 }
 
index b6407fb..957f15c 100644 (file)
@@ -213,7 +213,7 @@ prefix_ senf::ppi::connector::ActiveConnector::ActiveConnector()
 //-/////////////////////////////////////////////////////////////////////////////////////////////////
 // senf::ppi::connector::InputConnector
 
-prefix_ senf::Packet senf::ppi::connector::InputConnector::read()
+prefix_ senf::Packet const & senf::ppi::connector::InputConnector::read()
 {
     return operator()();
 }
@@ -225,46 +225,24 @@ prefix_ senf::ppi::connector::OutputConnector & senf::ppi::connector::InputConne
     return *peer_;
 }
 
-prefix_ senf::ppi::connector::InputConnector::queue_iterator
-senf::ppi::connector::InputConnector::begin()
-    const
-{
-    return queue_.begin();
-}
-
-prefix_ senf::ppi::connector::InputConnector::queue_iterator
-senf::ppi::connector::InputConnector::end()
-    const
-{
-    return queue_.end();
-}
-
-prefix_ senf::Packet senf::ppi::connector::InputConnector::peek()
-    const
-{
-    // Cannot peek() head of empty queue
-    SENF_ASSERT( ! queue_.empty(),
-                 "senf::ppi::connector::InputConnector: cannot call peek() on empty queue" );
-    return queue_.back();
-}
-
 prefix_ senf::ppi::connector::InputConnector::size_type
 senf::ppi::connector::InputConnector::queueSize()
     const
 {
-    return queue_.size();
+    return queue_.size() + (fastPacket_ ? 1 : 0);
 }
 
 prefix_ bool senf::ppi::connector::InputConnector::empty()
     const
 {
-    return queue_.empty();
+    return fastPacket_ == NULL && queue_.empty();
 }
 
 //-/////////////////////////////////////////////////////////////////////////////////////////////////
 // protected members
 
 prefix_ senf::ppi::connector::InputConnector::InputConnector()
+    : fastPacket_(NULL)
 {}
 
 //-/////////////////////////////////////////////////////////////////////////////////////////////////
@@ -272,8 +250,22 @@ prefix_ senf::ppi::connector::InputConnector::InputConnector()
 
 prefix_ void senf::ppi::connector::InputConnector::enqueue(Packet const & p)
 {
-    queue_.push_front(p);
-    v_enqueueEvent();
+    if (queue_.empty()) {
+        fastPacket_ = &p;
+        try {
+            v_enqueueEvent();
+        } catch (Exception & e) {
+            queue_.push_front(p);
+            throw e;
+        }
+        if (fastPacket_) {
+            queue_.push_front(p);
+            fastPacket_ = NULL;
+        }
+    } else {
+        queue_.push_front(p);
+        v_enqueueEvent();
+    }
 }
 
 //-/////////////////////////////////////////////////////////////////////////////////////////////////
index 225f8e2..82d7bd9 100644 (file)
@@ -42,7 +42,7 @@ template <class Self, class PacketType>
 prefix_ typename senf::ppi::connector::detail::TypedInputMixin<Self,PacketType>::Type
 senf::ppi::connector::detail::TypedInputMixin<Self,PacketType>::operator()()
 {
-    Packet p (static_cast<Self*>(this)->InputConnector::operator()());
+    Packet const & p (static_cast<Self*>(this)->InputConnector::operator()());
     return p ? p.as<Type>() : Type();
 }
 
@@ -57,13 +57,13 @@ senf::ppi::connector::detail::TypedInputMixin<Self,PacketType>::read()
 // senf::ppi::connector::detail::TypedOutputMixin<Self,PacketType>
 
 template <class Self, class PacketType>
-prefix_ void senf::ppi::connector::detail::TypedOutputMixin<Self,PacketType>::operator()(Type p)
+prefix_ void senf::ppi::connector::detail::TypedOutputMixin<Self,PacketType>::operator()(Type const & p)
 {
     static_cast<Self*>(this)->OutputConnector::operator()(p);
 }
 
 template <class Self, class PacketType>
-prefix_ void senf::ppi::connector::detail::TypedOutputMixin<Self,PacketType>::write(Type p)
+prefix_ void senf::ppi::connector::detail::TypedOutputMixin<Self,PacketType>::write(Type const & p)
 {
     static_cast<Self*>(this)->OutputConnector::write(p);
 }
index ff44b48..bbe8eb5 100644 (file)
@@ -399,7 +399,7 @@ namespace connector {
         typedef Queue::size_type size_type; ///< Unsigned type for counting queue elements
 
 
-        Packet operator()();            ///< Get a packet
+        Packet const & operator()();    ///< Get a packet
                                         /**< This member is the primary method to access received
                                              data. On passive connectors, this operator will just
                                              dequeue a packet from the packet queue. If the
@@ -408,14 +408,10 @@ namespace connector {
                                              request cannot be fulfilled an in-valid Packet is
                                              returned. */
 
-        Packet read();                  ///< Alias for operator()()
+        Packet const & read();          ///< Alias for operator()()
 
         OutputConnector & peer() const;
 
-        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
-
         size_type queueSize() const;    ///< Return number of elements in the queue
         bool empty() const;             ///< Return queueSize() == 0
 
@@ -434,6 +430,8 @@ namespace connector {
 
         OutputConnector * peer_;
         Queue queue_;
+        Packet const * fastPacket_;
+        Packet slowPacket_;
 
         friend class OutputConnector;
     };
index b8d1597..82873b1 100644 (file)
@@ -56,8 +56,8 @@ namespace detail {
     public:
         typedef PacketType Type;
 
-        void operator()(Type p);
-        void write(Type p);
+        void operator()(Type const & p);
+        void write(Type const & p);
     };
 
 }}}}
index 1e82306..eae2acd 100644 (file)
@@ -142,7 +142,6 @@ SENF_AUTO_UNIT_TEST(inputConnector)
 
     BOOST_CHECK_EQUAL ( & target.input.peer(), & source.output );
 
-    BOOST_CHECK( target.input.begin() == target.input.end() );
     BOOST_CHECK_EQUAL( target.input.queueSize(), 0u );
     BOOST_CHECK( target.input.empty() );
 }
index 8bbc23d..4a79660 100644 (file)
@@ -45,7 +45,7 @@ prefix_ senf::ppi::module::ThrottleBarrier::ThrottleBarrier()
 
 prefix_ void senf::ppi::module::ThrottleBarrier::request()
 {
-    Packet p (input());
+    Packet const & p (input());
     if (output)
         output(p);
 }
index 025bb6b..7242786 100644 (file)
@@ -80,6 +80,8 @@ def setup(env):
     env['BUILDERS']['RealBoostUnitTest'] = env['BUILDERS']['BoostUnitTest']
     env['BUILDERS']['BoostUnitTest'] = AutoObjectBoostUnitTest
     env['_UNIT_TEST_LIST'] = []
+    env.Append(EXTRA_LIBS = [ '$BOOSTREGEXLIB', '$BOOSTSIGNALSLIB',
+                       '$BOOSTFSLIB', '$BOOSTSYSTEMLIB' ])
 
 # This needs to be called after all build targets have been set
 # up. This is important since the list of object targets needs to be