Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Queue enque and deque thread safe



  • Hi,
    I have some ambiguities about thread safe and Queue.
    I read doc and there is note: All functions in this class are reentrant. That is clear.

    I need shared queue with one producer and one consumer. I used the simple example with two semaphores and change array to queue. With array is it clear, but with queue there theoretical should be enqueue and dequeue simultaneously. Always each on different item (so on different memory adress) in queue. Is it problem?

    If yes, can I use QSharedPointer to solve my problem ?
    If I understood correctly then I need two QSharedPointer reference to same queue for thread safe. Is it right?
    I would like to avoid using a mutex for locking queue.

    const int queueSize = 100;
    QQueue<int> queue;
    
    QSemaphore freeItems(queueSize);
    QSemaphore usedItems;
    
    class Producer : public QThread
    {
    public:
        void run() override
        {
          freeItems.acquire();
          queue.enqueue(1); 
          usedItems.release();
        }
    
    class Consumer : public QThread
    {
        Q_OBJECT
    public:
        void run() override
        {
          usedItems.acquire();
          cout << queue.dequeue() << Qt::endl;
          freeItems.release();
        };
    

    Thank you for your help



  • You should leave the semaphote/mutex there since the enqueue/dequeue will probably need to access the same counter or whatever is in the queue to count the items in there.
    Furthermore, the enqueueing/dequeueing is just a few processor cycles, so you won't loose any speed on this.
    The costly computaitons that you want to do on your items then can be performed after the release of the semaphore. However here you have to be sure to only work on one item at a time unless there are some mechanism to make this thread safe.

    Shared pointer has nothing to do with this. its just a smart pointer.


  • Qt Champions 2017

    @kubikula said in Queue enque and deque thread safe:

    If yes, can I use QSharedPointer to solve my problem ?

    No.

    If I understood correctly then I need two QSharedPointer reference to same queue for thread safe. Is it right?

    Absolutely not.

    I would like to avoid using a mutex for locking queue.

    Why? The mutex is a simpler semaphore, you're already using two semaphores, so how's a mutex a problem?

    You probably want something like this (I write off the top of my head, so you should test and fix so it compiles):

    QSemaphore availableItems;
    QMutex queueLock;
    
    void Producer::run()
    {
        QMutexLocker locker(&queueLock);
        queue.enqueue( ... );
        availableItems.release();
    }
    
    void Consumer::run()
    {
        availableItems.acquire();
        QMutexLocker locker(&queueLock);
        if (!queue.size())
            return 0; // < Allow to exit gracefully
    
        ... = queue.dequeue();
    }

Log in to reply