TPIE

2362a60
pipe_base.h
1 // -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*-
2 // vi:set ts=4 sts=4 sw=4 noet :
3 // Copyright 2011, 2012, 2013, 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 
20 #ifndef __TPIE_PIPELINING_PIPE_BASE_H__
21 #define __TPIE_PIPELINING_PIPE_BASE_H__
22 
23 #include <tpie/types.h>
24 #include <tpie/pipelining/priority_type.h>
25 #include <tpie/pipelining/pair_factory.h>
26 #include <tpie/pipelining/pipeline.h>
27 #include <tpie/pipelining/node_set.h>
28 
29 #ifdef WIN32
30 // Silence warning C4521: multiple copy constructors specified.
31 // This warning is emitted since we declare both
32 // pipe_middle(const pipe_middle &) and
33 // pipe_middle(pipe_middle &).
34 // However, both of these are necessary to ensure that copying takes
35 // preference over the template <T> pipe_middle(T) constructor.
36 #pragma warning(push)
37 #pragma warning(disable: 4521)
38 #endif
39 
40 namespace tpie {
41 
42 namespace pipelining {
43 
44 namespace bits {
45 
46 template <typename child_t>
47 class pipe_base {
48 public:
49  pipe_base() = default;
50  pipe_base(pipe_base & other) = delete;
51  pipe_base(pipe_base && other) = default;
52  pipe_base & operator=(pipe_base & other) = delete;
53  pipe_base & operator=(pipe_base && other) = default;
54 
65  child_t memory(double amount) {
66  self().factory.memory(amount);
67  return std::move(self());
68  }
69 
76  inline double memory() const {
77  return self().factory.memory();
78  }
79 
92  child_t name(const std::string & n, priority_type p = PRIORITY_USER) {
93  self().factory.name(n, p);
94  return std::move(self());
95  }
96 
104  child_t phase_name(const std::string & n, priority_type p = PRIORITY_USER) {
105  self().factory.phase_name(n, p);
106  return std::move(self());
107  }
108 
109 
117  child_t add_to_set(node_set s) {
118  self().factory.add_to_set(s);
119  return std::move(self());
120  }
121 
127  child_t add_dependencies(node_set s) {
128  self().factory.add_dependencies(s);
129  return std::move(self());
130  }
131 
137  child_t add_forwarding_dependencies(node_set s) {
138  self().factory.add_forwarding_dependencies(s);
139  return std::move(self());
140  }
141 
149  child_t breadcrumb(const std::string & n) {
150  self().factory.push_breadcrumb(n);
151  return std::move(self());
152  }
153 
154  child_t forward_any(const std::string & key, any_noncopyable value) {
155  self().factory.forward(key, std::move(value));
156  return std::move(self());
157  }
158 
159  template <typename T>
160  child_t forward(const std::string & key, T value) {
161  return forward_any(key, any_noncopyable(value));
162  }
163 
164 protected:
165  inline child_t & self() {return *static_cast<child_t*>(this);}
166  inline const child_t & self() const {return *static_cast<const child_t*>(this);}
167 };
168 
169 // The derived class has to pass its factory type to us as a template argument.
170 // See the following Stack Overflow question, dated Nov 13, 2011, for a discussion.
171 // http://stackoverflow.com/q/8113878
172 // At the time this class is instantiated, child_t is not yet complete.
173 // This means we cannot use child_t::factory_type as an existing type name.
174 template <typename child_t, typename fact_t>
175 class pipe_term_base : public pipe_base<child_t> {
176 public:
177  typedef typename fact_t::constructed_type constructed_type;
178 
179  constructed_type construct() {
180  return this->self().factory.construct();
181  }
182 };
183 
184 // For this class, we only use child_t::factory_type inside
185 // a templated member type, so at the time of its instantiation,
186 // child_t is complete and child_t::factory_type is valid.
187 template <typename child_t>
188 class pipe_nonterm_base : public pipe_base<child_t> {
189 public:
190  pipe_nonterm_base() = default;
191  pipe_nonterm_base(const pipe_nonterm_base &) = delete;
192  pipe_nonterm_base(pipe_nonterm_base &&) = default;
193  pipe_nonterm_base & operator=(const pipe_nonterm_base &) = delete;
194  pipe_nonterm_base & operator=(pipe_nonterm_base &&) = default;
195 
196  template <typename dest_t>
197  struct constructed {
198  typedef typename child_t::factory_type::template constructed<dest_t>::type type;
199  };
200 
201  template <typename dest_t>
202  typename constructed<dest_t>::type construct(const dest_t & dest) {
203  return this->self().factory.construct(dest);
204  }
205 };
206 
207 } // namespace bits
208 
209 template <typename fact_t>
210 class pipe_end : public bits::pipe_term_base<pipe_end<fact_t>, fact_t> {
211 public:
212  typedef fact_t factory_type;
213 
223  template <typename ... T_ARGS>
224  inline pipe_end(T_ARGS && ... t) : factory(std::forward<T_ARGS>(t)...) {}
225 
226  fact_t factory;
227 };
228 
229 
230 class empty_pipe_middle;
231 
240 template <typename fact_t>
241 class pipe_middle : public bits::pipe_nonterm_base<pipe_middle<fact_t> > {
242 public:
243  typedef fact_t factory_type;
244 
245  pipe_middle(const pipe_middle &) = delete;
246  pipe_middle(pipe_middle &&) = default;
247  pipe_middle & operator=(const pipe_middle &) = delete;
248  pipe_middle & operator=(pipe_middle &&) = default;
249 
250  pipe_middle(const fact_t && o) = delete;
251  pipe_middle(fact_t && o): factory(std::move(o)) {}
252  pipe_middle & operator=(const fact_t &) = delete;
253  pipe_middle & operator=(fact_t && o) {factory = std::move(o);}
254 
255 
256 
268  template <typename ... T_ARGS>
269  pipe_middle(T_ARGS && ... t) : factory(std::forward<T_ARGS>(t)...) {}
270 
274  template <typename fact2_t>
278  return bits::pair_factory<fact_t, fact2_t>(std::move(factory), std::move(r.factory));
279  }
280 
285 
290  template <typename fact2_t>
294  return bits::termpair_factory<fact_t, fact2_t>(std::move(factory), std::move(r.factory));
295  }
296 
297  fact_t factory;
298 };
299 
305 class empty_pipe_middle : public bits::pipe_nonterm_base<empty_pipe_middle> {
306 public:
307  empty_pipe_middle() = default;
308  empty_pipe_middle(const empty_pipe_middle &) = delete;
309  empty_pipe_middle(empty_pipe_middle &&) = default;
310  empty_pipe_middle & operator=(const empty_pipe_middle &) = delete;
311  empty_pipe_middle & operator=(empty_pipe_middle &&) = default;
312 
316  template <typename fact_t>
317  pipe_middle<fact_t> operator|(pipe_middle<fact_t> && r) const {return std::move(r);}
318 
323  template <typename fact_t>
324  pipe_end<fact_t> operator|(pipe_end<fact_t> && r) const {return std::move(r);}
325 };
326 
327 
328 template <typename fact_t>
329 class pipe_begin : public bits::pipe_nonterm_base<pipe_begin<fact_t> > {
330 public:
331  pipe_begin(const pipe_begin<fact_t> &) = default;
332  pipe_begin(pipe_begin<fact_t> &&) = default;
333  pipe_begin & operator=(const pipe_begin<fact_t> &) = delete;
334  pipe_begin & operator=(pipe_begin<fact_t> &&) = default;
335 
336  pipe_begin(fact_t && f): factory(std::move(f)) {}
337 
338  typedef fact_t factory_type;
339 
340  //pipe_begin(fact_t && f) : factory(std::move(f)) {};
341 
353  // template <typename T1, typename ... T_ARGS, typename = typename std::enable_if<!std::is_same<pipe_begin, T1>::value, T1>::type>
354  // explicit inline pipe_begin(T1 && t1, T_ARGS && ... t) : factory(std::forward(t1), std::forward<T_ARGS>(t)...) {}
355 
356  template <typename ... T_ARGS>
357  pipe_begin(T_ARGS && ... t) : factory(std::forward<T_ARGS>(t)...) {}
358 
359 
360  template <typename fact2_t>
362  operator|(pipe_middle<fact2_t> && r) {
364  return bits::pair_factory<fact_t, fact2_t>(std::move(factory), std::move(r.factory));
365  }
366 
367  pipe_begin operator|(empty_pipe_middle &&) {return pipe_begin(std::move(factory));}
368 
369  template <typename fact2_t>
370  bits::pipeline_impl<bits::termpair_factory<fact_t, fact2_t> >
371  operator|(pipe_end<fact2_t> && r) {
372  factory.set_destination_kind_push();
373  return bits::termpair_factory<fact_t, fact2_t>(std::move(factory), std::move(r.factory)).finalize();
374  }
375 
376  fact_t factory;
377 };
378 
379 template <typename fact_t>
380 class pullpipe_end : public bits::pipe_nonterm_base<pullpipe_end<fact_t> > {
381 public:
382  typedef fact_t factory_type;
383 
395  template <typename ... T_ARGS>
396  inline pullpipe_end(T_ARGS && ... t) : factory(std::forward<T_ARGS>(t)...) {}
397 
398  fact_t factory;
399 };
400 
401 template <typename fact_t>
402 class pullpipe_middle : public bits::pipe_nonterm_base<pullpipe_middle<fact_t> > {
403 public:
404  typedef fact_t factory_type;
405 
417  template <typename ... T_ARGS>
418  inline pullpipe_middle(T_ARGS && ... t) : factory(std::forward<T_ARGS>(t)...) {}
419 
420  template <typename fact2_t>
422  operator|(pipe_middle<fact2_t> && r) {
423  fact2_t f = std::move(r.factory);
424  f.set_destination_kind_pull();
425  return bits::pair_factory<fact2_t, fact_t>(std::move(f), std::move(factory));
426  }
427 
428  template <typename fact2_t>
429  pullpipe_end<bits::termpair_factory<fact2_t, fact_t> >
430  operator|(pipe_end<fact2_t> && r) {
431  fact2_t f = std::move(r.factory);
432  f.set_destination_kind_pull();
433  return bits::termpair_factory<fact2_t, fact_t>(std::move(f), std::move(factory));
434  }
435 
436  fact_t factory;
437 };
438 
439 template <typename fact_t>
440 class pullpipe_begin : public bits::pipe_term_base<pullpipe_begin<fact_t>, fact_t> {
441 public:
442  typedef fact_t factory_type;
443 
455  template <typename ... T_ARGS>
456  inline pullpipe_begin(T_ARGS && ... t) : factory(std::forward<T_ARGS>(t)...) {}
457 
458  template <typename fact2_t>
460  operator|(pullpipe_middle<fact2_t> && r) {
461  fact2_t f = std::move(r.factory);
462  f.set_destination_kind_pull();
463  return bits::termpair_factory<fact2_t, fact_t>(std::move(f), std::move(factory));
464  }
465 
466  template <typename fact2_t>
467  bits::pipeline_impl<bits::termpair_factory<fact2_t, fact_t> >
468  operator|(pullpipe_end<fact2_t> && r) {
469  fact2_t f = std::move(r.factory);
470  f.set_destination_kind_pull();
471  return bits::termpair_factory<fact2_t, fact_t>(std::move(f), std::move(factory)).finalize();
472  }
473 
474  fact_t factory;
475 };
476 
477 } // namespace pipelining
478 
479 } // namespace tpie
480 
481 #ifdef WIN32
482 #pragma warning(pop)
483 #endif
484 
485 #endif // __TPIE_PIPELINING_PIPE_BASE_H__
void set_destination_kind_push()
Used by pipe_base classes to indicate that the default actor edge is a push edge. ...
Definition: factory_base.h:273
pullpipe_middle(T_ARGS &&...t)
Forwards the arguments given to the constructor of the factory.
Definition: pipe_base.h:418
double memory() const
Get memory fraction for this node in the pipeline phase.
Definition: pipe_base.h:76
void memory(double amount)
Set memory fraction for this node in the pipeline phase.
Definition: factory_base.h:89
Typesafe bitflags.
child_t memory(double amount)
Set memory fraction for this node in the pipeline phase.
Definition: pipe_base.h:65
A empty_pipe_middle class has no effect.
Definition: pipe_base.h:305
void phase_name(const std::string &n, priority_type p)
Set name for this phase.
Definition: factory_base.h:252
pipe_end< bits::termpair_factory< fact_t, fact2_t > > operator|(pipe_end< fact2_t > &&r)
This pipe operator combines this generator/filter with a terminator to make a pipeline.
Definition: pipe_base.h:292
pipe_end< fact_t > operator|(pipe_end< fact_t > &&r) const
This pipe operator combines this generator/filter with a terminator to make a pipeline.
Definition: pipe_base.h:324
child_t name(const std::string &n, priority_type p=PRIORITY_USER)
Set name for this node.
Definition: pipe_base.h:92
pipe_middle< fact_t > operator|(pipe_middle< fact_t > &&r) const
The pipe operator combines this generator/filter with another filter.
Definition: pipe_base.h:317
pipe_end(T_ARGS &&...t)
Forwards the arguments given to the constructor of the factory.
Definition: pipe_base.h:224
pullpipe_begin(T_ARGS &&...t)
Forwards the arguments given to the constructor of the factory.
Definition: pipe_base.h:456
child_t add_forwarding_dependencies(node_set s)
Add a forwarding dependency to a referenced node.
Definition: pipe_base.h:137
pipe_middle< bits::pair_factory< fact_t, fact2_t > > operator|(pipe_middle< fact2_t > &&r)
The pipe operator combines this generator/filter with another filter.
Definition: pipe_base.h:276
void name(const std::string &n, priority_type p)
Set name for this node.
Definition: factory_base.h:241
pipe_middle operator|(empty_pipe_middle &&)
The pipe operator combines this generator/filter with another filter.
Definition: pipe_base.h:284
child_t phase_name(const std::string &n, priority_type p=PRIORITY_USER)
Set name for this phase.
Definition: pipe_base.h:104
child_t add_dependencies(node_set s)
Add a depencency to a referenced node.
Definition: pipe_base.h:127
child_t breadcrumb(const std::string &n)
Set a prefix for the name of this node.
Definition: pipe_base.h:149
pipe_middle(T_ARGS &&...t)
Forwards the arguments given to the constructor of the factory.
Definition: pipe_base.h:269
pipe_begin(T_ARGS &&...t)
Forwards the arguments given to the constructor of the factory.
Definition: pipe_base.h:357
Node factory for variadic argument generators.
child_t add_to_set(node_set s)
Get a refenerce to this node.
Definition: pipe_base.h:117
A pipe_middle class pushes input down the pipeline.
Definition: pipe_base.h:241
pullpipe_end(T_ARGS &&...t)
Forwards the arguments given to the constructor of the factory.
Definition: pipe_base.h:396
void push_breadcrumb(const std::string &n)
Set a prefix for the name of this node.
Definition: factory_base.h:264