TPIE

2362a60
pair_factory.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, 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_PAIR_FACTORY_H__
21 #define __TPIE_PIPELINING_PAIR_FACTORY_H__
22 
23 #include <tpie/types.h>
24 #include <tpie/tpie_log.h>
25 #include <tpie/pipelining/priority_type.h>
26 #include <tpie/pipelining/factory_base.h>
27 #include <boost/scoped_array.hpp>
28 
29 namespace tpie {
30 
31 namespace pipelining {
32 
33 namespace bits {
34 
35 template <typename child_t>
37 public:
39  : m_maps(new node_map::ptr[2])
40  , m_final(false)
41  {
42  }
43 
44  pair_factory_base(const pair_factory_base & other)= delete;
46  using std::swap;
47  m_final = other.m_final;
48  swap(m_maps, other.m_maps);
49  }
50 
51  pair_factory_base & operator=(const pair_factory_base & other) = delete;
52  pair_factory_base & operator=(pair_factory_base && other) {
53  using std::swap;
54  m_final = other.m_final;
55  swap(m_maps, other.m_maps);
56  }
57 
58  inline double memory() const {
59  return self().fact1.memory() + self().fact2.memory();
60  }
61 
62  inline void name(const std::string & n, priority_type) {
63  push_breadcrumb(n);
64  }
65 
66  void push_breadcrumb(const std::string & n) {
67  self().fact1.push_breadcrumb(n);
68  self().fact2.push_breadcrumb(n);
69  }
70 
75  self().hook_initialization_impl(hook);
76  }
77 
82  template <typename pipe_t>
83  pipe_t record(size_t idx, pipe_t && pipe) const {
84  m_maps[idx] = pipe.get_node_map();
85  if (idx == 0 && m_final) {
86  // Now is the opportunity to check that the constructed pipeline is
87  // connected.
88  assert_connected();
89  self().recursive_connected_check();
90  }
91  return std::move(pipe);
92  }
93 
94  void assert_connected() const {
95  if (m_maps[0]->find_authority() != m_maps[1]->find_authority()) {
96  log_error() << "Node map disconnected - more information in debug log"
97  << " (" << typeid(child_t).name() << ")" << std::endl;
98  log_debug()
99  << "Note about node implementations.\n\n"
100  "In a node constructor that accepts a destination node,\n"
101  "a relation should always be established between the current node\n"
102  "and the destination using one of the member functions add_push_destination,\n"
103  "add_pull_source and add_dependency.\n\n"
104  "If this relational graph is not connected, some nodes will not\n"
105  "be initialized: prepare(), begin(), end() and other methods will never\n"
106  "be called, and memory will not be assigned.\n"
107  "---------------------------------------------------------------------------" << std::endl;
108  throw tpie::exception("Node map disconnected - did you forget to add_push_destination?");
109  }
110  }
111 
116  child_t & finalize() {
117  m_final = true;
118  return self();
119  }
120 
124  void set_destination_kind_push() {
125  self().fact2.set_destination_kind_push();
126  }
127 
131  void set_destination_kind_pull() {
132  self().fact1.set_destination_kind_pull();
133  }
134 
135 private:
136  inline child_t & self() {return *static_cast<child_t*>(this);}
137  inline const child_t & self() const {return *static_cast<const child_t*>(this);}
138 
139  boost::scoped_array<node_map::ptr> m_maps;
140  bool m_final;
141 };
142 
147 template <typename fact_t>
149 
150 template <typename fact1_t, typename fact2_t>
151 class pair_factory : public pair_factory_base<pair_factory<fact1_t, fact2_t> > {
152 public:
153  template <typename dest_t>
154  struct constructed {
155  typedef typename fact1_t::template constructed<typename fact2_t::template constructed<dest_t>::type>::type type;
156  };
157 
158  pair_factory(const pair_factory &) = delete;
159  pair_factory(pair_factory &&) = default;
160  pair_factory & operator=(const pair_factory &) = delete;
161  pair_factory & operator=(pair_factory &&) = default;
162 
163  pair_factory(fact1_t && fact1, fact2_t && fact2)
164  : fact1(std::move(fact1)), fact2(std::move(fact2)) {
165  }
166 
167  template <typename dest_t>
168  typename constructed<dest_t>::type
169  construct(dest_t && dest) {
170  return this->record(0, fact1.construct(this->record(1, fact2.construct(std::forward<dest_t>(dest)))));
171  }
172 
173  template <typename dest_t>
174  typename constructed<dest_t>::type
175  construct_copy(dest_t && dest) {
176  return this->record(0, fact1.construct_copy(this->record(1, fact2.construct_copy(std::forward<dest_t>(dest)))));
177  }
178 
179  void recursive_connected_check() const {
180  maybe_check_connected<fact1_t>::check(fact1);
181  maybe_check_connected<fact2_t>::check(fact2);
182  }
183 
184  void hook_initialization_impl(factory_init_hook * hook) {
185  fact1.hook_initialization(hook);
186  fact2.hook_initialization(hook);
187  }
188 
189  fact1_t fact1;
190  fact2_t fact2;
191 };
192 
193 template <typename fact1_t, typename termfact2_t>
194 class termpair_factory : public pair_factory_base<termpair_factory<fact1_t, termfact2_t> > {
195 public:
196  typedef typename fact1_t::template constructed<typename termfact2_t::constructed_type>::type constructed_type;
197 
198 
199 
200  termpair_factory(const termpair_factory &) = delete;
201  termpair_factory(termpair_factory &&) = default;
202  termpair_factory & operator=(const termpair_factory &) = delete;
203  termpair_factory & operator=(termpair_factory &&) = default;
204 
205  termpair_factory(fact1_t && fact1, termfact2_t && fact2)
206  : fact1(std::move(fact1))
207  , fact2(std::move(fact2))
208  {
209  }
210 
211  fact1_t fact1;
212  termfact2_t fact2;
213 
214  constructed_type construct() {
215  return this->record(0, fact1.construct(this->record(1, fact2.construct())));
216  }
217 
218  constructed_type construct_copy() {
219  return this->record(0, fact1.construct_copy(this->record(1, fact2.construct_copy())));
220  }
221 
222  void recursive_connected_check() const {
225  }
226 
227  void hook_initialization_impl(factory_init_hook * hook) {
228  fact1.hook_initialization(hook);
229  fact2.hook_initialization(hook);
230  }
231 };
232 
237 template <typename fact1_t, typename fact2_t>
238 struct maybe_check_connected<pair_factory<fact1_t, fact2_t> > {
239  static void check(const pair_factory<fact1_t, fact2_t> & fact) {
240  fact.assert_connected();
241  }
242 };
243 
247 template <typename fact1_t, typename termfact2_t>
248 struct maybe_check_connected<termpair_factory<fact1_t, termfact2_t> > {
249  static void check(const termpair_factory<fact1_t, termfact2_t> & fact) {
250  fact.assert_connected();
251  }
252 };
253 
258 template <typename fact_t>
259 struct maybe_check_connected {
260  static void check(const fact_t & /*fact*/) {
261  }
262 };
263 
264 } // namespace bits
265 
266 } // namespace pipelining
267 
268 } // namespace tpie
269 
270 #endif // __TPIE_PIPELINING_PAIR_FACTORY_H__
void hook_initialization(factory_init_hook *hook)
See factory_base::hook_initialization.
Definition: pair_factory.h:74
Typesafe bitflags.
pipe_t record(size_t idx, pipe_t &&pipe) const
Internal - used by subclasses to record references to node_maps for a later connectivity check...
Definition: pair_factory.h:83
Logging functionality and log_level codes for different priorities of log messages.
Contains a method check that calls recursive_connected_check when fact_t is a pair factory...
Definition: pair_factory.h:148
child_t & finalize()
Signal that this factory is used to instantiate a pipeline_impl, i.e.
Definition: pair_factory.h:116
logstream & log_debug()
Return logstream for writing debug log messages.
Definition: tpie_log.h:167
logstream & log_error()
Return logstream for writing error log messages.
Definition: tpie_log.h:147