简体   繁体   中英

BlockingQueue's QWaitCondition: Destroyed while threads are still waiting

I've built my own blocking queue in Qt and I'm having a bit of a problem. If I don't Close the queue, then I get an error in console " QWaitCondition: Destroyed while threads are still waiting ". On the other hand, I get an access violation exception after I close the queue (regardless if it's in the constructor or from another thread). The exception occurs in the wait condition's wait method.

Here is my blocking queue:

#ifndef BLOCKING_QUEUE_H
#define BLOCKING_QUEUE_H

#include <QObject>
#include <QSharedPointer>
#include <QWaitCondition>
#include <QMutex>
#include <queue>

namespace Concurrency
{
    template<typename Data>
    class BlockingQueue
    {
    private:
        QMutex _mutex;
        QWaitCondition _monitor;
        volatile bool _closed;
        std::queue<QSharedPointer<Data>> _queue;

    public:
        BlockingQueue()
        {
            _closed = false;
        }

        ~BlockingQueue()
        {
            Close(); // When this is enabled, I get an access violation exception in TryDequeue
        }

        void Close()
        {
            QMutexLocker locker(&_mutex);
            if(!_closed)
            {
                _closed = true;
                _queue.empty();
                _monitor.wakeAll();
            }
        }

        bool Enqueue(QSharedPointer<Data> data)
        {
            QMutexLocker locker(&_mutex);

            // Make sure that the queue is not closed
            if(_closed)
            {
                return false;
            }

            _queue.push(data);

            // Signal all the waiting threads
            if(_queue.size()==1)
            {
                _monitor.wakeAll();
            }

            return true;
        }

        bool TryDequeue(QSharedPointer<Data>& value, unsigned long time = ULONG_MAX)
        {
            QMutexLocker locker(&_mutex);

            // Block until something goes into the queue
            // or until the queue is closed
            while(_queue.empty())
            {
                if(_closed || !_monitor.wait(&_mutex, time)) // <-- Access violation if I call close in the destructor
                {
                    return false;
                }
            }

            // Dequeue the next item from the queue
            value = _queue.front();
            _queue.pop();
            return true;
        }
    };
}
#endif BLOCKING_QUEUE_H

I'm assuming that this is happening because the thread that's waiting gets signaled after the Queue has been destroyed already and the mutex is subsequently destroyed too. When the thread is woken up in TryDequeue , the mutex is no longer allocated so it causes an access violation exception. What's the best way to avoid this?

The problem I was encountering was related to the threading approach, for more info take a look at this question: Why is QThread::finished signal not being emitted?

The service that was using the BlockingQueue was not properly closing the thread that was waiting on the queue and it was subsequently causing the queue to be destroyed while a thread is still waiting inside the TryDequeue method.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM