在 C++ Actors Framework 中的类型化 actor 之间转发消息的最佳实践?

Best practice for forwarding messages between typed actors in the C++ Actors Framework?

我正在尝试将一些工作从一位打字演员交给另一位打字演员。 CAF 用户手册指出这可以使用 forward_to 方法来完成。该方法看起来仅适用于明确属于 event_based_actor 类型的参与者。然而,forward_to 似乎是 forward_current_message 方法的一个薄包装,它是为 local_actor 类型的所有参与者定义的。因此,我认为可以直接调用 forward_current_message?

此外,为了让消息转发与有类型的 actor 一起工作,我仍然需要 return 来自中间 actor 的响应。那个演员的反应似乎被忽略了这是好的,但我做错了吗?还是真的有必要支付(通常是最低的)构建不会被使用的响应的成本?

下面是一些工作示例代码,演示了我尝试使用类型化 actor 进行消息转发:

#include <iostream>
#include "caf/all.hpp"

using namespace caf;
using namespace std;

using a_type = typed_actor<replies_to<int>::with<bool>>;
using b_type = typed_actor<replies_to<int>::with<bool>>;

actor worker()
{
    return spawn(
        [](event_based_actor *self) -> behavior
        {
            return
            {
                [self](int index)
                {
                    aout(self) << "Worker: " << index << endl;
                    return index;
                }
            };
        });
}

b_type::behavior_type bBehavior(b_type::pointer self)
{
    return
    {
        [self](int value)
        {
            // Create blocking actor
            scoped_actor blockingActor;

            // Spawn pool workers and send each a message
            auto pool = actor_pool::make(value, worker, actor_pool::round_robin());
            for(int i = 0; i < value; ++i)
            {
                blockingActor->send(pool, i);
            }

            // Wait for completion
            vector<int> results;
            int i = 0;
            blockingActor->receive_for(i, value) (
                [&results](int value)
                {
                    results.push_back(value);
                });

            blockingActor->send_exit(pool, exit_reason::user_shutdown);
            self->quit();
            return (value == results.size());
        }
    };
}

class A : public a_type::base
{
protected:
    behavior_type make_behavior() override
    {
        return
        {
            [this](int value) -> bool
            {
                aout(this) << "Number of tasks: " << value << endl;
                b_type forwardDestination = spawn(bBehavior);
                auto castDestination = actor_cast<actor>(forwardDestination);
                this->forward_current_message(castDestination);
                this->quit();
                return false;
            }
        };
    }
};


void tester()
{
    a_type testeeActor = spawn<A>();
    scoped_actor self;
    self->sync_send(testeeActor, 5).await(
        [testeeActor, &self](bool success)
        {
            aout(self) << "All workers completed? " << (success ? "Yes!" : "No :(") << endl;
        });
}

int main()
{
    tester();
    await_all_actors_done();
    shutdown();
    cout << "Press Enter to continue" << endl;
    cin.get();
}

Therefore, I assume it's okay to call forward_current_message directly?

不,forward_current_message 不是 CAF 中 public API 的一部分(因此未在 Doxygen 中列出)。这意味着可以随时重命名、删除或制作成员函数 protected/private

将消息转发给类型化 actor 的最佳做法是 delegate。这是一项新功能(在 0.14.1) and unfortunately is not mentioned in the manual yet. The best "documentation" currently available is its use in the unit test for typed actors.

中引入

简短版本是:delegatesend 的替代方案,它转发请求的责任。在类型化的 actor 中,您可以 return delegated<T> 而不是来自消息处理程序的 T 以指示其他 actor 将以 T 响应原始发件人。

在您的情况下,class A 将像这样实现:

class A : public a_type::base
{
protected:
    behavior_type make_behavior() override {
        return {
            [this](int value) {
                aout(this) << "Number of tasks: " << value << endl;
                auto forwardDestination = spawn(bBehavior);
                this->quit();
                return delegate(forwardDestination, value);
            }
        };
    }
};