
Hi Matt, --- Matt Vogt <mattvogt@warpmail.net> wrote:
Yes, that's not a bad idea. Of course, you don't want to rewrite all the forwarding functions with any regularity, so it's probably better to do this with a Handler object, constructed with an error-handling function and then supplied with the success-handling function for each new operation.
It'd be great if you could have a think about the interface for this object.
Is split_error documented somewhere?
It doesn't exist yet :) <snip>
Perhaps it's been discussed, but is there any particular reason you wouldn't want to define an 'asio::socket_error' subclass of asio::error? Attaching the relevant shared_ptr<socket> to the error code would make some error- handling strategies simpler.
I'm not sure that would be being useful enough in general, but perhaps a function object that automatically created a std::pair (or maybe boost::tuple) from the underlying asio::error and whatever you want to attach to it, e.g.: sock->read(bufs, throw_error_pair(sock));
If it were a pair of error-code and socket, and could be used asynchronously, it would be useful, but propagating the exception outside demuxer::run seems messy, since multiple threads could be calling 'run'.
In respect of exceptions and demuxer::run, I hope I have defined the behaviour clearly. Specifically, the demuxer cannot know about all exception types, so exceptions are allowed to safely propagate to outside the run call where they can be handled. This only affects the thread where the exception is raised. After handling the exception, that thread may immediately call demuxer::run again to return to the pool.
Sorry if I'm missing the point, but I don't see what your saying here. If there are some exceptions that you cannot deal with, why should that prevent you from handling the ones you do know about? If users supply handlers that throw, they will need to deal with the resulting exceptions manually. I don't see how anything is simplified by requiring the user to deal with library exceptions in the same place (the call to demuxer::run)...
I think we've lost track of the original point we were discussing here, whatever it was :) Basically asynchronous operations do not throw unless: - Something really serious has happened, like running out of a critical OS resource. - The user code throws an exception, or calls some other code that throws an exception. In both cases I think the appropriate place to handle these exceptions is outside of demuxer::run(). Cheers, Chris