通常のクラス メソッドを介して現在の状態を公開することにより、ブロッキング コンテキストからクラス ベースのアクターの状態にアクセスしたいと考えています。最善のアプローチは何ですか?主な方法として、次の 3 つが考えられます。
- クラスベースのアクターは、メッセージの受け渡し以外で自分の状態を公開すべきではありません (つまり、最初から何か間違ったことをしています)。
- クラス メソッド
scoped_actor
は、クラス ベースのアクターにメッセージを送信し、応答を返すために を使用する必要があります。 - クラス メソッドはアクター フレームワークをバイパスし、状態を保持するメンバー変数にアクセスする必要があります。
アプローチ #2 を試みましたが、「mutable」キーワードを追加してキャプチャされた変数を変更する方法を理解しましたが、デッドロックを作成せずにキャプチャされた変数を設定できるようになるまで、メソッドの戻りを遅らせることができませんでした。
アプローチ #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();
}