Orocos Real-Time Toolkit  2.6.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     ExecutionEngine* Service::getOwnerExecutionEngine() const {
00082         if(this->getOwner())
00083             return this->getOwner()->engine();
00084           return NULL;
00085     }
00086 
00087     bool Service::addService( Service::shared_ptr obj ) {
00088         if ( services.find( obj->getName() ) != services.end() ) {
00089             log(Error) << "Could not add Service " << obj->getName() <<": name already in use." <<endlog();
00090             return false;
00091         }
00092         // we only call shared_from_this() when someone has a shared ref to us.
00093         // In practice, this means when we have an owner.
00094         if ( obj->getParent() == 0 && mowner ) {
00095             obj->setOwner( mowner );
00096             obj->setParent( shared_from_this() );
00097         }
00098         services[obj->getName()] = obj;
00099         return true;
00100     }
00101 
00102     void Service::removeService( string const& name) {
00103         // carefully written to avoid destructor to call back on us when called from removeService.
00104         if ( services.count(name) ) {
00105             shared_ptr sp = services.find(name)->second;
00106             services.erase(name);
00107             sp.reset(); // this possibly deletes.
00108         }
00109     }
00110 
00111     Service::shared_ptr Service::provides() {
00112         try {
00113             return shared_from_this();
00114         } catch( boost::bad_weak_ptr& /*bw*/ ) {
00115             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();
00116             log(Error) <<"OR: upgrade to boost 1.40.0, then this error will go away." <<endlog();
00117             throw std::runtime_error("Illegal use of provides()");
00118         }
00119     }
00120 
00121     Service::shared_ptr Service::provides(const std::string& service_name) {
00122         if (service_name == "this")
00123             return provides();
00124         shared_ptr sp = services[service_name];
00125         if (sp)
00126             return sp;
00127         sp = boost::make_shared<Service>(service_name, mowner);
00128         sp->setOwner( mowner );
00129         sp->setParent( shared_from_this() );
00130         services[service_name] = sp;
00131         return sp;
00132     }
00133 
00134     Service::shared_ptr Service::getService(const std::string& service_name) {
00135         Services::iterator it = services.find(service_name);
00136         if (it != services.end() )
00137             return it->second;
00138         return shared_ptr();
00139     }
00140 
00141     OperationInterfacePart* Service::getOperation( std::string name )
00142     {
00143         Logger::In in("Service::getOperation");
00144         if ( this->hasMember(name ) ) {
00145             return this->getPart(name);
00146         }
00147         log(Warning) << "No such operation in service '"<< getName() <<"': "<< name <<endlog();
00148         return 0;
00149     }
00150 
00151     bool Service::resetOperation(std::string name, base::OperationBase* impl)
00152     {
00153         if (!hasOperation(name))
00154             return false;
00155         simpleoperations[name] = impl;
00156         return true;
00157     }
00158 
00159     bool Service::setOperationThread(std::string const& name, ExecutionThread et)
00160     {
00161         if ( !hasOperation(name) )
00162             return false;
00163         DisposableInterface::shared_ptr di = getOperation(name)->getLocalOperation();
00164         OperationCallerInterface::shared_ptr oci = dynamic_pointer_cast<OperationCallerInterface>(di);
00165         if (oci) {
00166             return oci->setThread( et, getOwner() ? getOwner()->engine() : 0 );
00167         }
00168         return false;
00169     }
00170 
00171     bool Service::hasService(const std::string& service_name) {
00172         if (service_name == "this")
00173             return true;
00174         return services.find(service_name) != services.end();
00175     }
00176 
00177     bool Service::addLocalOperation( OperationBase& op )
00178     {
00179         Logger::In in("Service::addLocalOperation");
00180         if ( op.getName().empty() ) {
00181             log(Error) << "Failed to add Operation: '"<< op.getName() <<"' has no name." <<endlog();
00182             return false;
00183         }
00184         // don't check ready() since the op may not have an owner yet:
00185         if ( !op.getImplementation() ) {
00186             log(Error) << "Failed to add Operation: '"<< op.getName() <<"' is not ready: not bound to a function." <<endlog();
00187             return false;
00188         }
00189         if ( simpleoperations.count( op.getName() ) ) {
00190             log(Warning) << "While adding Operation: '"<< op.getName() <<"': replacing previously added operation." <<endlog();
00191             this->removeOperation(op.getName());
00192         }
00193         simpleoperations[op.getName()] = &op;
00194         // finally set the (new) owner:
00195         if (mowner)
00196             op.setOwner(mowner->engine());
00197         return true;
00198     }
00199 
00200     boost::shared_ptr<base::DisposableInterface> Service::getLocalOperation( std::string name ) {
00201         if ( hasOperation(name) ) {
00202             return simpleoperations.find(name)->second->getImplementation();
00203         }
00204         return boost::shared_ptr<base::DisposableInterface>();
00205     }
00206 
00207     void Service::clear()
00208     {
00209         while ( !simpleoperations.empty() )
00210         {
00211             simpleoperations.erase(simpleoperations.begin() );
00212         }
00213 
00214         for_each(ownedoperations.begin(),ownedoperations.end(), lambda::delete_ptr() );
00215         ownedoperations.clear();
00216 
00217         OperationInterface::clear();
00218         ConfigurationInterface::clear();
00219         while ( !services.empty() ) {
00220             this->removeService( services.begin()->first );
00221         }
00222     }
00223 
00224     std::vector<std::string> Service::getOperationNames() const
00225     {
00226         return keys(simpleoperations);
00227         //return getNames();
00228     }
00229 
00230     bool Service::hasOperation(const std::string& name) const
00231     {
00232         return simpleoperations.count(name) == 1;
00233         //return hasMember(name);
00234     }
00235 
00236     void Service::removeOperation(const std::string& name)
00237     {
00238         if (!hasOperation(name))
00239             return;
00240         OperationList::iterator it = find(ownedoperations.begin(), ownedoperations.end(), simpleoperations.find(name)->second );
00241         if (it != ownedoperations.end()) {
00242             delete *it;
00243             ownedoperations.erase(it);
00244         }
00245         simpleoperations.erase( name );
00246         OperationInterface::remove(name);
00247     }
00248     void Service::setOwner(TaskContext* new_owner) {
00249         for( SimpleOperations::iterator it= simpleoperations.begin(); it != simpleoperations.end(); ++it)
00250             it->second->setOwner( new_owner ? new_owner->engine() : 0);
00251 
00252         this->mowner = new_owner;
00253 
00254         for( Services::iterator it= services.begin(); it != services.end(); ++it) {
00255             it->second->setOwner( new_owner );
00256             if (new_owner)
00257                 it->second->setParent( shared_from_this() );
00258         }
00259     }
00260 
00261     void Service::setParent( Service::shared_ptr p) {
00262         parent = p;
00263     }
00264 
00265     internal::OperationCallerC Service::create(std::string name, ExecutionEngine* caller) {
00266         return internal::OperationCallerC( getPart(name), name, caller );
00267     }
00268 
00269 }