On Fri, Jul 23, 2021 at 4:39 PM Thiago Macieira via Std-Proposals <std-proposals@lists.isocpp.org> wrote:
On Friday, 23 July 2021 13:26:49 PDT Tony V E wrote:
> Does Qt hold a lock on the current slot when calling the slot?

Slots are not objects that can be locked. They are just functions.

Sure. I mean a lock that represents/protects that slot.
 

> Boost.Signals2 doesn't lock the *list* of slots, but locks the individual
> slot.
>
> If another thread tries to disconnect the currently executing slot (say,
> because the slot target is being deleted) then it *must* wait for the slot
> to finish (else the slot might crash).
> If it must wait, it must hold a lock.

Right, the list is locked, but gets unlocked before every slot is called. So
those things end up operating independently. If the signal activation decided
to call that slot before it was disconnected, then it will get called. If the
disconnection happened first, then it won't.


And that's fine for DirectActivation.

 
> Qt (I think) avoids this because it uses an event queue - slots across
> threads are not called directly, they are queued.  When an object is
> deleted, you "just" need to remove the to-be-called slot from the queue.
> The Qt idea that an object "lives" on a specific thread is a great way of
> dealing with many things.

Only for Qt::QueuedActivation.

Yeah, that's the case I'm talking about.  Which is the case for objects living on other threads (unless someone is brave enough to force a interthread connection to be Direct).
 
Qt::DirectActivation (which is the default for
target objects living in the current thread) does not queue up. It does as
described above: drop the lock, call, reacquire the lock.


 
As for queued activations already queued but not yet delivered, the
destruction of the target object removes all pending events from the event
queue.

Yeah, that's the special sauce that avoids the problems. In the general (non-Qt) case, you don't have a queue mechanism to fall back on.

 

> Without a separate (global/findable) queue, you either hold a lock (risking
> deadlock) or don't hold a lock and risk crashing.

Or you drop the lock and don't crash.

You don't crash because you never delete an object from thread A while the slot is running from thread B.

In the non-Qt non-queue-available-for-threads world, you can't synchronize the deletion from thread A with a slot from thread B.

Before destroying your object, you want to make sure all connections are disconnected.  So you can call disconnect.  But is there a slot in progress in another thread? The only way (sans queue) disconnect() can know is by waiting.

In general, you want the contract of disconnect() to be "a slot will not be called after disconnection".  Seems like a simple and reasonable guarantee.
But it is hard. Either disconnect() needs to *wait* for a slot to finish, or cross-thread slots are queued, and disconnect() empties the queue of pending slots.
Furthermore, emptying the queue would need to wait for the current in-progress queue event to finish (if it was a slot), but in Qt that's fine because the delete is happening in that same thread. If a slot is in progress, the delete is happening _in that slot_.

Qt avoids the slot or list lock *because* it uses queues for the async slots.
I suppose if I did an explicit DirectActivation connection across threads, I could demonstrate the problem scenario in Qt, but the rule in Qt is just don't do DirectActivation across threads, or at least be very careful if you do.
 

The connection list has a flag saying "in use", which means the list can't be
shrunk or garbage collected. Disconnections can still happen by removing the
effect of the entry in the list, but the size of list doesn't change.


Yes, that's fine for the list handling. 
 
Then we just need to prevent livelocks: what happens if you *connect*
something else to the same signal that is being activated, every time that a
given slot is activated?

Yeah, do you get added to the end of the current list (ie will your slot be called on this signal), or wait for the next signal?  I say wait for the next signal.


 

--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
   Software Architect - Intel DPG Cloud Engineering



--
Std-Proposals mailing list
Std-Proposals@lists.isocpp.org
https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals


--
Be seeing you,
Tony