From 5b0be76430459e29c1e57d4c9f55be193ff8c05d Mon Sep 17 00:00:00 2001
From: ressac <paul.chavent@onera.fr>
Date: Sun, 21 Nov 2010 15:13:11 +0100
Subject: [PATCH] New service architecture.

Service now inherit of a base class ServiceInterface. The same thing apply for ServiceRequester.
---
 rtt/DataFlowInterface.hpp                  |   26 ++++-
 rtt/Service.cpp                            |   96 ++-----------
 rtt/Service.hpp                            |  139 ++++--------------
 rtt/ServiceInterface.cpp                   |  143 +++++++++++++++++++
 rtt/ServiceInterface.hpp                   |  210 ++++++++++++++++++++++++++++
 rtt/ServiceRequester.cpp                   |   44 +++----
 rtt/ServiceRequester.hpp                   |   68 +++------
 rtt/TaskContext.cpp                        |    6 +-
 rtt/TaskContext.hpp                        |   25 +++-
 rtt/marsh/MarshallingService.cpp           |   16 +-
 rtt/rtt-fwd.hpp                            |    1 +
 rtt/scripting/ScriptingService.cpp         |   20 ++--
 rtt/transports/corba/ServiceI.cpp          |    4 +-
 rtt/transports/corba/ServiceRequesterI.cpp |    8 +-
 rtt/transports/corba/TaskContextI.cpp      |    2 +-
 15 files changed, 511 insertions(+), 297 deletions(-)
 create mode 100644 rtt/ServiceInterface.cpp
 create mode 100644 rtt/ServiceInterface.hpp

diff --git a/rtt/DataFlowInterface.hpp b/rtt/DataFlowInterface.hpp
index 7f03728..018e693 100644
--- a/rtt/DataFlowInterface.hpp
+++ b/rtt/DataFlowInterface.hpp
@@ -175,6 +175,17 @@ namespace RTT
         base::PortInterface& addLocalPort(base::PortInterface& port);
 
         /**
+         * Name and add a Port to this task without registering a service for it.
+         * @see addLocalPort(base::PortInterface& port)
+         * @return \a port
+         */
+        base::PortInterface& addLocalPort(const std::string& name, base::PortInterface& port)
+        {
+            port.setName(name);
+            return addLocalPort(port);
+        }
+
+        /**
          * Add an Event triggering Port to this task without
          * registering a service for it.
          * When data arrives on this port your TaskContext will be woken up
@@ -190,6 +201,19 @@ namespace RTT
                 base::InputPortInterface::NewDataOnPortEvent::SlotFunction callback = base::InputPortInterface::NewDataOnPortEvent::SlotFunction() );
 
         /**
+         * Name and add an Event triggering Port to this task without
+         * registering a service for it.
+         * @see addLocalEventPort(base::InputPortInterface& port, base::InputPortInterface::NewDataOnPortEvent::SlotFunction callback = base::InputPortInterface::NewDataOnPortEvent::SlotFunction()) 
+         * @return \a port
+         */
+        base::InputPortInterface& addLocalEventPort(const std::string& name, base::InputPortInterface& port,
+                base::InputPortInterface::NewDataOnPortEvent::SlotFunction callback = base::InputPortInterface::NewDataOnPortEvent::SlotFunction() )
+        {
+            port.setName(name);
+            return addLocalEventPort(port, callback);
+        }
+
+        /**
          * Get a port of a specific type.
          */
         template< class Type>
@@ -225,7 +249,7 @@ namespace RTT
         /**
          * The parent Service. May be null in exceptional cases.
          */
-        Service* mservice;
+        ServiceInterface* mservice;
         /**
          * These handles contain the links from an event port's signal to
          * the TaskContext::dataOnPort method.
diff --git a/rtt/Service.cpp b/rtt/Service.cpp
index 0d8048a..597550d 100644
--- a/rtt/Service.cpp
+++ b/rtt/Service.cpp
@@ -49,15 +49,9 @@ namespace RTT {
     using namespace std;
     using namespace boost;
 
-    Service::shared_ptr Service::Create(const std::string& name, TaskContext* owner) {
-        return shared_ptr(new Service(name,owner));
-    }
-
-    Service::Service(const std::string& name, TaskContext* owner)
-    : mname(name), mowner(owner), parent()
+    Service::Service(const std::string& name, TaskContext* owner, shared_ptr parent)
+      : ServiceInterface(name, owner, parent)
     {
-        // Inform DataFlowInterface.
-        mservice = this;
     }
 
     Service::~Service()
@@ -65,51 +59,13 @@ namespace RTT {
         clear();
     }
 
-    vector<string> Service::getProviderNames() const {
-        return keys(services);
-    }
 
-    bool Service::addService( Service::shared_ptr obj ) {
-        if ( services.find( obj->getName() ) != services.end() ) {
-            log(Error) << "Could not add Service " << obj->getName() <<": name already in use." <<endlog();
-            return false;
-        }
-        // we only call shared_from_this() when someone has a shared ref to us.
-        // In practice, this means when we have an owner.
-        if ( obj->getParent() == 0 && mowner ) {
-            obj->setOwner( mowner );
-            obj->setParent( shared_from_this() );
-        }
-        services[obj->getName()] = obj;
-        return true;
-    }
-
-    void Service::removeService( string const& name) {
-        // carefully written to avoid destructor to call back on us when called from removeService.
-        if ( services.count(name) ) {
-            shared_ptr sp = services.find(name)->second;
-            services.erase(name);
-            sp.reset(); // this possibly deletes.
-        }
-    }
-
-    Service::shared_ptr Service::provides(const std::string& service_name) {
-        if (service_name == "this")
-            return shared_from_this();
-        shared_ptr sp = services[service_name];
-        if (sp)
-            return sp;
-        sp = boost::make_shared<Service>(service_name, mowner);
-        sp->setParent( shared_from_this() );
-        services[service_name] = sp;
-        return sp;
-    }
+    void Service::setOwner(TaskContext* new_owner) 
+    {
+        for( SimpleOperations::iterator it= simpleoperations.begin(); it != simpleoperations.end(); ++it)
+            it->second->setOwner( new_owner ? new_owner->engine() : 0);
 
-    Service::shared_ptr Service::getService(const std::string& service_name) {
-        Services::iterator it = services.find(service_name);
-        if (it != services.end() )
-            return it->second;
-        return shared_ptr();
+        ServiceInterface::setOwner(new_owner);
     }
 
     OperationInterfacePart* Service::getOperation( std::string name )
@@ -130,13 +86,7 @@ namespace RTT {
         return true;
     }
 
-    bool Service::hasService(const std::string& service_name) {
-        if (service_name == "this")
-            return true;
-        return services.find(service_name) != services.end();
-    }
-
-    bool Service::addLocalOperation( OperationBase& op )
+   bool Service::addLocalOperation( OperationBase& op )
     {
         Logger::In in("Service::addLocalOperation");
         if ( op.getName().empty() ) {
@@ -148,12 +98,13 @@ namespace RTT {
             this->removeOperation(op.getName());
         }
         simpleoperations[op.getName()] = &op;
-        if (mowner)
-            op.setOwner(mowner->engine());
+        if (getOwner())
+          op.setOwner(getOwner()->engine());
         return true;
     }
 
-    boost::shared_ptr<base::DisposableInterface> Service::getLocalOperation( std::string name ) {
+    boost::shared_ptr<base::DisposableInterface> Service::getLocalOperation( std::string name ) 
+    {
         if ( hasOperation(name) ) {
             return simpleoperations.find(name)->second->getImplementation();
         }
@@ -172,9 +123,7 @@ namespace RTT {
 
         OperationInterface::clear();
         ConfigurationInterface::clear();
-        while ( !services.empty() ) {
-        	this->removeService( services.begin()->first );
-        }
+        ServiceInterface::clear();
     }
 
     std::vector<std::string> Service::getOperationNames() const
@@ -201,24 +150,9 @@ namespace RTT {
         simpleoperations.erase( name );
         OperationInterface::remove(name);
     }
-    void Service::setOwner(TaskContext* new_owner) {
-        for( SimpleOperations::iterator it= simpleoperations.begin(); it != simpleoperations.end(); ++it)
-            it->second->setOwner( new_owner ? new_owner->engine() : 0);
-
-        this->mowner = new_owner;
-
-        for( Services::iterator it= services.begin(); it != services.end(); ++it) {
-            it->second->setOwner( new_owner );
-            if (new_owner)
-                it->second->setParent( shared_from_this() );
-        }
-    }
 
-    void Service::setParent( Service::shared_ptr p) {
-        parent = p;
-    }
-
-    internal::OperationCallerC Service::create(std::string name, ExecutionEngine* caller) {
+    internal::OperationCallerC Service::create(std::string name, ExecutionEngine* caller) 
+    {
         return internal::OperationCallerC( getPart(name), name, caller );
     }
 
diff --git a/rtt/Service.hpp b/rtt/Service.hpp
index 1a53e85..c2b9375 100644
--- a/rtt/Service.hpp
+++ b/rtt/Service.hpp
@@ -40,19 +40,20 @@
 #define ORO_SERVICE_PROVIDER_HPP
 
 #include "rtt-config.h"
-#include "OperationInterface.hpp"
-#include "DataFlowInterface.hpp"
+#include "rtt-fwd.hpp"
+
+#include "ServiceInterface.hpp"
+
+#include "Operation.hpp"
 #include "internal/OperationInterfacePartFused.hpp"
 #include "internal/LocalOperationCaller.hpp"
 #include "internal/OperationCallerC.hpp"
 #include "internal/UnMember.hpp"
 #include "internal/GetSignature.hpp"
-
-#include "ConfigurationInterface.hpp"
-#include "Operation.hpp"
 #ifdef ORO_REMOTING
 #include "internal/RemoteOperationCaller.hpp"
 #endif
+
 #include <boost/shared_ptr.hpp>
 #include <boost/static_assert.hpp>
 #include <boost/type_traits/function_traits.hpp>
@@ -70,24 +71,16 @@ namespace RTT
      * @ingroup Services
      */
     class RTT_API Service
-        : public OperationInterface,
-          public ConfigurationInterface,
-          public DataFlowInterface,
-          public boost::enable_shared_from_this<Service>
+      :   public ServiceInterface
     {
     public:
-        typedef OperationInterface Factory;
+
         typedef boost::shared_ptr<Service> shared_ptr;
-        typedef std::vector<std::string> ProviderNames;
 
-        /**
-         * Creates a Service with a name and an owner.  Each
-         * service must be owned by a TaskContext and the owner can be
-         * set afterwards with setOwner.
-         * @param name The name of this service.
-         * @param owner The TaskContext that will execute the operations of this service.
-         */
-        static Service::shared_ptr Create(const std::string& name, TaskContext* owner = 0);
+        static shared_ptr Create(const std::string& name, TaskContext* owner = 0, shared_ptr parent = shared_ptr()) 
+        {
+          return shared_ptr(new Service(name, owner, parent));
+        }
 
         /**
          * Creates a Service with a name and an owner.  Each
@@ -96,29 +89,19 @@ namespace RTT
          * @param name The name of this service.
          * @param owner The TaskContext that will execute the operations of this service.
          */
-        Service(const std::string& name, TaskContext* owner = 0);
-
-        virtual ~Service();
-
-        /**
-         * Returns the name of this service instance.
-         */
-        const std::string& getName() const { return mname; }
+        Service(const std::string& name, TaskContext* owner = 0, shared_ptr parent = shared_ptr());
 
-        /**
-         * Returns a descriptive text for this service.
-         */
-        const std::string& doc() const { return mdescription; }
+        virtual ~Service(void);
 
-        /**
-         * Sets the descriptive text for this service.
-         */
-        void doc(const std::string& description) { mdescription = description; }
+        shared_ptr provides(void) 
+        {
+          return boost::dynamic_pointer_cast<Service>(shared_from_this());
+        }
 
-        /**
-         * Changes the name of this service.
-         */
-        void setName(const std::string& name) { mname = name;}
+        shared_ptr provides(const std::string& service_name) 
+        { 
+          return boost::dynamic_pointer_cast<Service>(addService(service_name));
+        }
 
         /**
          * Sets the owning TaskContext that will execute the
@@ -127,69 +110,6 @@ namespace RTT
         void setOwner(TaskContext* new_owner);
 
         /**
-         * Sets the parent service in case this service is
-         * a sub-service.
-         */
-        void setParent(shared_ptr new_parent);
-
-        /**
-         * The parent is the direct parent of this service.
-         */
-        shared_ptr getParent() const { return parent; }
-
-        /**
-         * Return a standard container which contains all the sub-service names
-         * of this Service
-         */
-        virtual ProviderNames getProviderNames() const;
-
-        /**
-         * The owner is the top-level TaskContext owning this service
-         * (indirectly).
-         */
-        TaskContext* getOwner() const { return mowner; }
-
-        /**
-         * Add a new Service to this TaskContext.
-         *
-         * @param obj This object becomes owned by this TaskContext.
-         *
-         * @return true if it could be added, false if such
-         * service already exists.
-         */
-        virtual bool addService( shared_ptr obj );
-
-        /**
-         * Remove a previously added sub-service.
-         * @param the name of the service to remove.
-         */
-        virtual void removeService( std::string const& service_name );
-
-        /**
-         * Returns this Service.
-         * @return a shared pointer from this.
-         */
-        Service::shared_ptr provides() { return shared_from_this(); }
-
-        /**
-         * Returns a sub-Service which resorts under
-         * this Service.
-         * @param service_name The name of the sub-service.
-         */
-        Service::shared_ptr provides(const std::string& service_name);
-        /**
-         * Returns a shared pointer to strictly a sub-service.
-         * This method will not return the this pointer when
-         * service_name equals "this".
-         */
-        shared_ptr getService(const std::string& service_name);
-
-        /**
-         * Check if this service has the sub-service \a service_name.
-         */
-        bool hasService(const std::string& service_name);
-
-        /**
          * Clear all added operations from the repository, saving memory space.
          */
         void clear();
@@ -388,21 +308,22 @@ namespace RTT
          * Reset the implementation of a operation.
          */
         bool resetOperation(std::string name, base::OperationBase* impl);
+
     protected:
-        typedef std::map< std::string, shared_ptr > Services;
-        /// the services we implement.
-        Services services;
 
         bool testOperation(base::OperationBase& op);
+
         typedef std::map<std::string,base::OperationBase* > SimpleOperations;
+
         typedef std::vector<base::OperationBase*> OperationList;
+
         SimpleOperations simpleoperations;
+
         OperationList ownedoperations;
-        std::string mname;
-        std::string mdescription;
-        TaskContext* mowner;
-        shared_ptr parent;
     };
+
+
+
 }
 
 
diff --git a/rtt/ServiceInterface.cpp b/rtt/ServiceInterface.cpp
new file mode 100644
index 0000000..57b45b5
--- /dev/null
+++ b/rtt/ServiceInterface.cpp
@@ -0,0 +1,143 @@
+/***************************************************************************
+  tag: The SourceWorks  Tue Sep 7 00:55:18 CEST 2010  ServiceInterface.cpp
+
+                        ServiceInterface.cpp -  description
+                           -------------------
+    begin                : Tue September 07 2010
+    copyright            : (C) 2010 The SourceWorks
+    email                : peter@thesourceworks.com
+
+ ***************************************************************************
+ *   This library is free software; you can redistribute it and/or         *
+ *   modify it under the terms of the GNU General Public                   *
+ *   License as published by the Free Software Foundation;                 *
+ *   version 2 of the License.                                             *
+ *                                                                         *
+ *   As a special exception, you may use this file as part of a free       *
+ *   software library without restriction.  Specifically, if other files   *
+ *   instantiate templates or use macros or inline functions from this     *
+ *   file, or you compile this file and link it with other files to        *
+ *   produce an executable, this file does not by itself cause the         *
+ *   resulting executable to be covered by the GNU General Public          *
+ *   License.  This exception does not however invalidate any other        *
+ *   reasons why the executable file might be covered by the GNU General   *
+ *   Public License.                                                       *
+ *                                                                         *
+ *   This library is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
+ *   Lesser General Public License for more details.                       *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public             *
+ *   License along with this library; if not, write to the Free Software   *
+ *   Foundation, Inc., 59 Temple Place,                                    *
+ *   Suite 330, Boston, MA  02111-1307  USA                                *
+ *                                                                         *
+ ***************************************************************************/
+
+
+#include "ServiceInterface.hpp"
+#include "TaskContext.hpp"
+#include <algorithm>
+#include "internal/mystd.hpp"
+#include <boost/lambda/lambda.hpp>
+#include <boost/lambda/construct.hpp>
+#include <algorithm>
+
+namespace RTT {
+    using namespace detail;
+    using namespace std;
+    using namespace boost;
+
+    ServiceInterface::ServiceInterface(const std::string& name, TaskContext* owner, shared_ptr parent) : 
+      m_name(name), 
+      m_owner(owner), 
+      m_parent(parent)
+    {
+        // Inform DataFlowInterface.
+        mservice = this;
+    }
+
+    void ServiceInterface::setOwner(TaskContext* new_owner) 
+    {
+        this->m_owner = new_owner;
+
+        for( SubServices::iterator it= m_sub_services.begin(); it != m_sub_services.end(); ++it) {
+            it->second->setOwner( new_owner );
+            if (new_owner)
+                it->second->setParent( shared_from_this() );
+        }
+    }
+
+    std::vector<std::string> ServiceInterface::getServicesNames() const 
+    {
+        return keys(m_sub_services);
+    }
+
+    bool ServiceInterface::hasService(const std::string& service_name) 
+    {
+        if (service_name == "this")
+            return true;
+        SubServices::iterator it = m_sub_services.find(service_name);
+        if (it != m_sub_services.end() )
+            return true;
+        return false;
+    }
+
+    ServiceInterface::shared_ptr ServiceInterface::getService(const std::string& service_name) 
+    {
+        if (service_name == "this")
+            return shared_from_this();
+        SubServices::iterator it = m_sub_services.find(service_name);
+        if (it != m_sub_services.end() )
+            return it->second;
+        return shared_ptr();
+    }
+
+    ServiceInterface::shared_ptr ServiceInterface::addService(const std::string& service_name) 
+    {
+        if (service_name == "this")
+            return shared_from_this();
+        SubServices::iterator it = m_sub_services.find(service_name);
+        if (it != m_sub_services.end() )
+            return it->second;
+        m_sub_services[service_name] = Create(service_name);
+        return m_sub_services[service_name];
+    }
+
+    void ServiceInterface::removeService(const std::string& service_name) 
+    {
+        // carefully written to avoid destructor to call back on us when called from removeServiceInterface.
+        SubServices::iterator it = m_sub_services.find(service_name);
+        if (it != m_sub_services.end() ) {
+            shared_ptr sp = it->second;
+            m_sub_services.erase(it);
+            sp.reset(); // this possibly deletes.
+        }
+    }
+
+    bool ServiceInterface::addService( ServiceInterface::shared_ptr obj ) 
+    {
+        SubServices::iterator it = m_sub_services.find(obj->getName());
+        if (it != m_sub_services.end() ) {
+            log(Error) << "Could not add ServiceInterface " << obj->getName() <<": name already in use." <<endlog();
+            return false;
+        }
+        // we only call shared_from_this() when someone has a shared ref to us.
+        // In practice, this means when we have an owner.
+        if ((obj->getParent() == 0) && m_owner ) {
+            obj->setOwner( m_owner );
+            obj->setParent( shared_from_this() );
+        }
+        m_sub_services[obj->getName()] = obj;
+        return true;
+    }
+
+    void ServiceInterface::clear(void)
+    {
+      while ( !m_sub_services.empty() ) {
+        this->removeService( m_sub_services.begin()->first );
+      }
+    }
+
+}
diff --git a/rtt/ServiceInterface.hpp b/rtt/ServiceInterface.hpp
new file mode 100644
index 0000000..6f40231
--- /dev/null
+++ b/rtt/ServiceInterface.hpp
@@ -0,0 +1,210 @@
+/***************************************************************************
+  tag: The SourceWorks  Tue Sep 7 00:55:18 CEST 2010  ServiceInterface.hpp
+
+                        ServiceInterface.hpp -  description
+                           -------------------
+    begin                : Tue September 07 2010
+    copyright            : (C) 2010 The SourceWorks
+    email                : peter@thesourceworks.com
+
+ ***************************************************************************
+ *   This library is free software; you can redistribute it and/or         *
+ *   modify it under the terms of the GNU General Public                   *
+ *   License as published by the Free Software Foundation;                 *
+ *   version 2 of the License.                                             *
+ *                                                                         *
+ *   As a special exception, you may use this file as part of a free       *
+ *   software library without restriction.  Specifically, if other files   *
+ *   instantiate templates or use macros or inline functions from this     *
+ *   file, or you compile this file and link it with other files to        *
+ *   produce an executable, this file does not by itself cause the         *
+ *   resulting executable to be covered by the GNU General Public          *
+ *   License.  This exception does not however invalidate any other        *
+ *   reasons why the executable file might be covered by the GNU General   *
+ *   Public License.                                                       *
+ *                                                                         *
+ *   This library is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
+ *   Lesser General Public License for more details.                       *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public             *
+ *   License along with this library; if not, write to the Free Software   *
+ *   Foundation, Inc., 59 Temple Place,                                    *
+ *   Suite 330, Boston, MA  02111-1307  USA                                *
+ *                                                                         *
+ ***************************************************************************/
+
+
+#ifndef ORO_SERVICE_INTERFACE_HPP
+#define ORO_SERVICE_INTERFACE_HPP
+
+#include "rtt-config.h"
+
+#include "OperationInterface.hpp"
+#include "DataFlowInterface.hpp"
+#include "ConfigurationInterface.hpp"
+
+#include <boost/shared_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+
+#include <vector>
+#include <map>
+
+namespace RTT
+{
+    /**
+     * This class allows storage and retrieval of operations,
+     * attributes and properties provided by a component.
+     *
+     * Services can be nested in sub-services, although this is rare.
+     *
+     * @ingroup Services
+     */
+    class RTT_API ServiceInterface
+        : public OperationInterface,
+          public ConfigurationInterface,
+          public DataFlowInterface,
+          public boost::enable_shared_from_this<ServiceInterface>
+    {
+    public:
+        
+        typedef boost::shared_ptr<ServiceInterface> shared_ptr;
+
+        /**
+         * Creates a Service with a name and an owner.  Each
+         * service must be owned by a TaskContext and the owner can be
+         * set afterwards with setOwner.
+         * @param name The name of this service.
+         * @param owner The TaskContext that will execute the operations of this service.
+         */
+        static shared_ptr Create(const std::string& name, TaskContext* owner = 0, shared_ptr parent = shared_ptr())
+        {
+          return shared_ptr(new ServiceInterface(name, owner, parent));
+        }
+
+        /**
+         * Creates a Service with a name and an owner.  Each
+         * service must be owned by a TaskContext and the owner can be
+         * set afterwards with setOwner.
+         * @param name The name of this service.
+         * @param owner The TaskContext that will execute the operations of this service.
+         */
+        ServiceInterface(const std::string& name, TaskContext* owner = 0, shared_ptr parent = shared_ptr());
+
+        virtual ~ServiceInterface(void) {}
+
+        /**
+         * Returns the name of this service instance.
+         */
+        const std::string& getName() const { return m_name; }
+
+        /**
+         * Changes the name of this service.
+         */
+        void setName(const std::string& new_name) { m_name = new_name;}
+
+        /**
+         * Returns a descriptive text for this service.
+         */
+        const std::string& doc() const { return m_description; }
+
+        /**
+         * Sets the descriptive text for this service.
+         */
+        void doc(const std::string& new_description) { m_description = new_description; }
+
+        /**
+         * The owner is the top-level TaskContext owning this service
+         * (indirectly).
+         */
+        TaskContext* getOwner() const { return m_owner; }
+
+        /**
+         * Sets the owning TaskContext that will execute the
+         * operations in this service.
+         */
+        void setOwner(TaskContext* new_owner);
+
+        /**
+         * The parent is the direct parent of this service.
+         */
+        shared_ptr getParent() const { return m_parent; }
+
+        /**
+         * Sets the parent service in case this service is
+         * a sub-service.
+         */
+        void setParent(shared_ptr new_parent) { m_parent = new_parent; }
+
+
+        /**
+         * Return a standard container which contains all the sub-service names
+         * of this Service
+         */
+        std::vector<std::string> getServicesNames() const;
+
+        /**
+         * Check if this service has the sub-service \a service_name.
+         * This method will return the this pointer when
+         * service_name equals "this".
+         */
+        bool hasService(const std::string& service_name);
+
+        /**
+         * Returns a shared pointer to a sub-service or
+         * null if the service doesn't exist.
+         * This method will return the this pointer when
+         * service_name equals "this".
+         */
+        shared_ptr getService(const std::string& service_name);
+
+        /**
+         * Returns a shared pointer to a sub-service.
+         * This method will return the this pointer when
+         * service_name equals "this".
+         */
+        shared_ptr addService(const std::string& service_name);
+
+        /**
+         * Remove a previously added sub-service.
+         * @param the name of the service to remove.
+         */
+        void removeService(const std::string& service_name );
+
+       /**
+         * Add a new Service to this TaskContext.
+         *
+         * @param obj This object becomes owned by this TaskContext.
+         *
+         * @return true if it could be added, false if such
+         * service already exists.
+         */
+        bool addService( shared_ptr obj );
+
+        /**
+         * Remove all sub-service.
+         */
+        void clear(void);
+
+
+    private:
+
+        std::string m_description;
+
+        std::string m_name;
+
+        TaskContext* m_owner;
+
+        shared_ptr m_parent;
+ 
+        // the services we implement.
+        typedef std::map< std::string, shared_ptr > SubServices;
+
+        SubServices m_sub_services;
+
+     };
+}
+
+
+#endif
diff --git a/rtt/ServiceRequester.cpp b/rtt/ServiceRequester.cpp
index 4e8bdf2..a82d053 100644
--- a/rtt/ServiceRequester.cpp
+++ b/rtt/ServiceRequester.cpp
@@ -37,7 +37,6 @@
 
 
 #include "ServiceRequester.hpp"
-#include "Service.hpp"
 #include "internal/mystd.hpp"
 #include "Logger.hpp"
 #include "TaskContext.hpp"
@@ -51,12 +50,8 @@ namespace RTT
     using namespace detail;
     using namespace std;
 
-    ServiceRequester::ServiceRequester(const std::string& name, TaskContext* tc) :
-        mrname(name), mrowner(tc)
-    {
-    }
-
-    ServiceRequester::~ServiceRequester()
+    ServiceRequester::ServiceRequester(const std::string& name, TaskContext* owner, ServiceInterface::shared_ptr parent)
+      : ServiceInterface(name, owner, parent)
     {
     }
 
@@ -76,11 +71,6 @@ namespace RTT
         return keys(mmethods);
     }
 
-    std::vector<std::string> ServiceRequester::getRequesterNames() const
-    {
-        return keys(mrequests);
-    }
-
     OperationCallerBaseInvoker& ServiceRequester::getOperationCaller(const std::string& name)
     {
         return *mmethods.find(name)->second;
@@ -90,18 +80,18 @@ namespace RTT
         for (OperationCallers::iterator it = mmethods.begin(); it != mmethods.end(); ++it) {
             if ( !it->second->ready() ) {
                 if (sp->hasOperation( it->first )) {
-                    it->second->setImplementation( sp->getLocalOperation( it->first ), mrowner ? mrowner->engine() : 0 );
+                    it->second->setImplementation( sp->getLocalOperation( it->first ), getOwner() ? getOwner()->engine() : 0 );
                     if ( it->second->ready() ) {
-                        if (mrowner)
+                        if (getOwner())
                             log(Debug) << "Successfully set up OperationCaller " << it->first <<endlog();
                         else
                             log(Warning) << "OperationCaller "<< it->first << " has no caller set."<<endlog();
                     }
                 }
                 if (sp->hasMember( it->first )) {
-                    it->second->setImplementationPart( sp->getOperation( it->first ), mrowner ? mrowner->engine() : 0 );
+                    it->second->setImplementationPart( sp->getOperation( it->first ), getOwner() ? getOwner()->engine() : 0 );
                     if ( it->second->ready() ) {
-                        if (mrowner)
+                        if (getOwner())
                             log(Debug) << "Successfully set up OperationCaller " << it->first <<endlog();
                         else
                             log(Warning) << "OperationCaller "<< it->first << " has no caller set."<<endlog();
@@ -112,28 +102,30 @@ namespace RTT
         if (ready()) {
             if (!mprovider)
                 mprovider = sp;
-            log(Info) << "Found complete interface of requested service '" << mrname <<"'"<< endlog();
+            log(Info) << "Found complete interface of requested service '" << getName() <<"'"<< endlog();
             return true;
         }
 
         return false;
     }
 
-    void ServiceRequester::disconnect()
-    {
-        ExecutionEngine* ee(0);
-        for_each(mmethods.begin(), mmethods.end(),
-                 bind(&OperationCallerBaseInvoker::setImplementation, bind(&OperationCallers::value_type::second, _1), boost::shared_ptr<base::DisposableInterface>(), ee )
-                 );
-    }
-
     bool ServiceRequester::ready() const
     {
         for (OperationCallers::const_iterator it = mmethods.begin(); it != mmethods.end(); ++it)
             if ( !it->second->ready() ) {
-                log(Debug) << "ServiceRequeste: "<< it->first << " not set up." <<endlog();
+                log(Debug) << "ServiceRequester: "<< it->first << " not set up." <<endlog();
                 return false;
             }
         return true;
     }
+
+    void ServiceRequester::disconnect()
+    {
+        ExecutionEngine* ee(0);
+        for_each(mmethods.begin(), mmethods.end(),
+                 bind(&OperationCallerBaseInvoker::setImplementation, bind(&OperationCallers::value_type::second, _1), boost::shared_ptr<base::DisposableInterface>(), ee )
+                 );
+        mprovider = shared_ptr();
+    }
+
 }
diff --git a/rtt/ServiceRequester.hpp b/rtt/ServiceRequester.hpp
index ac8ea53..5ddc2a4 100644
--- a/rtt/ServiceRequester.hpp
+++ b/rtt/ServiceRequester.hpp
@@ -41,8 +41,10 @@
 
 #include "rtt-config.h"
 #include "rtt-fwd.hpp"
-#include "base/OperationCallerBaseInvoker.hpp"
+
 #include "Service.hpp"
+#include "ServiceInterface.hpp"
+#include "base/OperationCallerBaseInvoker.hpp"
 #include <map>
 #include <vector>
 #include <string>
@@ -61,56 +63,37 @@ namespace RTT
      * to it using addOperationCaller. @see RTT::Scripting for an example.
      */
     class RTT_API ServiceRequester
+        : public ServiceInterface
     {
     public:
-        typedef std::vector<std::string> RequesterNames;
-        typedef std::vector<std::string> OperationCallerNames;
-        ServiceRequester(const std::string& name, TaskContext* owner = 0);
-        virtual ~ServiceRequester();
 
-        const std::string& getRequestName() const { return mrname; }
+        typedef boost::shared_ptr<ServiceRequester> shared_ptr;
 
-        RequesterNames getRequesterNames() const;
+        static shared_ptr Create(const std::string& name, TaskContext* owner = 0, shared_ptr parent = shared_ptr()) 
+        {
+          return shared_ptr(new ServiceRequester(name, owner, parent));
+        }
 
-        /**
-         * The owner is the top-level TaskContext owning this service
-         * (indirectly).
-         */
-        TaskContext* getServiceOwner() const { return mrowner; }
+        ServiceRequester(const std::string& name, TaskContext* owner = 0, ServiceInterface::shared_ptr parent = shared_ptr());
 
-        /**
-         * Returns the service we're referencing.
-         * In case you used connectTo to more than one service,
-         * this returns the service which was used when connectTo
-         * first returned true.
-         */
-        Service::shared_ptr getReferencedService();
+        virtual ~ServiceRequester(void) {}
 
-        bool addOperationCaller( base::OperationCallerBaseInvoker& mbi);
+        shared_ptr requires(void) 
+        {
+          return boost::dynamic_pointer_cast<ServiceRequester>(shared_from_this());
+        }
 
-        OperationCallerNames getOperationCallerNames() const;
+        shared_ptr requires(const std::string& service_name) 
+        {
+          return boost::dynamic_pointer_cast<ServiceRequester>(addService(service_name));
+        }
 
-        base::OperationCallerBaseInvoker& getOperationCaller(const std::string& name);
 
-        ServiceRequester* requires() { return this; }
+        bool addOperationCaller( base::OperationCallerBaseInvoker& mbi);
 
-        ServiceRequester* requires(const std::string& service_name) {
-            ServiceRequester* sp = mrequests[service_name];
-            if (sp)
-                return sp;
-            sp = new ServiceRequester(service_name, mrowner);
-            mrequests[service_name] = sp;
-            return sp;
-        }
+        std::vector<std::string> getOperationCallerNames() const;
 
-        /**
-         * Query if this service requires certain sub-services.
-         * @param service_name
-         * @return
-         */
-        bool requiresService(const std::string& service_name) {
-            return mrequests.find(service_name) != mrequests.end();
-        }
+        base::OperationCallerBaseInvoker& getOperationCaller(const std::string& name);
 
         /**
          * Connects this service's methods to the operations provided by op.
@@ -137,17 +120,12 @@ namespace RTT
         void disconnect();
 
     protected:
-        typedef std::map< std::string, ServiceRequester* > Requests;
-        /// the services we implement.
-        Requests mrequests;
 
         /// Our methods
         typedef std::map<std::string, base::OperationCallerBaseInvoker*> OperationCallers;
         OperationCallers mmethods;
 
-        std::string mrname;
-        TaskContext* mrowner;
-        Service::shared_ptr mprovider;
+        ServiceInterface::shared_ptr mprovider;
     };
 }
 
diff --git a/rtt/TaskContext.cpp b/rtt/TaskContext.cpp
index 5d1b747..66b941b 100644
--- a/rtt/TaskContext.cpp
+++ b/rtt/TaskContext.cpp
@@ -131,7 +131,7 @@ namespace RTT
             // [Rule no 2: Don't call virtual functions in a constructor.]
             tcservice->clear();
 
-            delete tcrequests;
+            tcrequests->clear();
 
             // remove from all users.
             while( !musers.empty() ) {
@@ -183,8 +183,8 @@ namespace RTT
         const std::string& location = this->getName();
         Logger::In in( location.c_str()  );
 
-        vector<string> myreqs = this->requires()->getRequesterNames();
-        vector<string> peerreqs = peer->requires()->getRequesterNames();
+        vector<string> myreqs = this->requires()->getServicesNames();
+        vector<string> peerreqs = peer->requires()->getServicesNames();
 
         this->requires()->connectTo( peer->provides() );
         for (vector<string>::iterator it = myreqs.begin();
diff --git a/rtt/TaskContext.hpp b/rtt/TaskContext.hpp
index b1f53b2..6763ec7 100644
--- a/rtt/TaskContext.hpp
+++ b/rtt/TaskContext.hpp
@@ -265,27 +265,37 @@ namespace RTT
          * Returns this Service.
          * @return a shared pointer from this.
          */
-        Service::shared_ptr provides() { return tcservice; }
+        Service::shared_ptr provides() 
+        { 
+          return tcservice; 
+        }
 
         /**
          * Returns a sub-Service which resorts under
          * this Service.
          * @param service_name The name of the sub-service.
          */
-        Service::shared_ptr provides(const std::string& service_name) { return tcservice->provides(service_name); }
+        Service::shared_ptr provides(const std::string& service_name) 
+        { 
+          return tcservice->provides(service_name); 
+        }
 
         /**
          * Returns the object that manages which methods this Task
          * requires to be implemented by another task.
          */
-        ServiceRequester* requires() { return tcrequests; }
+        ServiceRequester* requires() 
+        { 
+          return tcrequests.get(); 
+        }
 
         /**
          * Returns the object that manages which methods this Task
          * requires to be implemented by another service.
          */
-        ServiceRequester* requires(const std::string& service_name) {
-            return tcrequests->requires(service_name);
+        ServiceRequester* requires(const std::string& service_name) 
+        {
+          return tcrequests->requires(service_name).get(); 
         }
 
         /**
@@ -646,8 +656,9 @@ namespace RTT
         typedef std::map<std::string, boost::shared_ptr<ServiceRequester> > LocalServices;
         LocalServices localservs;
 
-        Service::shared_ptr tcservice;
-        ServiceRequester*           tcrequests;
+        Service::shared_ptr          tcservice;  // m_service_providers
+        ServiceRequester::shared_ptr tcrequests; // m_service_requesters
+
         os::Mutex mportlock;
 
         // non copyable
diff --git a/rtt/marsh/MarshallingService.cpp b/rtt/marsh/MarshallingService.cpp
index 87d1435..155ac6f 100644
--- a/rtt/marsh/MarshallingService.cpp
+++ b/rtt/marsh/MarshallingService.cpp
@@ -90,44 +90,44 @@ namespace RTT {
     bool MarshallingService::loadProperties(const std::string& filename) const
     {
         PropertyLoader pl;
-        return pl.load( filename, mowner );
+        return pl.load( filename, getOwner() );
     }
 
     bool MarshallingService::storeProperties(const std::string& filename) const
     {
         PropertyLoader pl;
-        return pl.store( filename, mowner );
+        return pl.store( filename, getOwner() );
     }
 
     bool MarshallingService::readProperties(const std::string& filename) const
     {
         PropertyLoader pl;
-        return pl.configure( filename, mowner, true); // all
+        return pl.configure( filename, getOwner(), true); // all
     }
     bool MarshallingService::updateProperties(const std::string& filename) const
     {
         PropertyLoader pl;
-        return pl.configure( filename, mowner, false); // not all
+        return pl.configure( filename, getOwner(), false); // not all
     }
     bool MarshallingService::writeProperties(const std::string& filename) const
     {
         PropertyLoader pl;
-        return pl.save( filename, mowner, true);
+        return pl.save( filename, getOwner(), true);
     }
     bool MarshallingService::updateFile(const std::string& filename) const
     {
         PropertyLoader pl;
-        return pl.save( filename, mowner, false);
+        return pl.save( filename, getOwner(), false);
     }
 
     bool MarshallingService::readProperty(const std::string& name, const std::string& filename) {
         PropertyLoader p;
-        return p.configure(filename, mowner, name);
+        return p.configure(filename, getOwner(), name);
     }
 
     bool MarshallingService::writeProperty(const std::string& name, const std::string& filename) {
         PropertyLoader p;
-        return p.save(filename, mowner, name);
+        return p.save(filename, getOwner(), name);
     }
 
 
diff --git a/rtt/rtt-fwd.hpp b/rtt/rtt-fwd.hpp
index 3a44b81..94f4465 100644
--- a/rtt/rtt-fwd.hpp
+++ b/rtt/rtt-fwd.hpp
@@ -82,6 +82,7 @@ namespace RTT
     class DataFlowInterface;
     class OperationInterface;
     class OperationInterfacePart;
+    class ServiceInterface;
     class Service;
     class ServiceRequester;
     typedef boost::shared_ptr<Service> ServicePtr;
diff --git a/rtt/scripting/ScriptingService.cpp b/rtt/scripting/ScriptingService.cpp
index 93ec43c..7374de4 100644
--- a/rtt/scripting/ScriptingService.cpp
+++ b/rtt/scripting/ScriptingService.cpp
@@ -218,7 +218,7 @@ namespace RTT {
 
         // first load parent.
         states[sc->getName()] = sc;
-        mowner->engine()->runFunction( sc.get() );
+        getOwner()->engine()->runFunction( sc.get() );
 
         // then load children.
         for (it = sc->getChildren().begin(); it != sc->getChildren().end(); ++it)
@@ -285,7 +285,7 @@ namespace RTT {
 
         // lastly, unload the parent.
         states.erase(it);
-        mowner->engine()->removeFunction( sc.get() );
+        getOwner()->engine()->removeFunction( sc.get() );
     }
 
     bool ScriptingService::deleteStateMachine(const string& name)
@@ -350,7 +350,7 @@ namespace RTT {
        }
        programs[pi->getName()] = pi;
        pi->reset();
-       if ( mowner->engine()->runFunction( pi.get() ) == false) {
+       if ( getOwner()->engine()->runFunction( pi.get() ) == false) {
            programs.erase(pi->getName());
            log(Error) << "Could not load Program "<< pi->getName() << " in ExecutionEngine."<<endlog();
            return false;
@@ -364,7 +364,7 @@ namespace RTT {
 
        if ( it != programs.end() )
            {
-               mowner->engine()->removeFunction( it->second.get() );
+               getOwner()->engine()->removeFunction( it->second.get() );
                programs.erase( it );
                return true;
            }
@@ -493,7 +493,7 @@ namespace RTT {
 
     int ScriptingService::execute(const string& code ){
         if (sproc == 0)
-            sproc = new StatementProcessor(mowner);
+            sproc = new StatementProcessor(getOwner());
         return sproc->execute( code );
     }
 
@@ -522,7 +522,7 @@ namespace RTT {
       Functions ret;
       try {
           Logger::log() << Logger::Info << "Parsing file "<<filename << Logger::endl;
-          ret = p.parseFunction(code, mowner, filename);
+          ret = p.parseFunction(code, getOwner(), filename);
       }
       catch( const file_parse_exception& exc )
           {
@@ -542,7 +542,7 @@ namespace RTT {
               // Load all listed functions in the TaskContext's Processor:
               for( Parser::ParsedFunctions::iterator it = ret.begin(); it != ret.end(); ++it) {
                   Logger::log() << "Queueing Function "<< (*it)->getName() << Logger::endl;
-                  if ( mowner->engine()->runFunction( it->get() ) == false) {
+                  if ( getOwner()->engine()->runFunction( it->get() ) == false) {
                       Logger::log() << Logger::Error << "Could not run Function '"<< (*it)->getName() <<"' :" << Logger::nl;
                       Logger::log() << "Processor not accepting or function queue is full." << Logger::endl;
                   } else
@@ -580,7 +580,7 @@ namespace RTT {
         Logger::In in("ScriptingService");
         Parser parser;
         try {
-            parser.runScript(code, mowner, this, filename );
+            parser.runScript(code, getOwner(), this, filename );
         }
         catch( const file_parse_exception& exc )
             {
@@ -619,7 +619,7 @@ namespace RTT {
       } 
       try {
           Logger::log() << Logger::Info << "Parsing file "<<filename << Logger::endl;
-          pg_list = parser.parseProgram(code, mowner, filename );
+          pg_list = parser.parseProgram(code, getOwner(), filename );
       }
       catch( const file_parse_exception& exc )
           {
@@ -707,7 +707,7 @@ namespace RTT {
         }
         try {
             Logger::log() << Logger::Info << "Parsing file "<<filename << Logger::endl;
-            pg_list = parser.parseStateMachine( code, mowner, filename );
+            pg_list = parser.parseStateMachine( code, getOwner(), filename );
         }
         catch( const file_parse_exception& exc )
             {
diff --git a/rtt/transports/corba/ServiceI.cpp b/rtt/transports/corba/ServiceI.cpp
index 362e959..49ffe43 100644
--- a/rtt/transports/corba/ServiceI.cpp
+++ b/rtt/transports/corba/ServiceI.cpp
@@ -104,7 +104,7 @@ char * RTT_corba_CService_i::getServiceDescription (
 ::RTT::corba::CService::CProviderNames * RTT_corba_CService_i::getProviderNames (
     void)
 {
-    Service::ProviderNames names = mservice->getProviderNames();
+    std::vector<std::string> names = mservice->getServicesNames();
     ::RTT::corba::CService::CProviderNames_var result = new ::RTT::corba::CService::CProviderNames();
     result->length( names.size() );
     for (unsigned int i=0; i != names.size(); ++i )
@@ -116,7 +116,7 @@ char * RTT_corba_CService_i::getServiceDescription (
 ::RTT::corba::CService_ptr RTT_corba_CService_i::getService (
     const char * service_name)
 {
-    Service::shared_ptr provider = mservice->getService(service_name);
+    Service::shared_ptr provider = boost::dynamic_pointer_cast<Service>(mservice->getService(service_name));
     if ( !provider )
     	return RTT::corba::CService::_nil();
 
diff --git a/rtt/transports/corba/ServiceRequesterI.cpp b/rtt/transports/corba/ServiceRequesterI.cpp
index 35ef7d2..361e71b 100644
--- a/rtt/transports/corba/ServiceRequesterI.cpp
+++ b/rtt/transports/corba/ServiceRequesterI.cpp
@@ -85,13 +85,13 @@ RTT_corba_CServiceRequester_i::~RTT_corba_CServiceRequester_i (void)
 char * RTT_corba_CServiceRequester_i::getRequestName (
     void)
 {
-    return CORBA::string_dup( mservice->getRequestName().c_str() );
+    return CORBA::string_dup( mservice->getName().c_str() );
 }
 
 ::RTT::corba::CRequestNames * RTT_corba_CServiceRequester_i::getRequestNames (
     void)
 {
-    ServiceRequester::RequesterNames names = mservice->getRequesterNames();
+    std::vector<std::string> names = mservice->getServicesNames();
     ::RTT::corba::CRequestNames_var result = new ::RTT::corba::CRequestNames();
     result->length( names.size() );
     for (unsigned int i=0; i != names.size(); ++i )
@@ -103,7 +103,7 @@ char * RTT_corba_CServiceRequester_i::getRequestName (
 ::RTT::corba::COperationCallerNames * RTT_corba_CServiceRequester_i::getOperationCallerNames (
     void)
 {
-    ServiceRequester::OperationCallerNames names = mservice->getOperationCallerNames();
+    std::vector<std::string> names = mservice->getOperationCallerNames();
     ::RTT::corba::COperationCallerNames_var result = new ::RTT::corba::COperationCallerNames();
     result->length( names.size() );
     for (unsigned int i=0; i != names.size(); ++i )
@@ -121,7 +121,7 @@ char * RTT_corba_CServiceRequester_i::getRequestName (
 ::CORBA::Boolean RTT_corba_CServiceRequester_i::hasRequest (
     const char * name)
 {
-    return mservice->requiresService( name );
+    return mservice->hasService( name );
 }
 
 ::CORBA::Boolean RTT_corba_CServiceRequester_i::connectTo (
diff --git a/rtt/transports/corba/TaskContextI.cpp b/rtt/transports/corba/TaskContextI.cpp
index b9d832b..afbbfb6 100644
--- a/rtt/transports/corba/TaskContextI.cpp
+++ b/rtt/transports/corba/TaskContextI.cpp
@@ -221,7 +221,7 @@ char * RTT_corba_CTaskContext_i::getDescription (
 ::RTT::corba::CServiceRequester_ptr RTT_corba_CTaskContext_i::getRequester (
     const char * service_name)
 {
-    if ( mtask->requires()->requiresService(service_name) == false)
+    if ( mtask->requires()->hasService(service_name) == false)
         return CServiceRequester::_nil();
     // Creates service requester for "this"
     if ( CORBA::is_nil( mRequest ) ) {
-- 
1.7.0.4

