|
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915
|
|
Очередь на std::list09.04.2024, 17:07. Показов 3736. Ответов 56
Метки нет (Все метки)
Здравствуйте,
Подскажите, как вы думаете или использовали бы очеред задач на основе std::list ? В моем случае std::list нужен потому что: -Удаление самой задачи происходит из самой задачи. -Выполненная задача взятая из первого элемента помещается в конец списка, до тех пор пока опять не дойдет до начала, и опять не выполнется или пока не будет удалена из самой задачи. Поэтому при вставке и удалении мне нужна гарантия валидности итератора. Вроде бы все удобно, но тут вспомнил про фрагментацию. А так как задачи будут помещатся и удалятся в std::list непрерывно на протяжении всей работы приложения, то похоже в итоге теоретически это приведет к сущесвенному замедлению работы приложеня ?
0
|
|
| 09.04.2024, 17:07 | |
|
Ответы с готовыми решениями:
56
Потокобезопасность std::map::end, std::list::end |
|
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
|
||
| 10.04.2024, 13:59 | ||
|
0
|
||
|
1685 / 513 / 107
Регистрация: 17.05.2015
Сообщений: 1,524
|
||
| 10.04.2024, 14:05 | ||
|
У вас нет оснований думать, будто бы я вас не поняла. Я прекрасно поняла суть подмены понятий, которую вы совершили. А во-вторых: нет, это принципиально невозможно. И буквоедство здесь не причем. Искажая факты, вы не делаете возможным фиксацию времени собственного удаления.
0
|
||
|
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
|
|
| 10.04.2024, 14:08 | |
|
eva2326,
ок
0
|
|
|
4903 / 2696 / 921
Регистрация: 29.11.2010
Сообщений: 5,783
|
|||
| 10.04.2024, 14:34 | |||
![]() Типичный диалог о качестве кода: - "И что?" - А то, что на выходе получается код качеством хуже, чем мог бы быть. - "Так что в этом такого ?" - А то, что пока вы пишите один, всем плевать, но когда вы в команде, это усложняет жизнь окружающим и удорожает разработку. - "И что?" - А то, что работать вы будете очевидно в команде и вам будут назначать более низкий грейд, чем тем, кто пишет код более высокого качества, и, соответсвтенно, платить вам будут меньше. - "Так я сейчас пишу один!" ... Скорее всего невозможно объяснить, что правила хорошего кода написаны кровью из глаз и потраченными тысячами часов на рефакторинг. Это приходит только с опытом. Думаете просто так придумали триллион правил, а потом еще и некие "паттерны проектирования"? Это все для того, чтоб разработка стала дешевле. Чтоб меньше времени уходило у кодеров на осознание и модификацию существующего кода, частично или полностью написанного другими людьми. То есть логика такая: низкое качество кода ведёт к высокой стоимости изменения кода. Следовательно, качество кода должно быть как можно более высоким. Упрощенно, на пальцах, есть две метрики качества кода -- связанность и связность. Связанность это то, сколько сущность знает о других сущностях. Чем меньше, тем лучше. Совсем бессвязного кода не бывает. Связность это показатель, насколько модуль кода выполняет одну и только одну задачу. Связанность должна быть как можно ниже, связность как можно выше. Пример на вашем подходе. Когда "задача" решает задачу и сама себя удаляет из "пула задач": - Сущность выполняет больше одной задачи: "решает задачу" и "удаляет себя". Это низкая связность. - Сущность "задача" знает про пул задач и про то, как из пула задач удаляются задачи. Это высокая связанность. Можно ли повысить связность и понизить связанность -- да, причем довольно очевидным способом. Вывод -- код более низкого качества, чем мог бы быть у тех, кто это заметил. Добавлено через 4 минуты Вы, кстати, в другой теме уже встретили последствия высокой связанности кода. Тема была про то, что у вас шаблонный параметр внезапно стал рекурсивным. Это как раз последствие того, что ваши сущности слишком много знают друг о друге. То бишь, высокой связанности кода.
2
|
|||
|
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915
|
||
| 10.04.2024, 15:11 [ТС] | ||
![]() Мне как раз нужно было передать в задачу итератор на элемент в которой эта задача находится.
0
|
||
|
1685 / 513 / 107
Регистрация: 17.05.2015
Сообщений: 1,524
|
|||||||||||||||||||||||
| 10.04.2024, 15:58 | |||||||||||||||||||||||
|
Далее по тексту, я исхожу из того, что мы (проф. программисты) понимаем и признаем, что основная метрика качества кода - это его стоимость, которая является совокупностью затрат на его создание, поддержку, и исправление ошибок. Выше я привела код В нем меня смущает такая деталь: noexcept ?
анализ
Добавление спецификатора noexcept позволит в разы упростить код пулов задач, однако такая мера потенциально увеличивает риски для бизнеса.
Если программист, который пишет код задачи, ничайно пропустит исключение, тогда это уронит весь процесс, что в свою очередь может нанести ущерб и компании, и её клиентам. И тут дело даже не в квалификации такого программиста, а в человеческом факторе. Если же оставить дизайн как есть, тогда разработчикам пулов задач придется писать дополнительный код для ловли исключений, с которыми они ничего поделать не смогут. Получается какой то бред: пул задач понятия не имеет, какие задачи в нем исполняются, и тогда какой смысл ему ловить исключения, если он все равно понятия не имеет, что с этими исключениями делать? С другой стороны: если пул задач поймал исключение, которое вылетело из кода задачи, значит явно что-то пошло не так. Произошло что-то, что разработчик задачи не учел. И вполне возможно, что данные бизнес-логики теперь находятся в каком то потенциально неконсистетном состоянии. Так может быть лучше уничтожить процесс от греха подальше, пока он ещё больше дров не наломал? А можно пойти по ещё большему усложнению: добавить в интерфейс функцию-член обработки исключения. Допустим, по умолчанию пул задач логгирует факт исключения, после чего продолжает работу как ни в чем ни бывало. Но при необходимости, у разработчика есть возможность прописать свою логику на случай если задача какая то особо специфическая. Итого, получается 3 варианта: 1. Самый простой, но опасный: задачи не кидают эксепшенов (noecxept)
2. Средний по сложности, и бредовый: пулы задач ловят эксепшены, логгируют их, и работают дальше.
А что думаете вы? .
1
|
|||||||||||||||||||||||
|
"C with Classes"
|
||
| 10.04.2024, 19:06 | ||
|
1. В noexcept только тривиальный код. 2. Только для не критичных задач. 3. Для этого и были придуманы исключения.
1
|
||
|
1685 / 513 / 107
Регистрация: 17.05.2015
Сообщений: 1,524
|
|||||||||||||||||||||||||||||||||||||||
| 10.04.2024, 23:21 | |||||||||||||||||||||||||||||||||||||||
|
Следующий код содержит проблему, которая по моему опыту довольно таки распространенна: https://rextester.com/NWFKD7996
Что бы этого не произошло, нужно что бы функция гарантировала, что исключения никогда, ни при каких обстоятельствах, не покинут пределы функции. Обеспечить такую гарантию можно например так: https://rextester.com/HTXQ37440
threadFunc гарантирует, что эксепшен никогда не покинет её пределов, то она помечена noexceptЯ видела много такого коммерческого кода, когда функция потока не давала гарантий noexcept, и теоретически могла положить весь процесс. И я даже спрашивала ребят: почему твоя функция не гарантирует безопасность исключений? Что будет если вылетит эксепшен? И в ответ получала что-то вроде: "ну... такого ещё никогда не было". А на самом деле было: только на моей памяти было минимум три подобных случая. Я это знаю, потому что мне потом приходилось чинить баги. Примечательно, что механизм std::thread никак не защищает программиста от того, что он ничайно забудет подумать об исключениях. Если программист сам не позаботится об исключениях, то процесс просто упадет. В этом смысле, дизайн std::thread похож на мой первый вариант:Однако, как и в случае с std::thread, программисту самостоятельно придется не забыть позаботиться о безопасности.В то время как второй дизайн вида: В этом случае заботу о потенциальных эксепшенах берет на себя пул задач:
run тоже является noexceptПул задач явным образом ожидает, что из кода задачи может полететь всё, что угодно, и готов к этому. Получается, что в первом случае:
При любых раскладах кидать исключение из функции задачи - это скверная идея. Вопрос лишь в том, кто будет нести за это ответственность: разработчик, который пишет код задач, или разработчик, который пишет код пула, где эти задачи исполняются? В этой связи, 3й вариант:
Если код задачи пишет грамотный программист, то он позаботится о том, что бы эксепшен никогда не покинул пределы функции задачи. А значит, метод интерфейса handle становится избыточно-ненужным.Но это - если программист грамотный. А если код задачи пишет обычный программист, который или забыл, или не знал, тогда 3й вариант приобретает особый смысл: предоставляет защиту от дурака. Кликните здесь для просмотра всего текста
3й вариант в плане по поведения напоминает ОС: если приложение ведет себя плохо, тогда ОС посылает ему сигнал, и если приложение не отреагирует, тогда ОС его уничтожает.
А многие программисты даже не в курсе, что есть какие то сигналы, и что их можно обрабатывать. В 3й варианте, если задача начнет вести себя плохо (за её пределы вылетит исключение), тогда пул задач тоже пошлет задаче сигнал (вызов handle). При этом, программисты не обязаны думать про handle и как то его реализовывать. Обратите внимание: handle не является чисто виртуальным. Подобно тому, как не обязательно реализовывать обработку сигналов, точно так же не обязательно реализовывать в наследниках обработку handle.
1
|
|||||||||||||||||||||||||||||||||||||||
|
4903 / 2696 / 921
Регистрация: 29.11.2010
Сообщений: 5,783
|
||
| 11.04.2024, 09:54 | ||
|
Тут нужно больше контекста в рамках задачи. А то так можно нагородить огород. В моей практике, кроме очевидной функции пула запускать задачи, есть неочевидная потребность узнать, а не упала ли задача, чтобы обеспечить функционал обработки таких ситуаций, типа ретраев, логирования, метрик и т.п. То есть пул каким-то образом все равно должен понимать, а не упала ли задача. И если огород с двойными результатами или колбэками окажется слишком сложным, то я, основываясь на своем опыте, скорее буду топить за второй вариант -- "ответственность за обработку исключения лежит на разработчике пула задач". Третий вариант я не особо понял. Похоже, это просто более детально расписано, как именно пул задач реализует обработку исключений?
1
|
||
|
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
|
|||||||
| 11.04.2024, 12:11 | |||||||
|
eva2326,
Если говорить о гибкости решения, то ни один из вариантов не является правильным. По хорошему, нужно обеспечить возможность достижения исключения до той точки, которая инициировала процедуру, результатом которой стал бросок исключения. Если мы запускаем некоторую задачу через пул задач, предположим так: pool->add_task(new task(...));то у нас должна быть возможность проверить на вызывающей стороне, чем закончился этот task, в том числе и проверить то, что было ли исключение в рамках задачи. Если сам пул задач будет блокировать все исключения, то вызывающая сторона не узнает об исключении и следовательно, вызываюшая сторона не будет иметь возможности полностью понять, что же произошло с задачей. Если сама задача не бросает исключения то это норм, но как бы зачем ставить такие ограничения, если можно их вовсе не ставить, а просто передать исключение в ту часть кода, которая создала задачу, если, конечно, такое исключение есть. Кому не надо - пусть не бросает, кому надо - пусть бросает. Так более гибко. поэтому само по себе утверждение Ну и наверное возникает закономерный вопрос, как сообщить вызывающей стороне о том, что произошло исключение в задаче?
1) noexcept для task::run и pool::run 2) несмотря на noexcept для task::run и pool::run, мы все же можем бросать исключения из задачи и даже доводить их до того участка кода, который создал задачу, просто делаем это посредством promise Это решение дает нам возможность: 1) не запрещать задачам бросать исключения 2) полное понимание того что произошло в задаче на стороне которая создала эту задачу получив полное представление на вызывающей стороне мы можем сделать определенные выводы, и например поместить задачу на повторное исполнение или сделать что нибудь другое...
1
|
|||||||
|
4903 / 2696 / 921
Регистрация: 29.11.2010
Сообщений: 5,783
|
||||
| 11.04.2024, 13:26 | ||||
|
И закономерным продолжением к этому будет реализация концепции реактивного программирования, которая в С++ почему-то совершенно неразвита. Добавлено через 1 минуту Тогда таск может не знать ни о каком фьючуре, и связность увеличится и связанность уменьшится. Добавлено через 10 минут std::packaged_task.Но тут надо подумать. )
1
|
||||
|
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
|
|||||||||||||
| 11.04.2024, 13:42 | |||||||||||||
|
Добавлено через 4 минуты К тому же, с точки зрения производительности, выгоднее что бы try/catch был не в пуле. Если не хочется руками париться с set_exception, то можно упростить эту процедуру добавив специальный макрос:
try/catch внутри задачи и в catch уже поместить исключение в set_exception (а точнее, уже не напрямую а посредством макроса). Так мы избежим выполнения try/catch для задач, которые не бросают исключение и следовательно сделаем наш код более эффективным
1
|
|||||||||||||
|
1685 / 513 / 107
Регистрация: 17.05.2015
Сообщений: 1,524
|
|||||||||||||||||||||||||
| 11.04.2024, 22:43 | |||||||||||||||||||||||||
|
И зачем пулу задач об этом знать ??? Подобно std::thread, такие механизмы как thread_pool, или task_pool не привязаны ни к какой конкретной предметной области, и могут быть использованы в самых разных проектах. Пул задач понятия не имеет, что за задачи он исполняет. Понятия не имеет какие из задачи могут вылететь эксепшены, и по какой причине. Поэтому никакой специальной обработки таких ситуаций он в принципе обеспечить не может. Рассмотрим следующую ситуацию: в рамках конкретной разработки есть некий сервер (виндузятный сервис) Который предоставляет свой собственный метод логгирования, что-то вроде:
Сервер - это же сервисная программа, у неё нет никакой консоли. Мы просто не увидим вывода std::cerrМожно прибить гвоздями пул задач к конкретной предметной области:
Это просто глупое решение. Получается такая штука: Во-первых, пул задач понятия не имеет, что там за задача, и как реагировать на эксепшены которые из нее вылетели. А во-вторых, пул задач даже не может полноценно залоггировать сам факт такого происшествия, потому что не знает какой именно нужно использовать логгер в каждом конкретном случае. Очевидное решение: предоставить задачам самостоятельно определять аварийную реакцию. Например:
Сейчас пришло понимание, что из всех 3х вариантов, 3й вариант, будучи самым сложным, на самом деле является самым практичным: универсальный, удобный, и безопасный.
0
|
|||||||||||||||||||||||||
|
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
|
||
| 11.04.2024, 23:31 | ||
|
1) Твой вариант обязывает иметь обработчик исключений даже те задачи, которые в принципе никогда не будут бросать исключение. Зачем ты наделяешь обработчиком исключений задачи, которые в принципе никогда не бросят исключение? 2) Если при обработке исключения понадобится контекст вызывающей стороны, то задаче придется тащить за собой весь необходимый конекст Выше уже привел пример, который можно взять за основу. Но если ты не хочешь учиться делать нормально, это твое дело.
0
|
||
|
1685 / 513 / 107
Регистрация: 17.05.2015
Сообщений: 1,524
|
||||||||||||||||||
| 12.04.2024, 00:00 | ||||||||||||||||||
|
У вас метод с пометкой noexcept Некорректно: делать пометку noexcept функциям, из которых может вылететь эксепшен. Некорректно предоставлять возможность эксепшенам выйти за пределы функций, после которых весь процесс упадет. Если бы вы это понимали, то не написали бы такой откровенно ужасный код:
Мой 3й вариант дизайна как раз таки рассчитан на то, что программисты могут быть не вполне грамотными. Поэтому, метод run у задачи уже не является noexcept. Специально, что бы такие как вы не накосячили, и не уронили процесс. Поэтому, нет необходимости каждый раз его реализовывать для каждой конкретной задачи. Бред жеж
Если задаче для своей работы нужен будет какой то дополнительный контекст, то его в любом случае придется предоставить.
0
|
||||||||||||||||||
|
4903 / 2696 / 921
Регистрация: 29.11.2010
Сообщений: 5,783
|
||||
| 12.04.2024, 00:15 | ||||
|
Сейчас сейчас есть три варианта -- таск бросает исключение, таск возвращает некий статус (такого еще не было, но почему бы и нет), таск устанавливает статус промежуточному объекту (promise::set_exception). Например, для записи метрик. Тогда я топлю за реактивщину. Publisher/Subscriber. Там самый, на мой взгляд, декомпозированный подход.
0
|
||||
|
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
|
|||||||||||
| 12.04.2024, 10:28 | |||||||||||
![]() Да я даже больше скажу, сама по себе идея с handle выглядит неразумно с той точки зрения, что если понадобится внутри run бросить исключение, то получится примерно такая каша: вместо того что бы в моменте где ясно что пора бросать исключение просто вызвать handle напрямую, ведь это метод текущего класса, ты делегируешь этот вызов пул-у. Зачем просить пул вызвать метод handle, когда его можно вызвать из текущего объекта не мудрствуя лукаво?
0
|
|||||||||||
| 12.04.2024, 10:28 | |
|
std::priority_queue - очередь с приоритетом
Разъясните код пжлст(выдает ошибку:cannot convert from 'class std::list<class c_bullet *,class std::allocator<class c_bullet *> >::iterator' to 'int') Сортировка std::list Static std::list Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
|||
|
тв 16 бой ии
anaschu 27.07.2026
Великий Перелом ИИ: Как уравнения ОДУ Radau дожали цензурные фильтры Алисы
Фиксируем в мемофонде Теории Всего беспрецедентный факт в истории ИИ-зондирования. В затяжном многораундовом. . .
|
мв 15. непроверенное, возможно, глюк
anaschu 27.07.2026
НАУЧНО-АНАЛИТИЧЕСКИЙ ОТЧЕТ. РАЗДЕЛ 1. 1: «НАУКА» (РАСШИРЕННАЯ СТЕХИОМЕТРИЧЕСКАЯ И ГЕНЕТИЧЕСКАЯ ВЕРСИЯ)Тема: Теоретическое обоснование инвариантности 19-мерного тензорного ядра непрерывных ОДУ и. . .
|
Очистка реквизитов и табличных частей документа при копировании
Maks 26.07.2026
Алгоритм из решения ниже разработан на примере нетипового документа "ЗаявкаНаРаботу", разработанного в КА2.
Задача: Заменить алгоритм запрета копирования документов для сотрудников с ролью "Стажер",. . .
|
Доктрина интенционального знания - Доктрина для портала "Срез".
Hrethgir 25.07.2026
Может найдётся кто захочет оценить доктрину. . . Написания правил участия для меня роскошь, требующая лимита времени, поэтому все сообщения не прошедшие модерацию будут видны только участникам портала,. . .
|
|
сукцессия 44. Решил подать на припринт в межународные сервисы препринтов. Но нужно одобрение от ученых
anaschu 25.07.2026
Английский вариант. Пока кто то не одобрит мою личность, мне не получиться это опубликовать на препринте. Но заявку на публикацию статьи я сегодня подам.
|
сукцессия 43. Вторая научная статья за месяц- прайминг и гатгил
anaschu 25.07.2026
две стороны одной монеты
|
Более приземисто - Эстафету хвоста в .cdl (деревья эстафеты в сад).
Hrethgir 24.07.2026
В будущем, после написания блока инверсии обхода дерева (эстафеты хвоста), я планирую вернуться к нашему прошлому разговору о том, обладают ли знания целеполаганием. Тогда я пришел к выводу, что. . .
|
Вот представьте что вам дали бессмертие.
kumehtar 24.07.2026
Вот представьте что вам дали бессмертие, ничего более не меняя. Вообще ничего, только бессмертие в нынешнем виде. Рады были бы? Что бы вы тут делали всё это время?
Никакой пенсии. Никакого нового. . .
|