Проект, над которым я работаю, использует несколько потоков для работы с коллекцией файлов. Каждый поток может добавлять файлы в список файлов, которые нужно обработать, поэтому я собрал (как я думал) потокобезопасную очередь. Соответствующие части следуют:
// qMutex is a std::mutex intended to guard the queue
// populatedNotifier is a std::condition_variable intended to
// notify waiting threads of a new item in the queue
void FileQueue::enqueue(std::string&& filename)
{
std::lock_guard<std::mutex> lock(qMutex);
q.push(std::move(filename));
// Notify anyone waiting for additional files that more have arrived
populatedNotifier.notify_one();
}
std::string FileQueue::dequeue(const std::chrono::milliseconds& timeout)
{
std::unique_lock<std::mutex> lock(qMutex);
if (q.empty()) {
if (populatedNotifier.wait_for(lock, timeout) == std::cv_status::no_timeout) {
std::string ret = q.front();
q.pop();
return ret;
}
else {
return std::string();
}
}
else {
std::string ret = q.front();
q.pop();
return ret;
}
}
Тем не менее, я иногда сталкиваюсь внутри блока if (...wait_for(lock, timeout) == std::cv_status::no_timeout) { }
, и проверка в gdb указывает, что segfaults происходят, потому что очередь пуста. Как это возможно? Полагаю, что wait_for
возвращает cv_status::no_timeout
только когда он был уведомлен, и это должно произойти только после того, как FileQueue::enqueue
просто нажал новый элемент в очередь.