ecto
cell.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011, Willow Garage, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * * Neither the name of the Willow Garage, Inc. nor the names of its
14  * contributors may be used to endorse or promote products derived from
15  * this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 #pragma once
30 
31 #include <Python.h>
32 #include <ecto/forward.hpp>
33 #include <ecto/log.hpp>
34 #include <ecto/strand.hpp>
35 #include <ecto/tendril.hpp>
36 #include <ecto/tendrils.hpp>
37 #include <ecto/traits.hpp>
38 #include <ecto/util.hpp>
39 
40 #include <boost/noncopyable.hpp>
41 #include <boost/optional.hpp>
42 #include <boost/shared_ptr.hpp>
43 
44 namespace ecto
45 {
51  {
52  OK = 0,
53  QUIT = 1,
54  DO_OVER = 2,
55  BREAK = 3,
56  CONTINUE = 4,
57  UNKNOWN = -1
58  };
59 
60 #define ECTO_RETURN_VALUES \
61  (OK)(QUIT)(DO_OVER)(BREAK)(CONTINUE)(UNKNOWN) \
62 
63  const std::string&
64  ReturnCodeToStr(int rval);
65 
93  struct ECTO_EXPORT cell: boost::noncopyable
94  {
95  typedef boost::shared_ptr<cell> ptr;
96 
97  cell();
98  virtual ~cell();
99 
103  void declare_params();
108  void declare_io();
109 
114  void configure();
115 
119  void activate();
120 
124  void deactivate();
125 
127  void start();
128 
130  void stop();
131 
139  ReturnCode process();
140  ReturnCode process_with_only_these_inputs(const tendrils& connected_inputs);
141 
145  std::string type() const { return dispatch_name(); }
146 
151  std::string name() const
152  { return instance_name_.size() ? instance_name_ : dispatch_name(); }
153 
155  void name(const std::string& name)
156  { instance_name_ = name; }
157 
159  std::string short_doc() const
160  { return dispatch_short_doc(); }
161 
163  void short_doc(const std::string& short_doc)
164  { dispatch_short_doc(short_doc); }
165 
166  void reset_strand();
167  void set_strand(ecto::strand);
168 
174  std::string gen_doc(const std::string& doc = "A module...") const;
175 
176  void verify_params() const;
177  void verify_inputs() const;
178 
186  return process_connected_inputs_only_;
187  }
188  void set_process_connected_inputs_only(const bool &value) {
189  process_connected_inputs_only_ = value;
190  }
191 
192  ptr clone() const;
193 
200 
202  boost::optional<strand> strand_;
203 
204  virtual bool init() = 0;
205 
206  protected:
207 
208  virtual void dispatch_declare_params(tendrils& t) = 0;
209 
210  virtual void dispatch_declare_io(const tendrils& params, tendrils& inputs,
211  tendrils& outputs) = 0;
212 
213  virtual void dispatch_configure(const tendrils& params,
214  const tendrils& inputs,
215  const tendrils& outputs) = 0;
216 
217  virtual void dispatch_activate() = 0;
218 
219  virtual void dispatch_deactivate() = 0;
220 
221  virtual ReturnCode dispatch_process(const tendrils& inputs,
222  const tendrils& outputs) = 0;
223 
224  virtual void dispatch_start() = 0;
225  virtual void dispatch_stop() = 0;
226 
227  virtual std::string dispatch_name() const = 0;
228 
229  virtual ptr dispatch_clone() const = 0;
230 
231  virtual std::string dispatch_short_doc() const
232  { return std::string(); }
233 
234  virtual void dispatch_short_doc(const std::string&) { }
235 
236  private:
237  cell(const cell&);
238 
239  std::string instance_name_;
243 
244  }; // cell
245 
246 
251  template<class T>
252  struct has_f
253  {
254  typedef char yes;
255  typedef char (&no)[2];
256 
257  // SFINAE eliminates this when the type of arg is invalid
258  // overload resolution prefers anything at all over "..."
259  template<class U>
260  static yes test_declare_params(__typeof__(&U::declare_params));
261  template<class U>
262  static no test_declare_params(...);
263  enum
264  {
265  declare_params = sizeof(test_declare_params<T> (0)) == sizeof(yes)
266  };
267 
268  template<class U>
269  static yes test_declare_io(__typeof__(&U::declare_io));
270  template<class U>
271  static no test_declare_io(...);
272  enum
273  {
274  declare_io = sizeof(test_declare_io<T> (0)) == sizeof(yes)
275  };
276 
277  template<class U>
278  static yes test_configure(__typeof__(&U::configure));
279  template<class U>
280  static no test_configure(...);
281  enum
282  {
283  configure = sizeof(test_configure<T> (0)) == sizeof(yes)
284  };
285 
286  template<class U>
287  static yes test_activate(__typeof__(&U::activate));
288  template<class U>
289  static no test_activate(...);
290  enum
291  {
292  activate = sizeof(test_activate<T> (0)) == sizeof(yes)
293  };
294 
295  template<class U>
296  static yes test_deactivate(__typeof__(&U::deactivate));
297  template<class U>
298  static no test_deactivate(...);
299  enum
300  {
301  deactivate = sizeof(test_deactivate<T> (0)) == sizeof(yes)
302  };
303 
304  template<class U>
305  static yes test_process(__typeof__(&U::process));
306  template<class U>
307  static no test_process(...);
308  enum
309  {
310  process = sizeof(test_process<T> (0)) == sizeof(yes)
311  };
312 
313  template<class U>
314  static yes test_start(__typeof__(&U::start));
315  template<class U>
316  static no test_start(...);
317  enum
318  {
319  start = sizeof(test_start<T> (0)) == sizeof(yes)
320  };
321 
322  template<class U>
323  static yes test_stop(__typeof__(&U::stop));
324  template<class U>
325  static no test_stop(...);
326  enum
327  {
328  stop = sizeof(test_stop<T> (0)) == sizeof(yes)
329  };
330  }; // has_f
331 
335  template<class Impl>
336  struct cell_: cell
337  {
338  typedef boost::shared_ptr<cell_<Impl> > ptr; //convience type def
339 
341  { init_strand(typename ecto::detail::is_threadsafe<Impl>::type()); }
342 
343  ~cell_() {
344  // Make sure all cells in the plasm are deactivated prior to exiting.
345  dispatch_deactivate();
346  }
347  template <int I> struct int_ { };
350 
351  // declare_params
353 
354  static void declare_params(tendrils& params, not_implemented) { }
355 
356  static void declare_params(tendrils& params, implemented)
357  { Impl::declare_params(params); }
358 
359  static void declare_params(tendrils& params)
360  { declare_params(params, has_declare_params()); }
361 
363  { declare_params(params); }
364 
365 
366  // declare_io
367  static void declare_io(const tendrils& params, tendrils& inputs,
368  tendrils& outputs, not_implemented)
369  { }
370 
371  static void declare_io(const tendrils& params, tendrils& inputs,
372  tendrils& outputs, implemented)
373  { Impl::declare_io(params, inputs, outputs); }
374 
376 
377  static void declare_io(const tendrils& params, tendrils& inputs,
378  tendrils& outputs)
379  { declare_io(params, inputs, outputs, has_declare_io()); }
380 
381  void dispatch_declare_io(const tendrils& params, tendrils& inputs,
382  tendrils& outputs)
383  { declare_io(params, inputs, outputs); }
384 
385  // configure
386  void configure(const tendrils&, const tendrils& , const tendrils&,
387  not_implemented)
388  { }
389 
390  void configure(const tendrils& params, const tendrils& inputs,
391  const tendrils& outputs, implemented)
392  { impl_->configure(params,inputs,outputs); }
393 
394  void dispatch_configure(const tendrils& params, const tendrils& inputs,
395  const tendrils& outputs)
396  { configure(params, inputs, outputs, int_<has_f<Impl>::configure> ()); }
397 
398  // activate
399  void activate(not_implemented) { }
400 
401  void activate(implemented)
402  { if(impl_) impl_->activate(); }
403 
405  { activate(int_<has_f<Impl>::activate> ()); }
406 
407  // deactivate
408  void deactivate(not_implemented) { }
409 
410  void deactivate(implemented)
411  { if(impl_) impl_->deactivate(); }
412 
414  { deactivate(int_<has_f<Impl>::deactivate> ()); }
415 
416  // process
417  ReturnCode process(const tendrils&, const tendrils&, not_implemented)
418  { return OK; }
419 
420  ReturnCode process(const tendrils& inputs, const tendrils& outputs,
421  implemented)
422  { return ReturnCode(impl_->process(inputs, outputs)); }
423 
425  const tendrils& outputs)
426  { return process(inputs, outputs, int_<has_f<Impl>::process> ()); }
427 
428  // start
429  void start(not_implemented) { }
430  void start(implemented) { impl_->start(); }
432  { start(int_<has_f<Impl>::start> ()); }
433 
434  // stop
435  void stop(not_implemented) { }
436  void stop(implemented) { impl_->stop(); }
437  void dispatch_stop() { stop(int_<has_f<Impl>::stop> ()); }
438 
439  std::string dispatch_name() const { return CELL_TYPE_NAME; }
440  std::string dispatch_short_doc() const { return SHORT_DOC; }
441  void dispatch_short_doc(const std::string&) { }
442 
444  { return cell::ptr(new cell_<Impl> ()); }
445 
446  bool init();
447  public:
448  static std::string SHORT_DOC;
450  static std::string CELL_NAME;
452  static std::string MODULE_NAME;
453  static const std::string CELL_TYPE_NAME;
455  Impl& impl() {
456  ECTO_ASSERT(impl_, "impl is null, call configure first");
457  return *impl_;
458  }
459  const Impl& impl() const {
460  ECTO_ASSERT(impl_, "impl is null, call configure first");
461  return *impl_;
462  }
463 
464  private:
465  boost::scoped_ptr<Impl> impl_;
466  void init_strand(boost::mpl::true_) { } // threadsafe
467 
468  void init_strand(boost::mpl::false_) {
469  static ecto::strand strand_;
470  cell::strand_ = strand_;
471  ECTO_ASSERT(cell::strand_->id() == strand_.id(), "Catastrophe... cells not correctly assignable");
472  ECTO_LOG_DEBUG("%s cell has strand id=%p", cell::type() % cell::strand_->id());
473  }
474  }; // cell_
475 
476  template<typename Impl>
478  {
479  try {
480  if(!impl_)
481  {
482  impl_.reset(new Impl);
483  Impl* i=impl_.get();
484  //these handle finalizing the registration of spores that
485  //were registered at static time.
486  parameters.realize_potential(i);
487  inputs.realize_potential(i);
488  outputs.realize_potential(i);
489  }
490  return static_cast<bool>(impl_);
491  } catch (const std::exception& e) {
492  ECTO_TRACE_EXCEPTION("const std::exception&");
493  BOOST_THROW_EXCEPTION(except::CellException()
494  << except::when("Construction")
495  << except::type(name_of(typeid(e)))
496  << except::cell_name(name())
497  << except::what(e.what()));
498  } catch (...) {
499  ECTO_TRACE_EXCEPTION("...");
500  BOOST_THROW_EXCEPTION(except::CellException()
501  << except::when("Construction")
502  << except::what("(unknown exception)")
503  << except::cell_name(name()));
504  }
505  }
506 
507  template<typename Impl>
508  std::string cell_<Impl>::SHORT_DOC;
509 
510  template<typename Impl>
511  std::string cell_<Impl>::CELL_NAME;
512 
513  template<typename Impl>
514  std::string cell_<Impl>::MODULE_NAME;
515 
516  template<typename Impl>
517  const std::string cell_<Impl>::CELL_TYPE_NAME = ecto::name_of<Impl>();
518 
519 } // End of namespace ecto.
#define ECTO_TRACE_EXCEPTION(E)
Definition: log.hpp:74
std::string type() const
Return the type of the child class.
Definition: cell.hpp:145
static void declare_params(tendrils &params, implemented)
Definition: cell.hpp:356
int_< 1 > implemented
Definition: cell.hpp:349
void dispatch_activate()
Definition: cell.hpp:404
void stop(not_implemented)
Definition: cell.hpp:435
Definition: strand.hpp:38
Definition: traits.hpp:36
bool process_connected_inputs_only_
Definition: cell.hpp:242
void dispatch_declare_params(tendrils &params)
Definition: cell.hpp:362
cell_()
Definition: cell.hpp:340
#define ECTO_LOG_DEBUG(fmg, args)
Definition: log.hpp:66
ReturnCode dispatch_process(const tendrils &inputs, const tendrils &outputs)
Definition: cell.hpp:424
boost::shared_ptr< cell > ptr
A convenience pointer typedef.
Definition: cell.hpp:95
std::string instance_name_
Definition: cell.hpp:239
Helper class for determining if client modules have function implementations or not.
Definition: cell.hpp:252
static void declare_io(const tendrils &params, tendrils &inputs, tendrils &outputs)
Definition: cell.hpp:377
void dispatch_stop()
Definition: cell.hpp:437
std::string dispatch_short_doc() const
Definition: cell.hpp:440
void short_doc(const std::string &short_doc)
Set the short_doc_ of the instance.
Definition: cell.hpp:163
ecto::cell is the non virtual interface to the basic building block of ecto graphs. This interface should never be the parent of client cell, but may be used for polymorphic access to client cells.
Definition: cell.hpp:93
static void declare_io(const tendrils &params, tendrils &inputs, tendrils &outputs, not_implemented)
Definition: cell.hpp:367
const Impl & impl() const
Definition: cell.hpp:459
int_< has_f< Impl >::declare_io > has_declare_io
Definition: cell.hpp:375
tendrils parameters
Parameters.
Definition: cell.hpp:195
ReturnCode process(const tendrils &, const tendrils &, not_implemented)
Definition: cell.hpp:417
void dispatch_deactivate()
Definition: cell.hpp:413
static const std::string CELL_TYPE_NAME
Definition: cell.hpp:453
#define ECTO_EXPORT
Definition: util.hpp:49
Unknown return code.
Definition: cell.hpp:57
Definition: parameters.hpp:11
void deactivate(not_implemented)
Definition: cell.hpp:408
void configure(const tendrils &, const tendrils &, const tendrils &, not_implemented)
Definition: cell.hpp:386
bool init()
Definition: cell.hpp:477
cell::ptr dispatch_clone() const
Definition: cell.hpp:443
static void declare_params(tendrils &params)
Definition: cell.hpp:359
This modules&#39; process call needs to be made again.
Definition: cell.hpp:54
const std::string & ReturnCodeToStr(int rval)
Stop execution in my scope, jump to top of scope.
Definition: cell.hpp:56
static std::string MODULE_NAME
The module that the cell is part of.
Definition: cell.hpp:452
boost::scoped_ptr< Impl > impl_
Definition: cell.hpp:465
boost::optional< strand > strand_
The strand that this cell should be executed in.
Definition: cell.hpp:202
void start(implemented)
Definition: cell.hpp:430
ReturnCode process(const tendrils &inputs, const tendrils &outputs, implemented)
Definition: cell.hpp:420
tendrils outputs
Outputs, outboxes, always have a valid value ( may be NULL )
Definition: cell.hpp:199
void init_strand(boost::mpl::true_)
Definition: cell.hpp:466
void dispatch_declare_io(const tendrils &params, tendrils &inputs, tendrils &outputs)
Definition: cell.hpp:381
int_< has_f< Impl >::declare_params > has_declare_params
Definition: cell.hpp:352
void init_strand(boost::mpl::false_)
Definition: cell.hpp:468
bool configured_
Definition: cell.hpp:240
boost::shared_ptr< cell_< Impl > > ptr
Definition: cell.hpp:338
ECTO_EXPORT const std::string & name_of(const std::type_info &ti)
Get the unmangled type name of a type_info object.
static void declare_io(const tendrils &params, tendrils &inputs, tendrils &outputs, implemented)
Definition: cell.hpp:371
void dispatch_configure(const tendrils &params, const tendrils &inputs, const tendrils &outputs)
Definition: cell.hpp:394
void configure(const tendrils &params, const tendrils &inputs, const tendrils &outputs, implemented)
Definition: cell.hpp:390
Everything A OK.
Definition: cell.hpp:52
char yes
Definition: cell.hpp:254
static std::string CELL_NAME
The python name for the cell.
Definition: cell.hpp:450
void name(const std::string &name)
Set the name of the instance.
Definition: cell.hpp:155
Explicit quit now.
Definition: cell.hpp:53
std::string short_doc() const
Set the short_doc_ of the instance.
Definition: cell.hpp:159
std::string name() const
Grab the name of the instance.
Definition: cell.hpp:151
Stop execution in my scope, jump to outer scope.
Definition: cell.hpp:55
ReturnCode
Return values for cell::process(). TODO: Should these live in cell? These are appropriate for non exc...
Definition: cell.hpp:50
tendrils inputs
Inputs, inboxes, always have a valid value ( may be NULL )
Definition: cell.hpp:197
void dispatch_start()
Definition: cell.hpp:431
void activate(implemented)
Definition: cell.hpp:401
bool activated_
Definition: cell.hpp:241
virtual void dispatch_short_doc(const std::string &)
Definition: cell.hpp:234
void start(not_implemented)
Definition: cell.hpp:429
virtual std::string dispatch_short_doc() const
Definition: cell.hpp:231
std::size_t id() const
Definition: cell.hpp:347
void deactivate(implemented)
Definition: cell.hpp:410
std::string dispatch_name() const
Definition: cell.hpp:439
static void declare_params(tendrils &params, not_implemented)
Definition: cell.hpp:354
bool process_connected_inputs_only() const
Processing mode query - only connected tendrils or all. Typically used by the scheduler to arrange in...
Definition: cell.hpp:185
void dispatch_short_doc(const std::string &)
Definition: cell.hpp:441
void stop(implemented)
Definition: cell.hpp:436
void set_process_connected_inputs_only(const bool &value)
Definition: cell.hpp:188
int_< 0 > not_implemented
Definition: cell.hpp:348
static std::string SHORT_DOC
Definition: cell.hpp:448
~cell_()
Definition: cell.hpp:343
The tendrils are a collection for the ecto::tendril class, addressable by a string key...
Definition: tendrils.hpp:53
void activate(not_implemented)
Definition: cell.hpp:399
Impl & impl()
Grab a typed reference to the implementation of the cell.
Definition: cell.hpp:455
cell_<T> is for registering an arbitrary class with the the cell NVI. This adds a barrier between cli...
Definition: cell.hpp:336
#define ECTO_ASSERT(X, msg)
Definition: log.hpp:49