次のパターンを想像してみてください。非同期に更新する必要のある情報を含むウィンドウがあります。スレッドを起動して切り離し、情報のフェッチを処理しますが、情報がフェッチされている間、ウィンドウは閉じられ、メモリからアンロードされます。バックグラウンドスレッドがウィンドウのメモリ内の情報を更新しようとすると、メモリは既に割り当て解除されており、セグメンテーション違反が発生します。
私はC++でプログラミングしているので、更新中のメモリをstd::shared_ptr
ですが、これはバックグラウンドタスクの実行中はメモリを割り当てたままにする必要があることを意味します。この問題を解決するより良い方法はありますか?
タスクキャンセルパターンを実装できます。
このパターンは、インテルTBB、Microsoft C++ PPL、Microsoft C#TPL、および他の多くの並列フレームワークで見つけることができます。
タスクのキャンセルパターンは、共有フラグと共有データで構成されます。フラグ自体はstd::atomic<bool>
として実装できます。どちらのスレッドでも設定できます。データの処理にかなりのCPU時間を費やすコードでは、このフラグを時々チェックし、trueに設定されている場合は処理を終了または中止する必要があります。まとめに加えて、共有データにstd::shared_ptr<T>
も解放する必要があります。キャンセルを要求するスレッドはおそらく共有データも解放しているため、両方のスレッドが確認して応答する時間があれば、キャンセル後に共有データが実際にできるだけ早く解放されます。
場合によっては、一部のスレッドが一方的にデータを破棄することが適切である場合、std::weak_ptr<T>
を使用できます。 std::weak_ptr<T>
で保護されたデータにアクセスするコードは、アクセス中にstd::shared_ptr<T>
を要求して保持することにより、アクセスする必要があることに注意してください。そうしないと、マルチスレッドの解放後使用の競合状態(使用中に解放)の欠陥が発生します。
他にも、マネージャーオブジェクト、シングルトン(静的マネージャー)、メッセージパッシングアーキテクチャなどのアプローチがあります。