File indexing completed on 2025-07-30 08:46:16
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 #ifndef __TBB_flow_graph_H
0021 #error Do not #include this internal file directly; use public TBB headers instead.
0022 #endif
0023
0024
0025
0026 typedef std::uint64_t tag_value;
0027
0028
0029
0030 template<typename ... Policies> struct Policy {};
0031
0032 template<typename ... Policies> struct has_policy;
0033
0034 template<typename ExpectedPolicy, typename FirstPolicy, typename ...Policies>
0035 struct has_policy<ExpectedPolicy, FirstPolicy, Policies...> :
0036 std::integral_constant<bool, has_policy<ExpectedPolicy, FirstPolicy>::value ||
0037 has_policy<ExpectedPolicy, Policies...>::value> {};
0038
0039 template<typename ExpectedPolicy, typename SinglePolicy>
0040 struct has_policy<ExpectedPolicy, SinglePolicy> :
0041 std::integral_constant<bool, std::is_same<ExpectedPolicy, SinglePolicy>::value> {};
0042
0043 template<typename ExpectedPolicy, typename ...Policies>
0044 struct has_policy<ExpectedPolicy, Policy<Policies...> > : has_policy<ExpectedPolicy, Policies...> {};
0045
0046 namespace graph_policy_namespace {
0047
0048 struct rejecting { };
0049 struct reserving { };
0050 struct queueing { };
0051 struct lightweight { };
0052
0053
0054
0055
0056 template<typename K, typename KHash=tbb_hash_compare<typename std::decay<K>::type > >
0057 __TBB_requires(tbb::detail::hash_compare<KHash, K>)
0058 struct key_matching {
0059 typedef K key_type;
0060 typedef typename std::decay<K>::type base_key_type;
0061 typedef KHash hash_compare_type;
0062 };
0063
0064
0065 typedef key_matching<tag_value> tag_matching;
0066
0067
0068 typedef Policy<queueing, lightweight> queueing_lightweight;
0069 typedef Policy<rejecting, lightweight> rejecting_lightweight;
0070
0071 }
0072
0073
0074
0075
0076 template< typename Output >
0077 class input_body : no_assign {
0078 public:
0079 virtual ~input_body() {}
0080 virtual Output operator()(flow_control& fc) = 0;
0081 virtual input_body* clone() = 0;
0082 };
0083
0084
0085 template< typename Output, typename Body>
0086 class input_body_leaf : public input_body<Output> {
0087 public:
0088 input_body_leaf( const Body &_body ) : body(_body) { }
0089 Output operator()(flow_control& fc) override { return body(fc); }
0090 input_body_leaf* clone() override {
0091 return new input_body_leaf< Output, Body >(body);
0092 }
0093 Body get_body() { return body; }
0094 private:
0095 Body body;
0096 };
0097
0098
0099 template< typename Input, typename Output >
0100 class function_body : no_assign {
0101 public:
0102 virtual ~function_body() {}
0103 virtual Output operator()(const Input &input) = 0;
0104 virtual function_body* clone() = 0;
0105 };
0106
0107
0108 template <typename Input, typename Output, typename B>
0109 class function_body_leaf : public function_body< Input, Output > {
0110 public:
0111 function_body_leaf( const B &_body ) : body(_body) { }
0112 Output operator()(const Input &i) override { return tbb::detail::invoke(body,i); }
0113 B get_body() { return body; }
0114 function_body_leaf* clone() override {
0115 return new function_body_leaf< Input, Output, B >(body);
0116 }
0117 private:
0118 B body;
0119 };
0120
0121
0122 template <typename B>
0123 class function_body_leaf< continue_msg, continue_msg, B> : public function_body< continue_msg, continue_msg > {
0124 public:
0125 function_body_leaf( const B &_body ) : body(_body) { }
0126 continue_msg operator()( const continue_msg &i ) override {
0127 body(i);
0128 return i;
0129 }
0130 B get_body() { return body; }
0131 function_body_leaf* clone() override {
0132 return new function_body_leaf< continue_msg, continue_msg, B >(body);
0133 }
0134 private:
0135 B body;
0136 };
0137
0138
0139 template <typename Input, typename B>
0140 class function_body_leaf< Input, continue_msg, B> : public function_body< Input, continue_msg > {
0141 public:
0142 function_body_leaf( const B &_body ) : body(_body) { }
0143 continue_msg operator()(const Input &i) override {
0144 body(i);
0145 return continue_msg();
0146 }
0147 B get_body() { return body; }
0148 function_body_leaf* clone() override {
0149 return new function_body_leaf< Input, continue_msg, B >(body);
0150 }
0151 private:
0152 B body;
0153 };
0154
0155
0156 template <typename Output, typename B>
0157 class function_body_leaf< continue_msg, Output, B > : public function_body< continue_msg, Output > {
0158 public:
0159 function_body_leaf( const B &_body ) : body(_body) { }
0160 Output operator()(const continue_msg &i) override {
0161 return body(i);
0162 }
0163 B get_body() { return body; }
0164 function_body_leaf* clone() override {
0165 return new function_body_leaf< continue_msg, Output, B >(body);
0166 }
0167 private:
0168 B body;
0169 };
0170
0171
0172 template<typename Input, typename OutputSet>
0173 class multifunction_body : no_assign {
0174 public:
0175 virtual ~multifunction_body () {}
0176 virtual void operator()(const Input &, OutputSet &) = 0;
0177 virtual multifunction_body* clone() = 0;
0178 virtual void* get_body_ptr() = 0;
0179 };
0180
0181
0182 template<typename Input, typename OutputSet, typename B >
0183 class multifunction_body_leaf : public multifunction_body<Input, OutputSet> {
0184 public:
0185 multifunction_body_leaf(const B &_body) : body(_body) { }
0186 void operator()(const Input &input, OutputSet &oset) override {
0187 tbb::detail::invoke(body, input, oset);
0188 }
0189 void* get_body_ptr() override { return &body; }
0190 multifunction_body_leaf* clone() override {
0191 return new multifunction_body_leaf<Input, OutputSet,B>(body);
0192 }
0193
0194 private:
0195 B body;
0196 };
0197
0198
0199
0200 template<typename Input, typename Output>
0201 class type_to_key_function_body : no_assign {
0202 public:
0203 virtual ~type_to_key_function_body() {}
0204 virtual Output operator()(const Input &input) = 0;
0205 virtual type_to_key_function_body* clone() = 0;
0206 };
0207
0208
0209 template<typename Input, typename Output>
0210 class type_to_key_function_body<Input,Output&> : no_assign {
0211 public:
0212 virtual ~type_to_key_function_body() {}
0213 virtual const Output & operator()(const Input &input) = 0;
0214 virtual type_to_key_function_body* clone() = 0;
0215 };
0216
0217 template <typename Input, typename Output, typename B>
0218 class type_to_key_function_body_leaf : public type_to_key_function_body<Input, Output> {
0219 public:
0220 type_to_key_function_body_leaf( const B &_body ) : body(_body) { }
0221 Output operator()(const Input &i) override { return tbb::detail::invoke(body, i); }
0222 type_to_key_function_body_leaf* clone() override {
0223 return new type_to_key_function_body_leaf< Input, Output, B>(body);
0224 }
0225 private:
0226 B body;
0227 };
0228
0229 template <typename Input, typename Output, typename B>
0230 class type_to_key_function_body_leaf<Input,Output&,B> : public type_to_key_function_body< Input, Output&> {
0231 public:
0232 type_to_key_function_body_leaf( const B &_body ) : body(_body) { }
0233 const Output& operator()(const Input &i) override {
0234 return tbb::detail::invoke(body, i);
0235 }
0236 type_to_key_function_body_leaf* clone() override {
0237 return new type_to_key_function_body_leaf< Input, Output&, B>(body);
0238 }
0239 private:
0240 B body;
0241 };
0242
0243
0244
0245
0246
0247
0248 template< typename NodeType >
0249 class forward_task_bypass : public graph_task {
0250 NodeType &my_node;
0251 public:
0252 forward_task_bypass( graph& g, small_object_allocator& allocator, NodeType &n
0253 , node_priority_t node_priority = no_priority
0254 ) : graph_task(g, allocator, node_priority),
0255 my_node(n) {}
0256
0257 task* execute(execution_data& ed) override {
0258 graph_task* next_task = my_node.forward_task();
0259 if (SUCCESSFULLY_ENQUEUED == next_task)
0260 next_task = nullptr;
0261 else if (next_task)
0262 next_task = prioritize_task(my_node.graph_reference(), *next_task);
0263 finalize<forward_task_bypass>(ed);
0264 return next_task;
0265 }
0266
0267 task* cancel(execution_data& ed) override {
0268 finalize<forward_task_bypass>(ed);
0269 return nullptr;
0270 }
0271 };
0272
0273
0274
0275 template< typename NodeType, typename Input >
0276 class apply_body_task_bypass : public graph_task {
0277 NodeType &my_node;
0278 Input my_input;
0279 public:
0280
0281 apply_body_task_bypass( graph& g, small_object_allocator& allocator, NodeType &n, const Input &i
0282 , node_priority_t node_priority = no_priority
0283 ) : graph_task(g, allocator, node_priority),
0284 my_node(n), my_input(i) {}
0285
0286 task* execute(execution_data& ed) override {
0287 graph_task* next_task = my_node.apply_body_bypass( my_input );
0288 if (SUCCESSFULLY_ENQUEUED == next_task)
0289 next_task = nullptr;
0290 else if (next_task)
0291 next_task = prioritize_task(my_node.graph_reference(), *next_task);
0292 finalize<apply_body_task_bypass>(ed);
0293 return next_task;
0294 }
0295
0296 task* cancel(execution_data& ed) override {
0297 finalize<apply_body_task_bypass>(ed);
0298 return nullptr;
0299 }
0300 };
0301
0302
0303 template< typename NodeType >
0304 class input_node_task_bypass : public graph_task {
0305 NodeType &my_node;
0306 public:
0307 input_node_task_bypass( graph& g, small_object_allocator& allocator, NodeType &n )
0308 : graph_task(g, allocator), my_node(n) {}
0309
0310 task* execute(execution_data& ed) override {
0311 graph_task* next_task = my_node.apply_body_bypass( );
0312 if (SUCCESSFULLY_ENQUEUED == next_task)
0313 next_task = nullptr;
0314 else if (next_task)
0315 next_task = prioritize_task(my_node.graph_reference(), *next_task);
0316 finalize<input_node_task_bypass>(ed);
0317 return next_task;
0318 }
0319
0320 task* cancel(execution_data& ed) override {
0321 finalize<input_node_task_bypass>(ed);
0322 return nullptr;
0323 }
0324 };
0325
0326
0327
0328 template<typename T, typename DecrementType, typename DummyType = void>
0329 class threshold_regulator;
0330
0331 template<typename T, typename DecrementType>
0332 class threshold_regulator<T, DecrementType,
0333 typename std::enable_if<std::is_integral<DecrementType>::value>::type>
0334 : public receiver<DecrementType>, no_copy
0335 {
0336 T* my_node;
0337 protected:
0338
0339 graph_task* try_put_task( const DecrementType& value ) override {
0340 graph_task* result = my_node->decrement_counter( value );
0341 if( !result )
0342 result = SUCCESSFULLY_ENQUEUED;
0343 return result;
0344 }
0345
0346 graph& graph_reference() const override {
0347 return my_node->my_graph;
0348 }
0349
0350 template<typename U, typename V> friend class limiter_node;
0351 void reset_receiver( reset_flags ) {}
0352
0353 public:
0354 threshold_regulator(T* owner) : my_node(owner) {
0355
0356 }
0357 };
0358
0359 template<typename T>
0360 class threshold_regulator<T, continue_msg, void> : public continue_receiver, no_copy {
0361
0362 T *my_node;
0363
0364 graph_task* execute() override {
0365 return my_node->decrement_counter( 1 );
0366 }
0367
0368 protected:
0369
0370 graph& graph_reference() const override {
0371 return my_node->my_graph;
0372 }
0373
0374 public:
0375
0376 typedef continue_msg input_type;
0377 typedef continue_msg output_type;
0378 threshold_regulator(T* owner)
0379 : continue_receiver( 0, no_priority ), my_node(owner)
0380 {
0381
0382 }
0383 };
0384
0385 #endif