0

我正在尝试为 Flow Graph 编写一个适配器,该适配器模仿类似管道的同步函数调用。但我不明白如何阻止并等待特定令牌的输出。调用wait_for_all图表并没有帮助,因为我不需要等待所有值。有人可以提出解决方案吗?

template <typename TOutput, typename TInput>
class FlowPathAdapter {
public:
    TOutput operator()(const TInput& val) {
        m_input->try_put(val);
        TOutput result;
        // What should be done here to ensure that
        // m_output returns the result corresponding to this specific token?
        m_output->try_get(result);
        return result;
    }

private:
    // input and output are connected in some graph constructed outside the adapter
    std::shared_ptr<tbb::flow::receiver<TInput>> m_input;
    std::shared_ptr<tbb::flow::sender<TOutput>> m_output;
};
4

2 回答 2

0

TBB 中一般避免等待;等待是非生产性的。

TBB 中任务执行的时间也不能保证,因为我们依赖于操作系统进行调度。也就是说,在转发来自节点的消息之后,不会发生诸如原子操作之类的带外信令,因此结果不会准备好。您还必须使用一个queue_node或其他缓冲节点来保存结果。

鉴于此,如果您希望进行显式等待,您可以制作 afunction_node来接收最终答案,将其分配给结果位置,并发出信号以告知结果已准备好。(信号应该是一个原子以强制执行围栏。)您的其他任务可以在原子上旋转等待。或者您可以使用条件变量。

问候,克里斯

于 2013-07-29T20:23:15.837 回答
0

接收者和发送者类是“纯虚拟”类(try_* 方法有默认行为以简化节点的定义。)对于每个 flow::graph 节点,它们都被该类特有的行为覆盖。

如果您希望创建特定类型的节点(或适配器),则应覆盖虚拟方法。但是,您可以使用 function_node 来执行您尝试使用此适配器执行的操作。您可以删除 try_get 和 try_put 调用(这是 function_node 行为的一部分。)

// notice TInput and TOutput are exchanged
template < typename TInput, typename TOutput >
class FlowPathAdapterBody {
public:
    TOutput operator()(const TInput& val) {
        // val has the value passed to us
        TOutput result;
        // computation turning val into result
        return result;
    }
};

tbb::flow::graph g;
// node is fully-parallel in this case
tbb::flow::function_node<int, int> fnode(g, tbb::flow::unlimited, FlowPathAdapterBody<int,int>());

// ...

您可以将多个前任附加到 function_node 的输入,并将多个后继附加到其输出。

默认情况下,function_node 在其输入上有一个缓冲区,因此即使节点是串行的,它也将始终接受输入。如果您希望它拒绝输入而不是缓冲它们,您可以使节点function_node<T,U,tbb::flow::rejecting>.

如果您想要更高级的行为(例如每个输入发出多条消息的能力,或者可选择不为某些输入发出消息,或者发出特殊条件的信号,请查看 multifunction_node。如果只需要一个输出,则 multifunction_node 只能有一个输出.)

问候,克里斯

于 2013-07-29T15:27:21.823 回答