7

C++11 std::condition_variable を使用しようとしていますが、それに関連付けられている unique_lock を 2 番目のスレッドからロックしようとすると、「リソースのデッドロックが回避されました」という例外が発生します。それを作成したスレッドはそれをロックおよびロック解除できますが、2 番目のスレッドはできません。

FWIW Linux で -std=gnu++11 を指定して gcc 4.8.1 を使用しています。

condition_variable、unique_lock、mutex のラッパー クラスを作成したので、コード内の他の何もそれらに直接アクセスすることはできません。std::defer_lock の使用に注意してください。私はすでにそのトラップに陥っています :-)。

class Cond {
private:
    std::condition_variable cCond;
    std::mutex cMutex;
    std::unique_lock<std::mutex> cULock;
public:
    Cond() : cULock(cMutex, std::defer_lock)
    {}

    void wait()
    {
        std::ostringstream id;
        id << std::this_thread::get_id();
        H_LOG_D("Cond %p waiting in thread %s", this, id.str().c_str());
        cCond.wait(cULock);
        H_LOG_D("Cond %p woke up in thread %s", this, id.str().c_str());
    }

    // Returns false on timeout
    bool waitTimeout(unsigned int ms)
    {
        std::ostringstream id;
        id << std::this_thread::get_id();
        H_LOG_D("Cond %p waiting (timed) in thread %s", this, id.str().c_str());
        bool result = cCond.wait_for(cULock, std::chrono::milliseconds(ms))
                == std::cv_status::no_timeout;
        H_LOG_D("Cond %p woke up in thread %s", this, id.str().c_str());
        return result;
    }

    void notify()
    {
        cCond.notify_one();
    }

    void notifyAll()
    {
        cCond.notify_all();
    }

    void lock()
    {
        std::ostringstream id;
        id << std::this_thread::get_id();
        H_LOG_D("Locking Cond %p in thread %s", this, id.str().c_str());
        cULock.lock();
    }

    void release()
    {
        std::ostringstream id;
        id << std::this_thread::get_id();
        H_LOG_D("Releasing Cond %p in thread %s", this, id.str().c_str());
        cULock.unlock();
    }
};

私のメイン スレッドは、関連付けられたスレッドを持つ RenderContext を作成します。メイン スレッドの観点からは、Cond を使用してレンダリング スレッドにアクションを実行するように通知し、レンダリング スレッドがそのアクションを完了するのを CONd で待機することもできます。レンダリング スレッドは、メイン スレッドがレンダリング リクエストを送信するのを Cond で待機し、同じ Cond を使用して、必要に応じてアクションが完了したことをメイン スレッドに伝えます。私が得ているエラーは、レンダリング スレッドが Cond をロックしてレンダリング リクエストをチェック/待機しようとしたときに発生します。同じスレッド。出力は次のとおりです。

DEBUG: Created window
DEBUG: OpenGL 3.0 Mesa 9.1.4, GLSL 1.30
DEBUG: setScreen locking from thread 140564696819520
DEBUG: Locking Cond 0x13ec1e0 in thread 140564696819520
DEBUG: Releasing Cond 0x13ec1e0 in thread 140564696819520
DEBUG: Entering GLFW main loop
DEBUG: requestRender locking from thread 140564696819520
DEBUG: Locking Cond 0x13ec1e0 in thread 140564696819520
DEBUG: requestRender waiting
DEBUG: Cond 0x13ec1e0 waiting in thread 140564696819520
DEBUG: Running thread 'RenderThread' with id 140564575180544
DEBUG: render thread::run locking from thread 140564575180544
DEBUG: Locking Cond 0x13ec1e0 in thread 140564575180544
terminate called after throwing an instance of 'std::system_error'
  what():  Resource deadlock avoided

正直なところ、unique_lock の目的と、mutex を直接使用する代わりに condition_variable に必要な理由がよくわかりません。おそらく、それが問題の原因です。私はそれについての良い説明をオンラインで見つけることができません。

4

1 に答える 1