When implementing a semaphore using std::condition_variable, I came across an unexpected hang. If I use wait it never returns, but if I replace it as-is with wait_for it works fine despite the return value never being cv_status::timeout, and indeed the total runtime not being anywhere close to the timeout duration. I reproduced the relevant sections of the code below, although it only hangs in fairly chaotic usage with multiple threads waiting and notifying on various semaphores in quick succession (but with no thread ever acquiring more than one lock at once, so that is not the issue)
Notably, if I increase the scope of the lock_guard within Notify() to include m_cv.notify_one() within it, the hang also disappears. But the documentation indicates it should not be necessary to lock while calling notify, and I would rather avoid it since it's almost guaranteed to cause unnecessary mutex locks every time. Also, I was worried maybe m_count was being cached somehow, but replacing it with std::atomic with all calls being memory_order_seq_cst changes nothing. Disabling (or, indeed, enabling) optimization flags also doesn't help. Anyone have any clue why it could be behaving like this? Compiler is GCC 8.2.0 with -std=gnu++1z, if it helps. Thank you.
class Semaphore {
public:
Semaphore(int count = 0)
{
m_count = count;
}
inline void Notify()
{
{
std::lock_guard<std::mutex> lock(m_mtx);
++m_count;
}
m_cv.notify_one();
}
inline void Wait()
{
std::unique_lock<std::mutex> lock(m_mtx);
while(m_count == 0){
// m_cv.wait(lock);
m_cv.wait_for(lock, WAIT_DURATION);
}
--m_count;
}
private:
std::mutex m_mtx;
std::condition_variable m_cv;
int m_count;
constexpr static std::chrono::duration WAIT_DURATION = std::chrono::seconds(1000);
};
Aucun commentaire:
Enregistrer un commentaire