1 /* 2 Copyright (c) 2005-2021 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 #ifndef __TBB__flow_graph_indexer_impl_H 18 #define __TBB__flow_graph_indexer_impl_H 19 20 #ifndef __TBB_flow_graph_H 21 #error Do not #include this internal file directly; use public TBB headers instead. 22 #endif 23 24 // included in namespace tbb::detail::d1 25 26 #include "_flow_graph_types_impl.h" 27 28 // Output of the indexer_node is a tbb::flow::tagged_msg, and will be of 29 // the form tagged_msg<tag, result> 30 // where the value of tag will indicate which result was put to the 31 // successor. 32 33 template<typename IndexerNodeBaseType, typename T, size_t K> do_try_put(const T & v,void * p)34 graph_task* do_try_put(const T &v, void *p) { 35 typename IndexerNodeBaseType::output_type o(K, v); 36 return reinterpret_cast<IndexerNodeBaseType *>(p)->try_put_task(&o); 37 } 38 39 template<typename TupleTypes,int N> 40 struct indexer_helper { 41 template<typename IndexerNodeBaseType, typename PortTuple> set_indexer_node_pointerindexer_helper42 static inline void set_indexer_node_pointer(PortTuple &my_input, IndexerNodeBaseType *p, graph& g) { 43 typedef typename std::tuple_element<N-1, TupleTypes>::type T; 44 graph_task* (*indexer_node_put_task)(const T&, void *) = do_try_put<IndexerNodeBaseType, T, N-1>; 45 std::get<N-1>(my_input).set_up(p, indexer_node_put_task, g); 46 indexer_helper<TupleTypes,N-1>::template set_indexer_node_pointer<IndexerNodeBaseType,PortTuple>(my_input, p, g); 47 } 48 }; 49 50 template<typename TupleTypes> 51 struct indexer_helper<TupleTypes,1> { 52 template<typename IndexerNodeBaseType, typename PortTuple> 53 static inline void set_indexer_node_pointer(PortTuple &my_input, IndexerNodeBaseType *p, graph& g) { 54 typedef typename std::tuple_element<0, TupleTypes>::type T; 55 graph_task* (*indexer_node_put_task)(const T&, void *) = do_try_put<IndexerNodeBaseType, T, 0>; 56 std::get<0>(my_input).set_up(p, indexer_node_put_task, g); 57 } 58 }; 59 60 template<typename T> 61 class indexer_input_port : public receiver<T> { 62 private: 63 void* my_indexer_ptr; 64 typedef graph_task* (* forward_function_ptr)(T const &, void* ); 65 forward_function_ptr my_try_put_task; 66 graph* my_graph; 67 public: 68 void set_up(void* p, forward_function_ptr f, graph& g) { 69 my_indexer_ptr = p; 70 my_try_put_task = f; 71 my_graph = &g; 72 } 73 74 protected: 75 template< typename R, typename B > friend class run_and_put_task; 76 template<typename X, typename Y> friend class broadcast_cache; 77 template<typename X, typename Y> friend class round_robin_cache; 78 graph_task* try_put_task(const T &v) override { 79 return my_try_put_task(v, my_indexer_ptr); 80 } 81 82 graph& graph_reference() const override { 83 return *my_graph; 84 } 85 }; 86 87 template<typename InputTuple, typename OutputType, typename StructTypes> 88 class indexer_node_FE { 89 public: 90 static const int N = std::tuple_size<InputTuple>::value; 91 typedef OutputType output_type; 92 typedef InputTuple input_type; 93 94 // Some versions of Intel(R) C++ Compiler fail to generate an implicit constructor for the class which has std::tuple as a member. 95 indexer_node_FE() : my_inputs() {} 96 97 input_type &input_ports() { return my_inputs; } 98 protected: 99 input_type my_inputs; 100 }; 101 102 //! indexer_node_base 103 template<typename InputTuple, typename OutputType, typename StructTypes> 104 class indexer_node_base : public graph_node, public indexer_node_FE<InputTuple, OutputType,StructTypes>, 105 public sender<OutputType> { 106 protected: 107 using graph_node::my_graph; 108 public: 109 static const size_t N = std::tuple_size<InputTuple>::value; 110 typedef OutputType output_type; 111 typedef StructTypes tuple_types; 112 typedef typename sender<output_type>::successor_type successor_type; 113 typedef indexer_node_FE<InputTuple, output_type,StructTypes> input_ports_type; 114 115 private: 116 // ----------- Aggregator ------------ 117 enum op_type { reg_succ, rem_succ, try__put_task 118 }; 119 typedef indexer_node_base<InputTuple,output_type,StructTypes> class_type; 120 121 class indexer_node_base_operation : public aggregated_operation<indexer_node_base_operation> { 122 public: 123 char type; 124 union { 125 output_type const *my_arg; 126 successor_type *my_succ; 127 graph_task* bypass_t; 128 }; 129 indexer_node_base_operation(const output_type* e, op_type t) : 130 type(char(t)), my_arg(e) {} 131 indexer_node_base_operation(const successor_type &s, op_type t) : type(char(t)), 132 my_succ(const_cast<successor_type *>(&s)) {} 133 }; 134 135 typedef aggregating_functor<class_type, indexer_node_base_operation> handler_type; 136 friend class aggregating_functor<class_type, indexer_node_base_operation>; 137 aggregator<handler_type, indexer_node_base_operation> my_aggregator; 138 139 void handle_operations(indexer_node_base_operation* op_list) { 140 indexer_node_base_operation *current; 141 while(op_list) { 142 current = op_list; 143 op_list = op_list->next; 144 switch(current->type) { 145 146 case reg_succ: 147 my_successors.register_successor(*(current->my_succ)); 148 current->status.store( SUCCEEDED, std::memory_order_release); 149 break; 150 151 case rem_succ: 152 my_successors.remove_successor(*(current->my_succ)); 153 current->status.store( SUCCEEDED, std::memory_order_release); 154 break; 155 case try__put_task: { 156 current->bypass_t = my_successors.try_put_task(*(current->my_arg)); 157 current->status.store( SUCCEEDED, std::memory_order_release); // return of try_put_task actual return value 158 } 159 break; 160 } 161 } 162 } 163 // ---------- end aggregator ----------- 164 public: 165 indexer_node_base(graph& g) : graph_node(g), input_ports_type(), my_successors(this) { 166 indexer_helper<StructTypes,N>::set_indexer_node_pointer(this->my_inputs, this, g); 167 my_aggregator.initialize_handler(handler_type(this)); 168 } 169 170 indexer_node_base(const indexer_node_base& other) 171 : graph_node(other.my_graph), input_ports_type(), sender<output_type>(), my_successors(this) 172 { 173 indexer_helper<StructTypes,N>::set_indexer_node_pointer(this->my_inputs, this, other.my_graph); 174 my_aggregator.initialize_handler(handler_type(this)); 175 } 176 177 bool register_successor(successor_type &r) override { 178 indexer_node_base_operation op_data(r, reg_succ); 179 my_aggregator.execute(&op_data); 180 return op_data.status == SUCCEEDED; 181 } 182 183 bool remove_successor( successor_type &r) override { 184 indexer_node_base_operation op_data(r, rem_succ); 185 my_aggregator.execute(&op_data); 186 return op_data.status == SUCCEEDED; 187 } 188 189 graph_task* try_put_task(output_type const *v) { // not a virtual method in this class 190 indexer_node_base_operation op_data(v, try__put_task); 191 my_aggregator.execute(&op_data); 192 return op_data.bypass_t; 193 } 194 195 protected: 196 void reset_node(reset_flags f) override { 197 if(f & rf_clear_edges) { 198 my_successors.clear(); 199 } 200 } 201 202 private: 203 broadcast_cache<output_type, null_rw_mutex> my_successors; 204 }; //indexer_node_base 205 206 207 template<int N, typename InputTuple> struct input_types; 208 209 template<typename InputTuple> 210 struct input_types<1, InputTuple> { 211 typedef typename std::tuple_element<0, InputTuple>::type first_type; 212 typedef tagged_msg<size_t, first_type > type; 213 }; 214 215 template<typename InputTuple> 216 struct input_types<2, InputTuple> { 217 typedef typename std::tuple_element<0, InputTuple>::type first_type; 218 typedef typename std::tuple_element<1, InputTuple>::type second_type; 219 typedef tagged_msg<size_t, first_type, second_type> type; 220 }; 221 222 template<typename InputTuple> 223 struct input_types<3, InputTuple> { 224 typedef typename std::tuple_element<0, InputTuple>::type first_type; 225 typedef typename std::tuple_element<1, InputTuple>::type second_type; 226 typedef typename std::tuple_element<2, InputTuple>::type third_type; 227 typedef tagged_msg<size_t, first_type, second_type, third_type> type; 228 }; 229 230 template<typename InputTuple> 231 struct input_types<4, InputTuple> { 232 typedef typename std::tuple_element<0, InputTuple>::type first_type; 233 typedef typename std::tuple_element<1, InputTuple>::type second_type; 234 typedef typename std::tuple_element<2, InputTuple>::type third_type; 235 typedef typename std::tuple_element<3, InputTuple>::type fourth_type; 236 typedef tagged_msg<size_t, first_type, second_type, third_type, 237 fourth_type> type; 238 }; 239 240 template<typename InputTuple> 241 struct input_types<5, InputTuple> { 242 typedef typename std::tuple_element<0, InputTuple>::type first_type; 243 typedef typename std::tuple_element<1, InputTuple>::type second_type; 244 typedef typename std::tuple_element<2, InputTuple>::type third_type; 245 typedef typename std::tuple_element<3, InputTuple>::type fourth_type; 246 typedef typename std::tuple_element<4, InputTuple>::type fifth_type; 247 typedef tagged_msg<size_t, first_type, second_type, third_type, 248 fourth_type, fifth_type> type; 249 }; 250 251 template<typename InputTuple> 252 struct input_types<6, InputTuple> { 253 typedef typename std::tuple_element<0, InputTuple>::type first_type; 254 typedef typename std::tuple_element<1, InputTuple>::type second_type; 255 typedef typename std::tuple_element<2, InputTuple>::type third_type; 256 typedef typename std::tuple_element<3, InputTuple>::type fourth_type; 257 typedef typename std::tuple_element<4, InputTuple>::type fifth_type; 258 typedef typename std::tuple_element<5, InputTuple>::type sixth_type; 259 typedef tagged_msg<size_t, first_type, second_type, third_type, 260 fourth_type, fifth_type, sixth_type> type; 261 }; 262 263 template<typename InputTuple> 264 struct input_types<7, InputTuple> { 265 typedef typename std::tuple_element<0, InputTuple>::type first_type; 266 typedef typename std::tuple_element<1, InputTuple>::type second_type; 267 typedef typename std::tuple_element<2, InputTuple>::type third_type; 268 typedef typename std::tuple_element<3, InputTuple>::type fourth_type; 269 typedef typename std::tuple_element<4, InputTuple>::type fifth_type; 270 typedef typename std::tuple_element<5, InputTuple>::type sixth_type; 271 typedef typename std::tuple_element<6, InputTuple>::type seventh_type; 272 typedef tagged_msg<size_t, first_type, second_type, third_type, 273 fourth_type, fifth_type, sixth_type, 274 seventh_type> type; 275 }; 276 277 278 template<typename InputTuple> 279 struct input_types<8, InputTuple> { 280 typedef typename std::tuple_element<0, InputTuple>::type first_type; 281 typedef typename std::tuple_element<1, InputTuple>::type second_type; 282 typedef typename std::tuple_element<2, InputTuple>::type third_type; 283 typedef typename std::tuple_element<3, InputTuple>::type fourth_type; 284 typedef typename std::tuple_element<4, InputTuple>::type fifth_type; 285 typedef typename std::tuple_element<5, InputTuple>::type sixth_type; 286 typedef typename std::tuple_element<6, InputTuple>::type seventh_type; 287 typedef typename std::tuple_element<7, InputTuple>::type eighth_type; 288 typedef tagged_msg<size_t, first_type, second_type, third_type, 289 fourth_type, fifth_type, sixth_type, 290 seventh_type, eighth_type> type; 291 }; 292 293 294 template<typename InputTuple> 295 struct input_types<9, InputTuple> { 296 typedef typename std::tuple_element<0, InputTuple>::type first_type; 297 typedef typename std::tuple_element<1, InputTuple>::type second_type; 298 typedef typename std::tuple_element<2, InputTuple>::type third_type; 299 typedef typename std::tuple_element<3, InputTuple>::type fourth_type; 300 typedef typename std::tuple_element<4, InputTuple>::type fifth_type; 301 typedef typename std::tuple_element<5, InputTuple>::type sixth_type; 302 typedef typename std::tuple_element<6, InputTuple>::type seventh_type; 303 typedef typename std::tuple_element<7, InputTuple>::type eighth_type; 304 typedef typename std::tuple_element<8, InputTuple>::type nineth_type; 305 typedef tagged_msg<size_t, first_type, second_type, third_type, 306 fourth_type, fifth_type, sixth_type, 307 seventh_type, eighth_type, nineth_type> type; 308 }; 309 310 template<typename InputTuple> 311 struct input_types<10, InputTuple> { 312 typedef typename std::tuple_element<0, InputTuple>::type first_type; 313 typedef typename std::tuple_element<1, InputTuple>::type second_type; 314 typedef typename std::tuple_element<2, InputTuple>::type third_type; 315 typedef typename std::tuple_element<3, InputTuple>::type fourth_type; 316 typedef typename std::tuple_element<4, InputTuple>::type fifth_type; 317 typedef typename std::tuple_element<5, InputTuple>::type sixth_type; 318 typedef typename std::tuple_element<6, InputTuple>::type seventh_type; 319 typedef typename std::tuple_element<7, InputTuple>::type eighth_type; 320 typedef typename std::tuple_element<8, InputTuple>::type nineth_type; 321 typedef typename std::tuple_element<9, InputTuple>::type tenth_type; 322 typedef tagged_msg<size_t, first_type, second_type, third_type, 323 fourth_type, fifth_type, sixth_type, 324 seventh_type, eighth_type, nineth_type, 325 tenth_type> type; 326 }; 327 328 // type generators 329 template<typename OutputTuple> 330 struct indexer_types : public input_types<std::tuple_size<OutputTuple>::value, OutputTuple> { 331 static const int N = std::tuple_size<OutputTuple>::value; 332 typedef typename input_types<N, OutputTuple>::type output_type; 333 typedef typename wrap_tuple_elements<N,indexer_input_port,OutputTuple>::type input_ports_type; 334 typedef indexer_node_FE<input_ports_type,output_type,OutputTuple> indexer_FE_type; 335 typedef indexer_node_base<input_ports_type, output_type, OutputTuple> indexer_base_type; 336 }; 337 338 template<class OutputTuple> 339 class unfolded_indexer_node : public indexer_types<OutputTuple>::indexer_base_type { 340 public: 341 typedef typename indexer_types<OutputTuple>::input_ports_type input_ports_type; 342 typedef OutputTuple tuple_types; 343 typedef typename indexer_types<OutputTuple>::output_type output_type; 344 private: 345 typedef typename indexer_types<OutputTuple>::indexer_base_type base_type; 346 public: 347 unfolded_indexer_node(graph& g) : base_type(g) {} 348 unfolded_indexer_node(const unfolded_indexer_node &other) : base_type(other) {} 349 }; 350 351 #endif /* __TBB__flow_graph_indexer_impl_H */ 352