Aspen, Monday, May 15: These are just quick notes, and I apologize if they might not very coherent. I have little time to jot them down because the day was filled with talks and discussions. There are two main topics people are excited about: concurrency and template metaprogramming.
In the morning I went to Christopher Kohlhoff talk about Boost.Asio. Asio stands for Asynchronous IO. The problem is how to structure your program to deal with a lot of asynchronous calls. There are two main difficulties: resource management and inversion of control. An async-driven program is essentially a collection of disjoint callbacks. When control jumps from one callback to another, you can easily lose track of who is the owner of which resources, how to get hold of them, and how to reason about the whole system. Chris showed how to deal with resources, essentially by using shared, reference-counted, pointers. When you’re making an asynchronous call you usually have to make sure that the completion handler shares some resources with the caller. In Chris’s approach these resources are encapsulated in a Connection object and the completion handlers are methods of that object. So when a handler is called, it has access to the “this” pointer and can share data with the caller. A handler must take part in the reference counting of the Connection object, so that the object doesn’t suddenly disappear. Considering that a lot of event-driven code I’ve seen over the years used global shared data to store state, this is progress. The inversion of control is still a problem though.
Hartmut Kaiser talked about the Phoenix library, which essentially implements C++ inside C++. It is built on top of Proto (which is a big hit at the conference–more about it later). From what I gathered, Phoenix is mostly a better lambda. You can write anonymous functions in Phoenix using a very stylized C++: for instance, instead of braces, you use brackets, instead of semicolons, commas, etc. One advantage of Phoenix functions is that they can be statically polymorphic. Unfortunately the main example didn’t require polymorphism, and in fact would be much easier on the eyes if it were written using C++ lambdas. The other, more important advantage of Proto is that it’s highly customizable. Hartmut showed an example of how to extend C++ syntax to support parallelism. Behind the scenes, Phoenix took advantage of OpenMP, which is a system of ugly pragmas supported by many compilers to create parallel loops and other concurrent constructs.
An then there was a Proto marathon by Joel Falcou, after which I had a long discussion with him over dinner. Proto is a metaprogramming tour de force. If I described it as a library for constructing embedded domain-specific languages in C++, I wouldn’t give it justice. It’s a system that tricks the C++ compiler into parsing expressions into full-blown compile-time abstract syntax trees, which are at the same time function objects that can be executed at runtime. If this is not impressive enough, Proto provides multiple customization mechanism that allow you to plug in new constructs, give them specific semantics, and even rewrite the ASTs. Joel gave an example of an EDSL for expressing analytical functions, which could analytically calculate derivatives of functions at compile time. Joel is coming to my talk tomorrow and I hope he will be able to explain to me what I’m doing. My talk is essentially about how to get to grips with Proto by using Haskell monads. We’ll see how it goes.
May 16, 2011 at 10:27 pm
Yeah, there’s more to Phoenix than a better Lambda. Since it’s build on Proto, and since it makes its grammar and actions publicly accessible, you can use Proto to extend Phoenix to add your own syntax or do compile-time manipulations of Phoenix expressions. This is the difference. Boost.Lambdas and C++0x lambdas are black boxes. You can pass them, store them, and evaluate them, but that’s it. I have no idea what people will do with Phoenix’s openness. I’m pretty curious, though.
And a slight correction: Proto expression trees are not “function objects that can be executed at runtime.” By default, they have no behavior at all, but they can be extended with behaviors. That’s what Phoenix does. Phoenix adds the operator() overloads that make Phoenix expressions lambda-like.
May 17, 2011 at 7:03 am
Right, the main example didn’t make use of static polymorphism. One of the reasons was to give a nice and hopefully understandable example of how you can use Phoenix, by reusing already known patterns from asio: Instead of binding “regular” C++ member functions, why not just write them inline with Phoenix. Sure C++0x-Lambdas could have been used, but the talk was about Phoenix, not C++0x-Lambdas 😉
We decided to leave the more exciting applications of phoenix to a minimum. However, the examples (OpenMP-fication of for_ and invert) should have outlined the possibilities.
Imagine if you combine the stuff you learned from Joel Falcou and Phoenix, very exciting.
May 17, 2011 at 7:54 am
Thanks Eric and Thomas. My copout was “there’s more to it.” The OpenMP example was very interesting and definitely not implementable using simple-minded lambdas. However Asio was not a good example for two reasons: it could have been done with lambdas, and it showed the worst side of Pheoenix: the clunky and fragile syntax of C++ within C++.
May 17, 2011 at 11:31 am
Thanks for giving those of us who could not attend a taste of what is going on. I hope to read a similar write up for day 2.
May 17, 2011 at 11:07 pm
Thanks for the interesting post. I need to read up on some of these libraries like Phoenix and Proto.
May 18, 2011 at 4:13 am
> However Asio was not a good example for two
> reasons: it could have been done with
> lambdas, and it showed the worst side of
> Pheoenix: the clunky and fragile syntax of
> C++ within C++.
First of all, I think you can wrap almost any snippet programmed in Phoenix with C++0x lambdas, no doubt. However I believe that
that the syntax Phoenix tries to establish for “C++ in C++” is far easier on the eye than the long prologue you have to write for C++0x-lambdas.
There is no doubt that the syntax is fragile and errors you make while writing phoenix expression will lead to a big pile of template error backtrace. But I strongly believe that these error message can be improved. This is still a TODO for future versions.
P.S.: I think the comments miss a “quote” button 😉
July 24, 2011 at 3:04 pm
[…] Read the whole article […]