File indexing completed on 2025-01-18 10:12:46
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #ifndef __TBB__flow_graph_body_impl_H
0018 #define __TBB__flow_graph_body_impl_H
0019
0020 #include "tbb/internal/_template_helpers.h"
0021
0022 #ifndef __TBB_flow_graph_H
0023 #error Do not #include this internal file directly; use public TBB headers instead.
0024 #endif
0025
0026
0027
0028 namespace internal {
0029
0030 typedef tbb::internal::uint64_t tag_value;
0031
0032 using tbb::internal::strip;
0033
0034 #if __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT
0035
0036 template<typename ... Policies> struct Policy {};
0037
0038 template<typename ... Policies> struct has_policy;
0039
0040 template<typename ExpectedPolicy, typename FirstPolicy, typename ...Policies>
0041 struct has_policy<ExpectedPolicy, FirstPolicy, Policies...> :
0042 tbb::internal::bool_constant<has_policy<ExpectedPolicy, FirstPolicy>::value ||
0043 has_policy<ExpectedPolicy, Policies...>::value> {};
0044
0045 template<typename ExpectedPolicy, typename SinglePolicy>
0046 struct has_policy<ExpectedPolicy, SinglePolicy> :
0047 tbb::internal::bool_constant<tbb::internal::is_same_type<ExpectedPolicy, SinglePolicy>::value> {};
0048
0049 template<typename ExpectedPolicy, typename ...Policies>
0050 struct has_policy<ExpectedPolicy, Policy<Policies...> > : has_policy<ExpectedPolicy, Policies...> {};
0051
0052 #else
0053
0054 template<typename P1, typename P2 = void> struct Policy {};
0055
0056 template<typename ExpectedPolicy, typename SinglePolicy>
0057 struct has_policy : tbb::internal::bool_constant<tbb::internal::is_same_type<ExpectedPolicy, SinglePolicy>::value> {};
0058
0059 template<typename ExpectedPolicy, typename P>
0060 struct has_policy<ExpectedPolicy, Policy<P> > : has_policy<ExpectedPolicy, P> {};
0061
0062 template<typename ExpectedPolicy, typename P1, typename P2>
0063 struct has_policy<ExpectedPolicy, Policy<P1, P2> > :
0064 tbb::internal::bool_constant<has_policy<ExpectedPolicy, P1>::value || has_policy<ExpectedPolicy, P2>::value> {};
0065
0066 #endif
0067
0068 namespace graph_policy_namespace {
0069
0070 struct rejecting { };
0071 struct reserving { };
0072 struct queueing { };
0073 struct lightweight { };
0074
0075
0076
0077
0078 template<typename K, typename KHash=tbb_hash_compare<typename strip<K>::type > >
0079 struct key_matching {
0080 typedef K key_type;
0081 typedef typename strip<K>::type base_key_type;
0082 typedef KHash hash_compare_type;
0083 };
0084
0085
0086 typedef key_matching<tag_value> tag_matching;
0087
0088
0089 typedef interface11::internal::Policy<queueing, lightweight> queueing_lightweight;
0090 typedef interface11::internal::Policy<rejecting, lightweight> rejecting_lightweight;
0091
0092 }
0093
0094
0095
0096 template< typename Output >
0097 class input_body : tbb::internal::no_assign {
0098 public:
0099 virtual ~input_body() {}
0100
0101 #if TBB_DEPRECATED_INPUT_NODE_BODY
0102 virtual bool operator()(Output &output) = 0;
0103 #else
0104 virtual Output operator()(flow_control& fc) = 0;
0105 #endif
0106 virtual input_body* clone() = 0;
0107 };
0108
0109 template <typename Body>
0110 void check_input_node_body_input_type_impl(Body) {
0111 __TBB_STATIC_ASSERT((tbb::internal::is_same_type<typename tbb::internal::body_arg_detector<Body>::arg_type, flow_control&>::value),
0112 "TBB Warning: input_node body requirements have been changed."
0113 "To temporarily enforce deprecated API specify TBB_DEPRECATED_INPUT_NODE_BODY.");
0114 }
0115
0116 template <typename Body>
0117 void check_input_node_body_input_type(Body) {
0118 check_input_node_body_input_type_impl(&Body::operator());
0119 }
0120
0121 template <typename ReturnType, typename T>
0122 void check_input_node_body_input_type(ReturnType(*)(T)) {
0123 __TBB_STATIC_ASSERT((tbb::internal::is_same_type<T, flow_control&>::value),
0124 "TBB Warning: input_node body requirements have been changed."
0125 "To temporarily enforce deprecated API specify TBB_DEPRECATED_INPUT_NODE_BODY.");
0126 }
0127
0128
0129 template< typename Output, typename Body>
0130 class input_body_leaf : public input_body<Output> {
0131 public:
0132 input_body_leaf( const Body &_body ) : body(_body) { }
0133
0134 #if TBB_DEPRECATED_INPUT_NODE_BODY
0135 bool operator()(Output &output) __TBB_override { return body( output ); }
0136 #else
0137 Output operator()(flow_control& fc) __TBB_override {
0138 check_input_node_body_input_type(body);
0139 return body(fc);
0140 }
0141 #endif
0142 input_body_leaf* clone() __TBB_override {
0143 return new input_body_leaf< Output, Body >(body);
0144 }
0145 Body get_body() { return body; }
0146 private:
0147 Body body;
0148 };
0149
0150 template< typename Output >
0151 class source_body : tbb::internal::no_assign {
0152 public:
0153 virtual ~source_body() {}
0154 virtual bool operator()(Output &output) = 0;
0155 virtual source_body* clone() = 0;
0156 };
0157
0158
0159 template< typename Output, typename Body>
0160 class source_body_leaf : public source_body<Output> {
0161 public:
0162 source_body_leaf( const Body &_body ) : body(_body) { }
0163
0164 bool operator()(Output &output) __TBB_override { return body( output ); }
0165
0166 source_body_leaf* clone() __TBB_override {
0167 return new source_body_leaf< Output, Body >(body);
0168 }
0169
0170 Body get_body() { return body; }
0171 private:
0172 Body body;
0173 };
0174
0175
0176 template< typename Input, typename Output >
0177 class function_body : tbb::internal::no_assign {
0178 public:
0179 virtual ~function_body() {}
0180 virtual Output operator()(const Input &input) = 0;
0181 virtual function_body* clone() = 0;
0182 };
0183
0184
0185 template <typename Input, typename Output, typename B>
0186 class function_body_leaf : public function_body< Input, Output > {
0187 public:
0188 function_body_leaf( const B &_body ) : body(_body) { }
0189 Output operator()(const Input &i) __TBB_override { return body(i); }
0190 B get_body() { return body; }
0191 function_body_leaf* clone() __TBB_override {
0192 return new function_body_leaf< Input, Output, B >(body);
0193 }
0194 private:
0195 B body;
0196 };
0197
0198
0199 template <typename B>
0200 class function_body_leaf< continue_msg, continue_msg, B> : public function_body< continue_msg, continue_msg > {
0201 public:
0202 function_body_leaf( const B &_body ) : body(_body) { }
0203 continue_msg operator()( const continue_msg &i ) __TBB_override {
0204 body(i);
0205 return i;
0206 }
0207 B get_body() { return body; }
0208 function_body_leaf* clone() __TBB_override {
0209 return new function_body_leaf< continue_msg, continue_msg, B >(body);
0210 }
0211 private:
0212 B body;
0213 };
0214
0215
0216 template <typename Input, typename B>
0217 class function_body_leaf< Input, continue_msg, B> : public function_body< Input, continue_msg > {
0218 public:
0219 function_body_leaf( const B &_body ) : body(_body) { }
0220 continue_msg operator()(const Input &i) __TBB_override {
0221 body(i);
0222 return continue_msg();
0223 }
0224 B get_body() { return body; }
0225 function_body_leaf* clone() __TBB_override {
0226 return new function_body_leaf< Input, continue_msg, B >(body);
0227 }
0228 private:
0229 B body;
0230 };
0231
0232
0233 template <typename Output, typename B>
0234 class function_body_leaf< continue_msg, Output, B > : public function_body< continue_msg, Output > {
0235 public:
0236 function_body_leaf( const B &_body ) : body(_body) { }
0237 Output operator()(const continue_msg &i) __TBB_override {
0238 return body(i);
0239 }
0240 B get_body() { return body; }
0241 function_body_leaf* clone() __TBB_override {
0242 return new function_body_leaf< continue_msg, Output, B >(body);
0243 }
0244 private:
0245 B body;
0246 };
0247
0248
0249 template<typename Input, typename OutputSet>
0250 class multifunction_body : tbb::internal::no_assign {
0251 public:
0252 virtual ~multifunction_body () {}
0253 virtual void operator()(const Input &, OutputSet &) = 0;
0254 virtual multifunction_body* clone() = 0;
0255 virtual void* get_body_ptr() = 0;
0256 };
0257
0258
0259 template<typename Input, typename OutputSet, typename B >
0260 class multifunction_body_leaf : public multifunction_body<Input, OutputSet> {
0261 public:
0262 multifunction_body_leaf(const B &_body) : body(_body) { }
0263 void operator()(const Input &input, OutputSet &oset) __TBB_override {
0264 body(input, oset);
0265 }
0266 void* get_body_ptr() __TBB_override { return &body; }
0267 multifunction_body_leaf* clone() __TBB_override {
0268 return new multifunction_body_leaf<Input, OutputSet,B>(body);
0269 }
0270
0271 private:
0272 B body;
0273 };
0274
0275
0276
0277 template<typename Input, typename Output>
0278 class type_to_key_function_body : tbb::internal::no_assign {
0279 public:
0280 virtual ~type_to_key_function_body() {}
0281 virtual Output operator()(const Input &input) = 0;
0282 virtual type_to_key_function_body* clone() = 0;
0283 };
0284
0285
0286 template<typename Input, typename Output>
0287 class type_to_key_function_body<Input,Output&> : tbb::internal::no_assign {
0288 public:
0289 virtual ~type_to_key_function_body() {}
0290 virtual const Output & operator()(const Input &input) = 0;
0291 virtual type_to_key_function_body* clone() = 0;
0292 };
0293
0294 template <typename Input, typename Output, typename B>
0295 class type_to_key_function_body_leaf : public type_to_key_function_body<Input, Output> {
0296 public:
0297 type_to_key_function_body_leaf( const B &_body ) : body(_body) { }
0298 Output operator()(const Input &i) __TBB_override { return body(i); }
0299 B get_body() { return body; }
0300 type_to_key_function_body_leaf* clone() __TBB_override {
0301 return new type_to_key_function_body_leaf< Input, Output, B>(body);
0302 }
0303 private:
0304 B body;
0305 };
0306
0307 template <typename Input, typename Output, typename B>
0308 class type_to_key_function_body_leaf<Input,Output&,B> : public type_to_key_function_body< Input, Output&> {
0309 public:
0310 type_to_key_function_body_leaf( const B &_body ) : body(_body) { }
0311 const Output& operator()(const Input &i) __TBB_override {
0312 return body(i);
0313 }
0314 B get_body() { return body; }
0315 type_to_key_function_body_leaf* clone() __TBB_override {
0316 return new type_to_key_function_body_leaf< Input, Output&, B>(body);
0317 }
0318 private:
0319 B body;
0320 };
0321
0322
0323
0324
0325
0326
0327 template< typename NodeType >
0328 class forward_task_bypass : public graph_task {
0329
0330 NodeType &my_node;
0331
0332 public:
0333
0334 forward_task_bypass( NodeType &n
0335 #if __TBB_PREVIEW_FLOW_GRAPH_PRIORITIES
0336 , node_priority_t node_priority = no_priority
0337 ) : graph_task(node_priority),
0338 #else
0339 ) :
0340 #endif
0341 my_node(n) {}
0342
0343 task *execute() __TBB_override {
0344 task * new_task = my_node.forward_task();
0345 if (new_task == SUCCESSFULLY_ENQUEUED) new_task = NULL;
0346 return new_task;
0347 }
0348 };
0349
0350
0351
0352 template< typename NodeType, typename Input >
0353 class apply_body_task_bypass : public graph_task {
0354
0355 NodeType &my_node;
0356 Input my_input;
0357
0358 public:
0359
0360 apply_body_task_bypass( NodeType &n, const Input &i
0361 #if __TBB_PREVIEW_FLOW_GRAPH_PRIORITIES
0362 , node_priority_t node_priority = no_priority
0363 ) : graph_task(node_priority),
0364 #else
0365 ) :
0366 #endif
0367 my_node(n), my_input(i) {}
0368
0369 task *execute() __TBB_override {
0370 task * next_task = my_node.apply_body_bypass( my_input );
0371 if(next_task == SUCCESSFULLY_ENQUEUED) next_task = NULL;
0372 return next_task;
0373 }
0374 };
0375
0376
0377 template< typename NodeType >
0378 class source_task_bypass : public graph_task {
0379
0380 NodeType &my_node;
0381
0382 public:
0383
0384 source_task_bypass( NodeType &n ) : my_node(n) {}
0385
0386 task *execute() __TBB_override {
0387 task *new_task = my_node.apply_body_bypass( );
0388 if(new_task == SUCCESSFULLY_ENQUEUED) return NULL;
0389 return new_task;
0390 }
0391 };
0392
0393
0394
0395
0396 template< typename Input, typename Output >
0397 struct empty_body {
0398 Output operator()( const Input & ) const { return Output(); }
0399 };
0400
0401 template<typename T, typename DecrementType, typename DummyType = void>
0402 class decrementer;
0403
0404 template<typename T, typename DecrementType>
0405 class decrementer<T, DecrementType,
0406 typename tbb::internal::enable_if<
0407 tbb::internal::is_integral<DecrementType>::value, void>::type
0408 > : public receiver<DecrementType>, tbb::internal::no_copy {
0409 T* my_node;
0410 protected:
0411
0412 task* try_put_task( const DecrementType& value ) __TBB_override {
0413 task* result = my_node->decrement_counter( value );
0414 if( !result )
0415 result = SUCCESSFULLY_ENQUEUED;
0416 return result;
0417 }
0418
0419 graph& graph_reference() const __TBB_override {
0420 return my_node->my_graph;
0421 }
0422
0423 template<typename U, typename V> friend class tbb::flow::interface11::limiter_node;
0424 void reset_receiver( reset_flags f ) __TBB_override {
0425 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
0426 if (f & rf_clear_edges)
0427 my_built_predecessors.clear();
0428 #else
0429 tbb::internal::suppress_unused_warning( f );
0430 #endif
0431 }
0432
0433 public:
0434
0435
0436
0437 decrementer() : my_node(NULL) {}
0438 void set_owner( T *node ) { my_node = node; }
0439
0440 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
0441 spin_mutex my_mutex;
0442
0443 typedef typename receiver<DecrementType>::predecessor_type predecessor_type;
0444
0445 typedef internal::edge_container<predecessor_type> built_predecessors_type;
0446 typedef typename built_predecessors_type::edge_list_type predecessor_list_type;
0447 built_predecessors_type &built_predecessors() __TBB_override { return my_built_predecessors; }
0448
0449 void internal_add_built_predecessor( predecessor_type &s) __TBB_override {
0450 spin_mutex::scoped_lock l(my_mutex);
0451 my_built_predecessors.add_edge( s );
0452 }
0453
0454 void internal_delete_built_predecessor( predecessor_type &s) __TBB_override {
0455 spin_mutex::scoped_lock l(my_mutex);
0456 my_built_predecessors.delete_edge(s);
0457 }
0458
0459 void copy_predecessors( predecessor_list_type &v) __TBB_override {
0460 spin_mutex::scoped_lock l(my_mutex);
0461 my_built_predecessors.copy_edges(v);
0462 }
0463
0464 size_t predecessor_count() __TBB_override {
0465 spin_mutex::scoped_lock l(my_mutex);
0466 return my_built_predecessors.edge_count();
0467 }
0468 protected:
0469 built_predecessors_type my_built_predecessors;
0470 #endif
0471 };
0472
0473 template<typename T>
0474 class decrementer<T, continue_msg, void> : public continue_receiver, tbb::internal::no_copy {
0475
0476 T *my_node;
0477
0478 task *execute() __TBB_override {
0479 return my_node->decrement_counter( 1 );
0480 }
0481
0482 protected:
0483
0484 graph& graph_reference() const __TBB_override {
0485 return my_node->my_graph;
0486 }
0487
0488 public:
0489
0490 typedef continue_msg input_type;
0491 typedef continue_msg output_type;
0492 decrementer( int number_of_predecessors = 0 )
0493 : continue_receiver(
0494 __TBB_FLOW_GRAPH_PRIORITY_ARG1(number_of_predecessors, tbb::flow::internal::no_priority)
0495 )
0496
0497
0498
0499 , my_node(NULL)
0500 {}
0501 void set_owner( T *node ) { my_node = node; }
0502 };
0503
0504 }
0505
0506 #endif
0507