I have a class that should be able to send messages over TCP. Here's a simplified interface:
class CommandScreenshot : public CameraCommand { public: CommandScreenshot(); ~CommandScreenshot(); void Dispatch(boost::shared_ptr<boost::asio::io_service> io_service); private: void resolve_handler(const boost::system::error_code& err, boost::asio::ip::tcp::resolver::iterator endpoint_iterator); };
As you can see, I have a Dispatch function, which is actually just meant to trigger an async operation:
void CommandScreenshot::Dispatch(boost::shared_ptr<boost::asio::io_service> io_service) { boost::asio::ip::tcp::resolver resolver(*io_service); boost::asio::ip::tcp::resolver::query query(m_hostname,"http"); resolver.async_resolve(query,boost::bind(&CommandScreenshot::resolve_handler,this,boost::asio::placeholders::error, boost::asio::placeholders::iterator)); return; }
Everything else will be done in the following callback functions. The io_service object, as well as the corresponding stream, are managed by another class (which has an instance of CommandScreenshot and calls the Dispatch function).
Now, to implement a simple TCP connection with Boost, you need resolver and socket objects attached to the io_service object. Since the io_service object will be passed only then the function is called, I cannot initialize it in the constructor of the class. It is also impossible to declare them as members of a class, and then simply initialize them in the function itself.
My first idea was to simply initialize them when the function was called and pass them to my completion handler. This would mean that I declare both objects every time I call the function and bind them to io_service . Then in async_resolve I add both parameters via boost::bind . This would mean that my resolve_handler would expect more arguments - for example:
void resolve_handler(const boost::system::error_code& err, boost::asio::ip::tcp::resolver::iterator endpoint_iterator, boost::asio::ip::tcp::resolver resolver, boost::asio::ip::tcp::socket socket);
I really doubt that this is a worthy and fair decision. Typically, these objects should be stored as members, and not copied. So I gave him another thought, and my mind took me to boost::shared_ptr .
My heading now looks like this:
And the implementation will be as follows:
void CommandScreenshot::Dispatch(boost::shared_ptr<boost::asio::io_service> io_service) { m_resolver.reset(new boost::asio::ip::tcp::resolver(*io_service)); m_socket.reset(new boost::asio::ip::tcp::socket(*io_service)); boost::asio::ip::tcp::resolver::query query(m_hostname,"http"); m_resolver->async_resolve(query,boost::bind(&CommandScreenshot::resolve_handler,this,boost::asio::placeholders::error, boost::asio::placeholders::iterator)); return; }
In this case, I do not need to copy, for example, 4 (or perhaps even more) parameters and bind them together. When I need a socket object, I can just get it through a pointer that is a member of the class.
Now my simple question is the right way? The function can be called several times, even if the asynchronous part is not finished. (I know that then I have to protect the socket and resolver with the mutex). But is it so that every time I create a new object when I call the Dispatch function? Is calling reset enough to get rid of any unnecessary memory?
I know this is a long text for a specific short question, and besides, there is not even a mistake. But I always like to know how confident I am that I will, and if there is a better one, how will I do it.