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");
}
Exemplo n.º 2
0
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?");
}