digitalmars.D.learn - Only one signal per object?
- Peter Ravinovich (6/6) Oct 11 2011 Is there a way to have several signals per object?
- Justin Whear (6/15) Oct 11 2011 From the docs:
- Spacen Jasset (4/19) Oct 12 2011 I think this has come up before. It doesn't seem particularly intuitive....
- Justin Whear (37/61) Oct 12 2011 Yes, the docs don't elaborate or include an example. So, for posterity's...
- Andrej Mitrovic (2/2) Oct 12 2011 Johannes Pfau made an updated version of std.signals, I think he's
- Johannes Pfau (13/15) Oct 14 2011 http://dl.dropbox.com/u/24218791/d/src/signals.html
- Andrej Mitrovic (22/22) Oct 18 2011 I've ran into an awful bug right now (probably not related to your
- Andrej Mitrovic (34/34) Oct 24 2011 It seems neither std.signal nor the new signals module support ref
- Andrej Mitrovic (7/7) Oct 24 2011 I think I know what's going on,
- Andrej Mitrovic (8/8) Oct 24 2011 Yeah, if I change the two function types in Signal to this:
Is there a way to have several signals per object? The example in std.signal seams to suggest that only one signal per object can be emmited. Is it possible to have several events launched as it's possible in .NET? For example, bind one object to onClick and another to onKeyUp. Thanks
Oct 11 2011
From the docs: "Different signals can be added to a class by naming the mixins." So I think something like this ought to work: mixin Signal!(string) onBlah; mixin Signal!(int, int) onClicketyClick; Peter Ravinovich wrote:Is there a way to have several signals per object? The example in std.signal seams to suggest that only one signal per object can be emmited. Is it possible to have several events launched as it's possible in .NET? For example, bind one object to onClick and another to onKeyUp. Thanks
Oct 11 2011
On 11/10/2011 18:12, Justin Whear wrote:From the docs: "Different signals can be added to a class by naming the mixins." So I think something like this ought to work: mixin Signal!(string) onBlah; mixin Signal!(int, int) onClicketyClick; Peter Ravinovich wrote:I think this has come up before. It doesn't seem particularly intuitive. Perhaps it should be that the signals must be explicit to make things clear cut.Is there a way to have several signals per object? The example in std.signal seams to suggest that only one signal per object can be emmited. Is it possible to have several events launched as it's possible in .NET? For example, bind one object to onClick and another to onKeyUp. Thanks
Oct 12 2011
Yes, the docs don't elaborate or include an example. So, for posterity's sake here's a quick example: ---------------------------------------- import std.stdio, std.signals; void main() { auto foo = new Foo; auto listener = new Listener; foo.onClick.connect(&listener.clickHandler); foo.onFoo.connect(&listener.fooHandler); foo.doClick(10, 10); foo.doFoo("a message"); } class Foo { void doClick(int x, int y) { onClick.emit(x, y); } void doFoo(string s) { onFoo.emit(s); } mixin Signal!(int,int) onClick; mixin Signal!(string) onFoo; } class Listener { void clickHandler(int x, int y) { writeln("Clicked at ", x, ",", y); } void fooHandler(string bar) { writeln("Got ", bar); } } ---------------------------------------- $ rdmd test.d Clicked at 10,10 Got a message Spacen Jasset wrote:On 11/10/2011 18:12, Justin Whear wrote:From the docs: "Different signals can be added to a class by naming the mixins." So I think something like this ought to work: mixin Signal!(string) onBlah; mixin Signal!(int, int) onClicketyClick; Peter Ravinovich wrote:I think this has come up before. It doesn't seem particularly intuitive. Perhaps it should be that the signals must be explicit to make things clear cut.Is there a way to have several signals per object? The example in std.signal seams to suggest that only one signal per object can be emmited. Is it possible to have several events launched as it's possible in .NET? For example, bind one object to onClick and another to onKeyUp. Thanks
Oct 12 2011
Johannes Pfau made an updated version of std.signals, I think he's hosting it somewhere on his dropbox, you'll have to ask him.
Oct 12 2011
Andrej Mitrovic wrote:Johannes Pfau made an updated version of std.signals, I think he's hosting it somewhere on his dropbox, you'll have to ask him.http://dl.dropbox.com/u/24218791/d/src/signals.html https://gist.github.com/1194497 It should work well as a replacement for the current std.signals but compared to boost::signals2 it still misses some features. When I find some time for it, I'll update it to support all boost:signals2 features and propose it for phobos. Note: This bug can cause issues with my std.signals implementation: http://d.puremagic.com/issues/show_bug.cgi?id=5011 I should really file a pull request for that. -- Johannes Pfau
Oct 14 2011
I've ran into an awful bug right now (probably not related to your module). It basically comes down to this inside of a "Widget" constructor: this(Widget parent) { super(parent); void test() { msgbox(this.position); } parent.onMouseLDown.connect( { this.position; }); parent.onMouseLDown.connect( { test(); }); } If I comment out the first connect call I'll get an access violation when 'test()' tries to access the "position" field. The order of the two calls doesn't seem to affect the bug. I can't recreate the bug in a simple test-case though.. :/ Oh btw, there's a couple of failing unittests in your signal module when compiling with " -g -debug -w -wi": object.Exception signalsnew.d(679): Handler is not connected core.exception.AssertError signalsnew(950): unittest failure core.exception.AssertError signalsnew(968): unittest failure
Oct 18 2011
It seems neither std.signal nor the new signals module support ref parameters, which is a shame because I've found a very good use for them. The std.signal won't compile for handlers with ref parameters, the new one compiles but throws an access violation at runtime. Example usage: If you have a child widget and its parent widget which is a Layout widget, when the child emits a "doMove(Widget widget, Point newPoint)" signal the layout widget could handle it first by calling connectFirst when the parenting takes place. This allows the layout 'doMove' handler to modify the parameter so it fits some given limit, after which the next handler is called to further process the signal. In code this would look something like: auto button = new Widget; auto layout = new Layout(...); layout.addWidget(layout); // internally layout would do: widget.doMove.connectFirst(&layout.doMove); widget.move(Point(10, 10)); The last call translates to, say: -> widget.doMove.emit(this, Point(10, 10)); Which calls all the handlers sequentially until one of them returns 0: -> widget.doMove.handler[0] // layout.doMove() -> widget.doMove.handler[1] // handler 2.. and in Layout: bool doMove(Widget widget, ref Point newPoint) { newPoint.x = max(newPoint.x, 10); // limit to 10 newPoint.y = max(newPoint.y, 10); return true; } and then the other handlers would be called, but with potentially modified arguments. This would be super-useful to me right now. I haven't yet gone through the new signal implementation, but maybe I'll figure out how to add this feature myself.
Oct 24 2011
I think I know what's going on, getCallable() doesn't check for the storage class of a function, and does a cast based on the parameters and the return type when it's adding a new handler. The handler is later casted to a function type with no ref parameters, and this is where things probably cause problems. I'll have to devise something more sophisticated.
Oct 24 2011
Yeah, if I change the two function types in Signal to this: alias bool delegate(ref Types) slot_t; alias void delegate(ref Types) void_slot_t; then I can connect functions with ref arguments. But then I'll get exceptions thrown if the functions have non-ref arguments. This seems like a difficult problem to solve. How can you (efficiently) store a dynamic list of function pointers which could have arbitrary storage classes for its parameters? Hmm..
Oct 24 2011