2 Copyright 2005-2011 Intel Corporation. All Rights Reserved.
4 This file is part of Threading Building Blocks.
6 Threading Building Blocks is free software; you can redistribute it
7 and/or modify it under the terms of the GNU General Public License
8 version 2 as published by the Free Software Foundation.
10 Threading Building Blocks is distributed in the hope that it will be
11 useful, but WITHOUT ANY WARRANTY; without even the implied warranty
12 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with Threading Building Blocks; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 As a special exception, you may use this file as part of a free software
20 library without restriction. Specifically, if other files instantiate
21 templates or use macros or inline functions from this file, or you compile
22 this file and link it with other files to produce an executable, this
23 file does not by itself cause the resulting executable to be covered by
24 the GNU General Public License. This exception does not however
25 invalidate any other reasons why the executable file might be covered by
26 the GNU General Public License.
29 #ifndef __TBB__flow_graph_or_impl_H
30 #define __TBB__flow_graph_or_impl_H
34 // Output of the or_node is a struct containing a union, and will be of
47 // where the value of indx will indicate which result was put to the
48 // successor. indx == 0 => result0 and so on.
50 // The order of the items in the union is determined by the tuple that
51 // defines the input port types (the same way a join_node's inputs are
52 // defined.) So the union ordering corresponds to the ordering of the
53 // input ports of the node.
55 // the types of each element of the union are represented by tuple_types,
56 // a typedef in the or_node. So the 2nd type in the union that is the
57 // output type for an or_node OrType is
59 // std::tuple_element<1,OrType::tuple_types>::type
61 template<int N, typename OutputTuple>
62 struct or_output_type;
64 template<typename OutputTuple>
65 struct or_output_type<2, OutputTuple> {
66 typedef OutputTuple tuple_types;
70 typename std::tuple_element<0,OutputTuple>::type result0;
71 typename std::tuple_element<1,OutputTuple>::type result1;
76 template<typename OutputTuple>
77 struct or_output_type<3, OutputTuple> {
79 typedef OutputTuple tuple_types;
82 typename std::tuple_element<0,OutputTuple>::type result0;
83 typename std::tuple_element<1,OutputTuple>::type result1;
84 typename std::tuple_element<2,OutputTuple>::type result2;
89 template<typename OutputTuple>
90 struct or_output_type<4, OutputTuple> {
92 typedef OutputTuple tuple_types;
95 typename std::tuple_element<0,OutputTuple>::type result0;
96 typename std::tuple_element<1,OutputTuple>::type result1;
97 typename std::tuple_element<2,OutputTuple>::type result2;
98 typename std::tuple_element<3,OutputTuple>::type result3;
103 template<typename OutputTuple>
104 struct or_output_type<5, OutputTuple> {
106 typedef OutputTuple tuple_types;
109 typename std::tuple_element<0,OutputTuple>::type result0;
110 typename std::tuple_element<1,OutputTuple>::type result1;
111 typename std::tuple_element<2,OutputTuple>::type result2;
112 typename std::tuple_element<3,OutputTuple>::type result3;
113 typename std::tuple_element<4,OutputTuple>::type result4;
118 template<typename OutputTuple>
119 struct or_output_type<6, OutputTuple> {
121 typedef OutputTuple tuple_types;
124 typename std::tuple_element<0,OutputTuple>::type result0;
125 typename std::tuple_element<1,OutputTuple>::type result1;
126 typename std::tuple_element<2,OutputTuple>::type result2;
127 typename std::tuple_element<3,OutputTuple>::type result3;
128 typename std::tuple_element<4,OutputTuple>::type result4;
129 typename std::tuple_element<5,OutputTuple>::type result5;
134 template<typename OutputTuple>
135 struct or_output_type<7, OutputTuple> {
137 typedef OutputTuple tuple_types;
140 typename std::tuple_element<0,OutputTuple>::type result0;
141 typename std::tuple_element<1,OutputTuple>::type result1;
142 typename std::tuple_element<2,OutputTuple>::type result2;
143 typename std::tuple_element<3,OutputTuple>::type result3;
144 typename std::tuple_element<4,OutputTuple>::type result4;
145 typename std::tuple_element<5,OutputTuple>::type result5;
146 typename std::tuple_element<6,OutputTuple>::type result6;
151 template<typename OutputTuple>
152 struct or_output_type<8, OutputTuple> {
154 typedef OutputTuple tuple_types;
157 typename std::tuple_element<0,OutputTuple>::type result0;
158 typename std::tuple_element<1,OutputTuple>::type result1;
159 typename std::tuple_element<2,OutputTuple>::type result2;
160 typename std::tuple_element<3,OutputTuple>::type result3;
161 typename std::tuple_element<4,OutputTuple>::type result4;
162 typename std::tuple_element<5,OutputTuple>::type result5;
163 typename std::tuple_element<6,OutputTuple>::type result6;
164 typename std::tuple_element<7,OutputTuple>::type result7;
169 template<typename OutputTuple>
170 struct or_output_type<9, OutputTuple> {
172 typedef OutputTuple tuple_types;
175 typename std::tuple_element<0,OutputTuple>::type result0;
176 typename std::tuple_element<1,OutputTuple>::type result1;
177 typename std::tuple_element<2,OutputTuple>::type result2;
178 typename std::tuple_element<3,OutputTuple>::type result3;
179 typename std::tuple_element<4,OutputTuple>::type result4;
180 typename std::tuple_element<5,OutputTuple>::type result5;
181 typename std::tuple_element<6,OutputTuple>::type result6;
182 typename std::tuple_element<7,OutputTuple>::type result7;
183 typename std::tuple_element<8,OutputTuple>::type result8;
188 template<typename OutputTuple>
189 struct or_output_type<10, OutputTuple> {
191 typedef OutputTuple tuple_types;
194 typename std::tuple_element<0,OutputTuple>::type result0;
195 typename std::tuple_element<1,OutputTuple>::type result1;
196 typename std::tuple_element<2,OutputTuple>::type result2;
197 typename std::tuple_element<3,OutputTuple>::type result3;
198 typename std::tuple_element<4,OutputTuple>::type result4;
199 typename std::tuple_element<5,OutputTuple>::type result5;
200 typename std::tuple_element<6,OutputTuple>::type result6;
201 typename std::tuple_element<7,OutputTuple>::type result7;
202 typename std::tuple_element<8,OutputTuple>::type result8;
203 typename std::tuple_element<9,OutputTuple>::type result9;
208 template<typename TupleTypes, int N>
209 struct or_item_helper;
211 // or_item_helper takes 0-9 as its template parameter
212 template<typename TupleTypes>
213 struct or_item_helper<TupleTypes,0> {
214 template<typename OutputType>
215 static inline void create_output_value(OutputType &o, void *v) {
217 o.result0 = *(reinterpret_cast<typename std::tuple_element<0,TupleTypes>::type *>(v));
221 template<typename TupleTypes>
222 struct or_item_helper<TupleTypes,1> {
223 template<typename OutputType>
224 static inline void create_output_value(OutputType &o, void *v) {
226 o.result1 = *(reinterpret_cast<typename std::tuple_element<1,TupleTypes>::type *>(v));
230 template<typename TupleTypes>
231 struct or_item_helper<TupleTypes,2> {
232 template<typename OutputType>
233 static inline void create_output_value(OutputType &o, void *v) {
235 o.result2 = *(reinterpret_cast<typename std::tuple_element<2,TupleTypes>::type *>(v));
239 template<typename TupleTypes>
240 struct or_item_helper<TupleTypes,3> {
241 template<typename OutputType>
242 static inline void create_output_value(OutputType &o, void *v) {
244 o.result3 = *(reinterpret_cast<typename std::tuple_element<3,TupleTypes>::type *>(v));
248 template<typename TupleTypes>
249 struct or_item_helper<TupleTypes,4> {
250 template<typename OutputType>
251 static inline void create_output_value(OutputType &o, void *v) {
253 o.result4 = *(reinterpret_cast<typename std::tuple_element<4,TupleTypes>::type *>(v));
257 template<typename TupleTypes>
258 struct or_item_helper<TupleTypes,5> {
259 template<typename OutputType>
260 static inline void create_output_value(OutputType &o, void *v) {
262 o.result5 = *(reinterpret_cast<typename std::tuple_element<5,TupleTypes>::type *>(v));
266 template<typename TupleTypes>
267 struct or_item_helper<TupleTypes,6> {
268 template<typename OutputType>
269 static inline void create_output_value(OutputType &o, void *v) {
271 o.result6 = *(reinterpret_cast<typename std::tuple_element<6,TupleTypes>::type *>(v));
275 template<typename TupleTypes>
276 struct or_item_helper<TupleTypes,7> {
277 template<typename OutputType>
278 static inline void create_output_value(OutputType &o, void *v) {
280 o.result7 = *(reinterpret_cast<typename std::tuple_element<7,TupleTypes>::type *>(v));
284 template<typename TupleTypes>
285 struct or_item_helper<TupleTypes,8> {
286 template<typename OutputType>
287 static inline void create_output_value(OutputType &o, void *v) {
289 o.result8 = *(reinterpret_cast<typename std::tuple_element<8,TupleTypes>::type *>(v));
293 template<typename TupleTypes>
294 struct or_item_helper<TupleTypes,9> {
295 template<typename OutputType>
296 static inline void create_output_value(OutputType &o, void *v) {
298 o.result9 = *(reinterpret_cast<typename std::tuple_element<9,TupleTypes>::type *>(v));
302 template<typename TupleTypes,int N>
304 template<typename OutputType>
305 static inline void create_output(OutputType &o, size_t i, void* v) {
307 or_item_helper<TupleTypes,N-1>::create_output_value(o,v);
310 or_helper<TupleTypes,N-1>::create_output(o,i,v);
312 template<typename PortTuple, typename PutBase>
313 static inline void set_or_node_pointer(PortTuple &my_input, PutBase *p) {
314 std::get<N-1>(my_input).set_up(p, N-1);
315 or_helper<TupleTypes,N-1>::set_or_node_pointer(my_input, p);
319 template<typename TupleTypes>
320 struct or_helper<TupleTypes,1> {
321 template<typename OutputType>
322 static inline void create_output(OutputType &o, size_t i, void* v) {
324 or_item_helper<TupleTypes,0>::create_output_value(o,v);
327 template<typename PortTuple, typename PutBase>
328 static inline void set_or_node_pointer(PortTuple &my_input, PutBase *p) {
329 std::get<0>(my_input).set_up(p, 0);
334 virtual bool try_put_with_index(size_t index, void *v) = 0;
335 virtual ~put_base() { }
339 class or_input_port : public receiver<T> {
342 put_base *my_or_node;
344 void set_up(put_base *p, size_t i) { my_index = i; my_or_node = p; }
345 bool try_put(const T &v) {
346 return my_or_node->try_put_with_index(my_index, reinterpret_cast<void *>(const_cast<T*>(&v)));
350 template<size_t N, typename OutputTuple>
351 struct or_input_type;
353 template<typename OutputTuple>
354 struct or_input_type<2,OutputTuple> {
355 typedef typename std::tuple<
356 or_input_port<typename std::tuple_element<0,OutputTuple>::type>,
357 or_input_port<typename std::tuple_element<1,OutputTuple>::type>
361 template<typename OutputTuple>
362 struct or_input_type<3,OutputTuple> {
363 typedef typename std::tuple<
364 or_input_port<typename std::tuple_element<0,OutputTuple>::type>,
365 or_input_port<typename std::tuple_element<1,OutputTuple>::type>,
366 or_input_port<typename std::tuple_element<2,OutputTuple>::type>
370 template<typename OutputTuple>
371 struct or_input_type<4,OutputTuple> {
372 typedef typename std::tuple<
373 or_input_port<typename std::tuple_element<0,OutputTuple>::type>,
374 or_input_port<typename std::tuple_element<1,OutputTuple>::type>,
375 or_input_port<typename std::tuple_element<2,OutputTuple>::type>,
376 or_input_port<typename std::tuple_element<3,OutputTuple>::type>
380 template<typename OutputTuple>
381 struct or_input_type<5,OutputTuple> {
382 typedef typename std::tuple<
383 or_input_port<typename std::tuple_element<0,OutputTuple>::type>,
384 or_input_port<typename std::tuple_element<1,OutputTuple>::type>,
385 or_input_port<typename std::tuple_element<2,OutputTuple>::type>,
386 or_input_port<typename std::tuple_element<3,OutputTuple>::type>,
387 or_input_port<typename std::tuple_element<4,OutputTuple>::type>
391 template<typename OutputTuple>
392 struct or_input_type<6,OutputTuple> {
393 typedef typename std::tuple<
394 or_input_port<typename std::tuple_element<0,OutputTuple>::type>,
395 or_input_port<typename std::tuple_element<1,OutputTuple>::type>,
396 or_input_port<typename std::tuple_element<2,OutputTuple>::type>,
397 or_input_port<typename std::tuple_element<3,OutputTuple>::type>,
398 or_input_port<typename std::tuple_element<4,OutputTuple>::type>,
399 or_input_port<typename std::tuple_element<5,OutputTuple>::type>
403 template<typename OutputTuple>
404 struct or_input_type<7,OutputTuple> {
405 typedef typename std::tuple<
406 or_input_port<typename std::tuple_element<0,OutputTuple>::type>,
407 or_input_port<typename std::tuple_element<1,OutputTuple>::type>,
408 or_input_port<typename std::tuple_element<2,OutputTuple>::type>,
409 or_input_port<typename std::tuple_element<3,OutputTuple>::type>,
410 or_input_port<typename std::tuple_element<4,OutputTuple>::type>,
411 or_input_port<typename std::tuple_element<5,OutputTuple>::type>,
412 or_input_port<typename std::tuple_element<6,OutputTuple>::type>
416 template<typename OutputTuple>
417 struct or_input_type<8,OutputTuple> {
418 typedef typename std::tuple<
419 or_input_port<typename std::tuple_element<0,OutputTuple>::type>,
420 or_input_port<typename std::tuple_element<1,OutputTuple>::type>,
421 or_input_port<typename std::tuple_element<2,OutputTuple>::type>,
422 or_input_port<typename std::tuple_element<3,OutputTuple>::type>,
423 or_input_port<typename std::tuple_element<4,OutputTuple>::type>,
424 or_input_port<typename std::tuple_element<5,OutputTuple>::type>,
425 or_input_port<typename std::tuple_element<6,OutputTuple>::type>,
426 or_input_port<typename std::tuple_element<7,OutputTuple>::type>
430 template<typename OutputTuple>
431 struct or_input_type<9,OutputTuple> {
432 typedef typename std::tuple<
433 or_input_port<typename std::tuple_element<0,OutputTuple>::type>,
434 or_input_port<typename std::tuple_element<1,OutputTuple>::type>,
435 or_input_port<typename std::tuple_element<2,OutputTuple>::type>,
436 or_input_port<typename std::tuple_element<3,OutputTuple>::type>,
437 or_input_port<typename std::tuple_element<4,OutputTuple>::type>,
438 or_input_port<typename std::tuple_element<5,OutputTuple>::type>,
439 or_input_port<typename std::tuple_element<6,OutputTuple>::type>,
440 or_input_port<typename std::tuple_element<7,OutputTuple>::type>,
441 or_input_port<typename std::tuple_element<8,OutputTuple>::type>
445 template<typename OutputTuple>
446 struct or_input_type<10,OutputTuple> {
447 typedef typename std::tuple<
448 or_input_port<typename std::tuple_element<0,OutputTuple>::type>,
449 or_input_port<typename std::tuple_element<1,OutputTuple>::type>,
450 or_input_port<typename std::tuple_element<2,OutputTuple>::type>,
451 or_input_port<typename std::tuple_element<3,OutputTuple>::type>,
452 or_input_port<typename std::tuple_element<4,OutputTuple>::type>,
453 or_input_port<typename std::tuple_element<5,OutputTuple>::type>,
454 or_input_port<typename std::tuple_element<6,OutputTuple>::type>,
455 or_input_port<typename std::tuple_element<7,OutputTuple>::type>,
456 or_input_port<typename std::tuple_element<8,OutputTuple>::type>,
457 or_input_port<typename std::tuple_element<9,OutputTuple>::type>
461 template<typename InputTuple, typename OutputType, typename StructTypes>
462 class or_node_FE : public put_base {
464 static const int N = std::tuple_size<InputTuple>::value;
465 typedef OutputType output_type;
466 typedef InputTuple input_type;
469 or_helper<StructTypes,N>::set_or_node_pointer(my_inputs, this);
472 input_type &inputs() { return my_inputs; }
474 input_type my_inputs;
478 template<typename InputTuple, typename OutputType, typename StructTypes>
479 class or_node_base : public graph_node, public or_node_FE<InputTuple, OutputType,StructTypes>,
480 public sender<OutputType> {
482 static const size_t N = std::tuple_size<InputTuple>::value;
483 typedef OutputType output_type;
484 typedef StructTypes tuple_types;
485 typedef receiver<output_type> successor_type;
486 typedef or_node_FE<InputTuple, output_type,StructTypes> input_ports_type;
489 // ----------- Aggregator ------------
490 enum op_type { reg_succ, rem_succ, try__put };
491 enum op_stat {WAIT=0, SUCCEEDED, FAILED};
492 typedef or_node_base<InputTuple,output_type,StructTypes> my_class;
494 class or_node_base_operation : public aggregated_operation<or_node_base_operation> {
500 successor_type *my_succ;
502 or_node_base_operation(size_t i, const void* e, op_type t) :
503 type(char(t)), indx(i), my_arg(const_cast<void *>(e)) {}
504 or_node_base_operation(const successor_type &s, op_type t) : type(char(t)),
505 my_succ(const_cast<successor_type *>(&s)) {}
506 or_node_base_operation(op_type t) : type(char(t)) {}
509 typedef internal::aggregating_functor<my_class, or_node_base_operation> my_handler;
510 friend class internal::aggregating_functor<my_class, or_node_base_operation>;
511 aggregator<my_handler, or_node_base_operation> my_aggregator;
513 void handle_operations(or_node_base_operation* op_list) {
514 or_node_base_operation *current;
517 op_list = op_list->next;
518 switch(current->type) {
521 my_successors.register_successor(*(current->my_succ));
522 __TBB_store_with_release(current->status, SUCCEEDED);
526 my_successors.remove_successor(*(current->my_succ));
527 __TBB_store_with_release(current->status, SUCCEEDED);
532 or_helper<tuple_types,N>::create_output(oval,current->indx,current->my_arg);
533 if(my_successors.try_put(oval)) {
534 __TBB_store_with_release(current->status, SUCCEEDED);
536 else __TBB_store_with_release(current->status, FAILED);
541 // ---------- end aggregator -----------
543 or_node_base( ) : input_ports_type() {
544 my_successors.set_owner(this);
545 my_aggregator.initialize_handler(my_handler(this));
548 or_node_base( const or_node_base& /*other*/) : input_ports_type() {
549 my_successors.set_owner(this);
550 my_aggregator.initialize_handler(my_handler(this));
553 bool register_successor(successor_type &r) {
554 or_node_base_operation op_data(r, reg_succ);
555 my_aggregator.execute(&op_data);
556 return op_data.status == SUCCEEDED;
559 bool remove_successor( successor_type &r) {
560 or_node_base_operation op_data(r, rem_succ);
561 my_aggregator.execute(&op_data);
562 return op_data.status == SUCCEEDED;
565 bool try_put_with_index(size_t indx, void *v) {
566 or_node_base_operation op_data(indx, v, try__put);
567 my_aggregator.execute(&op_data);
568 return op_data.status == SUCCEEDED;
572 broadcast_cache<output_type, null_rw_mutex> my_successors;
576 template<typename OutputTuple>
578 static const int N = std::tuple_size<OutputTuple>::value;
579 typedef typename or_input_type<N,OutputTuple>::type input_ports_tuple_type;
580 typedef typename or_output_type<N, OutputTuple>::type output_type;
581 typedef internal::or_node_FE<input_ports_tuple_type,output_type,OutputTuple> or_FE_type;
582 typedef internal::or_node_base<input_ports_tuple_type, output_type, OutputTuple> or_base_type;
585 //! unfolded_or_node : passes input_ports_tuple_type to or_node_base. We build the input port type
586 // using tuple_element. The class PT is the port type (reserving_port, queueing_port, tag_matching_port)
587 // and should match the graph_buffer_policy.
588 template<typename OutputTuple>
589 class unfolded_or_node;
591 template<class OutputTuple>
592 class unfolded_or_node : public or_types<OutputTuple>::or_base_type {
594 // static const int N = std::tuple_size<OutputTuple>::value;
595 typedef typename or_types<OutputTuple>::input_ports_tuple_type input_ports_tuple_type;
596 typedef OutputTuple tuple_types;
597 typedef typename or_types<OutputTuple>::output_type output_type;
599 typedef typename or_types<OutputTuple>::or_base_type base_type;
601 unfolded_or_node() : base_type() {}
605 } /* namespace internal */
607 #endif /* __TBB__flow_graph_or_impl_H */