Good
Ой, это же гудя
А это мой должник?
Matwey
Чо это должник? Ты еще скажи, что я тебе BTC должен
Good
Возможно. Поэтому и спросил.
Matwey
Не было такого!
Vladislav
https://www.youtube.com/watch?v=ZLNq-4IiNTY
Aleksander
А так можно было? :)
А почему нет? Слишком мало информации в вопросе. Объявить переменную volatile, для исключения кеширования, и всё.
Aleksander
(до свидания, нога)
С чего вдруг?
Surreal
в плюсах volatile != thread safe
Aleksander
да тут смысла нет никакого в thread safe. Слишком мало информации в вопросе. Вполне допускаю, что в каких-то конкретных ситуациях у автора будет польза от атомиков/мьютексов в геттере этого bool-а, но в общем случае будут только грабли. Поэтому я и говорю, что смысла в них нет никакого.
Aleksander
А может я глубоко заблуждаюсь? Ну объясните плиз на примере псевдо кода: void work() { if (obj.getBool()) // hard work else // hard work 2 // hard work 3 for (int i=0;i<100;i++) if (obj.getBool()) // hard work4 }
Aleksander
вот какую пользу могут принести заморочки с синхронизацией внутри getBool() ?
Aleksander
подобный код имеет ненулевую вероятность вообще не заметить что эта переменная была много раз изменена в других потоках
Vladislav
подобный код имеет ненулевую вероятность вообще не заметить что эта переменная была много раз изменена в других потоках
Вот именно - переменная может измениться, а код об этом никогда (в худшем случае) не узнает
Aleksander
Вот именно - переменная может измениться, а код об этом никогда (в худшем случае) не узнает
Именно. И никакие мьютексы внутри геттера тут никак не помогут.
Vladislav
Разумеется, нужны и в геттере и в сеттере (или просто атомик)
Aleksander
Ээ, ну и как это поможет?
Aleksander
в течении любого этапа // hard work X эта переменная может поменяться любое число раз
Anton
если это критично, то мьютекс как раз и поможет
Anton
нужно просто его лочить во время hard_work()
Aleksander
Ну началось. Изначально речь шла про геттер
Aleksander
нужно просто его лочить во время hard_work()
Поможет только если лочить вместе с геттером.
Vladislav
Ээ, ну и как это поможет?
Это поможет от ситуации "поток А записал true, но поток B все равно постоянно видит false"
Constantine
Нет, так нельзя: компилятор вправе делать оптимизации не атомарных переменных из рассчёта, что они не используется в других потоках. Поэтому он например может выкинуть запись в эту переменную значения к чёртовой бабушке. А еще он может закешировать значение переменной и никогда его не обновлять
Дарю случай из памяти. Была функция, и была в ней зачем-то статическая переменная. Так вот, под -O2 data race не было, потому что компилятор заметил, что она всегда на входе и выходе имеет одно и то же значение, и решил ее вообще не создавать статически :)
Stas
Иногда, а может не помочь. Гарантии всё равно не будет.
У нас 4 варианта работы: 1 — bool flag; никаких гарантий, второй поток может НИКОГДА не узнать об изменениях переменной (компилятор может только один раз вычитать при старте и соптимизировать и разместить переменную в регистр) приехали. 2 — valatile bool flag; - гарантия того, что компилятор не будет проводить оптимизацию и то что каждое чтение будет проходить заново. По этому второй поток все таки увидит изменившуюся переменную (рано или поздно). Но гарантии атомарности при одновременном R/W нет! 3 — atomic<bool> flag; считай что 2 + гарантия атомарности при одновременном R/W. (но легче это продимонстрировать на счетчике один поток делает ++, другой -- при такой гарантии и одинаковом кол-ве итераций счетчик по окончанию будет 100% иметь первоначальное значение (до старта)). Дальше нюанс есть барьер или нет. Например на ARM при использовании эксклюзивной загрузке и выгрузки можно атомик написать без барьера (Железо позволяет) — сам атомик будет в согласованном состоянии а вот данные вокруг нет! 4 — Атомик с барьером (считай что мьютекс) Который гарантирует что ни только переменная будет в согласованном виде (см пример выше со счетчиком) но и данные рядом будут синхронизированы (Кэши ядер при каждом простом (большом) барьере будут синхронизироваться) Это самый медленный вариант. По этому придумали разные барьеры, чтобы программист смог оптимизировать сам если хочет. PS по этому атомик без барьера не позволяет написать примитив синхронизации (аля мьютекс) Только барьер памяти проводит синхронизацию кэшей — это долго в тактах! И как бы теряется смысл этого кэша считай что вы отказываетесь от него.
Constantine
А почему ты увидишь изменение volatile переменной хоть когда-то?
Constantine
Она валяется там в кэше одного ядра
Stas
Потому что валатайл сообщает компилятору что при каждом чтении и записи нужно записать и прочитать переменную в память. Но из-за наличия кэша затык. компилятор читает и пишет в кэшь одного ядра. и тут получается что мы должны дождаться сброса кэша или барьера из другого процесса!. Но если ситуация вырожденная и процессов два и два ядра и шедуллер не переключает то валатайл тоже приограл! Нужен барьер!
Stas
Если нужна только одна переменная и только нужно ее согласованное состояние то достаточно атомика, если же по этому флагу дается знать, что некие данные готовы или бла бла бла... то нужен барьер или тупо использовать любой примитив синхронизации (в каждом из них есть барьер)
Constantine
Эээээ в атомике уже встроен барьер
Stas
Атомик не явл-ся примитивом синхронизации - он явл-ся как бы примитивом синхронизации только для себя. Это заметно на АРМ, на x86 не знаю, нужно спросить знатоков.
Vladislav
У нас 4 варианта работы: 1 — bool flag; никаких гарантий, второй поток может НИКОГДА не узнать об изменениях переменной (компилятор может только один раз вычитать при старте и соптимизировать и разместить переменную в регистр) приехали. 2 — valatile bool flag; - гарантия того, что компилятор не будет проводить оптимизацию и то что каждое чтение будет проходить заново. По этому второй поток все таки увидит изменившуюся переменную (рано или поздно). Но гарантии атомарности при одновременном R/W нет! 3 — atomic<bool> flag; считай что 2 + гарантия атомарности при одновременном R/W. (но легче это продимонстрировать на счетчике один поток делает ++, другой -- при такой гарантии и одинаковом кол-ве итераций счетчик по окончанию будет 100% иметь первоначальное значение (до старта)). Дальше нюанс есть барьер или нет. Например на ARM при использовании эксклюзивной загрузке и выгрузки можно атомик написать без барьера (Железо позволяет) — сам атомик будет в согласованном состоянии а вот данные вокруг нет! 4 — Атомик с барьером (считай что мьютекс) Который гарантирует что ни только переменная будет в согласованном виде (см пример выше со счетчиком) но и данные рядом будут синхронизированы (Кэши ядер при каждом простом (большом) барьере будут синхронизироваться) Это самый медленный вариант. По этому придумали разные барьеры, чтобы программист смог оптимизировать сам если хочет. PS по этому атомик без барьера не позволяет написать примитив синхронизации (аля мьютекс) Только барьер памяти проводит синхронизацию кэшей — это долго в тактах! И как бы теряется смысл этого кэша считай что вы отказываетесь от него.
> Но гарантии атомарности нет стесняюсь спросить, что именно это значит для bool
Stas
Эээээ в атомике уже встроен барьер
Повторюсь для АРМ архитектуре ты можешь написать атомик без барьера.
Stas
там есть эксклюзивная загрузка и выгрузка.
Stas
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0204f/Cihbghef.html
Constantine
кажется, атомик операция memory_order_seq_cst гарантирует, что все там за барьером
Stas
Если эту гарантию дает стандарт, то да значит компилятору говорят засунуть барьер. Но это тогда не просто атомик, а атомик + барьер. Ты же можешь вообще работать на С99 и что значит ты не можешь атомики юзать или барьеры? можешь, но ты как человек должен понимать, что Атомик на некоторых архитектурах не обязан иметь барьер. просто будет атомарный свап и все!. Если же стандарт говорит, что и барьер будет, то круто ты получил гарантию из коробки.
Stas
Но так же и получил замедление работы атомика приблизительно на порядок.
Constantine
Когда я буду об этом париться, я сообщу
Berkus
А почему нет? Слишком мало информации в вопросе. Объявить переменную volatile, для исключения кеширования, и всё.
volatile не даст синхронизации между кэшами процессора, т.к. ничего не знает о барьерах - это рекомендация только для компилятора (и использовать ее надо только для mmio, и очень избирательно)
Berkus
Именно. И никакие мьютексы внутри геттера тут никак не помогут.
тут да, для чтения одной переменной мимоходом вообще никакая синхронизация не нужна, если тебе пофиг что выполняется в программе и когда - не синхронизируй
Egor
https://isocpp.org/files/papers/CppDevSurvey-2018-02-summary.pdf
Berkus
https://isocpp.org/files/papers/CppDevSurvey-2018-02-summary.pdf
Q16 Do you have any additional feedback for C++ standardization? Rust лол
Matwey
Так там переменная min неинициализирована. Будет хз чо
Matwey
И переменная n впрочем тоже
Matwey
Не ясно чему равна
Pepe 🐸
мне кажется ты забыл кейс когда есть несколько юзеров, и это не относится к многозадачности
Олександр
; в конце #include <iostream>
Олександр
Да, забавная картинка)
Vsevolod
в общем, чтобы исключения c++ пролетали бы через сишный фрейм, обязательно нужен .eh_frame в случае gcc/clang abi
Vsevolod
со всяческим jit это особенно актуально
Vsevolod
потому что без этой информации unwind останавливается, и ничего после такого фрейма уже не поймать
Berkus
красиво
Nikita
горизонт завален
Ostap ꑭ
Пыль на мониторе
Alexander "SonnySlave"
не оффтопим сильно 😊
Levan (Leo)
Цикл for задан не верно.
Levan (Leo)
Не определён счотчик цикла! И даже количество цикла тоже
Berkus
Цикл for задан не верно.
слушай не может быть, весь код без ошибок и вдруг в цикле ошибка, разве такое бывает?
Levan (Leo)
Нет
Levan (Leo)
Если пользуешся for значит ты знаешь всё о цикле . А если знаешь то как можно допустить та?))
Levan (Leo)
Иначе пиши while
Berkus
else while(?
Levan (Leo)
В С есть 3 цикла.
Alexander "SonnySlave"
Alexander "SonnySlave"
вроде только 2
Levan (Leo)
For, while и do while
Alexander "SonnySlave"
ты уверен?
Co(n)stantine👨‍🔬
В С есть 3 цикла.
а в плюсах 2 штоль? вродь тож три
Levan (Leo)
1вый пишется тогда когда ты знаешь колличество цикла.
Levan (Leo)
А остальные 2 , когда не знаешь
Georgiy
1вый пишется тогда когда ты знаешь колличество цикла.
не количество а условие останова цикла
Danil
@zamazan4ik @berkus парни, сверните это уже)
Levan (Leo)
И они почти схожи но нюансы есть
Alexander "SonnySlave"
Alexander "SonnySlave"
И они почти схожи но нюансы есть
иди в @supapro просвещать 😊
Levan (Leo)
)))
Berkus