BRE12
_flow_graph_indexer_impl.h
1 /*
2  Copyright 2005-2016 Intel Corporation. All Rights Reserved.
3 
4  This file is part of Threading Building Blocks. Threading Building Blocks is free software;
5  you can redistribute it and/or modify it under the terms of the GNU General Public License
6  version 2 as published by the Free Software Foundation. Threading Building Blocks is
7  distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
8  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9  See the GNU General Public License for more details. You should have received a copy of
10  the GNU General Public License along with Threading Building Blocks; if not, write to the
11  Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12 
13  As a special exception, you may use this file as part of a free software library without
14  restriction. Specifically, if other files instantiate templates or use macros or inline
15  functions from this file, or you compile this file and link it with other files to produce
16  an executable, this file does not by itself cause the resulting executable to be covered
17  by the GNU General Public License. This exception does not however invalidate any other
18  reasons why the executable file might be covered by the GNU General Public License.
19 */
20 
21 #ifndef __TBB__flow_graph_indexer_impl_H
22 #define __TBB__flow_graph_indexer_impl_H
23 
24 #ifndef __TBB_flow_graph_H
25 #error Do not #include this internal file directly; use public TBB headers instead.
26 #endif
27 
28 #include "tbb/internal/_flow_graph_types_impl.h"
29 
30 namespace internal {
31 
32  // Output of the indexer_node is a tbb::flow::tagged_msg, and will be of
33  // the form tagged_msg<tag, result>
34  // where the value of tag will indicate which result was put to the
35  // successor.
36 
37  template<typename IndexerNodeBaseType, typename T, size_t K>
38  task* do_try_put(const T &v, void *p) {
39  typename IndexerNodeBaseType::output_type o(K, v);
40  return reinterpret_cast<IndexerNodeBaseType *>(p)->try_put_task(&o);
41  }
42 
43  template<typename TupleTypes,int N>
44  struct indexer_helper {
45  template<typename IndexerNodeBaseType, typename PortTuple>
46  static inline void set_indexer_node_pointer(PortTuple &my_input, IndexerNodeBaseType *p) {
47  typedef typename tuple_element<N-1, TupleTypes>::type T;
48  task *(*indexer_node_put_task)(const T&, void *) = do_try_put<IndexerNodeBaseType, T, N-1>;
49  tbb::flow::get<N-1>(my_input).set_up(p, indexer_node_put_task);
50  indexer_helper<TupleTypes,N-1>::template set_indexer_node_pointer<IndexerNodeBaseType,PortTuple>(my_input, p);
51  }
52  template<typename InputTuple>
53  static inline void reset_inputs(InputTuple &my_input, reset_flags f) {
55  tbb::flow::get<N-1>(my_input).reset_receiver(f);
56  }
57 #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
58  template<typename InputTuple>
59  static inline void extract(InputTuple &my_input) {
61  tbb::flow::get<N-1>(my_input).extract_receiver();
62  }
63 #endif
64  };
65 
66  template<typename TupleTypes>
67  struct indexer_helper<TupleTypes,1> {
68  template<typename IndexerNodeBaseType, typename PortTuple>
69  static inline void set_indexer_node_pointer(PortTuple &my_input, IndexerNodeBaseType *p) {
70  typedef typename tuple_element<0, TupleTypes>::type T;
71  task *(*indexer_node_put_task)(const T&, void *) = do_try_put<IndexerNodeBaseType, T, 0>;
72  tbb::flow::get<0>(my_input).set_up(p, indexer_node_put_task);
73  }
74  template<typename InputTuple>
75  static inline void reset_inputs(InputTuple &my_input, reset_flags f) {
76  tbb::flow::get<0>(my_input).reset_receiver(f);
77  }
78 #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
79  template<typename InputTuple>
80  static inline void extract(InputTuple &my_input) {
81  tbb::flow::get<0>(my_input).extract_receiver();
82  }
83 #endif
84  };
85 
86  template<typename T>
87  class indexer_input_port : public receiver<T> {
88  private:
89  void* my_indexer_ptr;
90  typedef task* (* forward_function_ptr)(T const &, void* );
91  forward_function_ptr my_try_put_task;
92 #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
93  spin_mutex my_pred_mutex;
94  typedef typename receiver<T>::built_predecessors_type built_predecessors_type;
95  built_predecessors_type my_built_predecessors;
96 #endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */
97  public:
98 #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
99  indexer_input_port() : my_pred_mutex() {}
100  indexer_input_port( const indexer_input_port & /*other*/ ) : receiver<T>(), my_pred_mutex() {
101  }
102 #endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */
103  void set_up(void *p, forward_function_ptr f) {
104  my_indexer_ptr = p;
105  my_try_put_task = f;
106  }
107 #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
108  typedef typename receiver<T>::predecessor_list_type predecessor_list_type;
109  typedef typename receiver<T>::predecessor_type predecessor_type;
110 
111  /*override*/ built_predecessors_type &built_predecessors() { return my_built_predecessors; }
112 
113  /*override*/size_t predecessor_count() {
114  spin_mutex::scoped_lock l(my_pred_mutex);
115  return my_built_predecessors.edge_count();
116  }
117  /*override*/void internal_add_built_predecessor(predecessor_type &p) {
118  spin_mutex::scoped_lock l(my_pred_mutex);
119  my_built_predecessors.add_edge(p);
120  }
121  /*override*/void internal_delete_built_predecessor(predecessor_type &p) {
122  spin_mutex::scoped_lock l(my_pred_mutex);
123  my_built_predecessors.delete_edge(p);
124  }
125  /*override*/void copy_predecessors( predecessor_list_type &v) {
126  spin_mutex::scoped_lock l(my_pred_mutex);
127  return my_built_predecessors.copy_edges(v);
128  }
129  /*override*/void clear_predecessors() {
130  spin_mutex::scoped_lock l(my_pred_mutex);
131  my_built_predecessors.clear();
132  }
133 #endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */
134  protected:
135  template< typename R, typename B > friend class run_and_put_task;
136  template<typename X, typename Y> friend class internal::broadcast_cache;
137  template<typename X, typename Y> friend class internal::round_robin_cache;
138  task *try_put_task(const T &v) {
139  return my_try_put_task(v, my_indexer_ptr);
140  }
141 
142  public:
143 #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
144  /*override*/void reset_receiver(reset_flags f) { if(f&rf_clear_edges) my_built_predecessors.clear(); }
145 #else
146  /*override*/void reset_receiver(reset_flags /*f*/) { }
147 #endif
148 
149 #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
150  void extract_receiver() { my_built_predecessors.receiver_extract(*this); }
151 #endif
152  };
153 
154  template<typename InputTuple, typename OutputType, typename StructTypes>
156  public:
157  static const int N = tbb::flow::tuple_size<InputTuple>::value;
158  typedef OutputType output_type;
159  typedef InputTuple input_type;
160 
161  // Some versions of Intel C++ compiler fail to generate an implicit constructor for the class which has std::tuple as a member.
162  indexer_node_FE() : my_inputs() {}
163 
164  input_type &input_ports() { return my_inputs; }
165  protected:
166  input_type my_inputs;
167  };
168 
170  template<typename InputTuple, typename OutputType, typename StructTypes>
171  class indexer_node_base : public graph_node, public indexer_node_FE<InputTuple, OutputType,StructTypes>,
172  public sender<OutputType> {
173  protected:
174  using graph_node::my_graph;
175  public:
176  static const size_t N = tbb::flow::tuple_size<InputTuple>::value;
177  typedef OutputType output_type;
178  typedef StructTypes tuple_types;
179  typedef typename sender<output_type>::successor_type successor_type;
181 #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
182  typedef typename sender<output_type>::built_successors_type built_successors_type;
183  typedef typename sender<output_type>::successor_list_type successor_list_type;
184 #endif
185 
186  private:
187  // ----------- Aggregator ------------
188  enum op_type { reg_succ, rem_succ, try__put_task
189 #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
190  , add_blt_succ, del_blt_succ,
191  blt_succ_cnt, blt_succ_cpy
192 #endif
193  };
194  enum op_stat {WAIT=0, SUCCEEDED, FAILED};
196 
197  class indexer_node_base_operation : public aggregated_operation<indexer_node_base_operation> {
198  public:
199  char type;
200  union {
201  output_type const *my_arg;
202  successor_type *my_succ;
203  task *bypass_t;
204 #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
205  size_t cnt_val;
206  successor_list_type *succv;
207 #endif
208  };
209  indexer_node_base_operation(const output_type* e, op_type t) :
210  type(char(t)), my_arg(e) {}
211  indexer_node_base_operation(const successor_type &s, op_type t) : type(char(t)),
212  my_succ(const_cast<successor_type *>(&s)) {}
213  indexer_node_base_operation(op_type t) : type(char(t)) {}
214  };
215 
216  typedef internal::aggregating_functor<class_type, indexer_node_base_operation> handler_type;
217  friend class internal::aggregating_functor<class_type, indexer_node_base_operation>;
218  aggregator<handler_type, indexer_node_base_operation> my_aggregator;
219 
220  void handle_operations(indexer_node_base_operation* op_list) {
221  indexer_node_base_operation *current;
222  while(op_list) {
223  current = op_list;
224  op_list = op_list->next;
225  switch(current->type) {
226 
227  case reg_succ:
228  my_successors.register_successor(*(current->my_succ));
229  __TBB_store_with_release(current->status, SUCCEEDED);
230  break;
231 
232  case rem_succ:
233  my_successors.remove_successor(*(current->my_succ));
234  __TBB_store_with_release(current->status, SUCCEEDED);
235  break;
236  case try__put_task: {
237  current->bypass_t = my_successors.try_put_task(*(current->my_arg));
238  __TBB_store_with_release(current->status, SUCCEEDED); // return of try_put_task actual return value
239  }
240  break;
241 #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
242  case add_blt_succ:
243  my_successors.internal_add_built_successor(*(current->my_succ));
244  __TBB_store_with_release(current->status, SUCCEEDED);
245  break;
246  case del_blt_succ:
247  my_successors.internal_delete_built_successor(*(current->my_succ));
248  __TBB_store_with_release(current->status, SUCCEEDED);
249  break;
250  case blt_succ_cnt:
251  current->cnt_val = my_successors.successor_count();
252  __TBB_store_with_release(current->status, SUCCEEDED);
253  break;
254  case blt_succ_cpy:
255  my_successors.copy_successors(*(current->succv));
256  __TBB_store_with_release(current->status, SUCCEEDED);
257  break;
258 #endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */
259  }
260  }
261  }
262  // ---------- end aggregator -----------
263  public:
264  indexer_node_base(graph& g) : graph_node(g), input_ports_type() {
266  my_successors.set_owner(this);
267  my_aggregator.initialize_handler(handler_type(this));
268  }
269 
270  indexer_node_base(const indexer_node_base& other) : graph_node(other.my_graph), input_ports_type(), sender<output_type>() {
272  my_successors.set_owner(this);
273  my_aggregator.initialize_handler(handler_type(this));
274  }
275 
276  bool register_successor(successor_type &r) {
277  indexer_node_base_operation op_data(r, reg_succ);
278  my_aggregator.execute(&op_data);
279  return op_data.status == SUCCEEDED;
280  }
281 
282  bool remove_successor( successor_type &r) {
283  indexer_node_base_operation op_data(r, rem_succ);
284  my_aggregator.execute(&op_data);
285  return op_data.status == SUCCEEDED;
286  }
287 
288  task * try_put_task(output_type const *v) {
289  indexer_node_base_operation op_data(v, try__put_task);
290  my_aggregator.execute(&op_data);
291  return op_data.bypass_t;
292  }
293 
294 #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
295 
296  built_successors_type &built_successors() { return my_successors.built_successors(); }
297 
298  void internal_add_built_successor( successor_type &r) {
299  indexer_node_base_operation op_data(r, add_blt_succ);
300  my_aggregator.execute(&op_data);
301  }
302 
303  void internal_delete_built_successor( successor_type &r) {
304  indexer_node_base_operation op_data(r, del_blt_succ);
305  my_aggregator.execute(&op_data);
306  }
307 
308  size_t successor_count() {
309  indexer_node_base_operation op_data(blt_succ_cnt);
310  my_aggregator.execute(&op_data);
311  return op_data.cnt_val;
312  }
313 
314  void copy_successors( successor_list_type &v) {
315  indexer_node_base_operation op_data(blt_succ_cpy);
316  op_data.succv = &v;
317  my_aggregator.execute(&op_data);
318  }
319  void extract() {
320  my_successors.built_successors().sender_extract(*this);
322  }
323 #endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */
324  protected:
325  /*override*/void reset_node(reset_flags f) {
326  if(f & rf_clear_edges) {
327  my_successors.clear();
329  }
330  }
331 
332  private:
334  }; //indexer_node_base
335 
336 
337  template<int N, typename InputTuple> struct input_types;
338 
339  template<typename InputTuple>
340  struct input_types<1, InputTuple> {
341  typedef typename tuple_element<0, InputTuple>::type first_type;
343  };
344 
345  template<typename InputTuple>
346  struct input_types<2, InputTuple> {
347  typedef typename tuple_element<0, InputTuple>::type first_type;
348  typedef typename tuple_element<1, InputTuple>::type second_type;
350  };
351 
352  template<typename InputTuple>
353  struct input_types<3, InputTuple> {
354  typedef typename tuple_element<0, InputTuple>::type first_type;
355  typedef typename tuple_element<1, InputTuple>::type second_type;
356  typedef typename tuple_element<2, InputTuple>::type third_type;
358  };
359 
360  template<typename InputTuple>
361  struct input_types<4, InputTuple> {
362  typedef typename tuple_element<0, InputTuple>::type first_type;
363  typedef typename tuple_element<1, InputTuple>::type second_type;
364  typedef typename tuple_element<2, InputTuple>::type third_type;
365  typedef typename tuple_element<3, InputTuple>::type fourth_type;
366  typedef typename internal::tagged_msg<size_t, first_type, second_type, third_type,
367  fourth_type> type;
368  };
369 
370  template<typename InputTuple>
371  struct input_types<5, InputTuple> {
372  typedef typename tuple_element<0, InputTuple>::type first_type;
373  typedef typename tuple_element<1, InputTuple>::type second_type;
374  typedef typename tuple_element<2, InputTuple>::type third_type;
375  typedef typename tuple_element<3, InputTuple>::type fourth_type;
376  typedef typename tuple_element<4, InputTuple>::type fifth_type;
377  typedef typename internal::tagged_msg<size_t, first_type, second_type, third_type,
378  fourth_type, fifth_type> type;
379  };
380 
381  template<typename InputTuple>
382  struct input_types<6, InputTuple> {
383  typedef typename tuple_element<0, InputTuple>::type first_type;
384  typedef typename tuple_element<1, InputTuple>::type second_type;
385  typedef typename tuple_element<2, InputTuple>::type third_type;
386  typedef typename tuple_element<3, InputTuple>::type fourth_type;
387  typedef typename tuple_element<4, InputTuple>::type fifth_type;
388  typedef typename tuple_element<5, InputTuple>::type sixth_type;
389  typedef typename internal::tagged_msg<size_t, first_type, second_type, third_type,
390  fourth_type, fifth_type, sixth_type> type;
391  };
392 
393  template<typename InputTuple>
394  struct input_types<7, InputTuple> {
395  typedef typename tuple_element<0, InputTuple>::type first_type;
396  typedef typename tuple_element<1, InputTuple>::type second_type;
397  typedef typename tuple_element<2, InputTuple>::type third_type;
398  typedef typename tuple_element<3, InputTuple>::type fourth_type;
399  typedef typename tuple_element<4, InputTuple>::type fifth_type;
400  typedef typename tuple_element<5, InputTuple>::type sixth_type;
401  typedef typename tuple_element<6, InputTuple>::type seventh_type;
402  typedef typename internal::tagged_msg<size_t, first_type, second_type, third_type,
403  fourth_type, fifth_type, sixth_type,
404  seventh_type> type;
405  };
406 
407 
408  template<typename InputTuple>
409  struct input_types<8, InputTuple> {
410  typedef typename tuple_element<0, InputTuple>::type first_type;
411  typedef typename tuple_element<1, InputTuple>::type second_type;
412  typedef typename tuple_element<2, InputTuple>::type third_type;
413  typedef typename tuple_element<3, InputTuple>::type fourth_type;
414  typedef typename tuple_element<4, InputTuple>::type fifth_type;
415  typedef typename tuple_element<5, InputTuple>::type sixth_type;
416  typedef typename tuple_element<6, InputTuple>::type seventh_type;
417  typedef typename tuple_element<7, InputTuple>::type eighth_type;
418  typedef typename internal::tagged_msg<size_t, first_type, second_type, third_type,
419  fourth_type, fifth_type, sixth_type,
420  seventh_type, eighth_type> type;
421  };
422 
423 
424  template<typename InputTuple>
425  struct input_types<9, InputTuple> {
426  typedef typename tuple_element<0, InputTuple>::type first_type;
427  typedef typename tuple_element<1, InputTuple>::type second_type;
428  typedef typename tuple_element<2, InputTuple>::type third_type;
429  typedef typename tuple_element<3, InputTuple>::type fourth_type;
430  typedef typename tuple_element<4, InputTuple>::type fifth_type;
431  typedef typename tuple_element<5, InputTuple>::type sixth_type;
432  typedef typename tuple_element<6, InputTuple>::type seventh_type;
433  typedef typename tuple_element<7, InputTuple>::type eighth_type;
434  typedef typename tuple_element<8, InputTuple>::type nineth_type;
435  typedef typename internal::tagged_msg<size_t, first_type, second_type, third_type,
436  fourth_type, fifth_type, sixth_type,
437  seventh_type, eighth_type, nineth_type> type;
438  };
439 
440  template<typename InputTuple>
441  struct input_types<10, InputTuple> {
442  typedef typename tuple_element<0, InputTuple>::type first_type;
443  typedef typename tuple_element<1, InputTuple>::type second_type;
444  typedef typename tuple_element<2, InputTuple>::type third_type;
445  typedef typename tuple_element<3, InputTuple>::type fourth_type;
446  typedef typename tuple_element<4, InputTuple>::type fifth_type;
447  typedef typename tuple_element<5, InputTuple>::type sixth_type;
448  typedef typename tuple_element<6, InputTuple>::type seventh_type;
449  typedef typename tuple_element<7, InputTuple>::type eighth_type;
450  typedef typename tuple_element<8, InputTuple>::type nineth_type;
451  typedef typename tuple_element<9, InputTuple>::type tenth_type;
452  typedef typename internal::tagged_msg<size_t, first_type, second_type, third_type,
453  fourth_type, fifth_type, sixth_type,
454  seventh_type, eighth_type, nineth_type,
455  tenth_type> type;
456  };
457 
458  // type generators
459  template<typename OutputTuple>
460  struct indexer_types : public input_types<tuple_size<OutputTuple>::value, OutputTuple> {
461  static const int N = tbb::flow::tuple_size<OutputTuple>::value;
462  typedef typename input_types<N, OutputTuple>::type output_type;
463  typedef typename wrap_tuple_elements<N,indexer_input_port,OutputTuple>::type input_ports_type;
466  };
467 
468  template<class OutputTuple>
469  class unfolded_indexer_node : public indexer_types<OutputTuple>::indexer_base_type {
470  public:
471  typedef typename indexer_types<OutputTuple>::input_ports_type input_ports_type;
472  typedef OutputTuple tuple_types;
473  typedef typename indexer_types<OutputTuple>::output_type output_type;
474  private:
476  public:
477  unfolded_indexer_node(graph& g) : base_type(g) {}
478  unfolded_indexer_node(const unfolded_indexer_node &other) : base_type(other) {}
479  };
480 
481 } /* namespace internal */
482 
483 #endif /* __TBB__flow_graph_indexer_impl_H */
Definition: _flow_graph_indexer_impl.h:44
A cache of successors that are put in a round-robin fashion.
Definition: _flow_graph_impl.h:796
A cache of successors that are broadcast to.
Definition: _flow_graph_impl.h:751
Definition: _flow_graph_indexer_impl.h:469
Definition: _flow_graph_indexer_impl.h:87
Definition: _flow_graph_types_impl.h:602
Definition: _flow_graph_async_msg_impl.h:32
Definition: _flow_graph_indexer_impl.h:155
Definition: _flow_graph_indexer_impl.h:337
Definition: _flow_graph_indexer_impl.h:460
Definition: _flow_graph_types_impl.h:53
indexer_node_base
Definition: _flow_graph_indexer_impl.h:171