Пример из boost.asio
От: Wody  
Дата: 14.07.11 18:58
Оценка:
Здесь есть пример простого http-сервера http://www.boost.org/doc/libs/1_39_0/doc/html/boost_asio/examples.html
Тут идет прием (accept) новых соединений http://www.boost.org/doc/libs/1_39_0/doc/html/boost_asio/example/http/server/server.cpp

Возникло непонимание. Зачем указатель на новое подключение хранится в членах класса server? Разве нельзя вместо:

server::server(const std::string& address, const std::string& port,
    const std::string& doc_root)
  : io_service_(),
    acceptor_(io_service_),
    connection_manager_(),
    new_connection_(new connection(io_service_, connection_manager_, request_handler_)),
    request_handler_(doc_root)
{
//...
  acceptor_.async_accept(new_connection_->socket(),
      boost::bind(&server::handle_accept, this,
        boost::asio::placeholders::error));
}


сделать так:
server::server(const std::string& address, const std::string& port,
    const std::string& doc_root)
  : io_service_(),
    acceptor_(io_service_),
    connection_manager_(),
          connection_manager_, request_handler_)),
    request_handler_(doc_root)
{
//...
connection_ptr p(new connection(io_service_, connection_manager_, request_handler_));
  acceptor_.async_accept(new_connection_->socket(),
      boost::bind(&server::handle_accept, this, p, boost::asio::placeholders::error));
}

?
Тогда handle_accept будет таким:

void server::handle_accept(connection_ptr new_connection, const boost::system::error_code& e)
{
  if (!e)
  {
    connection_manager_.start(new_connection);
    new_connection_.reset(new connection(io_service_, connection_manager_, request_handler_));
connection_ptr p(new connection(io_service_, connection_manager_, request_handler_));
  acceptor_.async_accept(new_connection_->socket(),
      boost::bind(&server::handle_accept, this, p, boost::asio::placeholders::error));
  }
}


Если я правильно понимаю, то connection_ptr, будучи shared_ptr<connection> не должен разрушить объект, находясь в недрах asio. Зачем тогда хранить указатель в членах класса? Или я неправ?
Re: Пример из boost.asio
От: abrarov Россия http://asio-samples.blogspot.com/
Дата: 14.07.11 21:15
Оценка:
Здравствуйте, Wody, Вы писали:

W>Возникло непонимание. Зачем указатель на новое подключение хранится в членах класса server?

Можно, конечно, хранить в completion handler. В некоторых примерах из документации Asio так и сделано.

А это:
void server::handle_accept(connection_ptr new_connection, const boost::system::error_code& e)


Лучше все же заменить на:
void server::handle_accept(const connection_ptr& new_connection, const boost::system::error_code& e)


W>Если я правильно понимаю, то connection_ptr, будучи shared_ptr<connection> не должен разрушить объект, находясь в недрах asio.

Все правильно понимаете.

W>Зачем тогда хранить указатель в членах класса? Или я неправ?

Это примеры и они ориентированы на то, чтобы показать различные варианты использования Asio.
Programs must be written for people to read, and only incidentally for machines to execute
Re[2]: Пример из boost.asio
От: Wody  
Дата: 14.07.11 21:26
Оценка:
Здравствуйте, abrarov, Вы писали:

Спасибо за ответ. Просто хотел перестраховаться, т.к. в программе пока непонятный баг при приеме соединений. Значит проблема в другом.
Re[3]: Пример из boost.asio
От: abrarov Россия http://asio-samples.blogspot.com/
Дата: 14.07.11 21:47
Оценка:
Здравствуйте, Wody, Вы писали:

W>Здравствуйте, abrarov, Вы писали:

W>Спасибо за ответ. Просто хотел перестраховаться, т.к. в программе пока непонятный баг при приеме соединений. Значит проблема в другом.

На самом деле все не так уж и просто — раз у Вас есть проблемы, то я продолжу: вариант с хранением сокета (за счет connection_ptr) в completion handler гораздо лучше. Причина простая — ресурсы, используемые асинхронной операцией (те, что переданы по неконстантной ссылке), должны оставаться валидными до окончания операции. См. Requirements on asynchronous operations.
Programs must be written for people to read, and only incidentally for machines to execute
Re[4]: Пример из boost.asio
От: Wody  
Дата: 15.07.11 20:48
Оценка:
Здравствуйте, abrarov, Вы писали:

Спасибо, стало яснее.

Смотрю примеры на Вашем svn. Очень полезный ресурс, желаю успехов в развитии
Re[4]: Пример из boost.asio
От: Wody  
Дата: 15.07.11 21:15
Оценка:
В том-же примере возник еще вопрос. В классе connection есть функция close: http://www.boost.org/doc/libs/1_47_0/doc/html/boost_asio/example/http/server/connection.cpp
Она закрывает сокет. В классе connection_manager (http://www.boost.org/doc/libs/1_47_0/doc/html/boost_asio/example/http/server/connection_manager.cpp), который содержит указатели (shared_ptr<connection>) есть функция close, которая закрывает соответствующий сокет:
void connection_manager::stop(connection_ptr c)
{
  connections_.erase(c);
  c->stop();
}

Пусть сокет открыт и начато асинхронное чтение (то есть сокет стоит в очереди в io_service). Тогда, если в какой-то момент мы его закрываем: manager_.stop(some_connection_ptr) и удаляем все экземпляры данного shared_ptr, то объект connection разрушается, но сокет же все еще в очереди и лишь когда управление снова вернется boost::asio, будет вызван хэндлер, указанный при запуске асинхронного чтения и ему будет передана ошибка boost::asio::error::operation_aborted, но это будет уже обращение к удаленному объекту?
Re[5]: Пример из boost.asio
От: Wody  
Дата: 15.07.11 23:33
Оценка:
Здравствуйте, Wody, Вы писали:

Ступил. В хэндлере же хранится shared_ptr, полученный через shared_from_this.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.