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_indexer_impl_H
0018 #define __TBB__flow_graph_indexer_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 #include "_flow_graph_types_impl.h"
0027
0028
0029
0030
0031
0032
0033 template<typename IndexerNodeBaseType, typename T, size_t K>
0034 graph_task* do_try_put(const T &v, void *p) {
0035 typename IndexerNodeBaseType::output_type o(K, v);
0036 return reinterpret_cast<IndexerNodeBaseType *>(p)->try_put_task(&o);
0037 }
0038
0039 template<typename TupleTypes,int N>
0040 struct indexer_helper {
0041 template<typename IndexerNodeBaseType, typename PortTuple>
0042 static inline void set_indexer_node_pointer(PortTuple &my_input, IndexerNodeBaseType *p, graph& g) {
0043 typedef typename std::tuple_element<N-1, TupleTypes>::type T;
0044 graph_task* (*indexer_node_put_task)(const T&, void *) = do_try_put<IndexerNodeBaseType, T, N-1>;
0045 std::get<N-1>(my_input).set_up(p, indexer_node_put_task, g);
0046 indexer_helper<TupleTypes,N-1>::template set_indexer_node_pointer<IndexerNodeBaseType,PortTuple>(my_input, p, g);
0047 }
0048 };
0049
0050 template<typename TupleTypes>
0051 struct indexer_helper<TupleTypes,1> {
0052 template<typename IndexerNodeBaseType, typename PortTuple>
0053 static inline void set_indexer_node_pointer(PortTuple &my_input, IndexerNodeBaseType *p, graph& g) {
0054 typedef typename std::tuple_element<0, TupleTypes>::type T;
0055 graph_task* (*indexer_node_put_task)(const T&, void *) = do_try_put<IndexerNodeBaseType, T, 0>;
0056 std::get<0>(my_input).set_up(p, indexer_node_put_task, g);
0057 }
0058 };
0059
0060 template<typename T>
0061 class indexer_input_port : public receiver<T> {
0062 private:
0063 void* my_indexer_ptr;
0064 typedef graph_task* (* forward_function_ptr)(T const &, void* );
0065 forward_function_ptr my_try_put_task;
0066 graph* my_graph;
0067 public:
0068 void set_up(void* p, forward_function_ptr f, graph& g) {
0069 my_indexer_ptr = p;
0070 my_try_put_task = f;
0071 my_graph = &g;
0072 }
0073
0074 protected:
0075 template< typename R, typename B > friend class run_and_put_task;
0076 template<typename X, typename Y> friend class broadcast_cache;
0077 template<typename X, typename Y> friend class round_robin_cache;
0078 graph_task* try_put_task(const T &v) override {
0079 return my_try_put_task(v, my_indexer_ptr);
0080 }
0081
0082 graph& graph_reference() const override {
0083 return *my_graph;
0084 }
0085 };
0086
0087 template<typename InputTuple, typename OutputType, typename StructTypes>
0088 class indexer_node_FE {
0089 public:
0090 static const int N = std::tuple_size<InputTuple>::value;
0091 typedef OutputType output_type;
0092 typedef InputTuple input_type;
0093
0094
0095 indexer_node_FE() : my_inputs() {}
0096
0097 input_type &input_ports() { return my_inputs; }
0098 protected:
0099 input_type my_inputs;
0100 };
0101
0102
0103 template<typename InputTuple, typename OutputType, typename StructTypes>
0104 class indexer_node_base : public graph_node, public indexer_node_FE<InputTuple, OutputType,StructTypes>,
0105 public sender<OutputType> {
0106 protected:
0107 using graph_node::my_graph;
0108 public:
0109 static const size_t N = std::tuple_size<InputTuple>::value;
0110 typedef OutputType output_type;
0111 typedef StructTypes tuple_types;
0112 typedef typename sender<output_type>::successor_type successor_type;
0113 typedef indexer_node_FE<InputTuple, output_type,StructTypes> input_ports_type;
0114
0115 private:
0116
0117 enum op_type { reg_succ, rem_succ, try__put_task
0118 };
0119 typedef indexer_node_base<InputTuple,output_type,StructTypes> class_type;
0120
0121 class indexer_node_base_operation : public aggregated_operation<indexer_node_base_operation> {
0122 public:
0123 char type;
0124 union {
0125 output_type const *my_arg;
0126 successor_type *my_succ;
0127 graph_task* bypass_t;
0128 };
0129 indexer_node_base_operation(const output_type* e, op_type t) :
0130 type(char(t)), my_arg(e) {}
0131 indexer_node_base_operation(const successor_type &s, op_type t) : type(char(t)),
0132 my_succ(const_cast<successor_type *>(&s)) {}
0133 };
0134
0135 typedef aggregating_functor<class_type, indexer_node_base_operation> handler_type;
0136 friend class aggregating_functor<class_type, indexer_node_base_operation>;
0137 aggregator<handler_type, indexer_node_base_operation> my_aggregator;
0138
0139 void handle_operations(indexer_node_base_operation* op_list) {
0140 indexer_node_base_operation *current;
0141 while(op_list) {
0142 current = op_list;
0143 op_list = op_list->next;
0144 switch(current->type) {
0145
0146 case reg_succ:
0147 my_successors.register_successor(*(current->my_succ));
0148 current->status.store( SUCCEEDED, std::memory_order_release);
0149 break;
0150
0151 case rem_succ:
0152 my_successors.remove_successor(*(current->my_succ));
0153 current->status.store( SUCCEEDED, std::memory_order_release);
0154 break;
0155 case try__put_task: {
0156 current->bypass_t = my_successors.try_put_task(*(current->my_arg));
0157 current->status.store( SUCCEEDED, std::memory_order_release);
0158 }
0159 break;
0160 }
0161 }
0162 }
0163
0164 public:
0165 indexer_node_base(graph& g) : graph_node(g), input_ports_type(), my_successors(this) {
0166 indexer_helper<StructTypes,N>::set_indexer_node_pointer(this->my_inputs, this, g);
0167 my_aggregator.initialize_handler(handler_type(this));
0168 }
0169
0170 indexer_node_base(const indexer_node_base& other)
0171 : graph_node(other.my_graph), input_ports_type(), sender<output_type>(), my_successors(this)
0172 {
0173 indexer_helper<StructTypes,N>::set_indexer_node_pointer(this->my_inputs, this, other.my_graph);
0174 my_aggregator.initialize_handler(handler_type(this));
0175 }
0176
0177 bool register_successor(successor_type &r) override {
0178 indexer_node_base_operation op_data(r, reg_succ);
0179 my_aggregator.execute(&op_data);
0180 return op_data.status == SUCCEEDED;
0181 }
0182
0183 bool remove_successor( successor_type &r) override {
0184 indexer_node_base_operation op_data(r, rem_succ);
0185 my_aggregator.execute(&op_data);
0186 return op_data.status == SUCCEEDED;
0187 }
0188
0189 graph_task* try_put_task(output_type const *v) {
0190 indexer_node_base_operation op_data(v, try__put_task);
0191 my_aggregator.execute(&op_data);
0192 return op_data.bypass_t;
0193 }
0194
0195 protected:
0196 void reset_node(reset_flags f) override {
0197 if(f & rf_clear_edges) {
0198 my_successors.clear();
0199 }
0200 }
0201
0202 private:
0203 broadcast_cache<output_type, null_rw_mutex> my_successors;
0204 };
0205
0206
0207 template<int N, typename InputTuple> struct input_types;
0208
0209 template<typename InputTuple>
0210 struct input_types<1, InputTuple> {
0211 typedef typename std::tuple_element<0, InputTuple>::type first_type;
0212 typedef tagged_msg<size_t, first_type > type;
0213 };
0214
0215 template<typename InputTuple>
0216 struct input_types<2, InputTuple> {
0217 typedef typename std::tuple_element<0, InputTuple>::type first_type;
0218 typedef typename std::tuple_element<1, InputTuple>::type second_type;
0219 typedef tagged_msg<size_t, first_type, second_type> type;
0220 };
0221
0222 template<typename InputTuple>
0223 struct input_types<3, InputTuple> {
0224 typedef typename std::tuple_element<0, InputTuple>::type first_type;
0225 typedef typename std::tuple_element<1, InputTuple>::type second_type;
0226 typedef typename std::tuple_element<2, InputTuple>::type third_type;
0227 typedef tagged_msg<size_t, first_type, second_type, third_type> type;
0228 };
0229
0230 template<typename InputTuple>
0231 struct input_types<4, InputTuple> {
0232 typedef typename std::tuple_element<0, InputTuple>::type first_type;
0233 typedef typename std::tuple_element<1, InputTuple>::type second_type;
0234 typedef typename std::tuple_element<2, InputTuple>::type third_type;
0235 typedef typename std::tuple_element<3, InputTuple>::type fourth_type;
0236 typedef tagged_msg<size_t, first_type, second_type, third_type,
0237 fourth_type> type;
0238 };
0239
0240 template<typename InputTuple>
0241 struct input_types<5, InputTuple> {
0242 typedef typename std::tuple_element<0, InputTuple>::type first_type;
0243 typedef typename std::tuple_element<1, InputTuple>::type second_type;
0244 typedef typename std::tuple_element<2, InputTuple>::type third_type;
0245 typedef typename std::tuple_element<3, InputTuple>::type fourth_type;
0246 typedef typename std::tuple_element<4, InputTuple>::type fifth_type;
0247 typedef tagged_msg<size_t, first_type, second_type, third_type,
0248 fourth_type, fifth_type> type;
0249 };
0250
0251 template<typename InputTuple>
0252 struct input_types<6, InputTuple> {
0253 typedef typename std::tuple_element<0, InputTuple>::type first_type;
0254 typedef typename std::tuple_element<1, InputTuple>::type second_type;
0255 typedef typename std::tuple_element<2, InputTuple>::type third_type;
0256 typedef typename std::tuple_element<3, InputTuple>::type fourth_type;
0257 typedef typename std::tuple_element<4, InputTuple>::type fifth_type;
0258 typedef typename std::tuple_element<5, InputTuple>::type sixth_type;
0259 typedef tagged_msg<size_t, first_type, second_type, third_type,
0260 fourth_type, fifth_type, sixth_type> type;
0261 };
0262
0263 template<typename InputTuple>
0264 struct input_types<7, InputTuple> {
0265 typedef typename std::tuple_element<0, InputTuple>::type first_type;
0266 typedef typename std::tuple_element<1, InputTuple>::type second_type;
0267 typedef typename std::tuple_element<2, InputTuple>::type third_type;
0268 typedef typename std::tuple_element<3, InputTuple>::type fourth_type;
0269 typedef typename std::tuple_element<4, InputTuple>::type fifth_type;
0270 typedef typename std::tuple_element<5, InputTuple>::type sixth_type;
0271 typedef typename std::tuple_element<6, InputTuple>::type seventh_type;
0272 typedef tagged_msg<size_t, first_type, second_type, third_type,
0273 fourth_type, fifth_type, sixth_type,
0274 seventh_type> type;
0275 };
0276
0277
0278 template<typename InputTuple>
0279 struct input_types<8, InputTuple> {
0280 typedef typename std::tuple_element<0, InputTuple>::type first_type;
0281 typedef typename std::tuple_element<1, InputTuple>::type second_type;
0282 typedef typename std::tuple_element<2, InputTuple>::type third_type;
0283 typedef typename std::tuple_element<3, InputTuple>::type fourth_type;
0284 typedef typename std::tuple_element<4, InputTuple>::type fifth_type;
0285 typedef typename std::tuple_element<5, InputTuple>::type sixth_type;
0286 typedef typename std::tuple_element<6, InputTuple>::type seventh_type;
0287 typedef typename std::tuple_element<7, InputTuple>::type eighth_type;
0288 typedef tagged_msg<size_t, first_type, second_type, third_type,
0289 fourth_type, fifth_type, sixth_type,
0290 seventh_type, eighth_type> type;
0291 };
0292
0293
0294 template<typename InputTuple>
0295 struct input_types<9, InputTuple> {
0296 typedef typename std::tuple_element<0, InputTuple>::type first_type;
0297 typedef typename std::tuple_element<1, InputTuple>::type second_type;
0298 typedef typename std::tuple_element<2, InputTuple>::type third_type;
0299 typedef typename std::tuple_element<3, InputTuple>::type fourth_type;
0300 typedef typename std::tuple_element<4, InputTuple>::type fifth_type;
0301 typedef typename std::tuple_element<5, InputTuple>::type sixth_type;
0302 typedef typename std::tuple_element<6, InputTuple>::type seventh_type;
0303 typedef typename std::tuple_element<7, InputTuple>::type eighth_type;
0304 typedef typename std::tuple_element<8, InputTuple>::type nineth_type;
0305 typedef tagged_msg<size_t, first_type, second_type, third_type,
0306 fourth_type, fifth_type, sixth_type,
0307 seventh_type, eighth_type, nineth_type> type;
0308 };
0309
0310 template<typename InputTuple>
0311 struct input_types<10, InputTuple> {
0312 typedef typename std::tuple_element<0, InputTuple>::type first_type;
0313 typedef typename std::tuple_element<1, InputTuple>::type second_type;
0314 typedef typename std::tuple_element<2, InputTuple>::type third_type;
0315 typedef typename std::tuple_element<3, InputTuple>::type fourth_type;
0316 typedef typename std::tuple_element<4, InputTuple>::type fifth_type;
0317 typedef typename std::tuple_element<5, InputTuple>::type sixth_type;
0318 typedef typename std::tuple_element<6, InputTuple>::type seventh_type;
0319 typedef typename std::tuple_element<7, InputTuple>::type eighth_type;
0320 typedef typename std::tuple_element<8, InputTuple>::type nineth_type;
0321 typedef typename std::tuple_element<9, InputTuple>::type tenth_type;
0322 typedef tagged_msg<size_t, first_type, second_type, third_type,
0323 fourth_type, fifth_type, sixth_type,
0324 seventh_type, eighth_type, nineth_type,
0325 tenth_type> type;
0326 };
0327
0328
0329 template<typename OutputTuple>
0330 struct indexer_types : public input_types<std::tuple_size<OutputTuple>::value, OutputTuple> {
0331 static const int N = std::tuple_size<OutputTuple>::value;
0332 typedef typename input_types<N, OutputTuple>::type output_type;
0333 typedef typename wrap_tuple_elements<N,indexer_input_port,OutputTuple>::type input_ports_type;
0334 typedef indexer_node_FE<input_ports_type,output_type,OutputTuple> indexer_FE_type;
0335 typedef indexer_node_base<input_ports_type, output_type, OutputTuple> indexer_base_type;
0336 };
0337
0338 template<class OutputTuple>
0339 class unfolded_indexer_node : public indexer_types<OutputTuple>::indexer_base_type {
0340 public:
0341 typedef typename indexer_types<OutputTuple>::input_ports_type input_ports_type;
0342 typedef OutputTuple tuple_types;
0343 typedef typename indexer_types<OutputTuple>::output_type output_type;
0344 private:
0345 typedef typename indexer_types<OutputTuple>::indexer_base_type base_type;
0346 public:
0347 unfolded_indexer_node(graph& g) : base_type(g) {}
0348 unfolded_indexer_node(const unfolded_indexer_node &other) : base_type(other) {}
0349 };
0350
0351 #endif