PDA

View Full Version : Dequeue fails



saman_artorious
21st April 2013, 10:16
I do not know what the heck is wrong with my code that it never Dequeus the queue, instead isEmpty always meets true.

here's the queue class:



class ConcurrentQueue
{
private:
QQueue<QByteArray> dataStore;

public:

void Enqueue(QByteArray value);
QByteArray Dequeue();

bool isEmpty();
private:
QMutex mutex;
};

void ConcurrentQueue::Enqueue(QByteArray value)
{
qDebug() << dataStore.length();
mutex.lock();
dataStore.enqueue(value);
mutex.unlock();
qDebug() << dataStore.length();
}

QByteArray ConcurrentQueue::Dequeue()
{

// mutex.lock();
// return dataStore.dequeue();
// mutex.unlock();

QByteArray tmp;

mutex.lock();

if(!dataStore.isEmpty())
{
tmp = dataStore.dequeue();
}

mutex.unlock();

return tmp;
}

bool ConcurrentQueue::isEmpty()
{
return dataStore.isEmpty();
}



next a timer is connected to a slot to Enqueu a packet every lt's say 10 milliseconds:


QByteArray built((char*)data, len) ;
//qDebug() << built.toHex();
qDebug() << "EnQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ";
queue.Enqueue(built);


A thread regularly checks if this queue is not empty it dequeues the queue and does something, but isEmplty always returns true!



if(queue.isEmpty())
{
qDebug() << "#####################################";
return;
}
//NEVER COMES HERE!
QByteArray rd15Bytes = queue.Dequeue();



here's the thread:


Write::Write()
{
}

void Write::run(){
while(1)
{
rs.writeToSerialPort(); // in this function above always isemplty is true

this->msleep(10);
}
}


Added after 31 minutes:
as I run the code, queue size increases and the contents are enQd inside of it. but I wonder why isEmpty always meets !!!!

wysota
21st April 2013, 10:47
Your queue is not thread-safe. Your isEmpty() implementation is incorrect.

saman_artorious
21st April 2013, 11:03
I dont understand! how can I resolve this?
the isEmpty function works fine inside Queue Class, it even gives the correct number of elements already EnQd.
But why does it fail when I call it from outside the class!

wysota
21st April 2013, 11:42
Maybe because you're not protecting it from concurrent access.

saman_artorious
21st April 2013, 11:50
there is no need to protect it from concurrent access, it is a read-only function. On the other hand, EnQ and DeQ are
well protected. I don't understand this at all, this must be working o'rite.

wysota
21st April 2013, 12:10
there is no need to protect it from concurrent access, it is a read-only function.
No, that's wrong. You are supposed to protect data, not code. All access to your "datastore" member has to be protected by the same mutex. What if someone else is writing to the datastore while you're calling isEmpty()?

saman_artorious
21st April 2013, 13:16
no difference,


bool ConcurrentQueue::is_Empty()
{

mutex.lock();
bool boo = dataStore->isEmpty();
mutex.unlock();
return boo;
}

here is the output:



"020503"
EnQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
##################################### true
##################################### true

it enQs bytearray into queue whenever QTimer triggers, ok? next, another thread regularly calls a readfunction, at the beginning of this function I check if isEmpty is false, if false then I carry on with DeQing, ok? but the output shows it always returns true with ######

Added after 9 minutes:

if you need more info please let me know, I can't really find where I am doing wrong!

Added after 46 minutes:

I want answers, why is this doing this to me? I don't think there is a problem in my code.

wysota
21st April 2013, 14:40
Here is a working queue example: http://www.qtcentre.org/threads/26250-Thread-Safe-Queue-container

amleto
21st April 2013, 15:04
probably op is doing something silly like making two instances of the queue without realising. Without FULL compilable example we are just guessing (see my sig...)