PDA

View Full Version : Problems semaphores and buffers



AndresBarbaRoja
9th March 2011, 17:24
Hi, I am trying to solve a problem in which I have a producer receiving messages and storing them into a buffer without max limit. The consumer checks if there are any new messages and if any, it will create a new thread to process it.
I'm almost a complete newbie and I realize that I have a lot of C++ learning to do (and i'm doing it) but i have a dead line and need some urgent help.
at the moment the first problem that I encounter is that I do not know where to store the QSemaphore. In the examples they are declared as global variables, but will not have a main for my module. Right now i'm declaring it as a static public member of the consumer class so the producer can have access to it knowing only the class (i am not sure how to pass a consumer object's member to the producer object).
The second problem that i'm having is that my program compiles but does not link and i do not know where is the problem :S

These are my classes.
The consumer's .h:

#ifndef ETHTHREAD_H
#define ETHTHREAD_H

#include <QThread>
#include <QSemaphore>
#include <QObject>
#include <QString>
#include <iostream>
#include <QQueue>
using namespace std;

class EthThread : public QThread
{
Q_OBJECT
public:
EthThread(QObject *parent = 0);
void run();
static void enqueuePFLPMessage(QString message);
static QString retrievePFLPMessage();
static QSemaphore PFLPMessagesInQueue;
private:
static QQueue<QString> PFLPQueue;
};

#endif // ETHTHREAD_H

The consumers implementation.

#include "eththread.h"
#include "pflp_linkmanager.h"

EthThread::EthThread(QObject *parent) :
QThread(parent){}

void EthThread::run()
{
PFLP_LinkManager producer(new PFLP_LinkManager);
producer.start();

while(1)
{
sleep(3);
if(PFLPMessagesInQueue.tryAcquire())
cout<<retrievePFLPMessage().data();
else
cout<<"EmptyQueue";
}
exec();
}

void EthThread::enqueuePFLPMessage(QString message)
{
PFLPQueue.enqueue(message);
}

QString EthThread::retrievePFLPMessage()
{
return PFLPQueue.dequeue();
}

The producer's heading:

#ifndef PFLP_LINKMANAGER_H
#define PFLP_LINKMANAGER_H

#include <QThread>
#include <QObject>
using namespace std;

class PFLP_LinkManager : public QThread
{
Q_OBJECT

public:
PFLP_LinkManager(QObject *parent = 0);

void run();
};

#endif // PFLP_LINKMANAGER_H


and implementation:

#include "pflp_linkmanager.h"
#include "eththread.h"

PFLP_LinkManager::PFLP_LinkManager(QObject *parent) :
QThread(parent)
{
}

void PFLP_LinkManager::run()
{
while(1)
{
sleep(5);
EthThread::enqueuePFLPMessage("MensajePFLP");
EthThread::PFLPMessagesInQueue.release();
}
exec();
}

And finally the main:

#include <QtCore/QCoreApplication>
#include <QString>
#include <eththread.h>

int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
EthThread module;
module.start();
return a.exec();
}

Thanks in advance for any help

AndresBarbaRoja
10th March 2011, 09:06
Ok, I scrapped the code and now it runs and appears to be doing what I want, yet i do not know if there is any conceptual problem or hidden trap that i'm not triggering on my test.
This solution is not the one i imagined first, because instead of a continous loop trying to acquire the the resources from the semaphore, i wanted to use signals to trigger the message management.
I will post my code below, could anyone tell me if there is any problem at sight (of example I'm not sure if i'm using the mutex in the right way).

main.cpp:

#include <QtCore/QCoreApplication>
#include <messagemanager.h>

int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
MessageManager manager;
manager.start();
return a.exec();
}

Consumer
messagemanager.h:

#ifndef MESSAGEMANAGER_H
#define MESSAGEMANAGER_H

#include <QThread>
#include <pflplinkmanager.h>
#include <QDebug>

class MessageManager : public QThread
{
Q_OBJECT
public:
MessageManager(QObject *parent = 0);

protected:
void run();

private:
PFLPLinkManager pflpLink;
};

#endif // MESSAGEMANAGER_H

messagemanager.cpp:

#include "messagemanager.h"

MessageManager::MessageManager(QObject *parent) :
QThread(parent)
{
}

void MessageManager::run()
{
forever
{
sleep(1);
if(pflpLink.messagesInQueue.tryAcquire())
qDebug()<<pflpLink.retrieveMessage();
else
qDebug()<<"No Messages";
}
}

Producer
pflplinkmanager.h

#ifndef PFLPLINKMANAGER_H
#define PFLPLINKMANAGER_H

#include <QThread>
#include <QMutex>
#include <QQueue>
#include <QString>
#include <QSemaphore>

class PFLPLinkManager : public QThread
{
Q_OBJECT
public:
PFLPLinkManager(QObject *parent = 0);
~PFLPLinkManager();

void enqueueMessage(QString);
QString retrieveMessage();
QSemaphore messagesInQueue;
protected:
void run();
private:
QMutex mutex;
bool abort;
QQueue<QString> InMessagesQ;
};
#endif // PFLPLINKMANAGER_H

pflplinkmanager.cpp:

#include "pflplinkmanager.h"

PFLPLinkManager::PFLPLinkManager(QObject *parent) :
QThread(parent)
{
abort=false;
start();
}

PFLPLinkManager::~PFLPLinkManager()
{
mutex.lock();
abort=true;
mutex.unlock();
wait();
}

void PFLPLinkManager::run()
{
while(!abort)
{
sleep(5);//Cada 5 segundos voy a producir un mensaje
QString message("Mensaje de entrada");
enqueueMessage(message);
messagesInQueue.release();
}

}

void PFLPLinkManager::enqueueMessage(QString message)
{
QMutexLocker locker(&mutex);
InMessagesQ.enqueue(message);
}

QString PFLPLinkManager::retrieveMessage()
{
QMutexLocker locker(&mutex);
return InMessagesQ.dequeue();
}