1. C++ / Говнокод #13909

    −4

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    static Singleton * g_pInstance = NULL;
    
    Singleton* Singleton::sharedInstance()
    {
        if (g_pInstance)
            return g_pInstance;
        else {
            g_pInstance = new Singleton();
            if (g_pInstance->init()) {
                return g_pInstance;
            } else {
                delete g_pInstance;
                g_pInstance = NULL;
            }
            return g_pInstance;
        }
    }

    Ещё из жизни синглтонов. Даёшь больше return'ов!

    Запостил: Deacon, 08 Октября 2013

    Комментарии (162) RSS

    • Надо полагать, местным индусам религия не позволяет делать одну точку выхода и писать:
      if (!g_pInstance) {
          g_pInstance = new Singleton();
          if (!g_pInstance->init()) {
              delete g_pInstance;
              g_pInstance = NULL;
          }
      }
      return g_pInstance;
      Ответить
      • Да один хуй: как было говно потоко- и экцепшено-небезопасное, так и осталось.
        Ответить
        • Все хоть раз "оптимизировали" так многопоточный код.
          И 90% попыток написать double checked locking - говно.
          Да и это касается синглтонов в целом.
          Ответить
          • А синглтон в крестах разве можно вообще написать так, чтобы он был одновременно ленивым, быстрым, кроссплатформенным (не только с++11, и не в виде кучи ifdef'ов для разных платформ) и потокобезопасным? :)
            Ответить
            • Не знаю, я вот как раз хотел поинтересоваться у более осведомленных в крестах кодеров - как оно там, всякое happens-before стандартизировано, или по-прежнему UB?
              В с++11 вроде как что-то делали для многопоточности.
              Ответить
              • До с++11 потоков в крестах вообще не существовало (как и секса в СССР).
                Ответить
                • Хах. Лычева читали - "Интромиссия"?
                  Вывод: все кодили на Delphi.
                  Ответить
              • Сорри, интернет выключили, не успел дописать сообщение.

                В общем, если верить статьям, то и модель памяти с хеппенс бефор есть, и набор атомиков, и набор более высокоуровневых классов, и tls, и статикам внутри функций поведение стандартизировали... Но я могу заблуждаться, т.к. пока кресто11потоки не юзал, и стандарт не раскуривал...
                Ответить
                • Звучит неплохо. А то раньше volatilом единым.
                  Ответить
                  • > volatilом единым
                    Ересь виндузячья! По стандарту volatile не имеет отношения к тредам (т.к. тредов нет). И поэтому может сделать только хуже. А то, что MS прикрутил к volatile aquire-release семантику - это их персональное извращение.

                    P.S. volatile вроде как предназначался только для отображенных в память портов ввода-вывода.
                    Ответить
                    • Цитата с msdn: It is important to understand that these new guarantees only apply to Visual C++ 2005 and future versions of Visual C++. Compilers from other vendors will generally implement different semantics, without the extra guarantees of Visual C++ 2005. Also, on Xbox 360, the compiler does not insert any instructions to prevent the CPU from reordering reads and writes.

                      http://msdn.microsoft.com/en-us/library/ee418650%28v=VS.85%29.aspx

                      Короче это даже в вижуалке работает далеко не везде и не всегда.
                      Ответить
                      • "P.S. volatile вроде как предназначался только для отображенных в память портов ввода-вывода."
                        "[...] the compiler does not insert any instructions to prevent the CPU from reordering reads and writes."

                        что к слову не есть конфликт, т.к. CPU знает про io-mmap и обращения туда сам не оптимизирует.
                        Ответить
                        • > volatile вроде как предназначался только
                          DMA, Memory Mapped IO, Interrupts, борьба с оптимизацией в "синтетических" тестах.
                          Ответить
                          • > DMA, Memory Mapped IO, Interrupts
                            Ну и юниксовые сигналы еще тогда. Но в любом случае не для тредов.
                            Ответить
                            • > Interrupts
                              > в любом случае не для тредов.
                              А как по-вашему оно (thread switch context) сделан внутри ОС?
                              Или линуксовый планировщик не использует прерывания?
                              Ответить
                              • Вроде речь шла о том, какие гарантии дает volatile, и для чего его можно юзать? Причем тут context switch, который всяко написан на асме или вообще железный (интел вроде умел сохранять/загружать TSSки при прыжке через шлюз)?

                                Для межъядерного общения volatile неюзабелен чуть более чем полностью... Те же атомарные интринсики подавляют оптимизации намного аккуратней (всего лишь убирая перескоки через барьер), и вставляют необходимые на данной архитектуре барьеры и/или команды. volatile же глушит оптимизацию на переменной полностью, и ничего не понимает в барьерах (перверсии майкрософта в расчет не принимаем)... Я вот даже сомневаюсь, можно ли его юзать volatile переменные для общения с обработчиками прерываний на двух и более ядрах...
                                Ответить
                                • >Вроде речь шла о том, какие гарантии дает volatile

                                  >Для межъядерного общения volatile неюзабелен чуть более чем полностью...
                                  Нет. Отчасти.

                                  >Те же атомарные интринсики подавляют оптимизации намного аккуратней (всего лишь убирая перескоки через барьер)

                                  Они не всегда гарантируют что компилкр не закешит переменную в регистре или не оптимизнет каким-либо образом.

                                  Другое дело что сишкоблядский стандарт позволяет вообще ложить на volatile: "What constitutes an access to an object that has volatile-qualified type is implementation-defined".
                                  И я где-то читал что популярные компилеры собственно и ложат на это и потому баги при реализации volatile - тот же GCC на О2 не всегда работает как надо.
                                  Ответить
                                  • > Они не всегда гарантируют что компилкр не закешит переменную в регистре или не оптимизнет каким-либо образом.
                                    Ну собственно в этом и их плюс по сравнению с volatile. Они подавляют только те оптимизации, которые будут мешать правильному переходу через границу. Остальные то зачем трогать? Это ж не MMIO, где важен каждый load/store, и, емнип, даже зоны памяти размечают как некешируемые...

                                    > И я где-то читал что популярные компилеры собственно и ложат на это и потому баги при реализации volatile
                                    http://www.cs.utah.edu/~regehr/papers/emsoft08-preprint.pdf
                                    this?
                                    Ответить
                                    • > Они подавляют только те оптимизации, которые будут мешать правильному переходу через границу. >Остальные то зачем трогать?
                                      Объясняю. Зачем нужны volatile при трейдинге. volatile, как известно, означает отключение оптимизаций, и готовность к тому что переменная ВНЕЗАПНО изменится, неожиданным образом.

                                      Вот есть умный крестобляский компилер.
                                      Он видит ситуацию:
                                      bool stop=false;
                                      while(!stop){
                                         ...//stop не меняется
                                      }

                                      Он подумает stop в коде не меняется - можно такое оптимизнуть оставив безусловный переход, не проверяя stop.
                                      Откуда компилер узнает что переменная меняется из другого треда, пусть даже атомарно?

                                      >this?
                                      yeah
                                      Ответить
                                      • > Он видит ситуацию
                                        Блин, вот интересный пример на самом деле. В отличие от других примеров, здесь data race не страшный: флаг переключается только в одну сторону, тред после выхода из цикла просто завершает работу...

                                        С одной стороны, насколько я понимаю, volatile не имеет никакого воздействия на кеши. И одно ядро какой-нибудь SMP системы, не умеющей в когерентность кешей будет вечно дрочить stop в цикле и никогда не узнает о том, что другое ядро туда положило true...

                                        С другой же стороны в многозадачной оси потоки постоянно переключаются, и рано или поздно кеши все равно сбросятся, и оно этот флаг увидит...

                                        И еще меня смущает тот факт, что почти на всех архитектурах atomic_read/atomic_set в линуксе запилены как каст в volatile int *, но на power pc они по какой-то причине реализованы через ассемблерную вставку.
                                        Ответить
                                        • >вот интересный пример на самом деле
                                          Причем жизненный. Я не далее чем джва часа назад писал в проекте такое :)

                                          >в линуксе запилены как каст в volatile int
                                          Ну так не зря это. Я ж и говорю что volatile нужен для многозадачности - он отключает такие оптимизации компилера, чтоб не он выпилил лишнего.
                                          Потому что если будет где-то меняться атомиком, этого недостаточно - запросто оптимизнется в бесконечный цикл.
                                          Ответить
                                          • > Потому что если будет где-то меняться атомиком, этого недостаточно
                                            Менять атомиком недостаточно. Надо еще и читать атомиком ;) И этого будет вполне достаточно. Ибо каст в volatile будет заныкан в макросе, либо там будет volatile асмовая вставка, либо это вообще будет встроенная "функция", о которой компилятор и так знает все. Так зачем тащить в свой код эту деталь реализации атомика?

                                            На переменных, которые читаются\пишутся\CAS'ятся только атомарными операциями volatile писать не нужно (и даже вредно). Или есть опровержение? :)

                                            P.S. Небольшой вбросец: https://www.kernel.org/doc/Documentation/volatile-considered-harmful.txt
                                            Ответить
                                            • > Ибо каст в volatile будет заныкан в макросе
                                              Ну всё-равно то оптимизация где-то должна быть отключена. То есть категорически утверждать, что volatile совсем не нужен для многопоточных сред я бы не стал.
                                              Линк - хороший.
                                              Ответить
                                        • >Блин, вот интересный пример на самом деле.

                                          Ничего интересного. Это вечный цикл.
                                          А вот если бы переменная была:
                                          1) ссылка полученная неизвестно откуда
                                          2) глобальная переменная
                                          3) от этой переменной взяли ссылку или указатель и отправили в а)глобальную область видимости б)или передавали в неанализируемую функцию (функцию в скомпилированном объектнике или DLL) с)или отправили в данные, полученные по указателю\по ссылке (тут тоже возможен анализ и в некоторых случаях компилятор оставит бесконечный цикл при выполнении 3)с) ).

                                          То при выполнении любого условия из списка выше компилятор пишет цикл с постоянной проверкой этой переменной. По крайней мере так делают обычно в нормальном компиляторе. Стандарт до 11 этого правда не оговаривает, а в новый я не смотрел по этому поводу. Там могло появится.
                                          Ответить
                                          • > 2) глобальная переменная
                                            Ну я предполагал, что она глобальна ;)

                                            > Ничего интересного.
                                            Пример интересен тем, что до него трудно доебаться. Если бы флаг назывался не stop, а как-то еще, можно было бы упомянуть про переупорядочивание, и обозвать код говном...
                                            Ответить
                                        • >И одно ядро какой-нибудь SMP системы, не умеющей в когерентность кешей
                                          А такие бывают? Не слышал.
                                          Ответить
                                  • >Для межъядерного общения volatile неюзабелен чуть более чем полностью...
                                    >Нет. Отчасти.
                                    Ну в джаве то конечно...
                                    А вот если нужно, чтобы в крестах, то там перед\после обращения к переменной барьер лучше вставь. Ну или если нужно повторно зачитать переменную с гарантией обращения к памяти, то опять же между ними барьерчик.
                                    Ответить
                                    • >Ну в джаве то конечно...
                                      Там тоже не всё гладко. Вот в 8-ю предлагают запилить:
                                      http://openjdk.java.net/jeps/171
                                      Ответить
                                      • Жабин volatile немного не такой, как в ц.

                                        >jeps
                                        Пародия на pep?
                                        Ответить
                                        • > Пародия на pep?
                                          Да этих *EP горы... Хрен бы знал кто начал первым. Скорее всего и правда питонисты.
                                          Ответить
                                        • >Жабин volatile немного не такой, как в ц.
                                          Ведь улыбка - это флаг корабля.

                                          Само собой. Хотя бы тем что в сишке implementation-defined, а в жабе везде одинаковый. Это выше по треду указано кстати.
                                          Ответить
                                • показать все, что скрытоvanished
                                  Ответить
                  • В 11 стандарте появилась модель памяти с happens-before и synchronizes-with. Есть набор атомиков, барьеры, мутексы, локи, треды, промисы и фьючерсы. Струкрур данных и тредпулов нет :(
                    Ответить
                    • > Струкрур данных

                      буст доделает. главное что есть атомики, которые в некоторых случаях позволяют без структур обходится.

                      > и тредпулов нет :(

                      с std::function'ом я могу и сам налепить без проблем.

                      как по мне, std::function есть одно из самых важных дополнений в 11ом.
                      Ответить
                      • > с std::function'ом я могу и сам налепить без проблем.
                        Ты имел в виду с std::packaged_task. Простой тредпул запилить в 11 плюсах действительно несложно. А вот work-stealing уже не хочется самому писать.

                        > буст доделает
                        > std::function есть одно из самых важных дополнений
                        Ну тогда boost::function тоже давно есть

                        > есть атомики, которые в некоторых случаях позволяют без структур обходится
                        Атомики могут помочь избежать мутексов, но уж никак не структур данных. Заменить блокирующую очередь атомарным интом не получится. Конечно, оаписать простую медленную очередь - плёвое дело для тех, кто это уже делал. А вот новички могут все грабли собрать. Грамотно выбрать интерфейс многопоточной очереди, например, не каждый с первого раза сможет.
                        Ответить
                        • >work-stealing
                          А разве от него серъезный профит?

                          >оаписать простую медленную очередь - плёвое дело
                          Смотря как писать. Если через мьютексы - то несложно, там только надо подумать хорошо над waitForSingleObject и notify.

                          А вот если на спин-локах, там на порядок сложнее.
                          В любом случае алгоритмы известны.
                          Ответить
                          • > А разве от него серъезный профит?

                            Зависит от специфики задач. Я думаю, многим хватит и простого пула с одной очередью. Но если для уменьшения оверхеда сделать по очереди на поток, то вполне может сложиться, что треду-неудачнику достанется несколько тяжёлых задач, а остальные треды будут сделают простые таски и будут бездействовать.
                            Ответить
                            • >Зависит от специфики задач.
                              Причем сильно. Если задания больше тратят на I/O, то work-stealing не сильно поможет.
                              Это скорее отпимизация, над которой надо думать когда уже найдено узкое место.
                              Ответить
                              • Интенсивное IO всё равно по ресурсам выгоднее делать через асинхронный код. А вообще да, сначала используем простой подход, уж если не подходит, тогда только измерять и усложнять.
                                Ответить
                                • На хабре статью по Хацкелю только ты один прокомментил. Народ не осиливает.
                                  Ответить
                                  • > Народ не осиливает
                                    Мне кажется, что люди просто кидают такие статьи в "избранное", где они пыляться как непрочитанные вкладки.

                                    Бложик, статью из которого "перевели" на хабре (в 33 линии на хаскеле? wut?), кстати, очень даже годен, всем советую.
                                    Ответить
                                  • http://habrahabr.ru/post/195274/ ?
                                    Ответить
                                    • Я её прочитал, реализацию почти не пони.
                                      Ответить
                                    • Вот до чего людей доводит отсутствие async
                                      Ответить
                                      • > отсутствие async
                                        forkIO, Control.Concurrent.Async
                                        Ответить
                                        • Оно как-то заменяет оператор async? От скобок там не захлебнешься?
                                          Ответить
                                        • А зачем этот странный чувак это тогда реализовал, если оно уже и так есть?
                                          Ответить
                                        • Ты похоже не в теме про зеленные потоки. форкио делает новый поток, а не переиспользует, как в сшарп или в немерле старый поток
                                          Ответить
                                          • > Ты похоже не в теме
                                            > форкио делает новый поток
                                            Это ты не в теме как работает forkIO
                                            Ответить
                                            • Может быть ты и прав, в хаскеле можно использовать thread-local storage и насколько forkio зеленые потоки совместимы с TLS?
                                              Ответить
                                              • > насколько forkio зеленые потоки совместимы с TLS
                                                forkIO треды плавают между тредами операционки, поэтому ни о каком тред локал состоянии не может быть и речи... Если нужно привязать гринтред к одному потоку операционки - юзай forkOS.
                                                Ответить
                                                • по моему без unsafePerformIO до TLS и не достучаться, так что не особо важно, имхо
                                                  Ответить
                                        • Но вот на счет Control.Concurrent.Async корректное замечание. Единственная проблема этой штуки: не умеет в форк и в илду, но в асинхронность умеет. А раз не умеет - это повод написать свой велосипед
                                          Ответить
                                    • > Хаскель отличает себя от большинства функциональных языков тем, что имеет глубокие культурные корни из области математики
                                      > done команда не имеет детей, так что компилятор выводит, что она имеет полиморфное возвращаемое значение (т.е. r), это означает, что оно никогда не завершится

                                      Хороший водитель, но иногда педали путает.
                                      Ответить
                                      • Ну с русским языком тоже не в ладах. Но в Интернете это похоже становится нормой...
                                        Ответить
                                  • а кто знает, std::shared_ptr надо ли заворачивать в std::atomic, если из разных потоков юзаю? А бустовский шаредптр?
                                    Ответить
                                    • дык шаред птр на то он и нужен, чтобы юзать его из разных потоков
                                      а сам объект в куче ты уж синхронизируй как тебе надо
                                      Ответить
                                      • Тут осторожней надо. Он, походу, собирается юзать один инстанс shared_ptr из нескольких потоков. А это небезопасно, если не синхронизнуться.
                                        Ответить
                                        • ну да. хочу один шаред править из разных потоков, притом не хочу руками вызывать std::exchange, а хочу чтобы просто присвоение работало как в std::atomic
                                          Ответить
                                          • Ну заворачивание shared_ptr в атомик не поможет, имхо. Он же не примитив, конструкторы-десктрукторы нетривиальные. Скорее всего даже не скомпилится.

                                            А чем не нравится мутекс + шаред птр? Производительность реально проседает на этом месте?
                                            Ответить
                                            • примитив тут не причем

                                              http://ideone.com/OzLFib
                                              Ответить
                                              • Кстати, для std::shared_ptr<> есть специализация std::atomic_exchange() и std::atomic_store(). Я бы на них остановился.
                                                Ответить
                                                • я ж говорю не хочу стд эксчендж юзать. кто-нибудь увидит ссылку на шаред в поток к нему прислали и возмет, да заюзает где-нибудь в глубине не верно. копия шареда мне не подойдет, тк нужно изменять указатель. может если только шаред на шаред юзать. хотя не сработает... в общем хочу явно выразить интерфейсом, что нужно обновлять по особому или чтобы оно делало это не явно
                                                  Ответить
                                                  • Инкапсулируй :)
                                                    Ответить
                                                    • толсто. крестовики всю жизнь чтоли должны велосипеды писать? чем стдатомик от шаредптр не угодил?
                                                      Ответить
                                                      • > чем стдатомик от шаредптр не угодил?
                                                        In addition, std::atomic may be instantiated with any TriviallyCopyable type T. А std::shared_ptr<> не особо похож на тривиально копируемый...
                                                        Ответить
                                                        • ну так ты видел что все скомпилировалось. чего спрашиваешь то? это вообще бред про тривиальность копирования. олсо у атомика есть ещё и специализации. наверняка есть и для шаредпоинтера не смотря на эту глупость про не оправданное тривиальное копирование
                                                          Ответить
                                                  • Как-то так например:
                                                    template <typename T>
                                                    class shared_box {
                                                    public:
                                                        std::shared_ptr<T> get();
                                                        void set(const std::shared_ptr<T> &ptr);
                                                    };
                                                    И враг не пройдёт.
                                                    Ответить
                                        • няня я у них поел
                                          шаред птр как бы на то и _шаред_ птр
                                          это указатель на объект, который собирается _использовать_ несколько тредов, не думая о том, сколько владельцев в данный момент

                                          если живой шаред птр один из тредов собирается менять, то что-то странное, что-то пошло не так в датском королевстве
                                          вангую, что в данном случае подойдет вариант с одним реальным властелином + n-1 weak_ptr?

                                          ну... или shared lock + upgrade lock вокруг чтения и модификации этого шаред птра
                                          Ответить
                                          • кстати, а если стд атомик_ексчендж заюзаю к шаредпоинтеру, то могу в других потоках не атомически читать этот поинтер обычным образом?
                                            Ответить
                                            • зачем тебе атомик эксченж, если в шаред птр и так он есть внутри
                                              http://ru.cppreference.com/w/cpp/memory/shared_ptr/swap
                                              Ответить
                                              • ты хоть ссылку то видел на что мне даешь. не давай мне больше на русское с такими шрифтами. я чуть не ослеп. еще небось промптовский перевод.

                                                с чего ты взял что свап атомический при использовании одного смарта в разных потоках? никогда не слышал. вот атомик эксчендж или атомик стор как следует из названия явно атомический
                                                Ответить
                                                • с чего взял?
                                                  из памяти, когда в прошлой жизни читал сорцы буст шаред птр
                                                  Ответить
                                                  • в прошлой жизни? кот штоле? а я в прошлой жизни служил у Его Величества Англии. очень было интересно.

                                                    пс буст это не стд и полагаться на это нельзя
                                                    Ответить
                                                    • в прошлой жизни, это когда я от избытка свободного времени писал заумь в 10 этажные рекурсивные шаблоны на boost mpl ради высокой эстетики грошового никому не нужного выигрыша

                                                      теперь же отвечаю за всякую поебень вселенского масштаба на глиняных ногах, и студию не запускал очень давно
                                                      Ответить
                                            • > могу в других потоках не атомически читать этот поинтер обычным образом
                                              Нет, т.к. без atomic_load'а у тебя не будет happens before. Хотя на интеле и проканает (но на нём и atomic_load бесплатный, и ничего не делает, емнип, так что ты ничего не теряешь заюзав его).
                                              Ответить
                                          • Я как-то так его задачу представил: есть некая глобальная конфигурашка; поток, перед началом задания, берет себе ее копию; другой поток может поправить конфиг и сделать его глобальным (т.е. все новые задания должны юзать его, а старые - дорабатывать со старым).

                                            Т.е. shared_ptr + std::atomic_load на чтении + std::atomic_store на модификации. Ну или shared_ptr + r/w lock или мутекс, да.
                                            Ответить
                                            • не, мьютекс для лохов, когда есть атомик. атомик будет и дешевле и возни меньше

                                              пс ты все верно понял. разве что дорабатывать со старыми задания не обязательно, а можно и новые заюзать параметры
                                              Ответить
                                              • > атомик будет и дешевле
                                                Там настолько мелкие задания, что это влияет?
                                                Ответить
                                                • не, но мьютекс надо где-то хранить, а мне лень.

                                                  был бы pair мьютекса и объекта, который можно разьименовывать и мьютекс будет сам блокироваться
                                                  Ответить
                                                  • > был бы pair мьютекса и объекта, который можно разьименовывать и мьютекс будет сам блокироваться
                                                    lispgovno::locked_ptr<>
                                                    Ответить
                                                    • ну может пусть он сам и не блокируется. пофиг. главное чтобы от объекта не терялся

                                                      и лучше уж тогда
                                                      locked_ptr<t>( const unlocked_ptr<t>&)

                                                      если на то пошло (2 типа)
                                                      Ответить
                                                      • Если один locked_ptr<> жив остальные ждут? Норм идея, вроде. Только const там лишний, имхо. Всё же оно его лочит, т.е. меняет.
                                                        Ответить
                                                  • Тебе за таким в Rust.
                                                    Ответить
                                            • рв лок хоть в 14 завезли, а то в 11 ведь нет. да и не удобный он. тут уж я вспомню твою фразу:

                                              >> рвлоки будут и дешевле
                                              > Там настолько мелкие задания, что это влияет?
                                              Ответить
                                              • > рв лок хоть в 14 завезли
                                                Я в Qt его юзал, там он давным-давно. Ну и boost::shared_mutex, который советовал d++.

                                                > да и не удобный он
                                                Апгрейда с R на W нету поди?
                                                Ответить
                                                • ну там вроде создаешь шаредлок из уникую лока, если память не изменяет. это вообщем апгрейд. хотя в таком виде они не приняли его из-за тормозов в с++11, так что в 14 возможно апгрейда и правда нет
                                                  Ответить
                                                  • > шаредлок из уникую лока
                                                    Наоборот же. Поработал на уровне апгрейд лока, понял, что пора что-то менять, апгрейднул до эксклюзивного, записал, снял локи. Вот в Qt upgrade_lock'а не было. А без него хуёво.
                                                    Ответить
                                            • > Я как-то так его задачу представил: есть некая глобальная конфигурашка; поток, перед началом задания, берет себе ее копию; другой поток может поправить конфиг и сделать его глобальным (т.е. все новые задания должны юзать его, а старые - дорабатывать со старым).

                                              и нахуй тут локи?
                                              нужен объект конфиг-холдер
                                              в котором и хранится этот исходный эталонный шаред птр
                                              захотел сменить конфиг - говори этому конфиг холдеру "на тебе новый шаред птр, в нем новый конфиг"
                                              тот берет и делает .swap
                                              .swap потокобезопасный, атомарный и няшный вообще nothrow
                                              все старые потоки доработают со старым конфигом, просто в их шаред птре будет уже счетчик на 1 меньше, и он с последним заданием просто подохнет
                                              все новые задания должны взять себе копию шаред птра из холдера
                                              и пусть с ней работают сколько влезет, пока тоже не сдохнут
                                              Ответить
                                              • Ответ куда-то проебался. А свап даст гарантию, что чтение в соседнем потоке будет корректным на каком-нибудь ARMе?
                                                Ответить
                                                • ты так говоришь, будто кто-то передает и хранит shared_ptr &
                                                  у всех своя собственная копия shared_ptr
                                                  внутри которого есть shared_count
                                                  вот он как раз потокобезопасный, увеличивается на копировании, уменьшается на деструкторе

                                                  раз у тебя есть валидный объект shared_ptr, то он твой валидный объект, и каунт в нем больше нуля, значит и объект по этому шаред птр тоже в порядке (если ты не выстрелил сам себе в ногу и не затер эту область памяти смищными картинками с гоатсе)
                                                  Ответить
                                                  • Я про тот, который внутри холдера.

                                                    Один поток делал свап, а второй попросил прочитать. Есть ли гарантия, что он всегда получит непобитый шаредптр (либо старый, либо новый). И будет ли гарантирована видимость - увидит ли читающий тред в конфиге то, что туда засунул пишущий?

                                                    Почему я и предлагал атомиклоад и атомист ор вместо свапа и чтения (у них есть перегрузки для шаредптр).
                                                    Ответить
                                                    • > Есть ли гарантия, что он всегда получит непобитый шаредптр
                                                      что значит попросить прочитать
                                                      он может только попросить сделать себе копию, которую будет потом использовать сколько захочет
                                                      делание копии потокобезопасно, и развязано со swap, т.к. это всё атомарные операции над shared_count
                                                      Ответить
                                                      • Ну вот когда холдер делает эту копию, идет чтение шаредптра, в который соседний поток может делать свап.

                                                        А у арма подляна есть - weak order. Т.е. Читающий тред может увидеть новый указатель, но старые данные (мусор) по нему, т.к. чтение шло без барьера. Ну и кровь-кишки.

                                                        Жалко, что сотик одноядерный, потестить неначем.
                                                        Ответить
                                                        • проще открыть маркса и почитать
                                                          тут всё написано, что говорили борманд и лиспговно
                                                          http://www.boost.org/doc/libs/1_57_0/libs/smart_ptr/shared_ptr.htm#ThreadSafety
                                                          eco-terrorists win
                                                          Ответить
                                                          • Лол. То о чем я и говорил ниже
                                                            //--- Example 3 ---
                                                            // thread A
                                                            p = p3; // reads p3, writes p
                                                            
                                                            // thread B
                                                            p3.reset(); // writes p3; undefined, simultaneous read/write
                                                            Ответить
                                                      • хрень же. делать копию из объекта хоть со свапом, хоть с стд атомик эксченджем не безопасно. он мог уже отбросить кони
                                                        Ответить
                                                        • еще раз:
                                                          auto conf = std::make_shared<int>(1);
                                                          
                                                          void thread1(){
                                                            async thread2();//asinhronno startanuli noviy potok v paralleli na drugom yadre
                                                            conf.swap(std::make_shared<int>(2);
                                                          }
                                                          
                                                          void thread2(){
                                                            auto p = conf;
                                                            //tut mi scopirovaly ukazatel na vozmogno uge dohliy int(1), tak kak v sosednep potoke on umer ili int(2), tak kak v sosednem potoke on obnovlen.
                                                            cout<<*p;//fail
                                                          }
                                                          По сути указатель скопировали во втором потоке, затем в первом мы убили старый и заменили на новый и вот у нас дохлый в скопированным в треде2
                                                          Ответить
                                                          • ты делаешь неправильные выводы
                                                            я уже выше предоставил ссылку, что одновременная запись и чтение одного шаред птр может приводить к говну при удачном стечении обстоятельств - можно создать новый шаред птр со старым указателем и новым каунтером, и потом в будущем наткнуться на освобожденную память, либо дважды освободить её (т.к. сама по себе операция swap и операция = в бусте сделана оптимистично)

                                                            но в твоем примере, если представить, что операции swap и операции = атомарны, ты либо будешь читать хороший, годный int(1), либо хороший, годный int(2) - т.к. захватишь себе либо старую копию, либо уже новую
                                                            потенциально дохлый int(1) с каунтером от int(2) ты получишь только при действительно (не)удачных обстоятельствах
                                                            Ответить
                                                            • > представить, что операции swap и операции = атомарны
                                                              Ты мне предлагаешь ПРЕДСТАВИТЬ что операции атомарны и после этого с чувством уверенности писать падающую прогу? У меня уже бомбит
                                                              Ответить
                                                            • > если представить, что операции swap и операции = атомарны
                                                              Горький опыт подсказывает, что с потоками лучше не представлять... Вот такой код же имелся в виду?
                                                              class config_holder {
                                                              public:
                                                                  boost::shared_ptr<config> get() {
                                                                      return conf;
                                                                  }
                                                                  void set(boost::shared_ptr<config> new_conf) {
                                                                      conf.swap(new_conf);
                                                                  }
                                                              private:
                                                                  boost::shared_ptr<config> conf;
                                                              }
                                                              A shared_ptr instance can be "read" (accessed using only const operations) simultaneously by multiple threads. Different shared_ptr instances can be "written to" (accessed using mutable operations such as operator= or reset) simultaneously by multiple threads (even when these instances are copies, and share the same reference count underneath.)

                                                              Any other simultaneous accesses result in undefined behavior.


                                                              У нас как раз any other (один тред пишет в swap'е, второй читает в конструкторе копирования). На интеле будет работать из-за его strong ordering'а. А вот на ARM'ах, с их достаточно вольным обращением с кешами, я что-то очкую, от реализации конструктора копирования в boost::shared_ptr очень сильно зависит: если там сразу идет инкремент и барьер, то, скорее всего, работать будет, если какое-то неатомарное чтение из управляющего блока - кровь-кишки.
                                                              Ответить
                                    • Ответить
                                      • что сказать то хотел? а то я может тебя спугнул?
                                        Ответить
                        • > > std::function есть одно из самых важных дополнений
                          > Ну тогда boost::function тоже давно есть

                          сорри. имел в виду std::bind, результат которого кастится в std::function<void(void)>:

                          http://stackoverflow.com/questions/13108663/storing-functions-call-and-list-of-parameters-to-invoke-later

                          > Заменить блокирующую очередь атомарным интом не получится.

                          не ну про блокировку ни кто и не говорит. блокировка требует дергания ОСи/скедулера, и относительно медленна как ни крути.

                          самая простая структура на атомиках это stack/LIFO. circular buffer (фиксированого размера) тоже как бы не сильно сложна. знаю народ еще как-то singly-linked list делает, но я еще не догадался как (т.к. я не могу себе представить как они случай пустой очереди обрабатывают.)

                          > А вот новички могут все грабли собрать.

                          Новички везде с легкостью могут грабли найти. По себя еще помню...
                          Ответить
                          • 11 стандарт не гарантирует, что атомики будут реализованы не через мутексы :)
                            Это гарантируется только для std::atomic_flag.

                            По поводу lock-free: даже то, что рализовано, к примеру, в расширениях гнутых библиотек, часто подходит только для специфичных случаев (типа один писатель, один читатель), надо очень внимательно читать доки. Корректно написатать самому такие вещи крайне сложно.
                            Ответить
                            • "По поводу lock-free: даже то, что рализовано, к примеру, в расширениях гнутых библиотек, часто подходит только для специфичных случаев (типа один писатель, один читатель), надо очень внимательно читать доки."

                              Если ты доходишь до уровня таких оптимизаций, то принцип разработки меняется с "мне нужна такая-то структура для увдолетворения требований" на "у меня есть в распоряжении такие-то структуры, вопрос как на них оптимально замапить требования." Другими словами, ты "специфичные случаи" создаются преднамерено в дезайне, а не случайно.

                              "Корректно написатать самому такие вещи крайне сложно."

                              True. Граблей очень много.

                              Хотя сейчас стало легче, потому что на какой 16 процессорно-корной системе можно достаточно хорошо протестировать. Раньше, даже на двух процах, такое тестировать было почти невозможно.
                              Ответить
                              • >(типа один писатель, один читатель)
                                Профита от lock-free тогда нету. Грубо говоря вешаем мьютекс на чтение, мьютекс на запись. Теперь и чтение и запись синхронизированы по одному потоку.

                                А вот lock-free алгоритмы для очередей тот же классический Michael & Scott они могут обслуживать несколько потоков потребителей и производителей и они умудряются меньше мешать друг другу.
                                Суть в том что увидев ноду в промежуточном состоянии, другой поток помогает выпилить/связать её. А у первого потока CAS просто выдает false.
                                Работы делается чуть больше, да. Но она не идёт последовательно как в мьютексе. Плюс нет захвата/освобождения лочки.
                                Ответить
                                • "тот же классический Michael & Scott "

                                  не видел. линк в студию.

                                  "Профита от lock-free тогда нету."

                                  есть. мутексы не бесплатны. по моей метрике, лок/анлок аналогичен "memset(buf,0,128)". в то время как атомики по производительности почти не отличаются от обычных переменных.
                                  Ответить
                                  • >мутексы не бесплатны.
                                    Да, согласен.

                                    > в то время как атомики по производительности почти не отличаются от обычных

                                    Нет. Даже volatile считается дорого, если уж быть щепетильным.
                                    mutex>atomic>volatile>usual
                                    Ответить
                                  • >не видел. линк в студию.
                                    http://g.zeos.in/?q=michael%20scott%20lockfree%20queue
                                    Ответить
                                    • Спа. Бум втыкать.
                                      Ответить
                                      • http://www.cs.rochester.edu/research/synchronization/pseudocode/queues.html
                                        Вот в сжатом виде (чистый код, никаких abstract, описаний, доказательств и бенчей) джва самых известных алгоритма для очередей.
                                        Даже по объему кода видно насколько lock-free сложнее.
                                        Там же видно превосходство мьютексного кода "The two-lock concurrent queue algorithm performs well on under high contention".
                                        Ответить
                                        • а вот тут еще больше вкуснятины - http://www.cs.rochester.edu/research/synchronization/pseudocode/

                                          "Даже по объему кода видно насколько lock-free сложнее."

                                          оно не сложнее. просто синхронизационные примитивы в открытую кодируются, потому что стандартные не подходят.

                                          > "The two-lock concurrent queue algorithm performs well on under high contention".

                                          Ты опустил: "Useful for multiprocessors without a universal atomic primitive."

                                          не забывай, этот псевдо код еще с тех времен когда cache coherency была еще эксперементальным хай-эндом и многие из атомарных операций в лоб сбрасывали кэш проца. а локам нужно было сбрасывать кэш как мининмум два раза. вообщем это были страшные времена.
                                          Ответить
                                          • >и многие из атомарных операций в лоб сбрасывали кэш проца
                                            А сейчас нет?
                                            Ответить
                                            • Сейчас используется шина с протоколом например mesi для поддержания когерентности кэшей и по ней кэш переливают в кэш если нужно.
                                              Ответить
                                          • >оно не сложнее.
                                            Они сложнее, потому что к ним предъявляются особые требования.

                                            Тривиальный CAS-алгоритм может очутится в такой ситуации что треды мешают друг другу и никто не может выполнить до конца свою операцию, потому что второй (или последний) CAS обламывается, происходит клинч, он же лайвлок. В отличии от дедлока движение не замирает, оно происходит, но это хаотическое движение ни к чему ни приводит.

                                            Примерно такую же патовую ситуацию можно наблюдать в московском метро или банке набитой огурцами - все мешают друг, другу.

                                            В первом случае происходит конкуренция, а нужен качественно другой подход - кооперация, треды помогают друг дружке завершить начатую операцию. Это сильно усложняет дело.
                                            В отличие от мьютексного "кто первый встал тому и тапки", сортир занят - все ждут своей очереди.

                                            И так гарантированно, подчеркиваю _гарантированно_ осуществляется движение вперед.

                                            Вышеупомянутый work-stealing кстати это именно дальнейшее развитие идей кооперации.
                                            С эстетической точки зрения такие алгоритмы невероятно круты и являются произведениями искусства.
                                            Но при реализации на практике, они выглядят крайне непонятно и даже чтоб прочитать и вникнуть требуется немало умственных затрат. В отличие от более тривиального - попробовал захватить лок, не получилось, впал в спячку, пришло уведомление, захватил, поработал, освободил лок.
                                            Ответить
                                            • "Тривиальный CAS-алгоритм может очутится в такой ситуации что треды мешают друг другу и никто не может выполнить до конца свою операцию, потому что второй (или последний) CAS обламывается, происходит клинч, он же лайвлок."

                                              Live-lock может происходить на доморощеных реализациях CAS. И факт что в одном потоке CAS обломался означает что один из потоков на самом деле сделал прогресс и что-то записал.

                                              Последний раз когда я занимался этим в плотную, Intel/x86 и PPC32 платформы гарантировали отсутствие live-lock'ов, за счет тривиального тайминга прерываний и доступа к памяти. В случае PPC32, где CAS реализуется несколькими инструкциями и есть реальный шанс live-Lock'а, с официальной реализацией CAS гарантируется что live-lock не случается.

                                              Простой пример. Возвращаясь к ситуации когда один из потоков что-то сумел записать и в других потоках CAS обламался. Это будет значить что в других потоках/на других процах кэш данных для данной ячейки памяти был сброшен и процы должны перечитать ячейку из памяти. Только один проц может читать из ячейки память, что значит что процы выстроятся в очередь пытаясь читать память и вернутся в CAS цикл в разное время.

                                              И самое главное. Если у тебя часто обламывается CAS, то у тебя что-то неправильно реализовано на логическом уровне. Синхронизация, какой бы легковесной она не была, остается "тяжелой" и меньше программа ей пользуется, лучше.

                                              "Вышеупомянутый work-stealing кстати это именно дальнейшее развитие идей кооперации."

                                              Я читал как-то HP'шные документы по HPC оптимизациям (HPC: high performance computing) и честно говоря у меня сложилось впечатление что из-за cache coherency народ такого избегает, потому что тогда "ownership" ячеек памяти постоянно меняется с одного проца на другой.

                                              "[...] и даже чтоб прочитать и вникнуть требуется немало умственных затрат"

                                              Это приходит с опытом. По умственным усилиям не сильно отличается от чтения асма.
                                              Ответить
                                              • Касы обламываются в лайвлок из-за реализации кас через ll\sc на некоторых платформах в присутствии фолс шаринга. Питухи из стандарта крестов об этом молчат и никакую возможность вычислить размер линии кеша стандартными средствами не дают.

                                                Также есть облом касов в лайвлок части потоков в высоконагруженной среде при сильно разном времени выполнении транзакций. У тяжелых есть вероятность уйти в долгий лайвлок, пока нагрузка не спадет, или размеры транзакций не сравняются.
                                                Ответить
                                                • >облом касов в лайвлок части потоков в высоконагруженной среде

                                                  В этом случае дохера данных попусту гоняется всё-равно процесс идёт.

                                                  Это как перемещение войск строем хоть и выглядит на первый взгяд тупо, но при большом количестве народу - это есть вынужденная необходимость рационального использования дороги.
                                                  И колоннами люди передвигаются быстрее, и компактнее чем врассыпную.
                                                  Ответить
                                                  • > В этом случае дохера данных попусту гоняется всё-равно процесс идёт.
                                                    Процесс идет у мелкозернистых транзакций, а у крупных стоит колом и может стоять очень долго, если нагрузка или средняя зернистость не сменится.
                                                    Ответить
                                                • "Касы обламываются в лайвлок из-за реализации кас через ll\sc на некоторых платформах в присутствии фолс шаринга."

                                                  Что такое "фолс шаринг"? http://en.wikipedia.org/wiki/False_sharing ?

                                                  Про проблему слышал, но сам по граблям не ходил. Видел в системщине народ по простой целую страницу жертвует что бы избежать проблемы.

                                                  "Питухи из стандарта крестов об этом молчат и никакую возможность вычислить размер линии кеша стандартными средствами не дают."

                                                  А ее в принципе узнать портабельными средствами невозможно и она даже на внешне одинаковых системах может отличатся. Если на самом деле надо, то делай как системщики: выделяй страницу и ложи туда все что будет доступатся только из одного потока. Выделение страницы дело простое:
                                                  posix_memalign( ... sysconf(_SC_PAGESIZE ) ... );
                                                  Ответить
                              • >такое тестировать было почти невозможно
                                Многопоточный код не "тестируют". Его невозможно тестировать.
                                Можно только выявить некорректность, но невозможно "тестированием" доказать корректность. Можыд на хасвеле оно будет заебись, а на другой машине с другой памятью, процом оно может поломаться.
                                А при правильной фазе Луны, когда оно будет в продакшене - может поломаться и на исходной машине.

                                Это уже не сфера программирования - ололо у меня есть тесты, они проходят и мой код корректен, это сфера математики и теории.

                                Корректность lock-free алгоритма доказывается нетривиальными математическими рассуждениями. Это вам не assParallel писать.
                                Ответить
                                • карочи нахуй потоки
                                  Ответить
                                  • Правильно. Чем больше узнаю о потоках тем больше склоняюсь к такой мысли - потоки надо делать когда ясно что без них никак.
                                    И уж лучше использовать высокоуровневые чужие обёртки, чем самому из примитивов конструировать #12413 велосипеды.
                                    Ответить
                                  • Да здравствует assParallel()!
                                    Ответить
        • Судя по красной цифре, кому-то это говно очень даже по вкусу
          Ответить
          • Здесь минусуют не только не говно, но и просто скучный код.

            Ваш кэп.

            P.S. Надо запилить третью кнопку "не говно", чтобы народ наконец-то перестал думать, что заминусованный код кошерен.
            Ответить
            • Навалить бы вам тьщь десять строк подобного кода, посмотрел бы я как вы заскучали :)
              Ответить
              • Не ошибусь, если у большинства здесь присутствующих на работе есть (или была) куча из тыщ строк скучной херни, которую надо поддерживать...

                Это повод ее постить? Нет. Ибо код, в котором нет ничего интересного и нового читать скучно. Отсюда и пачки минусов.
                Ответить
                • Не ошибусь, если у некоторых здесь присутствующих еще не было работы.
                  Вот они под впечатлением и постят.
                  Ответить
        • >> Да один хуй: как было говно потоко- и экцепшено-небезопасное, так и осталось.

          Ты кого говном небезопасным назвал?
          Ответить
      • показать все, что скрыто
        ~Клуб знакомств для геев~
             Познакомлюсь с парнем
             Сделаю миньет, подставлю попку парню кавказской внешности.
             Прут наглые хуястые самцы, желательно с большим членом, так как  
             очко сильно раздолблено. Могу принять сразу до 3-х парней.
                Пишите [email protected]  /Тарас/
        Ответить
      • показать все, что скрыто
        ~Клуб знакомств для геев~
             [color=green]Познакомлюсь с парнем
             Сделаю миньет, подставлю попку парню кавказской внешности.
             Прут наглые хуястые самцы, желательно с большим членом, так как  
             очко сильно раздолблено. Могу принять сразу до 3-х парней.
                Пишите [email protected]  /Тарас/
        Ответить
        • показать все, что скрыто
          ~Клуб знакомств для геев~
               Познакомлюсь с парнем
               Сделаю миньет, подставлю попку парню кавказской внешности.
               Прут наглые хуястые самцы, желательно с большим членом, так как  
               очко сильно раздолблено. Могу принять сразу до 3-х парней.
                  Пишите [email protected]  /Тарас/
          Ответить
    • показать все, что скрытоПЫПЭЦ))0))0 ШЕСТЬ ДИЗЛАЙКАФ У ПАСТА В ИСТОРИИ ГАВНАКОДА ИЩО НИКТО НЕ ПАЛУЧАЛ СТОЛЬКО МИНУСАВ))0000 НУ ТЫ ЛАХ КАРОЧ)0нольскопка
      Ответить
      • показать все, что скрытоЗАЧЕМ МИНУСУИТИ????? ИЩО ЧУЧУТЬ И Я АПАЗОРЮЗЬ!!!!!! НИНАДА ДИЗЛАЙКИ СТАВИТ Я ПАЩУТИЛ!!!!!!!!!
        Ответить
        • Бля, как я тащусь со школоло.
          Это типа я тебя витаминами угостил (в школе часто с собой приносили)
          )
          Ответить
          • Годный тролль должен быть здоровым и сильным!
            Ответить
          • нас всё равно больше
            Ответить
            • http://muzofon.com/search/если%20с%20другом%20вышел%20в%20путь
              Ответить
            • Жаль, что like нельзя обменивать на золото.
              Ответить
              • Накручивать же будут, и это золото обесценится :)
                Ответить
              • Жаль что долбоёбов, рак и флудеров тут никто не банит, хотя бы изредка - в назидание остальным.
                Ответить
                • Не криви душой, тебя просто жаба душит, что его лайкают, а тобi - ни.
                  Ответить
                • Лизни гоатсе.
                  Ответить
                  • >Stertor
                    >anonimb84a2f6fd141
                    показательно что на пост про долбоёбов ответила только эта парочка.
                    Ответить
                    • Себя я не упоминаю, из скромности.
                      Ответить
            • показать все, что скрыто
              ~Клуб знакомств для геев~
                   Познакомлюсь с парнем
                   Сделаю миньет, подставлю попку парню кавказской внешности.
                   Прут наглые хуястые самцы, желательно с большим членом, так как  
                   очко сильно раздолблено. Могу принять сразу до 3-х парней.
                      Пишите [email protected]  /Тарас/
              Ответить
          • показать все, что скрыто
            ~Клуб знакомств для геев~
                 Познакомлюсь с парнем
                 Сделаю миньет, подставлю попку парню кавказской внешности.
                 Прут наглые хуястые самцы, желательно с большим членом, так как  
                 очко сильно раздолблено. Могу принять сразу до 3-х парней.
                    Пишите [email protected]  /Тарас/
            Ответить
    • "Ещё из жизни синглтонов. Даёшь больше return'ов!"

      ты меня обогнал на день обогнал! я уже собрался постить аналог из моего проекта.

      и говно не в количестве return'ов.

      после двух дней отладки я наконец понял почему у меня все сообщения об ошибках инициализации синглтона появляются на экране три раза. потому что после первого эксепшена из getInstance() (из init()), в ходе "обработки" ошибок он еще дополнительно два раза вызывается.

      чудеса да и только.
      Ответить
      • показать все, что скрыто
        ~Клуб знакомств для геев~
             Познакомлюсь с парнем
             Сделаю миньет, подставлю попку парню кавказской внешности.
             Прут наглые хуястые самцы, желательно с большим членом, так как  
             очко сильно раздолблено. Могу принять сразу до 3-х парней.
                Пишите [email protected]  /Тарас/
        Ответить
    • Привет!
      Мы коллектив студенток города Москва, продаем наши обнаженные фото 1шт-15р.
      Первые 3 фото с твоим именем бесплатно
      Сразу после опроса-регистрации можно выбрать свой институт
      с нами 967 девушек :)
      <a href=http://gelanc.ml/>gelanc.ml</a>
      Ответить

    Добавить комментарий