Ben Greear wrote:
>
> The template code is impossible to understand. I'd have a base
> 'XorpCallBack'
> class and have others inherit from that.
That approach is likely to introduce additional indirection, due to the
nature of virtual functions in C++; see below.
> In implementing clients/servers,
> I'd probably have a few methods like:
> foo::handleCallback(CallBackObject& obj)
> that would handle lots of different callbacks in one place.
>
> Maybe with a real object of obvious type, we could actually trace
> code flow. As it sits, the opaque templated callbacks make it
> impossible for me to really understand a backtrace, for instance.
This sounds like a job for stlfilt.
In an ideal world, the tool chain we normally use, GNU C++, would be
smart enough to run members, which happen to refer to templates, through
the demangler; unfortunately, this doesn't always happen.
One thing I find particularly frustrating is the inability to elide
namespaces, or default constructor signatures. I don't need to know all
the time that method foo is using std::string with the given allocator,
which happens to be the default STL allocator.
Of course, another problem with implementing this is: where does the
debug information needed to do this end up. I suppose one could say this
is part of the added value of commercially available toolchains, but of
course those aren't always up to scratch either.
I would hope LLVM is an improvement...
>
> Anyway, that's just a rant.
It's something which has affected all of our work at some point.
>
> If things cannot be completed async, then there is no need for all
> the callback indirection anyway, and we could greatly simplify logic
> flow by removing the callback logic.
I can't speak for the Router Manager right now, although in the case of
XrlAction, the asynchrony is probably needed.
In libxipc, it's very clear that asynchrony wasn't introduced
unnecessarily. There's a clear need to have a continuation in the
situation where an RPC endpoint isn't known straight away ('resolving an
XRL'), and callbacks are the usual mechanism by which this is realized.
I would agree that the syntax is not that elegant, and can be difficult
to work with.
If we had strong support for coroutines in the language, it would be an
entirely different story. It might be worth looking at D or Go. Python
certainly has coroutine/continuation support, in the form of the 'yield'
keyword.
One of the reasons why I'm doing the work on Thrift, is to give us a
means of moving to other languages for implementing different parts of
the system, and thus more options.
There are good reasons why C++ was chosen in the beginning, but I'd be
the first to agree that C++ may not be the right tool for all of the
components in the system.
>
>> FWIW, Boost.Function is actually implemented in a pretty similar way to
>> XORP's callback library:
>> http://www.boost.org/doc/libs/1_40_0/doc/html/function.html
>
> That's not helping me feel good about Boost :P
One problem with writing callback libraries for C++, is that functions
themselves are not first-class objects in C++; you can't refer to the
argument list as a container, for example, there is no concept of
reflection (aka introspection) as e.g. Java or Python have.
Implementing the callbacks using a base class usually means that there's
a virtual method involved, which means another pointer indirection to
dispatch it.
Python and other languages don't have these problems, because their
design is completely different, and such issues are not present there.
cheers,
BMS
_______________________________________________
Xorp-hackers mailing list
[email protected]
http://mailman.ICSI.Berkeley.EDU/mailman/listinfo/xorp-hackers