View mode: basic / threaded / horizontal-split · Log in · Help
December 04, 2004
Re: Signals and slots?
Thanks, Pragma, for the introduction :-)

The status is that signals and slots as defined by dcouple are currently 
usable in single-threaded applications. The declaration of signals is a 
tad more verbose than for example Trolltech's Qt framework, but that is 
just syntactic sugar. Connecting/disconnecting them looks actually nicer 
as compared to Qt, and since signals and slots get connected more often 
than declared, we are not too far off.

I should clean up the code a bit, because there are some work-arounds in 
there for compiler limitations that have since been fixed. On the 
todo-list are thread-safety, for which I see no problems. I am also 
interested in benchmarks against C++ implementations.

The big hindrance I see before we can call dcouple a state-of-the-art 
signal and slots implementation, is run-time identification of signals 
and slots in dynamically loaded classes. This is necessary for visual 
GUI designers/builders. Other properties in the classes will also need 
this kind of RTTI. This still needs some thinking, and possibly 
extension of the D language.

A language feature that has been discussed before, called "structed 
classes" (thread "Dropping the distinction between objects and 
references may hinder performance", started 10/18/04 23:12), if it ever 
gets implemented, would take away a good deal of the current complexity 
of dcouple, and improve performance.

By all means, check out dcouple and share your thoughts!
http://svn.dsource.org/svn/projects/dcouple/trunk/managed/doc/index.html

Bastiaan.


pragma wrote:
> I thought this sounded familiar, so I went looking.  Apparently, it's already
> out there.
> 
> http://www.dsource.org/projects/dcouple/
> 
> From the Readme.txt in the svn/trunk:
> 
> The dcouple project is a place for experimenting towards an effective
> implementation of the "signal and slot" call-back concept in D. As the basics
> have already been illustrated by others, the main contribution of this project
> will be usage issues (syntax) and performance in a garbage collected system. The
> ability to break all connections to a particular slot or from a particular
> signal is essential in this respect, and is reflected in the name of this
> project. Hopefully, a library will result that can be included into some
> "standard" library (phobos, deimos, phoenix, whatever) and form the basis of a
> Qt-like GUI library. 
> 
> In article <conii3$tkv$1@digitaldaemon.com>, Georg Wrede says...
> 
>>Hi!
>>
>>How hard would it be to have signals&slots included in the D spec?
>>
>>An intro at http://doc.trolltech.com/3.3/signalsandslots.html describes 
>>the idea as far as Qt is concerned, but this might be a generally useful 
>>thing in any OO language?
>>
>>Since they have implemented this with a couple of preprocessor definitions,
>>it probably wouldn't be too hard to incorporate in the D language core?
>>
>>Code shops usually have their staff writing stock classes between assignments,
>>and having signals&slots would make these classes handier to use. And large
>>programming projects would benefit from looser coupling between objects.
>>
>>I'm not saying SS should be used _instead_ of regular object methods, just
>>that they add value and versatility to a class. And adding some SS to 
>>already existing classes could make them usable in new contexts.
>>
>>(I know, I know) this might be a little too late for D 1.0. :-(
>>
>>Then again, having SS in D 1.0 could make writing usable libraries easier.
>>By D 2.0 we'd have a real mean package!
>>
>>Writing games, UI, multithreaded, real-time, control, OS, ... you name it,
>>SS would be of help.
>>
>>
>>
> 
> 
> - Pragma
December 04, 2004
Re: Signals and slots?
In article <cor3q6$1ls$1@digitaldaemon.com>, Russ Lewis says...
>Georg Wrede wrote:
..
>That would require that the dying object know about all delegates which 
>point to it, and have the ability to zero out their pointers.  That's 

I take it that you have connected all sending objects with delegates
to all those interested in their signals? Thus, 100 sending objects
emitting 10 different signals, and 100 receiving objects, each 
interested in all of them, gives 100*100*10 = 100_000 connections.
Additionally, using delegates, every sending object would "know" 
the recipient?

If all signals are sent via SS Dispatch, then we'd have
100*10 + 10*100 = 2000 connections, only 2% of the former.

If the pointers in SS Dispatch are not reference counted, then
SS objects should signal it from their destructor. A semaphore
in the Dispatch table could guarantee that the destructor does
not return before same-time signals have returned.

BTW, the Dispatch is only interested in signal receiving objects.

>doable, but again, it's complexity better left to an (optional) library.

I agree that new things should be made library, and only later
considered for inclusion into the language. But I can't figure out
how you could end up with a convenient syntax for SS then. Example:

#   // (C++ from QT)
#   class Foo : public QObject
#   {
#       Q_OBJECT
#   public:
#       Foo();
#       int value() const { return val; }
#   public slots:
#       void setValue( int );
#   signals:
#       void valueChanged( int );
#   private:
#       int val;
#   };
#

Of course, one could always run the code through a preprocessor,
but that would be against the spirit of D, right?

>> Race Conditions -- how does D currently handle simultaneous calling
>> of a method in a dying object? How, or whether, it is currently 
>> taken care of, is good enough for SS. Nothing more is needed.
>
>Simple.  We don't GC an object until all references are gone, so that 
>never becomes an issue.
>
>If you manually delete an object, then you are responsible to have 
>already cleaned up all of the lingering references...which is exactly 
>like the old C/C++ way of doing things.

Hmm. This suggests that (if not else, then for Asserts to be possible)
you can ask the GC how many references currently point to an object.
Like when you think there's only one reference to an object and it
turns out there are 5.
December 04, 2004
Re: Signals and slots?
"Georg Wrede" <Georg_member@pathlink.com> wrote in message
news:conii3$tkv$1@digitaldaemon.com...
> Hi!
>
> How hard would it be to have signals&slots included in the D spec?
>
> An intro at http://doc.trolltech.com/3.3/signalsandslots.html describes
> the idea as far as Qt is concerned, but this might be a generally useful
> thing in any OO language?
>
> Since they have implemented this with a couple of preprocessor
> definitions,
> it probably wouldn't be too hard to incorporate in the D language core?
>
> Code shops usually have their staff writing stock classes between
> assignments,
> and having signals&slots would make these classes handier to use. And
> large
> programming projects would benefit from looser coupling between objects.
>
> I'm not saying SS should be used _instead_ of regular object methods, just
> that they add value and versatility to a class. And adding some SS to
> already existing classes could make them usable in new contexts.
>
> (I know, I know) this might be a little too late for D 1.0. :-(
>
> Then again, having SS in D 1.0 could make writing usable libraries easier.
> By D 2.0 we'd have a real mean package!
>
> Writing games, UI, multithreaded, real-time, control, OS, ... you name it,
> SS would be of help.
>
>

Delegates come close but they only fire a single callback instead of 
allowing multiple callbacks. This thread got me thinking about multicast 
delegates (ala C#) so I whipped up another chunk of D code to manage 
multiple delegates. Here's the example from the supplied Qt page modified to 
use multi-delegates, with output:
 class Foo {
   MultiDelegate!(int) valueChanged;
   private int val;
   int value() {
     return val;
   }
   void value(int v) {
     if (val != v) {
       val = v;
       valueChanged(v);
     }
   }
 }

 import std.stdio;
 int main() {
   Foo a = new Foo;
   Foo b = new Foo;
   a.valueChanged ~= &b.value;
   writefln(a.value," ",b.value);
   b.value = 11;
   writefln(a.value," ",b.value);
   a.value = 79;
   writefln(a.value," ",b.value);
   a.valueChanged.remove(&b.value);
   a.value = 100;
   writefln(a.value," ",b.value);
   return 0;
 }

output:

C:\d>dmd multidg.d -version=MultiDgExample
C:\dmd\bin\..\..\dm\bin\link.exe multidg,,,user32+kernel32/noi;

C:\d>multidg
0 0
0 11
79 79
100 79

It's probably almost the same as other implementations only I use dynamic 
arrays instead of associative arrays since:
1) dynamic array take up less space and are faster and most multi-delegates 
will have 1 or 2 delegates attached
2) the order of execution of the delegates matches the order in which they 
were attached.

anyhow, enjoy!

-Ben
December 04, 2004
Re: Signals and slots?
"Georg Wrede" <Georg_member@pathlink.com> wrote in message 
news:cosgvu$23g0$1@digitaldaemon.com...
> In article <cor3q6$1ls$1@digitaldaemon.com>, Russ Lewis says...
>>Georg Wrede wrote:
> ..
>>That would require that the dying object know about all delegates which
>>point to it, and have the ability to zero out their pointers.  That's
>
> I take it that you have connected all sending objects with delegates
> to all those interested in their signals? Thus, 100 sending objects
> emitting 10 different signals, and 100 receiving objects, each
> interested in all of them, gives 100*100*10 = 100_000 connections.
> Additionally, using delegates, every sending object would "know"
> the recipient?
>
> If all signals are sent via SS Dispatch, then we'd have
> 100*10 + 10*100 = 2000 connections, only 2% of the former.

I don't know how SS stores the connection information so it is possible it 
compresses it for special cases but I would guess in reality the set of 
connections is not very compressable. In my experience you typically only 
have 0, 1 or 2 objects listening for a given signal from a given object so 
who cares how it compresses?

> If the pointers in SS Dispatch are not reference counted, then
> SS objects should signal it from their destructor. A semaphore
> in the Dispatch table could guarantee that the destructor does
> not return before same-time signals have returned.
>
> BTW, the Dispatch is only interested in signal receiving objects.
>
>>doable, but again, it's complexity better left to an (optional) library.
>
> I agree that new things should be made library, and only later
> considered for inclusion into the language. But I can't figure out
> how you could end up with a convenient syntax for SS then. Example:
>
> #   // (C++ from QT)
> #   class Foo : public QObject
> #   {
> #       Q_OBJECT
> #   public:
> #       Foo();
> #       int value() const { return val; }
> #   public slots:
> #       void setValue( int );
> #   signals:
> #       void valueChanged( int );
> #   private:
> #       int val;
> #   };
> #
>
> Of course, one could always run the code through a preprocessor,
> but that would be against the spirit of D, right?

see my post using multicast delegates. I think the user code is cleaner than 
the SS example.

>>> Race Conditions -- how does D currently handle simultaneous calling
>>> of a method in a dying object? How, or whether, it is currently
>>> taken care of, is good enough for SS. Nothing more is needed.
>>
>>Simple.  We don't GC an object until all references are gone, so that
>>never becomes an issue.
>>
>>If you manually delete an object, then you are responsible to have
>>already cleaned up all of the lingering references...which is exactly
>>like the old C/C++ way of doing things.
>
> Hmm. This suggests that (if not else, then for Asserts to be possible)
> you can ask the GC how many references currently point to an object.
> Like when you think there's only one reference to an object and it
> turns out there are 5.

There isn't an API to ask the GC how many references point to an object. The 
current implementation of the GC uses a mark-sweep algorithm so it only 
figures out if an object has live references during the GC run and otherwise 
an object has no idea if it is live or not - kindof a bummer to not know if 
you are alive but so it goes :-)

-Ben
December 04, 2004
Re: Signals and slots?
So you create an intermediate object between the various senders and the 
various receievers.  My argument still holds: whoever calls the 
receivers (in this case, the intermediate object) needs to get 
*immediate* notification when an object dies so as to prevent race 
conditions.

Anyhow, it seems that you're missing the point of what I wrote.  I think 
that SS sound really cool!  I would like to try them out!  But they are 
complex enough that they should not be a mandatory part of the language. 
 They should be implemented in a library for now.  Years later, if 
after long experience with it in a library, we all agree that it should 
be part of the next generation language, then we'll do it then.

Russ

Georg Wrede wrote:
> In article <cor3q6$1ls$1@digitaldaemon.com>, Russ Lewis says...
> 
>>Georg Wrede wrote:
> 
> ..
> 
>>That would require that the dying object know about all delegates which 
>>point to it, and have the ability to zero out their pointers.  That's 
> 
> 
> I take it that you have connected all sending objects with delegates
> to all those interested in their signals? Thus, 100 sending objects
> emitting 10 different signals, and 100 receiving objects, each 
> interested in all of them, gives 100*100*10 = 100_000 connections.
> Additionally, using delegates, every sending object would "know" 
> the recipient?
> 
> If all signals are sent via SS Dispatch, then we'd have
> 100*10 + 10*100 = 2000 connections, only 2% of the former.
> 
> If the pointers in SS Dispatch are not reference counted, then
> SS objects should signal it from their destructor. A semaphore
> in the Dispatch table could guarantee that the destructor does
> not return before same-time signals have returned.
> 
> BTW, the Dispatch is only interested in signal receiving objects.
> 
> 
>>doable, but again, it's complexity better left to an (optional) library.
> 
> 
> I agree that new things should be made library, and only later
> considered for inclusion into the language. But I can't figure out
> how you could end up with a convenient syntax for SS then. Example:
> 
> #   // (C++ from QT)
> #   class Foo : public QObject
> #   {
> #       Q_OBJECT
> #   public:
> #       Foo();
> #       int value() const { return val; }
> #   public slots:
> #       void setValue( int );
> #   signals:
> #       void valueChanged( int );
> #   private:
> #       int val;
> #   };
> #
> 
> Of course, one could always run the code through a preprocessor,
> but that would be against the spirit of D, right?
> 
> 
>>>Race Conditions -- how does D currently handle simultaneous calling
>>>of a method in a dying object? How, or whether, it is currently 
>>>taken care of, is good enough for SS. Nothing more is needed.
>>
>>Simple.  We don't GC an object until all references are gone, so that 
>>never becomes an issue.
>>
>>If you manually delete an object, then you are responsible to have 
>>already cleaned up all of the lingering references...which is exactly 
>>like the old C/C++ way of doing things.
> 
> 
> Hmm. This suggests that (if not else, then for Asserts to be possible)
> you can ask the GC how many references currently point to an object.
> Like when you think there's only one reference to an object and it
> turns out there are 5.
> 
>
December 05, 2004
Re: Signals and slots?
In article <conii3$tkv$1@digitaldaemon.com>, Georg Wrede says...
>
>How hard would it be to have signals&slots included in the D spec?
>

Hi!
Walter is in trouble because he has two "twins" in D: function pointers and
delegates. He doesn't know what to do with them. He doesn't understand S&S well,
they OOP-ish and power. There is must be delegates and S&S instead of function
pointers and delegates. But Walter still love C too much... shame! He froze any
move in this way.
:-(
December 07, 2004
Re: Signals and slots?
In article <cosich$255j$1@digitaldaemon.com>, Ben Hinkle says...
>
>
>"Georg Wrede" <Georg_member@pathlink.com> wrote in message
>news:conii3$tkv$1@digitaldaemon.com...
>> Hi!
>>
>> How hard would it be to have signals&slots included in the D spec?
>output:
>
>C:\d>dmd multidg.d -version=MultiDgExample
>C:\dmd\bin\..\..\dm\bin\link.exe multidg,,,user32+kernel32/noi;
>
>C:\d>multidg
>0 0
>0 11
>79 79
>100 79
>
>It's probably almost the same as other implementations only I use dynamic 
>arrays instead of associative arrays since:
>1) dynamic array take up less space and are faster and most multi-delegates 
>will have 1 or 2 delegates attached
>2) the order of execution of the delegates matches the order in which they 
>were attached.
>
>anyhow, enjoy!
>
>-Ben

Cool code! I'll use this.
December 07, 2004
Re: Signals and slots?
In article <cot4qh$2soj$1@digitaldaemon.com>, Russ Lewis says...
>
>Anyhow, it seems that you're missing the point of what I wrote.  I think 
>that SS sound really cool!  I would like to try them out!  But they are 
>complex enough that they should not be a mandatory part of the language. 
>
>They should be implemented in a library for now.  Years later, if 
>after long experience with it in a library, we all agree that it should 
>be part of the next generation language, then we'll do it then.

What can I say, I'm getting convinced!

Somehow this reminds me of the times everyone did their own linked lists
and trees again and again. It sure took a long time for mainstream 
languages to render that daily chore obsolete.

Actually, the only thing why I thought they should be in the language
core was to get a nice syntax. But on second thought that is a minor
issue.
December 09, 2004
Re: Signals and slots?
Dr.Dizel wrote:
> In article <conii3$tkv$1@digitaldaemon.com>, Georg Wrede says...
> 
>>How hard would it be to have signals&slots included in the D spec?
>>
> 
> 
> Hi!
> Walter is in trouble because he has two "twins" in D: function pointers and
> delegates. He doesn't know what to do with them. He doesn't understand S&S well,
> they OOP-ish and power. There is must be delegates and S&S instead of function
> pointers and delegates. But Walter still love C too much... shame! He froze any
> move in this way.
> :-(
> 
> 

Sorry Dizel, you must be trolling.
December 10, 2004
Re: Signals and slots?
Dr.Dizel wrote:

> In article <conii3$tkv$1@digitaldaemon.com>, Georg Wrede says...
>>
>>How hard would it be to have signals&slots included in the D spec?
>>
> 
> Hi!
> Walter is in trouble because he has two "twins" in D: function pointers
> and delegates. He doesn't know what to do with them. He doesn't understand
> S&S well, they OOP-ish and power. There is must be delegates and S&S
> instead of function pointers and delegates. But Walter still love C too
> much... shame! He froze any move in this way.
> :-(

Function pointers are still very useful for interfacing with C projects. 
They serve a different purpose than delegates.  I think you're hacking away
at a straw man.
Next ›   Last »
1 2
Top | Discussion index | About this forum | D home