Asio does not expose its handler tracking data. Attempting to extract the tracking information contained within Asio would be far more of a dirty hack than rolling ones own custom handler.
Here is a snippet from Asio's handler tracking:
namespace boost {
namespace asio {
namespace detail {
class handler_tracking
{
public:
class completion;
// Base class for objects containing tracked handlers.
class tracked_handler
{
private:
// Only the handler_tracking class will have access to the id.
friend class handler_tracking;
friend class completion;
uint64_t id_;
// ...
private:
friend class handler_tracking;
uint64_t id_;
bool invoked_;
completion* next_;
};
// ...
private:
struct tracking_state;
static tracking_state* get_state();
};
} // namespace detail
} // namespace asio
} // namespace boost
As others have mentioned, passing a GUID throughout the handlers would allow one to associate multiple asynchronous operations. One non-intrusive way to accomplish this is to create a custom tracking handler type that wraps existing handlers and manages the tracking data. For an example on custom handlers, see the Boost.Asio Invocation example.
Also, be aware that if a custom handler type is used, one should be very careful when composing handlers. In particular, the custom handler type's invocation hook (asio_handler_invoke()
) may need to account for the context of other handlers. For example, if one does not explicitly account for wrapped handler returned from strand::wrap()
, then it will prevent intermediate operations from running in the correct context for composed operations. To avoid having to explicitly handle this, one can wrap the custom handler by strand::wrap()
:
boost::asio::async_read(..., strand.wrap(tracker.wrap(&handle_read))); // Good.
boost::asio::async_read(..., tracker.wrap(strand.wrap(&handle_read))); // Bad.