TPIE

v1.1rc1-6-g0c97303
virtual.h
Go to the documentation of this file.
1 // -*- mode: c++; tab-width: 4; indent-tabs-mode: t; c-file-style: "stroustrup"; -*-
2 // vi:set ts=4 sts=4 sw=4 noet cino+=(0 :
3 // Copyright 2012, The TPIE development team
4 //
5 // This file is part of TPIE.
6 //
7 // TPIE is free software: you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License as published by the
9 // Free Software Foundation, either version 3 of the License, or (at your
10 // option) any later version.
11 //
12 // TPIE is distributed in the hope that it will be useful, but WITHOUT ANY
13 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 // License for more details.
16 //
17 // You should have received a copy of the GNU Lesser General Public License
18 // along with TPIE. If not, see <http://www.gnu.org/licenses/>
19 
23 
24 #ifndef __TPIE_PIPELINING_VIRTUAL_H__
25 #define __TPIE_PIPELINING_VIRTUAL_H__
26 
27 namespace tpie {
28 
29 namespace pipelining {
30 
37 public:
38  virtual ~virtual_container() {}
39 };
40 
41 namespace bits {
42 
47 template <typename T>
49  typedef const T & type;
50 };
51 
52 template <typename T>
53 struct maybe_add_const_ref<const T &> {
54  typedef const T & type;
55 };
56 
57 template <typename T>
58 struct maybe_add_const_ref<const T *> {
59  typedef const T * type;
60 };
61 
62 template <typename T>
63 struct maybe_add_const_ref<T &> {
64  typedef T & type;
65 };
66 
67 template <typename T>
68 struct maybe_add_const_ref<T *> {
69  typedef T * type;
70 };
71 
77 template <typename Input>
78 class virtsrc : public node {
79  typedef typename maybe_add_const_ref<Input>::type input_type;
80 
81 public:
82  virtual const node_token & get_token() = 0;
83  virtual void push(input_type v) = 0;
84 };
85 
89 template <typename dest_t>
90 class virtsrc_impl : public virtsrc<typename dest_t::item_type> {
91 public:
92  typedef typename dest_t::item_type item_type;
93 
94 private:
95  typedef typename maybe_add_const_ref<item_type>::type input_type;
96  dest_t dest;
97 
98 public:
99  virtsrc_impl(const dest_t & dest)
100  : dest(dest)
101  {
103  this->set_name("Virtual source", PRIORITY_INSIGNIFICANT);
104  }
105 
106  const node_token & get_token() {
107  return node::get_token();
108  }
109 
110  void push(input_type v) {
111  dest.push(v);
112  }
113 };
114 
120 template <typename Output>
121 class virtrecv : public node {
122  virtrecv *& m_self;
123  virtsrc<Output> * m_virtdest;
124 
125 public:
126  typedef Output item_type;
127 
128  virtrecv(virtrecv *& self)
129  : m_self(self)
130  , m_virtdest(0)
131  {
132  m_self = this;
133  set_name("Virtual destination", PRIORITY_INSIGNIFICANT);
134  }
135 
136  virtrecv(const virtrecv & other)
137  : node(other)
138  , m_self(other.m_self)
139  , m_virtdest(other.m_virtdest)
140  {
141  m_self = this;
142  }
143 
144  void begin() {
145  node::begin();
146  if (m_virtdest == 0) {
147  throw tpie::exception("No virtual destination");
148  }
149  }
150 
151  void push(typename maybe_add_const_ref<Output>::type v) {
152  m_virtdest->push(v);
153  }
154 
155  void set_destination(virtsrc<Output> * dest) {
156  if (m_virtdest != 0) {
157  throw tpie::exception("Virtual destination set twice");
158  }
159 
160  m_virtdest = dest;
161  add_push_destination(dest->get_token());
162  }
163 };
164 
175 class virt_node {
176 public:
177  typedef boost::shared_ptr<virt_node> ptr;
178 
179 private:
180  std::auto_ptr<node> m_pipeSegment;
181  std::auto_ptr<virtual_container> m_container;
182  ptr m_left;
183  ptr m_right;
184 
185 public:
189  static ptr take_own(node * pipe) {
190  virt_node * n = new virt_node();
191  n->m_pipeSegment.reset(pipe);
192  ptr res(n);
193  return res;
194  }
195 
199  static ptr combine(ptr left, ptr right) {
200  virt_node * n = new virt_node();
201  n->m_left = left;
202  n->m_right = right;
203  ptr res(n);
204  return res;
205  }
206 
212  m_container.reset(ctr);
213  }
214 };
215 
221 template <typename T, typename U, typename Result>
223  static Result go(...) {
225  }
226 };
227 
233 template <typename T, typename Result>
234 struct assert_types_equal_and_return<T, T, Result> {
235  static Result go(Result r) {
236  return r;
237  }
238 };
239 
244  // pipeline_base has virtual dtor and shared_ptr to m_segmap
245 protected:
246  virt_node::ptr m_node;
247 public:
248  virtual_chunk_base() {}
249 
250  virt_node::ptr get_node() const { return m_node; }
251  virtual_chunk_base(node_map::ptr segmap, virt_node::ptr ptr)
252  : m_node(ptr)
253  {
254  this->m_segmap = segmap;
255  }
256 
257  virtual_chunk_base(node_map::ptr segmap) {
258  this->m_segmap = segmap;
259  }
260 
261  void set_container(virtual_container * ctr) {
262  m_node->set_container(ctr);
263  }
264 
265  operator bool() { return m_node; }
266 };
267 
268 } // namespace bits
269 
270 // Predeclare
271 template <typename Input>
273 
274 // Predeclare
275 template <typename Input, typename Output>
277 
278 // Predeclare
279 template <typename Output>
281 
282 namespace bits {
283 
284 class access {
285  template <typename>
286  friend class pipelining::virtual_chunk_end;
287  template <typename, typename>
288  friend class pipelining::virtual_chunk;
289  template <typename>
290  friend class pipelining::virtual_chunk_begin;
291 
292  template <typename Input>
293  static virtsrc<Input> * get_source(const virtual_chunk_end<Input> &);
294  template <typename Input, typename Output>
295  static virtsrc<Input> * get_source(const virtual_chunk<Input, Output> &);
296  template <typename Input, typename Output>
297  static virtrecv<Output> * get_destination(const virtual_chunk<Input, Output> &);
298  template <typename Output>
299  static virtrecv<Output> * get_destination(const virtual_chunk_begin<Output> &);
300 };
301 
302 } // namespace bits
303 
307 template <typename Input>
309  friend class bits::access;
310  typedef bits::access acc;
311  typedef bits::virtsrc<Input> src_type;
312  src_type * m_src;
313 
314  src_type * get_source() const { return m_src; }
315 
316 public:
321  : m_src(0)
322  {}
323 
328  template <typename fact_t>
330  *this = pipe;
331  set_container(ctr);
332  }
333 
339  template <typename Mid>
341  const virtual_chunk_end<Mid> & right);
342 
346  template <typename fact_t>
348  if (this->m_node) {
349  log_error() << "Virtual chunk assigned twice" << std::endl;
350  throw tpie::exception("Virtual chunk assigned twice");
351  }
352 
353  typedef typename fact_t::constructed_type constructed_type;
354  m_src = new bits::virtsrc_impl<constructed_type>(pipe.factory.construct());
355  this->m_node = bits::virt_node::take_own(m_src);
356  this->m_segmap = m_src->get_node_map();
357 
358  return *this;
359  }
360 };
361 
365 template <typename Input, typename Output=Input>
366 class virtual_chunk : public bits::virtual_chunk_base {
367  friend class bits::access;
368  typedef bits::access acc;
369  typedef bits::virtsrc<Input> src_type;
370  typedef bits::virtrecv<Output> recv_type;
371  src_type * m_src;
372  recv_type * m_recv;
373  src_type * get_source() const { return m_src; }
374  recv_type * get_destination() const { return m_recv; }
375 
376 public:
381  : m_src(0)
382  , m_recv(0)
383  {}
384 
389  template <typename fact_t>
391  *this = pipe;
392  set_container(ctr);
393  }
394 
400  template <typename Mid>
402  const virtual_chunk<Mid, Output> & right)
403  : virtual_chunk_base(left.get_node_map(), bits::virt_node::combine(left.get_node(), right.get_node()))
404  {
405  m_src = acc::get_source(left);
406  m_recv = acc::get_destination(right);
407  }
408 
412  template <typename fact_t>
414  if (this->m_node) {
415  log_error() << "Virtual chunk assigned twice" << std::endl;
416  throw tpie::exception("Virtual chunk assigned twice");
417  }
418  typedef typename fact_t::template constructed<recv_type>::type constructed_type;
419  recv_type temp(m_recv);
420  m_src = new bits::virtsrc_impl<constructed_type>(pipe.factory.construct(temp));
421  this->m_node = bits::virt_node::take_own(m_src);
422  this->m_segmap = temp.get_node_map();
423 
424  return *this;
425  }
426 
430  template <typename NextOutput>
432  if (!*this) {
434  ::go(&dest);
435  }
436  m_recv->set_destination(acc::get_source(dest));
437  return virtual_chunk<Input, NextOutput>(*this, dest);
438  }
439 
444  if (!*this) {
446  ::go(&dest);
447  }
448  m_recv->set_destination(acc::get_source(dest));
449  return virtual_chunk_end<Input>(*this, dest);
450  }
451 };
452 
453 template <typename Input>
454 template <typename Mid>
456  const virtual_chunk_end<Mid> & right)
457  : virtual_chunk_base(left.get_node_map(),
458  bits::virt_node::combine(left.get_node(), right.get_node()))
459 {
460  m_src = acc::get_source(left);
461 }
462 
466 template <typename Output>
468  friend class bits::access;
469  typedef bits::access acc;
470  typedef bits::virtrecv<Output> recv_type;
471  recv_type * m_recv;
472  recv_type * get_destination() const { return m_recv; }
473 
474 public:
479  : m_recv(0)
480  {}
481 
486  template <typename fact_t>
488  *this = pipe;
489  set_container(ctr);
490  }
491 
497  template <typename Mid>
499  const virtual_chunk<Mid, Output> & right)
500  : virtual_chunk_base(left.get_node_map(),
501  bits::virt_node::combine(left.get_node(), right.get_node()))
502  {
503  m_recv = acc::get_destination(right);
504  }
505 
509  template <typename fact_t>
511  if (this->m_node) {
512  log_error() << "Virtual chunk assigned twice" << std::endl;
513  throw tpie::exception("Virtual chunk assigned twice");
514  }
515  typedef typename fact_t::template constructed<recv_type>::type constructed_type;
516  recv_type temp(m_recv);
517  this->m_node = bits::virt_node::take_own(new constructed_type(pipe.factory.construct(temp)));
518  this->m_segmap = m_recv->get_node_map();
519  return *this;
520  }
521 
525  template <typename NextOutput>
527  if (!*this) throw virtual_chunk_missing_begin();
528  if (!dest) {
530  ::go(this);
531  }
532  m_recv->set_destination(acc::get_source(dest));
533  return virtual_chunk_begin<NextOutput>(*this, dest);
534  }
535 
539  virtual_chunk_base operator|(virtual_chunk_end<Output> dest) {
540  if (!*this) throw virtual_chunk_missing_begin();
541  if (!dest) throw virtual_chunk_missing_end();
542  m_recv->set_destination(acc::get_source(dest));
543  return virtual_chunk_base(this->m_segmap,
544  bits::virt_node::combine(get_node(), dest.get_node()));
545  }
546 };
547 
548 namespace bits {
549 
550 template <typename Input>
551 virtsrc<Input> * access::get_source(const virtual_chunk_end<Input> & chunk) {
552  return chunk.get_source();
553 }
554 
555 template <typename Input, typename Output>
556 virtsrc<Input> * access::get_source(const virtual_chunk<Input, Output> & chunk) {
557  return chunk.get_source();
558 }
559 
560 template <typename Input, typename Output>
561 virtrecv<Output> * access::get_destination(const virtual_chunk<Input, Output> & chunk) {
562  return chunk.get_destination();
563 }
564 
565 template <typename Output>
566 virtrecv<Output> * access::get_destination(const virtual_chunk_begin<Output> & chunk) {
567  return chunk.get_destination();
568 }
569 
570 } // namespace bits
571 
572 } // namespace pipelining
573 
574 } // namespace tpie
575 
576 #endif // __TPIE_PIPELINING_VIRTUAL_H__
virtual void begin()
Begin pipeline processing phase.
Definition: node.h:167
virtual_chunk< Input, NextOutput > operator|(virtual_chunk< Output, NextOutput > dest)
Connect this virtual chunk to another chunk.
Definition: virtual.h:431
virtual_chunk()
Constructor that leaves the virtual chunk unassigned.
Definition: virtual.h:380
virtual_chunk_begin< NextOutput > operator|(virtual_chunk< Output, NextOutput > dest)
Connect this virtual chunk to another chunk.
Definition: virtual.h:526
void begin()
Begin pipeline processing phase.
Definition: virtual.h:144
virtual_chunk(const pipe_middle< fact_t > &pipe, virtual_container *ctr=0)
Constructor that recursively constructs a node and takes ownership of it.
Definition: virtual.h:390
bits::node_map::ptr get_node_map() const
Get the local node map, mapping node IDs to node pointers for all the nodes reachable from this one...
Definition: node.h:119
Virtual node that is injected into the end of a virtual chunk.
Definition: virtual.h:121
Base class of virtual chunks. Owns a virt_node.
Definition: virtual.h:243
static ptr combine(ptr left, ptr right)
Aggregate ownership of virt_nodes.
Definition: virtual.h:199
Base class of all nodes.
Definition: node.h:58
void add_push_destination(const node_token &dest)
Called by implementers to declare a push destination.
Definition: node.h:352
Virtual chunk that has no output (that is, virtual consumer).
Definition: virtual.h:272
const node_token & get_token()
Get the node_token that maps this node's ID to a pointer to this.
Definition: node.h:558
Virtual superclass for pipelines implementing the function call operator.
Definition: pipeline.h:39
virtual_chunk_begin()
Constructor that leaves the virtual chunk unassigned.
Definition: virtual.h:478
Virtual base class for extra data to go with virtual chunks.
Definition: virtual.h:36
void set_name(const std::string &name, priority_type priority=PRIORITY_USER)
Set this node's name.
Definition: node.h:241
Virtual chunk that has no input (that is, virtual producer).
Definition: virtual.h:280
The maybe_add_const_ref helper struct adds const & to a type unless the type is already const...
Definition: virtual.h:48
static ptr take_own(node *pipe)
Take std::new-ownership of given node.
Definition: virtual.h:189
Ownership of nodes.
Definition: virtual.h:175
Helper class that throws an exception on behalf of virtual_chunks that have not been assigned a pipe_...
Definition: virtual.h:222
void set_container(virtual_container *ctr)
Set and/or reset the virtual_container assigned to this virtual node.
Definition: virtual.h:211
virtual_chunk_end()
Constructor that leaves the virtual chunk unassigned.
Definition: virtual.h:320
A pipe_middle class pushes input down the pipeline.
Definition: pipe_base.h:119
Virtual base node that is injected into the beginning of a virtual chunk.
Definition: virtual.h:78
virtual_chunk_begin(const virtual_chunk_begin< Mid > &left, const virtual_chunk< Mid, Output > &right)
Constructor that combines two virtual chunks.
Definition: virtual.h:498
node()
Default constructor, using a new node_token.
Definition: node.h:296
virtual_chunk_end & operator=(const pipe_end< fact_t > &pipe)
Construct a node and assign it to this virtual chunk.
Definition: virtual.h:347
virtual_chunk_end< Input > operator|(virtual_chunk_end< Output > dest)
Connect this virtual chunk to another chunk.
Definition: virtual.h:443
Concrete implementation of virtsrc.
Definition: virtual.h:90
logstream & log_error()
Return logstream for writing error log messages.
Definition: tpie_log.h:104
virtual_chunk(const virtual_chunk< Input, Mid > &left, const virtual_chunk< Mid, Output > &right)
Constructor that combines two virtual chunks.
Definition: virtual.h:401
Virtual chunk that has input and output.
Definition: virtual.h:276
virtual_chunk_base operator|(virtual_chunk_end< Output > dest)
Connect this virtual chunk to another chunk.
Definition: virtual.h:539
virtual_chunk & operator=(const pipe_middle< fact_t > &pipe)
Construct a node and assign it to this virtual chunk.
Definition: virtual.h:413
virtual_chunk_begin & operator=(const pipe_begin< fact_t > &pipe)
Construct a node and assign it to this virtual chunk.
Definition: virtual.h:510
virtual_chunk_begin(const pipe_begin< fact_t > &pipe, virtual_container *ctr=0)
Constructor that recursively constructs a node and takes ownership of it.
Definition: virtual.h:487
virtual_chunk_end(const pipe_end< fact_t > &pipe, virtual_container *ctr=0)
Constructor that recursively constructs a node and takes ownership of it.
Definition: virtual.h:329