Reputation: 391
Essentially, I'm trying to add a Qt GUI onto an already existing GLUT application I made, and I'm not sure how to pass signals from the existing code into Qt, without introducing the overhead of making dozens of existing classes QObjects. Currently I'm using a QTimer and an event loop, but that isn't scaling very well, seeming to involve a lot of waiting for mutexes to then decide there's no work, with attempts to resolve this more increasing coupling than fixing it.
The best alternate I could come up with is this:
static std::mutex relay_mutex;
static std::condition_variable relay_condition;
static std::queue<std::pair<int, void*> > relay_queue;
extern "C"
void passMessage(int a, void * b)
{
std::lock_guard<std::mutex> lock(relay_mutex);
relay_queue.emplace_back(a, b);
relay_condition.notify_all();
}
class RelayThread : public QThread
{
Q_OBJECT
public:
RelayThread() {}
signals:
void passMessage(int, void *);
protected:
void run() override
{
std::unique_lock<std::mutex> lock(relay_mutex);
for(;;)
{
while(relay_queue.empty())
relay_condition.wait();
do {
emit passMessage(relay_queue.front().first, relay_queue.front().second);
if(relay_queue.front().first == 0)
return;
relay_queue.pop()
} while(relay_queue.size());
}
}
};
But this will obviously incur the overhead of an extra context switch, which is no good either. Is there a way to manually queue up a signal without going through a QThread like this?
Upvotes: 0
Views: 119
Reputation: 801
This should be sufficient. You can let Qt do the queueing, if needed, by setting the connection type to Qt::QueuedConnection, the value of the third argument of the connect() call.
#include <QObject>
void passMessage(int a, MessageType b) {
Relay r(a,b);
}
class Relay: public QObject {
Q_OBJECT
public:
Relay(int a, MessageType b) {
emit passMessage(a, b);
}
signals:
void passMessage(int, MessageType);
};
You will also need to register a metatype for MessageType. See here.
Upvotes: 1