Здравствуйте, landerhigh, Вы писали:
ХГ>>>>Никакого захвата новых ресурсов, только работа с уже захваченными.
P>>>попытка захватить новое место на диске во время flush'а
ХГ>>Это не ресурс в терминах RAII. Да и флаш может быть не на диск а, например, в сокет. Там чего захватываем?
L>Если честно, то за подобные выходки из деструкторов нужно сначала долго бить сапогами в живот, а потом разжаловать в старшие помощники младших черпальщиков в ассенизаторском обозе при холерных бараках. Безотносительно того, что захватываем.
Попробуй объяснить это авторам стандартной библиотеки Да заодно и бустоводам.
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Здравствуйте, Хон Гильдон, Вы писали:
ХГ>>>>>>>Да и флаш может быть не на диск а, например, в сокет. Там чего захватываем? P>>>>>>да пофиг что и как, у "правильного" объекта поломка должна быть возможна только до деструктора. P>>>>>>другие "неправильные" тоже могут со-существовать. ХГ>>>>>Осталось только научиться писать такие вот "правильные" стримы. Пока никто (ну кроме тебя, конечно) не умеет. P>>>>а что тебе не понятно? ХГ>>>Не понятно как писать такие стримы. P>>а я не говорил что стримы писать нужно именно так ХГ>Т.е., писать такие стримы ты не умеешь, но бездоказательно утверждаешь, что это не только возможно, но и удобно?
с таким тоном и настроем можешь идти куда подальше
Здравствуйте, SilentNoise, Вы писали:
SN>Может кто-нибудь привести примеры кода, где C++ уделает C при условии что это будут семантически эквивалентные программы (а не рантайм факториал в си vs шаблонный факториал C++)?
std::sort быстрее чем qsort потому-что компаратор встраивается (инлайнится) в первом случае, но не во втором. Хотя, строго говоря, это различие относится к стандартным библиотекам, а не к собственно языкам, поскольку на C тоже можно написать алгоритм сортировки в виде макроса компаратор для которого будет определяться (в клиентском коде) при помощи #define. Другое дело, что в том, что касается их использования, такие макроалгоритмы (еще) хуже шаблонов C++.
Здравствуйте, dilmah, Вы писали:
ХГ>>Первое, что в голову приходит — это сортировка. Ну и вообще шаблоны + встраивание пользовательского предиката в C++ vs. функция + коллбэк в C. D>в некоторых производительных библиотеках на С сортировку делали макросами
делали.. я ещё видел так делали red-black tree's. да и думаю много ещё чего делали.
но вот сделать на макросах несколько уровней такой абстракции будет на порядки тяжелей чем на C++.
Вот та же сортировка — что получится на макросах если попытаться абстрагироваться одновременно от последовательности (то есть не тупо массивы), от типа элемента контейнера, и от функции сравнения? уже не сладко, а вот добавь ещё пару уровней абстракции, будет ещё веселей.
Когда в C++ эти абстракции естественны + отлично оптимизируются. Вот например, посмотри на ассемблерный код цикла с итераторами. все эти вызовы "функций" ctor, copy ctor, dtor, operator++, operator+=, operator*, operator!= транслируются в отдельные ассемблерные инструкции, а то и убиваются вовсе.
P>всё однозначно, RAII рулит. P>1. без RAII в КАЖДОЙ функции которая как-то создаёт/удаляет ресурсы нужно лепить try/using_with_resources/или_как_их_там P>2. С RAII, когда ты используешь какой-либо объект, тебе абсолютно пофиг есть ли в нём какие-либо ресурсы или нет. Без RAII ты должен проверять, есть ли у этого объекта ресурсы или нет, так как если есть, то сам этот объект становится ресурсом (весело будет, когда ресурсы добавятся в объект после того, как его уже используют) — и всё, вся инкапсуляция летит к хреням собачим.
А с RAII вдруг выясняется, что какой-нибудь там стрим при закрытии не получилось флашнуть на диск. И как результат из деструктора летит исключение, и опять и всё летит к хреням собачим. Или, как альтернатива — мы эту ошибку игнорируем и все опять работает не правильно. Потому что никакой инкапсуляции, оказывается, и сроду не было.
Причем, если бы инкапсуляции не было сразу, и с ресурсом обращались бы как с ресурсом, то программа по крайней мере работала бы.
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Периодически встречаю мнение, что C++ потенциально может быть соптимизирован лучше, чем C, в силу каких-то своих особенностей.
Может кто-нибудь привести примеры кода, где C++ уделает C при условии что это будут семантически эквивалентные программы (а не рантайм факториал в си vs шаблонный факториал C++)?
P.S. действительно интересно, так ли это, но т.к. топик всеравно скатится в холивар C vs C++, сразу создаю его в КСВ :)
Здравствуйте, SilentNoise, Вы писали:
SN>Периодически встречаю мнение, что C++ потенциально может быть соптимизирован лучше, чем C, в силу каких-то своих особенностей. SN>Может кто-нибудь привести примеры кода, где C++ уделает C при условии что это будут семантически эквивалентные программы (а не рантайм факториал в си vs шаблонный факториал C++)?
Здравствуйте, SilentNoise, Вы писали:
SN>Периодически встречаю мнение, что C++ потенциально может быть соптимизирован лучше, чем C, в силу каких-то своих особенностей. SN>Может кто-нибудь привести примеры кода, где C++ уделает C при условии что это будут семантически эквивалентные программы (а не рантайм факториал в си vs шаблонный факториал C++)?
SN>P.S. действительно интересно, так ли это, но т.к. топик всеравно скатится в холивар C vs C++, сразу создаю его в КСВ
Первое, что в голову приходит — это сортировка. Ну и вообще шаблоны + встраивание пользовательского предиката в C++ vs. функция + коллбэк в C.
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Здравствуйте, SilentNoise, Вы писали:
SN>Может кто-нибудь привести примеры кода, где C++ уделает C при условии что это будут семантически эквивалентные программы (а не рантайм факториал в си vs шаблонный факториал C++)?
Ну от коммпилятора зависит, но значительная часть примеров будет про "шаблонный факториал" против "рантайм".
Доп возможности по оптимизации в С++ как раз и лежат в области переноса чего-то в CT...
Скажем статический полиморфизм на шаблонах (как в CRTP, например) против вплне так себе динамического в С, скажем на COM-образной технике...
Или С-шный переаллокируемый массив против С++ного-шаблонного.
Правда в С++ есть такойвстроенный пессимизатор, как STL, но он же и оптимиатор при ВЕРНОМ использовании. Так что быстру программу на С++ написать в цеом сложнее.
Ещё есть тема обработки ошибок, кстати. В целом есть такие реализации исключений, что пока исключения не наступают, код получается быстрее, чем ЭКВИВАЛЕНТНЫЙ на кодах возврата...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, SilentNoise, Вы писали:
SN>Периодически встречаю мнение, что C++ потенциально может быть соптимизирован лучше, чем C, в силу каких-то своих особенностей. SN>Может кто-нибудь привести примеры кода, где C++ уделает C при условии что это будут семантически эквивалентные программы (а не рантайм факториал в си vs шаблонный факториал C++)?
SN>P.S. действительно интересно, так ли это, но т.к. топик всеравно скатится в холивар C vs C++, сразу создаю его в КСВ
Как я понимаю, за счёт шаблонов и встраивания можно получить код оптимальнее. Возможно, за счёт реорганизации обработки ошибок и использования искоючений можно сэкономить ещё немного тактов.
Здравствуйте, Erop, Вы писали:
E>Ещё есть тема обработки ошибок, кстати. В целом есть такие реализации исключений, что пока исключения не наступают, код получается быстрее, чем ЭКВИВАЛЕНТНЫЙ на кодах возврата...
Здравствуйте, Mystic, Вы писали:
M>Вполне можно заюзать longjmp.
Если можно в С, то можно и в С++...
Мы же об ЭКВИВАЛЕНТНЫХ программах, или уже нет?..
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, SilentNoise, Вы писали:
SN>Периодически встречаю мнение, что C++ потенциально может быть соптимизирован лучше, чем C, в силу каких-то своих особенностей. SN>Может кто-нибудь привести примеры кода, где C++ уделает C при условии что это будут семантически эквивалентные программы (а не рантайм факториал в си vs шаблонный факториал C++)?
Шаблоны. Про сортировку и встраивание сказали. Можно про dead code elimination сказать(хотя оно не так заметно, если не в цикле вызывать по сотни раз). Взять к примеру rapid xml. Там сплошь и рядом такой код
template<int Flags>
static void insert_coded_character(Ch *&text, unsigned long code){
if (Flags & parse_no_utf8){
блабла
} else {
блабла
}
}
Компилятор легко и непринужденно может выкинуть сравнение и одну из then/else ветвей. На си через макросы это делать наверняка не стали бы и просто передали flags как аргумент функции => лишнее сравнение(да ещё место в стеке/регистре заняли). Без шаблонов сделать качественный DCE сложнее.
Здравствуйте, SilentNoise, Вы писали:
SN>Периодически встречаю мнение, что C++ потенциально может быть соптимизирован лучше, чем C, в силу каких-то своих особенностей. SN>Может кто-нибудь привести примеры кода, где C++ уделает C при условии что это будут семантически эквивалентные программы (а не рантайм факториал в си vs шаблонный факториал C++)?
SN>P.S. действительно интересно, так ли это, но т.к. топик всеравно скатится в холивар C vs C++, сразу создаю его в КСВ
всё просто.
В С++ более сильная система типов чем в Си, по этому компилятор С++ имеет больше информации о коде и может делать более эффективные оптимизации.
Здравствуйте, Abyx, Вы писали:
A>В С++ более сильная система типов чем в Си, по этому компилятор С++ имеет больше информации о коде и может делать более эффективные оптимизации.
Это утверждение тоже сильное, но пока голословное. Давай пример.
Здравствуйте, Mystic, Вы писали:
E>>Мы же об ЭКВИВАЛЕНТНЫХ программах, или уже нет?..
M>Ну правильно. Блоку try/catch эквивалентен longjump в C. А коды возврата есть и там и там
Не совсем так. Потому, что есть ещё освобождение ресурсов...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Mystic, Вы писали:
M>А это считай еще один неявный try/catch, т. е. longjump. Просто все неявное придется реализовывать явно.
Дык это окажется дороже, чем исключения...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, igna, Вы писали:
I>Здравствуйте, Abyx, Вы писали:
A>>В С++ более сильная система типов чем в Си, по этому компилятор С++ имеет больше информации о коде и может делать более эффективные оптимизации.
I>Это утверждение тоже сильное, но пока голословное. Давай пример.
пример — это статика vs динамика, например компиляторы С++ обычно инлайнят вызовы Сallable типов, а компиляторы обычно Си не инлайнят вызовы через указатель на функцию.
чем больше кода инлайнится — тем больше кода можно проанализировать.
если что-то известно на этапе компиляции — то можно не генерить код, определяющий это динамически.
если известно, что размер массива меньше 8 байт, можно скопировать его одной инструкцией, а не вызывая memcpy.
всякие явные `restrict` иногда могут быть не нужны, если компилятор сам может отследить что куски памяти не перекрываются. для этого ему надо видеть откуда взялась память, и не терять информацию о типах
и т.п.
Здравствуйте, SilentNoise, Вы писали:
SN>Периодически встречаю мнение, что C++ потенциально может быть соптимизирован лучше, чем C, в силу каких-то своих особенностей.
Штуки, приходящие на ум:
rvalue references, move constructors, return value optimization, классы для работы с SIMD. Что из этого есть в голом Си? Я не в курсе как-то.
Здравствуйте, SilentNoise, Вы писали:
SN>Периодически встречаю мнение, что C++ потенциально может быть соптимизирован лучше, чем C, в силу каких-то своих особенностей. SN>Может кто-нибудь привести примеры кода, где C++ уделает C при условии что это будут семантически эквивалентные программы (а не рантайм факториал в си vs шаблонный факториал C++)?
У меня были специализорованные под каждый тип SIMD классы, которые делали БВП, на С пришлось бы еще в рантайме выбирать в зависимости от размера и разрядности элемента.
Здравствуйте, D. Mon, Вы писали:
DM>классы для работы с SIMD
Не знаю насчет остального — но для SIMD можно использовать либо интринсики gcc, либо хинты для авто-векторизации. Да, непортабельно, но раз уж начали оптимизировать с применением SIMD — оно скорее всего и так уже непортабельно :)
Здравствуйте, Abyx, Вы писали:
A>пример — это статика vs динамика, например компиляторы С++ обычно инлайнят вызовы Сallable типов, а компиляторы обычно Си не инлайнят вызовы через указатель на функцию.
gcc обычно таки инлайнит даже при вызове через указатель, если он может определить откуда этот указатель пришел.
Легко проверить, объявив функцию как inline и скомпилировав с -Winline.
Здравствуйте, SilentNoise, Вы писали:
SN>Здравствуйте, D. Mon, Вы писали:
DM>>классы для работы с SIMD
SN>Не знаю насчет остального — но для SIMD можно использовать либо интринсики gcc, либо хинты для авто-векторизации. Да, непортабельно, но раз уж начали оптимизировать с применением SIMD — оно скорее всего и так уже непортабельно
Это все используется, но с C++ гораздо удобнее, чем с обычным с, где надо либо в рантайме решать что тебе надо, либо в режиме компиляции вручную следить что ты компиляешь.
Здравствуйте, dеnisko, Вы писали:
D>Это все используется, но с C++ гораздо удобнее, чем с обычным с, где надо либо в рантайме решать что тебе надо, либо в режиме компиляции вручную следить что ты компиляешь.
Это само собой, а на более других языках, возможно, еще удобнее чем в С++ :) Но речь то об оптимизациях.
Здравствуйте, D. Mon, Вы писали:
DM>Штуки, приходящие на ум: DM>rvalue references, move constructors, return value optimization, классы для работы с SIMD. Что из этого есть в голом Си? Я не в курсе как-то.
Ну, там всё это просто придётся фигачить врукопашную.
Здравствуйте, Ops, Вы писали:
Ops>Зачем? Если бы не было RAII, исключения в плюсах нахрен бы никому не сдались, были бы те же коды возврата.
Здрасте!
Банальный пример: return из середины функции, где по дороге нахапано ресурсов которые надо освобождать.
С RAII я просто пишу return — и всё освободится само.
Когда пишу на С мне RAII очень сильно не хватает.
Здравствуйте, Трололоша, Вы писали:
Т>Когда пишу на С мне RAII очень сильно не хватает.
Можно наколбасить подобие пулов ресурсов как в APR. Сильно выручает, +region-based memory allocation.
Здравствуйте, Трололоша, Вы писали:
Т>Здрасте! Т>Банальный пример: return из середины функции, где по дороге нахапано ресурсов которые надо освобождать. Т>С RAII я просто пишу return — и всё освободится само. Т>Когда пишу на С мне RAII очень сильно не хватает.
И? Я про то, что без RAII нет смысла для обработки ошибок что-то делать на sj/lj, потому что без него и исключения будут неудобны.
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Здравствуйте, SilentNoise, Вы писали:
SN>Здравствуйте, dеnisko, Вы писали:
D>>Это все используется, но с C++ гораздо удобнее, чем с обычным с, где надо либо в рантайме решать что тебе надо, либо в режиме компиляции вручную следить что ты компиляешь.
SN>Это само собой, а на более других языках, возможно, еще удобнее чем в С++ Но речь то об оптимизациях.
Ты получаешь не меньшую скорость при гораздо большем удобстве, по-моему это и есть самая оптимизабельная оптимизация. Ну для примера, вот у тебя есть задача реализовать свертку на интринсиках для 1,2,4 байтовых целых, приведи решение на с, увидишь что иметься для поддержания целостности программы придется очень много.
Здравствуйте, SilentNoise, Вы писали:
Т>>Когда пишу на С мне RAII очень сильно не хватает. SN>Можно наколбасить подобие пулов ресурсов как в APR. Сильно выручает, +region-based memory allocation.
Мне не тока для memory, мне ещё для всякого рода handles и для структур.
Здравствуйте, Ops, Вы писали:
Ops>Здравствуйте, Abyx, Вы писали:
A>>не было бы RAII — был бы finally или on error и те же самые исключения
Ops>Это что же, весь стек вызовов оборачивать? Ужоснах.
нет, надо оборачивать только куски где надо освободить ресурс.
никогда чтоли не видели языков с finally? или __finally в том же Си
Здравствуйте, Abyx, Вы писали:
Ops>>Это что же, весь стек вызовов оборачивать? Ужоснах.
A>нет, надо оборачивать только куски где надо освободить ресурс. A>никогда чтоли не видели языков с finally? или __finally в том же Си
Так с RAII об этом вообще думать не нужно, если в какой-то функции нас не интересуют исключения вызываемой, то никакую дополнительную обработку писать не надо, а обработают, если надо, уровнем выше. Ну и вложенные try...finally, когда ресурсов несколько, тоже не добавляют удобства и читаемости. ИМХО, исключения без RAII очень неудобны.
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Здравствуйте, Трололоша, Вы писали:
Ops>>Зачем? Если бы не было RAII, исключения в плюсах нахрен бы никому не сдались, были бы те же коды возврата. Т>Здрасте! Т>Банальный пример: return из середины функции, где по дороге нахапано ресурсов которые надо освобождать. Т>С RAII я просто пишу return — и всё освободится само. Т>Когда пишу на С мне RAII очень сильно не хватает.
и при чём тут оптимизация и исключения?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Ops, Вы писали:
A>>не было бы RAII — был бы finally или on error и те же самые исключения Ops>Это что же, весь стек вызовов оборачивать? Ужоснах.
ну в Java/C# нет RAII — там ёжики грызут кактус в виде finaly, using, try with resources, или как их там.
мне их жалко, честно
ХГ>>Первое, что в голову приходит — это сортировка. Ну и вообще шаблоны + встраивание пользовательского предиката в C++ vs. функция + коллбэк в C.
D>в некоторых производительных библиотеках на С сортировку делали макросами
Ну вообще-то существуют задачи и по неприятнее сортировки. С макросами там будет аццкий ад, а с шаблонами — терпимо.
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Здравствуйте, Piko, Вы писали:
A>>>не было бы RAII — был бы finally или on error и те же самые исключения Ops>>Это что же, весь стек вызовов оборачивать? Ужоснах.
P>ну в Java/C# нет RAII — там ёжики грызут кактус в виде finaly, using, try with resources, или как их там. P>мне их жалко, честно
Вот кстати все не так однозначно, если вспомнить про исключения из деструкторов. Может finaly то и правильнее.
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Здравствуйте, Хон Гильдон, Вы писали:
A>>>>не было бы RAII — был бы finally или on error и те же самые исключения Ops>>>Это что же, весь стек вызовов оборачивать? Ужоснах. P>>ну в Java/C# нет RAII — там ёжики грызут кактус в виде finaly, using, try with resources, или как их там. P>>мне их жалко, честно ХГ>Вот кстати все не так однозначно, если вспомнить про исключения из деструкторов. Может finaly то и правильнее.
всё однозначно, RAII рулит.
1. без RAII в КАЖДОЙ функции которая как-то создаёт/удаляет ресурсы нужно лепить try/using_with_resources/или_как_их_там
2. С RAII, когда ты используешь какой-либо объект, тебе абсолютно пофиг есть ли в нём какие-либо ресурсы или нет. Без RAII ты должен проверять, есть ли у этого объекта ресурсы или нет, так как если есть, то сам этот объект становится ресурсом (весело будет, когда ресурсы добавятся в объект после того, как его уже используют) — и всё, вся инкапсуляция летит к хреням собачим.
Здравствуйте, Хон Гильдон, Вы писали:
ХГ>А с RAII вдруг выясняется, что какой-нибудь там стрим при закрытии не получилось флашнуть на диск. И как результат из деструктора летит исключение, и опять и всё летит к хреням собачим.
Здравствуйте, Хон Гильдон, Вы писали:
ХГ>А с RAII вдруг выясняется, что какой-нибудь там стрим при закрытии не получилось флашнуть на диск.
а если без шуток, то эта проблема от того, что в этом деструкторе происходит попытка захвата новых ресурсов.
классы должны сохранять инварианты, и должны находится в нормальном состоянии с момента их конструкции, вплоть до момента разрушения. в описанном же примере деструктор получает объект в "хорошем" состоянии, и сам же его портит.
ХГ>>А с RAII вдруг выясняется, что какой-нибудь там стрим при закрытии не получилось флашнуть на диск.
P>а если без шуток, то эта проблема от того, что в этом деструкторе происходит попытка захвата новых ресурсов.
Никакого захвата новых ресурсов, только работа с уже захваченными.
P>классы должны сохранять инварианты, и должны находится в нормальном состоянии с момента их конструкции, вплоть до момента разрушения.
Осталось написать стрим или его клиента (архив для boost::serialization, например), которые так работают. Я таких пока не видел и не думаю, что это возможно.
P>в описанном же примере деструктор получает объект в "хорошем" состоянии, и сам же его портит.
Мало ли, что там должно быть в идеале. На практике, к вводу-выводу RAII плохо применим. Приходится приделывать метод close и дергать его руками.
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Здравствуйте, Хон Гильдон, Вы писали:
ХГ>>>А с RAII вдруг выясняется, что какой-нибудь там стрим при закрытии не получилось флашнуть на диск. P>>а если без шуток, то эта проблема от того, что в этом деструкторе происходит попытка захвата новых ресурсов. ХГ>Никакого захвата новых ресурсов, только работа с уже захваченными.
попытка захватить новое место на диске во время flush'а
P>>классы должны сохранять инварианты, и должны находится в нормальном состоянии с момента их конструкции, вплоть до момента разрушения. ХГ>Осталось написать стрим или его клиента (архив для boost::serialization, например), которые так работают. Я таких пока не видел и не думаю, что это возможно.
легко, flush на каждой записи.
либо вообще маразм в виде постоянного close+repoen
P>>в описанном же примере деструктор получает объект в "хорошем" состоянии, и сам же его портит. ХГ>Мало ли, что там должно быть в идеале. На практике, к вводу-выводу RAII плохо применим. Приходится приделывать метод close и дергать его руками.
ХГ>>>>А с RAII вдруг выясняется, что какой-нибудь там стрим при закрытии не получилось флашнуть на диск. P>>>а если без шуток, то эта проблема от того, что в этом деструкторе происходит попытка захвата новых ресурсов. ХГ>>Никакого захвата новых ресурсов, только работа с уже захваченными.
P>попытка захватить новое место на диске во время flush'а
Это не ресурс в терминах RAII. Да и флаш может быть не на диск а, например, в сокет. Там чего захватываем?
P>>>классы должны сохранять инварианты, и должны находится в нормальном состоянии с момента их конструкции, вплоть до момента разрушения. ХГ>>Осталось написать стрим или его клиента (архив для boost::serialization, например), которые так работают. Я таких пока не видел и не думаю, что это возможно.
P>легко, flush на каждой записи.
Это ничего не гарантирует. Например, у нас стрим вокруг ssl. При "освобождении" данного ресурса хорошо бы ему сделать shutdown.
P>либо вообще маразм в виде постоянного close+repoen
Какое это отношение имеет к RAII? В смысле, какой именно ресурс мы захватываем в конструкторе и освобождаем в деструкторе?
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Здравствуйте, Хон Гильдон, Вы писали:
ХГ>>>>>А с RAII вдруг выясняется, что какой-нибудь там стрим при закрытии не получилось флашнуть на диск. P>>>>а если без шуток, то эта проблема от того, что в этом деструкторе происходит попытка захвата новых ресурсов. ХГ>>>Никакого захвата новых ресурсов, только работа с уже захваченными. P>>попытка захватить новое место на диске во время flush'а ХГ>Это не ресурс в терминах RAII.
смотря как смотреть. файл ведь в деструкторе тоже не удаляется.
ХГ>Да и флаш может быть не на диск а, например, в сокет. Там чего захватываем?
да пофиг что и как, у "правильного" объекта поломка должна быть возможна только до деструктора.
другие "неправильные" тоже могут со-существовать.
P>>>>классы должны сохранять инварианты, и должны находится в нормальном состоянии с момента их конструкции, вплоть до момента разрушения. ХГ>>>Осталось написать стрим или его клиента (архив для boost::serialization, например), которые так работают. Я таких пока не видел и не думаю, что это возможно. P>>легко, flush на каждой записи. ХГ>Это ничего не гарантирует. Например, у нас стрим вокруг ssl. При "освобождении" данного ресурса хорошо бы ему сделать shutdown.
делаешь всё что нужно для поддержания объекта в destructable-non-throwable state.
P>>либо вообще маразм в виде постоянного close+repoen ХГ>Какое это отношение имеет к RAII? В смысле, какой именно ресурс мы захватываем в конструкторе и освобождаем в деструкторе?
Здравствуйте, Piko, Вы писали:
ХГ>>>>>>А с RAII вдруг выясняется, что какой-нибудь там стрим при закрытии не получилось флашнуть на диск. P>>>>>а если без шуток, то эта проблема от того, что в этом деструкторе происходит попытка захвата новых ресурсов. ХГ>>>>Никакого захвата новых ресурсов, только работа с уже захваченными. P>>>попытка захватить новое место на диске во время flush'а ХГ>>Это не ресурс в терминах RAII.
P>смотря как смотреть. файл ведь в деструкторе тоже не удаляется.
Почему именно удаление? Здесь мы вообще не имеем обратной операции.
ХГ>>Да и флаш может быть не на диск а, например, в сокет. Там чего захватываем?
P>да пофиг что и как, у "правильного" объекта поломка должна быть возможна только до деструктора. P>другие "неправильные" тоже могут со-существовать.
Осталось только научиться писать такие вот "правильные" стримы. Пока никто (ну кроме тебя, конечно) не умеет.
P>>>>>классы должны сохранять инварианты, и должны находится в нормальном состоянии с момента их конструкции, вплоть до момента разрушения. ХГ>>>>Осталось написать стрим или его клиента (архив для boost::serialization, например), которые так работают. Я таких пока не видел и не думаю, что это возможно. P>>>легко, flush на каждой записи. ХГ>>Это ничего не гарантирует. Например, у нас стрим вокруг ssl. При "освобождении" данного ресурса хорошо бы ему сделать shutdown.
P>делаешь всё что нужно для поддержания объекта в destructable-non-throwable state.
Как только напишешь "правильный" ssl-stream, который так себя и ведет, я тебе поверю
P>>>либо вообще маразм в виде постоянного close+repoen ХГ>>Какое это отношение имеет к RAII? В смысле, какой именно ресурс мы захватываем в конструкторе и освобождаем в деструкторе?
P>file handle (я же написал — reopen), file name
Это сейчас ты написал reopen, а в прошлый раз было repoen Но все равно ничего не понял. Что за reopen, что он должен делать, при чем тут file name? Пример можешь привести, как это все должно работать? Что именно будет освобождаться в деструкторе и почему того же поведения нельзя добиться без деструктора?
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Здравствуйте, Хон Гильдон, Вы писали:
ХГ>>>Никакого захвата новых ресурсов, только работа с уже захваченными.
P>>попытка захватить новое место на диске во время flush'а
ХГ>Это не ресурс в терминах RAII. Да и флаш может быть не на диск а, например, в сокет. Там чего захватываем?
Если честно, то за подобные выходки из деструкторов нужно сначала долго бить сапогами в живот, а потом разжаловать в старшие помощники младших черпальщиков в ассенизаторском обозе при холерных бараках. Безотносительно того, что захватываем.
Здравствуйте, Хон Гильдон, Вы писали:
ХГ>>>>>>>А с RAII вдруг выясняется, что какой-нибудь там стрим при закрытии не получилось флашнуть на диск. P>>>>>>а если без шуток, то эта проблема от того, что в этом деструкторе происходит попытка захвата новых ресурсов. ХГ>>>>>Никакого захвата новых ресурсов, только работа с уже захваченными. P>>>>попытка захватить новое место на диске во время flush'а ХГ>>>Это не ресурс в терминах RAII. P>>смотря как смотреть. файл ведь в деструкторе тоже не удаляется. ХГ>Почему именно удаление? Здесь мы вообще не имеем обратной операции.
это смотря как flush реализован
ХГ>>>Да и флаш может быть не на диск а, например, в сокет. Там чего захватываем? P>>да пофиг что и как, у "правильного" объекта поломка должна быть возможна только до деструктора. P>>другие "неправильные" тоже могут со-существовать. ХГ>Осталось только научиться писать такие вот "правильные" стримы. Пока никто (ну кроме тебя, конечно) не умеет.
а что тебе не понятно?
P>>>>>>классы должны сохранять инварианты, и должны находится в нормальном состоянии с момента их конструкции, вплоть до момента разрушения. ХГ>>>>>Осталось написать стрим или его клиента (архив для boost::serialization, например), которые так работают. Я таких пока не видел и не думаю, что это возможно. P>>>>легко, flush на каждой записи. ХГ>>>Это ничего не гарантирует. Например, у нас стрим вокруг ssl. При "освобождении" данного ресурса хорошо бы ему сделать shutdown. P>>делаешь всё что нужно для поддержания объекта в destructable-non-throwable state. ХГ>Как только напишешь "правильный" ssl-stream, который так себя и ведет, я тебе поверю
чему ты поверишь?
то, что RAII лучше тех огрызков в Java/C#?
P>>>>либо вообще маразм в виде постоянного close+repoen ХГ>>>Какое это отношение имеет к RAII? В смысле, какой именно ресурс мы захватываем в конструкторе и освобождаем в деструкторе? P>>file handle (я же написал — reopen), file name ХГ>Это сейчас ты написал reopen, а в прошлый раз было repoen Но все равно ничего не понял. Что за reopen, что он должен делать, при чем тут file name?
filename нужен для repoen (ещё раз порадуйся)
ХГ>Пример можешь привести, как это все должно работать?
на каждой записи файл закрывается, и возможно переотркывается.
ХГ>Что именно будет освобождаться в деструкторе и почему того же поведения нельзя добиться без деструктора?
если без repoen, то в деструкторе будет освобождаться file name, и возможно OS-level блокировка.
Здравствуйте, Piko, Вы писали:
ХГ>>>>>>>>А с RAII вдруг выясняется, что какой-нибудь там стрим при закрытии не получилось флашнуть на диск. P>>>>>>>а если без шуток, то эта проблема от того, что в этом деструкторе происходит попытка захвата новых ресурсов. ХГ>>>>>>Никакого захвата новых ресурсов, только работа с уже захваченными. P>>>>>попытка захватить новое место на диске во время flush'а ХГ>>>>Это не ресурс в терминах RAII. P>>>смотря как смотреть. файл ведь в деструкторе тоже не удаляется. ХГ>>Почему именно удаление? Здесь мы вообще не имеем обратной операции.
P>это смотря как flush реализован
Так, как он реализован в std::ofstream — мы же первоначально его обсуждали. Я утверждаю, что этот flush не является захватом ресурсов в терминах RAII, ты утверждаешь обратное.
ХГ>>>>Да и флаш может быть не на диск а, например, в сокет. Там чего захватываем? P>>>да пофиг что и как, у "правильного" объекта поломка должна быть возможна только до деструктора. P>>>другие "неправильные" тоже могут со-существовать. ХГ>>Осталось только научиться писать такие вот "правильные" стримы. Пока никто (ну кроме тебя, конечно) не умеет.
P>а что тебе не понятно?
Не понятно как писать такие стримы.
P>>>>>>>классы должны сохранять инварианты, и должны находится в нормальном состоянии с момента их конструкции, вплоть до момента разрушения. ХГ>>>>>>Осталось написать стрим или его клиента (архив для boost::serialization, например), которые так работают. Я таких пока не видел и не думаю, что это возможно. P>>>>>легко, flush на каждой записи. ХГ>>>>Это ничего не гарантирует. Например, у нас стрим вокруг ssl. При "освобождении" данного ресурса хорошо бы ему сделать shutdown. P>>>делаешь всё что нужно для поддержания объекта в destructable-non-throwable state. ХГ>>Как только напишешь "правильный" ssl-stream, который так себя и ведет, я тебе поверю
P>чему ты поверишь?
Что RAII удобно применять для объектов ввода-вывода, чему же еще.
P>>>>>либо вообще маразм в виде постоянного close+repoen ХГ>>>>Какое это отношение имеет к RAII? В смысле, какой именно ресурс мы захватываем в конструкторе и освобождаем в деструкторе? P>>>file handle (я же написал — reopen), file name ХГ>>Это сейчас ты написал reopen, а в прошлый раз было repoen Но все равно ничего не понял. Что за reopen, что он должен делать, при чем тут file name?
P>filename нужен для repoen (ещё раз порадуйся)
Допустим, нужен (хотя не помешало бы обсудить и сокеты). А захватываем то что?
ХГ>>Пример можешь привести, как это все должно работать?
P>на каждой записи файл закрывается, и возможно переотркывается.
Пример привести не можешь. Понятно.
ХГ>>Что именно будет освобождаться в деструкторе и почему того же поведения нельзя добиться без деструктора?
P>если без repoen, то в деструкторе будет освобождаться file name, и возможно OS-level блокировка.
Не понял — ты строку что ли предлагаешь в деструкторе освобождать? Т.е., для собственно объектов ввода-вывода RAII, получается, не пригоден?
И вообще, давай для полного веселья у нас будет SSL-поток
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Здравствуйте, Хон Гильдон, Вы писали:
P>>это смотря как flush реализован ХГ>Так, как он реализован в std::ofstream — мы же первоначально его обсуждали. Я утверждаю, что этот flush не является захватом ресурсов в терминах RAII, ты утверждаешь обратное.
а я думал мы сферический flush обсуждаем, так как ты скачешь с ssl на сокеты
ХГ>>>>>Да и флаш может быть не на диск а, например, в сокет. Там чего захватываем? P>>>>да пофиг что и как, у "правильного" объекта поломка должна быть возможна только до деструктора. P>>>>другие "неправильные" тоже могут со-существовать. ХГ>>>Осталось только научиться писать такие вот "правильные" стримы. Пока никто (ну кроме тебя, конечно) не умеет. P>>а что тебе не понятно? ХГ>Не понятно как писать такие стримы.
а я не говорил что стримы писать нужно именно так но тем не менее пример стрима без ошибок в деструкторе, я вроде показал
P>>>>>>>>классы должны сохранять инварианты, и должны находится в нормальном состоянии с момента их конструкции, вплоть до момента разрушения. ХГ>>>>>>>Осталось написать стрим или его клиента (архив для boost::serialization, например), которые так работают. Я таких пока не видел и не думаю, что это возможно. P>>>>>>легко, flush на каждой записи. ХГ>>>>>Это ничего не гарантирует. Например, у нас стрим вокруг ssl. При "освобождении" данного ресурса хорошо бы ему сделать shutdown. P>>>>делаешь всё что нужно для поддержания объекта в destructable-non-throwable state. ХГ>>>Как только напишешь "правильный" ssl-stream, который так себя и ведет, я тебе поверю P>>чему ты поверишь? ХГ>Что RAII удобно применять для объектов ввода-вывода, чему же еще.
я вообще этого не утверждал. но тем не менее, в частных случаях (в зависимости от требований) — они могут быть очень удобны
если приведёшь реальный паттерн использования который тебя интересует — мы можем рассмотреть его
P>>>>>>либо вообще маразм в виде постоянного close+repoen ХГ>>>>>Какое это отношение имеет к RAII? В смысле, какой именно ресурс мы захватываем в конструкторе и освобождаем в деструкторе? P>>>>file handle (я же написал — reopen), file name ХГ>>>Это сейчас ты написал reopen, а в прошлый раз было repoen Но все равно ничего не понял. Что за reopen, что он должен делать, при чем тут file name? P>>filename нужен для repoen (ещё раз порадуйся) ХГ>Допустим, нужен (хотя не помешало бы обсудить и сокеты). А захватываем то что?
объект filename + возможно lock файла
ХГ>>>Пример можешь привести, как это все должно работать? P>>на каждой записи файл закрывается, и возможно переотркывается. ХГ>Пример привести не можешь. Понятно.
не вижу в этом нужды, так как считаю что выделенного достаточно
ХГ>>>Что именно будет освобождаться в деструкторе и почему того же поведения нельзя добиться без деструктора? P>>если без repoen, то в деструкторе будет освобождаться file name, и возможно OS-level блокировка. ХГ>Не понял — ты строку что ли предлагаешь в деструкторе освобождать?
lock, строку, handle и любые другие implementation details.
ХГ>Т.е., для собственно объектов ввода-вывода RAII, получается, не пригоден?
зависит от требований
ХГ>И вообще, давай для полного веселья у нас будет SSL-поток
Здравствуйте, Piko, Вы писали:
P>>>это смотря как flush реализован ХГ>>Так, как он реализован в std::ofstream — мы же первоначально его обсуждали. Я утверждаю, что этот flush не является захватом ресурсов в терминах RAII, ты утверждаешь обратное. P>а я думал мы сферический flush обсуждаем, так как ты скачешь с ssl на сокеты
более того, если говорить про std::ofstream — то он мне не нравится, так как допускает, что объект может находится в "плохом" состоянии
P>>>это смотря как flush реализован ХГ>>Так, как он реализован в std::ofstream — мы же первоначально его обсуждали. Я утверждаю, что этот flush не является захватом ресурсов в терминах RAII, ты утверждаешь обратное.
P>а я думал мы сферический flush обсуждаем, так как ты скачешь с ssl на сокеты
Ну попробуй приведи пример реализации flush, действительно захватывающей ресурсы
ХГ>>>>>>Да и флаш может быть не на диск а, например, в сокет. Там чего захватываем? P>>>>>да пофиг что и как, у "правильного" объекта поломка должна быть возможна только до деструктора. P>>>>>другие "неправильные" тоже могут со-существовать. ХГ>>>>Осталось только научиться писать такие вот "правильные" стримы. Пока никто (ну кроме тебя, конечно) не умеет. P>>>а что тебе не понятно? ХГ>>Не понятно как писать такие стримы.
P>а я не говорил что стримы писать нужно именно так
Т.е., писать такие стримы ты не умеешь, но бездоказательно утверждаешь, что это не только возможно, но и удобно?
P>но тем не менее пример стрима без ошибок в деструкторе, я вроде показал
Не было
ХГ>>Что RAII удобно применять для объектов ввода-вывода, чему же еще.
P>я вообще этого не утверждал.
А с чем тогда споришь? Я привел пример именно ввода-вывода, как ситуации, когда RAII слабо подходит.
P>но тем не менее, в частных случаях (в зависимости от требований) — они могут быть очень удобны P>если приведёшь реальный паттерн использования который тебя интересует — мы можем рассмотреть его
Ну допустим нам нужно записать некий текст в некое устройство. Текст формируется сложным образом, в памяти единым куском не присутствует (например, большой очень). Что за устройство, наша подсистема не знает — может, диск, может сеть, может 3-d принтер. В случае возникновения ошибки информацию о ней надо показать пользователю. Максимально подробно, чтобы он догадался, что у него сломалось и мог уничтожать ошибочные результаты, после чего запустить задачу заново. Я утверждаю:
RAII для обращения с таким неизвестным устройством приносит больше вреда, чем пользы.
это частая задача, и RAII ошибочно применяется тоже часто.
ХГ>>Пример привести не можешь. Понятно.
P>не вижу в этом нужды, так как считаю что выделенного достаточно
Конечно, а то эдак и неправоту признать придется
ХГ>>>>Что именно будет освобождаться в деструкторе и почему того же поведения нельзя добиться без деструктора? P>>>если без repoen, то в деструкторе будет освобождаться file name, и возможно OS-level блокировка. ХГ>>Не понял — ты строку что ли предлагаешь в деструкторе освобождать?
P>lock, строку, handle и любые другие implementation details.
А хрен ли handle не освобождать в close? Зачем до деструктора откладывать?
ХГ>>Т.е., для собственно объектов ввода-вывода RAII, получается, не пригоден?
P>зависит от требований
Ну давай, придумай такие требования, при которых RAII подходит для объектов ввода-вывода. А я оценю, насколько они часто встречаются в моей практике. Глядишь, вместо тупого срача и жонглирования словами кто-нибудь сможет извлечь для себя что-то новое
ХГ>>И вообще, давай для полного веселья у нас будет SSL-поток
P>давай, приведи пример использования и требования
См. выше.
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
L>>Если честно, то за подобные выходки из деструкторов нужно сначала долго бить сапогами в живот, а потом разжаловать в старшие помощники младших черпальщиков в ассенизаторском обозе при холерных бараках. Безотносительно того, что захватываем.
ХГ>Попробуй объяснить это авторам стандартной библиотеки Да заодно и бустоводам.
Здравствуйте, landerhigh, Вы писали:
L>>>Если честно, то за подобные выходки из деструкторов нужно сначала долго бить сапогами в живот, а потом разжаловать в старшие помощники младших черпальщиков в ассенизаторском обозе при холерных бараках. Безотносительно того, что захватываем.
ХГ>>Попробуй объяснить это авторам стандартной библиотеки Да заодно и бустоводам.
L>А можно с этого места поподробнее?
В смысле — подробно объяснить, при каких условиях ofstream может кидать исключение из деструктора? Воспользуйся лучше поиском, я в форуме то ли cpp, то ли cpp.applied это буквально пару недель назад объяснял.
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Здравствуйте, Хон Гильдон, Вы писали:
L>>А можно с этого места поподробнее?
ХГ>В смысле — подробно объяснить, при каких условиях ofstream может кидать исключение из деструктора? Воспользуйся лучше поиском, я в форуме то ли cpp, то ли cpp.applied это буквально пару недель назад объяснял.
Раз сам кидал, то может сам и ссылку приведешь? А то найду, да не то.
ХГ>>В смысле — подробно объяснить, при каких условиях ofstream может кидать исключение из деструктора? Воспользуйся лучше поиском, я в форуме то ли cpp, то ли cpp.applied это буквально пару недель назад объяснял.
L>Раз сам кидал, то может сам и ссылку приведешь? А то найду, да не то.
Да, зело ленив Деструктор ofstream кидает исключения, если флаги, разрешающие исключения установлены, и при записи, осуществляемой перед закрытием файла, произошло исключение.
Аналогичные проблемы есть, например, у архивов из boost::serialization в некоторых версиях. Потом проблему типа пофиксили — стали исключения глотать Та же фигня с сокетами asio. В общем, в библиотеках такое сплошь и рядом.
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.