0

Suppose in a single threaded application, I have created a server and connected a slot with new connection arrival signal like following,

 connect(mTcpServer, SIGNAL(newConnection()), this, SLOT(newClientConnected()));

and after this line I went into a huge loop where I do some calculations. So my single thread which is the main thread is busy in a loop and now a new connection arrives.

So my questions are,

1) In which thread the new slot will be executed? I ask this because
main thread is already executing some code in a loop. 

2) In which thread the event loop is maintained? Because certainly my single
thread is executing some code in a loop and is not maintaining the event loop.

I'm a newbie in QT :(

Tahlil
  • 2,680
  • 6
  • 43
  • 84
  • I don't quite understand the question: you say you have a single-threaded application. As in: there's only one thread. Asking what thread will a slot execute on is weird: there is only one thread, you already know what thread the slot will execute in! – Kuba hasn't forgotten Monica Jan 03 '17 at 17:50
  • @KubaOber,I thought no matter what somehow event loop is always being processed. That's why I was curious that if main thread is not available for that processing then who does it. – Tahlil Jan 04 '17 at 03:29
  • You need to ask a more fundamental question: why do you think that signal and slots necessarily have anything to do with event loops? In your case, a signal-slot connection is **exactly like** using a function pointer. The slot is called from within the signal's body. By the time the signal returns (it's just a method, after all), the slot has been called. Nowhere in this do any event loops appear. Event loops are used to deliver cross-thread/queued slot calls, but you're not doing that. – Kuba hasn't forgotten Monica Jan 04 '17 at 14:26
  • So when the connect function returns,it has already emitted newConnection signal and executed the SLOT? Which means the connect call will be blocked until a new connection come? – Tahlil Jan 05 '17 at 09:44
  • 1
    No, the `connect` method simply adds an entry to a connection list. It's the signal that does all the work of actually invoking the slots. Again - think of how it would work if the signal was a function pointer, and the slot was a function you assigned to the pointer instead of using `connect`. That's more or less how it works. Think of the signal as a list of function pointers with a special call operator: when you invoke it, any slots in the list are called immediately (if they receiving objects are in the same thread, and here they are of course since there are no other threads). – Kuba hasn't forgotten Monica Jan 05 '17 at 13:39
  • Thanks for all the explanation :) I have one last question. As you said the signal can be thought as function pointers and when invoked they will call the function it has pointer to. So which thread invokes the signal? – Tahlil Jan 09 '17 at 03:33
  • *You* invoke the signal. You know what thread it happens in. After all, you invoke the signal from a thread you control. – Kuba hasn't forgotten Monica Jan 09 '17 at 13:36

2 Answers2

2

Main Thread.

Since you are running a single threaded application everything will be handled there (except some IO on the base level).

Your slot will always be executed in the calling thread, except you create a Qt::QueuedConnection to run the slot in the thread the object owning the slot belongs to. This becomes important as soon as you run multiple threads.

Every standard QThread has its own event queue. Since you have a single threaded application your event queue will also run in the main thread.

This concludes during your long running loop there will be no event processing and no handling for new connections.

Solution: Make your long running calculation run in a different thread to keep handling new connections and events. There are different options for you here.

  1. A bit out of favour in most of discussion but still valid for long running operations that do not have to handle signals/events during their calculation is to subclass QThread and reimplement the run() function.

  2. Move your calculation into a function and run it using QtConcurrent::run(), which will automatically use a thread on its own.

  3. Create a subclass of QRunnable and use the global thread pool.

All options are valid but a little different in implementation. See the documentation for more detailed information: http://doc.qt.io/qt-5/thread-basics.html

Sebastian Lange
  • 3,879
  • 1
  • 19
  • 38
  • Thanks very much for the answer. If I understand correctly, If a thread is idle only then its event loop will be at work? In my scenario the event loop will do nothing and even if there is a new connection it won't execute the slot. – Tahlil Jan 03 '17 at 06:58
  • Since your loop is blocking the thread you will have no event handling. So yes, you will not reach the event loop. Your handling of connections is done by the event loop calling your slot. As soon as you return from the slot the event handling will continue. – Sebastian Lange Jan 03 '17 at 07:03
0

In which thread the event loop is maintained? Because certainly my single thread is executing some code in a loop and is not maintaining the event loop.

Each thread can have an event loop. If your code is not returning the control to the event loop in the thread it runs in, you're not going to be processing any events, and are setting yourself up for failure. So don't do that. Transform your code as follows:

// before
forever {
  code();
}

// after
void timerEvent(QTimerEvent *ev) {
  if (ev->timerId() == m_timer.timerId())
    code();
}

void start() {
  m_timer.start(0, this);
}

QBasicTimer m_timer; // class member
Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313