Un progetto su cui sto lavorando utilizza più thread per lavorare su una raccolta di file. Ogni thread può aggiungere file all'elenco dei file da elaborare, quindi ho messo insieme (quello che pensavo fosse) una coda thread-safe. parti rilevanti seguono:C++ 11 coda thread-safe
// 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;
}
}
Tuttavia, sono occasionalmente segfault all'interno del blocco if (...wait_for(lock, timeout) == std::cv_status::no_timeout) { }
e ispezione gdb indica che i segfaults si verificano perché la coda è vuota. Com'è possibile? Sono stato a conoscenza del fatto che wait_for
restituisce solo cv_status::no_timeout
quando è stato notificato, e ciò dovrebbe avvenire solo dopo che FileQueue::enqueue
ha appena inserito un nuovo elemento nella coda.
Qui si va: http://www.justsoftwaresolutions.co.uk/threading/implementing-a-thread-safe-queue-using-condition-variables.html – GManNickG
domanda, perché stai prendendo 'filename' con ref-ref? Non riesco a vedere alcun motivo per questo qui> –
@TonyTheLion Generalmente in C++ è più efficiente passare oggetti per riferimento piuttosto che fare una copia. In questo caso sto anche usando la semantica del movimento, che consente al compilatore di spostare il contenuto della stringa in coda invece di crearne un'altra copia. –