3

我想通过常规类方法公开当前状态,从阻塞上下文中访问基于类的参与者状态。最好的方法是什么?我可以想到三个主要途径:

  1. 基于类的参与者不应该暴露他们的状态,除非通过消息传递(即我一开始就做错了)
  2. 类方法应该使用 ascoped_actor向基于类的参与者发送消息并返回响应。
  3. 类方法应该绕过参与者框架并简单地访问持有状态的成员变量。

我尝试了方法 #2,但是虽然我确实弄清楚了如何添加“可变”关键字来修改捕获的变量,但我无法成功地延迟方法返回,直到可以设置捕获的变量而不会造成死锁。

方法#3 似乎适用于我在下面包含的示例。受保护和不受保护的访问似乎都有效,所以我不确定是否需要保护对状态的访问。

using size_atom = atom_constant<atom("size")>;
using done_atom = atom_constant<atom("done")>;
using a_type = typed_actor<
    replies_to<int>::with<void>,
    replies_to<size_atom>::with<size_t>,
    replies_to<done_atom>::with<void>>;

class A : public a_type::base
{
public:
    size_t size_direct_access()
    {
        return this->m_values.size();
    }

    size_t size_protected_access()
    {
        lock_guard<mutex> lock(this->m_mutex);
        return this->m_values.size();
    }
protected:
    behavior_type make_behavior() override
    {
        return
        {
            [this](int value)
            {
                lock_guard<mutex> lock(this->m_mutex);
                this->m_values.push_back(value);
            },
            [this](size_atom) -> size_t
            {
                lock_guard<mutex> lock(this->m_mutex);
                return this->m_values.size();
            },
            [this](done_atom)
            {
                this->quit();
            }
        };
    }
private:
    vector<int> m_values;
    mutex m_mutex;
};

void tester()
{
    a_type testeeActor = spawn_typed<A, detached>();
    abstract_actor* abstractActor = actor_cast<abstract_actor*, a_type>(testeeActor);
    A* a = dynamic_cast<A*>(abstractActor);
    scoped_actor self;
    self->sync_send(testeeActor, 5).await(
        [a, testeeActor, &self]()
        {
            size_t direct_access = a->size_direct_access();
            size_t protected_access = a->size_protected_access();
            aout(self) << "Direct: " << direct_access << " Protected: " << protected_access << endl;

            self->sync_send(testeeActor, 3).await(
                [a, testeeActor, &self]()
            {
                size_t direct_access = a->size_direct_access();
                size_t protected_access = a->size_protected_access();
                aout(self) << "Direct: " << direct_access << " Protected: " << protected_access << endl;

                self->sync_send(testeeActor, 1).await(
                    [a, testeeActor, &self]()
                {
                    size_t direct_access = a->size_direct_access();
                    size_t protected_access = a->size_protected_access();
                    aout(self) << "Direct: " << direct_access << " Protected: " << protected_access << endl;

                    self->sync_send(testeeActor, done_atom::value);
                });
            });
        });
}

int main()
{
    cout << "Spawning actors" << endl;
    tester();
    cout << "Awaiting all actors done" << endl;
    await_all_actors_done();
    cout << "Shutdown" << endl;
    shutdown();
    cout << "Press Enter to continue" << endl;
    cin.get();
}
4

1 回答 1

4

你在一开始就回答了你自己的问题:

基于类的参与者不应该暴露他们的状态,除非通过消息传递(即我一开始就做错了)

Actor 仅通过消息传递进行通信。你不应该试图违反这个原则。否则,运行时提供的所有安全保证都将不复存在。如果您想要共享的、可变的状态,那么 Actor 模型对您来说是错误的原语。

也就是说,共享的不可变状态在 Actor 模型中运行良好。您可以将 const-reference 传递给 Actor 构造函数以与外部范围共享状态,但必须确保该引用在 Actor 的生命周期内保持有效。另一种选择是只使用消息,它通过为其元素提供写时复制接口来封装共享、不可变数据的概念。

升级:如果您发现自己需要访问参与者的数据,您可能应该重新审视您的程序设计。

于 2015-11-20T20:28:27.527 回答