Обновить
129
0
Григорий Демченко@gridem

Software Engineer

Отправить сообщение
Вообще говоря, это не так. Смотрите, например: комментарий на stackoverflow, а также секцию 5.4 в Technical Report on C++ Performance
Для того, чтобы бросить исключение, надо эту ситуацию обнаружить, т.е. вставить соответствующую проверку. Такая проверка будет выполняться даже в том случае, если все хорошо. Именно поэтому будет замедление. Но мне кажется, что это есть преждевременная оптимизация. Для меня лучше иметь стабильное поведение, чем непонятные креши. А сделать профайлинг и заоптимизировать можно в любой момент, отказавшись от этого if.
Как минимум, при обращении к данным shared_ptr упадет в случае отсутствия таковых, в то время как мой подход кидает исключение, что является более безопасным способом. Уже это серьезно отличает от shared_ptr и является очень полезным. Я не говорю о других достоинствах, которые значительно упрощают жизнь. Поэтому использование дополнительного класса более, чем оправдано.
А в чем сложность? Если посмотреть на другие вещи, например реализацию того же shared_ptr или просто std::vector, то там сложность на порядки выше. An — это всего лишь легкая обертка вокруг shared_ptr с вполне понятной семантикой.
Да, как вариант можно использовать unique_ptr. Однако с ним связана определенная сложность: он обладает move-семантикой и это может приводить к неприятным последствиям. С ним надо проявлять осторожность, в то время как shared_ptr можно без каких-либо проблем копировать. Однако с синглтонами такой фокус не пройдет (имеется в виду использование unique_ptr), т.к. надо шарить данные между различными клиентами.
Не совсем согласен. Используя чистый shared_ptr невозможно использовать принцип обращения зависимостей. Это усложнение обоснованное, а не просто ради прихоти. Если вы знаете, как можно реализовать похожий функционал проще, то приведите соответствующий пример. Думаю, всем это будет полезно.

По поводу запрета. Если внимательно посмотрите на приведенный код, то все классы-реализации находятся в cpp файле и соответственно недоступны другому коду.

Еще раз повторюсь, что здесь я хотел показать принцип обращения зависимостей на примере порождающих шаблонов проектирования.
1. В подзаголовке «Синглтон, фабрика и прототип» приведен способ, который позволяет избежать switch/case. В принципе, можно было бы описать подход, который бы избегал полностью решал эту проблему, но это выходит за рамки этой статьи. Здесь конкретная реализация может быть любой, начиная от простой на свичах, и заканчивая более сложной, главное — единый интерфейс.
2. Про макросы уже обсуждали в предыдущей статье.
В разговорах с коллегами мы обычно употребляем слово «фабрика». В приведенных ссылках тоже используется это слово (то, что нагуглил за пару секунд):
Фабрика 1
Фабрика 2
Строго говоря, лучше, конечно же, использовать понятие «фабричный метод», но сути это никак не меняет.
Судя по всему, статью вы не читали:

Теперь поговорим о наиболее распространенном шаблоне: фабричный метод или просто фабрика.
Можно немного раскрыть комментарий? Что в предлагаемом подходе является излишним?
Этот подход очень неплохо показал себя в библиотеке boost.asio. Там для каждого действия введены 2 функции: одна с исключением, другая — без него. Для функции без исключения передается специальный параметр, который говорит о том, какая конкретно ошибка произошла. Таким образом можно использовать любой из подходов без потери производительности, а также их комбинировать. Но написание такой библиотеки — довольно хлопотное дело.
Мне как пользователю, абсолютно все равно, что является узким местом. Если кто-то взломал компьютер через браузер, то виноват браузер (ну и я тоже, конечно). А вот вывод сообщение не решит ровным счетом ничего: большинство пользователей будет считать, что этот плагин здесь нужен, т.к. нет нормального способа определить, используется ли он для тебя или против тебя. Лучше всего, когда выдается сообщение: сейчас ваш компьютер взломают, продолжить? В противном случае это не будет работать.
1. Есть вполне неплохой термин — алгоритм без блокировок. Можно, конечно, считать, что его не существует, но тогда уж лучше вообще не переводить, чем переводить как захочется.
2. Вот это и удивляет. Приведенный код пишется человеком, который знает в этом толк. При этом отсутствие разделения lock-free и wait-free выглядит так, как будто человек не знаком с общепринятыми терминами и известными методиками. Я бы после этого поостерегся к нему прислушиваться в такой деликатной теме. Вот здесь, например, wait-free алгоритм: Беззамочные алгоритмы: ненастойчивый кэш.
3. Знакомство — это хорошо. Но хочется примеры правильного использования, а также повторного использования кода в других областях. А этого нет.

В целом я для себя кое-что новое и интересное узнал. Так что возьму на заметку с описанными выше оговорками.
Вообще, статьи это серии достаточно интересны и познавательны. Но хочется отметить несколько моментов:
1. Спорный перевод. Некоторые важные термины переводятся так, что это приводит к замешательству и спорам.
2. Нет акцента на том, где lock-free, а где wait-free алгоритмы. Это очень важно, однако из-за пункта 1 такого разграничения нет, что затуманивает понимание.
3. Отсутствие использования абстракций. С одной стороны, используются классы, типа new Y(), однако приведенный код — хардкорный С, больше структурный, чем объектный. Это приводит к каше в коде и в голове, где смешиваются главный алгоритмический код и код, использующий эти алгоритмы. Если вы хотите писать сложный код с lock-free/wait-free алгоритмами, никогда так не пишите. Таким образом, статья получилась больше похожая на введение, нежели на реальное использование в продакшн коде. Похоже на следующее: «посмотрите, как можно писать. Видите, как сложно? Я даже не уверен, что у меня все правильно. Вот, поэтому не пишите так». И это удивляет.
Лучше писать, что «алгоритм без блокировок», т.е lock-free algorithm. Но никак не «беззамочный» или «беззахватный».
Стало вообще непонятно. Чем отличается блокирующий алгоритм от захватного? Как это соотносится с lock-free алгоритмами?
Можно поподробнее, что означает что, «событие в nonsignaled state» и нет потока, который бы владел событием? Зачем тогда использовать это событие? Кто использует SetEvent, а кто WaitForSingleObject?
Мне сегодня удалось зайти, хотя еще вчера это было сделать невозможно.
Интересно то, что всегда в подобных статьях упоминается закон Мура. Невольно задаешься вопросом: это производители специально такой темп сохраняют, или само получается?
Важно обратить внимание, что получившаяся система не вполне беззамочна: используя беззамочные алгоритмы, мы фактически реализовали эффективный замок. Если «застрянет» поток, заблокировавший кэш для записи, — все прочие потоки, хотя и продолжат выполняться, кэшем пользоваться уже не смогут.

Как раз именно потому, что другие потоки будут выполняться, данный алгоритм не только lock-free, но и wait-free. И не важно, что кэшем никто не может воспользоваться, это с характеристикой алгоритма никак не связано.

Информация

В рейтинге
Не участвует
Дата рождения
Зарегистрирован
Активность