Intel(R) Threading Building Blocks Doxygen Documentation  version 4.2.3
_flow_graph_node_impl.h
Go to the documentation of this file.
1 /*
2  Copyright (c) 2005-2018 Intel Corporation
3 
4  Licensed under the Apache License, Version 2.0 (the "License");
5  you may not use this file except in compliance with the License.
6  You may obtain a copy of the License at
7 
8  http://www.apache.org/licenses/LICENSE-2.0
9 
10  Unless required by applicable law or agreed to in writing, software
11  distributed under the License is distributed on an "AS IS" BASIS,
12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  See the License for the specific language governing permissions and
14  limitations under the License.
15 
16 
17 
18 
19 */
20 
21 #ifndef __TBB__flow_graph_node_impl_H
22 #define __TBB__flow_graph_node_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 
29 
31 namespace internal {
32 
36 
37  template< typename T, typename A >
38  class function_input_queue : public item_buffer<T,A> {
39  public:
40  bool empty() const {
41  return this->buffer_empty();
42  }
43 
44  const T& front() const {
45  return this->item_buffer<T, A>::front();
46  }
47 
48  bool pop( T& t ) {
49  return this->pop_front( t );
50  }
51 
52  void pop() {
53  this->destroy_front();
54  }
55 
56  bool push( T& t ) {
57  return this->push_back( t );
58  }
59  };
60 
62  // The only up-ref is apply_body_impl, which should implement the function
63  // call and any handling of the result.
64  template< typename Input, typename Policy, typename A, typename ImplType >
65  class function_input_base : public receiver<Input>, tbb::internal::no_assign {
67 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
68  , add_blt_pred, del_blt_pred,
69  blt_pred_cnt, blt_pred_cpy // create vector copies of preds and succs
70 #endif
71  };
73 
74  public:
75 
77  typedef Input input_type;
78  typedef typename receiver<input_type>::predecessor_type predecessor_type;
81  typedef typename A::template rebind< input_queue_type >::other queue_allocator_type;
83  "queueing and rejecting policies can't be specified simultaneously");
84 
85 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
86  typedef typename predecessor_cache_type::built_predecessors_type built_predecessors_type;
87  typedef typename receiver<input_type>::predecessor_list_type predecessor_list_type;
88 #endif
89 
93  my_queue(!internal::has_policy<rejecting, Policy>::value ? new input_queue_type() : NULL),
94  forwarder_busy(false)
95  {
97  my_aggregator.initialize_handler(handler_type(this));
98  }
99 
102  receiver<Input>(), tbb::internal::no_assign(),
104  my_concurrency(0), my_queue(src.my_queue ? new input_queue_type() : NULL),
105  forwarder_busy(false)
106  {
108  my_aggregator.initialize_handler(handler_type(this));
109  }
110 
112  // The queue is allocated by the constructor for {multi}function_node.
113  // TODO: pass the graph_buffer_policy to the base so it can allocate the queue instead.
114  // This would be an interface-breaking change.
116  if ( my_queue ) delete my_queue;
117  }
118 
121  }
122 
125  operation_type op_data(reg_pred);
126  op_data.r = &src;
127  my_aggregator.execute(&op_data);
128  return true;
129  }
130 
133  operation_type op_data(rem_pred);
134  op_data.r = &src;
135  my_aggregator.execute(&op_data);
136  return true;
137  }
138 
139 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
140  void internal_add_built_predecessor( predecessor_type &src) __TBB_override {
142  operation_type op_data(add_blt_pred);
143  op_data.r = &src;
144  my_aggregator.execute(&op_data);
145  }
146 
148  void internal_delete_built_predecessor( predecessor_type &src) __TBB_override {
149  operation_type op_data(del_blt_pred);
150  op_data.r = &src;
151  my_aggregator.execute(&op_data);
152  }
153 
154  size_t predecessor_count() __TBB_override {
155  operation_type op_data(blt_pred_cnt);
156  my_aggregator.execute(&op_data);
157  return op_data.cnt_val;
158  }
159 
160  void copy_predecessors(predecessor_list_type &v) __TBB_override {
161  operation_type op_data(blt_pred_cpy);
162  op_data.predv = &v;
163  my_aggregator.execute(&op_data);
164  }
165 
166  built_predecessors_type &built_predecessors() __TBB_override {
167  return my_predecessors.built_predecessors();
168  }
169 #endif /* TBB_DEPRECATED_FLOW_NODE_EXTRACTION */
170 
171  protected:
172 
174  my_concurrency = 0;
175  if(my_queue) {
176  my_queue->reset();
177  }
178  reset_receiver(f);
179  forwarder_busy = false;
180  }
181 
182  graph& my_graph_ref;
183  const size_t my_max_concurrency;
187 
190  else
192  __TBB_ASSERT(!(f & rf_clear_edges) || my_predecessors.empty(), "function_input_base reset failed");
193  }
194 
196  return my_graph_ref;
197  }
198 
200  operation_type op_data(i, app_body_bypass); // tries to pop an item or get_item
201  my_aggregator.execute(&op_data);
202  return op_data.bypass_t;
203  }
204 
205  private:
206 
209 
210  class operation_type : public aggregated_operation< operation_type > {
211  public:
212  char type;
213  union {
216 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
217  size_t cnt_val;
218  predecessor_list_type *predv;
219 #endif /* TBB_DEPRECATED_FLOW_NODE_EXTRACTION */
220  };
223  type(char(t)), elem(const_cast<input_type*>(&e)) {}
224  operation_type(op_type t) : type(char(t)), r(NULL) {}
225  };
226 
228  typedef internal::aggregating_functor<class_type, operation_type> handler_type;
229  friend class internal::aggregating_functor<class_type, operation_type>;
231 
233  task* new_task = NULL;
234  if(my_queue) {
235  if(!my_queue->empty()) {
236  ++my_concurrency;
237  new_task = create_body_task(my_queue->front());
238 
239  my_queue->pop();
240  }
241  }
242  else {
243  input_type i;
244  if(my_predecessors.get_item(i)) {
245  ++my_concurrency;
246  new_task = create_body_task(i);
247  }
248  }
249  return new_task;
250  }
251  void handle_operations(operation_type *op_list) {
252  operation_type *tmp;
253  while (op_list) {
254  tmp = op_list;
255  op_list = op_list->next;
256  switch (tmp->type) {
257  case reg_pred:
258  my_predecessors.add(*(tmp->r));
259  __TBB_store_with_release(tmp->status, SUCCEEDED);
260  if (!forwarder_busy) {
261  forwarder_busy = true;
263  }
264  break;
265  case rem_pred:
266  my_predecessors.remove(*(tmp->r));
267  __TBB_store_with_release(tmp->status, SUCCEEDED);
268  break;
269  case app_body_bypass: {
270  tmp->bypass_t = NULL;
271  __TBB_ASSERT(my_max_concurrency != 0, NULL);
272  --my_concurrency;
274  tmp->bypass_t = perform_queued_requests();
275 
276  __TBB_store_with_release(tmp->status, SUCCEEDED);
277  }
278  break;
279  case tryput_bypass: internal_try_put_task(tmp); break;
280  case try_fwd: internal_forward(tmp); break;
281  case occupy_concurrency:
283  ++my_concurrency;
284  __TBB_store_with_release(tmp->status, SUCCEEDED);
285  } else {
286  __TBB_store_with_release(tmp->status, FAILED);
287  }
288  break;
289 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
290  case add_blt_pred: {
291  my_predecessors.internal_add_built_predecessor(*(tmp->r));
292  __TBB_store_with_release(tmp->status, SUCCEEDED);
293  }
294  break;
295  case del_blt_pred:
296  my_predecessors.internal_delete_built_predecessor(*(tmp->r));
297  __TBB_store_with_release(tmp->status, SUCCEEDED);
298  break;
299  case blt_pred_cnt:
300  tmp->cnt_val = my_predecessors.predecessor_count();
301  __TBB_store_with_release(tmp->status, SUCCEEDED);
302  break;
303  case blt_pred_cpy:
304  my_predecessors.copy_predecessors( *(tmp->predv) );
305  __TBB_store_with_release(tmp->status, SUCCEEDED);
306  break;
307 #endif /* TBB_DEPRECATED_FLOW_NODE_EXTRACTION */
308  }
309  }
310  }
311 
313  void internal_try_put_task(operation_type *op) {
314  __TBB_ASSERT(my_max_concurrency != 0, NULL);
316  ++my_concurrency;
317  task * new_task = create_body_task(*(op->elem));
318  op->bypass_t = new_task;
319  __TBB_store_with_release(op->status, SUCCEEDED);
320  } else if ( my_queue && my_queue->push(*(op->elem)) ) {
321  op->bypass_t = SUCCESSFULLY_ENQUEUED;
322  __TBB_store_with_release(op->status, SUCCEEDED);
323  } else {
324  op->bypass_t = NULL;
325  __TBB_store_with_release(op->status, FAILED);
326  }
327  }
328 
330  void internal_forward(operation_type *op) {
331  op->bypass_t = NULL;
333  op->bypass_t = perform_queued_requests();
334  if(op->bypass_t)
335  __TBB_store_with_release(op->status, SUCCEEDED);
336  else {
337  forwarder_busy = false;
338  __TBB_store_with_release(op->status, FAILED);
339  }
340  }
341 
343  operation_type op_data(t, tryput_bypass);
344  my_aggregator.execute(&op_data);
345  if( op_data.status == internal::SUCCEEDED ) {
346  return op_data.bypass_t;
347  }
348  return NULL;
349  }
350 
352  if( my_max_concurrency == 0 ) {
353  return apply_body_bypass(t);
354  } else {
355  operation_type check_op(t, occupy_concurrency);
356  my_aggregator.execute(&check_op);
357  if( check_op.status == internal::SUCCEEDED ) {
358  return apply_body_bypass(t);
359  }
360  return internal_try_put_bypass(t);
361  }
362  }
363 
365  if( my_max_concurrency == 0 ) {
366  return create_body_task(t);
367  } else {
368  return internal_try_put_bypass(t);
369  }
370  }
371 
373  // then decides if more work is available
375  return static_cast<ImplType *>(this)->apply_body_impl_bypass(i);
376  }
377 
379  inline task * create_body_task( const input_type &input ) {
380 
382  new(task::allocate_additional_child_of(*(my_graph_ref.root_task())))
384  NULL;
385  }
386 
389  operation_type op_data(try_fwd);
390  task *rval = NULL;
391  do {
392  op_data.status = WAIT;
393  my_aggregator.execute(&op_data);
394  if(op_data.status == SUCCEEDED) {
395  // workaround for icc bug
396  tbb::task *ttask = op_data.bypass_t;
397  rval = combine_tasks(my_graph_ref, rval, ttask);
398  }
399  } while (op_data.status == SUCCEEDED);
400  return rval;
401  }
402 
405  new(task::allocate_additional_child_of(*(my_graph_ref.root_task()))) forward_task_bypass< class_type >(*this) :
406  NULL;
407  }
408 
410  inline void spawn_forward_task() {
411  task* tp = create_forward_task();
412  if(tp) {
414  }
415  }
416  }; // function_input_base
417 
419  // a type Output to its successors.
420  template< typename Input, typename Output, typename Policy, typename A>
421  class function_input : public function_input_base<Input, Policy, A, function_input<Input,Output,Policy,A> > {
422  public:
423  typedef Input input_type;
424  typedef Output output_type;
429 
430  // constructor
431  template<typename Body>
432  function_input( graph &g, size_t max_concurrency, Body& body ) :
434  my_body( new internal::function_body_leaf< input_type, output_type, Body>(body) ),
435  my_init_body( new internal::function_body_leaf< input_type, output_type, Body>(body) ) {
436  }
437 
440  base_type(src),
441  my_body( src.my_init_body->clone() ),
442  my_init_body(src.my_init_body->clone() ) {
443  }
444 
446  delete my_body;
447  delete my_init_body;
448  }
449 
450  template< typename Body >
452  function_body_type &body_ref = *this->my_body;
453  return dynamic_cast< internal::function_body_leaf<input_type, output_type, Body> & >(body_ref).get_body();
454  }
455 
457  // There is an extra copied needed to capture the
458  // body execution without the try_put
460  output_type v = (*my_body)(i);
462  return v;
463  }
464 
465  //TODO: consider moving into the base class
468  task* postponed_task = NULL;
469 #if TBB_DEPRECATED_MESSAGE_FLOW_ORDER
470  task* successor_task = successors().try_put_task(v);
471 #endif
473  postponed_task = base_type::try_get_postponed_task(i);
474  }
475 #if TBB_DEPRECATED_MESSAGE_FLOW_ORDER
476  graph& g = base_type::my_graph_ref;
477  return combine_tasks(g, successor_task, postponed_task);
478 #else
479  // postponed_task is either NULL or the pointer to TBB task
480  if(postponed_task) {
481  // spawn task to make it available for other workers
482  // since we do not know successors' execution policy
484  }
485  task* successor_task = successors().try_put_task(v);
486 #if _MSC_VER && !__INTEL_COMPILER
487 #pragma warning (push)
488 #pragma warning (disable: 4127) /* suppress conditional expression is constant */
489 #endif
491 #if _MSC_VER && !__INTEL_COMPILER
492 #pragma warning (pop)
493 #endif
494  if(!successor_task) {
495  // Return confirmative status since current
496  // node's body has been executed anyway
497  successor_task = SUCCESSFULLY_ENQUEUED;
498  }
499  }
500  return successor_task;
501 #endif /* TBB_DEPRECATED_MESSAGE_FLOW_ORDER */
502  }
503 
504  protected:
505 
508  if(f & rf_reset_bodies) {
510  delete my_body;
511  my_body = tmp;
512  }
513  }
514 
518 
519  }; // function_input
520 
521 
522  // helper templates to clear the successor edges of the output ports of an multifunction_node
523  template<int N> struct clear_element {
524  template<typename P> static void clear_this(P &p) {
525  (void)tbb::flow::get<N-1>(p).successors().clear();
527  }
528  template<typename P> static bool this_empty(P &p) {
529  if(tbb::flow::get<N-1>(p).successors().empty())
531  return false;
532  }
533  };
534 
535  template<> struct clear_element<1> {
536  template<typename P> static void clear_this(P &p) {
537  (void)tbb::flow::get<0>(p).successors().clear();
538  }
539  template<typename P> static bool this_empty(P &p) {
540  return tbb::flow::get<0>(p).successors().empty();
541  }
542  };
543 
544 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
545  // helper templates to extract the output ports of an multifunction_node from graph
546  template<int N> struct extract_element {
547  template<typename P> static void extract_this(P &p) {
548  (void)tbb::flow::get<N-1>(p).successors().built_successors().sender_extract(tbb::flow::get<N-1>(p));
549  extract_element<N-1>::extract_this(p);
550  }
551  };
552 
553  template<> struct extract_element<1> {
554  template<typename P> static void extract_this(P &p) {
555  (void)tbb::flow::get<0>(p).successors().built_successors().sender_extract(tbb::flow::get<0>(p));
556  }
557  };
558 #endif
559 
561  // and has a tuple of output ports specified.
562  template< typename Input, typename OutputPortSet, typename Policy, typename A>
563  class multifunction_input : public function_input_base<Input, Policy, A, multifunction_input<Input,OutputPortSet,Policy,A> > {
564  public:
566  typedef Input input_type;
567  typedef OutputPortSet output_ports_type;
572 
573  // constructor
574  template<typename Body>
576  graph &g,
577  size_t max_concurrency,
578  Body& body) :
580  my_body( new internal::multifunction_body_leaf<input_type, output_ports_type, Body>(body) ),
581  my_init_body( new internal::multifunction_body_leaf<input_type, output_ports_type, Body>(body) ) {
582  }
583 
586  base_type(src),
587  my_body( src.my_init_body->clone() ),
588  my_init_body(src.my_init_body->clone() ) {
589  }
590 
592  delete my_body;
593  delete my_init_body;
594  }
595 
596  template< typename Body >
598  multifunction_body_type &body_ref = *this->my_body;
599  return *static_cast<Body*>(dynamic_cast< internal::multifunction_body_leaf<input_type, output_ports_type, Body> & >(body_ref).get_body_ptr());
600  }
601 
602  // for multifunction nodes we do not have a single successor as such. So we just tell
603  // the task we were successful.
604  //TODO: consider moving common parts with implementation in function_input into separate function
607  (*my_body)(i, my_output_ports);
609  task* ttask = NULL;
612  }
613  return ttask ? ttask : SUCCESSFULLY_ENQUEUED;
614  }
615 
617 
618  protected:
619 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
620  void extract() {
621  extract_element<N>::extract_this(my_output_ports);
622  }
623 #endif
624 
625  void reset(reset_flags f) {
628  if(f & rf_reset_bodies) {
630  delete my_body;
631  my_body = tmp;
632  }
633  __TBB_ASSERT(!(f & rf_clear_edges) || clear_element<N>::this_empty(my_output_ports), "multifunction_node reset failed");
634  }
635 
639 
640  }; // multifunction_input
641 
642  // template to refer to an output port of a multifunction_node
643  template<size_t N, typename MOP>
645  return tbb::flow::get<N>(op.output_ports());
646  }
647 
648  inline void check_task_and_spawn(graph& g, task* t) {
649  if (t && t != SUCCESSFULLY_ENQUEUED) {
651  }
652  }
653 
654  // helper structs for split_node
655  template<int N>
656  struct emit_element {
657  template<typename T, typename P>
658  static task* emit_this(graph& g, const T &t, P &p) {
659  // TODO: consider to collect all the tasks in task_list and spawn them all at once
660  task* last_task = tbb::flow::get<N-1>(p).try_put_task(tbb::flow::get<N-1>(t));
661  check_task_and_spawn(g, last_task);
662  return emit_element<N-1>::emit_this(g,t,p);
663  }
664  };
665 
666  template<>
667  struct emit_element<1> {
668  template<typename T, typename P>
669  static task* emit_this(graph& g, const T &t, P &p) {
670  task* last_task = tbb::flow::get<0>(p).try_put_task(tbb::flow::get<0>(t));
671  check_task_and_spawn(g, last_task);
672  return SUCCESSFULLY_ENQUEUED;
673  }
674  };
675 
677  template< typename Output, typename Policy>
678  class continue_input : public continue_receiver {
679  public:
680 
682  typedef continue_msg input_type;
683 
685  typedef Output output_type;
688 
689  template< typename Body >
690  continue_input( graph &g, Body& body )
691  : my_graph_ref(g),
692  my_body( new internal::function_body_leaf< input_type, output_type, Body>(body) ),
693  my_init_body( new internal::function_body_leaf< input_type, output_type, Body>(body) ) { }
694 
695  template< typename Body >
696  continue_input( graph &g, int number_of_predecessors, Body& body )
697  : continue_receiver( number_of_predecessors ), my_graph_ref(g),
698  my_body( new internal::function_body_leaf< input_type, output_type, Body>(body) ),
699  my_init_body( new internal::function_body_leaf< input_type, output_type, Body>(body) )
700  { }
701 
702  continue_input( const continue_input& src ) : continue_receiver(src),
704  my_body( src.my_init_body->clone() ),
705  my_init_body( src.my_init_body->clone() ) {}
706 
708  delete my_body;
709  delete my_init_body;
710  }
711 
712  template< typename Body >
714  function_body_type &body_ref = *my_body;
715  return dynamic_cast< internal::function_body_leaf<input_type, output_type, Body> & >(body_ref).get_body();
716  }
717 
719  continue_receiver::reset_receiver(f);
720  if(f & rf_reset_bodies) {
722  delete my_body;
723  my_body = tmp;
724  }
725  }
726 
727  protected:
728 
729  graph& my_graph_ref;
732 
734 
735  friend class apply_body_task_bypass< class_type, continue_msg >;
736 
739  // There is an extra copied needed to capture the
740  // body execution without the try_put
742  output_type v = (*my_body)( continue_msg() );
744  return successors().try_put_task( v );
745  }
746 
749  return NULL;
750  }
751 #if _MSC_VER && !__INTEL_COMPILER
752 #pragma warning (push)
753 #pragma warning (disable: 4127) /* suppress conditional expression is constant */
754 #endif
756 #if _MSC_VER && !__INTEL_COMPILER
757 #pragma warning (pop)
758 #endif
759  return apply_body_bypass( continue_msg() );
760  }
761  else {
762  return new ( task::allocate_additional_child_of( *(my_graph_ref.root_task()) ) )
764  }
765  }
766 
768  return my_graph_ref;
769  }
770  }; // continue_input
771 
773  template< typename Output >
774  class function_output : public sender<Output> {
775  public:
776 
777  template<int N> friend struct clear_element;
778  typedef Output output_type;
779  typedef typename sender<output_type>::successor_type successor_type;
781 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
782  typedef typename sender<output_type>::built_successors_type built_successors_type;
783  typedef typename sender<output_type>::successor_list_type successor_list_type;
784 #endif
785 
787  function_output(const function_output & /*other*/) : sender<output_type>() {
788  my_successors.set_owner(this);
789  }
790 
794  return true;
795  }
796 
800  return true;
801  }
802 
803 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
804  built_successors_type &built_successors() __TBB_override { return successors().built_successors(); }
805 
806 
807  void internal_add_built_successor( successor_type &r) __TBB_override {
808  successors().internal_add_built_successor( r );
809  }
810 
811  void internal_delete_built_successor( successor_type &r) __TBB_override {
812  successors().internal_delete_built_successor( r );
813  }
814 
815  size_t successor_count() __TBB_override {
816  return successors().successor_count();
817  }
818 
819  void copy_successors( successor_list_type &v) __TBB_override {
820  successors().copy_successors(v);
821  }
822 #endif /* TBB_DEPRECATED_FLOW_NODE_EXTRACTION */
823 
824  // for multifunction_node. The function_body that implements
825  // the node will have an input and an output tuple of ports. To put
826  // an item to a successor, the body should
827  //
828  // get<I>(output_ports).try_put(output_value);
829  //
830  // if task pointer is returned will always spawn and return true, else
831  // return value will be bool returned from successors.try_put.
832  task *try_put_task(const output_type &i) { // not a virtual method in this class
833  return my_successors.try_put_task(i);
834  }
835 
837  protected:
839 
840  }; // function_output
841 
842  template< typename Output >
843  class multifunction_output : public function_output<Output> {
844  public:
845  typedef Output output_type;
848 
851 
852  bool try_put(const output_type &i) {
853  task *res = try_put_task(i);
854  if(!res) return false;
855  if(res != SUCCESSFULLY_ENQUEUED) {
856  FLOW_SPAWN(*res); // TODO: Spawn task inside arena
857  }
858  return true;
859  }
860 
861  protected:
862 
864  return my_successors.try_put_task(i);
865  }
866 
867  template <int N> friend struct emit_element;
868 
869  }; // multifunction_output
870 
871 //composite_node
872 #if __TBB_FLOW_GRAPH_CPP11_FEATURES
873  template<typename CompositeType>
874  void add_nodes_impl(CompositeType*, bool) {}
875 
876  template< typename CompositeType, typename NodeType1, typename... NodeTypes >
877  void add_nodes_impl(CompositeType *c_node, bool visible, const NodeType1& n1, const NodeTypes&... n) {
878  void *addr = const_cast<NodeType1 *>(&n1);
879 
880  fgt_alias_port(c_node, addr, visible);
881  add_nodes_impl(c_node, visible, n...);
882  }
883 #endif
884 
885 } // internal
886 
887 #endif // __TBB__flow_graph_node_impl_H
graph & graph_reference() __TBB_override
task * try_put_task(const T &t) __TBB_override
task * apply_body_impl_bypass(const input_type &i)
function_body< input_type, output_type > function_body_type
static void fgt_alias_port(void *, void *, bool)
static tbb::task * combine_tasks(graph &g, tbb::task *left, tbb::task *right)
Definition: flow_graph.h:171
void reset_function_input(reset_flags f)
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task * task
void set_owner(owner_type *owner)
multifunction_input(const multifunction_input &src)
Copy constructor.
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task __itt_model_task_instance ITT_FORMAT p void ITT_FORMAT p void ITT_FORMAT p void size_t ITT_FORMAT d void ITT_FORMAT p const wchar_t ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s no args void ITT_FORMAT p size_t ITT_FORMAT d no args const wchar_t const wchar_t ITT_FORMAT s __itt_heap_function void size_t int ITT_FORMAT d __itt_heap_function void ITT_FORMAT p __itt_heap_function void void size_t int ITT_FORMAT d no args no args unsigned int ITT_FORMAT u const __itt_domain __itt_id ITT_FORMAT lu const __itt_domain __itt_id __itt_id __itt_string_handle ITT_FORMAT p const __itt_domain __itt_id ITT_FORMAT p const __itt_domain __itt_id __itt_timestamp __itt_timestamp ITT_FORMAT lu const __itt_domain __itt_id __itt_id __itt_string_handle ITT_FORMAT p const __itt_domain ITT_FORMAT p const __itt_domain __itt_string_handle unsigned long long ITT_FORMAT lu const __itt_domain __itt_id __itt_string_handle __itt_metadata_type type
void spawn_in_graph_arena(graph &g, tbb::task &arena_task)
Spawns a task inside graph arena.
task * apply_body_impl_bypass(const input_type &i)
broadcast_cache_type my_successors
Base class for user-defined tasks.
Definition: task.h:576
static task * emit_this(graph &g, const T &t, P &p)
function_body_type * my_init_body
void __TBB_store_with_release(volatile T &location, V value)
Definition: tbb_machine.h:717
predecessor_cache< input_type, null_mutex > predecessor_cache_type
function_body that takes an Input and a set of output ports
void remove_successor(successor_type &r)
function_input_queue< input_type, A > input_queue_type
void * addr
predecessor_cache< input_type, null_mutex > my_predecessors
static void fgt_end_body(void *)
function_input_queue< input_type, A > input_queue_type
void internal_try_put_task(operation_type *op)
Put to the node, but return the task instead of enqueueing it.
task * apply_body_bypass(input_type)
Applies the body to the provided input.
function_input_base(graph &g, size_t max_concurrency)
Constructor for function_input_base.
void reset_receiver(reset_flags f) __TBB_override
Input input_type
The input type of this receiver.
const item_type & front() const
task * try_put_task_impl(const input_type &t, tbb::internal::true_type)
Implements methods for an executable node that takes continue_msg as input.
task * apply_body_bypass(const input_type &i)
Applies the body to the provided input.
bool remove_successor(successor_type &r) __TBB_override
Removes a successor from this node.
function_body_type * my_body
Implements methods for a function node that takes a type Input as input.
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:169
virtual multifunction_body * clone()=0
#define __TBB_override
Definition: tbb_stddef.h:244
void const char const char int ITT_FORMAT __itt_group_sync p
Implements methods for a function node that takes a type Input as input and sends.
int max_concurrency()
Returns the maximal number of threads that can work inside the arena.
Definition: task_arena.h:402
task * try_get_postponed_task(const input_type &i)
the leaf for function_body
bool register_predecessor(predecessor_type &src) __TBB_override
Adds src to the list of cached predecessors.
Input and scheduling for a function node that takes a type Input as input.
Base class for types that should not be assigned.
Definition: tbb_stddef.h:324
virtual ~function_input_base()
Destructor.
A task that calls a node's apply_body_bypass function, passing in an input of type Input.
aggregator< handler_type, operation_type > my_aggregator
virtual broadcast_cache< output_type > & successors()=0
broadcast_cache< output_type > broadcast_cache_type
#define FLOW_SPAWN(a)
Definition: flow_graph.h:53
leaf for multifunction. OutputSet can be a std::tuple or a vector.
function_body< input_type, output_type > function_body_type
task * try_put_task(const input_type &t) __TBB_override
Put item to successor; return task to run the successor if possible.
void add_nodes_impl(CompositeType *, bool)
internal::aggregating_functor< class_type, operation_type > handler_type
void register_successor(successor_type &r)
function_input_base< Input, Policy, A, my_class > base_type
function_input(graph &g, size_t max_concurrency, Body &body)
void reset_receiver(reset_flags f) __TBB_override
void set_owner(successor_type *owner)
multifunction_output(const multifunction_output &)
__TBB_STATIC_ASSERT(!((internal::has_policy< queueing, Policy >::value) &&(internal::has_policy< rejecting, Policy >::value)), "queueing and rejecting policies can't be specified simultaneously")
A task that calls a node's forward_task function.
multifunction_input< Input, OutputPortSet, Policy, A > my_class
virtual function_body * clone()=0
Implements methods for both executable and function nodes that puts Output to its successors.
virtual broadcast_cache< output_type > & successors()=0
A functor that takes an Input and generates an Output.
continue_msg input_type
The input type of this receiver.
function_body_type * my_body
function_body_type * my_init_body
function_input_base(const function_input_base &src)
Copy constructor.
function_input_base< Input, Policy, A, my_class > base_type
task * try_put_task(const output_type &i)
sender< output_type >::successor_type successor_type
void check_task_and_spawn(graph &g, task *t)
graph & graph_reference() __TBB_override
function_input_queue< input_type, A > input_queue_type
function_input_base< Input, Policy, A, ImplType > class_type
multifunction_body_type * my_init_body
bool remove_predecessor(predecessor_type &src) __TBB_override
Removes src from the list of cached predecessors.
The graph class.
task * internal_try_put_bypass(const input_type &t)
A::template rebind< input_queue_type >::other queue_allocator_type
bool register_successor(successor_type &r) __TBB_override
Adds a new successor to this node.
Output output_type
The output type of this receiver.
task * execute() __TBB_override
function_output(const function_output &)
void handle_operations(operation_type *op_list)
output_type apply_body_impl(const input_type &i)
broadcast_cache_type & successors()
task * forward_task()
This is executed by an enqueued task, the "forwarder".
void reset_function_input_base(reset_flags f)
Input input_type
The input type of this receiver.
Definition: flow_graph.h:440
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task __itt_model_task_instance ITT_FORMAT p void ITT_FORMAT p void ITT_FORMAT p void size_t ITT_FORMAT d void ITT_FORMAT p const wchar_t ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s no args void ITT_FORMAT p size_t ITT_FORMAT d no args const wchar_t const wchar_t ITT_FORMAT s __itt_heap_function void size_t int ITT_FORMAT d __itt_heap_function void ITT_FORMAT p __itt_heap_function void void size_t int ITT_FORMAT d no args no args unsigned int ITT_FORMAT u const __itt_domain __itt_id ITT_FORMAT lu const __itt_domain __itt_id __itt_id __itt_string_handle ITT_FORMAT p const __itt_domain __itt_id ITT_FORMAT p const __itt_domain __itt_id __itt_timestamp __itt_timestamp ITT_FORMAT lu const __itt_domain __itt_id __itt_id __itt_string_handle ITT_FORMAT p const __itt_domain ITT_FORMAT p const __itt_domain __itt_string_handle unsigned long long value
static void fgt_begin_body(void *)
void spawn_forward_task()
Spawns a task that calls forward()
task * try_put_task(const output_type &i)
multifunction_body_type * my_body
static task * emit_this(graph &g, const T &t, P &p)
void internal_forward(operation_type *op)
Tries to spawn bodies if available and if concurrency allows.
function_input< Input, Output, Policy, A > my_class
bool try_put(const output_type &i)
task * try_put_task_impl(const input_type &t, tbb::internal::false_type)
static tbb::task *const SUCCESSFULLY_ENQUEUED
continue_input< output_type, Policy > class_type
tbb::flow::tuple_element< N, typename MOP::output_ports_type >::type & output_port(MOP &op)
continue_input(graph &g, Body &body)
receiver< input_type >::predecessor_type predecessor_type
continue_input(graph &g, int number_of_predecessors, Body &body)
multifunction_input(graph &g, size_t max_concurrency, Body &body)
function_input(const function_input &src)
Copy constructor.
function_output< output_type > base_type
task * create_body_task(const input_type &input)
allocates a task to apply a body
multifunction_body< input_type, output_ports_type > multifunction_body_type
continue_input(const continue_input &src)

Copyright © 2005-2018 Intel Corporation. All Rights Reserved.

Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are registered trademarks or trademarks of Intel Corporation or its subsidiaries in the United States and other countries.

* Other names and brands may be claimed as the property of others.