Orocos Real-Time Toolkit
2.6.0
|
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 }