1

I am working on some code where I see the following:

In header file:

private slot:
  void OnNotifySomeSlot(const QList<bool>& someList); // Note the argument is pass by const ref

In implementation file:

connect(&m_serviceObj,SIGNAL(NotifySomeSlot(QList<bool>)), this, SLOT(OnNotifySomeSlot(QList<bool>)); // Note that arguments are pass by value

Slot function definition:

void OnNotifySomeSlot(const QList<bool>& someList)
{
  m_list = someList;
} // Note that argument is passed by const ref as in the header 

Now my doubt is that:

1: Why is such a code getting compiled as there is difference in signature between connect statement and slot definition?

2: During runtime if the value is getting passed a const ref , will it still not cause problems in a multithreaded environment. Because the reference to the list (be it const) can still be modified by some other code referring the same list in a multithreaded environment.

3: Can we just "pass by value" everywhere to avoid any issue in a multi threaded environment. Will it make the application slower?

273K
  • 29,503
  • 10
  • 41
  • 64
Avi
  • 71
  • 5
  • Does the slot get triggered? – RoQuOTriX Aug 18 '22 at 06:44
  • `SIGNAL` and `SLOT` are macros, not method signatures. The connection is made at runtime, not at compile time, so you should not expect the compiler to complain, but I believe this code will run properly. (https://stackoverflow.com/questions/31589435/signal-slot-macros-in-qt-what-do-they-do) – dmedine Aug 18 '22 at 06:59
  • In this code you copy your referenced list in the body of the slot method, so once you return, you can modify the object referenced without issue. You probably don't want to modify anything belonging to the GUI thread off of the GUI thread---in fact you might not be able to. – dmedine Aug 18 '22 at 07:03
  • Possible duplicate: https://stackoverflow.com/questions/2582797/why-pass-by-const-reference-instead-of-by-value?rq=1 but passing by value is always slower because a copy is involved. – dmedine Aug 18 '22 at 07:06
  • And passing by value doesn't help you when you run into certain concurrency issues. You can always pass by value and still end up in a data race/deadlock or cause indeterminate behavior. – dmedine Aug 18 '22 at 07:09
  • @RoQuOTriX The slot is working fine – Avi Aug 18 '22 at 08:25
  • @dmedine Does it mean the slot reference points to a local copy when the slot is triggered. If that is the case it is safe to use const ref ? – Avi Aug 18 '22 at 08:29
  • @dmedine The only race condition I am worried about here is that the "reference to list" is not modified by some other code while this slot is getting executed. – Avi Aug 18 '22 at 08:37
  • 1
    You should stop using the SIGNAL and SLOT macros and switch to compile-time connections. – Botje Aug 18 '22 at 08:38

1 Answers1

2

Answering your questions in order:

  1. The Qt macro machinery canonicalizes signal and slot names so they "fit". If you use the modern connection approach you do not have to worry about this:
QObject::connect(m_serviceObj, &SomeServiceObjectClass::NotifySomeSlot, this, &ThisObjectClassOnNotifySomeSlot)
  1. Yes, even though you pass the list as a const ref, some other thread that has a non-const ref can change it behind your back.
  2. Yes, passing it by value makes this behave properly. It is also efficient, as QList is an "implicitly shared" datastructure. This means that a copy is only made when a mutation happens, by the thread doing the mutation.
Botje
  • 26,269
  • 3
  • 31
  • 41