Orocos Real-Time Toolkit  2.8.3
OperationCallerC.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  tag: Peter Soetens Wed Jan 18 14:11:40 CET 2006 OperationCallerC.cxx
3 
4  OperationCallerC.cxx - description
5  -------------------
6  begin : Wed January 18 2006
7  copyright : (C) 2006 Peter Soetens
8  email : peter.soetens@mech.kuleuven.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 "OperationCallerC.hpp"
40 #include "../FactoryExceptions.hpp"
41 #include "DataSourceCommand.hpp"
42 #include "../Service.hpp"
43 #include "../Logger.hpp"
44 #include "Exceptions.hpp"
45 #include <vector>
46 
47 namespace RTT
48 { namespace internal {
49 
50  using namespace detail;
51 
52 
54  {
55  public:
58  std::string mname;
59  std::vector<DataSourceBase::shared_ptr> args;
63 
64  void checkAndCreate() {
65  if ( ofp ) {
66  size_t sz = ofp->arity();
67  if ( sz == args.size() ) {
68  // may throw or return nill
69  m = ofp->produce(args, caller );
70  try {
71  s = ofp->produceSend(args, caller );
72  } catch( no_asynchronous_operation_exception const& /*e*/) {
73  // leave s empty.
74  }
75  args.clear();
76  if ( !m )
77  return;
78  if (rta)
79  try {
80  m = new DataSourceCommand( rta->updateAction( m.get() ) );
81  } catch( bad_assignment& /*ba*/ ) {
82  Logger::In in("OperationCallerC");
83  log(Error) << "Error in OperationCallerC::ret : can not convert return value of type "<< m->getType() << " to given type "<< rta->getType()<<endlog();
84  }
85 
86  }
87  }
88  }
89 
91  {
92  this->args.push_back( na );
93  this->checkAndCreate();
94  }
95 
96  void ret(AttributeBase* r)
97  {
98  this->rta = r->getDataSource();
99  }
100 
102  {
103  this->rta = d;
104  }
105 
106  D( OperationInterfacePart* mr, const std::string& name, ExecutionEngine* caller)
107  : ofp(mr), caller(caller), mname(name), rta(), m(), s()
108  {
109  this->checkAndCreate();
110  }
111 
112  D(const D& other)
113  : ofp(other.ofp), caller(other.caller), mname(other.mname),
114  args( other.args ), rta( other.rta ), m( other.m ), s(other.s)
115  {
116  }
117 
118  ~D()
119  {
120  }
121 
122  };
123 
125  : d(0), ofp(0)
126  {
127  }
128 
130  : d( mr ? new D( mr, name, caller) : 0 ), ofp(mr), mname(name)
131  {
132  if ( d && d->m ) {
133  this->m = d->m;
134  this->s = d->s;
135  delete d;
136  d = 0;
137  } else {
138  if (mr == 0)
139  log(Error) <<"Can not construct OperationCallerC for '"<<name<<"' from null OperationInterfacePart."<<endlog();
140  }
141  }
142 
144  : d( other.d ? new D(*other.d) : 0 ), m( other.m ? other.m : 0), s( other.s ? other.s : 0), ofp(other.ofp), mname(other.mname)
145  {
146  }
147 
149  : d( other.d ? new D(*other.d) : 0 ), ofp(other.ofp), mname(other.mname)
150  {
151  if ( d ) {
152  d->caller = caller;
153  } else {
154  d = new D(other.ofp, other.mname, caller);
155  }
156  }
157 
159  {
160  if ( &other == this )
161  return *this;
162  delete d;
163  d = ( other.d ? new D(*other.d) : 0 );
164  m = other.m;
165  s = other.s;
166  ofp = other.ofp;
167  mname = other.mname;
168  return *this;
169  }
170 
172  {
173  delete d;
174  }
175 
177  {
178  if (d)
179  d->newarg( a );
180  else {
181  Logger::log() <<Logger::Warning << "Extra argument discarded for OperationCallerC."<<Logger::endl;
182  }
183  if ( d && d->m ) {
184  this->m = d->m;
185  this->s = d->s;
186  delete d;
187  d = 0;
188  }
189  return *this;
190  }
191 
193  {
194  if (d)
195  d->ret( r );
196  else {
197  if (m) {
198  try {
199  m = new DataSourceCommand(r->getDataSource()->updateAction( m.get() ) );
200  } catch( bad_assignment& /*ba*/ ) {
201  log(Error) << "Error in OperationCallerC::ret : can not convert return value of type "<< m->getType() << " to given type "<< r->getDataSource()->getType()<<endlog();
202  }
203  } else
204  log(Error) <<"Can not add return argument to invalid OperationCallerC."<<endlog();
205  }
206  return *this;
207  }
208 
210  {
211  if (d)
212  d->ret( r );
213  else {
214  // no d, store manually:
215  if (m)
216  m = new DataSourceCommand(r->updateAction( m.get() ) );
217  else
218  log(Error) <<"Can not add return argument to invalid OperationCallerC."<<endlog();
219  }
220  return *this;
221  }
222 
224  if (m)
225  return m->evaluate();
226  else {
227  Logger::log() <<Logger::Error << "call() called on incomplete OperationCallerC."<<Logger::endl;
228  if (d) {
229  size_t sz;
230  sz = d->ofp->arity();
231  Logger::log() <<Logger::Error << "Wrong number of arguments provided for method '"+d->mname+"'"<<Logger::nl;
232  Logger::log() <<Logger::Error << "Expected "<< sz << ", got: " << d->args.size() <<Logger::endl;
233  }
234  }
235  return false;
236  }
237 
239  if (d) {
240  // something went wrong, let producer throw
241  if (d->ofp)
242  DataSourceBase::shared_ptr dummy = d->ofp->produce( d->args, d->caller );
243  else
244  throw name_not_found_exception( d->mname );
245  }
246  }
247 
250  try {
251  h = ofp->produceHandle();
252  } catch( no_asynchronous_operation_exception const& nao) {
253  log(Error) <<"OperationCallerC::send(): Can not send the '" << ofp->getName() << "' operation:" << nao.what() << endlog();
254  return SendHandleC();
255  }
256  if (s) {
257  // evaluate and copy result of s to handle and pass handle to SendHandleC.
258 #ifndef NDEBUG
259  bool result =
260 #endif
261  h->update( s.get() );
262  assert( result );
263  return SendHandleC( s, h, ofp, mname );
264  }
265  else {
266  Logger::log() <<Logger::Error << "send() called on incomplete OperationCallerC."<<Logger::endl;
267  if (d) {
268  size_t sz;
269  sz = d->ofp->arity();
270  Logger::log() <<Logger::Error << "Wrong number of arguments provided for method '"+d->mname+"'"<<Logger::nl;
271  Logger::log() <<Logger::Error << "Expected "<< sz << ", got: " << d->args.size() <<Logger::endl;
272  }
273  }
274  return SendHandleC();
275  }
276 
278  {
279  return m != 0;
280  }
281 
283  return ofp;
284  }
285 
286  std::string const& OperationCallerC::getName() const {
287  return mname;
288  }
289 
292 
293 }}
OperationCallerC & arg(base::DataSourceBase::shared_ptr a)
Add a datasource argument to the OperationCaller.
base::DataSourceBase::shared_ptr getCallDataSource()
Get the contained data source for &#39;call&#39;.
virtual base::DataSourceBase::shared_ptr produceSend(const std::vector< base::DataSourceBase::shared_ptr > &args, ExecutionEngine *caller) const =0
Create a DataSource for a given send operation.
OperationCallerC & operator=(const OperationCallerC &other)
A OperationCallerC is assignable.
void newarg(DataSourceBase::shared_ptr na)
bool ready() const
Returns true if this method is ready for execution.
void check()
Checks if this method is ready for calling, will throw if not so.
SendHandleC send()
Send the contained method.
Exception thrown when a factory is requested to create an object with an unknown name.
static std::ostream & nl(std::ostream &__os)
Insert a newline &#39; &#39; in the ostream.
Definition: Logger.cpp:373
When Orocos is compiled without exceptions (define ORO_EMBEDDED), the functions which would throw an ...
virtual std::string getName() const =0
Returns the name of this operation.
virtual DataSourceBase::shared_ptr getDataSource() const =0
Return a internal::DataSource which contains the same contents.
DataSourceBase::shared_ptr rta
This exception is thrown if the target and source type of an assignment of a DataSource with a base::...
Definition: DataSource.hpp:62
D(OperationInterfacePart *mr, const std::string &name, ExecutionEngine *caller)
An execution engine serialises (executes one after the other) the execution of all commands...
virtual unsigned int arity() const =0
Returns the arity (number of arguments) of this operation.
A template-less SendHandle manager.
Definition: SendHandleC.hpp:61
virtual base::DataSourceBase::shared_ptr produceHandle() const =0
Create an empty SendHandle object for this operation.
An attribute is a minimalistic, named placeholder for data.
base::DataSourceBase::shared_ptr getSendDataSource()
Get the contained data source for &#39;send&#39;.
static std::ostream & endl(std::ostream &__os)
Definition: Logger.cpp:383
A template-less manager for OperationCaller calls.
virtual base::DataSourceBase::shared_ptr produce(const std::vector< base::DataSourceBase::shared_ptr > &args, ExecutionEngine *caller) const =0
Create a DataSource for a given callable operation.
This class defines the interface for creating operation objects without using C++ templates...
bool call()
Call the contained method.
OperationCallerC & ret(base::AttributeBase *r)
Store the result of the method in a task&#39;s attribute.
void ret(DataSourceBase::shared_ptr d)
OperationCallerC()
The default constructor.
A class that wraps a Command in a internal::DataSource<bool> interface.
DataSourceBase::shared_ptr s
std::vector< DataSourceBase::shared_ptr > args
Notify the Logger in which &#39;module&#39; the message occured.
Definition: Logger.hpp:159
static Logger & log()
As Instance(), but more userfriendly.
Definition: Logger.cpp:117
DataSourceBase::shared_ptr m
boost::intrusive_ptr< DataSourceBase > shared_ptr
Use this type to store a pointer to a DataSourceBase.
std::string const & getName() const
Returns the name of the operation that will be called.
Contains TaskContext, Activity, OperationCaller, Operation, Property, InputPort, OutputPort, Attribute.
Definition: Activity.cpp:51
OperationInterfacePart * getOrp() const
Returns the factory which we use to produce the operation call.
Exception thrown when a factory is requested to produce an asynchronous object while it is not availa...