У меня есть класс, который сможет отправлять сообщения по TCP.Вот упрощенный интерфейс:
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);
};
Как вы можете видеть, у меня есть функция Dispatch
, которая фактически просто имеет целью запустить асинхронную операцию:
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;
}
Все остальное будетбыть сделано в следующих функциях обратного вызова.Объект io_service
, а также соответствующий поток управляются другим классом (который имеет экземпляр CommandScreenshot
и вызывает функцию Dispatch
).
Теперь нужно реализовать простое TCP-соединение с Boostвам нужен объект resolver
и socket
, оба связаны с объектом io_service
.Поскольку объект io_service
будет передан только в то время, когда вызывается функция, я не могу инициализировать их в конструкторе классов.Также невозможно объявить их как членов класса, а затем просто инициализировать их в самой функции.
Моя первая идея состояла в том, чтобы просто инициализировать их при вызове функции и передать их моему обработчику завершения.Это означало бы, что каждый раз, когда вызывается функция, я объявляю оба объекта и связываю их с io_service
.Затем в async_resolve
я добавляю оба в качестве параметров через boost::bind
.Это означало бы, что мой resolve_handler
будет ожидать больше аргументов - например:
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);
Я на самом деле сомневаюсь, что это достойное и справедливое решение.Обычно эти объекты должны храниться как члены, а не копироваться вокруг - поэтому я еще раз подумал, и мой разум привел меня к boost::shared_ptr
.
. В моем заголовке это теперь выглядит так:
// Stuff above stays the same
private:
boost::shared_ptr<boost::asio::ip::tcp::resolver> m_resolver;
boost::shared_ptr<boost::asio::ip::tcp::socket> m_socket;
// Stuff below stays the same
И реализация будет такой:
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;
}
При этом мне не нужно копировать около 4 (или, может быть, даже больше) параметров и связывать их вместе.Когда мне нужен объект сокета, я могу просто получить к нему доступ через указатель, который является членом класса.
Теперь мой простой вопрос -> это правильный путь?Функцию можно вызывать несколько раз, даже если асинхронная часть не завершена.(Я знаю, что тогда я должен защитить сокет и распознаватель мьютексом).Но разве это чисто, что я каждый раз создаю новый объект, когда вызываю функцию Dispatch
?Достаточно ли вызова reset
, чтобы избавиться от ненужной памяти?
Я знаю, что это длинный текст для конкретного короткого вопроса, и, кроме того, в нем даже нет ошибки.Но я всегда хотел бы знать, прилично ли я иду и если есть лучший способ, как я это сделаю.