2017-02-10 7 views
0

キュー内のcondition_variablesで待機しているオブジェクトをプッシュする方法をテストしています。後でクリティカルセクションに入るので、スレッドごとに実行したい。スレッドから何も印刷されていない、何が間違っている可能性がありますか?スレッドがstd::condition_variable::waitを呼び出すと、別のスレッドが同じcondition_variablenotify_oneまたはnotify_allを呼び出すまでキュー内のcondition_variablesで待機中の複数のスレッドのテスト

mutex print_mu; 

void print(function<void()> func) 
{ 
    lock_guard<mutex> lock(print_mu); 
    func(); 
} 

unsigned int generate_id() 
{ 
    static unsigned int id = 1; 
    return id++; 
} 

class foo 
{ 
    unsigned int id_; 
    mutex mu_; 
    condition_variable cv_; 
    bool signal_; 
    bool& kill_; 
public: 
    foo(bool kill) 
     :kill_(kill) 
     , signal_(false) 
     , id_(generate_id()) 
    { 
     run(); 
    } 

    void set() 
    { 
     signal_ = true; 
    } 

    void run() 
    { 
     async(launch::async, [=]() 
     { 
      unique_lock<mutex> lock(mu_); 
      cv_.wait(lock, [&]() { return signal_ || kill_ ; }); 

      if (kill_) 
      { 
       print([=](){ cout << " Thread " << id_ << " killed!" << endl; }); 
       return; 
      } 

      print([=](){ cout << " Hello from thread " << id_ << endl; }); 
     }); 
    } 
}; 

int main() 
{ 
    queue<shared_ptr<foo>> foos; 
    bool kill = false; 

    for (int i = 1; i <= 10; i++) 
    { 
     shared_ptr<foo> p = make_shared<foo>(kill); 
     foos.push(p); 
    } 
    this_thread::sleep_for(chrono::seconds(2)); 

    auto p1 = foos.front(); 
    p1->set(); 
    foos.pop(); 

    auto p2 = foos.front(); 
    p2->set(); 
    foos.pop(); 

    this_thread::sleep_for(chrono::seconds(2)); 

    kill = true; // terminate all waiting threads unconditionally 

    this_thread::sleep_for(chrono::seconds(2)); 

    print([=](){ cout << " Main thread exits" << endl; }); 

    return 0; 
} 

答えて

1

は、それがブロックされます。 condition_variablesのいずれにもnotify_*を電話することはありませんので、永遠にブロックされます。 std::futureのデストラクタは、それがその結果を参照し、最後std::futureかどうstd::async呼び出しの結果を待ってブロックされますので、

あなたfoo::run方法は、また、永遠にブロックします。したがって、あなたのコードはデッドロックしています:あなたのメインスレッドは非同期の未来が終了するのを待ってブロックされ、非同期の未来はブロックされ、メインスレッドがシグナルcv_を待っています。

runが今までとにかく返された場合もfoo::kill_はぶら下がり参照です。まあ、それは一つになるでしょう。)

+0

ナイスキャッチ。ありがとう。 – ark1974

関連する問題