2017-02-10 2 views
0

Я тестирую, как вытаскивать объекты, ожидающие состояния_переменных в очереди. Я хочу выполнить потоки в соответствии с моим желанием, потому что они будут в критических разделах позже. Из нитей ничего не печатается, что может быть неправильно?Тестирование нескольких потоков, ожидающих 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

Когда поток вызывает std::condition_variable::wait, он будет блокировать, пока другой поток не вызывает notify_one или notify_all на том же condition_variable. Поскольку вы никогда не звоните notify_* ни на один из ваших condition_variables, они будут блокироваться навсегда.

Ваш метод foo::run будет также блокировать навсегда, так как std::future «s деструктор блокирует ожидание в результате std::async вызова, если это последний std::future ссылающейся на этот результат. Таким образом, ваши блокировки кода: ваш основной поток заблокирован, ожидая вашего будущего асинхронного завершения, и ваше будущее async заблокировано, ожидая, когда ваш основной поток будет сигнализировать cv_.

(Также foo::kill_ является оборванной ссылка. Ну, это стало бы один, если run не вернулся в любом случае.)

+0

Хорошего улова. Благодарю. – ark1974

Смежные вопросы