|
Boost : |
Subject: Re: [boost] Futures - Reviews Needed (January 5, 2009)
From: Steve Karmesin (steve.karmesin_at_[hidden])
Date: 2008-12-31 14:27:42
I have some comments on the design of Braddock Gaskill's Boost.Future library.
I haven't really looked at the other one because I don't want to reverse
engineer the code. I would not accept that library without documentation
comparable to Gaskill's.
I have a fair amount of experience with using threads from C++. While I've seen
the idea of futures before I haven't used them.
I really like the documentation. It is a major help for evaluating the design
decisions. I have not yet used the library, at this point I'm just evaluating
the design and interface in the docs. Since I haven't acutally used it yet I'm
not yet prepared to say accept or reject on this library.
It appears to be well thought through. I like the split between promise and
future to separate the put and get interfaces.
There is one point where I question the design decision: reference semantics.
There are certainly times when that is useful, but I can also see times when it
is not. My preference would be for a exposed concrete class. That could then
be used as a building block for a reference semantic class. Allowing users to
minimize interaction with memory management seems like a potential win. This
doesn't seem like a huge issue, but I thought I would raise it for discussion.
A second issue has to do with capturing and rethrowing exceptions. This is a
very cool capability but the implementation is limited because it can't detect
and use user derived subtypes of the system exception types. This can be done
with external polymorphism and would be a significant improvement.
Instead of storing a runtime_error store a pointer to an internal abstract base
class such as untyped_exception_wrapper. Derive from that a templated class
exception_wrapper that stores the user's type and can rethrow that type.
Then the set_exception member can be template and the exception type, wraps it
with exception_wrapper and stores the pointer to the abstract base.
Then when the user goes to get the value from the future and it finds that there
was an exception, it calls the rethrow method on the abstract base, the
templated derived class does the concrete rethrow of the user's type and the
user can then catch that type. This way the future library can catch and
rethrow exceptions of types that it knows nothing about.
Below is some demonstration code for this pattern.
-Steve Karmesin
Here is exception_wrapper,h:
#ifndef _exception_wrapper_h_
#define _exception_wrapper_h_
class exception_wrapper
{
public:
virtual void rethrow() const = 0;
};
template<typename E>
class typed_exception_wrapper : public exception_wrapper
{
public:
typed_exception_wrapper(const E& e) : exception_(e) {}
void rethrow() const { throw exception_; }
private:
E exception_;
};
template<typename E>
exception_wrapper* wrap_exception(const E& e)
{
return new typed_exception_wrapper<E>(e);
}
#endif
And a simple usage of it:
#include "exception_wrapper.h"
#include <iostream>
using namespace std;
exception_wrapper* caught;
void bar()
{
throw "This is an example of an exception of arbitrary class";
}
void foo()
{
try
{
bar();
}
catch (const char *p)
{
caught = wrap_exception(p);
}
}
void baz()
{
if ( caught )
caught->rethrow();
}
int main()
{
// Call foo, which will throw and save the arbitrary type.
foo();
// Call baz, which will rethrow the arbitrary type.
try
{
baz();
cout << "Huh, we should have thrown!" << endl;
}
catch (const char *p)
{
cout << "Caught: " << p << endl;
}
return 0;
}
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk