Why this code snippet stall?
The program intends to output firstsecondthird
whereas the program stalls after firstsecond
has been printed.
#include <condition_variable>
#include <mutex>
#include <thread>
#include <functional>
#include <iostream>
#include <vector>
class Foo {
public:
Foo() {
}
void first(std::function<void()> printFirst)
{
{
std::unique_lock<std::mutex> lk(mutex);
cv1.wait(lk, [this](){return 1==state;});
doing = 1;
// printFirst() outputs "first". Do not change or remove this line.
printFirst();
state = 2;
}
cv2.notify_one();
}
void second(std::function<void()> printSecond)
{
{
std::unique_lock<std::mutex> lk(mutex);
if(state !=2 )
{
if((1 == state)&&(1 != doing))
{
lk.unlock();
cv1.notify_one();
}
}
cv2.wait(lk, [this](){return 2==state;});
doing = 2;
// printSecond() outputs "second". Do not change or remove this line.
printSecond();
state = 3;
}
cv3.notify_one();
}
void third(std::function<void()> printThird)
{
{
std::unique_lock<std::mutex> lk(mutex);
if(state !=3 )
{
if((1 == state)&&(1 != doing))
{
lk.unlock();
cv1.notify_one();
}
else if((2 == state)&&(2 != doing))
{
lk.unlock();
cv2.notify_one();
}
}
cv3.wait(lk, [this](){return 3==state;});
// printThird() outputs "third". Do not change or remove this line.
printThird();
state = 3;
}
}
private:
std::condition_variable cv1;
std::condition_variable cv2;
std::condition_variable cv3;
std::mutex mutex;
int state{1};
int doing{0};
};
int main()
{
Foo foo;
std::vector<std::thread> threads;
std::this_thread::sleep_for(std::chrono::milliseconds(300));
threads.push_back(std::thread([&](){foo.second([]()->void{std::cout <<"second" <<std::endl;});}));
std::this_thread::sleep_for(std::chrono::milliseconds(300));
threads.push_back(std::thread([&](){foo.first([]()->void{std::cout <<"first" <<std::endl;});}));
std::this_thread::sleep_for(std::chrono::milliseconds(300));
threads.push_back(std::thread([&](){foo.third([]()->void{std::cout <<"third" <<std::endl;});}));
std::this_thread::sleep_for(std::chrono::seconds(2));
for(auto itr=threads.begin(); itr!=threads.end(); itr++)
{
itr->join();
}
}
Aucun commentaire:
Enregistrer un commentaire