Resource Limiting in the Flow Graph

Resource Limiting in the Flow Graph#

Note

To enable this feature, set the TBB_PREVIEW_FLOW_GRAPH_RESOURCE_LIMITING or TBB_PREVIEW_FLOW_GRAPH_FEATURES macro to 1.

Description#

The Resource Limiting feature enables Flow Graph nodes to safely coordinate access to shared external resources such as database connections, thread-unsafe libraries, etc.

The feature consists of two components:

  • flow::resource_limiter class - a provider that manages a set of resources.

  • flow::resource_limited_node class - a consumer node whose body is invoked only after the node acquires access to a resource from each associated resource_limiter.

API#

Example#

In the example below, two nodes share an exclusive database connection through a resource_limiter managing a single handle:

#define TBB_PREVIEW_FLOW_GRAPH_RESOURCE_LIMITING 1
#include <oneapi/tbb/flow_graph.h>

int main() {
    using namespace tbb::flow;

    resource_limiter<DB_handle*> db_limiter{open_database()};

    graph g;

    using resource_limited_node_type = resource_limited_node<int, std::tuple<int>>;

    // Concurrency is unlimited, but db_limiter ensures exclusive DB access
    resource_limited_node_type db_reader(g, unlimited,
        std::tie(db_limiter),
        [](int id, auto& ports, DB_handle* db) {
            db->read();
            // other actions with the data read from db
            std::get<0>(ports).try_put(id);
        });

    function_node<int, int> processor(g, unlimited, processor_body{});

    resource_limited_node_type db_writer(g, unlimited,
        std::tie(db_limiter),
        [](int id, auto& ports, DB_handle* db) {
            // other actions with the database
            db->write();
            std::get<0>(ports).try_put(id);
        }
    );

    make_edge(output_port<0>(db_reader), processor);
    make_edge(processor, db_writer);
    // Other graph nodes and edges

    for (int id : input_ids) {
        db_reader.try_put(id);
    }

    g.wait_for_all();
}

Because db_limiter holds only one resource handle, the bodies of db_reader and db_writer are never invoked at the same time - even though both nodes allow unlimited concurrency.