3

There is main function:

int main(int argc, char *argv[]) {
    QCoreApplication a(argc, argv);

    Worker w;
    QObject::connect(&w, SIGNAL(done()), &a, SLOT(quit()), Qt::QueuedConnection);
    w.start();

    int ret = a.exec();
    w.quit();
    w.wait();

    return ret;
}

And there is Worker's definition:

class Worker : public QThread
{
    Q_OBJECT
public:
    Worker(QObject *parent=0);
protected:
    void run();
protected slots:
    void process_request();
private:
    int ttl;
    Messenger* messenger;
}

Worker::Worker(QObject * parent)
    :QThread(parent),
    ttl(5),
    messenger(new Messenger(this))
{
    moveToThread(this);
    connect(messenger, SIGNAL(new_message()), SLOT(process_request()), Qt::QueuedConnection);
}

void Worker::finish(){
  quit();
  messenger->disconnectFromNetwork();   
}

void Worker::run(){
  messenger->connectToNetwork("somewhere");
  exec();
  emit done();
}

void Worker::process_request(){
    net_message msg;
    messenger->recv(msg);

    // PROCESSING

    messenger->send(msg);

    BOOST_LOG_SEV(file_log, severity::notification) << "TTL = " << ttl;
    if (--ttl == 0) {
        finish();
    }
}

Well, sorry for the long exposition. The idea was that the Messenger lives in the main thread, and pokes the Worker when it has a new message for it, and the Worker lives only a certain amount of messages, after which it stops and shuts down entire application.

But there is a problem: the log file has lines TTL = -1, and TTL = -2, and such. It shouldn't, and the only reason I can think about is that quit() doesn't quite ends the event loop: it allows pending events to be processed before returning from exec(). Is it so? If "no", then what may cause such a behaviour?

Joker_vD
  • 3,715
  • 1
  • 28
  • 42

1 Answers1

7

First of all "You're doing that wrong".

Secondly documentation doesn't say what is the state of queue in event loop after exit was called. It is possible that exec() returns after event queue is empty to make sure that all asynchronous cleanups are done (in case if this it top most event loop, in this case it is).


edit:
I've checked source code. Apparently QEventLoop::processEvents is call between each check that event loop should exit. So it looks like exec() returns only when queue is empty.
Peter R.
  • 71
  • 9
Marek R
  • 32,568
  • 6
  • 55
  • 140
  • I know it is not the most correct way. And now that you confirm that pending events are processed between `quit()` call and actual returning from `exec()`, I guess I have to refactor quite a lot of legacy code. What a joy. Anyway, could you please sketch up the correct way of doing this thing? – Joker_vD Dec 03 '12 at 14:52
  • Very well, I split my class in two parts, but I still need to put `if (ttl <= 0) return;` in the beginning of the `process_request()`. Then what's the big difference, especially since I don't want an "object for manipulating a thread" plus "a task for executing", I just want one "object representing a task in a separate thread". – Joker_vD Dec 05 '12 at 14:00