
Long post - continued.
The deferral needs of the client are decoupled. If the client does not care what thread calls it, then it can go:
parser.register_callback(my_callback);
However if the client has specific needs (such as that the calls must come in only on a specific thread) then it would use its own dispatcher to provide those guarantees:
parser.register_callback(client_dispatcher_.wrap(my_callback));
This is where the optimised dispatch() call (versus always-deferring post() function) comes into play. The client code is not aware of the parser's deferral decision and vice versa. However they may in fact share the same dispatcher (such as an application-wide asio::demuxer object), in which case you want the callback to be optimised into a single deferral.
there is some subtle and clever stuff going on there (particularly the last optimisation). I'm not sure if it works out as more efficient though than the programmer/integrator making a single policy decision conveyed to the originator of the callback (the parser) about how to do the callback. The one case where yours is clearly more efficient is the parser not doing a defer, but calling the callback object immediately, and that object being a non-wrapped ordinary function object.
The thing that asio does not provide is a polymorphic wrapper for the dispatcher concept so that the choice of deferral mechanism is done at runtime. However assuming one exists (and it wouldn't be hard to create one) the parser interface might be:
class parser { ... parser(polymorphic_dispatcher& d) : parser_dispatcher_(d) {} ... void register_callback(function<void(int)> callback); ... polymorphic_dispatcher& parser_dispatcher_; function<void(int)> callback_; ... };
I agree - that looks entirely reasonable.
Specifying what dispatcher the parser should use is separate to supplying a callback function. It is still the parser's decision as to whether it requires a deferred call using post() or not.
As discussed, i think it can be expressed entirely via post() by kicking the post()/dispatch() decision upstairs to main(). Thanks again for responding to my posts. Hope the discussion is useful feedback for the asio review process. Simon