Avec l'aide de cbreak et Ravadre (commentaires) je suis arrivé à partir d'ici :
int main()
{
std::mutex m;
std::condition_variable cv;
std::thread t([&] {
std::this_thread::sleep_for(std::chrono::seconds(1));
std::unique_lock<std::mutex> lock(m);
cv.wait(lock);
std::cout << "Yay!\n";
});
cv.notify_one();
t.join();
}
Ce qui ne se termine généralement pas du tout, jusqu'ici :
int main()
{
std::mutex m;
std::condition_variable cv;
bool flag = false;
std::thread t([&] {
std::this_thread::sleep_for(std::chrono::seconds(1));
std::unique_lock<std::mutex> lock(m);
cv.wait(lock, [&] { return flag; });
std::cout << "Yay!\n";
});
{
std::lock_guard<std::mutex> lock(m);
flag = true;
}
cv.notify_one();
t.join();
}
Ce qui fait effectivement le travail, mais semble toujours être beaucoup de frais généraux inutiles. N'hésitez pas à poster une réponse équivalente mais plus performante (ou plus élégante), je l'accepterai avec plaisir. Merci de n'utiliser que le standard C++11, et si non, expliquez pourquoi le standard C++11 ne peut pas faire cela.
Edit : J'ai aussi écrit une classe safe_flag pour encapsuler ceci (merci encore à cbreak) ; n'hésitez pas à suggérer des améliorations.
class safe_flag
{
mutable std::mutex m_;
mutable std::condition_variable cv_;
bool flag_;
public:
safe_flag()
: flag_(false)
{}
bool is_set() const
{
std::lock_guard<std::mutex> lock(m_);
return flag_;
}
void set()
{
{
std::lock_guard<std::mutex> lock(m_);
flag_ = true;
}
cv_.notify_all();
}
void reset()
{
{
std::lock_guard<std::mutex> lock(m_);
flag_ = false;
}
cv_.notify_all();
}
void wait() const
{
std::unique_lock<std::mutex> lock(m_);
cv_.wait(lock, [this] { return flag_; });
}
template <typename Rep, typename Period>
bool wait_for(const std::chrono::duration<Rep, Period>& rel_time) const
{
std::unique_lock<std::mutex> lock(m_);
return cv_.wait_for(lock, rel_time, [this] { return flag_; });
}
template <typename Rep, typename Period>
bool wait_until(const std::chrono::duration<Rep, Period>& rel_time) const
{
std::unique_lock<std::mutex> lock(m_);
return cv_.wait_until(lock, rel_time, [this] { return flag_; });
}
};