Sign in to follow this  
RobAU78

Signals and Slots

Recommended Posts

Hey everyone, Lately I've been investigating the concepts of signals and slots. So far, they seem like a great way to implement the Observer pattern on a generic level. I'm wondering about a couple things, though. First, how often are signals and slots used in game programming? Second, are there any disadvantages to implementing them? I look forward to your answers. [smile]

Share this post


Link to post
Share on other sites
Hey there.

Yea, signals are a great OOP tool. As for game programming, the only drawback I can think of is their speed. They usually need a few extra functions on the stack to get to the functions that are supposed to be called. This however is only a drawback for heavy duty functions. For the general "game-level" programming, they are great.
About the implementation, I'd rather go with libsigc++ or boost::signals than implementing them yourself.

Share this post


Link to post
Share on other sites
Quote:
Original post by LtJax
Hey there.

Yea, signals are a great OOP tool. As for game programming, the only drawback I can think of is their speed. They usually need a few extra functions on the stack to get to the functions that are supposed to be called. This however is only a drawback for heavy duty functions. For the general "game-level" programming, they are great.
About the implementation, I'd rather go with libsigc++ or boost::signals than implementing them yourself.


Thanks for your reply, LtJax! [smile]

Since I'm developing games in Java, I can't use either of those great libraries that you mentioned. Right now I'm trying to devise a simple signal/slot system using Java's Method objects (part of its Reflection API). Hopefully doing this will not require much more overhead than what you mentioned with C/C++.

Share this post


Link to post
Share on other sites
Quote:
Original post by RobAU78
Quote:
Original post by LtJax
Hey there.

Yea, signals are a great OOP tool. As for game programming, the only drawback I can think of is their speed. They usually need a few extra functions on the stack to get to the functions that are supposed to be called. This however is only a drawback for heavy duty functions. For the general "game-level" programming, they are great.
About the implementation, I'd rather go with libsigc++ or boost::signals than implementing them yourself.


Thanks for your reply, LtJax! [smile]

Since I'm developing games in Java, I can't use either of those great libraries that you mentioned. Right now I'm trying to devise a simple signal/slot system using Java's Method objects (part of its Reflection API). Hopefully doing this will not require much more overhead than what you mentioned with C/C++.


Reflection? It might. The C++ solutions incur little overhead other than an extra function call (you call the signal, the signal calls the function), because it uses partial template specialization to produce the correctly typed object at compile time.

Share this post


Link to post
Share on other sites
I know people really like Boost and for good reason, but there are alternatives. If you want something very lightweight and portable for C++, you might want to look at this:

http://sigslot.sourceforge.net/

As you seem to be interested in it from an academic point of view, you might also be interested in the paper Sarah Thompson wrote:
http://sigslot.sourceforge.net/sigslot.pdf

Try to back in to a pattern, prefer simple until that kind of complexity is required. The observer pattern is useful to add flexibility to your code. It also encourages you to split off the game logic and the game view, which is no bad thing (means it's easier to develop test firsts that use the game logic, then building the view seperately on top).

Use whatever works for you.


EDIT: Ah noticed you wrote you are using Java. Well that's got a few things already in there to help you out, and there are tons of example pattern implementations in Java - the classes that make up the sdk itself are littered with example uses of the observer pattern.

[Edited by - paulecoyote on April 4, 2006 5:02:30 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by RDragon1
If you're using C++, check out the boost.signals library


I believe he stated that he'll be using Java.

I don't know much about java, but if functions are first-class objects and allows for weak references to GC objects, then it should be simple to create a signal/slot mechanism. I created a signal/slot library for python last year. Even though it's written in python, it might provide a good guideline to follow for a Java implementation.

Share this post


Link to post
Share on other sites
Quote:
Original post by smr
Quote:
Original post by RDragon1
If you're using C++, check out the boost.signals library


I believe he stated that he'll be using Java.


My mistake and apologies then, I didn't read the entire thread.

Share this post


Link to post
Share on other sites
Hey guys,

Thanks for your replies!

I've now been able to implement a rather simple signal/slot mechanism in Java. It uses just one extra class, the Signal class. However, it's a little more difficult to use it compared to C++ implementations. For one thing, Java's Method objects (the closest thing to C++ function pointers) can only be invoked with Object arrays that contain the parameters. Another issue really concerns connecting the Signal objects with Methods to begin with. Should the connections occur in the constructors? Or should there be a separate method to handle the connections? Does it really matter? Finally, I'm also wondering if it's not overkill to implement signals/slots in my game, since it's a relatively simple one (for those who haven't seen it, feel free to click on the link in my signature and download the source code -- critiques are welcome). Again, I'd appreciate any and all help with this. [smile]

Share this post


Link to post
Share on other sites
Quote:
Original post by RobAU78
Hey guys,

Thanks for your replies!

I've now been able to implement a rather simple signal/slot mechanism in Java. It uses just one extra class, the Signal class. However, it's a little more difficult to use it compared to C++ implementations. For one thing, Java's Method objects (the closest thing to C++ function pointers) can only be invoked with Object arrays that contain the parameters. Another issue really concerns connecting the Signal objects with Methods to begin with. Should the connections occur in the constructors? Or should there be a separate method to handle the connections? Does it really matter? Finally, I'm also wondering if it's not overkill to implement signals/slots in my game, since it's a relatively simple one (for those who haven't seen it, feel free to click on the link in my signature and download the source code -- critiques are welcome). Again, I'd appreciate any and all help with this. [smile]


Quote:
Original post by PaulECoyote
As you seem to be interested in it from an academic point of view, you might also be interested in the paper Sarah Thompson wrote:
http://sigslot.sourceforge.net/sigslot.pdf

That paper details construction details and design decisions...

Share this post


Link to post
Share on other sites
The biggest risk in signals/slots is that you'll get into some recursive invalidation/read loop that eats up your stack.

We use something slightly more elaborate than signal/slot in the same vein, a whole lot. However, we will just invalidate calculated values on a notify that something changed, and then call back to actually read the value only when we need to calculate a new value (which is when someone else asks us for a value, or upon a pulse).

Share this post


Link to post
Share on other sites
Quote:
Original post by paulecoyote
That paper details construction details and design decisions...


I read the paper and it doesn't seem to talk about where in the classes' code the signals and slots should be connected. It seems to talk only about implementing the functionality of the signals and slots.

- Rob

Share this post


Link to post
Share on other sites
Something else I've been thinking about lately is whether I should implement signals and slots at all for my current project (see the link in my signature). Given the rather small scale of the project, it may seem reasonable to allow a greater amount of coupling than with larger and/or more complicated designs. For example, the two main classes in my current project are GameLogic (the game mechanics) and GameBoard (the user interface). Right now, the GameBoard object owns a GameLogic object. However, this is not a very good design and should be changed even with implementing signals and slots. The better choice would be to have the GameLogic object own a GameBoard object. That way, it could directly control what the user interface displays. Anyways, I'd like to hear what the rest of you think. [smile]

Share this post


Link to post
Share on other sites
I don't really see how signals/slots are useful in Java. I haven't used them, but it seems to me that they are mainly useful in a language that makes it painful to use observer classes, because those
a) need to be defined at a separate location in the code, making the code hard to follow
b) need to be initialized explicitly with "context variables" (what objects to call methods on, etc)
But in Java, you can use anonymous inner classes, which can be used in-place and capture their context automatically - they are effectively closures.

Share this post


Link to post
Share on other sites
Quote:
Original post by Barius
I don't really see how signals/slots are useful in Java.

They are pretty useful in C#, VB and most other .NET languages. Surely they could be useful in Java.

Share this post


Link to post
Share on other sites
Have you looked at the example code from that Java project? I think it's not very clear compared to using "normal" observers and anonymous classes.


Compare this line from the example program

SignalSlotMap.connect(p, Producer.INT_SIGNAL, SlotProviderMethodPair.create(ni, "setIntObject", IntObject.class));

to this line from an imaginary program using an inner class:

p.addIntObjectCallback(new IntObjectCallback() {
public void call(IntObject o) {
ni.setIntObject(o);
}});

Share this post


Link to post
Share on other sites
Quote:
Original post by Barius
Have you looked at the example code from that Java project? I think it's not very clear compared to using "normal" observers and anonymous classes.


Compare this line from the example program

SignalSlotMap.connect(p, Producer.INT_SIGNAL, SlotProviderMethodPair.create(ni, "setIntObject", IntObject.class));

to this line from an imaginary program using an inner class:

p.addIntObjectCallback(new IntObjectCallback() {
public void call(IntObject o) {
ni.setIntObject(o);
});


Seems complicated (of course everything in java seems too complicated to me ;P). Something like this would be cool (I don't know if this would work. I'm not a java programmer):


class X {
public Signal Clicked = new Signal();
}

class Y {
public OnClicked() { do stuff };
}

void settingItUp() {
X x = new X();
Y y = new Y();

X.Clicked.connect(y.OnClicked);
}



Share this post


Link to post
Share on other sites
Quote:
Original post by smr
Seems complicated (of course everything in java seems too complicated to me ;P). Something like this would be cool (I don't know if this would work. I'm not a java programmer):

*** Source Snippet Removed ***


It's nearly that simple in C#:


delegate void ClickDelegate();

class X {
public event ClickDelegate Click;
}

class Y {
public void OnClick() { /*do stuff*/ }
}

void settingItUp() {
X x = new X();
Y y = new Y();

x.Click += new ClickDelegate(y.OnClick);
}


EDIT: I'll stop posting about C# in this topic. Promise.

[Edited by - dalleboy on April 12, 2006 10:56:34 AM]

Share this post


Link to post
Share on other sites
Quote:
Original post by Barius
I don't really see how signals/slots are useful in Java. I haven't used them, but it seems to me that they are mainly useful in a language that makes it painful to use observer classes, because those
a) need to be defined at a separate location in the code, making the code hard to follow
b) need to be initialized explicitly with "context variables" (what objects to call methods on, etc)
But in Java, you can use anonymous inner classes, which can be used in-place and capture their context automatically - they are effectively closures.


Signal/slot and observers are totally different beasts, and they are used to solve different problems. Basically, you use an observer when you want to emphasis on the fact that an update is needed, while the signal/slot mecanism puts an emphasis on the treatment itself and on the fact that it is possible to modify the dynamically change the treatment. Moreover, signals are typically functions or methods while the observer's update function is inherited from a base class.

Regards,

Share this post


Link to post
Share on other sites
Quote:
Original post by Emmanuel Deloget
Signal/slot and observers are totally different beasts, and they are used to solve different problems. Basically, you use an observer when you want to emphasis on the fact that an update is needed, while the signal/slot mecanism puts an emphasis on the treatment itself and on the fact that it is possible to modify the dynamically change the treatment.


"Totally different beasts"? IMO, they are just two types of event handling mechanisms that both try to decouple the sender from the receiver - with signals/slots, the sender of the signal does not know to which slots it goes, and what those slots do. With observers, the "sender" has a list of receivers (observers) and calls a method on each, but does not know what those methods do.
And you can dynamically add/remove observers from those lists, too.

Maybe our ideas of what an Observer is are different? I thought that classes implementing Java's MouseListener, ActionListener, ... interfaces were observers, because they observe what happens to the GUI (that a button is clicked, etc.)

Quote:

Moreover, signals are typically functions or methods while the observer's update function is inherited from a base class.


Java doesn't have an easy way to use "free" methods/functions as first-class objects - using the reflection API to get at a method just feels inelegant, clunky and error-prone (because you throw compile-time checks out of the window) to me. Using anonymous classes implementing an interface is much easier.
That why I just don't see any benefits to using signals/slots in Java (compared to languages without anonymous classes or delegates or closures, like C++).

Share this post


Link to post
Share on other sites
Quote:
Original post by Barius
Quote:
Original post by Emmanuel Deloget
Signal/slot and observers are totally different beasts, and they are used to solve different problems. Basically, you use an observer when you want to emphasis on the fact that an update is needed, while the signal/slot mecanism puts an emphasis on the treatment itself and on the fact that it is possible to modify the dynamically change the treatment.


"Totally different beasts"? IMO, they are just two types of event handling mechanisms that both try to decouple the sender from the receiver - with signals/slots, the sender of the signal does not know to which slots it goes, and what those slots do. With observers, the "sender" has a list of receivers (observers) and calls a method on each, but does not know what those methods do.
And you can dynamically add/remove observers from those lists, too.

Maybe our ideas of what an Observer is are different? I thought that classes implementing Java's MouseListener, ActionListener, ... interfaces were observers, because they observe what happens to the GUI (that a button is clicked, etc.)


I was perhaps too extreme. The biggest difference between these two solution is semantic rather than practical. The purpose of the observer pattern is to manage state change, while the signal/slot mecanism is more like a generic way to ask to a target to perform a particular action. The difference is easier to see when you come to the implementation: typically, your observer's update() method is the only entry point of your observer - it will probably have a state parameter (or the update method will get the state of the subject) in order to perform a specific action. Using the signal/slot, you'll define 1+ independent signals - so you have 1+ entry points that are used to perform specific actions. In one case, the observer does the dispatch, in the other case, the signal emiter does the dispatch.

Quote:
Original post by Barius
Quote:
Original post by Emmanuel Deloget
Moreover, signals are typically functions or methods while the observer's update function is inherited from a base class.


Java doesn't have an easy way to use "free" methods/functions as first-class objects - using the reflection API to get at a method just feels inelegant, clunky and error-prone (because you throw compile-time checks out of the window) to me. Using anonymous classes implementing an interface is much easier.
That why I just don't see any benefits to using signals/slots in Java (compared to languages without anonymous classes or delegates or closures, like C++).


I get your point: of course, if the Java language itself makes it difficult and error prone to use the signal/slot mecanism, I would suggest to not using it at all unless it is really necessary (something that is never true: I never saw a case where you have only one design choice).

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this