Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:12:46

0001 /*
0002     Copyright (c) 2005-2020 Intel Corporation
0003 
0004     Licensed under the Apache License, Version 2.0 (the "License");
0005     you may not use this file except in compliance with the License.
0006     You may obtain a copy of the License at
0007 
0008         http://www.apache.org/licenses/LICENSE-2.0
0009 
0010     Unless required by applicable law or agreed to in writing, software
0011     distributed under the License is distributed on an "AS IS" BASIS,
0012     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013     See the License for the specific language governing permissions and
0014     limitations under the License.
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 // included in namespace tbb::flow::interfaceX (in flow_graph.h)
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     // K == type of field used for key-matching.  Each tag-matching port will be provided
0076     // functor that, given an object accepted by the port, will return the
0077     /// field of type K being used for matching.
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     // old tag_matching join's new specifier
0086     typedef key_matching<tag_value> tag_matching;
0087 
0088     // Aliases for Policy combinations
0089     typedef interface11::internal::Policy<queueing, lightweight> queueing_lightweight;
0090     typedef interface11::internal::Policy<rejecting, lightweight>  rejecting_lightweight;
0091 
0092 } // namespace graph_policy_namespace
0093 
0094 // -------------- function_body containers ----------------------
0095 //! A functor that takes no input and generates a value of type Output
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 //! The leaf for input_body
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 //! The leaf for source_body
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 //! A functor that takes an Input and generates an Output
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 //! the leaf for function_body
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 //! the leaf for function_body specialized for Input and output of continue_msg
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 //! the leaf for function_body specialized for Output of continue_msg
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 //! the leaf for function_body specialized for Input of continue_msg
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 //! function_body that takes an Input and a set of output ports
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 &/* input*/, OutputSet &/*oset*/) = 0;
0254     virtual multifunction_body* clone() = 0;
0255     virtual void* get_body_ptr() = 0;
0256 };
0257 
0258 //! leaf for multifunction.  OutputSet can be a std::tuple or a vector.
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); // body may explicitly put() to one or more of 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 // ------ function bodies for hash_buffers and key-matching joins.
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;  // returns an Output
0282         virtual type_to_key_function_body* clone() = 0;
0283 };
0284 
0285 // specialization for ref output
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;  // returns a const Output&
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 // --------------------------- end of function_body containers ------------------------
0323 
0324 // --------------------------- node task bodies ---------------------------------------
0325 
0326 //! A task that calls a node's forward_task function
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 //! A task that calls a node's apply_body_bypass function, passing in an input of type Input
0351 //  return the task* unless it is SUCCESSFULLY_ENQUEUED, in which case return NULL
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 //! A task that calls a node's apply_body_bypass function with no input
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 // ------------------------ end of node task bodies -----------------------------------
0394 
0395 //! An empty functor that takes an Input and returns a default constructed Output
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     // Since decrementer does not make use of possibly unconstructed owner inside its
0435     // constructor, my_node can be directly initialized with 'this' pointer passed from the
0436     // owner, hence making method 'set_owner' needless.
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     //! The predecessor type for this node
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  /* TBB_DEPRECATED_FLOW_NODE_EXTRACTION */
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           // Since decrementer does not make use of possibly unconstructed owner inside its
0497           // constructor, my_node can be directly initialized with 'this' pointer passed from the
0498           // owner, hence making method 'set_owner' needless.
0499         , my_node(NULL)
0500     {}
0501     void set_owner( T *node ) { my_node = node; }
0502 };
0503 
0504 } // namespace internal
0505 
0506 #endif // __TBB__flow_graph_body_impl_H
0507