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


rtt
Author(s): RTT Developers
autogenerated on Fri Sep 9 2016 04:01:58