void run_function() { ASSERT(!filter_node_count, NULL); const size_t number_of_filters = 3; input_filter<type1> i_filter; middle_filter<type1, type2> m_filter; output_filter<type2> o_filter; unsigned limit = 1; // Test pipeline that contains number_of_filters filters for( unsigned i=0; i<number_of_filters; ++i) limit *= number_of_filter_types; // Iterate over possible filter sequences for( unsigned numeral=0; numeral<limit; ++numeral ) { unsigned temp = numeral; tbb::filter::mode filter_type[number_of_filter_types]; for( unsigned i=0; i<number_of_filters; ++i, temp/=number_of_filter_types ) filter_type[i] = filter_table[temp%number_of_filter_types]; tbb::filter_t<void, type1> filter1( filter_type[0], i_filter ); tbb::filter_t<type1, type2> filter2( filter_type[1], m_filter ); tbb::filter_t<type2, void> filter3( filter_type[2], o_filter ); ASSERT(filter_node_count==3, "some filter nodes left after previous iteration?"); // Create filters sequence when parallel_pipeline() is being run tbb::parallel_pipeline( n_tokens, filter1 & filter2 & filter3 ); check_and_reset(); // Create filters sequence partially outside parallel_pipeline() and also when parallel_pipeline() is being run tbb::filter_t<void, type2> filter12; filter12 = filter1 & filter2; tbb::parallel_pipeline( n_tokens, filter12 & filter3 ); check_and_reset(); tbb::filter_t<void, void> filter123 = filter12 & filter3; // Run pipeline twice with the same filter sequence for( unsigned i = 0; i<2; i++ ) { tbb::parallel_pipeline( n_tokens, filter123 ); check_and_reset(); } // Now copy-construct another filter_t instance, and use it to run pipeline { tbb::filter_t<void, void> copy123( filter123 ); tbb::parallel_pipeline( n_tokens, copy123 ); check_and_reset(); } // Construct filters and create the sequence when parallel_pipeline() is being run tbb::parallel_pipeline( n_tokens, tbb::make_filter<void, type1>(filter_type[0], i_filter) & tbb::make_filter<type1, type2>(filter_type[1], m_filter) & tbb::make_filter<type2, void>(filter_type[2], o_filter) ); check_and_reset(); // Construct filters, make a copy, destroy the original filters, and run with the copy int cnt = filter_node_count; { tbb::filter_t<void, void>* p123 = new tbb::filter_t<void,void> ( tbb::make_filter<void, type1>(filter_type[0], i_filter) & tbb::make_filter<type1, type2>(filter_type[1], m_filter) & tbb::make_filter<type2, void>(filter_type[2], o_filter) ); ASSERT(filter_node_count==cnt+5, "filter node accounting error?"); tbb::filter_t<void, void> copy123( *p123 ); delete p123; ASSERT(filter_node_count==cnt+5, "filter nodes deleted prematurely?"); tbb::parallel_pipeline( n_tokens, copy123 ); check_and_reset(); } ASSERT(filter_node_count==cnt, "scope ended but filter nodes not deleted?"); #if __TBB_LAMBDAS_PRESENT tbb::atomic<int> counter; counter = max_counter; // Construct filters using lambda-syntax and create the sequence when parallel_pipeline() is being run; tbb::parallel_pipeline( n_tokens, tbb::make_filter<void, type1>(filter_type[0], [&counter]( tbb::flow_control& control ) -> type1 { if( --counter < 0 ) control.stop(); return type1(); } ) & tbb::make_filter<type1, type2>(filter_type[1], []( type1 /*my_storage*/ ) -> type2 { return type2(); } ) & tbb::make_filter<type2, void>(filter_type[2], [] ( type2 ) -> void { tmp_counter++; } ) ); check_and_reset(); #endif } ASSERT(!filter_node_count, "filter_node objects leaked"); }
void run_filter_set( input_filter<t1>& i_filter, middle_filter<t1,t2>& m_filter, output_filter<t2>& o_filter, mode_array *filter_type, final_assert_type my_t) { tbb::filter_t<void, t1> filter1( filter_type[0], i_filter ); tbb::filter_t<t1, t2> filter2( filter_type[1], m_filter ); tbb::filter_t<t2, void> filter3( filter_type[2], o_filter ); ASSERT(filter_node_count==3, "some filter nodes left after previous iteration?"); resetCounters(); // Create filters sequence when parallel_pipeline() is being run tbb::parallel_pipeline( n_tokens, filter1 & filter2 & filter3 ); checkCounters(my_t); // Create filters sequence partially outside parallel_pipeline() and also when parallel_pipeline() is being run tbb::filter_t<void, t2> filter12; filter12 = filter1 & filter2; resetCounters(); tbb::parallel_pipeline( n_tokens, filter12 & filter3 ); checkCounters(my_t); tbb::filter_t<void, void> filter123 = filter12 & filter3; // Run pipeline twice with the same filter sequence for( unsigned i = 0; i<2; i++ ) { resetCounters(); tbb::parallel_pipeline( n_tokens, filter123 ); checkCounters(my_t); } // Now copy-construct another filter_t instance, and use it to run pipeline { tbb::filter_t<void, void> copy123( filter123 ); resetCounters(); tbb::parallel_pipeline( n_tokens, copy123 ); checkCounters(my_t); } // Construct filters and create the sequence when parallel_pipeline() is being run resetCounters(); tbb::parallel_pipeline( n_tokens, tbb::make_filter<void, t1>(filter_type[0], i_filter) & tbb::make_filter<t1, t2>(filter_type[1], m_filter) & tbb::make_filter<t2, void>(filter_type[2], o_filter) ); checkCounters(my_t); // Construct filters, make a copy, destroy the original filters, and run with the copy int cnt = filter_node_count; { tbb::filter_t<void, void>* p123 = new tbb::filter_t<void,void> ( tbb::make_filter<void, t1>(filter_type[0], i_filter) & tbb::make_filter<t1, t2>(filter_type[1], m_filter) & tbb::make_filter<t2, void>(filter_type[2], o_filter) ); ASSERT(filter_node_count==cnt+5, "filter node accounting error?"); tbb::filter_t<void, void> copy123( *p123 ); delete p123; ASSERT(filter_node_count==cnt+5, "filter nodes deleted prematurely?"); resetCounters(); tbb::parallel_pipeline( n_tokens, copy123 ); checkCounters(my_t); } // construct a filter with temporaries { tbb::filter_t<void, void> my_filter; fill_chain<t1,t2>( my_filter, filter_type, i_filter, m_filter, o_filter ); resetCounters(); tbb::parallel_pipeline( n_tokens, my_filter ); checkCounters(my_t); } ASSERT(filter_node_count==cnt, "scope ended but filter nodes not deleted?"); }