PPI: Implement Connector and Event un-registration
g0dil [Tue, 27 Oct 2009 10:51:49 +0000 (10:51 +0000)]
git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1510 270642c3-0616-0410-b53a-bc976706d245

19 files changed:
senf/PPI/AnnotationRouter.ct
senf/PPI/Connectors.cc
senf/PPI/Connectors.cci
senf/PPI/Connectors.cti
senf/PPI/Connectors.hh
senf/PPI/EventManager.cc
senf/PPI/EventManager.hh
senf/PPI/Events.cc
senf/PPI/Events.cci
senf/PPI/Events.hh
senf/PPI/Module.cci
senf/PPI/Module.hh
senf/PPI/Route.cci
senf/PPI/Route.cti
senf/PPI/Route.hh
senf/PPI/Route.ih
senf/PPI/detail/EventBinding.cc
senf/PPI/detail/EventBinding.cci
senf/PPI/detail/EventBinding.hh

index 29a9cab..0e1bbef 100644 (file)
@@ -26,6 +26,7 @@
 //#include "AnnotationRouter.ih"
 
 // Custom includes
+#include "Connectors.hh"
 
 #define prefix_
 ///////////////////////////////ct.p////////////////////////////////////////
index debe7ec..065d36f 100644 (file)
@@ -268,6 +268,13 @@ prefix_ void senf::ppi::connector::ActiveConnector::registerRoute(ForwardingRout
     notifyRoutes_.push_back(&route);
 }
 
+prefix_ void senf::ppi::connector::ActiveConnector::unregisterRoute(ForwardingRoute & route)
+{
+    NotifyRoutes::iterator i (std::find(notifyRoutes_.begin(), notifyRoutes_.end(), &route));
+    if (i != notifyRoutes_.end())
+        notifyRoutes_.erase(i);
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // senf::ppi::connector::InputConnector
 
index 2abd3b1..3f9ceee 100644 (file)
@@ -26,6 +26,7 @@
 // Custom includes
 #include <senf/Utils/TypeInfo.hh>
 #include <senf/Utils/senfassert.hh>
+#include "Module.hh"
 
 #define prefix_ inline
 ///////////////////////////////cci.p///////////////////////////////////////
@@ -84,6 +85,12 @@ prefix_ bool senf::ppi::connector::Connector::connected()
     return peer_;
 }
 
+prefix_ void senf::ppi::connector::Connector::unregisterConnector()
+{
+    if (module_)
+        module_->unregisterConnector(*this);
+}
+
 ////////////////////////////////////////
 // private members
 
@@ -141,6 +148,13 @@ prefix_ void senf::ppi::connector::PassiveConnector::registerRoute(ForwardingRou
     routes_.push_back(&route);
 }
 
+prefix_ void senf::ppi::connector::PassiveConnector::unregisterRoute(ForwardingRoute & route)
+{
+    Routes::iterator i (std::find(routes_.begin(), routes_.end(), &route));
+    if (i != routes_.end())
+        routes_.erase(i);
+}
+
 // public members 
 
 prefix_ bool senf::ppi::connector::PassiveConnector::nativeThrottled()
index b8f5bf3..598e7f1 100644 (file)
@@ -66,6 +66,12 @@ prefix_ void senf::ppi::connector::detail::TypedOutputMixin<Self,PacketType>::wr
 ///////////////////////////////////////////////////////////////////////////
 // senf::ppi::connector::PassiveConnector
 
+prefix_ senf::ppi::connector::PassiveConnector::~PassiveConnector()
+{
+    // Must be here and NOT in base so it is called before destructing the routes_ member
+    unregisterConnector();
+}
+
 template <class Handler>
 prefix_ void senf::ppi::connector::PassiveConnector::onRequest(Handler handler)
 {
@@ -75,6 +81,12 @@ prefix_ void senf::ppi::connector::PassiveConnector::onRequest(Handler handler)
 ///////////////////////////////////////////////////////////////////////////
 // senf::ppi::connector::ActiveConnector
 
+prefix_ senf::ppi::connector::ActiveConnector::~ActiveConnector()
+{
+    // Must be here and NOT in base so it is called before destructing the routes_ member
+    unregisterConnector();
+}
+
 template <class Handler>
 prefix_ void senf::ppi::connector::ActiveConnector::onThrottle(Handler handler)
 {
index c0b0b49..0dfe9cf 100644 (file)
@@ -184,6 +184,8 @@ namespace connector {
 
         void trace(Packet const & p, char const * label);
         void throttleTrace(char const * label, char const * type);
+
+        void unregisterConnector();
         
     private:
         virtual std::type_info const & packetTypeID();
@@ -220,6 +222,8 @@ namespace connector {
         : public virtual Connector
     {
     public:
+        ~PassiveConnector();
+
         template <class Handler>
         void onRequest(Handler handler);///< Register I/O event handler
                                         /**< The registered handler will be called, whenever packets
@@ -263,6 +267,7 @@ namespace connector {
 
         // called by ForwardingRoute to register a new route
         void registerRoute(ForwardingRoute & route);
+        void unregisterRoute(ForwardingRoute & route);
 
         typedef ppi::detail::Callback<>::type Callback;
         Callback callback_;
@@ -291,6 +296,8 @@ namespace connector {
     {
         typedef ppi::detail::Callback<>::type Callback;
     public:
+        ~ActiveConnector();
+
         template <class Handler>
         void onThrottle(Handler handler); ///< Register throttle notification handler
                                         /**< The handler register here will be called, whenever a
@@ -333,6 +340,7 @@ namespace connector {
 
         // called by ForwardingRoute to register a new route
         void registerRoute(ForwardingRoute & route);
+        void unregisterRoute(ForwardingRoute & route);
 
         Callback throttleCallback_;
         Callback unthrottleCallback_;
index be2dc76..0b6a482 100644 (file)
@@ -28,6 +28,7 @@
 
 // Custom includes
 #include <boost/lambda/lambda.hpp>
+#include <boost/lambda/bind.hpp>
 
 //#include "EventManager.mpp"
 #define prefix_
 prefix_ void senf::ppi::EventManager::destroyModule(module::Module & module)
 {
     using boost::lambda::_1;
+    namespace l = boost::lambda;
 
-    // boost::ptr_vector::erase(f,l) asserts !empty() .. why ??
-    if (!registrations_.empty())
-        registrations_.erase(
-            std::remove_if(registrations_.begin(), registrations_.end(),
-                           ((&_1) ->* & detail::EventBindingBase::module_) == & module),
-            registrations_.end());
+    registrations_.erase_if(l::bind(&detail::EventBindingBase::module_,_1) == &module);
+}
+
+prefix_ void senf::ppi::EventManager::destroyEvent(EventDescriptor & event)
+{
+    using boost::lambda::_1;
+    namespace l = boost::lambda;
+    
+    SENF_ASSERT(
+        std::find_if(registrations_.begin(), registrations_.end(),
+                     l::bind(&detail::EventBindingBase::descriptor_,_1) == &event) 
+        == registrations_.end());
 }
 
 ///////////////////////////////cc.e////////////////////////////////////////
index 0f5fd9c..16f671b 100644 (file)
@@ -87,6 +87,7 @@ namespace ppi {
                            Descriptor & descriptor);
 
         void destroyModule(module::Module & module);
+        void destroyEvent(EventDescriptor & event);
 
         typedef boost::ptr_vector<detail::EventBindingBase> EventRegistrations;
         EventRegistrations registrations_;
@@ -97,6 +98,7 @@ namespace ppi {
 
         friend class detail::EventBindingBase;
         friend class module::Module;
+        friend class EventDescriptor;
     };
 
 }}
index 7aa0298..f74a329 100644 (file)
@@ -28,6 +28,7 @@
 
 // Custom includes
 #include "Route.hh"
+#include "EventManager.hh"
 
 //#include "Events.mpp"
 #define prefix_
 ///////////////////////////////////////////////////////////////////////////
 // senf::ppi::EventDescriptor
 
+prefix_ senf::ppi::EventDescriptor::~EventDescriptor()
+{
+    if (binding_)
+        binding_->manager().destroyEvent(*this);
+}
+
 prefix_ void senf::ppi::EventDescriptor::notifyUnthrottle()
 {
     Routes::const_iterator i (routes_.begin());
index 8ba444a..3282ba5 100644 (file)
@@ -25,6 +25,7 @@
 
 // Custom includes
 #include <senf/Utils/senfassert.hh>
+#include <senf/PPI/detail/EventBinding.hh>
 
 #define prefix_ inline
 ///////////////////////////////cci.p///////////////////////////////////////
@@ -32,9 +33,6 @@
 ///////////////////////////////////////////////////////////////////////////
 // senf::ppi::EventDescriptor
 
-prefix_ senf::ppi::EventDescriptor::~EventDescriptor()
-{}
-
 prefix_ bool senf::ppi::EventDescriptor::enabled()
 {
     return enabled_;
@@ -61,6 +59,13 @@ prefix_ void senf::ppi::EventDescriptor::registerRoute(ForwardingRoute & route)
     routes_.push_back(&route);
 }
 
+prefix_ void senf::ppi::EventDescriptor::unregisterRoute(ForwardingRoute & route)
+{
+    Routes::iterator i (std::find(routes_.begin(), routes_.end(), &route));
+    if (i != routes_.end())
+        routes_.erase(i);
+}
+
 ///////////////////////////////cci.e///////////////////////////////////////
 #undef prefix_
 
index 8e922cd..1025db5 100644 (file)
@@ -36,6 +36,8 @@
 
 namespace senf {
 namespace ppi {
+
+    namespace detail { class EventBindingBase; }
     
     /** \defgroup event_group Events
 
@@ -85,6 +87,7 @@ namespace ppi {
         void notifyUnthrottle();
 
         void registerRoute(ForwardingRoute & route);
+        void unregisterRoute(ForwardingRoute & route);
 
         bool enabled_;
         bool throttled_;
@@ -92,7 +95,10 @@ namespace ppi {
         typedef std::vector<ForwardingRoute*> Routes;
         Routes routes_;
 
+        detail::EventBindingBase * binding_;
+
         friend class ForwardingRoute;
+        friend class detail::EventBindingBase;
     };
     
     /** \brief Internal: Callback forwarders
index 3f0817d..73865c2 100644 (file)
@@ -28,6 +28,9 @@
 #include "Connectors.hh"
 #include "EventManager.hh"
 #include "ModuleManager.hh"
+#include <boost/lambda/lambda.hpp>
+#include <boost/lambda/bind.hpp>
+#include <algorithm>
 
 #define prefix_ inline
 ///////////////////////////////cci.p///////////////////////////////////////
@@ -62,6 +65,21 @@ prefix_ void senf::ppi::module::Module::registerConnector(connector::Connector &
     }
 }
 
+prefix_ void senf::ppi::module::Module::unregisterConnector(connector::Connector & connector)
+{
+    ConnectorRegistry::iterator i (std::find(connectorRegistry_.begin(), connectorRegistry_.end(),
+                                             &connector));
+    if (i != connectorRegistry_.end())
+        connectorRegistry_.erase(i);
+
+    routes_.erase_if(boost::bind(&RouteBase::hasConnector, _1, boost::cref(connector)));
+}
+
+prefix_ void senf::ppi::module::Module::unregisterEvent(EventDescriptor & event)
+{
+    routes_.erase_if(boost::bind(&RouteBase::hasEvent, _1, boost::cref(event)));
+}
+
 prefix_ senf::ppi::RouteBase &
 senf::ppi::module::Module::addRoute(std::auto_ptr<RouteBase> route)
 {
@@ -74,6 +92,9 @@ senf::ppi::module::Module::addRoute(std::auto_ptr<RouteBase> route)
 
 prefix_ senf::ppi::module::Module::~Module()
 {
+    SENF_ASSERT(connectorRegistry_.empty());
+    SENF_ASSERT(routes_.empty());
+
     moduleManager().unregisterModule(*this);
 }
 
index e4f2599..73f5385 100644 (file)
@@ -40,6 +40,9 @@
 
 namespace senf {
 namespace ppi {
+
+    namespace detail { class EventBindingBase; }
+
 namespace module {
 
     /** \namespace senf::ppi::module
@@ -313,6 +316,9 @@ namespace module {
         ModuleManager & moduleManager() const;
         
         void registerConnector(connector::Connector & connector);
+        void unregisterConnector(connector::Connector & connector);
+        void unregisterEvent(EventDescriptor & event);
+
         RouteBase & addRoute(std::auto_ptr<RouteBase> route);
 
         typedef std::vector<connector::Connector *> ConnectorRegistry;
@@ -324,6 +330,8 @@ namespace module {
         template <class Source, class Target>
         friend class detail::RouteHelper;
         friend class senf::ppi::ModuleManager;
+        friend class connector::Connector;
+        friend class senf::ppi::detail::EventBindingBase;
     };
 
     /** \brief Define PPI Module
index 0a3117a..4c45f95 100644 (file)
 prefix_ senf::ppi::RouteBase::~RouteBase()
 {}
 
+prefix_ bool senf::ppi::RouteBase::hasConnector(connector::Connector const & conn)
+    const
+{
+    return v_hasConnector(conn);
+}
+
+prefix_ bool senf::ppi::RouteBase::hasEvent(EventDescriptor const & event)
+    const
+{
+    return v_hasEvent(event);
+}
+
 ////////////////////////////////////////
 // protected members
 
index c72ad31..d6ed64e 100644 (file)
@@ -52,6 +52,12 @@ prefix_ void senf::ppi::ForwardingRoute::registerRoute(T & ob)
 }
 
 template <class T>
+prefix_ void senf::ppi::ForwardingRoute::unregisterRoute(T & ob)
+{
+    ob.unregisterRoute(*this);
+}
+
+template <class T>
 prefix_ void senf::ppi::ForwardingRoute::notifyThrottle(T & ob)
 {
     ob.notifyThrottle();
@@ -89,6 +95,57 @@ BaseRouteImplementation(module::Module & module, Source & source, Target & targe
     : Base(module), source_(&source), target_(&target)
 {}
 
+////////////////////////////////////////
+// private members
+
+template <class Source, class Target, class Base>
+prefix_ bool senf::ppi::detail::BaseRouteImplementation<Source,Target,Base>::
+v_hasConnector(connector::Connector const & conn)
+    const
+{
+    return isSame(conn, source()) || isSame(conn, target());
+}
+
+template <class Source, class Target, class Base>
+prefix_ bool senf::ppi::detail::BaseRouteImplementation<Source,Target,Base>::
+v_hasEvent(EventDescriptor const & event)
+    const
+{
+    return isSame(event, source()) || isSame(event, target());
+}
+
+template <class Source, class Target, class Base>
+prefix_ bool senf::ppi::detail::BaseRouteImplementation<Source,Target,Base>::
+isSame(connector::Connector const & conn, connector::Connector const & other)
+    const
+{
+    return &conn == &other;
+}
+
+template <class Source, class Target, class Base>
+prefix_ bool senf::ppi::detail::BaseRouteImplementation<Source,Target,Base>::
+isSame(connector::Connector const & conn, EventDescriptor const & other)
+    const
+{
+    return false;
+}
+
+template <class Source, class Target, class Base>
+prefix_ bool senf::ppi::detail::BaseRouteImplementation<Source,Target,Base>::
+isSame(EventDescriptor const & event, connector::Connector const & other)
+    const
+{
+    return false;
+}
+
+template <class Source, class Target, class Base>
+prefix_ bool senf::ppi::detail::BaseRouteImplementation<Source,Target,Base>::
+isSame(EventDescriptor const & event, EventDescriptor const & other)
+    const
+{
+    return &event == &other;
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // senf::ppi::detail::ForwardingRouteImplementation<Source,Target>
 
@@ -105,6 +162,15 @@ ForwardingRouteImplementation(module::Module & module, Source & source, Target &
     registerRoute(target);
 }
 
+template <class Source, class Target>
+prefix_
+senf::ppi::detail::ForwardingRouteImplementation<Source,Target>::
+~ForwardingRouteImplementation()
+{
+    unregisterRoute(this->source());
+    unregisterRoute(this->target());
+}
+
 ////////////////////////////////////////
 // private members
 
index fb29305..7977031 100644 (file)
@@ -57,10 +57,18 @@ namespace ppi {
                                              class is internal and not documented. */
 #endif
 
+        bool hasConnector(connector::Connector const & conn) const;
+                                        ///< \c true, if route has connector \a conn
+        bool hasEvent(EventDescriptor const & event) const;
+                                        ///< \c true, if route has event \a event
+
     protected:
         RouteBase(module::Module & module);
 
     private:
+        virtual bool v_hasConnector(connector::Connector const & conn) const = 0;
+        virtual bool v_hasEvent(EventDescriptor const & event) const = 0;
+
         module::Module * module_;
     };
 
@@ -100,6 +108,7 @@ namespace ppi {
 
         // Called to register this route with the connectors forwarding information base
         template <class T> void registerRoute(T & ob);
+        template <class T> void unregisterRoute(T & ob);
 
         template <class T> void notifyThrottle(T & ob);
         template <class T> void notifyUnthrottle(T & ob);
index 31a4e5b..901cf92 100644 (file)
@@ -110,6 +110,14 @@ namespace detail {
         BaseRouteImplementation(module::Module & module, Source & source, Target & target);
 
     private:
+        bool v_hasConnector(connector::Connector const & conn) const;
+        bool v_hasEvent(EventDescriptor const & event) const;
+
+        bool isSame(connector::Connector const & conn, connector::Connector const & other) const;
+        bool isSame(connector::Connector const & conn, EventDescriptor const & other) const;
+        bool isSame(EventDescriptor const & event, connector::Connector const & other) const;
+        bool isSame(EventDescriptor const & event, EventDescriptor const & other) const;
+
         Source * source_;
         Target * target_;
     };
@@ -135,6 +143,7 @@ namespace detail {
         
     protected:
         ForwardingRouteImplementation(module::Module & module, Source & source, Target & target);
+        ~ForwardingRouteImplementation();
 
     private:
         // send a throttle/unthrottle notification  only if the second argument is a 'true' type
index 65aa700..e1d5a4f 100644 (file)
 
 // Custom includes
 #include <senf/PPI/EventManager.hh>
+#include <senf/PPI/Module.hh>
 
 //#include "EventBinding.mpp"
 #define prefix_
 ///////////////////////////////cc.p////////////////////////////////////////
 
+prefix_ senf::ppi::detail::EventBindingBase::~EventBindingBase()
+{
+    descriptor_->enabled(false);
+    module().unregisterEvent(*descriptor_);
+    descriptor_->binding_ = 0;
+}
+
 prefix_ void senf::ppi::detail::EventBindingBase::eventTime(ClockService::clock_type time)
 {
     // It's hard to make this inline because of a circular header dependency ...
index 032d4bd..6a4cffc 100644 (file)
 ///////////////////////////////////////////////////////////////////////////
 // senf::ppi::detail::EventBindingBase
 
-prefix_ senf::ppi::detail::EventBindingBase::~EventBindingBase()
-{
-    descriptor_->enabled(false);
-}
-
 prefix_ senf::ppi::EventManager & senf::ppi::detail::EventBindingBase::manager()
     const
 {
@@ -56,7 +51,9 @@ prefix_ senf::ppi::detail::EventBindingBase::EventBindingBase(EventManager & man
                                                               module::Module & module,
                                                               EventDescriptor & descriptor)
     : manager_(&manager), module_(&module), descriptor_(&descriptor)
-{}
+{
+    descriptor_->binding_ = this;
+}
 
 ///////////////////////////////cci.e///////////////////////////////////////
 #undef prefix_
index 97087c2..15a4318 100644 (file)
@@ -59,6 +59,7 @@ namespace detail {
         EventDescriptor * descriptor_;
 
         friend class senf::ppi::EventManager;
+        friend class senf::ppi::EventDescriptor;
     };
 
     /** \brief Internal: Callback forwarders