Orocos Real-Time Toolkit  2.9.0
FunctionFactory.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  tag: Peter Soetens Tue Dec 21 22:43:08 CET 2004 FunctionFactory.cxx
3 
4  FunctionFactory.cxx - description
5  -------------------
6  begin : Tue December 21 2004
7  copyright : (C) 2004 Peter Soetens
8  email : peter.soetens@mech.kuleuven.ac.be
9 
10  ***************************************************************************
11  * This library is free software; you can redistribute it and/or *
12  * modify it under the terms of the GNU General Public *
13  * License as published by the Free Software Foundation; *
14  * version 2 of the License. *
15  * *
16  * As a special exception, you may use this file as part of a free *
17  * software library without restriction. Specifically, if other files *
18  * instantiate templates or use macros or inline functions from this *
19  * file, or you compile this file and link it with other files to *
20  * produce an executable, this file does not by itself cause the *
21  * resulting executable to be covered by the GNU General Public *
22  * License. This exception does not however invalidate any other *
23  * reasons why the executable file might be covered by the GNU General *
24  * Public License. *
25  * *
26  * This library is distributed in the hope that it will be useful, *
27  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
28  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
29  * Lesser General Public License for more details. *
30  * *
31  * You should have received a copy of the GNU General Public *
32  * License along with this library; if not, write to the Free Software *
33  * Foundation, Inc., 59 Temple Place, *
34  * Suite 330, Boston, MA 02111-1307 USA *
35  * *
36  ***************************************************************************/
37 
38 
39 #include "FunctionFactory.hpp"
40 
41 #include "../ExecutionEngine.hpp"
42 #include "../internal/GlobalEngine.hpp"
43 #include "CommandComposite.hpp"
44 #include "CommandBinary.hpp"
45 #include "CallFunction.hpp"
46 #include "CmdFunction.hpp"
47 #include "ConditionComposite.hpp"
48 #include "TryCommand.hpp"
49 #include <sstream>
50 #include <map>
51 #include <string>
52 #include "../internal/mystd.hpp"
53 #include <PropertyBag.hpp>
54 #include <Property.hpp>
55 #include "../Attribute.hpp"
56 #include "parse_exception.hpp"
57 #include "../internal/DataSourceCommand.hpp"
58 #include "../FactoryExceptions.hpp"
59 #include "../../Handle.hpp"
60 
61 
62 namespace RTT {
63  using namespace detail;
64 
66  : public DataSource<SendStatus>
67  {
69  public:
70  typedef boost::intrusive_ptr<CmdFunctionWrapper> shared_ptr;
71 
73  : alias(ds)
74  {}
75 
77 
78  bool evaluate() const {
79  return alias->evaluate();
80  }
81 
83  {
84  return alias->get();
85  }
86 
88  {
89  return alias->value();
90  }
91 
93  {
94  return alias->rvalue();
95  }
96 
97  virtual void reset() { /* nop, don't reset ! */ }
98 
99  virtual CmdFunctionWrapper* clone() const {
100  return new CmdFunctionWrapper(alias.get());
101  }
102  virtual CmdFunctionWrapper* copy( std::map<const base::DataSourceBase*, base::DataSourceBase*>& alreadyCloned ) const {
103  return new CmdFunctionWrapper(alias->copy(alreadyCloned) );
104  }
105  };
106 
107 
109  : func(pi), proc(procs) {}
110 
111  std::string FunctionFactory::resultType() const {
112  return func->getResult() ? func->getResult()->getDataSource()->getTypeName() : "void";
113  }
114 
115  std::string FunctionFactory::getName() const {
116  return func->getName();
117  }
118 
119  std::string FunctionFactory::description() const {
120  return "Orocos Program Script Function.";
121  }
122 
123  std::vector< ArgumentDescription > FunctionFactory::getArgumentList() const
124  {
125  std::vector<AttributeBase*> origlist = func->getArguments();
126  std::vector< ArgumentDescription > mlist;
127  for ( std::vector<AttributeBase*>::const_iterator it = origlist.begin();
128  it != origlist.end(); ++it)
129  mlist.push_back( ArgumentDescription( "arg", "Function Argument", (*it)->getDataSource()->getType() ) );
130  return mlist;
131  }
132 
133  unsigned int FunctionFactory::arity( ) const
134  {
135  return func->getArguments().size();
136  }
137 
138  unsigned int FunctionFactory::collectArity( ) const
139  {
140  return func->getResult() ? 1 : 0;
141  }
142 
143  const types::TypeInfo* FunctionFactory::getArgumentType(unsigned int arg) const
144  {
145  if (arg == 0 ) {
146  if ( func->getResult() )
147  return func->getResult()->getDataSource()->getTypeInfo();
148  else
150  }
151  std::vector<AttributeBase*> origlist = func->getArguments();
152  if ( arg > origlist.size() )
153  return 0;
154  return origlist[arg - 1]->getDataSource()->getTypeInfo();
155  }
156 
157  const types::TypeInfo* FunctionFactory::getCollectType(unsigned int arg) const {
158  if (arg == 1 && collectArity() )
159  return func->getResult()->getDataSource()->getTypeInfo();
160  return 0;
161  }
162 
164  const std::vector<DataSourceBase::shared_ptr>& args
165  , ExecutionEngine* caller
166  ) const {
167  bool issend = false;
168  return produceHelper(args, caller, issend);
169  }
170 
171  DataSourceBase::shared_ptr FunctionFactory::produceHelper(
172  const std::vector<DataSourceBase::shared_ptr>& args
173  , ExecutionEngine* caller, bool issend
174  ) const {
175  // check if correct number of args :
176  boost::shared_ptr<ProgramInterface> orig = func;
177  std::vector<AttributeBase*> origlist = orig->getArguments();
178  if ( args.size() != origlist.size() )
179  throw wrong_number_of_args_exception( origlist.size(), args.size() );
180 
181  // make a semi-deep copy of the function :
182  // copy the local variables, but clone() the remote datasources.
183  std::map<const DataSourceBase*, DataSourceBase*> replacementdss;
184  assert( orig );
185  boost::shared_ptr<ProgramInterface> fcopy( orig->copy( replacementdss ) );
186  assert( fcopy );
187  // create commands that init all the args :
188  CommandComposite* icom= new CommandComposite();
189 
190  // get the correct pointers.
191  origlist = fcopy->getArguments();
192  std::vector<DataSourceBase::shared_ptr>::const_iterator dit = args.begin();
193  std::vector<AttributeBase*>::const_iterator tit = origlist.begin();
194 #ifndef ORO_EMBEDDED
195  try {
196  for (; dit != args.end(); ++dit, ++tit)
197  icom->add( (*tit)->getDataSource()->updateAction( dit->get() ) );
198  }
199  catch( const bad_assignment& ) {
200  delete icom;
201  int parnb = (dit - args.begin()) + 1;
202  throw wrong_types_of_args_exception(parnb, (*tit)->getDataSource()->getType() ,(*dit)->getType() );
203  }
204 #else
205  for (; dit != args.end(); ++dit, ++tit) {
206  ActionInterface* ret = (*tit)->getDataSource()->updateAction( dit->get() );
207  if (ret)
208  icom->add( ret );
209  else {
210  delete icom;
211  return 0;
212  }
213  }
214 #endif
215 
216  // the args of the copy can now safely be removed (saves memory):
217  //fcopy->clearArguments();
218 
219  if (!caller)
220  caller = GlobalEngine::Instance();
221  if (issend == false) {
222  // the command gets ownership of the new function :
223  // this command is a DataSourceBase...
224  AttributeBase* ar= fcopy->getResult();
225  if (ar)
226  return ar->getDataSource()->getTypeInfo()->buildActionAlias( new CallFunction( icom, fcopy, proc, caller ), ar->getDataSource()).get();
227  else // void case, returns result of runFunction (backwards compatibility).
228  return new DataSourceCommand( new CallFunction( icom, fcopy, proc, caller ) );
229  } else {
230  return new CmdFunction( icom, fcopy, proc, caller );
231  }
232  }
233 
236  }
237  base::DataSourceBase::shared_ptr FunctionFactory::produceSend(const std::vector<base::DataSourceBase::shared_ptr>& args, ExecutionEngine* caller
238  ) const {
239  return produceHelper(args, caller, true);
240  }
241  base::DataSourceBase::shared_ptr FunctionFactory::produceCollect(const std::vector<base::DataSourceBase::shared_ptr>& args, DataSource<bool>::shared_ptr blocking
242  ) const {
243  if (blocking->get() == true )
244  throw no_asynchronous_operation_exception("Blocking call to collect() not yet implemented for scripting functions. Use collectIfDone().");
245 
246  if (args.size() >= 1) {
247  if ( dynamic_cast<CmdFunction* > (args[0].get()) != 0 ) {
248  // The CmdFunction : wrap it and return it
249  // wrapping is necessary because we don't want to propagate reset()
250  return new CmdFunctionWrapper( dynamic_cast<CmdFunction*>(args[0].get()) );
251  } else if ( dynamic_cast<CmdFunctionWrapper* > (args[0].get()) != 0 ) {
252  // Return argument.
253  return args[0];
254  } else {
255  log(Error) <<"FunctionFactory: Please define your SendHandle with 'var SendHandle' for script functions." <<endlog();
256  return 0;
257  }
258 
259  }
260  log(Error) <<"FunctionFactory: Must provide an argument in produceCollect." <<endlog();
261  return 0;
262  }
263 #ifdef ORO_SIGNALLING_OPERATIONS
264  Handle FunctionFactory::produceSignal(base::ActionInterface* func, const std::vector<base::DataSourceBase::shared_ptr>& args, ExecutionEngine* subscriber
265  ) const {
266  throw no_asynchronous_operation_exception("Signal not yet implemented for scripting functions.");
267  return Handle();
268  }
269 #endif
270 }
271 
272 
DataSource is a base class representing a generic way to read data of type T.
Definition: DataSource.hpp:94
std::string resultType() const
Return the result (return) type of this operation.
const types::TypeInfo * getCollectType(unsigned int arg) const
Returns the type information of the n&#39;th collectable argument.
virtual result_t get() const =0
Return the data as type T.
std::string getName() const
Returns the name of this operation.
unsigned int collectArity() const
Returns the number of collectable arguments of this operation&#39;s function.
virtual CmdFunctionWrapper * copy(std::map< const base::DataSourceBase *, base::DataSourceBase * > &alreadyCloned) const
Create a deep copy of this internal::DataSource, unless it is already cloned.
base::DataSourceBase::shared_ptr produceCollect(const std::vector< base::DataSourceBase::shared_ptr > &args, internal::DataSource< bool >::shared_ptr blocking) const
Create a DataSource for collecting the results of a Send.
virtual CmdFunctionWrapper * clone() const
Return a shallow clone of this DataSource.
virtual DataSourceBase::shared_ptr getDataSource() const =0
Return a internal::DataSource which contains the same contents.
boost::shared_ptr< ProgramInterface > ProgramInterfacePtr
DataSource< SendStatus >::result_t value() const
Return the result of the last evaluate() function.
This exception is thrown if the target and source type of an assignment of a DataSource with a base::...
Definition: DataSource.hpp:62
An execution engine serialises (executes one after the other) the execution of all commands...
virtual DataSource< T > * copy(std::map< const base::DataSourceBase *, base::DataSourceBase * > &alreadyCloned) const =0
Create a deep copy of this internal::DataSource, unless it is already cloned.
const types::TypeInfo * getArgumentType(unsigned int arg) const
Returns the type information of the n&#39;th argument, with argument zero being the return value...
An attribute is a minimalistic, named placeholder for data.
virtual void reset()
Reset the data to initial values.
static const types::TypeInfo * getTypeInfo()
Return the typeinfo object.
static RTT_API ExecutionEngine * Instance()
This is an overloaded member function, provided for convenience. It differs from the above function o...
Description of one Argument of a Command.
virtual const_reference_t rvalue() const =0
Get a const reference to the value of this DataSource.
Based on the software pattern &#39;command&#39;, this interface allows execution of action objects...
base::DataSourceBase::shared_ptr produce(const std::vector< base::DataSourceBase::shared_ptr > &args, ExecutionEngine *caller) const
Create a DataSource for a given callable operation.
std::string description() const
Returns the description of this operation.
A class for representing a user type, and which can build instances of that type. ...
Definition: TypeInfo.hpp:67
std::vector< ArgumentDescription > getArgumentList() const
Get a description of the desired arguments in the ArgumentDescription format.
boost::intrusive_ptr< CmdFunctionWrapper > shared_ptr
unsigned int arity() const
Returns the arity (number of arguments) of this operation.
base::DataSourceBase::shared_ptr produceSend(const std::vector< base::DataSourceBase::shared_ptr > &args, ExecutionEngine *caller) const
Create a DataSource for a given send operation.
base::DataSourceBase::shared_ptr produceHandle() const
Create an empty SendHandle object for this operation.
A class that wraps a Command in a internal::DataSource<bool> interface.
A DataSource which sends a FunctionFraph for execution in a ExecutionEngine.
Definition: CmdFunction.hpp:26
Returned when the send() failed to deliver the operation call to the receiving component.
Definition: SendStatus.hpp:56
virtual void add(base::ActionInterface *com)
add a command to the vect
bool evaluate() const
Force an evaluation of the DataSourceBase.
Exception thrown when a factory is requested to create an object, but a wrong argument type was given...
virtual result_t value() const =0
Return the result of the last evaluate() function.
Exception thrown when a factory is requested to create an object but the wrong number of arguments wa...
boost::intrusive_ptr< DataSourceBase > shared_ptr
Use this type to store a pointer to a DataSourceBase.
Contains TaskContext, Activity, OperationCaller, Operation, Property, InputPort, OutputPort, Attribute.
Definition: Activity.cpp:52
DataSource< SendStatus >::const_reference_t rvalue() const
Get a const reference to the value of this DataSource.
CmdFunctionWrapper(DataSource< SendStatus > *ds)
An action which calls a FunctionFraph for execution in a ExecutionEngine.
virtual bool evaluate() const
Force an evaluation of the DataSourceBase.
Definition: DataSource.inl:52
A simple, yet very useful DataSource, which keeps a value, and returns it in its get() method...
Definition: DataSources.hpp:60
The Handle holds the information, and allows manipulation, of a connection between a internal::Signal...
Definition: Handle.hpp:66
Based on the software pattern &#39;composite&#39;, this class RTT_SCRIPTING_API allows composing command obje...
Exception thrown when a factory is requested to produce an asynchronous object while it is not availa...
FunctionFactory(ProgramInterfacePtr func, ExecutionEngine *procs)