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