如何从阻塞上下文访问基于 class 的 actor 状态(C++ Actor 框架)
How can a class-based actor's state be accessed from a blocking context (C++ Actor Framework)
我想通过常规 class 方法公开当前状态,从阻塞上下文访问基于 class 的 actor 状态。最好的方法是什么?我可以想到三个主要途径:
- Class-based actors 不应该公开他们的状态,除非通过消息传递(即我一开始就做错了)
- class 方法应该使用
scoped_actor
向基于 class 的参与者发送消息并 return 响应。
- class 方法应该绕过 actor 框架并简单地访问保存状态的成员变量。
我尝试了方法 #2,但虽然我确实弄清楚了如何添加 'mutable' 关键字来修改捕获的变量,但我无法成功延迟方法 return 直到捕获的变量可以在不产生死锁的情况下进行设置。
方法 #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();
}
你一开始就在回答你自己的问题:
Class-based actors should not expose their state except by message passing (i.e. I'm doing something wrong to begin with)
Actor 仅通过消息传递进行通信。你不应该试图违反这个原则。否则,运行时提供的所有安全保证都将消失。如果你想要共享的、可变的状态,actor 模型对你来说是错误的原语。
也就是说,共享 immutable 状态在 actor 模型中工作正常。您可以将 const-reference 传递给 actor 构造函数以与外部作用域共享状态,但随后必须确保该引用在 actor 的生命周期内保持有效。另一种选择是只使用消息,它通过为其元素提供写时复制接口来封装共享、不可变数据的概念。
升级:如果您发现自己需要从演员那里访问数据,您可能应该重新审视您的程序设计。
我想通过常规 class 方法公开当前状态,从阻塞上下文访问基于 class 的 actor 状态。最好的方法是什么?我可以想到三个主要途径:
- Class-based actors 不应该公开他们的状态,除非通过消息传递(即我一开始就做错了)
- class 方法应该使用
scoped_actor
向基于 class 的参与者发送消息并 return 响应。 - class 方法应该绕过 actor 框架并简单地访问保存状态的成员变量。
我尝试了方法 #2,但虽然我确实弄清楚了如何添加 'mutable' 关键字来修改捕获的变量,但我无法成功延迟方法 return 直到捕获的变量可以在不产生死锁的情况下进行设置。
方法 #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();
}
你一开始就在回答你自己的问题:
Class-based actors should not expose their state except by message passing (i.e. I'm doing something wrong to begin with)
Actor 仅通过消息传递进行通信。你不应该试图违反这个原则。否则,运行时提供的所有安全保证都将消失。如果你想要共享的、可变的状态,actor 模型对你来说是错误的原语。
也就是说,共享 immutable 状态在 actor 模型中工作正常。您可以将 const-reference 传递给 actor 构造函数以与外部作用域共享状态,但随后必须确保该引用在 actor 的生命周期内保持有效。另一种选择是只使用消息,它通过为其元素提供写时复制接口来封装共享、不可变数据的概念。
升级:如果您发现自己需要从演员那里访问数据,您可能应该重新审视您的程序设计。