Нашли или выдавили из себя код, который нельзя назвать нормальным,
на который без улыбки не взглянешь?
Не торопитесь его удалять или рефакторить, — запостите его на
говнокод.ру, посмеёмся вместе!
Не станет 🙂 Там худшее что случится - нагрузка по копированию ляжет не на тот тред (хотя мне логика "кто портит, тот и платит" по душе), или произойдет лишнее копирование (если два треда одновременно войдут в detach()).
Все остальные ошибки они и с stl векторами вылезут. Попортил контейнер во время работы итераторов - ССЗБ (ну разве что кроме std::map'а). Дал доступ к одному инстансу контейнера двум потокам - ССЗБ (к разным инстансам с одним shared блоком можно, все будет норм).
Зачем? Детач делает тот, кому нужно портить объект. Для остальных он вообще иммутабельный (если сдуру не сделать ССЗБ из топика). Если во время работы константных методов и случится detach() в соседнем треде, то никто ничего не заметит, т.к. тот тред замутит себе копию, а к оригиналу притронется только для чтения.
> Если во время работы константных методов и случится detach() в соседнем треде, то никто ничего не заметит, т.к. тот тред замутит себе копию, а к оригиналу притронется только для чтения.
А если в этот момент, когда делается копия в соседнем треде, произойдет запись в оригинал?
> А если в этот момент когда делается копия в соседнем треде произойдет запись в оригинал?
Все будет норм, т.к. счетчик ссылок декрементят после копирования (см. вырезки из кода в соседнем треде). Тот, кто пишет в оригинал замутит себе копию и насрет в нее. А оригинальный блок данных после завершения копирований умрет от одиночества.
Т.е. я правильно понимаю, что ситуация такая?
- два треда имели разные инстансы QVector'а с одним shared блоком
- первый тред захотел что-то записать в вектор, вошел в detach() и начал копирование
- в это время второй тред через STL итератор поменял что-то в оригинале
- кровь-кишки-распидорасило
Эта проблема, как я уже неоднократно писал в этом треде, возникает только в одном случае - если ты сделал копирование контейнера при живых итераторах. Если же ты сначала расшарил контейнер, а потом получаешь итератор, то begin() сделает detach() и все будет норм.
P.S. Вот замутили бы они clone() для твоего случая - и никакой проблемы бы не было.
> в это время второй тред через STL итератор поменял что-то в оригинале
В сраных жабах во всех дефолтных коллекциях (непотокобезопасных) обычно из итератора кидается ConcurentModificationException, не для контроля, а скорее для того чтобы не использовали их там где не следует.
Ну щас. Ограничивать себя ещё... Уж лучше подергать, чем не пользоваться частью удобного функционала. тем более что последствий вредных у этого не будет никаких.
А что вы еще ожидали? Любой шаринг данных незащищенных лочкой приведет к неконсистентной катастрофе. И вообще считаю итератор одноразовым объектом, который кстати при синхронизации частенько забывают и обходят стороной, хотя если он может мутировать то что обходит, то капец. Интересно как будет разрулена сия проблема в TBVector
Это все происходило в одном потоке. Да и сам по себе QVector не потокобезопасный, равно как и std::vector и жабьи List'ы.
> И вообще считаю итератор одноразовым объектом
+1. С осторожностью поюзал внутри функции и выбросил. Хранить итераторы - ССЗБ (ну разве что они в привате вместе с контейнером).
> Хранить же итератор глобально или копировать имхо какое-то безумие.
Херню сказал. Иногда например нужно вставить рядом с каким-то элементом. По этой причине итератор нужен. Тот же указатель понятное дело не подойдет в таком случае. А каждый раз искать по элементу его положение в коллекции - верх идеотизма
Ну можно на клиенте преобразовать - ссылки на рисунки обернуть в <img> и поставить слева от коммента, убрать отступы, отсортировать комменты по дате, и под комментом проставить ссылки на ответы, которые по наведению в попапе покажут сам ответ. И получится говноборда 🙂
> Не работает при развороте коментов из аякса. И при посте тоже.
Я знаю. Но я не силен в юзерскриптах. А без них такое особого смысла нету писать, т.к. лень тыкать каждый раз в букмарклет.
Завтра поставлю гризманки да перепилю гк в анонимный говнач. Линейный вид, отсортированный по дате, оказался удобней дерева - сразу видать новые комменты.
Там ещё это связано с загрузкой незагруженного, минимизацией-максимизацией картинок, ... Плюс свой набор функций для работы с DOM.
Я, когда GK parent comment изменял, решил посмотреть, но в итоге сделал просто удаление всплывающего комментария через N миллисекунд, отмену удаления, если мышь перешла на комментарий, удаление через N миллисекунд, если мышь ушла.
А я сделал так - при наведении на линк всплывает попап. При наведении на попап или линк их айдишка сохраняется в переменную. При уходе мышки с линка или попапа в эту переменную помещается нулл и запускается таймер на 200мс. По таймеру удаляются все попапы, лежащие выше того, который был в переменной (или вообще все, если там null). По ощущениям вроде бы похоже на вакабу. Только там таймауты походу больше.
> По таймеру удаляются все попапы, лежащие выше того, который был в переменной (или вообще все, если там null).
Вот эта логика меня затралела, поскольку я не сидел и не сижу на имиджбордах.
> Почему не "въебал плюс"?
Вероятно, тут это чаще пишут.
А вообще, должен же быть какой-то враг/оппонент, с которым надо спорить, ради утопления которого писать боты, фильтровать его юзерскриптами и т.д.
> А вообще, должен же быть какой-то враг/оппонент, с которым надо спорить, ради утопления которого писать боты, фильтровать его юзерскриптами и т.д.
Бой с тенью.
> Иногда например нужно вставить рядом с каким-то элементом.
Это когда? И зачем? Лично я стараюсь практически никогда не мутировать коллекцию итератором. Единожды написал такое, и то была говнооптимизация и хак, которого можно было избежать.
> Тот же указатель понятное дело не подойдет в таком случае.
Да итератор это и есть указатель, просто обобщенный на случай непотребщины, в которой элементы лежат не подряд единым блоком. Практически все проблемы указателей автоматом переходят и на итераторы, а на деле еще и новые добавляются.
И обращаться с ними надо именно так, как ты обращаешься с голыми указателями.
> Херню сказал.
Нифига не херню. Такой итератор должен лежать рядом с контейнером, в который он указывает. Причем и то и другое должно лежать в привате, чтобы не дай бог между ними рассинхрон не произошел. А глобальный итератор, ссылающийся в хуй знает куда это риалли безумие.
2. У меня в поисковике сортированный список документов представлен парой константных итераторов, указывающих на участок иммутабельного индекса. Пару можно прекрасно сплиттить для параллельной обработки. Хотя с этим также неплохо справляются slice-ы в Go-версии.
> За что такая нелюбовь к stl-итераторам?
Это не не любовь, а осторожность. Я же нигде не писал, что я ими не пользуюсь и другим не советую... Просто они настолько же опасны/безопасны, насколько и самые обычные указатели.
> 1. LRU-кэш на итераторах std::list
Ну вот mCacheList и mCacheMap надо засунуть в приват какому-нибудь классу, иначе кто-нибудь обязательно порушит инвариант (тут проблема более общая, без итераторов я бы тоже это сделал).
> иммутабельного
Ключевое слово 😉 Отдавать куда попало итератор на мутабельную коллекцию я бы не рисковал.
> они настолько же опасны/безопасны, насколько и самые обычные указатели
Just as designed. Итераторы и были спроектированы, чтобы моделировать абстрактный указатель. Даже нотацию сохранили, чтобы их не отличить было. Сишники вон таскают всюду указатели и не жалуются.
Я не предлагаю совать итераторы во все дыры, особенно с учётом с++11 с его range-based for. Концепция Range мне всегда нравилась больше. Но и итераторы весьма полезны и универсальны.
>> итераторов, указывающих на участок иммутабельного индекса
>Ключевое слово 😉
Истинно. Выше же писал что итератору в 90% случаев необходимо и достаточно быть read-only. Глобальный итератор мутирующий коллекцию - неиссякаемый источник гейзенбагов.
При этом ни о каких блокировках на итераторе естественно речи не идёт.
Все остальные ошибки они и с stl векторами вылезут. Попортил контейнер во время работы итераторов - ССЗБ (ну разве что кроме std::map'а). Дал доступ к одному инстансу контейнера двум потокам - ССЗБ (к разным инстансам с одним shared блоком можно, все будет норм).
А если в этот момент, когда делается копия в соседнем треде, произойдет запись в оригинал?
Все будет норм, т.к. счетчик ссылок декрементят после копирования (см. вырезки из кода в соседнем треде). Тот, кто пишет в оригинал замутит себе копию и насрет в нее. А оригинальный блок данных после завершения копирований умрет от одиночества.
- два треда имели разные инстансы QVector'а с одним shared блоком
- первый тред захотел что-то записать в вектор, вошел в detach() и начал копирование
- в это время второй тред через STL итератор поменял что-то в оригинале
- кровь-кишки-распидорасило
Эта проблема, как я уже неоднократно писал в этом треде, возникает только в одном случае - если ты сделал копирование контейнера при живых итераторах. Если же ты сначала расшарил контейнер, а потом получаешь итератор, то begin() сделает detach() и все будет норм.
P.S. Вот замутили бы они clone() для твоего случая - и никакой проблемы бы не было.
В сраных жабах во всех дефолтных коллекциях (непотокобезопасных) обычно из итератора кидается ConcurentModificationException, не для контроля, а скорее для того чтобы не использовали их там где не следует.
Я хз. Должно выглядеть как-то так. Это не я писал, но у нас юзается в проекте "операция подергивание или UB". Я как бы хз как правильно.
До - можно. И после того, как закончишь юзать итератор - можно. Пусть там хоть 10 потоков потом его дрочат, никаких проблем не случится.
P.S. Там кстати detach() в паблике, просто недокументированный. Это я так, к слову, не надо его юзать.
Интересно как будет разрулена сия проблема в TBVector
> И вообще считаю итератор одноразовым объектом
+1. С осторожностью поюзал внутри функции и выбросил. Хранить итераторы - ССЗБ (ну разве что они в привате вместе с контейнером).
В жабе для этих целей придумали Spliterator.
http://docs.oracle.com/javase/8/docs/api/java/util/Spliterator.html#CONCURRENT
Хранить же итератор глобально или копировать имхо какое-то безумие.
Но там не лисп и не кложура.
Херню сказал. Иногда например нужно вставить рядом с каким-то элементом. По этой причине итератор нужен. Тот же указатель понятное дело не подойдет в таком случае. А каждый раз искать по элементу его положение в коллекции - верх идеотизма
Я знаю. Но я не силен в юзерскриптах. А без них такое особого смысла нету писать, т.к. лень тыкать каждый раз в букмарклет.
http://shitstream.ru/
Еще с аяксом разобраться, да с закрытием плашек по отведению мыши, и можно альфатестить.
Респект таким парнямА у меня что-то апатия какая-то образовалась, даже кодить лень.
Глянь на двачах же.
Я, когда GK parent comment изменял, решил посмотреть, но в итоге сделал просто удаление всплывающего комментария через N миллисекунд, отмену удаления, если мышь перешла на комментарий, удаление через N миллисекунд, если мышь ушла.
Вот эта логика меня затралела, поскольку я не сидел и не сижу на имиджбордах.
P.S. Является говном, т.к. задваивает комменты при повторном запуске.
Почему не "въебал плюс"?
Вероятно, тут это чаще пишут.
А вообще, должен же быть какой-то враг/оппонент, с которым надо спорить, ради утопления которого писать боты, фильтровать его юзерскриптами и т.д.
Бой с тенью.
Там console.log вроде бы отображается
Только вот при ошибке вываливается текст всего скрипта и текст ошибки 🙁
Им и дебажился.
> А вообще, вали в хром + tampermonkey, там скрипты можно отлаживать.
Там прям нормальный отладчик, такой же как для остального жс?
> дебажился.
Лол
Прям нормальный.
Это когда? И зачем? Лично я стараюсь практически никогда не мутировать коллекцию итератором. Единожды написал такое, и то была говнооптимизация и хак, которого можно было избежать.
Если Вас что-то не устраивает - покиньте сайт.
Да итератор это и есть указатель, просто обобщенный на случай непотребщины, в которой элементы лежат не подряд единым блоком. Практически все проблемы указателей автоматом переходят и на итераторы, а на деле еще и новые добавляются.
И обращаться с ними надо именно так, как ты обращаешься с голыми указателями.
> Херню сказал.
Нифига не херню. Такой итератор должен лежать рядом с контейнером, в который он указывает. Причем и то и другое должно лежать в привате, чтобы не дай бог между ними рассинхрон не произошел. А глобальный итератор, ссылающийся в хуй знает куда это риалли безумие.
Чтоэта?
> Хранить итераторы - ССЗБ (ну разве что они в привате вместе с контейнером)
За что такая нелюбовь к stl-итераторам? Незаменимая же вещь. Примеры:
1. LRU-кэш на итераторах std::list
2. У меня в поисковике сортированный список документов представлен парой константных итераторов, указывающих на участок иммутабельного индекса. Пару можно прекрасно сплиттить для параллельной обработки. Хотя с этим также неплохо справляются slice-ы в Go-версии.
Это не не любовь, а осторожность. Я же нигде не писал, что я ими не пользуюсь и другим не советую... Просто они настолько же опасны/безопасны, насколько и самые обычные указатели.
> 1. LRU-кэш на итераторах std::list
Ну вот mCacheList и mCacheMap надо засунуть в приват какому-нибудь классу, иначе кто-нибудь обязательно порушит инвариант (тут проблема более общая, без итераторов я бы тоже это сделал).
> иммутабельного
Ключевое слово 😉 Отдавать куда попало итератор на мутабельную коллекцию я бы не рисковал.
Just as designed. Итераторы и были спроектированы, чтобы моделировать абстрактный указатель. Даже нотацию сохранили, чтобы их не отличить было. Сишники вон таскают всюду указатели и не жалуются.
Я не предлагаю совать итераторы во все дыры, особенно с учётом с++11 с его range-based for. Концепция Range мне всегда нравилась больше. Но и итераторы весьма полезны и универсальны.
>Ключевое слово 😉
Истинно. Выше же писал что итератору в 90% случаев необходимо и достаточно быть read-only. Глобальный итератор мутирующий коллекцию - неиссякаемый источник гейзенбагов.
При этом ни о каких блокировках на итераторе естественно речи не идёт.