TPIE

11a2c2d
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::pipelining::bits {
30 
31 template <typename child_t>
33 public:
35  : m_maps(new node_map::ptr[2])
36  , m_final(false)
37  {
38  }
39 
40  pair_factory_base(const pair_factory_base & other)= delete;
42  using std::swap;
43  m_final = other.m_final;
44  swap(m_maps, other.m_maps);
45  }
46 
47  pair_factory_base & operator=(const pair_factory_base & other) = delete;
48  pair_factory_base & operator=(pair_factory_base && other) {
49  using std::swap;
50  m_final = other.m_final;
51  swap(m_maps, other.m_maps);
52  }
53 
54  double memory() const noexcept {
55  return self().fact1.memory() + self().fact2.memory();
56  }
57 
58  void name(const std::string & n, priority_type) {
59  push_breadcrumb(n);
60  }
61 
62  void push_breadcrumb(const std::string & n) {
63  self().fact1.push_breadcrumb(n);
64  self().fact2.push_breadcrumb(n);
65  }
66 
71  self().hook_initialization_impl(hook);
72  }
73 
78  template <typename pipe_t>
79  pipe_t record(size_t idx, pipe_t && pipe) const {
80  m_maps[idx] = pipe.get_node_map();
81  if (idx == 0 && m_final) {
82  // Now is the opportunity to check that the constructed pipeline is
83  // connected.
84  assert_connected();
85  self().recursive_connected_check();
86  }
87  return std::move(pipe);
88  }
89 
90  void assert_connected() const {
91  if (m_maps[0]->find_authority() != m_maps[1]->find_authority()) {
92  log_error() << "Node map disconnected - more information in debug log"
93  << " (" << typeid(child_t).name() << ")" << std::endl;
94  log_debug()
95  << "Note about node implementations.\n\n"
96  "In a node constructor that accepts a destination node,\n"
97  "a relation should always be established between the current node\n"
98  "and the destination using one of the member functions add_push_destination,\n"
99  "add_pull_source and add_dependency.\n\n"
100  "If this relational graph is not connected, some nodes will not\n"
101  "be initialized: prepare(), begin(), end() and other methods will never\n"
102  "be called, and memory will not be assigned.\n"
103  "---------------------------------------------------------------------------" << std::endl;
104  throw tpie::exception("Node map disconnected - did you forget to add_push_destination?");
105  }
106  }
107 
112  child_t & finalize() {
113  m_final = true;
114  return self();
115  }
116 
120  void set_destination_kind_push() {
121  self().fact2.set_destination_kind_push();
122  }
123 
127  void set_destination_kind_pull() {
128  self().fact1.set_destination_kind_pull();
129  }
130 
131 private:
132  child_t & self() {return *static_cast<child_t*>(this);}
133  const child_t & self() const {return *static_cast<const child_t*>(this);}
134 
135  boost::scoped_array<node_map::ptr> m_maps;
136  bool m_final;
137 };
138 
143 template <typename fact_t>
145 
146 template <typename fact1_t, typename fact2_t>
147 class pair_factory : public pair_factory_base<pair_factory<fact1_t, fact2_t> > {
148 public:
149  template <typename dest_t>
150  using constructed_type = typename fact1_t::template constructed_type<typename fact2_t::template constructed_type<dest_t>>;
151 
152  pair_factory(const pair_factory &) = delete;
153  pair_factory(pair_factory &&) = default;
154  pair_factory & operator=(const pair_factory &) = delete;
155  pair_factory & operator=(pair_factory &&) = default;
156 
157  pair_factory(fact1_t && fact1, fact2_t && fact2)
158  : fact1(std::move(fact1)), fact2(std::move(fact2)) {
159  }
160 
161  template <typename dest_t>
162  constructed_type<dest_t> construct(dest_t && dest) {
163  return this->record(0, fact1.construct(this->record(1, fact2.construct(std::forward<dest_t>(dest)))));
164  }
165 
166  template <typename dest_t>
167  constructed_type<dest_t> construct_copy(dest_t && dest) {
168  return this->record(0, fact1.construct_copy(this->record(1, fact2.construct_copy(std::forward<dest_t>(dest)))));
169  }
170 
171  void recursive_connected_check() const {
174  }
175 
176  void hook_initialization_impl(factory_init_hook * hook) {
177  fact1.hook_initialization(hook);
178  fact2.hook_initialization(hook);
179  }
180 
181  fact1_t fact1;
182  fact2_t fact2;
183 };
184 
185 template <typename fact1_t, typename termfact2_t>
186 class termpair_factory : public pair_factory_base<termpair_factory<fact1_t, termfact2_t> > {
187 public:
188  using constructed_type = typename fact1_t::template constructed_type<typename termfact2_t::constructed_type>;
189 
190  termpair_factory(const termpair_factory &) = delete;
191  termpair_factory(termpair_factory &&) = default;
192  termpair_factory & operator=(const termpair_factory &) = delete;
193  termpair_factory & operator=(termpair_factory &&) = default;
194 
195  termpair_factory(fact1_t && fact1, termfact2_t && fact2)
196  : fact1(std::move(fact1))
197  , fact2(std::move(fact2))
198  {
199  }
200 
201  fact1_t fact1;
202  termfact2_t fact2;
203 
204  constructed_type construct() {
205  return this->record(0, fact1.construct(this->record(1, fact2.construct())));
206  }
207 
208  constructed_type construct_copy() {
209  return this->record(0, fact1.construct_copy(this->record(1, fact2.construct_copy())));
210  }
211 
212  void recursive_connected_check() const {
215  }
216 
217  void hook_initialization_impl(factory_init_hook * hook) {
218  fact1.hook_initialization(hook);
219  fact2.hook_initialization(hook);
220  }
221 };
222 
227 template <typename fact1_t, typename fact2_t>
228 struct maybe_check_connected<pair_factory<fact1_t, fact2_t> > {
229  static void check(const pair_factory<fact1_t, fact2_t> & fact) {
230  fact.assert_connected();
231  }
232 };
233 
237 template <typename fact1_t, typename termfact2_t>
238 struct maybe_check_connected<termpair_factory<fact1_t, termfact2_t> > {
239  static void check(const termpair_factory<fact1_t, termfact2_t> & fact) {
240  fact.assert_connected();
241  }
242 };
243 
248 template <typename fact_t>
249 struct maybe_check_connected {
250  static void check(const fact_t & /*fact*/) {
251  }
252 };
253 
254 } // namespace tpie::pipelining::bits
255 
256 #endif // __TPIE_PIPELINING_PAIR_FACTORY_H__
tpie::pipelining::bits::termpair_factory
Definition: pair_factory.h:186
types.h
tpie::pipelining::bits::pair_factory_base
Definition: pair_factory.h:32
tpie::log_error
logstream & log_error()
Return logstream for writing error log messages.
Definition: tpie_log.h:148
tpie::pipelining::bits::pair_factory_base::finalize
child_t & finalize()
Signal that this factory is used to instantiate a pipeline_impl, i.e.
Definition: pair_factory.h:112
tpie::exception
Definition: exception.h:33
tpie::log_debug
logstream & log_debug()
Return logstream for writing debug log messages.
Definition: tpie_log.h:168
tpie::pipelining::bits::pair_factory_base::record
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:79
tpie_log.h
tpie::pipelining::bits::maybe_check_connected
Contains a method check that calls recursive_connected_check when fact_t is a pair factory,...
Definition: pair_factory.h:144
tpie::pipelining::bits::pair_factory
Definition: pair_factory.h:147
tpie::pipelining::bits::pair_factory_base::hook_initialization
void hook_initialization(factory_init_hook *hook)
See factory_base::hook_initialization.
Definition: pair_factory.h:70
tpie::pipelining::factory_init_hook
Definition: factory_base.h:34