Orocos Real-Time Toolkit  2.5.0
Service.cpp
00001 /***************************************************************************
00002   tag: The SourceWorks  Tue Sep 7 00:55:18 CEST 2010  Service.cpp
00003 
00004                         Service.cpp -  description
00005                            -------------------
00006     begin                : Tue September 07 2010
00007     copyright            : (C) 2010 The SourceWorks
00008     email                : peter@thesourceworks.com
00009 
00010  ***************************************************************************
00011  *   This library is free software; you can redistribute it and/or         *
00012  *   modify it under the terms of the GNU General Public                   *
00013  *   License as published by the Free Software Foundation;                 *
00014  *   version 2 of the License.                                             *
00015  *                                                                         *
00016  *   As a special exception, you may use this file as part of a free       *
00017  *   software library without restriction.  Specifically, if other files   *
00018  *   instantiate templates or use macros or inline functions from this     *
00019  *   file, or you compile this file and link it with other files to        *
00020  *   produce an executable, this file does not by itself cause the         *
00021  *   resulting executable to be covered by the GNU General Public          *
00022  *   License.  This exception does not however invalidate any other        *
00023  *   reasons why the executable file might be covered by the GNU General   *
00024  *   Public License.                                                       *
00025  *                                                                         *
00026  *   This library is distributed in the hope that it will be useful,       *
00027  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00028  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00029  *   Lesser General Public License for more details.                       *
00030  *                                                                         *
00031  *   You should have received a copy of the GNU General Public             *
00032  *   License along with this library; if not, write to the Free Software   *
00033  *   Foundation, Inc., 59 Temple Place,                                    *
00034  *   Suite 330, Boston, MA  02111-1307  USA                                *
00035  *                                                                         *
00036  ***************************************************************************/
00037 
00038 
00039 #include "Service.hpp"
00040 #include "TaskContext.hpp"
00041 #include <algorithm>
00042 #include "internal/mystd.hpp"
00043 #include <boost/lambda/lambda.hpp>
00044 #include <boost/lambda/construct.hpp>
00045 #include <algorithm>
00046 
00047 namespace RTT {
00048     using namespace detail;
00049     using namespace std;
00050     using namespace boost;
00051 
00052     Service::shared_ptr Service::Create(const std::string& name, TaskContext* owner) {
00053         shared_ptr ret(new Service(name,owner));
00054         if (owner)
00055             owner->provides()->addService( ret );
00056         return ret;
00057     }
00058 
00059     Service::Service(const std::string& name, TaskContext* owner)
00060     : mname(name),
00061 #if BOOST_VERSION >= 104000
00062       mowner(owner),
00063 #else
00064       mowner(0),
00065 #endif
00066       parent()
00067     {
00068         // Inform DataFlowInterface.
00069         mservice = this;
00070     }
00071 
00072     Service::~Service()
00073     {
00074         clear();
00075     }
00076 
00077     vector<string> Service::getProviderNames() const {
00078         return keys(services);
00079     }
00080 
00081     bool Service::addService( Service::shared_ptr obj ) {
00082         if ( services.find( obj->getName() ) != services.end() ) {
00083             log(Error) << "Could not add Service " << obj->getName() <<": name already in use." <<endlog();
00084             return false;
00085         }
00086         // we only call shared_from_this() when someone has a shared ref to us.
00087         // In practice, this means when we have an owner.
00088         if ( obj->getParent() == 0 && mowner ) {
00089             obj->setOwner( mowner );
00090             obj->setParent( shared_from_this() );
00091         }
00092         services[obj->getName()] = obj;
00093         return true;
00094     }
00095 
00096     void Service::removeService( string const& name) {
00097         // carefully written to avoid destructor to call back on us when called from removeService.
00098         if ( services.count(name) ) {
00099             shared_ptr sp = services.find(name)->second;
00100             services.erase(name);
00101             sp.reset(); // this possibly deletes.
00102         }
00103     }
00104 
00105     Service::shared_ptr Service::provides() {
00106         try {
00107             return shared_from_this();
00108         } catch( boost::bad_weak_ptr& /*bw*/ ) {
00109             log(Error) <<"When using boost < 1.40.0 : You are not allowed to call provides() on a Service that does not yet belong to a TaskContext or another Service." << endlog();                                                                                                     log(Error) <<"Try to avoid using provides() in this case: omit it or use the service directly." <<endlog();
00110             log(Error) <<"OR: upgrade to boost 1.40.0, then this error will go away." <<endlog();
00111             throw std::runtime_error("Illegal use of provides()");
00112         }
00113     }
00114 
00115     Service::shared_ptr Service::provides(const std::string& service_name) {
00116         if (service_name == "this")
00117             return provides();
00118         shared_ptr sp = services[service_name];
00119         if (sp)
00120             return sp;
00121         sp = boost::make_shared<Service>(service_name, mowner);
00122         sp->setOwner( mowner );
00123         sp->setParent( shared_from_this() );
00124         services[service_name] = sp;
00125         return sp;
00126     }
00127 
00128     Service::shared_ptr Service::getService(const std::string& service_name) {
00129         Services::iterator it = services.find(service_name);
00130         if (it != services.end() )
00131             return it->second;
00132         return shared_ptr();
00133     }
00134 
00135     OperationInterfacePart* Service::getOperation( std::string name )
00136     {
00137         Logger::In in("Service::getOperation");
00138         if ( this->hasMember(name ) ) {
00139             return this->getPart(name);
00140         }
00141         log(Warning) << "No such operation in service '"<< getName() <<"': "<< name <<endlog();
00142         return 0;
00143     }
00144 
00145     bool Service::resetOperation(std::string name, base::OperationBase* impl)
00146     {
00147         if (!hasOperation(name))
00148             return false;
00149         simpleoperations[name] = impl;
00150         return true;
00151     }
00152 
00153     bool Service::setOperationThread(std::string const& name, ExecutionThread et)
00154     {
00155         if ( !hasOperation(name) )
00156             return false;
00157         DisposableInterface::shared_ptr di = getOperation(name)->getLocalOperation();
00158         OperationCallerInterface::shared_ptr oci = dynamic_pointer_cast<OperationCallerInterface>(di);
00159         if (oci) {
00160             return oci->setThread( et, getOwner() ? getOwner()->engine() : 0 );
00161         }
00162         return false;
00163     }
00164 
00165     bool Service::hasService(const std::string& service_name) {
00166         if (service_name == "this")
00167             return true;
00168         return services.find(service_name) != services.end();
00169     }
00170 
00171     bool Service::addLocalOperation( OperationBase& op )
00172     {
00173         Logger::In in("Service::addLocalOperation");
00174         if ( op.getName().empty() ) {
00175             log(Error) << "Failed to add Operation: '"<< op.getName() <<"' has no name." <<endlog();
00176             return false;
00177         }
00178         // don't check ready() since the op may not have an owner yet:
00179         if ( !op.getImplementation() ) {
00180             log(Error) << "Failed to add Operation: '"<< op.getName() <<"' is not ready: not bound to a function." <<endlog();
00181             return false;
00182         }
00183         if ( simpleoperations.count( op.getName() ) ) {
00184             log(Warning) << "While adding Operation: '"<< op.getName() <<"': replacing previously added operation." <<endlog();
00185             this->removeOperation(op.getName());
00186         }
00187         simpleoperations[op.getName()] = &op;
00188         // finally set the (new) owner:
00189         if (mowner)
00190             op.setOwner(mowner->engine());
00191         return true;
00192     }
00193 
00194     boost::shared_ptr<base::DisposableInterface> Service::getLocalOperation( std::string name ) {
00195         if ( hasOperation(name) ) {
00196             return simpleoperations.find(name)->second->getImplementation();
00197         }
00198         return boost::shared_ptr<base::DisposableInterface>();
00199     }
00200 
00201     void Service::clear()
00202     {
00203         while ( !simpleoperations.empty() )
00204         {
00205             simpleoperations.erase(simpleoperations.begin() );
00206         }
00207 
00208         for_each(ownedoperations.begin(),ownedoperations.end(), lambda::delete_ptr() );
00209         ownedoperations.clear();
00210 
00211         OperationInterface::clear();
00212         ConfigurationInterface::clear();
00213         while ( !services.empty() ) {
00214             this->removeService( services.begin()->first );
00215         }
00216     }
00217 
00218     std::vector<std::string> Service::getOperationNames() const
00219     {
00220         return keys(simpleoperations);
00221         //return getNames();
00222     }
00223 
00224     bool Service::hasOperation(const std::string& name) const
00225     {
00226         return simpleoperations.count(name) == 1;
00227         //return hasMember(name);
00228     }
00229 
00230     void Service::removeOperation(const std::string& name)
00231     {
00232         if (!hasOperation(name))
00233             return;
00234         OperationList::iterator it = find(ownedoperations.begin(), ownedoperations.end(), simpleoperations.find(name)->second );
00235         if (it != ownedoperations.end()) {
00236             delete *it;
00237             ownedoperations.erase(it);
00238         }
00239         simpleoperations.erase( name );
00240         OperationInterface::remove(name);
00241     }
00242     void Service::setOwner(TaskContext* new_owner) {
00243         for( SimpleOperations::iterator it= simpleoperations.begin(); it != simpleoperations.end(); ++it)
00244             it->second->setOwner( new_owner ? new_owner->engine() : 0);
00245 
00246         this->mowner = new_owner;
00247 
00248         for( Services::iterator it= services.begin(); it != services.end(); ++it) {
00249             it->second->setOwner( new_owner );
00250             if (new_owner)
00251                 it->second->setParent( shared_from_this() );
00252         }
00253     }
00254 
00255     void Service::setParent( Service::shared_ptr p) {
00256         parent = p;
00257     }
00258 
00259     internal::OperationCallerC Service::create(std::string name, ExecutionEngine* caller) {
00260         return internal::OperationCallerC( getPart(name), name, caller );
00261     }
00262 
00263 }