How to enforce signals to behave as callback
What I want to do is to emit signal as standard callback so that execution blocks until all slots are finished - otherwise it will break logic of my program (emitter depends on actions taken by slots at that time).
I now that I can use Qt::AutoConnection (in the same thread), Qt::DirectConnection or Qt::BlockingQueuedConnection but it depends on how the slots are attached to signal's object (one can connect slots as Qt::QueuedConnection). Is there any way to enforce direct connection ?
You can declare the "connection type in every connect statement":http://qt-project.org/doc/qt-5.0/qtcore/qobject.html#connect you can overwrite the default.
so i will have to document this feature like "do not attache nonblocking slots" ?
Maybe there is some better solution for this usecase ?
As long as your application is single thread things are quite easy. As there only is a single thread, everything is serialized! So when you call an emit(), all connected slots are executed before the next instruction after the emit() is executed. So there is not much to worry about here.
Things get more complicated, when you have multiple threads. More specifically, things get different, when you send a signal to an object that belongs to a different thread. In this case, the default (Qt::QueuedConnection) connection type will simply put the signal into the thread's queue and then go on immediately. The thread's event loop will pick up the pending signal from the queue and, eventually, execute the slot.
Though, if you need to serialize things in this case too, then simply enforce the Qt::BlockingQueuedConnection type and everything will be as desired. The slot will still be executed in context the target thread, i.e. it will be executed by thread's event loop, but the emit() in the sender thread will not return until the slot has been executed.
When sending signals to a different thread, be VERY careful with Qt::DirectConnection though! It would execute the slot in the context of the sender thread! At the same time, the thread to which the object belongs goes on, without even noticing the signal has occurred! This can easily lead to race conditions and undesired results. It would only be "safe", if the slot either does not access member variables at all or if all access to member variables is carefully protected with Mutexes - not only in the slot function itself, but everywhere where they are used!