クラスインスタンスのすべての使用法をミューテックスでラップしたいと思います。今日は
std::map<int, std::shared_ptr<MyClass>> classes;
インスタンスを検索して返すための関数:
std::shared_ptr<MyClass> GetClass(int i);
GetClass()は、RAIIメカニズムを使用して、他の誰かがまだ取得していない場合にのみインスタンスを取得できるようにします。使用法は次のようになります。
void CallingFunction()
{
auto c = GetClass(i); // mutex for class id 'i' is acquired here
// some calls to class
c.SomeFunction();
} // mutex is released here when 'c' goes out of scope
CallingFunction()によって取得されたミューテックスでは、同じクラスインスタンスにアクセスしたい他のスレッドは、GetClass()の呼び出しをブロックします。
次のようなラッパークラスを使用するなど、いくつかの方法を検討しています。
class ClassContainer
{
public:
std::shared_ptr<Class> c;
std::mutex m;
};
GetClass()を次のように変更する場合:
ClassContainer GetClass(int i);
しかし、std :: mutexを保持する場所の両方を把握するのに問題があります。最初にマップに保存してから、次のようなコンテナクラスの使用に移行しました。
std::map<int, std::pair<std::mutex, std::shared_ptr<MyClass<>>> classes;
しかし、それはうまく機能していませんでしたが、ClassContainerではstd :: lock_guard<>のようにClassContainerがstd :: mutexをロックする方法があります呼び出し元がGetClass()の呼び出しを介して取得した場合。
回答 3 件
Class
ですmutex
を保持する必要があります 、 何かのようなもの:class Class { public: // Your methods... std::mutex& GetMutex() { return m; } private: std::mutex m; }; class ClassContainer { public: ClassContainer(std::shared_ptr<Class> c) : c(std::move(c)), l(this->c->GetMutex()) {} ClassContainer(const ClassContainer&) = delete; ClassContainer(ClassContainer&&) = delete; ClassContainer& operator =(const ClassContainer&) = default; ClassContainer& operator =(ClassContainer&&) = default; // For transparent pointer like access to Class. decltype(auto) operator -> () const { return c; } decltype(auto) operator -> () { return c; } const Class& operator*() const { return *c; } Class& operator*() { return *c; } private: std::shared_ptr<Class> c; std::lock_guard<std::mutex> l; }; ClassContainer GetClass(int i) { auto c = std::make_shared<Class>(); return {c}; // syntax which avoids copy/move contructor. }
そして最後に使用法:
auto&& cc = GetClass(42); // `auto&&` or `const&` pre-C++17, simple auto possible in C++17 cc->ClassMethod();
簡易デモ。
偶然、私は最近非常に似たようなことをしました(
shared_ptr
の代わりにオブジェクトへの参照を返しました 。コードは次のように機能しました:struct locked_queue { locked_queue(locked_queue&& ) = default; mutable std::unique_lock<decltype(queue::mutex)> lock; const queue::q_impl_t& queue; // std::deque };
そして、これがどのように使用されるかです:
locked_queue ClassX::get_queue(...) { return {std::unique_lock<decltype(mutex)>{mutex}, queue_impl}; }
関連した質問
- 割り込みが到着したときにsleep()を終了する方法は?
- スレッド間の単純な分業は、かかる時間を短縮しません
- 並列実行ポリシーを使用してからstd - : reduce()内でbinaryopを使用する
- ThreadId、Description、Statusなどのすべてのスレッドの詳細を取得する方法。 Win32 API C ++?
- HDF5ファイルを操作する際のマルチスレッドの読み取りと処理
- 並列std - : transform_reduce()の中間コンテナーを削除する方法は?
- ベクトルのカーリング数のC ++マルチスレッド決定
- 呼び出し元のスレッドが実行されているCPUを特定しますか?
- c ++マルチスレッド:共有変数への書き込みの処理方法
- C ++のRAIIでスレッドラッパークラスのセマティックを移動する
はい、これはそれを行う適切な方法であり、あなたは近くにいますが、あなたは
mutex
を保つことができません このクラスでは、ロッカーのみです。そして、std::unique_lock
必要なmove ctorなどがあるため、そのための適切なタイプです。ただし、フィールドをプライベートにし、必要なアクセサーを作成します。使い方は簡単です: