派生デストラクタでのvtableデータ競合からの保護

arynaq

次のコードがあるとします

#include <thread>
#include <iostream>
#include <atomic>

struct FooBase {
    void start(){
        run_condition_ = true;
        t_ = std::thread([this](){
            thread_handler();
        });
    }

    virtual ~FooBase(){
        run_condition_ = false;
        if(t_.joinable())
            t_.join();
    }

protected:
    virtual void thread_handler() = 0;
    std::atomic_bool run_condition_{false};
private:
    std::thread t_;
};


struct Foo : FooBase {
    void thread_handler() override {
        while(run_condition_){
            std::cout << "Foo derived thread.." << std::endl;
        }
    }
};


int main(){
    Foo f;
    f.start();

    getchar();

    return 0;
}

ここで、派生クラスのデストラクタは、のデストラクタが実行されたときにスレッドがまだ参加していない(まだ実行されている)場合、基本クラスでvtableルックアップが発生するFooFooBase呼び出されるためだと思います以来純粋仮想である私は、基本的にSIGABORTをguranteedています。thread_handlerFooFooBase::thread_handler

これを防ぐにはどうすればよいですか?thread_handlerは純粋な仮想を持っいないことによって私の道をハックします

virtual void thread_handler(){}

しかし、基本クラス自体でこれを防ぐ方法がわかりません。基本クラスにjoin_threadインターフェイスを実装し、すべての派生クラスからこれを呼び出すことができますが、これは面倒なようです。

バリー

ここには2つの問題がありますが、どちらもあなたが説明したものと正確には一致しません。

  1. スレッドはでのみ停止し~FooBase()ます。これはFoo::thread_handler、そのメンバーのいずれかに対して読み取りまたは書き込みを行うと、スレッドが停止する前にそのメンバーの下から破棄されることを意味します。

  2. デストラクタに十分な速さで到達した場合、破棄start()されるthread_handler()までに新しいスレッドで実際に呼び出さない可能性がありFooます。これにより、純粋な仮想呼び出しが発生します。

いずれにせよ、Foo破壊されるまでに、関連するすべてのことthread_handlerが行われるようにする必要がありますこれFooBaseは、から派生したすべてのクラスが、そのデストラクタに次の要素を持たなければならないことを意味します

run_condition_ = false;
if (t_.joinable()) {
    t_join();
}

これが直接機能しないことt_は別としてprivate(これをにラップすることができますprotected stop())、派生クラスのすべてが機能するためだけに特別なことを行う必要がある場合、これは厄介な設計です。代わりにFooBase、引数として任意の呼び出し可能オブジェクトを受け取る独自のクラスに入れることができます。

class joining_thread {
public:
    joining_thread() = default;
    ~joining_thread() { stop(); }

    bool running() const { return run_condition_.load(); }

    template <typename... Args>
    void start(Args&&... args) {
        run_condition_ = true;
        t_ = std::thread(std::forward<Args>(args)...);
    }

    void stop() {
        run_condition_ = false;
        if (t_.joinable()) t_.join();
    }
private:
    std::thread t_;
    std::atomic_bool run_condition_{false};
};

そして、あなたFooはそれをメンバーとして持つことができます

class Foo {
public:
    void start() {
        t_.start([this]{
            while (t_.running()) { ... }
        });
    }

private:
    // just make me the last member, so it's destroyed first
    joining_thread t_;
};

それはまだ全体的に少し厄介ですrunning()が、うまくいけば、アイデアは理にかなっています。

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

保護されたデストラクタは、スタック上での派生クラスのオブジェクトの作成を無効にしますか?

分類Dev

クライアント側でのデータの保存-操作から保護する方法は?

分類Dev

共有変数への保護されていないアクセスは常にデータの競合ですか?

分類Dev

デストラクタからの例外のスローはvtableにとって安全ですか?

分類Dev

派生クラス関数内で、基本クラスの保護されたデータメンバーにアクセスできません

分類Dev

クラスの派生で保護されたコンストラクターを適用する

分類Dev

C ++:派生クラスで保護されたコンストラクターにアクセスできないのはなぜですか?

分類Dev

AjaxJSONデータとライトボックスの競合

分類Dev

Java ArrayListクラスでのデータ競合

分類Dev

保護された/プライベートの継承を使用して、派生インスタンスの基本クラスの保護されたメンバーにアクセスできないのはなぜですか?

分類Dev

保護されたデストラクタを持つクラスでのunique_ptrの使用

分類Dev

派生クラスの基本クラスで保護されたデータメンバーベクトルにアクセスすると、エラー139が発生します

分類Dev

Kerberosで保護されたStreamsetsData Collector(SDC)からのデータの取得

分類Dev

保護されたC ++-Cliデストラクタがコンパイルエラーを引き起こさないのはなぜですか?

分類Dev

基本クラスの保護された静的プロパティは、派生クラス間でデータを共有するための良い習慣ですか?

分類Dev

Webアクセスからのディレクトリ保護

分類Dev

Apacheサーバー上のパブリックディレクトリを介したアクセスからデータを保護する方法

分類Dev

異なるデータでの再利用からExcelワークブック(VBAを使用)を保護する

分類Dev

C ++デザイン:追加のデータメンバーなしでベースクラスから派生クラスにキャスト

分類Dev

データフレームでilocを使用すると、データフレームから派生したインデックスのリストを使用している場合でも、範囲外のエラーが発生します

分類Dev

保護されたクラスターでのNifiの使用

分類Dev

クラスターでの Spark ジョブの保護

分類Dev

盗難のリスクからデスクトップコンピュータ上のデータを保護するにはどうすればよいですか?

分類Dev

派生クラスから基本クラスの保護されたメンバーにアクセスする

分類Dev

クラスをネストすると、含まれているクラスが子クラスの保護されたデータにアクセスできるのはなぜですか?

分類Dev

データベースクラスから派生できる抽象クラス

分類Dev

クラウドベースのマルチテナント環境で機密性の高い顧客データを保護する

分類Dev

グローバル変数コンストラクタ/デストラクタにはスレッド保護が必要ですか?

分類Dev

更新前のデータの保護

Related 関連記事

  1. 1

    保護されたデストラクタは、スタック上での派生クラスのオブジェクトの作成を無効にしますか?

  2. 2

    クライアント側でのデータの保存-操作から保護する方法は?

  3. 3

    共有変数への保護されていないアクセスは常にデータの競合ですか?

  4. 4

    デストラクタからの例外のスローはvtableにとって安全ですか?

  5. 5

    派生クラス関数内で、基本クラスの保護されたデータメンバーにアクセスできません

  6. 6

    クラスの派生で保護されたコンストラクターを適用する

  7. 7

    C ++:派生クラスで保護されたコンストラクターにアクセスできないのはなぜですか?

  8. 8

    AjaxJSONデータとライトボックスの競合

  9. 9

    Java ArrayListクラスでのデータ競合

  10. 10

    保護された/プライベートの継承を使用して、派生インスタンスの基本クラスの保護されたメンバーにアクセスできないのはなぜですか?

  11. 11

    保護されたデストラクタを持つクラスでのunique_ptrの使用

  12. 12

    派生クラスの基本クラスで保護されたデータメンバーベクトルにアクセスすると、エラー139が発生します

  13. 13

    Kerberosで保護されたStreamsetsData Collector(SDC)からのデータの取得

  14. 14

    保護されたC ++-Cliデストラクタがコンパイルエラーを引き起こさないのはなぜですか?

  15. 15

    基本クラスの保護された静的プロパティは、派生クラス間でデータを共有するための良い習慣ですか?

  16. 16

    Webアクセスからのディレクトリ保護

  17. 17

    Apacheサーバー上のパブリックディレクトリを介したアクセスからデータを保護する方法

  18. 18

    異なるデータでの再利用からExcelワークブック(VBAを使用)を保護する

  19. 19

    C ++デザイン:追加のデータメンバーなしでベースクラスから派生クラスにキャスト

  20. 20

    データフレームでilocを使用すると、データフレームから派生したインデックスのリストを使用している場合でも、範囲外のエラーが発生します

  21. 21

    保護されたクラスターでのNifiの使用

  22. 22

    クラスターでの Spark ジョブの保護

  23. 23

    盗難のリスクからデスクトップコンピュータ上のデータを保護するにはどうすればよいですか?

  24. 24

    派生クラスから基本クラスの保護されたメンバーにアクセスする

  25. 25

    クラスをネストすると、含まれているクラスが子クラスの保護されたデータにアクセスできるのはなぜですか?

  26. 26

    データベースクラスから派生できる抽象クラス

  27. 27

    クラウドベースのマルチテナント環境で機密性の高い顧客データを保護する

  28. 28

    グローバル変数コンストラクタ/デストラクタにはスレッド保護が必要ですか?

  29. 29

    更新前のデータの保護

ホットタグ

アーカイブ