Boost.asio и асинхронная цепочка, unique_ptr?

Я не очень хорошо знаком с асинхронным программированием, и у меня есть вопрос.

Мой вопрос заключается в следующем. Учитывая приведенный здесь пример echo_server для C++11 в boost.asio: http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/example/cpp11/spawn/echo_server.cpp

Я хотел бы знать, можно ли заменить std::make_shared<session> в С++ 14 на std::unique_ptr<session> в С++ 14, избегая накладных расходов на подсчет ссылок.

Я не уверен, так как у нас есть shared_from_this(), но не что-то вроде unique_from_this(), так как я могу получить доступ к unique_ptr<session> изнутри this?.


person Germán Diago    schedule 09.05.2016    source источник
comment
Вы знаете, что накладные расходы - это один указатель на дополнительную память для каждого экземпляра и скачок счетчика ссылок при создании и удалении общего указателя - в остальном это точно так же, как обычный указатель. Также неясно, о каком shared_ptr вы говорите, поскольку в этом примере их несколько.   -  person xaxxon    schedule 09.05.2016
comment
Концепция unique_from_this даже не имеет смысла. Вы не можете просто создать уникальный указатель на адрес памяти произвольно, так как у вас возникнет состояние гонки относительно того, кто очистит память.   -  person xaxxon    schedule 09.05.2016


Ответы (2)


Нет, использование shared_ptr в asio программировании идиоматично.

Идея состоит в том, что количество незавершенных обработчиков соответствует общему счету объекта, инициирующего асинхронные операции. Это достигается путем привязки копии shared_ptr, управляющей объектом, к объектам функции-обработчика.

Способ С++ 11/14 состоял бы в том, чтобы заменить boost::shared_ptr на std::shared_ptr (std::bind, лямбда-выражения и т. д. также отлично работают с asio).

Обновление, теперь, когда я полностью понимаю вопрос:

В приведенном вами примере, я так понимаю, вы имеете в виду shared_ptr с именем self, который создается в методе go()? Вы можете написать его без shared_ptr, если хотите. Вам нужно будет удалить это как последнюю строку go(). Вы также должны помнить, чтобы поймать любые исключения, чтобы убедиться, что этот путь кода был выбран. Уникальный_ptr, конечно, может быть настроен для этого, но тогда у вас возникнет проблема управления временем жизни между созданием сеанса и успешным созданием уникального_ptr. shared_ptr облегчает бремя управления за счет стоимости одного атомарного вкл...

В этом случае ответ строго «да», но имхо я посоветую, так как он более хрупкий.

person Richard Hodges    schedule 09.05.2016
comment
Насколько я понимаю, ваш объект сеанса будет проходить через конвейер обработчиков, по одному. Состояние вашего сеанса никогда не передается. Почему unique_ptr не имеет смысла? Дело в том, что когда последний обработчик завершится, память будет освобождена. Верно ли это? - person Germán Diago; 09.05.2016
comment
Последний или последний? Если есть какие-либо незавершенные обработчики, которые включают сеанс, все они в конечном итоге сработают (даже если они будут отменены в результате уничтожения сокета). Вы можете вести ручной подсчет невыполненных обработчиков и удалять сеанс, когда он достигает нуля, но зачем? Shared_ptr делает именно это практически без накладных расходов. - person Richard Hodges; 09.05.2016
comment
Если есть сессия, в цикле asio все еще есть работа. Это не закончится. Итак, если я не ошибаюсь, произойдет следующее: если вы используете unique_ptr для каждой из сессий, только когда работы больше не будет, цикл завершится. Я согласен, что накладные расходы могут быть низкими, это больше теоретический вопрос :) - person Germán Diago; 09.05.2016
comment
В приведенном вами примере, я так понимаю, вы имеете в виду shared_ptr с именем self, который создается в методе go()? Вы можете написать его без shared_ptr, если хотите. Вам нужно будет поставить delete this в качестве последней строки go(). Вы также должны помнить, чтобы поймать любые исключения, чтобы убедиться, что этот путь кода был выбран. Уникальный_ptr, конечно, может быть настроен для этого, но тогда у вас возникнет проблема управления временем жизни между созданием сеанса и успешным созданием уникального_ptr. shared_ptr облегчает бремя управления за счет стоимости одного атомарного вкл.. - person Richard Hodges; 09.05.2016
comment
@GermánDiago ... в этом случае, когда я сказал «нет», я имел в виду «да» :) - person Richard Hodges; 09.05.2016
comment
Я понимаю. если вы задокументируете этот последний комментарий в своем ответе, я могу закрыть его как решенный :) Это отвечает на мой вопрос. - person Germán Diago; 09.05.2016
comment
Если есть сессия, в цикле asio все еще есть работа — это просто курица и яйцо. Это не правда ни в каком смысле. Это верно, когда сеанс исчезает с последней незавершенной операцией (но это круговое рассуждение). - person sehe; 09.05.2016

Насколько я понимаю, ваш объект сеанса будет проходить через конвейер обработчиков, по одному. Состояние вашего сеанса никогда не передается. Почему unique_ptr не имеет смысла? Дело в том, что когда последний обработчик завершится, память будет освобождена. Верно ли это?

Да, это трюк. Библиотека была разработана на основе копируемых обработчиков завершения.

Если вы беспокоитесь о накладных расходах, действительно избегайте shared_ptr.

В этом случае просто укажите ссылку на некоторое состояние с внешним управлением временем жизни. Просто убедитесь, что он остается живым (так же, как вы делаете это с самим объектом io_service).

person sehe    schedule 09.05.2016
comment
Я понимаю это, но это не отвечает на мой первоначальный вопрос, а именно: могу ли я использовать unique_ptr и сделать unique_pr, который будет автоматически переноситься до тех пор, пока сам сеанс не умрет? - person Germán Diago; 09.05.2016
comment
Если вы это поняли, почему вы спросили< /а>? К тому же, я не знаю, как ответить более четко. Можно ли std::unique_ptr копировать? Если нет, то использовать его в обработчиках завершения напрямую невозможно, и в лучшем случае это будет кладж, если его прикрыть косвенностью. Мой совет в моем ответе. - person sehe; 09.05.2016
comment
В С++ 14 вы можете захватить [my_ptr=move(my_ptr)], но мне интересно, есть ли какие-либо оставшиеся проблемы. Больше всего беспокоит unique_from_this() или подобное, поэтому я задался вопросом, действительно ли это возможно: заменить на unique_ptr и получить что-то подобное. - person Germán Diago; 09.05.2016
comment
Можно, но это не делает результат копируемым. Как уже упоминали другие, unique_from_this не имеет смысла. Мой совет о чем-то подобном был в ответе с самого начала. delete this — это один из способов взломать этот результат. Я считаю, что это запах кода, но он может быть близок к вашей ментальной модели вещей. - person sehe; 09.05.2016