Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Re: Free lightweight C++ signals and slots library

Reply
Thread Tools

Re: Free lightweight C++ signals and slots library

 
 
Marcel Müller
Guest
Posts: n/a
 
      08-12-2012
On 11.08.12 14.32, Leigh Johnston wrote:
> I present "neosigslot" a new, free to use/modify, lightweight signals
> and slots library that has the following features:
>
> * Automatic deregistration of slots from signals when a slot is
> destroyed.
> * Fully re-entrant: signals and slots can be destroyed, added and
> signals triggered whilst a slot is being notified of a signal.
> * Support for "slots with keys" to allow one signal to be used for
> more than one event (e.g. GUI menu command IDs).
> * Support for up to 10 signal arguments (if you need more see a doctor
> or edit the source).
> * Threading policy (by default mutex locking is turned on ensuring
> thread safety but a no locking policy can also be specified).
>
> http://i42.co.uk/stuff/neosigslot.htm


Hmm, I wrote a similar set of classes some time ago.

You spent quite much effort to make it re-entrant. But from what I can
see each invocation of trigger copies a notification list. This is a
high price. But, maybe I did not catch your implementation correctly.

Furthermore, I think the mutex solution may deadlock, because the mutex
is held until the event handlers have completed. While this is no
problem when calling myself, it might become a problem if two signals
are involved and if thread 1 calls signal2.trigger() in the handler of
signal1 and thread 2 vice versa.
Of course, without this mutex the handling of slot destruction while a
signal handler is active becomes a tricky task. But it is always
critical to call handlers from some internal, synchronized context.

I have no real clean solution for the mutex problem. I have run into the
same problem and decided to use some static mutex together with
cond-vars to handle the destructors. So I need to synchronize access to
the notification list only when advancing to the next slot in trigger.

Another solution instead of your notification lists might use a revision
counter. It is incremented at each invocation of add/remove. The counter
is part of signal_base and it is copied into the registered slots.
Trigger samples the revision counter and takes care of it during
invocation of the handlers.
Additionally you need a reference counter on each registered slot. It is
incremented at add and decremented at remove. And it is incremented at
the start of trigger for the current content of the slot list and
decremented after a slot has been handled by trigger. As usual as soon
as it counts to zero, the entry could be removed from the map.
To avoid ABA problems you need to use a multi_map or put the counter
into the key, because different revisions of the same slot may coexist
for short times.

A even more sophisticated task might be to do most of the operations
lock free, because dealing with several thousands of mutexes of several
thousand signals could be a serious problem on some platforms.
I have gone this way to some degree, but the price is that remove is now
O(n) instead of O(log(n)) of your implementation. Most likely a lock
free skip list could improve that, but I did not spent much time in this
topic because more that two dozen registrations per signal are very
uncommon in my use case.


Marcel
 
Reply With Quote
 
 
 
 
Marcel Müller
Guest
Posts: n/a
 
      08-12-2012
On 12.08.2012 16:12, Leigh Johnston wrote:
>> Furthermore, I think the mutex solution may deadlock, because the mutex
>> is held until the event handlers have completed. While this is no
>> problem when calling myself, it might become a problem if two signals
>> are involved and if thread 1 calls signal2.trigger() in the handler of
>> signal1 and thread 2 vice versa.
>> Of course, without this mutex the handling of slot destruction while a
>> signal handler is active becomes a tricky task. But it is always
>> critical to call handlers from some internal, synchronized context.

>
> Not sure if it will currently deadlock as you describe as you cannot
> send signals between threads (i.e. signal2 handler would still be
> thread1).


No, I am talking about two asynchronous signals created by independent
threads. It's quite simple to get that.

Think of a change notification of two dependent objects. E.g. a page and
a document. Changing a page may also change some aggregate properties of
the document (e.g. the number of words). Changing document properties
like the footer area may also introduce changes to the pages. If these
two action happen concurrently than thread 1 may lock the mutex of the
page while thread 2 locks the mutex of the document. None of the threads
will ever be able to acquire the second mutex to dispatch the dependency
change events.


Marcel
 
Reply With Quote
 
 
 
 
Marcel Müller
Guest
Posts: n/a
 
      08-13-2012
On 13.08.2012 00:29, Leigh Johnston wrote:
> After further thought yes I agree deadlocks you mention are possible
> however thread 1 should not be triggering signals which are also handled
> by thread 2 and vice-versa; if you keep this in mind there should be no
> problems.


OK, this means that an event handler (that is generally from another
object) must not fire other events, because it cannot ensure that it is
in the same thread from what the events are normally fired. This
secondary event has to be dispatched to the thread that "owns" the
corresponding signal class. You need to post the event in an
asynchronous queue of the target thread. (No serious problem in GUI
applications with message queues, but inconvenient in others.)
Is this that the inter-thread signalling feature, you mentioned?

One should aware of this restriction.


Marcel
 
Reply With Quote
 
Marcel Müller
Guest
Posts: n/a
 
      08-15-2012
On 13.08.2012 16:26, Leigh Johnston wrote:
> An event handler can fire other events no problem if the programmer
> knows that it is the same thread (which is almost certainly the case if
> the programmer is in control of the software design).


If an event handler can safely fire other events (with the restriction),
it must always be called from the same thread. And furthermore the event
that it fires must also always be called by the same thread only. In
fact that means that your application must be single threaded with
respect to event processing.

But if there is a strict ordering of all events, i.e. event A can call
ebent B but never the other way around, then none of the restrictions apply.

Marcel

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Github (was Re: Free lightweight C++ signals and slots library) Jorgen Grahn C++ 11 08-21-2012 08:08 PM
Re: Free lightweight C++ signals and slots library Rui Maciel C++ 0 08-11-2012 08:54 PM
A problem with slots and signals in a simple widget in Qt Alex M. C++ 4 08-02-2010 06:34 PM
slots? SLOTS? tin gherdanarra Python 2 10-13-2005 12:31 AM



Advertisments