kkolyan
> то локфри логгер неминуемо выставит барьер, внося риск спугнуть баг, вызванный
> отсутствием этого барьера.
Барьер по памяти, то есть кэш флаш?
На х64 это не страшно, там и так все сразу синхронизируется.
Тут главная проблема это аллокация памяти для строки лога, так как они может быть под мютексом.
/A\
а в крестах есть реордеринг? когда инструкции меняются местами для лучшей загрузки конвейера, если между ними нет барьера. в яве это есть, но я не знаю на каком уровне это реализовано - в явовском JIT или уже где-то поглубже, на стороне оси или даже прошивки.
/A\
> Тут главная проблема это аллокация памяти для строки лога, так как они может быть под мютексом.
тредлокал аллокация же легко делается, разве нет?
/A\
> когда логирование добавляет синхронизацию и баг не воспроизводится?
а что за баг?
может добавить тормозов (тип sleep(15)) одному из участников.
теоретически ты можешь на стадии инициализации памяти на выделять, тогда этого не надо будет делать во время логгирования
Есть идеи как заставить шаред существовать со время конструктора? А то сейчас шаред создаётся после того, как зовётся конструктор.
MrShoor
> Кек. Если барьер есть, то это уже не локфри. Это противоположные понятия.
в моей сфере локфри - это когда нет ожиданий на мониторах. т.е. всякие там волатайл и касы - вполне локфри. в том стеке с котором я работаю, волатайл ставит барьеры, соответственно противоречия между локфри и барьерами нет.
Где наше расхождение?)
samrrr
> как заставить шаред существовать со время конструктора?
есть такой костыль https://en.cppreference.com/w/cpp/memory/enable_shared_from_this если я правильно понял
забыл про всё это как страшный сон после перехода на Pool Handle
kkolyan
> а в крестах есть реордеринг?
Есть реордеринг компилятором и реордеринг в ЦП.
В С++ есть барьер для компилятора (atomic_signal_fence) и барьер для памяти включая барьер компилятора (atomic_thread_fence).
> тредлокал аллокация же легко делается, разве нет?
Это еще в планах. Для глобальных объектов уже свои аллокаторы есть, а вот временные не все еще есть.
skalogryz
> а что за баг?
Да как всегда:
if (complete) return; // <<< вот тут complete=true и все зависимости помечаются как готовые к выполнению AddDependency( ...); // << тут добавляется зависимость, которая не будет использована
#!
> есть такой костыль https://en.cppreference.com/w/cpp/memory/enable_shared_from_this если я правильно понял
Он не работает во время конструктора так как сам шаред ещё не существует во время конструкции класса.
samrrr
> Он не работает во время конструктора
Работает, так как ты наследуешься от enable_shared_from_this<> а внутри него создаются счетчики.
Так что во время вызова твоего конструктора все уже инициализированно и может быть использованно.
Но нельзя уменьшать счетчик, так как вызовется деструктор внутри конструктора.
/A\
> Работает
Покажешь? У меня пишет
+ _Wptr empty std::weak_ptr<MyClass>
Код примерно такой:
class MyClass: public std::enable_shared_from_this<MyClass>{ public: MyClass(){ auto t=shared_from_this( ); } };
make_shared<MyClass>();
/A\
> а внутри него
std::weak_ptr<MyClass> и всё. Выставляется этот веак конструктором шареда.
samrrr
> enable_shared_from_this
Там внутри хитро сделано:
_NODISCARD shared_ptr<_Ty> shared_from_this() { return shared_ptr<_Ty>( _Wptr); } mutable weak_ptr<_Ty> _Wptr;
Счетчик нулевой, поэтому не может сконвертировать weak в shared.
shared_ptr<MyClass>{this} должно сработать.
Но это может быть UB если в make_shared записывается 1 в счетчик, вместо прибавления 1.
upd: Ладно, я давно его не использовал, может переделали, чтоб слабые ссылки не мешали освобождению памяти.
/A\
> Тут главная проблема это аллокация памяти для строки лога, так как они может
> быть под мютексом.
Буфер фиксированного размера в стеке + snprintf
Dmitry_Milk
> Буфер фиксированного размера в стеке + snprintf
Что анреала насмотрелся?
samrrr
Выдели неинициализированную память @ инициализируй шаред указателем @ вызови плейсмент нью с умным указателем как аргументом конструктора (или через глобальный объект)