Orocos Real-Time Toolkit
2.5.0
|
00001 /*************************************************************************** 00002 tag: The SourceWorks Tue Sep 7 00:55:18 CEST 2010 CallFunction.hpp 00003 00004 CallFunction.hpp - 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 #ifndef ORO_CALL_FUNCTION_HPP 00040 #define ORO_CALL_FUNCTION_HPP 00041 00042 #include "../base/ActionInterface.hpp" 00043 #include "../base/DisposableInterface.hpp" 00044 #include "../internal/DataSources.hpp" 00045 #include "ProgramInterface.hpp" 00046 #include "../internal/DataSource.hpp" 00047 #include "../ExecutionEngine.hpp" 00048 #include <boost/shared_ptr.hpp> 00049 #include <boost/bind.hpp> 00050 00051 namespace RTT 00052 { namespace scripting { 00053 using namespace detail; 00054 00062 class RTT_SCRIPTING_API CallFunction 00063 : public base::ActionInterface 00064 { 00065 base::ActionInterface* minit; 00066 ExecutionEngine* mrunner; 00067 ExecutionEngine* mcaller; 00071 internal::AssignableDataSource<ProgramInterface*>::shared_ptr _v; 00076 boost::shared_ptr<ProgramInterface> _foo; 00077 bool isqueued; 00078 bool maccept; 00079 00080 bool fooDone() { 00081 return _foo->inError() || _foo->isStopped(); 00082 } 00083 public: 00092 CallFunction( base::ActionInterface* init_com, 00093 boost::shared_ptr<ProgramInterface> foo, 00094 ExecutionEngine* p, ExecutionEngine* caller, 00095 internal::AssignableDataSource<ProgramInterface*>* v = 0 , 00096 internal::AssignableDataSource<bool>* a = 0 ) 00097 : minit(init_com), 00098 mrunner(p), mcaller(caller), 00099 _v( v==0 ? new internal::UnboundDataSource< internal::ValueDataSource<ProgramInterface*> >(foo.get()) : v ), 00100 _foo( foo ), isqueued(false), maccept(false) 00101 { 00102 } 00103 00104 ~CallFunction() { 00105 this->reset(); 00106 } 00107 00108 virtual bool execute() { 00109 // this is asyn behaviour : 00110 if (isqueued == false ) { 00111 isqueued = true; 00112 maccept = minit->execute() && mrunner->runFunction( _foo.get() ); 00113 // we ignore the ret value of start(). It could have been auto-started during loading() of the function. 00114 if ( _foo->needsStart() ) // _foo might be auto-started in runFunction() 00115 _foo->start(); 00116 if ( maccept ) { 00117 // block for the result: foo stopped or in error 00118 //mcaller->waitForFunctions(boost::bind(&CallFunction::fooDone,this) ); 00119 mrunner->waitForFunctions(boost::bind(&CallFunction::fooDone,this) ); 00120 if ( _foo->inError() ) { 00121 throw false; 00122 } 00123 return true; 00124 } 00125 return false; 00126 } 00127 return true; 00128 } 00129 00130 virtual void reset() { 00131 mrunner->removeFunction( _foo.get() ); 00132 maccept = false; 00133 isqueued = false; 00134 } 00135 00136 virtual bool valid() const { 00137 return maccept; 00138 } 00139 00140 virtual void readArguments() { 00141 // is called before runFunction is executed. 00142 minit->readArguments(); 00143 } 00144 00145 base::ActionInterface* clone() const 00146 { 00147 // _v is shared_ptr, so don't clone. 00148 return new CallFunction( minit->clone(), _foo, mrunner, mcaller, _v.get() ); 00149 } 00150 00151 base::ActionInterface* copy( std::map<const base::DataSourceBase*, base::DataSourceBase*>& alreadyCloned ) const 00152 { 00153 // this may seem strange, but : 00154 // make a copy of foo (a function), make a copy of _v (a datasource), store pointer to new foo in _v ! 00155 boost::shared_ptr<ProgramInterface> fcpy( _foo->copy(alreadyCloned) ); 00156 internal::AssignableDataSource<ProgramInterface*>* vcpy = _v->copy(alreadyCloned); 00157 vcpy->set( fcpy.get() ); // since we own _foo, we may manipulate the copy of _v 00158 return new CallFunction( minit->copy(alreadyCloned), fcpy , mrunner, mcaller, vcpy ); 00159 } 00160 00161 }; 00162 00163 }} 00164 00165 #endif