www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Signals & Slots

reply "David B. Held" <dheld codelogicconsulting.com> writes:
I know much has been said about this topic over the years, and several 
libraries have been written.  Can anyone summarize the state of the art 
for S&S in D?  I know there is a std.signals, but I can see that it is 
not the end of the story...

Dave
Nov 04 2007
next sibling parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
David B. Held wrote:
 I know much has been said about this topic over the years, and several 
 libraries have been written.  Can anyone summarize the state of the art 
 for S&S in D?  I know there is a std.signals, but I can see that it is 
 not the end of the story...
 
 Dave
I'd like to know what the current story is too, both in Phobos and Tango. Mainly I mean the current story with regard to weak references. --bb
Nov 05 2007
parent Sean Kelly <sean f4.ca> writes:
Bill Baxter wrote:
 David B. Held wrote:
 I know much has been said about this topic over the years, and several 
 libraries have been written.  Can anyone summarize the state of the 
 art for S&S in D?  I know there is a std.signals, but I can see that 
 it is not the end of the story...
I'd like to know what the current story is too, both in Phobos and Tango. Mainly I mean the current story with regard to weak references.
Tango does not currently support weak references. This was a deliberate decision on my part because I do not feel that weak references are compatible with garbage collection in D. In a multithreaded program, the only way to safely use the callback mechanism built to support the weak reference concept is by using lock-free programming (using synchronized blocks instead is a sure way to deadlock an application when using "stop the world" collections). However, lock-free programming is quite complicated and utterly non-portable, given its reliance on specialized knowledge of the target memory model. Therefore, I can't rationalize adding a feature that is so prone to error and misuse unless it provides an extremely compelling reason for its presence. And I'll admit that I question the point of needing the weak reference feature for S&S in the first place. I feel that doing so encourages bad programming style, and frankly, I can't envision a programming model that requires it anyway. But then I'm not a Qt person, so perhaps someone could explain the need for this to me? If it's any consolation, the Tango/Phobos merger will basically require that weak reference support be added to the runtime unless Phobos decides this feature is no longer necessary. So my opinion in the matter may ultimately be rendered unimportant. Unfortunately, this will complicate the means by which object monitors are overridden in Tango, but I don't think there's any way around this. Sean
Nov 05 2007
prev sibling parent reply Lutger <lutger.blijdestijn gmail.com> writes:
David B. Held wrote:
 I know much has been said about this topic over the years, and several 
 libraries have been written.  Can anyone summarize the state of the art 
 for S&S in D?  I know there is a std.signals, but I can see that it is 
 not the end of the story...
 
 Dave
Besides std.signals, there is a S&S implementation in Tango, one in Luigi by Bill Baxter and one written by myself (sslot). There are mostly two differences between these implementations: thread-safety and the types of slots that are allowed to connect. The tango implementation is thread-safe, at the cost of being unable to 'track' connections. sslot has a thread-safe implementation which frankly stinks, because it's not really thread-safe at all (deadlock possibility in some - documented - circumstances). The ones in Luigi and sslot are the most generic, and tango's signals can also accept functions. std.signals only accepts member functions. It's not possible in any of the current implementations (that I'm aware of) to have both managed or tracked connections and thread-safety. I doubt it is possible at all to do in a reasonable efficient manner currently. Perhaps when reference counting will come to D.
Nov 05 2007
next sibling parent reply Lars Ivar Igesund <larsivar igesund.net> writes:
Lutger wrote:

 David B. Held wrote:
 I know much has been said about this topic over the years, and several
 libraries have been written.  Can anyone summarize the state of the art
 for S&S in D?  I know there is a std.signals, but I can see that it is
 not the end of the story...
 
 Dave
Besides std.signals, there is a S&S implementation in Tango, one in Luigi by Bill Baxter and one written by myself (sslot). There are mostly two differences between these implementations: thread-safety and the types of slots that are allowed to connect. The tango implementation is thread-safe, at the cost of being unable to 'track' connections. sslot has a thread-safe implementation which frankly stinks, because it's not really thread-safe at all (deadlock possibility in some - documented - circumstances). The ones in Luigi and sslot are the most generic, and tango's signals can also accept functions. std.signals only accepts member functions. It's not possible in any of the current implementations (that I'm aware of) to have both managed or tracked connections and thread-safety. I doubt it is possible at all to do in a reasonable efficient manner currently. Perhaps when reference counting will come to D.
Walter claims that the notifyRegister/Unregister method used by among others std.signals _are_ threadsafe. If you are using the same methods, can you reproduce deadlocks with sslot? It would be nice to have some actual evidence in this matter (either way, although I understand that complete thread safety may be impossible to prove for an efficient solution). -- Lars Ivar Igesund blog at http://larsivi.net DSource, #d.tango & #D: larsivi Dancing the Tango
Nov 05 2007
next sibling parent Lutger <lutger.blijdestijn gmail.com> writes:
Lars Ivar Igesund wrote:
 Lutger wrote:
...
 Walter claims that the notifyRegister/Unregister method used by among others
 std.signals _are_ threadsafe. If you are using the same methods, can you
 reproduce deadlocks with sslot? It would be nice to have some actual
 evidence in this matter (either way, although I understand that complete
 thread safety may be impossible to prove for an efficient solution).
 
Hmmm, I remember Walter saying std.signals isn't thread-safe, maybe I;m wrong? Sean mentioned the reason the notifyRegister/Unregister methods aren't implemented in Tango is the potential for deadlocks. Here is the deadlock scenario as I understand it: 1) delegate A is stored by notifyRegister (as a weak reference that is). 2) Method B gets a lock 3) Concurrently, Object C is being collected, all threads halt 4) As a result of 3, delegate A is invoked and calls method B 5) deadlock I'll try to make a case where this happens as proof.
Nov 05 2007
prev sibling next sibling parent reply Lutger <lutger.blijdestijn gmail.com> writes:
Lars Ivar Igesund wrote:

 It would be nice to have some actual
 evidence in this matter (either way, although I understand that complete
 thread safety may be impossible to prove for an efficient solution).
 
The following hack resulted in a deadlock on my machine. I also found some access violations, this is perhaps a bug in sslot. A similar program for std.signals also gave deadlocks. Well, this thread has reminded me I should remove the pretense that is multithreaded signals in sslot :) import std.stdio; import std.thread; import std.gc; import sslot = sslot.signal; class Observer { void watch(char[] msg, int i) { writefln("Observed msg '%s' and value %s", msg, i); } ~this() { writef("died..."); } } sslot.SignalMT!(void, char[], int) signal; class FooThread : Thread { int run() { while(true) { Observer o = new Observer; signal ~= &o.watch; signal("message", 2); o = null; std.gc.fullCollect(); } return 0; } } void main() { std.gc.minimize(); signal = new sslot.SignalMT!(void, char[], int); auto thread = new FooThread; thread.start(); while(true) signal("message", 1); }
Nov 05 2007
parent Sean Kelly <sean f4.ca> writes:
Lutger wrote:
 Lars Ivar Igesund wrote:
 
 It would be nice to have some actual
 evidence in this matter (either way, although I understand that complete
 thread safety may be impossible to prove for an efficient solution).
The following hack resulted in a deadlock on my machine. I also found some access violations, this is perhaps a bug in sslot. A similar program for std.signals also gave deadlocks.
Weird, I'd expect std.signals to work. But then I just glanced at the implementation so perhaps it has a bug or two. In theory, std.signals could work, but the implementation would have to be very carefully done (and lock-free as it is now). Sean
Nov 05 2007
prev sibling next sibling parent Lutger <lutger.blijdestijn gmail.com> writes:
Lars Ivar Igesund wrote:
 Lutger wrote:
...
 Walter claims that the notifyRegister/Unregister method used by among others
 std.signals _are_ threadsafe. If you are using the same methods, can you
 reproduce deadlocks with sslot? It would be nice to have some actual
 evidence in this matter (either way, although I understand that complete
 thread safety may be impossible to prove for an efficient solution).
 
I should have read the docs for std.signals first, it states: "Not safe for multiple threads operating on the same signals or slots." The thing is, notifyRegister itself is threadsafe, but when the delegate that it stores is called all threads are halted so it's really not safe to use at all in a multithreaded program if you aren't very careful.
Nov 05 2007
prev sibling parent Sean Kelly <sean f4.ca> writes:
Lars Ivar Igesund wrote:
 Lutger wrote:
 It's not possible in any of the current implementations (that I'm aware
 of) to have both managed or tracked connections and thread-safety. I
 doubt it is possible at all to do in a reasonable efficient manner
 currently. Perhaps when reference counting will come to D.
Walter claims that the notifyRegister/Unregister method used by among others std.signals _are_ threadsafe. If you are using the same methods, can you reproduce deadlocks with sslot? It would be nice to have some actual evidence in this matter (either way, although I understand that complete thread safety may be impossible to prove for an efficient solution).
I'm fairly sure this is correct, assuming an x86 CPU. The Phobos S&S implementation is lock-free. Sean
Nov 05 2007
prev sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
Lutger wrote:
 std.signals only accepts member functions.
That is not exactly correct, it accepts delegates. Delegates are a superset of member functions and nested functions. std.signals is also thread safe.
Nov 05 2007
parent reply Lutger <lutger.blijdestijn gmail.com> writes:
Walter Bright wrote:
 Lutger wrote:
 std.signals only accepts member functions.
That is not exactly correct, it accepts delegates. Delegates are a superset of member functions and nested functions. std.signals is also thread safe.
Has it been changed then? At least the documentation states: BUGS: Slots can only be delegates formed from class objects or interfaces to class objects. If a delegate to something else is passed to connect(), such as a struct member function, a nested function or a COM interface, undefined behavior will result. Not safe for multiple threads operating on the same signals or slots. http://www.digitalmars.com/d/1.0/phobos/std_signals.html
Nov 05 2007
parent Walter Bright <newshound1 digitalmars.com> writes:
Lutger wrote:
 Walter Bright wrote:
 Lutger wrote:
 std.signals only accepts member functions.
That is not exactly correct, it accepts delegates. Delegates are a superset of member functions and nested functions. std.signals is also thread safe.
Has it been changed then? At least the documentation states: BUGS: Slots can only be delegates formed from class objects or interfaces to class objects. If a delegate to something else is passed to connect(), such as a struct member function, a nested function or a COM interface, undefined behavior will result. Not safe for multiple threads operating on the same signals or slots. http://www.digitalmars.com/d/1.0/phobos/std_signals.html
Oops, you're right. My mistake.
Nov 05 2007