callback design question

M

mliptak

Hi, I'm implementing a class which will serve as a callback. It will
have multiple virtual operations, which will be called upon certain
events.
The user of the class can inherit from this class and implement the
virtual operations to fit his/her needs.
Each operation will have up to 3 parameters of either basic integral
types (e.g. int, unsigned, size_t) or pointers (e.g. const char*).
However these parameters can be stored in the class as attributes.
My question is - whould you rather design operations with parameters
or have these parameters as members of the class and the operations
would have no parameters?
Can this have a impact on the performance (copying the parameters via
stack)? I know, design first, then do the profiling and see.. ;) But
I'd like to hear your opinion.
Thanks
 
J

John Harrison

mliptak said:
Hi, I'm implementing a class which will serve as a callback. It will
have multiple virtual operations, which will be called upon certain
events.
The user of the class can inherit from this class and implement the
virtual operations to fit his/her needs.
Each operation will have up to 3 parameters of either basic integral
types (e.g. int, unsigned, size_t) or pointers (e.g. const char*).
However these parameters can be stored in the class as attributes.
My question is - whould you rather design operations with parameters
or have these parameters as members of the class and the operations
would have no parameters?
Can this have a impact on the performance (copying the parameters via
stack)? I know, design first, then do the profiling and see.. ;) But
I'd like to hear your opinion.
Thanks

I there is any possibility that the parameters would change during the
lifetime of the callback object then I would undoubtedly want the
parameters to be real parameters, rather than class attributes.

Class attributes would be an example of the 'accumulate and fire'
anti-pattern.

http://en.wikipedia.org/wiki/Accumulate_and_fire

john
 
M

mliptak

I there is any possibility that the parameters would change during the
lifetime of the callback object then I would undoubtedly want the
parameters to be real parameters, rather than class attributes.

Yes, the parameters would change, however they are meaningful only
during the call of the operation.
 
B

boaz1sade

Hi, I'm implementing a class which will serve as a callback. It will
have multiple virtual operations, which will be called upon certain
events.
The user of the class can inherit from this class and implement the
virtual operations to fit his/her needs.
Each operation will have up to 3 parameters of either basic integral
types (e.g. int, unsigned, size_t) or pointers (e.g. const char*).
However these parameters can be stored in the class as attributes.
My question is - whould you rather design operations with parameters
or have these parameters as members of the class and the operations
would have no parameters?
Can this have a impact on the performance (copying the parameters via
stack)? I know, design first, then do the profiling and see.. ;) But
I'd like to hear your opinion.
Thanks

Maybe before you are writing your own code, you want to think of the
best pattern that I know - using a well design lib that will do what
you need to do and that was writing by expert programmers, in this
case you may want to look at:
http://libsigc.sourceforge.net/doc.shtml
and
http://www.boost.org/doc/html/function.html
and
http://www.boost.org/doc/html/signals.html
as libraries writing by programmers who devoted enough time to the
problem and have enough skill to have a well design lib for other to
use. By saying this I don't mean that you don't have the skills, just
that it may save you time and if you don't find them useful then at
least you may find some good ideas
Have luck
 
J

John Harrison

mliptak said:
Yes, the parameters would change, however they are meaningful only
during the call of the operation.

Which is why 'real parameters' are the natural fit. Class attributes
last for the lifetime of the object.

One situation in which class attributes would not only be ugly but
actually fail to work is when the same callback object was being used in
different threads of execution.

john
 
M

mliptak

Maybe before you are writing your own code, you want to think of the
best pattern that I know - using a well design lib that will do what
you need to do and that was writing by expert programmers, in this
case you may want to look at:http://libsigc.sourceforge.net/doc.shtml
andhttp://www.boost.org/doc/html/function.html
andhttp://www.boost.org/doc/html/signals.html
as libraries writing by programmers who devoted enough time to the
problem and have enough skill to have a well design lib for other to
use. By saying this I don't mean that you don't have the skills, just
that it may save you time and if you don't find them useful then at
least you may find some good ideas
Have luck

Thanks for the info. Have you actually used any of these? I'm kind
of familiar with http://sigslot.sf.net - are the libs above better
than this one?
 
D

dasjotre

Thanks for the info. Have you actually used any of these? I'm kind
of familiar withhttp://sigslot.sf.net- are the libs above better
than this one?

libsigc and boost::signals are actually the same lib
(by the same people) with some cosmetic differences.
I am not familiar with sigslot but at short glance it
seems to offer similar, albeit more limited, functionality
to libsigc/signals, the only real difference I see is that
libsigc/signals thread safety is left entirely to the user.
The benefit of boost is that it is well documented,
tested, supported and portable. it is also an entry point
for future standard library extensions. (you also get
an added benefit of the rest of excellent boost libraries)

I have been using libsigc/signals for several years
and I warmly recommend it.
 
M

mliptak

I have been using libsigc/signals for several years
and I warmly recommend it.

So I gave it a try and instead of using virtual functions I used the
signals..
But I gained nothing in terms of performance and also the interface
remained pretty much the same.
So what's the rationale behind using signals / slots?
 
D

dasjotre

So I gave it a try and instead of using virtual functions I used the
signals..
But I gained nothing in terms of performance and also the interface
remained pretty much the same.
So what's the rationale behind using signals / slots?

signals/slots is a very simple library.

you have much less restrictive interface with signals than with
abstract bases.

struct my_interface
{
virtual void fun1(A &)=0;
virtual void fun2(B &)=0;
};

with this approach you have to implement both functions even if
you don't use one of them

signal<void (A&)> asignal;
signal<void (B&)> bsignal;

slots are arbitrary function objects
you can connect any function object that is convertible to
the slot

void fun(A&);
asignal.connect(&fun);
struct T
{
void fun(A&);
};
T t;
asignal.connect(bind(&T:fun, &t, _1));

you can bind extra arguments and adapt
interface to fit the signal.

void my_fun(A & a, int n);
asignal.connect(bind(&my_fun, _1, 4));

you have much more robust
and functional connection management.

void my_fun1(B &);
connection con = bsignal.connect(bind(&my_fun1, _1));
....
con.block();
...
con.unblock();
...
con.disconnect();

using signals::trackable and signals::scoped_connection you
can have automatic connection management

you can group/order slots. you can chain signals. you can
collate results.

now, of course you can implement all that functionality yourself.
the point is that you don't have to since someone else has done
it already.
 
M

mliptak

signals/slots is a very simple library.

you have much less restrictive interface with signals than with
abstract bases.

struct my_interface
{
virtual void fun1(A &)=0;
virtual void fun2(B &)=0;

};

with this approach you have to implement both functions even if
you don't use one of them

You can do the default implementation in the base class as well,
instead of pure virtuals..
signal<void (A&)> asignal;
signal<void (B&)> bsignal;

slots are arbitrary function objects
you can connect any function object that is convertible to
the slot

void fun(A&);
asignal.connect(&fun);
struct T
{
void fun(A&);};

T t;
asignal.connect(bind(&T:fun, &t, _1));

you can bind extra arguments and adapt
interface to fit the signal.

void my_fun(A & a, int n);
asignal.connect(bind(&my_fun, _1, 4));

you have much more robust
and functional connection management.

void my_fun1(B &);
connection con = bsignal.connect(bind(&my_fun1, _1));
...
con.block();
..
con.unblock();
..
con.disconnect();

using signals::trackable and signals::scoped_connection you
can have automatic connection management

you can group/order slots. you can chain signals. you can
collate results.

now, of course you can implement all that functionality yourself.
the point is that you don't have to since someone else has done
it already.

Thanks for the explanation.
I think I just did not see the use for all this because I did not come
over a realworld application where this could be a perfect fit.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,013
Latest member
KatriceSwa

Latest Threads

Top