Здравствуйте, LaptevVV, Вы писали:
LVV>Может ли уважаемый ALL привести примеры задач, в которых без шаред_птр никак не обойтись ?
У нас в RESTinio объект request создается самим RESTinio на контексте одной из IO-нитей. Затем этот объект отдается в пользовательский request_handler, а пользовательский request_handler может делегировать обработку запроса кому-то еще (подробнее здесь). И получается два владельца у request-а: и RESTinio, и пользователь. Причем, поскольку обработка асинхронная и может занять больше времени, чем это позволяет RESTinio, то в таком случае RESTinio у себя удаляет информацию о request-е. Но сам объект request остается жить, т.к. указатель на него еще есть у пользователя.
В такой ситуации shared_ptr является простым и достаточно эффективным решением проблемы совместного владения объектом request.
LVV>>Может ли уважаемый ALL привести примеры задач, в которых без шаред_птр никак не обойтись ? S>У нас в RESTinio объект request создается самим RESTinio на контексте одной из IO-нитей. Затем этот объект отдается в пользовательский request_handler, а пользовательский request_handler может делегировать обработку запроса кому-то еще (подробнее здесь). И получается два владельца у request-а: и RESTinio, и пользователь. Причем, поскольку обработка асинхронная и может занять больше времени, чем это позволяет RESTinio, то в таком случае RESTinio у себя удаляет информацию о request-е. Но сам объект request остается жить, т.к. указатель на него еще есть у пользователя. S>В такой ситуации shared_ptr является простым и достаточно эффективным решением проблемы совместного владения объектом request.
Спасибо.
Вот и я тоже как-то в эту сторону смотрел: разные треды имеют доступ к одному объекту.
Но думал, что мож попроще как-то удастся смастерить...
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Здравствуйте, LaptevVV, Вы писали:
LVV>Может ли уважаемый ALL привести примеры задач, в которых без шаред_птр никак не обойтись ?
ну самое очевидное, когда мы передаём ссылку в другой объект. Как без shared+weak уследить за временем жизни?
У меня такой случай был недавно. Одни умники прописали в корпоративном гайдлайне, что пользоваться shared_ptr нельзя. Поэтому все передавали обычные сырые указатели. И понятно что когда проект разросся, за временем жизни не уследишь. Владелец помер — мы получили мёртвую ссылку. Я предложил либо по-быстрому делаем на shared_ptr + weak_ptr, либо надо переделывать полностью архитектуру (причём всё равно без гарантий). Шареды не разрешили и время не дали. В общем, этот баг там живёт уже год. Причём по крэшам тот проект был наверное рекордсменом на моём опыте. Жёсткие гайдлайны не дают писать нормально, приходится извращаться. Вот и получили. Там и с мьютексами была такая же фигня. Для всех очевидно что в коде гонка, все знают, что периодически там стреляет крэш, но никто идти разбираться с писателями гайдлайнов не хочет.
Мораль сей басни: гайдлайны — зло, с shared_ptr проще бороться на этапе code review.
Тип shared_ptr — это умный указатель в стандартной библиотеке C++, предназначенной для сценариев, в которых несколько владельцев должны управлять временем существования объекта. После инициализации указателя shared_ptr его можно копировать, передавать по значению в аргументах функций и присваивать другим экземплярам shared_ptr. Все экземпляры указывают на один и тот же объект и имеют общий доступ к одному "блоку управления", который увеличивает и уменьшает счетчик ссылок, когда указатель shared_ptr добавляется, выходит из области действия или сбрасывается. Когда счетчик ссылок достигает нуля, блок управления удаляет ресурс в памяти и самого себя.
Пример настройки
Пример 1
Пример 2
Пример 3
Пример 4
Пример 5
Пример 6
См. также
Я лично это понимаю так.
1. Первая предпосылка, что нужен именно указатель, без указателя ведь тоже можно обойтись.
2. Вторая предпосылка, что нужно передавать указатель с обрывом связи где он был изначально создан, то есть нет ручного удаления объекта по указателю.
И вот здесь я даже не знаю, потому что есть большая разница между.
1. Так просто не обойтись.
2. Прямо никак не обойтись.
Что имеет умный указатель?
Он имеет счётчик ссылок.
Что прямо никак нельзя имитировать это другим способом?
Очень сомнительно.
Другое дело конструкция умного указателя может быть очень удобна в текущей архитектуре, которую выбрал архитектор данной программы. Причём как адрес указателя, так и счётчик ссылок занимают память, это накладные расходы. Но в тоже время выделение и перераспределение блоков памяти не дешёвая операция на чём и можно сэкономить с указателями и следовательно умными указателями.
А архитектур может быть миллион и три тележки, и опять же смотрим первую и вторую предпосылки. И часто можно извратиться и сделать через пень колоду, то есть провести уничтожение объекта иначе. Но ведь вопрос не как сделать иначе, а чтобы вот прямо ну никак не обойтись без умных указателей.
Кстати, мне тут подумалось, что основная выгода умных указателей ещё и в том, чтобы очищать объекты независимо. Если есть массив указателей и все объекты по указателям будут уничтожены только в момент уничтожения массива, то что даёт умный указатель? Он в теории даёт кучу лишних счётчиков ссылок, которые обнулят одновременно. Так-то надо смотреть, что там на самом деле в коде реализовано.
Здравствуйте, velkin, Вы писали:
V>Для примера Valgrind.
обнаружить утечку/краш не проблема. Проблема его предотвратить в будущем. Я говорю об архитектурном решении, как без shared+weak быть уверенным, что ссылка не умрёт. Вот Rust ругают, что задолбёшься компилятор ублажать. Но чтобы построить такое же безопасное решение на С++, надо потратить времени иногда даже больше.
Вот банальная задача подписки на события. Есть notifier, который оповещает своих подписчиков (listener). В любой момент listener может двинуть кони. Чтобы не получить умершую ссылку, надо как минимум добавлять метод unsubscribe. Чтобы быть уверенным, что программист не забудет его вызвать, надо оборачивать его в raii объект (какой-то Subscriber). С созданием и хранением такого объекта тоже могут возникнуть проблемы (чтобы он сам не пережил Listener). Причём проблему то мы полностью не решили. Мы просто перенесли боль от dead ref на Subscriber вместо Notifier. Иногда пойти по пути Java может быть самым простым решением:
SP>У меня такой случай был недавно. Одни умники прописали в корпоративном гайдлайне, что пользоваться shared_ptr нельзя. Поэтому все передавали обычные сырые указатели. И понятно что когда проект разросся, за временем жизни не уследишь. Владелец помер — мы получили мёртвую ссылку. Я предложил либо по-быстрому делаем на shared_ptr + weak_ptr, либо надо переделывать полностью архитектуру (причём всё равно без гарантий). Шареды не разрешили и время не дали. В общем, этот баг там живёт уже год. Причём по крэшам тот проект был наверное рекордсменом на моём опыте. Жёсткие гайдлайны не дают писать нормально, приходится извращаться. Вот и получили. Там и с мьютексами была такая же фигня. Для всех очевидно что в коде гонка, все знают, что периодически там стреляет крэш, но никто идти разбираться с писателями гайдлайнов не хочет.
Сурово... SP>Мораль сей басни: гайдлайны — зло, с shared_ptr проще бороться на этапе code review.
Интересно, чем вызвано категорическое нежелание использовать шаред_петеэры ?
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Здравствуйте, LaptevVV, Вы писали:
LVV>Интересно, чем вызвано категорическое нежелание использовать шаред_петеэры ?
Наверно начитались статей, в которых авторы утверждали, что 10% времени программы уходило на инкремент/декремент каунтеров shared_ptr.
Подозреваю, что авторы пропустили какую-нибудь хрень типа такой:
func(shared_ptr p) {}
...
shared_ptr ptr = ptr_create();
for(i = 0; i < billion; ++i)
{
func(ptr);
}
Мораль — передача по значению не всегда хорошо. И вообще, имхо, лучше func(shared_ptr::value_type* p). Если ф-ция сихронная
Здравствуйте, LaptevVV, Вы писали:
LVV>Может ли уважаемый ALL привести примеры задач, в которых без шаред_птр никак не обойтись ?
Передача объектов DOM в плагины, или в иные языки программирования типа python.
Т.е. когда мы не контролируем время жизни объектов, на стадии проектирования.
Здравствуйте, LaptevVV, Вы писали:
LVV>Может ли уважаемый ALL привести примеры задач, в которых без шаред_птр никак не обойтись ?
В двух разных окнах приложения отображаем (редактируем) одни и те же данные (картинку) с, например, разными фильтрами. Пользователь волен открывать и закрывать окна в произвольном порядке.
Здравствуйте, LaptevVV, Вы писали:
LVV>Может ли уважаемый ALL привести примеры задач, в которых без шаред_птр никак не обойтись ?
Задачи, где нет уникального владения объектом. Например, что-то вроде tee для данных в многопоточной среде, особенно если данные читают в разных целях. В голову приходит некоторый CV который анализирует фрейм и одновременно энкодер, который сжимает или загонят в сжималку этот фрейм.
Здравствуйте, LaptevVV, Вы писали:
LVV>Может ли уважаемый ALL привести примеры задач, в которых без шаред_птр никак не обойтись ?
А что входит в никак? Всегда можно ручками следить и удалять), только это же ужас ужас.
Здравствуйте, Chorkov, Вы писали:
LVV>>Может ли уважаемый ALL привести примеры задач, в которых без шаред_птр никак не обойтись ?
C>Передача объектов DOM в плагины, или в иные языки программирования типа python. C>Т.е. когда мы не контролируем время жизни объектов, на стадии проектирования.
Так лучше не делать, в итоге стреляет когда по разному удаляется и приходят к init/deinit в С стиле. В плагины и т.д. проще голый указатель передать, как явное указание что нет владения данными.
LVV>>Может ли уважаемый ALL привести примеры задач, в которых без шаред_птр никак не обойтись ? I>А что входит в никак? Всегда можно ручками следить и удалять), только это же ужас ужас.
не-не-не...
Ручками — это как раз для сравнения с шаредом...
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Здравствуйте, LaptevVV, Вы писали:
LVV>>>Может ли уважаемый ALL привести примеры задач, в которых без шаред_птр никак не обойтись ? I>>А что входит в никак? Всегда можно ручками следить и удалять), только это же ужас ужас. LVV>не-не-не... LVV>Ручками — это как раз для сравнения с шаредом...
Тогда ответ: в любом случае когда нужен полиморфизм. А то я уже подумал вопрос о том когда не хватает unique_ptr.
LVV>>>>Может ли уважаемый ALL привести примеры задач, в которых без шаред_птр никак не обойтись ? I>>>А что входит в никак? Всегда можно ручками следить и удалять), только это же ужас ужас. LVV>>не-не-не... LVV>>Ручками — это как раз для сравнения с шаредом... I>Тогда ответ: в любом случае когда нужен полиморфизм. А то я уже подумал вопрос о том когда не хватает unique_ptr.
Ну, с уникумом вопросов нет, там понятно и легко объясняется на простых примерах с локальным указателем...
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Здравствуйте, LaptevVV, Вы писали:
LVV>Может ли уважаемый ALL привести примеры задач, в которых без шаред_птр никак не обойтись ?
Кэши, CoW, сложные динамические структуры типа DOM.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
LVV>>Может ли уважаемый ALL привести примеры задач, в которых без шаред_птр никак не обойтись ? ·>Кэши, CoW, сложные динамические структуры типа DOM.
Насчет DOM — спасибо!
Как раз в тему для меня сейчас...
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
А что мешает использовать как шаред птр, но не называть таковым. И гайдлайны целы и код не глючен
Всмысле хранить в объекте счетчик ссылок и ручками обрабатывать.