|
Boost : |
From: Tomasz Kowalczyk (tomek_at_[hidden])
Date: 2000-04-04 07:09:09
Dear Boost Members,
I have written a library which deals with so-called signal/slot
connections. I would like to ask you for review and comments. Since
boost libraries contain lots of beautiful work, I thought it would be
the best place to have my own code criticized.
The source can be found in:
http://www2.gol.com/users/tomek/signals.tar.gz
and a short introduction:
http://www2.gol.com/users/tomek/signals.html
Although the library is far from complete, I decided to post it because
I believe the techniques employed are very powerful and extremely
useful, especially in event-driven environments (such as most GUI
toolkits). I hope to find here new ideas, advice, and maybe gain some
interest in the further development.
The library you can find in the above URL was a side product of an
OpenGL-based viewer for 3D geometry. That's why the abstractions may not
be as general as they could be (this is especially true for slots and
and connection predicates).
Please let me explain in a few words what the whole signal idea is
about, as I can see it now.
Say you have an class template called signal. For example:
signal<A,B> sig; // equivalent to a function void sig(A,B)
where A and B are some types. You may store in this signal some
lambda-expressions for further use:
sig.connect( <lambda-expression-1> );
sig.connect( <lambda-expression-2> );
...
Some time later in a different place you can execute all previously
stored code with your choice of arguments:
sig( a, b );
Note the difference when compared to usage of lambda expressions in
algorithms, such as std::for_each, where the expressions are composed
and executed immediately. Signals are capable to delay the execution
until requested.
GUI toolkits use the mentioned mechanisms to manage notification
callbacks. However, it is very likely that there exist other potential
applications than just callbacks (I am hoping to find some ideas in this
list :)
The library provides also another kind of signal, which I call a
delegate. It can store only one expression, but in turn can return
values (returned from that expression). I find it convenient to think of
delegates as virtual functions, which implementation can be bound at run
time. For example:
delegate<void,char> put; // equivalent to void put(char)
put.connect( closure( &cout, &cout.put ) );
put('a'); // a printed to cout
put.connect( function(fputc) );
put('a'); // a printed to stdout
Delegates can be used as a way to achieve non-intrusive polymorphism,
because implementation can be provided by completely unrelated code.
As the next step, I am currently thinking about adaptation of the
signals to be able to use boost's lambda-calculus library, instead of
the limited choice of slot classes.
I hope you will like it :)
Thank you
Tomasz
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk