私が取り組んでいるプロジェクトでは、複数のスレッドを使用してファイルのコレクションを処理しています。各スレッドは処理されるファイルのリストにファイルを追加できるので、私は(私が思っていたように)スレッドセーフなキューをまとめました。関連する部分は次のとおりです。
// 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で検査すると、キューが空であるためにセグフォールトが発生していることがわかります。これはどのように可能ですか?通知されたときにwait_for
のみ戻るというのが私の理解でした。これは、新しいアイテムをキューにプッシュした後にのみ発生するはずです。cv_status::no_timeout
FileQueue::enqueue