
The highest level class in my code is an active function class, which both returns a future and takes futures as arguments. That way, the main thread can setup the flow of data by passing futures between active objects, and then leave them to their work. For example, you might have a batch of objects you want to pass though a pipeline of processing operations.
Because of this, I gave my active_return<> class the forbidden implicit cast operator, that way I saved a lot of duplicating what boost::bind was already doing. Example: active_return<int> ar1 = active_function(&getSomeInt); active_return<int> ar2 = active_function(boost::bind(&doSomethingWithAnInt, ar1)); boost::bind stores an active_return<int> in the second line, but does not attempt to use it as an int until the bound function is called. This results in a thread being spawned for getSomeInt and a second thread spawned for doSomethingWithAnInt which waits on the first result. I'm sure someone will take issue with this implementation detail (which is called deplorable in c++ coding standards #40), but it sure does make for clean use of the library.
You can do things like assign a Future<T> to a Future<U> if T is implicitly converible to U, without blocking. You can also extract elements from future containers and such, like getting a Future<int> from a Future<std::vector<int> > without blocking.
Those are great ideas, I had not thought of that.
I'm not familiar with the boost::asio library, but I suspect there is stuff in there I could (should) have made use of.
I am also not familiar with asio and there has been a lot of talk about it here lately.
-- Frank
Jason