了解 stateful_actor
Understanding the stateful_actor
我在examples/curl/curl_fuse.cpp and libcaf_core/test/stateful_actor.cpp下阅读了stateful_actor的一些用法。看起来 stateful_actor<State>
可以通过在 State struct
中声明字段来为 actor 绑定一些状态。这非常有用。
我们可以将状态声明为 class-based actor
中的字段以获得相同的效果吗?或者在 stateful_actor
中有一些特殊处理(例如线程安全访问)?
以下示例中的参与者是否提供相同的功能?
/* Class based actor */
struct ClassCounter : caf::event_based_actor
{
caf::behavior make_behavior() override {
return {
[=](inc_atom){ i += 1; }
, [=](ret_atom){ return i; }
};
}
const char* name() const override { return "I am class-based"; }
int i = 0;
};
/* Stateful actor */
struct CounterState
{
caf::local_actor* self;
int i = 0;
const char* name = "I am stateful";
};
caf::behavior StatefulCounter(caf::stateful_actor<CounterState>* self)
{
return {
[=](inc_atom){ self->state.i += 1; }
, [=](ret_atom){ return self->state.i; }
};
};
Can we declare the states as fields in class-based actor
to get the same effects? Or there is some special handling in the stateful_actor
(e.g. thread-safety access) ?
CAF 的运行时假定 actor 是隔离的,即只允许 actor 本身访问其状态。因此,对参与者状态的访问永远不会同步。参与者间通信使用消息传递,从而通过设计避免竞争条件。
Stateful actor 允许程序员编写更少的 类(因此更少的样板代码),但是 ClassCounter
和 StatefulCounter
之间也有一个显着的区别:变量的生命周期。在ClassCounter
中,成员变量i
一直存在,直到ClassCounter
的析构函数被调用。由于 actor 是引用计数的,如果没有留下对它的引用,则析构函数将运行,即,不存在 actor 的 actor
或 actor_addr
句柄。在 StatefulCounter
中,如果 actor 初始化并销毁,则构造 CounterState
成员。
只要演员还活着,状态就存在。这对于中断循环特别有用。如果你有两个演员 A
和 B
,如果 A
通过成员变量持有对 B
的引用,你就有了一个循环,反之亦然。使用有状态的 actor 可以打破这个循环。 A
将在退出时自动释放对 B
的引用,反之亦然。
我在examples/curl/curl_fuse.cpp and libcaf_core/test/stateful_actor.cpp下阅读了stateful_actor的一些用法。看起来 stateful_actor<State>
可以通过在 State struct
中声明字段来为 actor 绑定一些状态。这非常有用。
我们可以将状态声明为 class-based actor
中的字段以获得相同的效果吗?或者在 stateful_actor
中有一些特殊处理(例如线程安全访问)?
以下示例中的参与者是否提供相同的功能?
/* Class based actor */
struct ClassCounter : caf::event_based_actor
{
caf::behavior make_behavior() override {
return {
[=](inc_atom){ i += 1; }
, [=](ret_atom){ return i; }
};
}
const char* name() const override { return "I am class-based"; }
int i = 0;
};
/* Stateful actor */
struct CounterState
{
caf::local_actor* self;
int i = 0;
const char* name = "I am stateful";
};
caf::behavior StatefulCounter(caf::stateful_actor<CounterState>* self)
{
return {
[=](inc_atom){ self->state.i += 1; }
, [=](ret_atom){ return self->state.i; }
};
};
Can we declare the states as fields in
class-based actor
to get the same effects? Or there is some special handling in thestateful_actor
(e.g. thread-safety access) ?
CAF 的运行时假定 actor 是隔离的,即只允许 actor 本身访问其状态。因此,对参与者状态的访问永远不会同步。参与者间通信使用消息传递,从而通过设计避免竞争条件。
Stateful actor 允许程序员编写更少的 类(因此更少的样板代码),但是 ClassCounter
和 StatefulCounter
之间也有一个显着的区别:变量的生命周期。在ClassCounter
中,成员变量i
一直存在,直到ClassCounter
的析构函数被调用。由于 actor 是引用计数的,如果没有留下对它的引用,则析构函数将运行,即,不存在 actor 的 actor
或 actor_addr
句柄。在 StatefulCounter
中,如果 actor 初始化并销毁,则构造 CounterState
成员。
只要演员还活着,状态就存在。这对于中断循环特别有用。如果你有两个演员 A
和 B
,如果 A
通过成员变量持有对 B
的引用,你就有了一个循环,反之亦然。使用有状态的 actor 可以打破这个循环。 A
将在退出时自动释放对 B
的引用,反之亦然。