2

In Qt, how does one avoid race conditions if signals can be emitted around the same time when I connect to them?

Consider the following naïve example:

MySignalSender *sender = new MySignalSender(); // starts async operation that emits `fooSignal`
// <-- Possibility (1): `fooSignal` can be emitted here
MySignalReceiver *receiver = new MySignalReceiver();
// <-- Possibility (2): `fooSignal` can be emitted here
QObject::connect(sender, &MySignalSender::fooSignal, receiver, &MySignalReceiver::fooSlot);
// <-- Possibility (3): `fooSignal` can be emitted here or later

Since fooSignal is emitted from another thread, the choice of possibilities 1-3 is realized non-deterministically by the scheduler at runtime. While the desired behavior would only be achieved in the third case, in the remaining two we lose the signal, likely leading to a deadlock or some other undefined behavior.

Does Qt offer some atomic mechanism to temporarily pause signals from objects? I'm aware of QObject::blockSignals(), however my understanding is that this suppresses signals entirely rather than just postponing them for a while.

Thank you in advance!

scopchanov
  • 7,966
  • 10
  • 40
  • 68
Petr Mánek
  • 1,046
  • 1
  • 9
  • 24

1 Answers1

2

One option is to simply change the way you're constructing the objects sending the signals. You can separate the construction of the object from the starting of the async operation.

MySignalSender *sender = new MySignalSender();
MySignalReceiver *receiver = new MySignalReceiver();
QObject::connect(sender, &MySignalSender::fooSignal, receiver, &MySignalReceiver::fooSlot);

sender->startAsyncOperations();
JarMan
  • 7,589
  • 1
  • 10
  • 25
  • Agreed, I would do this with objects that are within my control. Unfortunately this is not a possibility when calling Qt library objects, e.g. `QNetworkAccessManager::get()`. What to do then? – Petr Mánek Oct 27 '20 at 16:37
  • 2
    In that specific case, I've always connected to the QNetworkAccessManager, rather than the QNetworkReply. But I understand your point. – JarMan Oct 27 '20 at 16:45
  • 1
    Oh that's cool, didn't know you could do that. Cheers! – Petr Mánek Oct 27 '20 at 16:53