Каков наилучший способ обеспечения допустимой продолжительности жизни объекта при использовании Boost.Asio? - PullRequest
13 голосов
/ 08 января 2009

В последнее время много играл с Boost.Asio. Мне очень нравится библиотека, поскольку она предлагает фантастический способ выжать производительность из современных многоядерных систем.

Вопрос, который я задавал себе несколько раз, и я подумал, что стоит отбросить вопрос о продолжительности жизни / владении объектом при выполнении асинхронных вызовов с Asio.

Проблема, с которой я неоднократно сталкивался, заключается в том, что вам часто приходится «истекать» у объекта, для которого все еще существуют асинхронные обратные вызовы. Если этот объект выходит из области видимости до того, как будет вызван обратный вызов, все неизбежно пойдет не так.

Для борьбы с этим я использовал шаблон boost::enable_shared_from_this в качестве базового класса для большинства классов, основанных на asio. Это работает нормально, но это немного обременительно: обычно это также означает защиту конструктора и добавление метода фабрики в класс, чтобы гарантировать, что все экземпляры создаются внутри shared_ptr.

Я просто хотел узнать, как другие люди решали эту проблему. Я иду об этом лучшим способом? Или я получил свой Asio.Foo все неправильно?

Обсудить ...:)

Ответы [ 2 ]

2 голосов
/ 12 июня 2009

Использование boost::enable_shared_from_this в значительной степени способ сделать это. Кроме того, обратите внимание на использование boost::weak_ptr, если вам нужны ссылки на объект, которые не должны сохранять объект, если они являются единственными оставшимися ссылками.

Хороший пример использования weak_ptr: я использую enable_shared_from_this в своем классе сокетов, который использует boost::asio. Фреймворк boost::asio - это единственное, что хранит постоянные ссылки на объект через обработчики чтения и записи. Таким образом, когда вызывается деструктор сокета, я знаю, что сокет закрыт, и я могу «делать вещи» в обработчике для очистки этого закрытого сокета. Приложение, которое использует сокет, имеет только ссылку weak_ptr на него, которое оно продвигает до shared_ptr, когда оно хочет работать с сокетом (обычно для записи в него). Это продвижение может быть проверено на неудачу в случае, если сокет исчез, хотя обработчик закрытия сокета обычно очищает все ссылки weak_ptr соответствующим образом, прежде чем это произойдет.

1 голос
/ 08 января 2009

Такие вещи не ограничиваются Асио. Недавно я написал класс пула потоков (используя Boost :: Thread), у которого почти такая же проблема - потоки будут вызывать класс пула потоков, который их создал, чтобы увидеть, какую задачу они должны делать дальше, используя простой указатель к нему, и если класс пула потоков был уничтожен с дочерним потоком, все еще работающим, программа потерпит крах. Я справился с этим, вызвав interrupt для каждого из потоков в деструкторе пула потоков, затем подождав, пока все они выйдут, прежде чем позволить деструктору вернуться.

Если я понимаю ваше решение с указателем общего доступа, похоже, оно делает то же самое - обеспечение того, что элемент не может быть уничтожен, пока он больше не нужен. Эстетически приятное решение тоже. Я не вижу лучшего ответа на эту проблему.

...