Orocos Real-Time Toolkit  2.9.0
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  using namespace detail;
49 
50 
52  {
53  public:
56  std::string mname;
57  std::vector<DataSourceBase::shared_ptr> args;
61 
62  void checkAndCreate() {
63  if ( ofp ) {
64  size_t sz = ofp->arity();
65  if ( sz == args.size() ) {
66  // may throw or return nill
67  m = ofp->produce(args, caller );
68  try {
69  s = ofp->produceSend(args, caller );
70  } catch( no_asynchronous_operation_exception const& /*e*/) {
71  // leave s empty.
72  }
73  args.clear();
74  if ( !m )
75  return;
76  if (rta)
77  try {
78  m = new DataSourceCommand( rta->updateAction( m.get() ) );
79  } catch( bad_assignment& /*ba*/ ) {
80  Logger::In in("OperationCallerC");
81  log(Error) << "Error in OperationCallerC::ret : can not convert return value of type "<< m->getType() << " to given type "<< rta->getType()<<endlog();
82  }
83 
84  }
85  }
86  }
87 
89  {
90  this->args.push_back( na );
91  this->checkAndCreate();
92  }
93 
94  void ret(AttributeBase* r)
95  {
96  this->rta = r->getDataSource();
97  }
98 
100  {
101  this->rta = d;
102  }
103 
104  D( OperationInterfacePart* mr, const std::string& name, ExecutionEngine* caller)
105  : ofp(mr), caller(caller), mname(name), rta(), m(), s()
106  {
107  this->checkAndCreate();
108  }
109 
110  D(const D& other)
111  : ofp(other.ofp), caller(other.caller), mname(other.mname),
112  args( other.args ), rta( other.rta ), m( other.m ), s(other.s)
113  {
114  }
115 
116  ~D()
117  {
118  }
119 
120  };
121 
123  : d(0), ofp(0)
124  {
125  }
126 
127  OperationCallerC::OperationCallerC(OperationInterfacePart* mr, const std::string& name, ExecutionEngine* caller)
128  : d( mr ? new D( mr, name, caller) : 0 ), ofp(mr), mname(name)
129  {
130  if ( d && d->m ) {
131  this->m = d->m;
132  this->s = d->s;
133  delete d;
134  d = 0;
135  } else {
136  if (mr == 0)
137  log(Error) <<"Can not construct OperationCallerC for '"<<name<<"' from null OperationInterfacePart."<<endlog();
138  }
139  }
140 
142  : 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)
143  {
144  }
145 
147  : d( other.d ? new D(*other.d) : 0 ), ofp(other.ofp), mname(other.mname)
148  {
149  if ( d ) {
150  d->caller = caller;
151  } else {
152  d = new D(other.ofp, other.mname, caller);
153  }
154  }
155 
157  {
158  if ( &other == this )
159  return *this;
160  delete d;
161  d = ( other.d ? new D(*other.d) : 0 );
162  m = other.m;
163  s = other.s;
164  ofp = other.ofp;
165  mname = other.mname;
166  return *this;
167  }
168 
170  {
171  delete d;
172  }
173 
175  {
176  if (d)
177  d->newarg( a );
178  else {
179  Logger::log() <<Logger::Warning << "Extra argument discarded for OperationCallerC."<<Logger::endl;
180  }
181  if ( d && d->m ) {
182  this->m = d->m;
183  this->s = d->s;
184  delete d;
185  d = 0;
186  }
187  return *this;
188  }
189 
191  {
192  if (d)
193  d->ret( r );
194  else {
195  if (m) {
196  try {
197  m = new DataSourceCommand(r->getDataSource()->updateAction( m.get() ) );
198  } catch( bad_assignment& /*ba*/ ) {
199  log(Error) << "Error in OperationCallerC::ret : can not convert return value of type "<< m->getType() << " to given type "<< r->getDataSource()->getType()<<endlog();
200  }
201  } else
202  log(Error) <<"Can not add return argument to invalid OperationCallerC."<<endlog();
203  }
204  return *this;
205  }
206 
208  {
209  if (d)
210  d->ret( r );
211  else {
212  // no d, store manually:
213  if (m)
214  m = new DataSourceCommand(r->updateAction( m.get() ) );
215  else
216  log(Error) <<"Can not add return argument to invalid OperationCallerC."<<endlog();
217  }
218  return *this;
219  }
220 
221  bool OperationCallerC::call() {
222  if (m) {
223  m->reset();
224  return m->evaluate();
225  } else {
226  Logger::log() <<Logger::Error << "call() called on incomplete OperationCallerC."<<Logger::endl;
227  if (d) {
228  size_t sz;
229  sz = d->ofp->arity();
230  Logger::log() <<Logger::Error << "Wrong number of arguments provided for method '"+d->mname+"'"<<Logger::nl;
231  Logger::log() <<Logger::Error << "Expected "<< sz << ", got: " << d->args.size() <<Logger::endl;
232  }
233  }
234  return false;
235  }
236 
237  void OperationCallerC::check() {
238  if (d) {
239  // something went wrong, let producer throw
240  if (d->ofp)
241  DataSourceBase::shared_ptr dummy = d->ofp->produce( d->args, d->caller );
242  else
243  throw name_not_found_exception( d->mname );
244  }
245  }
246 
249  try {
250  h = ofp->produceHandle();
251  } catch( no_asynchronous_operation_exception const& nao) {
252  log(Error) <<"OperationCallerC::send(): Can not send the '" << ofp->getName() << "' operation:" << nao.what() << endlog();
253  return SendHandleC();
254  }
255  if (s) {
256  // evaluate and copy result of s to handle and pass handle to SendHandleC.
257  s->reset();
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 
277  bool OperationCallerC::ready() const
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 }
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.
void ret(DataSourceBase::shared_ptr d)
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.
std::string const & getName() const
Returns the name of the operation that will be called.
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 ...
base::DataSourceBase::shared_ptr getSendDataSource()
Get the contained data source for &#39;send&#39;.
std::vector< DataSourceBase::shared_ptr > args
OperationCallerC & ret(base::AttributeBase *r)
Store the result of the method in a task&#39;s attribute.
virtual DataSourceBase::shared_ptr getDataSource() const =0
Return a internal::DataSource which contains the same contents.
D(OperationInterfacePart *mr, const std::string &name, ExecutionEngine *caller)
DataSourceBase::shared_ptr m
OperationCallerC & operator=(const OperationCallerC &other)
A OperationCallerC is assignable.
DataSourceBase::shared_ptr s
This exception is thrown if the target and source type of an assignment of a DataSource with a base::...
Definition: DataSource.hpp:62
void ret(AttributeBase *r)
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.
base::DataSourceBase::shared_ptr getCallDataSource()
Get the contained data source for &#39;call&#39;.
OperationInterfacePart * getOrp() const
Returns the factory which we use to produce the operation call.
A template-less SendHandle manager.
Definition: SendHandleC.hpp:61
An attribute is a minimalistic, named placeholder for data.
void newarg(DataSourceBase::shared_ptr na)
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.
DataSourceBase::shared_ptr rta
This class defines the interface for creating operation objects without using C++ templates...
bool call()
Call the contained method.
OperationCallerC()
The default constructor.
A class that wraps a Command in a internal::DataSource<bool> interface.
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
OperationInterfacePart * ofp
OperationCallerC & arg(base::DataSourceBase::shared_ptr a)
Add a datasource argument to the OperationCaller.
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
Exception thrown when a factory is requested to produce an asynchronous object while it is not availa...