Solved QThread's time slice and signal/slot response
-
Hi
After the question aboutQthread
's context switch, I confuse about the response between a signal in one thread and a slot in the other thread.- Dose the slot's thread response the signal after the time slice of signal thread over?
- If using
QThread::yieldCurrentThread()
after sending the signal, does the context switch still depend on theQThread::priority()
? But if both threads areQThread::NormalPrority
, is random? - If a thread has only a slot ( without any other function,just
void on_signal_received();
), do you have a way to switch to this thread till receiving signal? - BTW,could you provide the processes of responding signal.
Regards
Mihan -
@Mihan said in QThread's time slice and signal/slot response:
- Dose the slot's thread response the signal after the time slice of signal thread over?
No. The timing of the receiver thread does not depend on what's happening on the sender thread.
- If using
QThread::yieldCurrentThread()
after sending the signal, does the context switch still depend on theQThread::priority()
? But if both threads areQThread::NormalPrority
, is random?
No. We cannot control the context switching like that.
Why do you need to control the switching?
Note: On a multi-core CPU, there might not be any context switching at all. The sender thread could run on one CPU core, and the receiver thread could run on a different CPU core — Both threads could be active at the same time, without switching.
- BTW,could you provide the processes of responding signal.
- The sender thread emits the signal.
- The signal's information is queued in the receiver thread's event loop.
- When the receiver thread's event loop has finished its current task (or if the event loop was idle when the signal arrived), it starts processing the signal.
-
Thanks, @JKSH
Does it mean the receive thread with the other thread on the same CPU will respond the signal by the processes above till (context switch) switch to it ?OTOH,if there is a loop, does it mean the receive thread will never respond the signal untill the loop over or using
qApp::processEvents()
in the loopI hope the main thread can be active as far as possible to ensure the smooth running; other threads can be inactive after finishing the jobs as soon as possible. Cound I use
sleep()
orQThread::yieldCurrentThread()
to achieve this?
e.g. the slot can finish the job in 5ms, but the thread's time slice of this slot is 100ms, is the rest of time(95ms) wasted?OTOH, is there any function like
ucontext
in Qt. Maybe my project has too many threads so that make the context switch frequent( more than 5000 times ) (double-core CPU) (usingvmstat
to get this) -
@Mihan said in QThread's time slice and signal/slot response:
I hope the main thread can be active as far as possible to ensure the smooth running
Again: you can't control this (and there is no need for it in most cases). You can set a thread priority but you can't force a context switch (if there is any needed at all).
-
@Mihan said in QThread's time slice and signal/slot response:
Does it mean the receive thread with the other thread on the same CPU will respond the signal by the processes above till (context switch) switch to it ?
I don't understand your question, sorry.
if there is a loop, does it mean the receive thread will never respond the signal untill the loop over or using
qApp::processEvents()
in the loopThe thread's event loop actively processes the signals as fast as it can. You don't need to call
processEvents()
.Do not put your own infinite loop (like
while (true) { ... }
) in a thread that needs to receive signals.I hope the main thread can be active as far as possible to ensure the smooth running
All you need to do is make sure that the functions in your main thread return quickly. That will ensure that your main thread is always smooth running.
Cound I use
sleep()
orQThread::yieldCurrentThread()
to achieve this?No. These functions stop the current thread. They do not force a different thread to start running.
e.g. the slot can finish the job in 5ms, but the thread's time slice of this slot is 100ms, is the rest of time(95ms) wasted?
No, the event loop doesn't work like that. If it starts running a slot at t=0ms and finishes at t=5ms, then it will start running the next slot at t=6ms.
OTOH, is there any function like
ucontext
in Qt.I would not use
ucontext
. You don't need it.Just let Qt manage its own timing. It is very efficient.
-
@Mihan said in QThread's time slice and signal/slot response:
Hi
Hi.
- Dose the slot's thread response the signal after the time slice of signal thread over?
No, because time slices in a multitasking system are controlled by the scheduler and after your slice's over then another thread/process can be activated, although you may get another slice. You can't (nor should you be able to) force the scheduler to allocate a slice to a specific thread.
- If using
QThread::yieldCurrentThread()
after sending the signal, does the context switch still depend on theQThread::priority()
?
Yes and no.
QThread::yieldCurrentThread()
tells the scheduler that you don't need your full time slice, but it's ultimately up to the kernel to decide which thread (if any) is going to get the reminder of it and how that's decided. Usually yes, it's going to trigger a context switch, and usually higher priority threads (if the OS supports them) get slices more often, but both of those are beyond your control.But if both threads are
QThread::NormalPrority
, is random?From your point of view as a programmer it's still random either way, or rather non-deterministic.
- If a thread has only a slot ( without any other function,just
void on_signal_received();
), do you have a way to switch to this thread till receiving signal?
Let's break it down a bit. Why would a thread's worker have only one slot to begin with? And yes, you can do it, but not in the way you think you can, use imperative thread control (i.e. blocking primitives). Something along these lines:
QSemaphore waitForActivated, activateCaller; void WorkerThread::activateThread() { waitForActivated.release(); activateCaller.acquire(); } void WorkerThread::run() { waitForActivated.acquire(); while (!isInterruptionRequested()) { // Do stuff } activateCaller.release(); }
You activate the above by calling
activateThread()
either directly or through aQt::DirectConnection
, which causes the caller to sleep until the thread's run its course. after that the caller's freed. The internal loop can be broken by a third thread that callsQThread::requestInterruption()
if needed.- BTW,could you provide the processes of responding signal.
This doesn't even make sense to me. What do you mean?