Orocos Real-Time Toolkit
2.5.0
|
00001 /*************************************************************************** 00002 tag: FMTC do nov 2 13:06:07 CET 2006 OperationCaller.hpp 00003 00004 OperationCaller.hpp - description 00005 ------------------- 00006 begin : do november 02 2006 00007 copyright : (C) 2006 FMTC 00008 email : peter.soetens@fmtc.be 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 #ifndef ORO_TASK_OPERATION_CALLER_HPP 00040 #define ORO_TASK_OPERATION_CALLER_HPP 00041 00042 #include <string> 00043 #include <boost/function.hpp> 00044 #include "base/OperationCallerBase.hpp" 00045 #ifdef ORO_TEST_OPERATION_CALLER 00046 #include "internal/UnMember.hpp" 00047 #include "internal/LocalOperationCaller.hpp" 00048 #endif 00049 #include "internal/InvokerSignature.hpp" 00050 #include "base/OperationCallerBaseInvoker.hpp" 00051 #include "Logger.hpp" 00052 #include "Service.hpp" 00053 #ifdef ORO_REMOTING 00054 #include "OperationInterface.hpp" 00055 #include "internal/RemoteOperationCaller.hpp" 00056 #endif 00057 00058 namespace RTT 00059 { 00081 template<class SignatureT> 00082 class OperationCaller 00083 : public internal::InvokerSignature<boost::function_traits<SignatureT>::arity, 00084 SignatureT, 00085 boost::shared_ptr< base::OperationCallerBase<SignatureT> > >, 00086 public base::OperationCallerBaseInvoker 00087 { 00088 std::string mname; 00089 ExecutionEngine* mcaller; 00090 public: 00091 typedef SignatureT Signature; 00092 typedef internal::InvokerSignature<boost::function_traits<Signature>::arity, 00093 Signature, 00094 boost::shared_ptr< base::OperationCallerBase<Signature> > > Base; 00095 typedef typename boost::function_traits<Signature>::result_type result_type; 00096 typedef boost::function_traits<Signature> traits; 00097 typedef boost::shared_ptr< base::OperationCallerBase<Signature> > OperationCallerBasePtr; 00098 00103 OperationCaller() 00104 : Base(), mname() 00105 {} 00106 00111 OperationCaller(std::string name, ExecutionEngine* caller = 0) 00112 : Base(), mname(name), mcaller(caller) 00113 {} 00114 00122 OperationCaller(const OperationCaller& m) 00123 : Base(m.impl ? boost::shared_ptr< base::OperationCallerBase<Signature> >(m.impl->cloneI(m.mcaller)) : m.impl ), 00124 mname(m.mname), mcaller(m.mcaller) 00125 {} 00126 00136 OperationCaller& operator=(const OperationCaller& m) 00137 { 00138 if ( this == &m ) 00139 return *this; 00140 mname = m.mname; 00141 mcaller = m.mcaller; 00142 if (m.impl) 00143 this->impl.reset( m.impl->cloneI(mcaller) ); 00144 else 00145 this->impl.reset(); 00146 return *this; 00147 } 00148 00158 OperationCaller(boost::shared_ptr<base::DisposableInterface> implementation, ExecutionEngine* caller = 0) 00159 : Base( boost::dynamic_pointer_cast< base::OperationCallerBase<Signature> >(implementation) ), 00160 mname(), mcaller(caller) 00161 { 00162 if ( !this->impl && implementation ) { 00163 log(Error) << "Tried to construct OperationCaller from incompatible local operation."<< endlog(); 00164 } else { 00165 if (this->impl) { 00166 this->impl.reset( this->impl->cloneI(mcaller) ); 00167 } 00168 } 00169 } 00170 00179 OperationCaller(OperationInterfacePart* part, ExecutionEngine* caller = 0) 00180 : Base(), 00181 mname(), mcaller(caller) 00182 { 00183 if (part) { 00184 mname = part->getName(); 00185 this->impl = boost::dynamic_pointer_cast< base::OperationCallerBase<Signature> >( part->getLocalOperation() ); 00186 setupOperationCaller( part ); 00187 } 00188 } 00189 00198 OperationCaller(const std::string& name, ServicePtr service, ExecutionEngine* caller = 0) 00199 : Base(), 00200 mname(name), mcaller(caller) 00201 { 00202 if (service) { 00203 this->impl = boost::dynamic_pointer_cast< base::OperationCallerBase<Signature> >( service->getLocalOperation(name) ); 00204 if (service->hasMember(name)) 00205 setupOperationCaller( service->getOperation(name) ); 00206 } 00207 } 00208 00217 OperationCaller& operator=(boost::shared_ptr<base::DisposableInterface> implementation) 00218 { 00219 if (this->impl && this->impl == implementation) 00220 return *this; 00221 OperationCaller<Signature> tmp(implementation); 00222 *this = tmp; 00223 return *this; 00224 } 00225 00235 OperationCaller& operator=(OperationInterfacePart* part) 00236 { 00237 if (part == 0) { 00238 log(Warning) << "Assigning OperationCaller from null part."<<endlog(); 00239 this->impl.reset(); 00240 } 00241 if (this->impl && this->impl == part->getLocalOperation() ) 00242 return *this; 00243 OperationCaller<Signature> tmp(part); 00244 *this = tmp; 00245 return *this; 00246 } 00247 00255 OperationCaller& operator=(ServicePtr service) 00256 { 00257 if ( !service ) { 00258 log(Warning) << "Assigning OperationCaller from null service."<<endlog(); 00259 this->impl.reset(); 00260 } 00261 if (this->mname.empty()) { 00262 log(Error) << "Can't initialise unnamed OperationCaller from service '"<<service->getName() <<"'."<<endlog(); 00263 return *this; 00264 } 00265 OperationCaller<Signature> tmp(mname,service); 00266 *this = tmp; 00267 return *this; 00268 } 00269 00270 #ifdef ORO_TEST_OPERATION_CALLER 00271 00279 template<class M, class ObjectType> 00280 OperationCaller(std::string name, M meth, ObjectType object, ExecutionEngine* ee = 0, ExecutionEngine* caller = 0, ExecutionThread et = ClientThread) 00281 : Base( OperationCallerBasePtr(new internal::LocalOperationCaller<Signature>(meth, object, ee, caller, et) ) ), 00282 mname(name), mcaller(caller) 00283 {} 00284 00291 template<class M> 00292 OperationCaller(std::string name, M meth, ExecutionEngine* ee = 0, ExecutionEngine* caller = 0, ExecutionThread et = ClientThread) 00293 : Base( OperationCallerBasePtr(new internal::LocalOperationCaller<Signature>(meth,ee,caller, et) ) ), 00294 mname(name), mcaller(caller) 00295 {} 00296 #endif 00297 #ifdef ORO_REMOTING 00298 00304 template<class M> 00305 OperationCaller(std::string name, OperationInterfacePart* orp, ExecutionEngine* caller = 0) 00306 : Base( OperationCallerBasePtr(new internal::RemoteOperationCaller<Signature>(orp,caller) ) ), 00307 mname(name) 00308 {} 00309 #endif 00310 00314 ~OperationCaller() 00315 { 00316 } 00317 00323 bool ready() const { 00324 return this->impl && this->impl->ready(); 00325 } 00326 00327 00331 std::string const& getName() const {return mname;} 00332 00333 bool setImplementation(boost::shared_ptr<base::DisposableInterface> implementation, ExecutionEngine* caller = 0) { 00334 *this = implementation; 00335 if ( this->impl ) { 00336 this->mcaller = caller; 00337 this->impl->setCaller(caller); 00338 } 00339 return ready(); 00340 } 00341 00342 bool setImplementationPart(OperationInterfacePart* orp, ExecutionEngine* caller = 0) { 00343 OperationCaller<Signature> tmp(orp, caller); 00344 if (tmp.ready()) { 00345 *this = tmp; 00346 return true; 00347 } 00348 return false; 00349 } 00350 00354 const OperationCallerBasePtr getOperationCallerImpl() const { 00355 return this->impl; 00356 } 00357 00361 void setOperationCallerImpl( OperationCallerBasePtr new_impl) const { 00362 this->impl = new_impl; 00363 } 00364 00365 void setCaller(ExecutionEngine* caller) { 00366 this->mcaller = caller; 00367 if (this->impl) 00368 this->impl->setCaller(caller); 00369 } 00370 00371 void disconnect() 00372 { 00373 this->impl.reset(); 00374 } 00375 protected: 00381 void setupOperationCaller(OperationInterfacePart* part) { 00382 if ( !this->impl ) { 00383 #ifdef ORO_REMOTING 00384 // try differently 00385 try { 00386 this->impl.reset( new internal::RemoteOperationCaller<Signature>( part, mname, mcaller )); 00387 } catch( std::exception& e ) { 00388 log(Error) << "Constructing RemoteOperationCaller for "<< mname <<" was not possible."<<endlog(); 00389 log(Error) << "Probable cause: " << e.what() <<endlog(); 00390 return; 00391 } 00392 if (this->impl->ready()) { 00393 log(Debug) << "Constructed OperationCaller from remote implementation '"<< mname<<"'."<< endlog(); 00394 this->impl->setCaller(mcaller); 00395 } else { 00396 this->impl.reset(); // clean up. 00397 log(Error) << "Tried to construct OperationCaller from incompatible operation '"<< mname<<"'."<< endlog(); 00398 } 00399 #else 00400 log(Error) << "Tried to construct remote OperationCaller but ORO_REMOTING was disabled."<< endlog(); 00401 #endif 00402 } else { 00403 // finally clone and set caller on clone. 00404 this->impl.reset( this->impl->cloneI(mcaller) ); 00405 } 00406 } 00407 00408 }; 00409 00410 #ifdef ORO_TEST_OPERATION_CALLER 00411 00418 template<class F, class O> 00419 OperationCaller< typename internal::UnMember<F>::type > method(std::string name, F method, O object, ExecutionEngine* ee = 0, ExecutionEngine* caller = 0) { 00420 return OperationCaller< typename internal::UnMember<F>::type >(name, method, object, ee, caller); 00421 } 00422 00429 template<class F> 00430 OperationCaller<F> method(std::string name, F method, ExecutionEngine* ee = 0, ExecutionEngine* caller = 0) { 00431 return OperationCaller<F>(name, method, ee, caller); 00432 } 00439 template<class F> 00440 OperationCaller< typename internal::ArgMember<F>::type > method_ds(std::string name, F method, ExecutionEngine* ee = 0, ExecutionEngine* caller = 0) { 00441 return OperationCaller< typename internal::ArgMember<F>::type >(name, method, ee, caller); 00442 } 00443 #endif 00444 } 00445 00446 #endif