Как стать автором
Обновить
31
0
Александр Дубовик @Dubovik_a

С++

Отправить сообщение
Pimpl на базе std::shared_ptr в статье приведён.
Если Вы имеете в виду, что при таком построении пимпла фасад может подсунуть реализации ссылку на неё же саму — то да, может. И получится то же самое, что с std::enable_shared_from_this. Это ситуация типа «захотелось применить std::enable_shared_from_this, но не знали о таком, поэтому сделали то же самое, но без перламутровых пуговиц». И проверить будет сложнее, т.к. поиск по shared_from_this не покажет такого места.

Антипаттерн «Зомби» — не просто про управление классом собственным временем жизни. Это ещё цветочки, которые могут работать корректно.
Пример SteppingZomby в статье отработал так:
Вывод в консоль
N13SteppingZomby5ZombyE::resolveDnsName started
N13SteppingZomby5ZombyE::resolveDnsName finished
N13SteppingZomby5ZombyE::connectTcp started
============================================================
| Zomby was killed |
============================================================
N13SteppingZomby5ZombyE::connectTcp finished
N13SteppingZomby5ZombyE::establishSsl started
N13SteppingZomby5ZombyE::establishSsl finished
N13SteppingZomby5ZombyE::sendHttpRequest started
N13SteppingZomby5ZombyE::sendHttpRequest finished
N13SteppingZomby5ZombyE::readHttpReply started
N13SteppingZomby5ZombyE::readHttpReply finished
N13SteppingZomby5ZombyE::~Zomby
N6Common22WriteToConsoleListenerE::~WriteToConsoleListener


А мог бы отработать вот так:
Вывод в консоль
N13SteppingZomby5ZombyE::resolveDnsName started
N13SteppingZomby5ZombyE::resolveDnsName finished
N13SteppingZomby5ZombyE::connectTcp started
============================================================
| Zomby was killed |
============================================================
N13SteppingZomby5ZombyE::connectTcp finished
N13SteppingZomby5ZombyE::~Zomby
N6Common22WriteToConsoleListenerE::~WriteToConsoleListener


Управление собственным временем жизни могло быть в обоих случаях. Но иногда оно создаёт весьма сложные для детектирования и отладки проблемы, а иногда — нет.
Т.е. «Зомби» — это когда уже «доуправлялись собственным временем жизни». Когда абстрактная кривизна архитектуры превратилась в большущие, но при этом хорошо замаскированные проблемы. Вроде код работает. И автотесты проходят. И динимаческий анализ молчит. И статический тоже молчит. Ну может в логах оно отбивается (но если отбивается — значит логи многокилометровые, и следы зомби там могут теряться годами).
Ведь в примерах SimpleCyclic и PimplCyclic тоже есть управление собственным временем жизни. Но это не то, оно не так опасно — и динамическим анализом находится, и на практике я не знаю ситуаций, в которых захотелось бы так написать.
А для активных сущностей — иногда именно так и пишут.
Бензин опасен, да. Любая штуковина с большим запасом энергии опасна.
Но бензиновая технология отрабатывается уже больше века.
А литий — мало того, что недавно применяется в технике, так Вы им ещё и пользуетесь в очень опасной манере.
Какое отношение вызов detach имеет к зачистке системой? Поток продолжает жить и после detch(), только деструктор std::thread перестаёт быть блокирующим.
Кроме того, аналогичного поведения можно добиться вообще без вызова detach и даже без запуска потока в пользовательском коде. Примеры из документации буста легко переделать под такое — надо только не блокировать главный поток вызовом run(), а запустить в нём polling-loop с вызовами boost::asio::io_context::poll().
1. Соединять литий-ионные аккумуляторы при помощи пайки — плохо. Правильная технология — точечная сварка. Температурой пайки даже при кратковременном воздействии можно нанести аккумулятору перманентное повреждение, плюс оно ещё и массивнее.
2. Литий-ионные аккумуляторы — крайне опасная шутка. От 6 таких элементов, как на фото, не одна квартира сгорела. От аккумуляторов размером в одну треть элемента иногда люди гибнут. Несмотря на то, что опасность обычно возникает при зарядке (умное зарядное устройство с контролем температуры обязательно!), но при таких режимах, в которых Вы это собрались эксплуатировать, я бы не рискнул иметь эту бомбу ближе метров 20 от себя.
3. На 72 ампера нужны очень нехилые провода от АКБ до мотора. Подумайте о повышении вольтажа с целью снижения тока.
Всякая селёдка — рыба, но не всякая рыба — селёдка.
Не каждое место в C++-коде, требующее повышенного внимания, вызвано применением std::enable_shared_from_this. Но каждое место применения std::enable_shared_from_this требует повышенного внимания.
Статья не совсем о циклических ссылках. Это только половина вопроса. Причём более лёгкая половина — та, которую можно выявить динамическим анализом кода.
Статья — о циклических ссылках, в которые попадают активные сущности.

Моя практика (да и примеры стороннего кода) показывает, что обычно циклическая ссылка возникает всё же при помощи std::enable_shared_from_this.
И я бы даже сильнее сказал: если Вам захотелось задействовать std::enable_shared_from_this — вероятно, Вам надо чинить архитектуру.
Можно и без — если кто-нибудь снаружи ссылку подсунет. И в статье об этом тоже говорится.
Не совсем исправно. В SingletonShared, пример 3 рассмотрен вариант, когда деструктор синглтона как раз не вызывается. Правда, это скорее не про утечку памяти, а про сбой требуемой деинициализации типа подчистки временных файлов.
PVS — штука определённо полезная, как и данная статья.
Но для совсем честного понимания выгоды от использования PVS случаи
не тот цвет кнопки, поправили логику работы меню, использовали не ту формулу
тоже в общем-то надо учитывать.
Данная статья в первую очередь про избежание неопределённого поведения.
Но теперь мне хотя бы понятен довод: производительность. Сравнение которой еще и в многопоточном исполнении после устранения гонок в оригинальном счётчике Шварца вполне потянет на отдельную статью.
Предлагаю завязывать — обсуждение ни о чём.
Вариант, да.
Но в плане реальной применимости:
— реализовать идиому Шварца по памяти через месяц после прочтения — вряд ли реально, а приведённые мной модификации — вполне;
— как поддерживать код, для правильного функционирования которого требуется столько весьма точно выполненных ритуалов?
— требуемый для корректировки синглтона Мейерса механизм (умные указатели) УЖЕ давно стандартизован, и отказываться от него в пользу самодельного велосипеда — ну я прямо даже не знаю…
И самое главное — ради чего? Где преимущества?
Если Вы это приводите, как аргумент в пользу счётчика Шварца — то какой-то он очень уж слабенький. Вообще к любому указателю, даже сырому, лучше не обращаться без проверки.
Счётчик Шварца является старомодной идиомой на сырых указателях без потокобезопасности, использующей для той же задачи несколько объектов со static storage duration. Возможно, его тоже можно улучшить с применением современного STL — напишите свою статью об этом, там и обсудим более подробно. В нём намного больше магии, чем в синглтонах Мейерса и их модификациях, рассмотренных в статье. Например (код отсюда):
static struct StreamInitializer {
  StreamInitializer ();
  ~StreamInitializer ();
} streamInitializer; // static initializer for every translation unit

Достаточно забыть «streamInitializer» перед завершающей точкой с запятой (при реализации без шпаргалки наверняка так и будет) — и эта идиома может несколько раз создать-уничтожить синглтон, что вряд ли соответствует задумке. Хотя как-то работать при этом будет, и о такой ошибке Вас никто не предупредит — ни компилятор, ни даже сторонний статический анализатор.
Да, весь материал статьи основан именно на синглтоне Мейерса и его модификациях.
Не понял вопроса. Уточните.
Ну я же просил — не выходить за рамки статьи. Она НЕ об архитекуре вообще. Она НЕ о недостатках синглтона как архитектурного решения.Она НЕ о возможных альтернативах. Может быть немного она «о возможных последствиях нескольких синглтонов в одной программе, и что с этим по-быстрому сделать, чтобы не перекраивать архитектуру».
Упомянутые «возможные последствия» вполне могут отпугнуть от использования паттерна (я даже надеюсь, что отпугнут).
Ну а тех, кого не отпугнут — снабдят более глубоким пониманием.
Опять же, поднятые в статье вопросы, если Вы не заметили (допускаю, что статью толком не прочитали), как раз приближают к:
проектировать все свои проекты/системы с учетом трёх фаз «жизни»
и
Инициализация/деинициализация недоступна обычному (его можно называть «user-level») коду

Ещё более неуместно в данном контексте выглядит критика стандарта, если честно.
Там используется другая идея — разделение компилятором инициализации статиков на две фазы: статическую и динамическую. Преимуществ относительно применения STL не просматривается.
Чуть подробнее вчитался в код идиомы Шварца.
С одновременным созданием из разных потоков проблемы как бы нет совсем — стандарт гарантирует отсутствие гонки. Если интересно — дам ссылки на пункты стандарта. Хотя это и выходит за рамки статьи.
Просто с созданием — тоже нет проблемы, т.к. сам по себе паттерн «Синглтон» именно и направлен на то, чтобы статик инициализировался при первом обращении.
А вот с уничтожением — просто беда. Говорю из личного опыта: примерно половина случаев применения синглтона требовала дебага, т.к. при сворачивании приложения происходил крэш. В статье показано, что, если о возможных проблемах не задумываться, то оно примерно так и будет, т.к. зависит от казалось бы незначительных факторов.

«The 'nifty counter' or 'Schwarz counter' idiom is an example of a reference counting idiom». Идиома подсчёта ссылок уже реализована в STL. Причём в дополнение к std::shared_ptr есть еще и std::weak_ptr, который позволяет делать очень замечательные вещи. В статье полезность std::weak_ptr я раскрыл аж в двух примерах — последний пример из классики, и корректный пример из SingletonWeak. Кроме того, std::shared_ptr гарантирует потокобезопасность блока подсчёта ссылок (хотя, опять же, это выходит за рамки статьи). Итого, упомянутая Вами идиома:
— требует ручной реализации того, что уже есть в STL;
— чтобы сделать её потокобезопасной, придётся попотеть;
— предполагает только продление жизни, недостатки которого я раскрыл достаточно подробно.
Условие выхода из рекурсии хотя бы предусмотрено?

Информация

В рейтинге
Не участвует
Откуда
Минск, Минская обл., Беларусь
Зарегистрирован
Активность