Давно не программировал, поэтому если встретятся фактические ошибки, делающие неверной цепь рассуждений, просьба просто указать на них. Если это трюизмы (== баян, если в словарь лазить лень), то причина в том же.
Насколько мне известно, память в языках типа Явы или Шарпа — не ресурс. Вернее, ресурс, но управляет им некая внешняя по отношению к программе штуковина — рантайм или виртуальная машина, или еще какой контейнер.
У программистов на плюсах был излюбленный прием — использовать пару конструктор-деструктор для контроля за выходом из блока кода. Например, CWaitCursor() делал запрос к API на отрисовку песочных часов, а ~CWaitCursor() вертал все в зад. Соответственно, можно было разместить на стеке анонимный объект в любом блоке, который управлял курсором автоматически и этот трюк был эксепшено-безопасным, что немаловажно. Конструкции finally не требовалось.
Теперь объекты размещаются в куче, но время их уничтожения недетерминировано.
Почему не ввести вместо using на такой случай специальный тип — стековый класс? Это ведь не потребует усложнения синтаксиса. Просто у структуры появится деструктор с детерминированным временем вызова.
Здравствуйте, PC Car, Вы писали:
PC>Почему не ввести вместо using на такой случай специальный тип — стековый класс? Это ведь не потребует усложнения синтаксиса. Просто у структуры появится деструктор с детерминированным временем вызова.
Вообще насчет баяна ты угадал
То есть ты предлагаешь создать типы которые можно располагать только на стеке? И ты думаешь это полетит (в смысле покроет потребности)?
Оставим в покое песочные часы и возьмем SomeConnection к примеру.
Хранить ее только на стеке? Спасибо не надо...
Разрешим хранить в куче? Привет using...
Здравствуйте, PC Car, Вы писали:
PC>Почему не ввести вместо using на такой случай специальный тип — стековый класс? Это ведь не потребует усложнения синтаксиса. Просто у структуры появится деструктор с детерминированным временем вызова.
В C++/CLI так и сделано. Жить от это особо лучше не стало. По крайней это не компенсировало отсуствия в C++/CLI других полезных свойств Шарпа.
На самом деле после некоторого опыта использования управляемых языков понимашь, что страхи плюсовиков (коим я являлся до перехода на управляемые среды) сильно надуманы. 99% контроля ресурсов — это контроль памяти. А когда память не нужно пасти, то остальное можно хоть руками контролировать. В общем using-а за глаза хватает.
Ну, а стековый объект все равно не всегда поможет. Ведь если время жизни объекта не совпадает с временем проведенным в процедуре, то и контролировать его так не выйдет.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Сборщик мусора и размещение объектов в стеке
Здравствуйте, GarryIV, Вы писали:
GIV>Оставим в покое песочные часы и возьмем SomeConnection к примеру.
GIV>Хранить ее только на стеке? Спасибо не надо... GIV>Разрешим хранить в куче? Привет using...
Почему бы не разрешить хранить только на стеке? А если всё же "Спасибо не надо... ", то разрешаешь хранить на стеке объект, который в конструкторе получает соединение из пула, а в деструкторе возвращает в пул.
В отношении Java 6 нечто подобное (оптимизация под названием Escape-анализ) уже реальность:
Стековая аллокация
C++ предлагает программистам на выбор аллокацию объектов в массиве или в стеке. Стековая аллокация является эффективной: аллокация недорога, затраты на деаллокацию почти равны нулю, а язык помогает демаркировать жизненные циклы объекта, снижая риск того, что объект забудут освободить. С другой стороны, в C++ вам нужно быть очень осторожными при публикации или совместном использовании ссылок на стековые объекты, потому что стековые объекты автоматически освобождаются, когда стековый фрейм раскрывается, приводя к появлению неработающих ссылок.
Другим преимуществом стековой аллокации является то, что она гораздо более удобна для кэша. В современных процессорах цена кэш-промахов весьма значительна, следовательно, если язык и рабочий цикл могут помочь вашей программе достичь лучшей локализации данных, то производительность улучшится. Верхушка стека почти всегда "горячая" в кэше, тогда как верхушка массива почти всегда "холодная" (потому что наверняка прошло достаточно времени с тех пор, как использовалась эта память). В результате аллокация объекта в массиве, скорее всего, повлечет за собой больше кэш-промахов, чем аллокация объекта в стеке.
Плохо то, что кэш-промах при аллокации объекта в массиве имеет особенно опасное взаимодействие с памятью. При аллокации памяти из массива содержимое данной памяти является мусором — любые биты, оставшиеся после того, как память использовалась в последний раз. Если вы размещаете блок памяти в массиве, который еще не находится в кэше, при выполнении возможны зависания, пока содержимое данной памяти будет переноситься в кэш. Затем вы немедленно перепишете эти значения, которые вы затратили на то, чтобы перенести в кэш с нулями или другими исходными данными, а это приводит к большим потерям работы памяти. (Некоторые процессоры, такие как Azul's Vega, включают аппаратную поддержку для ускорения аллокации массива).
Escape-анализ
Язык Java не предлагает никакого способа точно расположить объект в стеке, но этот факт не мешает JVM использовать стековую аллокацию, где это уместно. JVM может использовать технологию, именуемую escape-анализ, с помощью которой можно сказать, что определенные объекты удерживаются в одном потоке в течение всего жизненного цикла, а он связан со временем существования данного стекового фрейма. Такие объекты можно безопасно располагать в стеке вместо массива. Что даже лучше для маленьких объектов, JVM может полностью оптимизировать аллокацию и просто поднять поля объекта в списки.
(прим. ред. — далее приводятся примеры с псевдокодом оптимизации)
...
Escape-анализ в Mustang
Escape-анализ является оптимизацией, о которой уже давно говорилось, и наконец-то вот она — текущие сборки Mustang (Java SE 6) могут осуществлять escape-анализ и конвертировать аллокацию массива в стековую аллокацию (или без аллокации) там, где это уместно. Использование escape-анализа для устранения некоторых результатов аллокаций с более быстрым средним временем аллокации, уменьшенным потреблением ОЗУ и меньшим количеством кэш-промахов. Кроме этого, оптимизирование некоторых аллокаций уменьшает давление на сборщик мусора и позволяет реже запускать сборку.
Здравствуйте, PC Car, Вы писали:
PC>Почему не ввести вместо using на такой случай специальный тип — стековый класс? Это ведь не потребует усложнения синтаксиса. Просто у структуры появится деструктор с детерминированным временем вызова.
А ты дальше подумай — что делать, если эта структура будет полем класса, уничтожение которого недетерминировано?
Здравствуйте, VladD2, Вы писали:
VD>На самом деле после некоторого опыта использования управляемых языков понимашь, что страхи плюсовиков (коим я являлся до перехода на управляемые среды) сильно надуманы. 99% контроля ресурсов — это контроль памяти. А когда память не нужно пасти, то остальное можно хоть руками контролировать. В общем using-а за глаза хватает.
Ресурсами, которые контролируются стековым объектом, могут быть не только такие объекты как соединение, файл и т.д.
Техника значительно шире. Например, с помощью стекового объекта может контролироваться временный перевод курсора в "часики", блокировка/разблокировка мьютекса, задержка/возобновление обновления графического элемента управления, резервирование/разрезервирование какого-либо места/счётчика и т.д. и т.д.
Так же техника применяется для обеспечения транзакционности, когда действие, выполняемое в деструкторе объекта, отменяется методом commit(). Например транзакционная вставка в 3 контейнера (всё или ничего):
Если у объекта типа push_back_tx не был вызван метод commit(), то в деструкторе он удаляет из контейнера элемент, который вставил в конструкторе.
Как это будет выглядеть в языке без стековой семантики? Я не видел красивого и *масштабируемого* решения.
Такие приёмы делают разработку не только проще и приятней, но так же, что не менее важно, автоматически обеспечивают надёжность и робустность кода. Если в языке без исключений стековая семантика могла бы являться приятной фичей, то в языке с исключениями стековая семантика — необходимое условие разработки надёжного кода.
VD>Ну, а стековый объект все равно не всегда поможет. Ведь если время жизни объекта не совпадает с временем проведенным в процедуре, то и контролировать его так не выйдет.
Хммм... Такие заявления ставят под сомнение твоё умение программировать на языках со стековой семантикой...
Если время жизни объекта не совпадает с временем проведенным в процедуре, то объект создаётся в динамической памяти, а на стеке создаётся объект, контролирующий время жизни первого объекта:
Здравствуйте, rsn81, Вы писали:
R>Здравствуйте, PC Car, Вы писали:
R>В отношении Java 6 нечто подобное (оптимизация под названием Escape-анализ) уже реальность:[q]Стековая аллокация
LOL
Как сделать хорошо? Вначале сделайте плохо, а потом сделайте как было.
Вначале ввели аллокацию на стеке, потом ручное управление памятью... Осталось только union'ы вернуть
Здравствуйте, remark, Вы писали:
R>LOL R>Как сделать хорошо? Вначале сделайте плохо, а потом сделайте как было. R>Вначале ввели аллокацию на стеке, потом ручное управление памятью... Осталось только union'ы вернуть R>
Иронию не догнал: ручную-детерминированную аллокацию на стеке никто и не обещал, а про ручное управление памятью вообще не понял. Так что чего-то вы не по теме радуетесь.
Re[4]: Сборщик мусора и размещение объектов в стеке
Здравствуйте, rsn81, Вы писали:
R>Здравствуйте, remark, Вы писали:
R>>LOL R>>Как сделать хорошо? Вначале сделайте плохо, а потом сделайте как было. R>>Вначале ввели аллокацию на стеке, потом ручное управление памятью... Осталось только union'ы вернуть R>> R>Иронию не догнал: ручную-детерминированную аллокацию на стеке никто и не обещал, а про ручное управление памятью вообще не понял. Так что чего-то вы не по теме радуетесь.
Ищи по "The Real-Time Specification for Java". Фактически они добавили синхронное освобождение памяти — схема применяемая в современном С++.
Здравствуйте, remark, Вы писали:
R>Ищи по "The Real-Time Specification for Java". Фактически они добавили синхронное освобождение памяти — схема применяемая в современном С++.
Нет. В realtime Java _нет_ синхронного освобождения памяти — это сделать в общем случае чрезвычайно дорого. Для realtime Java гарантируются только верхние границы на время отклика сборщика мусора, ничего более.
Sapienti sat!
Re[2]: Сборщик мусора и размещение объектов в стеке
Здравствуйте, Cyberax, Вы писали:
C>Здравствуйте, PC Car, Вы писали:
PC>>Почему не ввести вместо using на такой случай специальный тип — стековый класс? Это ведь не потребует усложнения синтаксиса. Просто у структуры появится деструктор с детерминированным временем вызова. C>А ты дальше подумай — что делать, если эта структура будет полем класса, уничтожение которого недетерминировано?
И что? Если ее создали на стеке — ведет себя как стековый объект. Если нет — ну нет так нет. В C++\CLI именно так и работает.
Re[3]: Сборщик мусора и размещение объектов в стеке
Здравствуйте, Константин Л., Вы писали:
C>>А ты дальше подумай — что делать, если эта структура будет полем класса, уничтожение которого недетерминировано? КЛ>И что? Если ее создали на стеке — ведет себя как стековый объект. Если нет — ну нет так нет. В C++\CLI именно так и работает.
Осталось сделать следующий шаг, и понять, что стековые объекты не нужны — достаточно паттерна Disposable и сахара в виде using().
Sapienti sat!
Re[5]: Сборщик мусора и размещение объектов в стеке
Здравствуйте, remark, Вы писали:
R>Ищи по "The Real-Time Specification for Java". Фактически они добавили синхронное освобождение памяти — схема применяемая в современном С++.
Java RTS и Java SE — как говорится найти 10 отличий. Причем тут оно?
И потом, RTS вроде какой-то древнючий JRS-... какой-то там чуть не под первым номером с коммерческой реализацией, а я говорил про Java SE 6.
Re[4]: Сборщик мусора и размещение объектов в стеке
Здравствуйте, Cyberax, Вы писали:
C>Осталось сделать следующий шаг, и понять, что стековые объекты не нужны — достаточно паттерна Disposable и сахара в виде using().
Не нужны кому, программисту просто как сахар? Ну тогда да. В принципе, и без конструкции using даже можно жить не чихая.
Здравствуйте, remark, Вы писали:
R>Техника значительно шире. Например, с помощью стекового объекта может контролироваться временный перевод курсора в "часики", блокировка/разблокировка мьютекса, задержка/возобновление обновления графического элемента управления, резервирование/разрезервирование какого-либо места/счётчика и т.д. и т.д.
Это прекрасно реализуется при помощи using. Более того, именно для таких фич using предпочтительнее, потому что явно выделяет регион действия и при чтении сразу видно, что и как происходит.
R>Так же техника применяется для обеспечения транзакционности, когда действие, выполняемое в деструкторе объекта, отменяется методом commit().
Вот как раз под рукой из DSL Tools:
using (var tran = partition.Store.TransactionManager.BeginTransaction())
{
...
tran.Commit();
}
R> Например транзакционная вставка в 3 контейнера (всё или ничего): R>
R>Если у объекта типа push_back_tx не был вызван метод commit(), то в деструкторе он удаляет из контейнера элемент, который вставил в конструкторе. R>Как это будет выглядеть в языке без стековой семантики? Я не видел красивого и *масштабируемого* решения.
Аналогично
using (var tx1 = v1.TxPushBack(1))
using (var tx2 = v2.TxPushBack(2))
{
v3.PushBack(3);
tx1.Commit();
tx2.Commit();
}
R>Хммм... Такие заявления ставят под сомнение твоё умение программировать на языках со стековой семантикой... R>Если время жизни объекта не совпадает с временем проведенным в процедуре, то объект создаётся в динамической памяти, а на стеке создаётся объект, контролирующий время жизни первого объекта:
И счетчик с количеством использований? Это, мягко говоря, не очень стыкуется с GC.
R>Такой приём является абсолютно отработанным и обыденным в современном С++. Это не составляет никакой проблемы.
Для этого, помимо стековой семантики, нужен еще и автоматический вызов деструкторов всех членов класса.
... << RSDN@Home 1.2.0 alpha rev. 725 on Windows Vista 6.0.6000.0>>
Здравствуйте, Cyberax, Вы писали:
C>Здравствуйте, Константин Л., Вы писали:
C>>>А ты дальше подумай — что делать, если эта структура будет полем класса, уничтожение которого недетерминировано? КЛ>>И что? Если ее создали на стеке — ведет себя как стековый объект. Если нет — ну нет так нет. В C++\CLI именно так и работает. C>Осталось сделать следующий шаг, и понять, что стековые объекты не нужны — достаточно паттерна Disposable и сахара в виде using().
Шаг к чему? К дао? Достаточно понять, что using менее сладок нежели стековые объекты.
Здравствуйте, remark, Вы писали:
VD>>На самом деле после некоторого опыта использования управляемых языков понимашь, что страхи плюсовиков (коим я являлся до перехода на управляемые среды) сильно надуманы. 99% контроля ресурсов — это контроль памяти. А когда память не нужно пасти, то остальное можно хоть руками контролировать. В общем using-а за глаза хватает.
R>Ресурсами, которые контролируются стековым объектом, могут быть не только такие объекты как соединение, файл и т.д. R>Техника значительно шире. Например, с помощью стекового объекта может контролироваться временный перевод курсора в "часики", блокировка/разблокировка мьютекса, задержка/возобновление обновления графического элемента управления, резервирование/разрезервирование какого-либо места/счётчика и т.д. и т.д.
Тут складывается весьма странная ситуация. Ты рассказываешь мне про то что я и сам пробовал и не согласен с тем, что разве что видел из далека. Продолжай в том же духе. Это очень "конструктивная" позиция.
Здравствуйте, Константин Л., Вы писали:
КЛ>Здравствуйте, Cyberax, Вы писали:
C>>Здравствуйте, Константин Л., Вы писали:
C>>>>А ты дальше подумай — что делать, если эта структура будет полем класса, уничтожение которого недетерминировано? КЛ>>>И что? Если ее создали на стеке — ведет себя как стековый объект. Если нет — ну нет так нет. В C++\CLI именно так и работает. C>>Осталось сделать следующий шаг, и понять, что стековые объекты не нужны — достаточно паттерна Disposable и сахара в виде using().
КЛ>Шаг к чему? К дао? Достаточно понять, что using менее сладок нежели стековые объекты.
Здравствуйте, Cyberax, Вы писали:
C>Здравствуйте, remark, Вы писали:
R>>Ищи по "The Real-Time Specification for Java". Фактически они добавили синхронное освобождение памяти — схема применяемая в современном С++. C>Нет. В realtime Java _нет_ синхронного освобождения памяти — это сделать в общем случае чрезвычайно дорого. Для realtime Java гарантируются только верхние границы на время отклика сборщика мусора, ничего более.
Смотрю описание интерфейса ScopedMemory — "When the last reference to the object is removed, by exiting the thread or exiting the enter() method, finalizers are run for all objects in the memory area, and the area is emptied"
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, remark, Вы писали:
VD>>>На самом деле после некоторого опыта использования управляемых языков понимашь, что страхи плюсовиков (коим я являлся до перехода на управляемые среды) сильно надуманы. 99% контроля ресурсов — это контроль памяти. А когда память не нужно пасти, то остальное можно хоть руками контролировать. В общем using-а за глаза хватает.
R>>Ресурсами, которые контролируются стековым объектом, могут быть не только такие объекты как соединение, файл и т.д. R>>Техника значительно шире. Например, с помощью стекового объекта может контролироваться временный перевод курсора в "часики", блокировка/разблокировка мьютекса, задержка/возобновление обновления графического элемента управления, резервирование/разрезервирование какого-либо места/счётчика и т.д. и т.д.
VD>Тут складывается весьма странная ситуация. Ты рассказываешь мне про то что я и сам пробовал и не согласен с тем, что разве что видел из далека. Продолжай в том же духе. Это очень "конструктивная" позиция.
VD>Вот тебе реальные факты. В проекте компилятора Немерле есть 5 файлов (из 124 файлов) в которых используется using:
Это ни о чём не говорит. Возможно разработчики просто его не применяли.
У того, кто использует компонент, мотивация не использовать using — надо писать дополнительные строчки кода + дополнительный отступ.
У того, кто разрабатывает компонент, мотивация не предоставлять объекты, которые можно использовать в using — нет гарантии, что их будет кто-то использовать. using — это не более необязательного синтаксического сахара.
VD>Теперь, ВНИМАНИЕ вопрос... О чем речь то?
Я не согласен с твоими утвержедниями:
1. стековые объекты нужны крайне редко, если есть GC
2. у стековых объектов есть какие-то проблемы, когда время жизни больше времени работы функции
Здравствуйте, AndrewVK, Вы писали:
AVK>Здравствуйте, remark, Вы писали:
R>>Техника значительно шире. Например, с помощью стекового объекта может контролироваться временный перевод курсора в "часики", блокировка/разблокировка мьютекса, задержка/возобновление обновления графического элемента управления, резервирование/разрезервирование какого-либо места/счётчика и т.д. и т.д.
AVK>Это прекрасно реализуется при помощи using. Более того, именно для таких фич using предпочтительнее, потому что явно выделяет регион действия и при чтении сразу видно, что и как происходит.
А так же требуют дополнительных строк кода и дополнительного отступа.
А так же являются не более, чем необязательным синтаксическим сахаром. В то время, как стековый объект может формировать правильное использование класса. А это имхо посильнее, чем отсутствие явного региона.
Здравствуйте, remark, Вы писали:
R>А так же требуют дополнительных строк кода и дополнительного отступа. R>А так же являются не более, чем необязательным синтаксическим сахаром. В то время, как стековый объект может формировать правильное использование класса. А это имхо посильнее, чем отсутствие явного региона.
Каким образом? Кто запретит разработчику создать lock в куче?
R>Если внтури веток будет ещё какой-то код, то будет напоминать С-код с 18 уровнями отступов... Т.е. не масштабируется.
Здравствуйте, Константин Б., Вы писали:
КБ>Здравствуйте, remark, Вы писали:
R>>А так же требуют дополнительных строк кода и дополнительного отступа. R>>А так же являются не более, чем необязательным синтаксическим сахаром. В то время, как стековый объект может формировать правильное использование класса. А это имхо посильнее, чем отсутствие явного региона.
КБ>Каким образом? Кто запретит разработчику создать lock в куче?
Согласен. С форсированием я погорячился. Тогда скажем так:
С using по-умолчанию получается некорректный код, что бы получить корректный надо приложить усилия.
Со стеком по-умолчанию получается корректный код, что бы получить некорректный надо приложить усилия.
Возможно, это даже лучше полного форсирования.
К тому же можно закрыть operator new, тогда некорректное использование станет ещё сложнее.
R>>Если внтури веток будет ещё какой-то код, то будет напоминать С-код с 18 уровнями отступов... Т.е. не масштабируется.
КБ>Со стековыми объектами тоже самое: КБ>
Здравствуйте, remark, Вы писали:
R>Это ни о чём не говорит. Возможно разработчики просто его не применяли.
С то же вероятностью С++-программист может создавать стековые хелперы через new или запихивать их в динамически создаваемые объекты. Это не серьезно. Компилятор обложен тестами и утечек ресурсов в нем не замечено.
К тому же я работал далеко не над одним проектом и все было очень похоже. Более того я обычно вообще старался избегать using-ов. Например, если заранее известно, что файлы не будут большим, то я скорее считаю его в память одним вызовм File.ReadAllText()\File.ReadAllLines().
Кроме того есть еще один интересный подход.
Обычно ресурсы вроде файлов обрабатываются последовательным перебором. При этом их или используют в foreach-е или применяют к ним разные фунции вроде Map(), Iter(), Fold() и т.п. Так вот если сделать для подобного ресурса оболочку реализующую IEnumerable<тип перечисляемого ресурса>, то освобождение ресурсов будет производиться автоматически. Делается подобная обертка на раз. Вот смотри как может выглядеть оболочка для построчного чтения текстового файла:
using System;
using System.Collections.Generic;
using System.Console;
using System.IO;
using System.IO.Path;
using Nemerle.Utility;
[Record]
public class FileIterator : IEnumerable[string]
{
fileName : string;
public GetEnumerator() : IEnumerator[string]
{
using (resource = File.OpenText(fileName))
{
def loop(line)
{
| null => ()
| _ => yield line; loop(resource.ReadLine())
}
loop(resource.ReadLine())
}
}
}
module Program
{
Main() : void
{
def asmPath = Reflection.Assembly.GetCallingAssembly().Location;
def thisFileName = Combine(GetDirectoryName(asmPath), @"..\..\Main.n");
foreach (line in FileIterator(thisFileName))
WriteLine(line);
WriteLine();
WriteLine("--------------------------------------------------------------");
WriteLine();
FileIterator(thisFileName).Iter(WriteLine);
_ = ReadLine();
}
}
Оба варианта применения вызывают Dispose() автоматически.
Все это нужно для блокирующих ресурсов вроде файлов. Для соеденений с БД вполне полходит использование финалийзеров.
В общем, не та это проблема чтобы о нее пытаться лоб разбить. Била бы она актуальна, ее бы давно решили. Ну, или все бы давно использовали C++/CLI вместо Шарпа и Немерла. Меж тем все с точностью до наоборот.
R>У того, кто использует компонент, мотивация не использовать using — надо писать дополнительные строчки кода + дополнительный отступ. R>У того, кто разрабатывает компонент, мотивация не предоставлять объекты, которые можно использовать в using — нет гарантии, что их будет кто-то использовать. using — это не более необязательного синтаксического сахара.
Это не более чем пустые слова. Если бы они были не пыстыми, то весь дотнетный форум был бы завален вопросами по утечкам ресурсов. Меж тем подобными вопросами завален форум по С++.
R>Я не согласен с твоими утвержедниями: R>1. стековые объекты нужны крайне редко, если есть GC R>2. у стековых объектов есть какие-то проблемы, когда время жизни больше времени работы функции
Не согласен, так не согласен. Всегда есть море теоретиков несогласных с чем угодно. Попробуй, через годик расскажешь.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, remark, Вы писали:
R>А так же требуют дополнительных строк кода и дополнительного отступа.
Слушай, уж не приверженцам С++ о размерах кода писать. Не тот язык.
К тому на разработку и соблюдение стратегий управления памяти в С++-программах тратится так много времени разработчиков, что скорость разработки С++-программ становится просто черепашьей. И при этом каждая вторая С++-ная программа "течет" как дырявый самовар.
R>Если внтури веток будет ещё какой-то код, то будет напоминать С-код с 18 уровнями отступов... Т.е. не масштабируется.
Тебе виднее. В моих программах такого нет.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: Сборщик мусора и размещение объектов в стеке
R>Не говоря о том, что using это всё ещё просто сахар, который можно забыть, а стековый объект — способ форсирования корректного использования.
Попробуй на досуге так:
void f()
{
using (lock l1 = m1.lock(), l2 = m2.lock())
using file f = open_file()
{
//...
}
}
Кстати, для блокировок никаких внешних примитивов использовать не надо. В Ява и дотнете блокировки можно делать на любых объектах и без создания каких-то левых переенных:
lock(obj)
{
...
}
В прочем, мое мнение — многопоточность на явных блокировках и разделяемых ресурсах — это путь в ад.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>К тому на разработку и соблюдение стратегий управления памяти в С++-программах тратится так много времени разработчиков, что скорость разработки С++-программ становится просто черепашьей. И при этом каждая вторая С++-ная программа "течет" как дырявый самовар.
Помедитируй над этим С++ кодом, и почувствуй какой бред ты говоришь. Подсказка: здесь есть не менее 5 выделений/освобождений памяти, программа течёт не более, чем аналогичная на Java/C#/Nemerle/Ocaml, программа безопасна при возникновении исключений, вся память освобождается синхронно при завершении функции. Так же подумай, сколько времени я затратил на управление памятью в этой абсолютно не текущей программе.
Здравствуйте, VladD2, Вы писали:
VD>Попробуй на досуге так:
Задача была — впихнуть между захватами ресурсов ещё стейтменты.
VD>Кстати, для блокировок никаких внешних примитивов использовать не надо. В Ява и дотнете блокировки можно делать на любых объектах и без создания каких-то левых переенных:
Да, я знаю. Эта одна из причин, по которым программы в этих языках жирные, и не получается делать красивый ретейловый софт...
VD>В прочем, мое мнение — многопоточность на явных блокировках и разделяемых ресурсах — это путь в ад.
Передача сообщений, кстати, всегда реализуется через "разделяемые ресурсы" на SMP/multicore машинах. Хороший вопрос — почему?
Хватит, а?
Ты тут далеко не один на С/С++ пишешь.
R>Помедитируй над этим С++ кодом, и почувствуй какой бред ты говоришь.
Бред тут говоришь ты.
R>Подсказка: здесь есть не менее 5 выделений/освобождений памяти,
В аналогичном коде на C# одно выделение памяти. (то что происходит в f2 не учитываем)
R>программа течёт не более, чем аналогичная на Java/C#/Nemerle/Ocaml, программа безопасна при возникновении исключений, вся память освобождается синхронно при завершении функции.
В том что память освобождается синхронно никаких преимеществ нет.
Скорее одни проблемы... скажем нужно мъютексом лишний раз щелкать...
R>Так же подумай, сколько времени я затратил на управление памятью в этой абсолютно не текущей программе.
В примитивных случаях все действительно просто (хотя если вспомнить про то сколько вариантов реализации std::string ).
Но как только дело доходит то чегото посложнее.
Скажем завернуть сишную либу в нетекущий интерфейс и чтобы оно при этом не тормозило
... << RSDN@Home 1.2.0 alpha rev. 745>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
R>>Подсказка: здесь есть не менее 5 выделений/освобождений памяти, WH>В аналогичном коде на C# одно выделение памяти. (то что происходит в f2 не учитываем)
В С++ тоже может быть одно
R>>программа течёт не более, чем аналогичная на Java/C#/Nemerle/Ocaml, программа безопасна при возникновении исключений, вся память освобождается синхронно при завершении функции. WH>В том что память освобождается синхронно никаких преимеществ нет. WH>Скорее одни проблемы... скажем нужно мъютексом лишний раз щелкать...
Ничем щёлкать не надо
R>>Так же подумай, сколько времени я затратил на управление памятью в этой абсолютно не текущей программе. WH>В примитивных случаях все действительно просто (хотя если вспомнить про то сколько вариантов реализации std::string ).
Как реализация std::string отразится на этом код? На его семантике? Утечкам?
С++ программист хотя бы знает про реализацию строки, которую он использует
WH>Но как только дело доходит то чегото посложнее. WH>Скажем завернуть сишную либу в нетекущий интерфейс и чтобы оно при этом не тормозило
А какие проблемы? Таких примеров тонны. Погляди С++ обёртки к популярным либам типа libxml2, pqsql.
Про "тормозило" вообще не понятно. На современных компиляторах ран-тайм цена такой обёртки — 0 тактов процессора, 0 байт оперативной памяти, 0 байт размера выполняемого файла.
Ну так по сути-то что? Где эта программа течёт? Или как сильно это затормозило разработку?
Здравствуйте, remark, Вы писали:
R>В С++ тоже может быть одно
И куча щелканей interlocked функциями... а они всетки не дешевы.
R>Ничем щёлкать не надо
При освобождении памяти в многопоточной программе надо.
R>Как реализация std::string отразится на этом код? На его семантике? Утечкам?
На этом коде никак.
Но Влад говорил не об этом.
Влад говорил о том что кто-то очень долго и нудно думал какже эту строку реализовать.
R>С++ программист хотя бы знает про реализацию строки, которую он использует
Нормальные программисты на C# тоже.
R>А какие проблемы? Таких примеров тонны. Погляди С++ обёртки к популярным либам типа libxml2, pqsql. R>Про "тормозило" вообще не понятно. На современных компиляторах ран-тайм цена такой обёртки — 0 тактов процессора, 0 байт оперативной памяти, 0 байт размера выполняемого файла.
Можно конечно тупо понаписать тупых ScopeGuard'ов но ими пользоватся не удобно.
R>Ну так по сути-то что? Где эта программа течёт? Или как сильно это затормозило разработку?
По сути ты просто не знаешь что значит работать в среде где про управление памятью задумыватся не нужно.
Вот и говоришь всякую ерунду.
... << RSDN@Home 1.2.0 alpha rev. 745>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, remark, Вы писали:
R>Ты тоже считаешь, что С++ программисты большую часть своего времени проводят в безуспешных попытках залатать утечки ресурсов?
Они проводят очень не маленькую часть своего времени за обдумыванием того как эти утечки недопустить.
Прикладники которые тупо педалят код на std::string'ах меньше.
Писатели библиотек больше.
Но тратят все.
В то время как программисты на C# или Java про управление памятью ваще не думают.
Максимум в совсем клинических случаях ключики GC крутит.
... << RSDN@Home 1.2.0 alpha rev. 745>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, WolfHound, Вы писали:
WH>Здравствуйте, remark, Вы писали:
R>>В С++ тоже может быть одно WH>И куча щелканей interlocked функциями... а они всетки не дешевы.
Если ты имешь в виду interlocked в функции освобождения памяти, то если одно копирование, то и interlocked один
R>>Ничем щёлкать не надо WH>При освобождении памяти в многопоточной программе надо.
В этом основное отличие программистов на языках с наличием семантических барьеров от программистов на языках без наличия семантических барьеров.
Программист на языке с наличием семантических барьеров думает "Я обязан делать так, как это сделано в языке. От этого никуда не деться. Освобождение памяти подразумевает interlocked".
Программист на языке без наличия семантических барьеров думает "Пока меня не волнует, я буду делать так, как это сделано в языке. Если для меня это будет важно, то я сделаю это так как мне надо. Освобождение памяти при необходимости можно сделать без interlocked".
R>>Как реализация std::string отразится на этом код? На его семантике? Утечкам? WH>На этом коде никак. WH>Но Влад говорил не об этом. WH>Влад говорил о том что кто-то очень долго и нудно думал какже эту строку реализовать.
Это достаточно тривиально при наличии небольшого опыта.
Вот гляди — вот небольшая полностью безопасная обёртка для ресурса, которой можно пользоваться годами без каких либо утечек и дополнительных затрат времени:
Всё это чистая механика. Всё делается полностью по шаблонам. Никакой фантазии.
R>>А какие проблемы? Таких примеров тонны. Погляди С++ обёртки к популярным либам типа libxml2, pqsql. R>>Про "тормозило" вообще не понятно. На современных компиляторах ран-тайм цена такой обёртки — 0 тактов процессора, 0 байт оперативной памяти, 0 байт размера выполняемого файла. WH>Можно конечно тупо понаписать тупых ScopeGuard'ов но ими пользоватся не удобно.
А от них сильно много и не требуется...
R>>Ну так по сути-то что? Где эта программа течёт? Или как сильно это затормозило разработку? WH>По сути ты просто не знаешь что значит работать в среде где про управление памятью задумыватся не нужно. WH>Вот и говоришь всякую ерунду.
Попробую сформулировать так: С++ позволяет большую часть времени не задумываться об управлении памятью. Если в начале проекта потратить пару дней на создание некого общего инструментария, либо возможно он уже есть у программиста/компании, то об управлении памятью можно не задумываться 99.9% времени. Но тем не менее, и это имхо сильная сторона, об управлении памяти хотя бы можно задуматься при большой необходимости.
И ещё раз повторюсь: обеспечивается гарантия отсутствия утечек не меньшая чем в других современных языках, обеспечивается полная безопасность при возникновении исключений.
С++ я знаю не хуже тебя.
И знаю все методы и приемы которые используются при разработке на это недоязычке.
Так что не надо мне показывать как пишут скопгарды.
R>Если ты имешь в виду interlocked в функции освобождения памяти, то если одно копирование, то и interlocked один
Там будут вызваны несколько конструкторов копирования и несколько деструкторов.
Если строки на счетчиках ссылок то нужно в каждом конструкторе и деструкторе дергать interlocked. Это неизбежно в случае многопточной программы.
R>В этом основное отличие программистов на языках с наличием семантических барьеров от программистов на языках без наличия семантических барьеров.
Сколько пафоса то...
R>Программист на языке с наличием семантических барьеров думает "Я обязан делать так, как это сделано в языке. От этого никуда не деться. Освобождение памяти подразумевает interlocked".
Программист на языке с этими самыми барьерами ( ) вобще не думает о освобождении памяти.
Понимаешь вобще не думает.
R>Программист на языке без наличия семантических барьеров думает "Пока меня не волнует, я буду делать так, как это сделано в языке. Если для меня это будет важно, то я сделаю это так как мне надо. Освобождение памяти при необходимости можно сделать без interlocked". R>
Это потом не настанет никогда.
WH>>Можно конечно тупо понаписать тупых ScopeGuard'ов но ими пользоватся не удобно. R>А от них сильно много и не требуется...
Использовать Сишный интерфейс тот еще геморой.
Так что требуется.
R>Попробую сформулировать так: С++ позволяет большую часть времени не задумываться об управлении памятью.
В тривиальных случаях.
R>Если в начале проекта потратить пару дней на создание некого общего инструментария, либо возможно он уже есть у программиста/компании, то об управлении памятью можно не задумываться 99.9% времени. Но тем не менее, и это имхо сильная сторона, об управлении памяти хотя бы можно задуматься при большой необходимости.
Наивный чукотский юноша. Я несколько лет назад тоже таким был.
R>И ещё раз повторюсь: обеспечивается гарантия отсутствия утечек не меньшая чем в других современных языках, обеспечивается полная безопасность при возникновении исключений.
Конечно же меньшая.
С этим спорить бессмысленно.
Это факт.
... << RSDN@Home 1.2.0 alpha rev. 745>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, WolfHound, Вы писали:
WH>Здравствуйте, remark, Вы писали:
WH>С++ я знаю не хуже тебя. WH>И знаю все методы и приемы которые используются при разработке на это недоязычке. WH>Так что не надо мне показывать как пишут скопгарды.
Ты просто сказал, что тут надо что-то долго и нужно думать, что бы это реализовать. Я показал, что всё достаточно просто.
R>>Если ты имешь в виду interlocked в функции освобождения памяти, то если одно копирование, то и interlocked один WH>Там будут вызваны несколько конструкторов копирования и несколько деструкторов. WH>Если строки на счетчиках ссылок то нужно в каждом конструкторе и деструкторе дергать interlocked. Это неизбежно в случае многопточной программы.
Во-первых, избежно.
Во-вторых, сейчас уже никто не делает строки с подсчётом ссылок.
Копий не будет не потомучто там разделяемое тело, а потомучто компилятор соптимизирует.
R>>Программист на языке с наличием семантических барьеров думает "Я обязан делать так, как это сделано в языке. От этого никуда не деться. Освобождение памяти подразумевает interlocked". WH>Программист на языке с этими самыми барьерами ( ) вобще не думает о освобождении памяти. WH>Понимаешь вобще не думает.
Хорошо, я понял, что он вобще не думает.
Имхо более интересный момент заключается не в том, что один вообще не думает, а второй думает иногда; а в том, что первый и не сможет подумать в принципе, даже если сильно захочет.
R>>Программист на языке без наличия семантических барьеров думает "Пока меня не волнует, я буду делать так, как это сделано в языке. Если для меня это будет важно, то я сделаю это так как мне надо. Освобождение памяти при необходимости можно сделать без interlocked". R>> WH>Это потом не настанет никогда.
У кого как. У меня лично уже настало.
WH>>>Можно конечно тупо понаписать тупых ScopeGuard'ов но ими пользоватся не удобно. R>>А от них сильно много и не требуется... WH>Использовать Сишный интерфейс тот еще геморой. WH>Так что требуется.
Ну так его и не надо использовать — его надо просто обернуть.
R>>Попробую сформулировать так: С++ позволяет большую часть времени не задумываться об управлении памятью. WH>В тривиальных случаях.
Большая часть программ это и есть тривиальные случаи.
R>>Если в начале проекта потратить пару дней на создание некого общего инструментария, либо возможно он уже есть у программиста/компании, то об управлении памятью можно не задумываться 99.9% времени. Но тем не менее, и это имхо сильная сторона, об управлении памяти хотя бы можно задуматься при большой необходимости. WH>Наивный чукотский юноша. Я несколько лет назад тоже таким был.
Знаешь, история мысли развивается по спирали...
R>>И ещё раз повторюсь: обеспечивается гарантия отсутствия утечек не меньшая чем в других современных языках, обеспечивается полная безопасность при возникновении исключений. WH>Конечно же меньшая. WH>С этим спорить бессмысленно. WH>Это факт.
Ну просто, что бы не быть голословным, покажи где эта гарантия меньше на этом примере:
Здравствуйте, remark, Вы писали:
R>А так же требуют дополнительных строк кода и дополнительного отступа.
Точно. Поэтому я никогда не пишу комментарии.
R>А так же являются не более, чем необязательным синтаксическим сахаром. В то время, как стековый объект может формировать правильное использование класса.
Ага. И догадаться, что там за кадром происходит transaction scope можно только изучив исходники.
R> А это имхо посильнее, чем отсутствие явного региона.
Ну, тогда АОП посильнее твоей фигни, там вообще внутри кода ничего писать не надо.
AVK>>Аналогично AVK>>
Здравствуйте, remark, Вы писали:
R>Про "тормозило" вообще не понятно. На современных компиляторах ран-тайм цена такой обёртки — 0 тактов процессора, 0 байт оперативной памяти, 0 байт размера выполняемого файла.
А на синхронизацию инкремента/декремента счетчиков внутри оберток тоже 0 тактов процессора тратится?
... << RSDN@Home 1.2.0 alpha rev. 725 on Windows Vista 6.0.6000.0>>
Здравствуйте, Константин Л., Вы писали:
C>>>>А ты дальше подумай — что делать, если эта структура будет полем класса, уничтожение которого недетерминировано? КЛ>>>И что? Если ее создали на стеке — ведет себя как стековый объект. Если нет — ну нет так нет. В C++\CLI именно так и работает. C>>Осталось сделать следующий шаг, и понять, что стековые объекты не нужны — достаточно паттерна Disposable и сахара в виде using(). КЛ>Шаг к чему? К дао? Достаточно понять, что using менее сладок нежели стековые объекты.
Ты подумай, однако. "Стековые" объекты нельзя просто так класть в ref-классы, так как они уничтожаются в недетерминированое время. Да, и семантики передачи по значению с вызовом копирующих конструкторов в C#/Java тоже как таковой нет. Следовательно, нам нужно будет или добавлять всю сементику копирующих конструкторов с операторами присваивания, или ограничивать стековые объекты только одним фреймом. Ну а если ограничить их только одним фреймом — и получим полный аналог using().
Sapienti sat!
Re[7]: Сборщик мусора и размещение объектов в стеке
Здравствуйте, remark, Вы писали:
R>Смотрю описание интерфейса ScopedMemory — "When the last reference to the object is removed, by exiting the thread or exiting the enter() method, finalizers are run for all objects in the memory area, and the area is emptied" R>Или я что-то не так понял?
Не совсем, оно без GC, AFAIR, все равно не работает.
Sapienti sat!
Re[6]: Сборщик мусора и размещение объектов в стеке
Здравствуйте, Cyberax, Вы писали:
C>Здравствуйте, Константин Л., Вы писали:
C>>>>>А ты дальше подумай — что делать, если эта структура будет полем класса, уничтожение которого недетерминировано? КЛ>>>>И что? Если ее создали на стеке — ведет себя как стековый объект. Если нет — ну нет так нет. В C++\CLI именно так и работает. C>>>Осталось сделать следующий шаг, и понять, что стековые объекты не нужны — достаточно паттерна Disposable и сахара в виде using(). КЛ>>Шаг к чему? К дао? Достаточно понять, что using менее сладок нежели стековые объекты. C>Ты подумай, однако. "Стековые" объекты нельзя просто так класть в ref-классы, так как они уничтожаются в недетерминированое время.
Так подумать над этой проблемой, или над тем, что слаще?
C>Да, и семантики передачи по значению с вызовом копирующих конструкторов в C#/Java тоже как таковой нет. Следовательно, нам нужно будет или добавлять всю сементику копирующих конструкторов с операторами присваивания, или ограничивать стековые объекты только одним фреймом. Ну а если ограничить их только одним фреймом — и получим полный аналог using().
А вот волшебники взяли и заимплементили такую фичу в c++\cli
Re[7]: Сборщик мусора и размещение объектов в стеке
Здравствуйте, Константин Л., Вы писали:
C>>Ты подумай, однако. "Стековые" объекты нельзя просто так класть в ref-классы, так как они уничтожаются в недетерминированое время. КЛ>Так подумать над этой проблемой, или над тем, что слаще?
То есть?
C>>Да, и семантики передачи по значению с вызовом копирующих конструкторов в C#/Java тоже как таковой нет. Следовательно, нам нужно будет или добавлять всю сементику копирующих конструкторов с операторами присваивания, или ограничивать стековые объекты только одним фреймом. Ну а если ограничить их только одним фреймом — и получим полный аналог using(). КЛ>А вот волшебники взяли и заимплементили такую фичу в c++\cli
Это вполне понятно, так как C++/CLI уже включает в себя все механизмы обычного С++ для управления памятью. А ты попробуй придумать как добиться того же, не повторяя половину С++.
Здравствуйте, VladD2, Вы писали:
VD>Теперь, ВНИМАНИЕ вопрос... О чем речь то?
Наверно о том что пример некорректный
В программе занимающейся пакетными расчетами управление ресурсами кроме памяти (GC) и доступа к файлам (который несложно автоматизировать) и не нужно.
Re[2]: Сборщик мусора и размещение объектов в стеке
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, PC Car, Вы писали:
PC>>Почему не ввести вместо using на такой случай специальный тип — стековый класс? Это ведь не потребует усложнения синтаксиса. Просто у структуры появится деструктор с детерминированным временем вызова.
VD>В C++/CLI так и сделано. Жить от это особо лучше не стало. По крайней это не компенсировало отсуствия в C++/CLI других полезных свойств Шарпа.
Ну в D тоже есть, но там сделали чуть умнее чем в C++/CLI, есть ключевое слово scope, если класс обявлен как scope, то он может жить только на стеке, и объявить его например членом класса не выйдет, кроме того переменную любого класса можно заставить жить на стеке объявив с модификатором scope:
import std.stdio;
// обычный классclass SimpleClass
{
this(int n)
{
this.n = n;
writefln("SimpleClass constructor #", n);
}
~this()
{
writefln("SimpleClass destructor #", n);
}
int n;
}
// этот класс может объявлятся только на стеке
scope class ScopeClass
{
this()
{
writefln("ScopeClass constructor");
}
~this()
{
writefln("ScopeClass destructor ");
}
}
class Test1
{
// нормально
SimpleClass tstSimple;
// ниже не скомпилируется
//ScopeClass tstScope; this()
{
tstSimple = new SimpleClass(1);
}
}
void main()
{
// чисто стековая переменная
scope sc = new ScopeClass();
// обычная переменная управляемая GCauto sm = new SimpleClass(1);
// переменная обычного класса с временем жизни ограниченным областью
scope scsm = new SimpleClass(2);
}
VD>На самом деле после некоторого опыта использования управляемых языков понимашь, что страхи плюсовиков (коим я являлся до перехода на управляемые среды) сильно надуманы. 99% контроля ресурсов — это контроль памяти. А когда память не нужно пасти, то остальное можно хоть руками контролировать. В общем using-а за глаза хватает.
Ну а те кто уже не пишут на плюсах со своей стороны любят преувеличить сложность управления памятью в них.
VD>Ну, а стековый объект все равно не всегда поможет. Ведь если время жизни объекта не совпадает с временем проведенным в процедуре, то и контролировать его так не выйдет.
Это да, для этого хороши потоки (итераторы — генераторы) и продолжения.
Здравствуйте, AndrewVK, Вы писали:
AVK>Здравствуйте, remark, Вы писали:
R>>Про "тормозило" вообще не понятно. На современных компиляторах ран-тайм цена такой обёртки — 0 тактов процессора, 0 байт оперативной памяти, 0 байт размера выполняемого файла.
AVK>А на синхронизацию инкремента/декремента счетчиков внутри оберток тоже 0 тактов процессора тратится?
Какое это имеет отношение к обёртке над С библиотекой? Это уже новый функционал. Если это необходимый функционал, то он уже есть внутри С библиотеки, только не через RAII, а через acquire()/release().
FR wrote: > C>А чем тогда это лучше using()? ИМХО, абсолютно лишняя сущность. > Тем что жестче контроль и разделение. Случайно объявить не там где нужно > такой класс не возможно.
ИМХО, совсем не оправдывает введение еще одной сущности.
Posted via RSDN NNTP Server 2.1 beta
Sapienti sat!
Re[6]: Сборщик мусора и размещение объектов в стеке
Здравствуйте, Cyberax, Вы писали:
C>FR wrote: >> C>А чем тогда это лучше using()? ИМХО, абсолютно лишняя сущность. >> Тем что жестче контроль и разделение. Случайно объявить не там где нужно >> такой класс не возможно. C>ИМХО, совсем не оправдывает введение еще одной сущности.
А что для Вальтера лишняя сущность!
А using не лишняя сущность?
К тому же scope используемый вот так:
{
scope scsm = new SimpleClass(2);
// .....
}
эквивалентен using
Re[8]: Сборщик мусора и размещение объектов в стеке
Здравствуйте, Cyberax, Вы писали:
C>Здравствуйте, Константин Л., Вы писали:
C>>>Ты подумай, однако. "Стековые" объекты нельзя просто так класть в ref-классы, так как они уничтожаются в недетерминированое время. КЛ>>Так подумать над этой проблемой, или над тем, что слаще? C>То есть?
Сначала ты с пафосом предлагал "дойти" до мысли, что это просто не нужно. Потом начал упирать на то, что это нереализуемо.
C>>>Да, и семантики передачи по значению с вызовом копирующих конструкторов в C#/Java тоже как таковой нет. Следовательно, нам нужно будет или добавлять всю сементику копирующих конструкторов с операторами присваивания, или ограничивать стековые объекты только одним фреймом. Ну а если ограничить их только одним фреймом — и получим полный аналог using(). КЛ>>А вот волшебники взяли и заимплементили такую фичу в c++\cli C>Это вполне понятно, так как C++/CLI уже включает в себя все механизмы обычного С++ для управления памятью. А ты попробуй придумать как добиться того же, не повторяя половину С++.
для этого не нужно ничего повторять.
Re[2]: Сборщик мусора и размещение объектов в стеке
Здравствуйте, IT, Вы писали:
IT>Здравствуйте, PC Car, Вы писали:
PC>>Почему не ввести вместо using на такой случай специальный тип — стековый класс?
IT>Зачем что-то ещё? Используй тот же using.
А что будет, если из кода внутри юзинга вылетит исключение? Которое по идее ловится на два уровня выше по колстеку?
Re[3]: Сборщик мусора и размещение объектов в стеке
Здравствуйте, FR, Вы писали:
C>>ИМХО, совсем не оправдывает введение еще одной сущности. FR>А что для Вальтера лишняя сущность!
Ну да, после трех сортов константности от таких людей чего угодно можно ждать.
FR>
FR>эквивалентен using
В _таком_ виде scope просто является другой записью using'а — я не против. Но зачем делать scope-классы — это уже мне не очень понятно.
Там же целая гора проблем сразу возникает: как работает наследование, что произойдет при наследовании от обычного класса, и т.д.
Sapienti sat!
Re[9]: Сборщик мусора и размещение объектов в стеке
Здравствуйте, Константин Л., Вы писали:
C>>>>Ты подумай, однако. "Стековые" объекты нельзя просто так класть в ref-классы, так как они уничтожаются в недетерминированое время. КЛ>>>Так подумать над этой проблемой, или над тем, что слаще? C>>То есть? КЛ>Сначала ты с пафосом предлагал "дойти" до мысли, что это просто не нужно. Потом начал упирать на то, что это нереализуемо.
Не "не нужно", а "невозможно сделать правильно". А если делать только в тех случаях, когда _можно_ сделать правильно — получим или полный С++ или аналог using()'а.
КЛ>>>А вот волшебники взяли и заимплементили такую фичу в c++\cli C>>Это вполне понятно, так как C++/CLI уже включает в себя все механизмы обычного С++ для управления памятью. А ты попробуй придумать как добиться того же, не повторяя половину С++. КЛ>для этого не нужно ничего повторять.
Ну покажи как ты будешь стековые объекты с детерминированым деструкторами и ref-классы совмещать (без финализаторов — это хак).
Sapienti sat!
Re[5]: Сборщик мусора и размещение объектов в стеке
Здравствуйте, Константин Л., Вы писали:
КЛ>Здравствуйте, Cyberax, Вы писали:
C>>Здравствуйте, Константин Л., Вы писали:
C>>>>А ты дальше подумай — что делать, если эта структура будет полем класса, уничтожение которого недетерминировано? КЛ>>>И что? Если ее создали на стеке — ведет себя как стековый объект. Если нет — ну нет так нет. В C++\CLI именно так и работает. C>>Осталось сделать следующий шаг, и понять, что стековые объекты не нужны — достаточно паттерна Disposable и сахара в виде using().
КЛ>Шаг к чему? К дао? Достаточно понять, что using менее сладок нежели стековые объекты.
Особенно сладки стековые объекты в С++, когда идёт отмотка стека из-за исключения и тут из деструктора вылетает новое исключение
Re[8]: Сборщик мусора и размещение объектов в стеке
Здравствуйте, Cyberax, Вы писали:
C>Здравствуйте, FR, Вы писали:
C>>>ИМХО, совсем не оправдывает введение еще одной сущности. FR>>А что для Вальтера лишняя сущность! C>Ну да, после трех сортов константности от таких людей чего угодно можно ждать.
Угу если еще учесть что есть scope(exit) и т. п.
C>В _таком_ виде scope просто является другой записью using'а — я не против. Но зачем делать scope-классы — это уже мне не очень понятно.
Я одно хорошее примение вижу — гарантированный RAI объект который нельзя использовать в других целях
C>Там же целая гора проблем сразу возникает: как работает наследование, что произойдет при наследовании от обычного класса, и т.д.
Ну scope как вирус если определяешь то все потомки будут scope.
А наследоватся можно от любого класса.
Re[6]: Сборщик мусора и размещение объектов в стеке
Здравствуйте, anton_t, Вы писали:
_>Здравствуйте, Константин Л., Вы писали:
КЛ>>Здравствуйте, Cyberax, Вы писали:
C>>>Здравствуйте, Константин Л., Вы писали:
C>>>>>А ты дальше подумай — что делать, если эта структура будет полем класса, уничтожение которого недетерминировано? КЛ>>>>И что? Если ее создали на стеке — ведет себя как стековый объект. Если нет — ну нет так нет. В C++\CLI именно так и работает. C>>>Осталось сделать следующий шаг, и понять, что стековые объекты не нужны — достаточно паттерна Disposable и сахара в виде using().
КЛ>>Шаг к чему? К дао? Достаточно понять, что using менее сладок нежели стековые объекты.
_>Особенно сладки стековые объекты в С++, когда идёт отмотка стека из-за исключения и тут из деструктора вылетает новое исключение
Если освобождения ресурсов/откаты действий могут не проходить, то в принципе нельзя добиться никакой осмысленной семантики, в частности консистентности нетривиальных данных.
Например, хотим добавить значения в 2 списка:
В точке //!!! остаётся только убить себя об стену или выпить йада, ничего лучше придумать нельзя. Т.ч. возможное завершение программы на С++ при вылете исключения из конструктора есть вполне удобная вещь — автоматизация убивания об стену.
Здравствуйте, FR, Вы писали:
FR>Угу если еще учесть что есть scope(exit) и т. п.
scope(exit) — это тоже вполне нормальная идея, согласен.
C>>В _таком_ виде scope просто является другой записью using'а — я не против. Но зачем делать scope-классы — это уже мне не очень понятно. FR>Я одно хорошее примение вижу — гарантированный RAI объект который нельзя использовать в других целях
RAII очень ограниченый получается — если мы не можем сохранять его в поля класса.
C>>Там же целая гора проблем сразу возникает: как работает наследование, что произойдет при наследовании от обычного класса, и т.д. FR>Ну scope как вирус если определяешь то все потомки будут scope. FR>А наследоватся можно от любого класса.
Ооо...
class Base
{
Base()
{
someExternalVariable=this;
}
};
scope class Derived : public Base
{
Derived() : Base() //???
{
}
}
И вот таких шуток, если подумать, можно найти еще несколько штук.
Нет, при желании их можно решить — но это куча сложности добавится на пустом месте.
Sapienti sat!
Re[7]: Сборщик мусора и размещение объектов в стеке
Здравствуйте, remark, Вы писали:
R>Здравствуйте, anton_t, Вы писали:
_>>Здравствуйте, Константин Л., Вы писали:
КЛ>>>Здравствуйте, Cyberax, Вы писали:
C>>>>Здравствуйте, Константин Л., Вы писали:
C>>>>>>А ты дальше подумай — что делать, если эта структура будет полем класса, уничтожение которого недетерминировано? КЛ>>>>>И что? Если ее создали на стеке — ведет себя как стековый объект. Если нет — ну нет так нет. В C++\CLI именно так и работает. C>>>>Осталось сделать следующий шаг, и понять, что стековые объекты не нужны — достаточно паттерна Disposable и сахара в виде using().
КЛ>>>Шаг к чему? К дао? Достаточно понять, что using менее сладок нежели стековые объекты.
_>>Особенно сладки стековые объекты в С++, когда идёт отмотка стека из-за исключения и тут из деструктора вылетает новое исключение
R>Если освобождения ресурсов/откаты действий могут не проходить, то в принципе нельзя добиться никакой осмысленной семантики, в частности консистентности нетривиальных данных. R>Например, хотим добавить значения в 2 списка:
R>
R>В точке //!!! остаётся только убить себя об стену или выпить йада, ничего лучше придумать нельзя. Т.ч. возможное завершение программы на С++ при вылете исключения из конструктора есть вполне удобная вещь — автоматизация убивания об стену.
Ага, мы убили себя, даже не залогировав ошибку, потому что логер доступен только выше по стэку. Не хотел бы я такое отлавливать.
Re[10]: Сборщик мусора и размещение объектов в стеке
Здравствуйте, anton_t, Вы писали:
R>>В точке //!!! остаётся только убить себя об стену или выпить йада, ничего лучше придумать нельзя. Т.ч. возможное завершение программы на С++ при вылете исключения из конструктора есть вполне удобная вещь — автоматизация убивания об стену.
_>Ага, мы убили себя, даже не залогировав ошибку, потому что логер доступен только выше по стэку. Не хотел бы я такое отлавливать.
Во-первых, большинство функций освобождения ресурсов/отката действий дают гарантию бессбойности, по вышеупомянутой причине.
Во-вторых, если всё же функция может провалиться, то попытаться залогировать это можно точно так же, как и залогировать любое другое событие в любой другой функции.
Здравствуйте, Cyberax, Вы писали:
C>Здравствуйте, Константин Л., Вы писали:
C>>>>>Ты подумай, однако. "Стековые" объекты нельзя просто так класть в ref-классы, так как они уничтожаются в недетерминированое время. КЛ>>>>Так подумать над этой проблемой, или над тем, что слаще? C>>>То есть? КЛ>>Сначала ты с пафосом предлагал "дойти" до мысли, что это просто не нужно. Потом начал упирать на то, что это нереализуемо. C>Не "не нужно", а "невозможно сделать правильно". А если делать только в тех случаях, когда _можно_ сделать правильно — получим или полный С++ или аналог using()'а.
Что значит полный с++? Что-то я не догоняю.
КЛ>>>>А вот волшебники взяли и заимплементили такую фичу в c++\cli C>>>Это вполне понятно, так как C++/CLI уже включает в себя все механизмы обычного С++ для управления памятью. А ты попробуй придумать как добиться того же, не повторяя половину С++. КЛ>>для этого не нужно ничего повторять. C>Ну покажи как ты будешь стековые объекты с детерминированым деструкторами и ref-классы совмещать (без финализаторов — это хак).
С финализатором как раз просто, а вот что делать в случае, когда объект реализует IDisposable. Что делать что делать. В финализаторе звать dtor автоматом (пусть компайлер зовет). В Dispose звать ручками. Тогда получится некий аналог IDisposable. Но я этого не отрицаю. Просто синтаксический сахарок.
Re[6]: Сборщик мусора и размещение объектов в стеке
Здравствуйте, Константин Л., Вы писали:
КЛ>>>Сначала ты с пафосом предлагал "дойти" до мысли, что это просто не нужно. Потом начал упирать на то, что это нереализуемо. C>>Не "не нужно", а "невозможно сделать правильно". А если делать только в тех случаях, когда _можно_ сделать правильно — получим или полный С++ или аналог using()'а. КЛ>Что значит полный с++? Что-то я не догоняю.
Фича стековых объектов — детерминированое уничтожение. Чтобы стековые объекты были чем-то большим, чем записаный по-другому using(), нужно уметь эти объекты передавать по значению. А это потребует семантики оператора присваивания и копирующего конструктора. А это, в свою очередь, привлечет другие проблемы (например, захочется иметь ссылки на стековые объекты).
И если их попробовать решить — С++ и получим.
C>>Ну покажи как ты будешь стековые объекты с детерминированым деструкторами и ref-классы совмещать (без финализаторов — это хак). КЛ>С финализатором как раз просто, а вот что делать в случае, когда объект реализует IDisposable. Что делать что делать. В финализаторе звать dtor автоматом (пусть компайлер зовет). В Dispose звать ручками. Тогда получится некий аналог IDisposable. Но я этого не отрицаю. Просто синтаксический сахарок.
И стоит ради такого сахара вводить еще одну фундаментальную сущность языка?
Sapienti sat!
Re[7]: Сборщик мусора и размещение объектов в стеке
Здравствуйте, Константин Л., Вы писали:
КЛ>Здравствуйте, anton_t, Вы писали:
КЛ>[]
_>>Особенно сладки стековые объекты в С++, когда идёт отмотка стека из-за исключения и тут из деструктора вылетает новое исключение
КЛ>А ты возьми за правило, что деструкторы не должны кидать исключений. И вообще, пост твой не в тему.
Действительно, прелести С++ это отдельный разговор
Здравствуйте, remark, Вы писали:
R>Ты тоже считаешь, что С++ программисты большую часть своего времени проводят в безуспешных попытках залатать утечки ресурсов?
Тет, конечно. Большую часть своего времени они ловят баги.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
FR>Наверно о том что пример некорректный FR>В программе занимающейся пакетными расчетами управление ресурсами кроме памяти (GC) и доступа к файлам (который несложно автоматизировать) и не нужно.
А где те программы в которых учет реусурсво становится проблемой?
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, FR, Вы писали:
FR>Ну в D тоже есть, но там сделали чуть умнее чем в C++/CLI, есть ключевое слово scope, если класс обявлен как scope, то он может жить только на стеке, и объявить его например членом класса не выйдет, кроме того переменную любого класса можно заставить жить на стеке объявив с модификатором scope:
Возможно поэтому Ди не не является С++-ом? Не задумывался над этим?
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: Сборщик мусора и размещение объектов в стеке
Здравствуйте, remark, Вы писали:
R>Задача была — впихнуть между захватами ресурсов ещё стейтменты.
То есть она абстракная?
Я вот потребность в таком коде ни разу в жизни не видел. Видел конечно когда нужно несколько ресурсов разом захватить, но чтобы вот так в столбик...
R>Да, я знаю. Эта одна из причин, по которым программы в этих языках жирные, и не получается делать красивый ретейловый софт...
Примеры привести сможешь? А то обратных примеров море. А так чтобы программа на С++ оказалась меньше чем аналогичная на языках более высокого уровня...
R>Передача сообщений, кстати, всегда реализуется через "разделяемые ресурсы" на SMP/multicore машинах. Хороший вопрос — почему?
Кого трогают проблемы реализации? Людям надо писать многозадачный софт. Причем далеть это с минимумо ошибок и максимально быстро.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
FR>>Наверно о том что пример некорректный FR>>В программе занимающейся пакетными расчетами управление ресурсами кроме памяти (GC) и доступа к файлам (который несложно автоматизировать) и не нужно. VD>А где те программы в которых учет реусурсво становится проблемой?
Игры, например...
Sapienti sat!
Re[6]: Сборщик мусора и размещение объектов в стеке
Здравствуйте, VladD2, Вы писали:
FR>>Тем что жестче контроль и разделение. Случайно объявить не там где нужно такой класс не возможно. VD>Готов согласиться с твоим доводами. Но исходный вопрос все же остается. Почему контроль ресурсов не достает орды разработчиков на Яве и дотнете?
Меня, лично, переодически на Java достает Бороться, конечно, можно определенными путями, но гибкости С++ иногда не хватает...
Здравствуйте, VladD2, Вы писали:
VD>Готов согласиться с твоим доводами. Но исходный вопрос все же остается. Почему контроль ресурсов не достает орды разработчиков на Яве и дотнете?
Он также не достает и разработчиков на си, просто им как и явщикам и дотнетчикам приходится прилагать для этого контроля больше усилий.
Здравствуйте, FR, Вы писали:
VD>>Само появление "хорошего аллокатора" говорит о том, что кто-то подумал об уарвлении памятью. Не так ли?
FR>Конечно, но это одноразовое действие
Ага... которое приходится делать постоянно.
ЗЫ
Факт в том, что в сложной программе, если конечно она должна сносно работать и не течь, дожена быть продумана и отслежена концепция вледения памятью. Это дополнительный слой головной боли.
То что многие С++-ники не замечают этого ровным счетом ничего не значит. Часть их мозга невсегда отдана всяческим концепциям и мелким приемам необходимым для контроля за памятью. Ну, и как результат их производительность, при прочих равных, значительно ниже чем у тех кто использует языки с автоматическим управлением памяти.
Да и вообще, сам разговор абстурдный. Если бы управление памятью ничего не столо бы, то кто бы стал возиться с ее автоматизацией? Все просто реализовали бы деструкторы в скриптах и Явах и жили бы припеваючи.
Вопрос только в том почему этого простого факта не понимаю фанатики от С++? Мне кажется, что тут примерно тоже самое что у сомашедших. Многие сумашедшие счасливы потому что они не понимают, что они сумашедшие. Те же кто говоря им об этом просто кажутся им недоумками или просто игнорируются. Так же и С++-ники. Они живут в своем низкоуровневом мире и не видят как можно жить по другому. Ну, а те кто пытается им что-то сказать для них выглядят врагами.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Cyberax, Вы писали:
VD>>А где те программы в которых учет реусурсво становится проблемой? C>Игры, например...
С чего бы это? Я вот видел код игровых движков и что-то особых проблем там не заметил. XNA вроде как тоже в применении в разы проще чем DirectX. Не так ли?
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Cyberax, Вы писали:
C>Меня, лично, переодически на Java достает Бороться, конечно, можно определенными путями, но гибкости С++ иногда не хватает...
А меня на Немерле не достает, почему-то. Я вообще о нем давно не задумывался.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[7]: Сборщик мусора и размещение объектов в стеке
Здравствуйте, FR, Вы писали:
FR>Он также не достает и разработчиков на си, просто им как и явщикам и дотнетчикам приходится прилагать для этого контроля больше усилий.
Вот это не надо. У С-шников это первешая проблема. Сделай поиск по "goto cleanup" и больше такого не говори.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: Сборщик мусора и размещение объектов в стеке
Здравствуйте, VladD2, Вы писали:
FR>>Конечно D почти во всем лучше C++,
VD>Ну, не очень все же... слава богу...
Так Вальтер (даже слишком) активно трудится
FR>>притом оставаясь очень близким к нему, иначе он бы меня так сильно не интересовал.
VD>Месье любитель извращений?
Конечно, вот сейчас ML подобные языки ковыряю.
Вроде отличные языки, несложные в обучении, и более мощные чем C++/C#/Java и непонятно почему не стали майнстримом.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, FR, Вы писали:
FR>>Да в любых может стать, даже и в пакетных, но в пакетных как раз этот учет проще всего сделать.
VD>Это пустые слова. Ты хоть показал бы одну жалобу на это дело на наших форумах, что ли.
То есть у тея самого никогда не было чтобы программа подвешивала систему из-за нехватки GDI ресурсов, или уходила в синий экран при работе c DX?
Здравствуйте, VladD2, Вы писали:
VD>>>А где те программы в которых учет реусурсво становится проблемой? C>>Игры, например... VD>С чего бы это? Я вот видел код игровых движков и что-то особых проблем там не заметил.
Ну так естественно — указатели с подсчетом ссылок, и проблем нет.
VD>XNA вроде как тоже в применении в разы проще чем DirectX. Не так ли?
И много Half-life'ов на XNA написано?
Здравствуйте, VladD2, Вы писали:
VD>С чего бы это? Я вот видел код игровых движков и что-то особых проблем там не заметил. XNA вроде как тоже в применении в разы проще чем DirectX. Не так ли?
Nebula или Ogre тоже в разы проще в применении чем DirectX.
Здравствуйте, Cyberax, Вы писали:
VD>>С чего бы это? Я вот видел код игровых движков и что-то особых проблем там не заметил. C>Ну так естественно — указатели с подсчетом ссылок, и проблем нет.
О чем ты?
VD>>XNA вроде как тоже в применении в разы проще чем DirectX. Не так ли? C>И много Half-life'ов на XNA написано?
Дык он только появился. Уверен, что напишут и не один. Новые команды могут догнать старые только выбирая более мощьные и удобные инструменты. XNA — это шанс войти на рынок.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, FR, Вы писали:
FR>Nebula или Ogre тоже в разы проще в применении чем DirectX.
DirectX — это АПИ, а Ogre — игровой движок. Их просто сравнивать нельзя. Ты лучше сравни игровой код для Ogre и менеджед-Ogre (если я не ошибаюсь он есть в двух вариантах).
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, FR, Вы писали:
FR>То есть у тея самого никогда не было чтобы программа подвешивала систему из-за нехватки GDI ресурсов, или уходила в синий экран при работе c DX?
А причем тут это? Ты вот видел менеджед-программу которая делала бы это?
Чтобы терять необходимое для появления дыр в окнах количество ресурсов их нужно в цикле складывать в список. Иначе схема слежения за хэндлами их подчистит. Так что тут как раз в управляемом мире все очень хорошо. Схему слежения за ресурсами продумали создатели фрэймворка. Причем они же обеспечили подстраховку. Так что написать код который достигает описанных тобой эффектов на управляемом языке куда сложнее чем на С++.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[7]: Сборщик мусора и размещение объектов в стеке
VD>>>XNA вроде как тоже в применении в разы проще чем DirectX. Не так ли? C>>И много Half-life'ов на XNA написано? VD>Дык он только появился. Уверен, что напишут и не один. Новые команды могут догнать старые только выбирая более мощьные и удобные инструменты. XNA — это шанс войти на рынок.
Не встревая в основную дискуссию: XNA as-is, к сожалению, суть рекламная поделка. Ничего +- существенного на нем написать нельзя. Может быть в будущем это и измениться, но пока так.
Сама проблема управления памятью, конкретно для игр — как правило не стоит в классическом виде, ибо подавляющая часть ресурсов выделяется статически либо 1 раз (читать — мы точно знаем когда, сколько и каких ресурсов нам понадобится. И точно знаем когда, где и как мы их убьем). Было бы интересно посмотреть на движок, полностью живущий в управляемой среде (а не затащенный в нее через врапперы) — но пока я такого не видел и не очень понимаю какие бонусы "именно для движка" это может принести — судя по тому что такого нет — не только я.
А для написания говнокода, которого 80% в любом проекте, там да — почему нет, такие примеры есть и вполне успешные.
Здравствуйте, VladD2, Вы писали:
VD>>>С чего бы это? Я вот видел код игровых движков и что-то особых проблем там не заметил. C>>Ну так естественно — указатели с подсчетом ссылок, и проблем нет. VD>О чем ты?
В играх очень важно, чтобы движек работал предсказуемо. Там обычно дофига всяких кэшей, и никому не хочется, чтобы кэшировалось что-то лишнее.
Ну и еще приставки есть, где память — совсем даже ценный ресурс (на Wii ее всего около 64Мб, например).
C>>И много Half-life'ов на XNA написано? VD>Дык он только появился. Уверен, что напишут и не один. Новые команды могут догнать старые только выбирая более мощьные и удобные инструменты. XNA — это шанс войти на рынок.
Так никто не спорит — для определенных типов игр он вполне подходит.
VD>XNA — это шанс войти на рынок.
И в догонку, конкретно по этой фразе: геймдев он гораздо ближе к медиа, нежели к it. Программирование — хорошо если четверть проекта.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, FR, Вы писали:
FR>>Nebula или Ogre тоже в разы проще в применении чем DirectX.
VD>DirectX — это АПИ, а Ogre — игровой движок. Их просто сравнивать нельзя. Ты лучше сравни игровой код для Ogre и менеджед-Ogre (если я не ошибаюсь он есть в двух вариантах).
Можно, так как XNA тоже высокоуровневая надстройка. Хотя с небулой или огром сравнивать не стоит скорее счем то попроще типа Irrlicht
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, FR, Вы писали:
FR>>То есть у тея самого никогда не было чтобы программа подвешивала систему из-за нехватки GDI ресурсов, или уходила в синий экран при работе c DX?
VD>А причем тут это? Ты вот видел менеджед-программу которая делала бы это?
А ты видел не менеджед delphi программу которая бы это делала?
VD>Чтобы терять необходимое для появления дыр в окнах количество ресурсов их нужно в цикле складывать в список. Иначе схема слежения за хэндлами их подчистит. Так что тут как раз в управляемом мире все очень хорошо. Схему слежения за ресурсами продумали создатели фрэймворка. Причем они же обеспечили подстраховку. Так что написать код который достигает описанных тобой эффектов на управляемом языке куда сложнее чем на С++.
Если на C++ пишешь использую любой высокоуровневый фреймворк то никаких отличий.
Re[7]: Сборщик мусора и размещение объектов в стеке
Здравствуйте, Константин Л., Вы писали:
КЛ>А ты возьми за правило, что деструкторы не должны кидать исключений. И вообще, пост твой не в тему.
А ты думашь, что писать на языке где нужно то и дело лезть в спеку и к тому же нужно знать море мелких правил из серии "как не пройти по коридору не наступив на грабли..." позволяет быстро писать надежный код?
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, doarn, Вы писали:
VD>>XNA — это шанс войти на рынок. D>И в догонку, конкретно по этой фразе: геймдев он гораздо ближе к медиа, нежели к it. Программирование — хорошо если четверть проекта.
Наверно так и есть. И XNA, кстати, насклько мне известно, как раз не просто либа для 3Д, а комплексное решение. См. XNA Studio.
Ну, а насколько он готов к применению не мне судить. Думаю, раз уж МС занялся, то рано или поздно до ума доведут.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, FR, Вы писали:
FR>А ты видел не менеджед delphi программу которая бы это делала?
Мы о Дельфи или о управляемом коде?
FR>Если на C++ пишешь использую любой высокоуровневый фреймворк то никаких отличий.
Ну, ну. Вот тут еао197 жаловался как-то на то, что в одном проекте приходится увязвать разные библиотеки которые получаются совместимы как уж с ежом только потому, что там были приняты разные политики управления память.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
FR>>А ты видел не менеджед delphi программу которая бы это делала?
VD>Мы о Дельфи или о управляемом коде?
Мы о том что для типовых случаев управление и ресурсами и памятью тривиально и не зависит от того управляемый фреймворк или нет.
FR>>Если на C++ пишешь использую любой высокоуровневый фреймворк то никаких отличий.
VD>Ну, ну. Вот тут еао197 жаловался как-то на то, что в одном проекте приходится увязвать разные библиотеки которые получаются совместимы как уж с ежом только потому, что там были приняты разные политики управления память.
Здравствуйте, VladD2, Вы писали:
VD>Факт в том, что в сложной программе, если конечно она должна сносно работать и не течь, дожена быть продумана и отслежена концепция вледения памятью. Это дополнительный слой головной боли.
В сложной программе дожена быть продумана и отслежена концепция управления самыми разными ресурсами — память всего лишь один из них.
Имея GC становится одного гемора поменьше, но остаётся ещё куча других ресурсов, которые надо освобождать вовремя. Если класс реализует IDisposable, то об этом надо думать обязательно, причём иногда надо знать как именно он реализован — я как-то нарывался на вещи неочевидные.
Я не к тому, что ты это не знаешь, а к тому, что в спорах ручное управление пмятью против GC очень часто передёргивают. В .NET можно тоже нехило косячитm несмотря на GC.
now playing: Scorn — Glugged
Re[8]: Сборщик мусора и размещение объектов в стеке
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, Константин Л., Вы писали:
КЛ>>А ты возьми за правило, что деструкторы не должны кидать исключений. И вообще, пост твой не в тему.
VD>А ты думашь, что писать на языке где нужно то и дело лезть в спеку и к тому же нужно знать море мелких правил из серии "как не пройти по коридору не наступив на грабли..." позволяет быстро писать надежный код?
Не думаю. Думаю, что чем тоньше стандарт, тем лучше (в ветке .NET я не давно высказался про то, что скоро без стандарта c# проги писать будет затруднительно). Однако с++ эта беда не обошла стороной и это факт. Стандарт ужасно большой и сложный. Однако я за все время коммерческой разработки на нем (~2,5 года) заглядывал в стандарт разы. Со временем он нужен все меньше и меньше.
btw, в практически любом языке есть куча мелких best practices и правил. Просто их несоблюдения для с++ заканчивается AV, а для других исключениями.
Здравствуйте, EvilChild, Вы писали:
EC>В сложной программе дожена быть продумана и отслежена концепция управления самыми разными ресурсами
+1
EC> — память всего лишь один из них.
А вот тут не совсем.
1. Памятью можно управлять автоматически.
2. Без автоматического управления память превращается в огромную проблему.
EC>Имея GC становится одного гемора поменьше, но остаётся ещё куча других ресурсов, которые надо освобождать вовремя.
Не так их много как кажется. Многие ресурсы достаточно прибивать в финализаторах. Остаются только блокирующие ресурсы. Вот их нужно отслеживать, но их обычно не много.
EC> Если класс реализует IDisposable, то об этом надо думать обязательно, причём иногда надо знать как именно он реализован — я как-то нарывался на вещи неочевидные.
Это не совсем так. В большинстве случаев все будет работать корректно даже если ты наплюешь на IDisposable. Например, формы тоже реализуют IDisposable, на на них можно забить. Если не забьешь, то будет немного лучше, но не сильно. Проблем точно не будет.
EC>Я не к тому, что ты это не знаешь, а к тому, что в спорах ручное управление пмятью против GC очень часто передёргивают. В .NET можно тоже нехило косячитm несмотря на GC.
Накосячить можно везде. Вопрос не в этом. Просто когда у тебя постоянно весит проблема управления памятью, то ты должен все время верять с ней все свои решения. Это требует постоянных умственных усилий. То что некоторые орлы тратят эти усилия незаметно для себя ровным счетом ничего не значит. Они просто привыкли трать часть своего времени впусую.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, FR, Вы писали:
VD>>Мы о Дельфи или о управляемом коде?
FR>Мы о том что для типовых случаев управление и ресурсами и памятью тривиально и не зависит от того управляемый фреймворк или нет.
Это заблуждение. И пример с Дельфи это хорошо демонстриурет. В дотнете разработан алгоритм отслеживания ресурсов. Даже если писать код крайне халтурно (без юсингов) с GDI-ресурсами особых проблем не будет. Максимум чего ты добьешся — это потеряешь в производительности. В Дельфи же потеря ресурсов будет приводить к неработоспособности приложения, а то и ОС.
FR>>>Если на C++ пишешь использую любой высокоуровневый фреймворк то никаких отличий.
VD>>Ну, ну. Вот тут еао197 жаловался как-то на то, что в одном проекте приходится увязвать разные библиотеки которые получаются совместимы как уж с ежом только потому, что там были приняты разные политики управления память.
FR>Угу "а у вас зато негров линчуют"
У нас негры давно кончились.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[9]: Сборщик мусора и размещение объектов в стеке
Здравствуйте, Константин Л., Вы писали:
КЛ>Не думаю. Думаю, что чем тоньше стандарт, тем лучше (в ветке .NET я не давно высказался про то, что скоро без стандарта c# проги писать будет затруднительно).
Ты неверно оценивашь ситуацию. То что в Шарпе появились косяки — это конечно прискорбно. Но до кривости С++ Шарпу еще очень далеко. Думаю, он никогда этого не осилит.
КЛ> Однако с++ эта беда не обошла стороной и это факт. Стандарт ужасно большой и сложный. Однако я за все время коммерческой разработки на нем (~2,5 года) заглядывал в стандарт разы. Со временем он нужен все меньше и меньше.
В С++ очень часто приходится сверяться со стандартом. Там нелогичных решений море. Одни только невертуальные вызовы виртуальных деструкторов чего стоят? Но проблема С++ даже не в сложности стандрата. Он все же не так сложен. Проблем в этом языке две:
1. Стандарт очень многое неоговаривает или оговаривает в стиле "Если сделать А, то будет UB".
2. В языке нет примитивов для решения частовтречающихся задач, вроде передаче ссылки на методы.
КЛ>btw, в практически любом языке есть куча мелких best practices и правил. Просто их несоблюдения для с++ заканчивается AV, а для других исключениями.
Не, не. Тут речь не о best practices, а о шаманстве. Сюда не ходы, туда ходы. А то снег башка попадет совсем мертвый будешь. (с)
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: Сборщик мусора и размещение объектов в стеке
Здравствуйте, PC Car, Вы писали:
PC>А что будет, если из кода внутри юзинга вылетит исключение? Которое по идее ловится на два уровня выше по колстеку?
Ресурсы освободятся, а исключение полетит выше по стеку вызовов и будет отловено на два уровня выше, но ресурс к тому времени будет уже освобожден.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Схему слежения за ресурсами продумали создатели фрэймворка.
ОС проектировалось задолго до .NET, и тогда про такое не подумали. GDI хендлы хранятся в глобальной таблице ядра, которая одна на сессию (считай — на все процессы). Один процесс никогда не сможет создать все возможные 16К хендлов — от этого есть защита (в ядре). Но 2 процесса это могут сделать очень легко. Фреймворк, видимо, должен иметь компонент в ядре, что бы за этим следить. То есть это либо решено только в новых ОС, либо не решено нигде.
P.S. BSOD при использовании DX — однозначно баг ОС либо видеодравера.
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Здравствуйте, gear nuke, Вы писали:
GN>ОС проектировалось задолго до .NET, и тогда про такое не подумали. GDI хендлы хранятся в глобальной таблице ядра, которая одна на сессию (считай — на все процессы). Один процесс никогда не сможет создать все возможные 16К хендлов — от этого есть защита (в ядре). Но 2 процесса это могут сделать очень легко. Фреймворк, видимо, должен иметь компонент в ядре, что бы за этим следить. То есть это либо решено только в новых ОС, либо не решено нигде.
Во фрэймворке сделано слежение за утеряными хэндлами. При создании хэндла он помещается в специльную обетрку. Если произходят проблемы с хэндлами, то запускается сборка мусора которая высвобождает утерянные хэндлы. Это позволяет программисту тупо не брость ненужные ресурсы, а фрэйворк их сам освободит. В отличии от файлов ГДИ-ресурсы ничего не блокируют (в NT), так что пока их достаточно проблем нет. Ну, а если их недостаточно, то сбркра мусора вернет все потерянные ресурсы.
GN>P.S. BSOD при использовании DX — однозначно баг ОС либо видеодравера.
+1
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Andrei N.Sobchuck, Вы писали:
ANS>А каким образом сборщик мусора узнаёт, что натекло достаточно хендлов для запуска GC?
Никаким. Просто при выделении ресурсов по хитрой формуле вычисляется, когда нужно запустить сборку мусора. И периодически сборка мусора запускается, пришибая в финалайзерах все ненужные хендлы. Кроме того, большая часть GDI хендлов используется ненадолго, попадает в 0 поколение и прибирается довольно быстро. Кроме того, в 2.0 есть фигня под названием memory pressure, когда GC делается намек, что этот ресурс нужно собрать побыстрее. Кроме того в 2.0 SP1 есть возможность вызвать GC не немедленно, а побыстрее, как только сложится ситуация для этого. Все это позволяет для не очень ценных unmanaged ресурсов пожддерживать их количество в разумныъх пределах автоматом. Хотя конечно, при желании, это все можно обойти.
... << RSDN@Home 1.2.0 alpha rev. 725 on Windows Vista 6.0.6000.0>>
Здравствуйте, FR, Вы писали: FR>А ты видел не менеджед delphi программу которая бы это делала?
Сколько угодно. Я учил правила дорожного движения по программе на дельфи, которая забывала освобождать загружаемые картинки. В итоге, ее приходилось регулярно перезапускать (как только она выедала всю виртуальную память)
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Сколько угодно. Я учил правила дорожного движения по программе на дельфи, которая забывала освобождать загружаемые картинки. В итоге, ее приходилось регулярно перезапускать (как только она выедала всю виртуальную память)
Сделать такое же на NET или Java тоже никаких проблем.
Здравствуйте, Sinclair, Вы писали:
S>Сколько угодно. Я учил правила дорожного движения по программе на дельфи, которая забывала освобождать загружаемые картинки. В итоге, ее приходилось регулярно перезапускать (как только она выедала всю виртуальную память)
И вообще я имел в виду, что сделать для типичных случаев авторматическое управление ресурсами не такая сложная задача и вполне решена в том же delphi или в большинстве C++ GUI бибилотек. Другое дело нетипичные случаи и когда ресурсы дорогие, тогда C++ с его автоматическим управлением оказывается более подходящим инструментом, чем языки без RAI (или равноценных аналогов).
Re[7]: Сборщик мусора и размещение объектов в стеке
_>>Особенно сладки стековые объекты в С++, когда идёт отмотка стека из-за исключения и тут из деструктора вылетает новое исключение
R>Если освобождения ресурсов/откаты действий могут не проходить, то в принципе нельзя добиться никакой осмысленной семантики, в частности консистентности нетривиальных данных. R>Например, хотим добавить значения в 2 списка:
R>
R>В точке //!!! остаётся только убить себя об стену или выпить йада, ничего лучше придумать нельзя. Т.ч. возможное завершение программы на С++ при вылете исключения из конструктора есть вполне удобная вещь — автоматизация убивания об стену.
Хм. По-моему, это просто смешение уровней абстракции. Есть желание обеспечить транзакционную семантику, но делается это на уровне прикладного кода: push(v1), push(v2). Делать ROLLBACK на том же уровне, в виде pop
Re[8]: Сборщик мусора и размещение объектов в стеке
Здравствуйте, deniok, Вы писали:
R>>В точке //!!! остаётся только убить себя об стену или выпить йада, ничего лучше придумать нельзя. Т.ч. возможное завершение программы на С++ при вылете исключения из конструктора есть вполне удобная вещь — автоматизация убивания об стену.
D>Хм. По-моему, это просто смешение уровней абстракции. Есть желание обеспечить транзакционную семантику, но делается это на уровне прикладного кода: push(v1), push(v2). Делать ROLLBACK на том же уровне, в виде pop
pop() не проходит
смотри код внимательнее, или я не понял твою мысль
з.ы. операции можно переименовать во что угодно — commit/rollback, draw/erase, create/destroy, launch_nuclear_rocket/blow_up_nuclear_rocket...
Здравствуйте, FR, Вы писали: FR>Сделать такое же на NET или Java тоже никаких проблем.
Да ну? Сборщик мусора банально соберет ненужную картинку сразу, как только на нее исчезнет ссылка.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, FR, Вы писали:
FR>И вообще я имел в виду, что сделать для типичных случаев авторматическое управление ресурсами не такая сложная задача и вполне решена в том же delphi или в большинстве C++ GUI бибилотек.
Другое дело, когда случай мало-мальски отличается от типичного. Например, большинство дельфи-разработчиков никогда не вызывают Dispose вручную, потому что для VCL-объектов поддерживается иерархия владения. Поэтому как только встречается динамическое создание объектов, которые не попадают в эту иерархию, получается программа навроде описанной мной.
Поэтому перестань нести ерунду.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
FR>>Сделать такое же на NET или Java тоже никаких проблем. S>Да ну? Сборщик мусора банально соберет ненужную картинку сразу, как только на нее исчезнет ссылка.
Не "сразу", а "когда-нибудь в будущем".
Sapienti sat!
Re[9]: Сборщик мусора и размещение объектов в стеке
Здравствуйте, remark, Вы писали:
R>Здравствуйте, deniok, Вы писали:
R>>>В точке //!!! остаётся только убить себя об стену или выпить йада, ничего лучше придумать нельзя. Т.ч. возможное завершение программы на С++ при вылете исключения из конструктора есть вполне удобная вещь — автоматизация убивания об стену.
D>>Хм. По-моему, это просто смешение уровней абстракции. Есть желание обеспечить транзакционную семантику, но делается это на уровне прикладного кода: push(v1), push(v2). Делать ROLLBACK на том же уровне, в виде pop
R>pop() не проходит R>смотри код внимательнее, или я не понял твою мысль
Именно. И я о том же. Сначала предъявляются транзакционные требования к коду, а потом идёт попытка вручную реализовать механизм транзакций. pop() для этой цели как раз тем и плох, что не проходит.
R>з.ы. операции можно переименовать во что угодно — commit/rollback, draw/erase, create/destroy, launch_nuclear_rocket/blow_up_nuclear_rocket...
Вопрос не в переименовании, а в модели. Можно поддерживать транзакции на уровне контейнера:
Вопрос в том, что эта схема должна гарантировать, что все списки, задействованные в транзакции, при возникновении исключений по ходу этой транзакции оказываются в начальном состоянии. В худшем случае это означает, что нужно сначала создать копии и при катастрофическом развитии событий подсовывать именно их.
Re[10]: Сборщик мусора и размещение объектов в стеке
Здравствуйте, deniok, Вы писали:
D>Здравствуйте, remark, Вы писали:
R>>Здравствуйте, deniok, Вы писали:
R>>>>В точке //!!! остаётся только убить себя об стену или выпить йада, ничего лучше придумать нельзя. Т.ч. возможное завершение программы на С++ при вылете исключения из конструктора есть вполне удобная вещь — автоматизация убивания об стену.
D>>>Хм. По-моему, это просто смешение уровней абстракции. Есть желание обеспечить транзакционную семантику, но делается это на уровне прикладного кода: push(v1), push(v2). Делать ROLLBACK на том же уровне, в виде pop
R>>pop() не проходит R>>смотри код внимательнее, или я не понял твою мысль
D>Именно. И я о том же. Сначала предъявляются транзакционные требования к коду, а потом идёт попытка вручную реализовать механизм транзакций. pop() для этой цели как раз тем и плох, что не проходит.
Так речь как раз и идёт о ситуации, когда ты не можешь создать функцию, которая подходит.
R>>з.ы. операции можно переименовать во что угодно — commit/rollback, draw/erase, create/destroy, launch_nuclear_rocket/blow_up_nuclear_rocket...
D>Вопрос не в переименовании, а в модели. Можно поддерживать транзакции на уровне контейнера: D>
D>Можно на глобальном уровне (типа STM в Хаскелле).
Перемещай куда угодно. Ну а толку. Ну будет этот код внутри контейнера. Если он не может сделать pop(), то это ничего не изменит. Та же безвыходная ситуация и остаётся.
STM в Хаскелле — плохой пример, т.к. в нём *можно* сделать rollback().
D>Вопрос в том, что эта схема должна гарантировать, что все списки, задействованные в транзакции, при возникновении исключений по ходу этой транзакции оказываются в начальном состоянии. В худшем случае это означает, что нужно сначала создать копии и при катастрофическом развитии событий подсовывать именно их.
Здравствуйте, Cyberax, Вы писали: C>Не "сразу", а "когда-нибудь в будущем".
Это "когда-нибудь", в частности, наступит тогда, когда под очередную загружаемую картинку не хватит памяти. Может, уже хватит фигней страдать?
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
C>>Не "сразу", а "когда-нибудь в будущем". S>Это "когда-нибудь", в частности, наступит тогда, когда под очередную загружаемую картинку не хватит памяти. Может, уже хватит фигней страдать?
Если картинки — это не просто объекты в памяти, а ссылки на системный или внешний объект, то именно "когда-нибудь в будушем".
Sapienti sat!
Re[11]: Сборщик мусора и размещение объектов в стеке
D>>Именно. И я о том же. Сначала предъявляются транзакционные требования к коду, а потом идёт попытка вручную реализовать механизм транзакций. pop() для этой цели как раз тем и плох, что не проходит.
R>Так речь как раз и идёт о ситуации, когда ты не можешь создать функцию, которая подходит.
Так вопрос как раз в том, почему я не могу создать. Либо прикладная задача, которую я решаю, противоречива, либо (в нашем случае) механизмы языка (раскрутка стека и деструкторы) не дают ее решить. Ведь хотим-то мы простой и естественной вещи — гарантированно выполнить либо оба push, либо ни одного, так ведь? Это же и есть задача приведённого кода?
R>>>з.ы. операции можно переименовать во что угодно — commit/rollback, draw/erase, create/destroy, launch_nuclear_rocket/blow_up_nuclear_rocket...
D>>Вопрос не в переименовании, а в модели. Можно поддерживать транзакции на уровне контейнера: D>>
D>>Можно на глобальном уровне (типа STM в Хаскелле).
R>Перемещай куда угодно. Ну а толку. Ну будет этот код внутри контейнера. Если он не может сделать pop(), то это ничего не изменит. Та же безвыходная ситуация и остаётся. R>STM в Хаскелле — плохой пример, т.к. в нём *можно* сделать rollback().
Естественно. Реализация механизма транзакций в этом и состоит.
D>>Вопрос в том, что эта схема должна гарантировать, что все списки, задействованные в транзакции, при возникновении исключений по ходу этой транзакции оказываются в начальном состоянии. В худшем случае это означает, что нужно сначала создать копии и при катастрофическом развитии событий подсовывать именно их.
R>А если операция "подсовывания" фэйлиться?
В данном примере операция подсовывания заключается в том, что указатели на list в begin_tran выставляются на его top в begin_tran и переставляются в последнем try_commit. Ну и клозуру из предпоследнего try_commit в последний (с перестановкой указателя) надо уметь передавать.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, FR, Вы писали: FR>>Сделать такое же на NET или Java тоже никаких проблем. S>Да ну? Сборщик мусора банально соберет ненужную картинку сразу, как только на нее исчезнет ссылка.
Файл не закроет, спроецированный файл не уберет, DX поверхность не освободит, только память почистит, и то не известно когда.
Re[12]: Сборщик мусора и размещение объектов в стеке
Здравствуйте, deniok, Вы писали:
D>Здравствуйте, remark, Вы писали:
D>>>Именно. И я о том же. Сначала предъявляются транзакционные требования к коду, а потом идёт попытка вручную реализовать механизм транзакций. pop() для этой цели как раз тем и плох, что не проходит.
R>>Так речь как раз и идёт о ситуации, когда ты не можешь создать функцию, которая подходит.
D>Так вопрос как раз в том, почему я не могу создать. Либо прикладная задача, которую я решаю, противоречива, либо (в нашем случае) механизмы языка (раскрутка стека и деструкторы) не дают ее решить. Ведь хотим-то мы простой и естественной вещи — гарантированно выполнить либо оба push, либо ни одного, так ведь? Это же и есть задача приведённого кода?
Вопрос не в том, почему я не могу создать.
Воспрос в следующем. Берём как данность, что есть некая операция типа "отмены" (pop, rollback, что угодно), которая может завершаться неуспешно. И в таком контексте задаёмся следующем вопросом. Если механизм языка (раскрутка стека и деструкторы) при возникновении исключения в деструкторе молча завершает программу, является ли это плохим/неправильным поведением. И если бы язык себя так не вёл, а вёл бы как-то по-другому, то могли бы мы добиться какого хорошего поведения в таком ситуации (когда операция типа "отмены" может проваливаться, повторюсь — это берём как данность).
Несколько постов выше с сказал, что язык винить в такой ситуации нет смысла, т.к. если бы он вёл себя как-то по-другому, то мы всё равно бы ничего хорошего не получили. Т.к. в ситуации, когда операция типа "отмены" может проваливаться, получить ничего хорошего нельзя в принципе.
D>>>Вопрос в том, что эта схема должна гарантировать, что все списки, задействованные в транзакции, при возникновении исключений по ходу этой транзакции оказываются в начальном состоянии. В худшем случае это означает, что нужно сначала создать копии и при катастрофическом развитии событий подсовывать именно их.
R>>А если операция "подсовывания" фэйлиться?
D>В данном примере операция подсовывания заключается в том, что указатели на list в begin_tran выставляются на его top в begin_tran и переставляются в последнем try_commit. Ну и клозуру из предпоследнего try_commit в последний (с перестановкой указателя) надо уметь передавать.
Это абсолютно не важно, в чём заключается операция подсовывания в данном примере.
Здравствуйте, Sinclair, Вы писали:
S>Другое дело, когда случай мало-мальски отличается от типичного. Например, большинство дельфи-разработчиков никогда не вызывают Dispose вручную, потому что для VCL-объектов поддерживается иерархия владения. Поэтому как только встречается динамическое создание объектов, которые не попадают в эту иерархию, получается программа навроде описанной мной. S>Поэтому перестань нести ерунду.
Это ты тут несешь ерунду, разговор шел не про память, а про ресурсы при том критичные. Тут GC практически ничего ни дает.
Здравствуйте, Cyberax, Вы писали: C>Если картинки — это не просто объекты в памяти, а ссылки на системный или внешний объект, то именно "когда-нибудь в будушем".
Я привел конкретный пример на конкретный вопрос. В ответ, как обычно, получаю абстрактные рассуждения.
Вот у меня в системе сейчас текут GDI объекты. И вовсе не из-за управляемого софта, а из-за 100% написанных на мегапродвинутых языках типа С++ IE7.0 и Outlook2007.
Может, все-таки хватит фигней страдать?
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Delight, Вы писали: D>Их можно в глобальную коллекцию загружать и брать оттуда, не удаляя.
Совершенно верно. Тогда память рискует кончиться сразу при старте приложения, а не через полчаса использования. Радикальное решение вопроса, спасибо
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Я привел конкретный пример на конкретный вопрос. В ответ, как обычно, получаю абстрактные рассуждения. S>Вот у меня в системе сейчас текут GDI объекты. И вовсе не из-за управляемого софта, а из-за 100% написанных на мегапродвинутых языках типа С++ IE7.0 и Outlook2007. S>Может, все-таки хватит фигней страдать?
Угу а у меня rss читалка написаная на NET летом подвешивала систему так что ее не хватало ресурсов, будем и дальше такой же ерундой заниматся?
Re[13]: Сборщик мусора и размещение объектов в стеке
R>Вопрос не в том, почему я не могу создать. R>Воспрос в следующем. Берём как данность, что есть некая операция типа "отмены" (pop, rollback, что угодно), которая может завершаться неуспешно. И в таком контексте задаёмся следующем вопросом. Если механизм языка (раскрутка стека и деструкторы) при возникновении исключения в деструкторе молча завершает программу, является ли это плохим/неправильным поведением. И если бы язык себя так не вёл, а вёл бы как-то по-другому, то могли бы мы добиться какого хорошего поведения в таком ситуации (когда операция типа "отмены" может проваливаться, повторюсь — это берём как данность). R>Несколько постов выше с сказал, что язык винить в такой ситуации нет смысла, т.к. если бы он вёл себя как-то по-другому, то мы всё равно бы ничего хорошего не получили. Т.к. в ситуации, когда операция типа "отмены" может проваливаться, получить ничего хорошего нельзя в принципе.
С этим я совершенно согласен. Если в языке есть детерминированные деструкторы, стековые объекты и модель исполнения диктует механизм исключений, жестко базирующийся на раскрутке стека, то такое поведение скорее всего оптимальное.
Здравствуйте, Sinclair, Вы писали:
S>Совершенно верно. Тогда память рискует кончиться сразу при старте приложения, а не через полчаса использования. Радикальное решение вопроса, спасибо
Я скорее имел в виду дырявую реализацию кэширования.
Здравствуйте, FR, Вы писали:
S>>Да ну? Сборщик мусора банально соберет ненужную картинку сразу, как только на нее исчезнет ссылка.
FR>Файл не закроет, спроецированный файл не уберет, DX поверхность не освободит, только память почистит, и то не известно когда.
Во-первых, никто не отменял финализаторы. Во-вторых, непонятно, зачем оставлять файл открытым тогда, когда картинка открыта. В-третьих, управление файлами — это из другой оперы, они принципиально принадлежат к классу управляемых ресурсов; для этого в управляемых средах предусмотрены close, Dispose, using и т.д.
Здравствуйте, FR, Вы писали:
FR>Угу а у меня rss читалка написаная на NET летом подвешивала систему так что ее не хватало ресурсов, будем и дальше такой же ерундой заниматся?
Как захотите. Вот я лично вижу два мегапроекта, написанных мегакрутыми парнями, причем у одного версия 7.0, а у другого — ажно 12.0. То есть затраты на QA в них обоих превышают суммарные затраты на все проекты, в которых я за свою жизнь поучаствовал, в несколько раз. И, естественно, в них применяются самые распродвинутые фреймворки на C++, которые вот здесь
рекламируются как легко справляющиеся с утечками. Однако ж вот дела, текут они хуже, чем Janus, написанный в свободное от отдыха время крохотной кучкой энтузиастов.
Смею полагать, что янус на плюсах, буде таковой вообще написан, тек бы как дуршлаг.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
C>>Если картинки — это не просто объекты в памяти, а ссылки на системный или внешний объект, то именно "когда-нибудь в будушем". S>Я привел конкретный пример на конкретный вопрос. В ответ, как обычно, получаю абстрактные рассуждения.
Кстати, могу еще один интересный пример привести — на SWT в Java точно так же нужно делать dispose() для графических объектов, чтобы их освободить. Однако, это делать можно только вручную (или неявно с помощью иерархии владения) — финализаторы для этого не используются. Как результат — более надежные приложения, так как разработчики вынуждены исправлять утечки.
S>Вот у меня в системе сейчас текут GDI объекты. И вовсе не из-за управляемого софта, а из-за 100% написанных на мегапродвинутых языках типа С++ IE7.0 и Outlook2007.
А в других браузерах и почтовых клиентах — не текут
Здравствуйте, konsoletyper, Вы писали:
K>Во-первых, никто не отменял финализаторы. Во-вторых, непонятно, зачем оставлять файл открытым тогда, когда картинка открыта. В-третьих, управление файлами — это из другой оперы, они принципиально принадлежат к классу управляемых ресурсов; для этого в управляемых средах предусмотрены close, Dispose, using и т.д.
Конечно не нужно оставлять файл открытым, и поэтому если инструмент не предоставляет средств автоматизировать такие вещи то и приходится это делать по старинке ручками через close и т. п., и управляемые инстументы в таком контексте ничем не лучше неуправляемых (delphi) и хуже чем C++.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, FR, Вы писали:
FR>>Угу а у меня rss читалка написаная на NET летом подвешивала систему так что ее не хватало ресурсов, будем и дальше такой же ерундой заниматся?
S>Как захотите. Вот я лично вижу два мегапроекта, написанных мегакрутыми парнями, причем у одного версия 7.0, а у другого — ажно 12.0. То есть затраты на QA в них обоих превышают суммарные затраты на все проекты, в которых я за свою жизнь поучаствовал, в несколько раз. И, естественно, в них применяются самые распродвинутые фреймворки на C++, которые вот здесь
рекламируются как легко справляющиеся с утечками. Однако ж вот дела, текут они хуже, чем Janus, написанный в свободное от отдыха время крохотной кучкой энтузиастов.
Не надо передергивать, может еще сравним за одно и объем кода и функциональность этих приложений?
Или может сравним с той же оперой тоже написоной на C++ и не большой как раз фирмой и гораздо более устойчивой чем IE?
S>Смею полагать, что янус на плюсах, буде таковой вообще написан, тек бы как дуршлаг.
Есть куча стабильных приложений сопоставимых по функциональности и объему с янусом написанных на C++ или том же delphi наверно их авторы забыли сказать что написать такое просто невозможно.
Я думаю будь янус на плюсах по качеству он был бы примерно таким же какой и сейчас.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, FR, Вы писали:
FR>>Угу а у меня rss читалка написаная на NET летом подвешивала систему так что ее не хватало ресурсов, будем и дальше такой же ерундой заниматся?
S>Как захотите. Вот я лично вижу два мегапроекта, написанных мегакрутыми парнями, причем у одного версия 7.0, а у другого — ажно 12.0. То есть затраты на QA в них обоих превышают суммарные затраты на все проекты, в которых я за свою жизнь поучаствовал, в несколько раз. И, естественно, в них применяются самые распродвинутые фреймворки на C++, которые вот здесь
рекламируются как легко справляющиеся с утечками. Однако ж вот дела, текут они хуже, чем Janus, написанный в свободное от отдыха время крохотной кучкой энтузиастов.
1. Как написан Janus не имеет какого-либо значения. Или ты намекаешь что при его написании нах уважаемый топ100 откровенно халтурил? Сомневаюсь.
2. Как вы вообще определяете, что они текут? При наличии исходников это бывает сделать очень сложно, а без них и подавно.
S>Смею полагать, что янус на плюсах, буде таковой вообще написан, тек бы как дуршлаг.
Re[14]: Сборщик мусора и размещение объектов в стеке
Здравствуйте, deniok, Вы писали:
D>Здравствуйте, remark, Вы писали:
R>>Вопрос не в том, почему я не могу создать. R>>Воспрос в следующем. Берём как данность, что есть некая операция типа "отмены" (pop, rollback, что угодно), которая может завершаться неуспешно. И в таком контексте задаёмся следующем вопросом. Если механизм языка (раскрутка стека и деструкторы) при возникновении исключения в деструкторе молча завершает программу, является ли это плохим/неправильным поведением. И если бы язык себя так не вёл, а вёл бы как-то по-другому, то могли бы мы добиться какого хорошего поведения в таком ситуации (когда операция типа "отмены" может проваливаться, повторюсь — это берём как данность). R>>Несколько постов выше с сказал, что язык винить в такой ситуации нет смысла, т.к. если бы он вёл себя как-то по-другому, то мы всё равно бы ничего хорошего не получили. Т.к. в ситуации, когда операция типа "отмены" может проваливаться, получить ничего хорошего нельзя в принципе.
D>С этим я совершенно согласен. Если в языке есть детерминированные деструкторы, стековые объекты и модель исполнения диктует механизм исключений, жестко базирующийся на раскрутке стека, то такое поведение скорее всего оптимальное.
Я бы даже сказал, что фактически какое именно поведение не важно. Т.к. если операция типа "отмены" может провалиться, то программе уже не поможет никакое конкретное поведение. Можно было бы вместо вызова std::terminate(), назвать поведение undefined behavior, и отдать это на откуп реализации. Скорее всего возможность возникновения такой ситуации просто свидетельствует либо об ошибке дизайна, либо о банальной ошибке в программе.
Здравствуйте, Sinclair, Вы писали:
D>>Их можно в глобальную коллекцию загружать и брать оттуда, не удаляя. S>Совершенно верно. Тогда память рискует кончиться сразу при старте приложения, а не через полчаса использования. Радикальное решение вопроса, спасибо
Кстати вполне распрастраненный паттерн в игрострое, вся память и остальные ресурсы на уровень игры выделяются и освобождаются скопом — http://www.dtf.ru/articles/print.php?id=4071
Здравствуйте, konsoletyper, Вы писали:
K>Здравствуйте, FR, Вы писали:
S>>>Да ну? Сборщик мусора банально соберет ненужную картинку сразу, как только на нее исчезнет ссылка.
FR>>Файл не закроет, спроецированный файл не уберет, DX поверхность не освободит, только память почистит, и то не известно когда.
K>Во-первых, никто не отменял финализаторы. Во-вторых, непонятно, зачем оставлять файл открытым тогда, когда картинка открыта. В-третьих, управление файлами — это из другой оперы, они принципиально принадлежат к классу управляемых ресурсов; для этого в управляемых средах предусмотрены close, Dispose, using и т.д.
Что и требовалось доказать. От malloc/free никуда не ушли. Соотв. и надёжность/утечки равны таковым при использовании malloc/free. Какие основания ожидать иного?
Далее самое интересное — если мы в управляемой среде можем реализовать надёжное управление некоторыми ресурсами с помощью close/Dispose/using (можем же, правильно?), то в чём проблема при использовании тех же средств, но в других языках и для других ресурсов?
Здравствуйте, Константин Л., Вы писали: КЛ>1. Как написан Janus не имеет какого-либо значения. Или ты намекаешь что при его написании нах уважаемый топ100 откровенно халтурил? Сомневаюсь. КЛ>2. Как вы вообще определяете, что они текут? При наличии исходников это бывает сделать очень сложно, а без них и подавно.
Гыгы. Определить это очень легко — достаточно запустить Task Manager. И когда он показывает 5000 GDI хэндлов, выданных одному приложению, и 3000 — другому, то ежу понятно, что дело не в огромном количестве тегов select. А утечка приводит к большому количеству разнообразных спецэффектов: от исчезновения smart tags в офисе и контекстных меню вообще везде, до неработоспособности встроенного поиска в аутлуке.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, remark, Вы писали: R>Что и требовалось доказать. От malloc/free никуда не ушли. Соотв. и надёжность/утечки равны таковым при использовании malloc/free. Какие основания ожидать иного? R>Далее самое интересное — если мы в управляемой среде можем реализовать надёжное управление некоторыми ресурсами с помощью close/Dispose/using (можем же, правильно?), то в чём проблема при использовании тех же средств, но в других языках и для других ресурсов?
Непонятно, как вы собираетесь реализовывать using в "других языках"? Ну, если не рассматривать Nemerle? Понятно, что сам по себе using никак не требует управляемости среды, т.к. разворачивается в совершенно стандартный код, приемлемый в практически любом интересном ЯВУ девяностых годов. По крайней мере, плюсы, дельфи и жава сделали бы это без проблем.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, remark, Вы писали: R>>Что и требовалось доказать. От malloc/free никуда не ушли. Соотв. и надёжность/утечки равны таковым при использовании malloc/free. Какие основания ожидать иного? R>>Далее самое интересное — если мы в управляемой среде можем реализовать надёжное управление некоторыми ресурсами с помощью close/Dispose/using (можем же, правильно?), то в чём проблема при использовании тех же средств, но в других языках и для других ресурсов? S>Непонятно, как вы собираетесь реализовывать using в "других языках"? Ну, если не рассматривать Nemerle? Понятно, что сам по себе using никак не требует управляемости среды, т.к. разворачивается в совершенно стандартный код, приемлемый в практически любом интересном ЯВУ девяностых годов. По крайней мере, плюсы, дельфи и жава сделали бы это без проблем.
Во-первых, это совершенно не важно. using — лишь одно средство из.
Во-вторых:
C#:
using (db_conn conn = new db_conn(pool))
{
//...
}
Здравствуйте, remark, Вы писали:
R>Здравствуйте, deniok, Вы писали:
R>Я бы даже сказал, что фактически какое именно поведение не важно. Т.к. если операция типа "отмены" может провалиться, то программе уже не поможет никакое конкретное поведение. Можно было бы вместо вызова std::terminate(), назвать поведение undefined behavior, и отдать это на откуп реализации. Скорее всего возможность возникновения такой ситуации просто свидетельствует либо об ошибке дизайна, либо о банальной ошибке в программе.
Согласен. Замечу только, что в некоторых (чистых) языках компилятор и/или программист может дать формальные гарантии, что "операция типа "отмены"" не провалится. Для довольно объемного кода этой "отмены".
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, Константин Л., Вы писали: КЛ>>1. Как написан Janus не имеет какого-либо значения. Или ты намекаешь что при его написании нах уважаемый топ100 откровенно халтурил? Сомневаюсь. КЛ>>2. Как вы вообще определяете, что они текут? При наличии исходников это бывает сделать очень сложно, а без них и подавно. S>Гыгы. Определить это очень легко — достаточно запустить Task Manager. И когда он показывает 5000 GDI хэндлов, выданных одному приложению, и 3000 — другому, то ежу понятно, что дело не в огромном количестве тегов select. А утечка приводит к большому количеству разнообразных спецэффектов: от исчезновения smart tags в офисе и контекстных меню вообще везде, до неработоспособности встроенного поиска в аутлуке.
Прошу прощения, я имел ввиду память. Тем более что "течет" понятие субъективное.
Здравствуйте, Константин Л., Вы писали:
КЛ>Здравствуйте, Sinclair, Вы писали:
КЛ>[]
S>>Ну да, то же самое, только наоборот. У юзинга скоуп определен следующей за ним парой скобок, у conn — объемлющей.
КЛ>и?
Здравствуйте, VladD2, Вы писали:
FR>>Если на C++ пишешь использую любой высокоуровневый фреймворк то никаких отличий.
VD>Ну, ну. Вот тут еао197 жаловался как-то на то, что в одном проекте приходится увязвать разные библиотеки которые получаются совместимы как уж с ежом только потому, что там были приняты разные политики управления память.
Про управление памятью говорил, есть такое дело. Хуже всего с этим у GDI библиотек, но там, вероятно, своя специфика.
А вот высокоуровневых С++ библиотек, в которых бы утекали другие ресурсы (GDI хендлы, сокеты, мутексы и пр.) не видел. Хотя приходилось объединять, например, Qt и Crypto++, ACE с Qt, ACE с FOX Toolkit и пр.
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Что требовалось доказать?
R> От malloc/free никуда не ушли.
Ушли. Файлы и память — раные вещи. С файлами работают только части программы, ответственные за ввод/вывод, а с памятью так или иначе работает вся программа.
R>Соотв. и надёжность/утечки равны таковым при использовании malloc/free. Какие основания ожидать иного?
Не равны. Если есть GC, то надёжность сильно возрастает. За счёт того, что в 99% мест, где управление было бы ручным, оно станет автоматическим. А с файлами да, придётся по-преэнемы трахаться. Но это в десятки раз меньше траха, чем с памятью.
R>Далее самое интересное — если мы в управляемой среде можем реализовать надёжное управление некоторыми ресурсами с помощью close/Dispose/using (можем же, правильно?), то в чём проблема при использовании тех же средств, но в других языках и для других ресурсов?
Не можем мы организовать надёжное ручное управление ресурсами! И никто обратного не утверждал. Самое надёжное управление — это автоматическое.
В других языках зато либо вообще отсутсвует возможность автоматического управления ресурсами (C), либо это делается так, что хочется проклинать и язык, и ресурсы (C++). Д а и что тут "другие"? Языков, требующих GC немало, они не ограничиваются Java/C#. Так вот, при этом ручное управление ресурсами одинаково хорошо реализовано и в С, и в C++, и в C#. Значит, у языков с GC есть некоторое преимущество.
Здравствуйте, FR, Вы писали:
FR>Конечно не нужно оставлять файл открытым, и поэтому если инструмент не предоставляет средств автоматизировать такие вещи то и приходится это делать по старинке ручками через close и т. п., и управляемые инстументы в таком контексте ничем не лучше неуправляемых (delphi) и хуже чем C++.
Здравствуйте, konsoletyper, Вы писали:
K>Здравствуйте, remark, Вы писали:
R>>Что и требовалось доказать.
K>Что требовалось доказать?
R>> От malloc/free никуда не ушли.
K>Ушли. Файлы и память — раные вещи. С файлами работают только части программы, ответственные за ввод/вывод, а с памятью так или иначе работает вся программа.
R>>Соотв. и надёжность/утечки равны таковым при использовании malloc/free. Какие основания ожидать иного?
K>Не равны. Если есть GC, то надёжность сильно возрастает. За счёт того, что в 99% мест, где управление было бы ручным, оно станет автоматическим. А с файлами да, придётся по-преэнемы трахаться. Но это в десятки раз меньше траха, чем с памятью.
R>>Далее самое интересное — если мы в управляемой среде можем реализовать надёжное управление некоторыми ресурсами с помощью close/Dispose/using (можем же, правильно?), то в чём проблема при использовании тех же средств, но в других языках и для других ресурсов?
K>Не можем мы организовать надёжное ручное управление ресурсами! И никто обратного не утверждал. Самое надёжное управление — это автоматическое.
K>В других языках зато либо вообще отсутсвует возможность автоматического управления ресурсами (C), либо это делается так, что хочется проклинать и язык, и ресурсы (C++). Д а и что тут "другие"? Языков, требующих GC немало, они не ограничиваются Java/C#. Так вот, при этом ручное управление ресурсами одинаково хорошо реализовано и в С, и в C++, и в C#. Значит, у языков с GC есть некоторое преимущество.
Забудем на время про память, и рассмотрим все остальные ресурсы — файла, сокеты, соединения с БД, графические хэндлы и всевозможные хэндлы различных библиотек. Программисты на управляемых языках умеют писать программы безопасные по отношению к этим ресурсам?
з.ы. не знаю как ты пишешь на С++, но я пишу так и ничего не проклинаю:
file f ("data");
//...
Этот фрагмент не менее надёжен, чем аналог на управляемом языке.
з.з.ы. Аналогично работаю с памятью. Это аналогично не менее надёжно. Никаких утечек не помню на протяжении лет...
Здравствуйте, remark, Вы писали:
R>Забудем на время про память, и рассмотрим все остальные ресурсы — файла, сокеты, соединения с БД, графические хэндлы и всевозможные хэндлы различных библиотек.
Я же говорю — с памятью обычно работы гораздо больше. К тому же, с памятью попадаются гораздо более изощрённые ситуации, чем со всем остальным. Хэндлы — это от лукавого, если бы ОС изначально проектировалась в расчёте на managed-среду, то таких проблем не возникало бы в принципе. В соединении с БД аналогично: всякие кэши и прочее мог бы собирать GC, а явно управлять нужно управлять сокетом/файлом/расшаренной памятью. Т.е. вручную есть смысл управлять теми ресурсами, к которым имеет доступ несколько процессов. В данном случае вообще, мы вынуждены управлять не временем жизни, а лишь временем эксклюзивного доступа к ресурсу.
R> Программисты на управляемых языках умеют писать программы безопасные по отношению к этим ресурсам?
Ага. А что им должно мешать?
R>з.ы. не знаю как ты пишешь на С++, но я пишу так и ничего не проклинаю: R>
R>file f ("data");
R>//...
R>
R>Этот фрагмент не менее надёжен, чем аналог на управляемом языке. R>з.з.ы. Аналогично работаю с памятью. Это аналогично не менее надёжно. Никаких утечек не помню на протяжении лет...
Это тривиальный случай. Вообще, в случае с файлами как правило не приходится сильно извращаться. С памятью бывает полный ППЦ. Например, те же вещи связанные с генерацией ДКА по регулярному выражению. Или задача на ICFP 2007 (интерпретатор генов), которая _оптимально_ в случае с GC решается легко и естественно, а без GC приходится извращаться. Или та, задача, которую я решаю сейчас — выделение из прайс-листов полезной информации и запихивание её в БД. Вот сижу, смотрю на свой код на C#, и думаю: до чего же надо иметь извращённый мозг, чтобы во всей этой трёхэтажной алгоритмике, вовсю нашпигованной эвристикой, ещё и памятью управлять?
ЗЫ: А что если надо открыть файл, и вернуть кортеж, содержащий в том числе и хэндл, а потом этот кортеж учавтствует в формировании множеств элеметов (которые так же содержат хэндл), которые помещаются в узлы некого дерева, причём эти множества могут дублироваться в разных узлах? А что если потом это дерево несколько раз хитро обходится и на каждом обходе строится некая модификация дерева? И как потом всё это удалить, затрагивая лишь то, на что не осталось ссылок?
Здравствуйте, konsoletyper, Вы писали:
FR>>Тем что в них управлять ресурсами чуть сложнее чем в C++.
K>В 99% случаев ими вообще не нужно управлять. Зато в этих 99% случаев, когда в C#/Java всё просто и логично, в C++ — кошмар.
Ваши страхи по поводу C++ сильно преувеличены.
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Здравствуйте, konsoletyper, Вы писали:
K>ЗЫ: А что если надо открыть файл, и вернуть кортеж, содержащий в том числе и хэндл, а потом этот кортеж учавтствует в формировании множеств элеметов (которые так же содержат хэндл), которые помещаются в узлы некого дерева, причём эти множества могут дублироваться в разных узлах? А что если потом это дерево несколько раз хитро обходится и на каждом обходе строится некая модификация дерева? И как потом всё это удалить, затрагивая лишь то, на что не осталось ссылок?
А как вы будете все это делать с GC, если все это нужно будет действительно _удалить_, а не оставить в мусоре до следующего прихода GC?
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Здравствуйте, konsoletyper, Вы писали:
K>Это тривиальный случай. Вообще, в случае с файлами как правило не приходится сильно извращаться. С памятью бывает полный ППЦ. Например, те же вещи связанные с генерацией ДКА по регулярному выражению. Или задача на ICFP 2007 (интерпретатор генов), которая _оптимально_ в случае с GC решается легко и естественно, а без GC приходится извращаться. Или та, задача, которую я решаю сейчас — выделение из прайс-листов полезной информации и запихивание её в БД. Вот сижу, смотрю на свой код на C#, и думаю: до чего же надо иметь извращённый мозг, чтобы во всей этой трёхэтажной алгоритмике, вовсю нашпигованной эвристикой, ещё и памятью управлять?
Мне кажется у тебя неверная предросылка, о том что С++ програмист управляет памятью. На самом деле опытный профи совершенно не будет тратить на это время и переложит все управление на обертки.
Здравствуйте, minorlogic, Вы писали:
M>Мне кажется у тебя неверная предросылка, о том что С++ програмист управляет памятью. На самом деле опытный профи совершенно не будет тратить на это время и переложит все управление на обертки.
Я знаю про всякие мутации смартпоинтеров и про способы прикручивания GC к C++. Но тут есть одна штука. В C++ по умолчанию ресурсами надо управлять вручную, потому есть определённая вероятность ошибиться и заюзать небезопасные указатели и т.п.
Здравствуйте, remark, Вы писали:
R>Забудем на время про память, и рассмотрим все остальные ресурсы — файла, сокеты, соединения с БД, графические хэндлы и всевозможные хэндлы различных библиотек. Программисты на управляемых языках умеют писать программы безопасные по отношению к этим ресурсам?
На безопасных языках возможно реализовать автоматику для любых ресурсов, которые не требуют детерминированного завершения и не являются сверхценными. В твоем примере "графические хэндлы и всевозможные хэндлы различных библиотек" таковыми могут и не являться. Штатно в дотнете подобное управление реализовано для хендлов GDI и USER, причем первые реально никто почти никогда не чистит руками. Тем не менее к проблемам это не приводит.
... << RSDN@Home 1.2.0 alpha rev. 725 on Windows Vista 6.0.6000.0>>
Здравствуйте, minorlogic, Вы писали:
M>Мне кажется у тебя неверная предросылка, о том что С++ програмист управляет памятью.
Ну да, в шарпе проблема явно юзинг указать для детерминированного завершения, а явно использовать смартпоинтеры для любого класса и руками разруливать циклы, это конечно не проблема .
... << RSDN@Home 1.2.0 alpha rev. 725 on Windows Vista 6.0.6000.0>>
Здравствуйте, konsoletyper, Вы писали:
K>В других языках зато либо вообще отсутсвует возможность автоматического управления ресурсами (C), либо это делается так, что хочется проклинать и язык, и ресурсы (C++). Д а и что тут "другие"? Языков, требующих GC немало, они не ограничиваются Java/C#. Так вот, при этом ручное управление ресурсами одинаково хорошо реализовано и в С, и в C++, и в C#. Значит, у языков с GC есть некоторое преимущество.
Кстати, есть, на мой взгляд, как минимум одна область, где GC дает явное преимущество, а возможно и просто является необходимостью — многопоточные и асинхронные приложения. В свое время я набросал кое-что в блоге по этому поводу. А в библиотеке acto мне пришлось двухфазное удаление делать (так как в С++ нет GC). А все потому, что ссылки на объект могут находиться в другом потоке, или в какой-нибудь очереди сообщений и явное удаление просто обрушит программу...
Здравствуйте, konsoletyper, Вы писали:
K>Это тривиальный случай. Вообще, в случае с файлами как правило не приходится сильно извращаться. С памятью бывает полный ППЦ. Например, те же вещи связанные с генерацией ДКА по регулярному выражению. Или задача на ICFP 2007 (интерпретатор генов), которая _оптимально_ в случае с GC решается легко и естественно, а без GC приходится извращаться.
Это не совсем так — там просто нужна структура типа "веревка". На чистом С++ она тоже неплохо делается, причем даже работает вполне быстро
K>Или та, задача, которую я решаю сейчас — выделение из прайс-листов полезной информации и запихивание её в БД. Вот сижу, смотрю на свой код на C#, и думаю: до чего же надо иметь извращённый мозг, чтобы во всей этой трёхэтажной алгоритмике, вовсю нашпигованной эвристикой, ещё и памятью управлять?
В таких задачах, действительно, сборщик мусора вполне нормально подходит.
Здравствуйте, eao197, Вы писали:
E>А как вы будете все это делать с GC, если все это нужно будет действительно _удалить_, а не оставить в мусоре до следующего прихода GC?
GC.Collect() ?
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Cyberax, Вы писали:
C>Это не совсем так — там просто нужна структура типа "веревка". На чистом С++ она тоже неплохо делается, причем даже работает вполне быстро
Что это за структура?
C>В таких задачах, действительно, сборщик мусора вполне нормально подходит.
Здравствуйте, Sinclair, Вы писали:
S>GC.Collect() ?
Тяжеловато, да и, скажем, не гарантируется в Java. ИМХО подход с возможностью и явного, и неявного освобождения логичнее (привет, D), хотя и не без своих проблем.
Здравствуйте, Delight, Вы писали: D>Тяжеловато, да и, скажем, не гарантируется в Java. ИМХО подход с возможностью и явного, и неявного освобождения логичнее (привет, D), хотя и не без своих проблем.
Как правило, явное освобождение памяти (кроме вырожденных случаев) приносит больше проблем, чем решает.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, konsoletyper, Вы писали:
K>Я знаю про всякие мутации смартпоинтеров и про способы прикручивания GC к C++. Но тут есть одна штука. В C++ по умолчанию ресурсами надо управлять вручную, потому есть определённая вероятность ошибиться и заюзать небезопасные указатели и т.п.
Возможность для ошибки существует всегда (с этим странно спорить) . Я коментировал высказывание о том что програмируя на С++ програмист тратит время на управление ресурсами.
Здравствуйте, Sinclair, Вы писали:
E>>А как вы будете все это делать с GC, если все это нужно будет действительно _удалить_, а не оставить в мусоре до следующего прихода GC? S>GC.Collect() ?
Т.е. это нормальное решение, когда какая-то подсистема приложения дергает GC всего приложения для того, чтобы очистить свои ресурсы?
Но меня вот что больше интересует: принято ли при разработке компонентов на Java или .NET где-то документировать, что компонент инициирует внутри себя сборку мусора?
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Здравствуйте, Стэн, Вы писали:
С>Кстати, есть, на мой взгляд, как минимум одна область, где GC дает явное преимущество, а возможно и просто является необходимостью — многопоточные и асинхронные приложения.
Где GC может стать причиной остановки большого количества потоков для сборки мусора.
С>В свое время я набросал кое-что в блоге по этому поводу. А в библиотеке acto мне пришлось двухфазное удаление делать (так как в С++ нет GC).
В связи с этим вопрос -- а зачем было делать библиотеку на C++?
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Здравствуйте, eao197, Вы писали:
E>Где GC может стать причиной остановки большого количества потоков для сборки мусора.
Кстати, в java 6 научились вызывать не только stop-the-world, но и конкурентный сборщик мусора. Это снимает проблему блокирования приложения, но пропадает гарантия, что "управляемый неуправляемый" ресурс будет убран в обозримом будущем.
Здравствуйте, eao197, Вы писали: E>Т.е. это нормальное решение, когда какая-то подсистема приложения дергает GC всего приложения для того, чтобы очистить свои ресурсы?
Это — нет. По идее, у подсистемы должен быть свой независимый GC. Но такое щасте нам будет доступно только в 100%-managed OS.
E>Но меня вот что больше интересует: принято ли при разработке компонентов на Java или .NET где-то документировать, что компонент инициирует внутри себя сборку мусора?
По разному.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
E>>Т.е. это нормальное решение, когда какая-то подсистема приложения дергает GC всего приложения для того, чтобы очистить свои ресурсы? S>Это — нет. По идее, у подсистемы должен быть свой независимый GC. Но такое щасте нам будет доступно только в 100%-managed OS.
А почему так категорично на счет OS? Например, если мы на языке с GC делаем текстовый процессор, то создаем его из нескольких библиотек-подсистем. Одна из подсистем отвечает за отображение структуры документа, как раз она и строит хитрые деревья с хендлами ресурсов в узлах. Когда пользователь закрывает окно с графической структурой документа, это дерево должно быть разрушено. Вроде как все работает в рамках одного процесса, причем же здесь OS?
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Здравствуйте, Sinclair, Вы писали:
E>>Т.е. это нормальное решение, когда какая-то подсистема приложения дергает GC всего приложения для того, чтобы очистить свои ресурсы? S>Это — нет. По идее, у подсистемы должен быть свой независимый GC. Но такое щасте нам будет доступно только в 100%-managed OS.
Ничего не даст. Всё равно нужно запускать GC в контексте приложения захватившего ресурс. А это либо stop-the-world в приложении, либо без гарантии, что ресурс будет убран.
Здравствуйте, eao197, Вы писали:
E>Здравствуйте, Стэн, Вы писали:
С>>Кстати, есть, на мой взгляд, как минимум одна область, где GC дает явное преимущество, а возможно и просто является необходимостью — многопоточные и асинхронные приложения.
E>Где GC может стать причиной остановки большого количества потоков для сборки мусора.
Ведь есть же разные алгоритмы, необязательно все останавливать разом?!.. Ну и много ли имеется вариантов по данному вопросу? Когда произвольная схема многопоточности (каждый поток может взаимодействовать с любым другим), когда актеры могут произвольным образом между собой связываться и взаимодействовать... Вот как в такой системе управлять их временем жизни и при этом, по-возможности, не заставлять пользователя следить за этим самостоятельно?
С>>В свое время я набросал кое-что в блоге по этому поводу. А в библиотеке acto мне пришлось двухфазное удаление делать (так как в С++ нет GC).
E>В связи с этим вопрос -- а зачем было делать библиотеку на C++?
Не на C++, а для С++... Приходится писать на C++, ну и хочется какого-то человеческого взаимодействия между потоками. Однажды мне пришлось делать небольшую программу, где была необходимость асинхронного взаимодействия между потоками, там я использовал Windows-очередь, но это уж как-то совсем неудобно мне показалось...
Здравствуйте, Стэн, Вы писали:
С>Здравствуйте, eao197, Вы писали:
E>>Здравствуйте, Стэн, Вы писали:
С>>>Кстати, есть, на мой взгляд, как минимум одна область, где GC дает явное преимущество, а возможно и просто является необходимостью — многопоточные и асинхронные приложения.
E>>Где GC может стать причиной остановки большого количества потоков для сборки мусора. С>Ведь есть же разные алгоритмы, необязательно все останавливать разом?!.. Ну и много ли имеется вариантов по данному вопросу? Когда произвольная схема многопоточности (каждый поток может взаимодействовать с любым другим), когда актеры могут произвольным образом между собой связываться и взаимодействовать... Вот как в такой системе управлять их временем жизни и при этом, по-возможности, не заставлять пользователя следить за этим самостоятельно?
А в чём проблема? Никаких отличий от использования обычного умного указателя, например shared_ptr, для пользователя не будет.
Банально shared_ptr может делать atomic_inc/atomic_dec для счётчика ссылок, либо применять какую-то более умную схему. Но это не важно с т.з. пользователя, т.к. для него будет тот же "smart_ptr", а уж что он там делает за кулисами — не касается пользователя.
Почему у тебя там возникли проблемы — не понимаю...
Погляди реализацию в SObjectizer — там, например, когда актёру посылается сообщение, для него инкрементируется счётчик, а когда обработка завершается — декрементируется.
Здравствуйте, Стэн, Вы писали:
С>Здравствуйте, konsoletyper, Вы писали:
K>>В других языках зато либо вообще отсутсвует возможность автоматического управления ресурсами (C), либо это делается так, что хочется проклинать и язык, и ресурсы (C++). Д а и что тут "другие"? Языков, требующих GC немало, они не ограничиваются Java/C#. Так вот, при этом ручное управление ресурсами одинаково хорошо реализовано и в С, и в C++, и в C#. Значит, у языков с GC есть некоторое преимущество.
С>Кстати, есть, на мой взгляд, как минимум одна область, где GC дает явное преимущество, а возможно и просто является необходимостью — многопоточные и асинхронные приложения. В свое время я набросал кое-что в блоге по этому поводу. А в библиотеке acto мне пришлось двухфазное удаление делать (так как в С++ нет GC). А все потому, что ссылки на объект могут находиться в другом потоке, или в какой-нибудь очереди сообщений и явное удаление просто обрушит программу...
Там в блоге практически ничего нет. По существу только — определение циклов. Но это проблема существовала и до многопоточности и асинхронности. И соотв. не имеет с ней ничего общего.
Решали же все проблему циклов. Первый вариант — не создавать циклов. Второй — создавать циклы, но с помощью weak_ptr, т.ч. не было сильных циклов. Третьий — вручную разрушать циклы, когда они перестают быть нужны. Я не вижу тут никакой связи ни с многопоточностью, ни с асинхронностью... за исключением того, что это становится немного сложнее...
Здравствуйте, AndrewVK, Вы писали:
AVK>Здравствуйте, minorlogic, Вы писали:
M>>Мне кажется у тебя неверная предросылка, о том что С++ програмист управляет памятью.
AVK>Ну да, в шарпе проблема явно юзинг указать для детерминированного завершения, а явно использовать смартпоинтеры для любого класса и руками разруливать циклы, это конечно не проблема .
Хух... Последние полдня мучался, что бы использовать смарт-поинтер для одного объекта. Вроде получилось. Да... не лёгкое было дело. Надо будет ещё протестировать, корректно ли он использовался, или ошибся где-нибудь...
Завтра буду весь день заниматься организацией циклов объектов, т.ч. не поминайте лихом. Да... циклы объектов — это вообще беда... Пора браться за ум и отучаться от этого моветона...
Здравствуйте, remark, Вы писали:
E>>>Где GC может стать причиной остановки большого количества потоков для сборки мусора. С>>Ведь есть же разные алгоритмы, необязательно все останавливать разом?!.. Ну и много ли имеется вариантов по данному вопросу? Когда произвольная схема многопоточности (каждый поток может взаимодействовать с любым другим), когда актеры могут произвольным образом между собой связываться и взаимодействовать... Вот как в такой системе управлять их временем жизни и при этом, по-возможности, не заставлять пользователя следить за этим самостоятельно?
R>А в чём проблема? Никаких отличий от использования обычного умного указателя, например shared_ptr, для пользователя не будет. R>Банально shared_ptr может делать atomic_inc/atomic_dec для счётчика ссылок, либо применять какую-то более умную схему. Но это не важно с т.з. пользователя, т.к. для него будет тот же "smart_ptr", а уж что он там делает за кулисами — не касается пользователя. R>Почему у тебя там возникли проблемы — не понимаю... R>Погляди реализацию в SObjectizer — там, например, когда актёру посылается сообщение, для него инкрементируется счётчик, а когда обработка завершается — декрементируется.
Вот, как раз с сообщениями у меня проблем меньше всего. Но актеры не просто посылают сообщения друг другу, но и связи между собой устанавливают. Каждый актер хранит ссылку на самого себя, плюс пользователь еще может добавить парочку таких ссылок, а еще можно описать схему, где a->b->c->a, ну и еще кучу разнообразных вариантов... а еще все это может меняться динамически... И как в общем случае управлять таким графом актеров, но так, чтобы не рубить жестко связи (это не всегда подходит) и чтобы не забывать ненужное?
Здравствуйте, Стэн, Вы писали:
С>Здравствуйте, remark, Вы писали:
E>>>>Где GC может стать причиной остановки большого количества потоков для сборки мусора. С>>>Ведь есть же разные алгоритмы, необязательно все останавливать разом?!.. Ну и много ли имеется вариантов по данному вопросу? Когда произвольная схема многопоточности (каждый поток может взаимодействовать с любым другим), когда актеры могут произвольным образом между собой связываться и взаимодействовать... Вот как в такой системе управлять их временем жизни и при этом, по-возможности, не заставлять пользователя следить за этим самостоятельно?
R>>А в чём проблема? Никаких отличий от использования обычного умного указателя, например shared_ptr, для пользователя не будет. R>>Банально shared_ptr может делать atomic_inc/atomic_dec для счётчика ссылок, либо применять какую-то более умную схему. Но это не важно с т.з. пользователя, т.к. для него будет тот же "smart_ptr", а уж что он там делает за кулисами — не касается пользователя. R>>Почему у тебя там возникли проблемы — не понимаю... R>>Погляди реализацию в SObjectizer — там, например, когда актёру посылается сообщение, для него инкрементируется счётчик, а когда обработка завершается — декрементируется. С>Вот, как раз с сообщениями у меня проблем меньше всего. Но актеры не просто посылают сообщения друг другу, но и связи между собой устанавливают.
С>Каждый актер хранит ссылку на самого себя,
не имеет значения
С>плюс пользователь еще может добавить парочку таких ссылок,
не имеет значения
С>а еще можно описать схему, где a->b->c->a,
классический цикл. как говорится пользователь "сам дурак", если такое сделал. проблемы бы у него были и без актёров, и без асинхронности, и без многопоточности.
С>ну и еще кучу разнообразных вариантов...
не имеет значения
С>а еще все это может меняться динамически...
konsoletyper wrote: > C>Это не совсем так — там просто нужна структура типа "веревка". На > чистом С++ она тоже неплохо делается, причем даже работает вполне быстро > Что это за структура? http://en.wikipedia.org/wiki/Rope_%28computer_science%29
Sinclair wrote: > E>Т.е. это нормальное решение, когда какая-то подсистема приложения > дергает GC всего приложения для того, чтобы очистить свои ресурсы? > Это — нет. По идее, у подсистемы должен быть свой независимый GC. Но > такое щасте нам будет доступно только в 100%-managed OS.
Тогда другая проблема — все вызовы между доменами придется маршаллить.
Здравствуйте, Стэн, Вы писали:
С>>>Кстати, есть, на мой взгляд, как минимум одна область, где GC дает явное преимущество, а возможно и просто является необходимостью — многопоточные и асинхронные приложения.
E>>Где GC может стать причиной остановки большого количества потоков для сборки мусора. С>Ведь есть же разные алгоритмы, необязательно все останавливать разом?!..
Я и не говорил про остановку всего разом. Но то что часть потоков будет одновременно приостановлена GC -- это факт. И в какой момент это произойдет заранее не известно.
С>Ну и много ли имеется вариантов по данному вопросу? Когда произвольная схема многопоточности (каждый поток может взаимодействовать с любым другим), когда актеры могут произвольным образом между собой связываться и взаимодействовать... Вот как в такой системе управлять их временем жизни и при этом, по-возможности, не заставлять пользователя следить за этим самостоятельно?
Пользователю в любом случае придется как-то помечать уже не нужные ему актеры. Автор фреймворка должен будет только определиться с тем, как пользователь будет это делать: вызывать какой-нибудь deregister_actor или delete в C++, или занулять ссылку на актера в языке с GC. А остальное уже дело техники.
С>>>В свое время я набросал кое-что в блоге по этому поводу. А в библиотеке acto мне пришлось двухфазное удаление делать (так как в С++ нет GC).
E>>В связи с этим вопрос -- а зачем было делать библиотеку на C++? С>Не на C++, а для С++... Приходится писать на C++, ну и хочется какого-то человеческого взаимодействия между потоками. Однажды мне пришлось делать небольшую программу, где была необходимость асинхронного взаимодействия между потоками, там я использовал Windows-очередь, но это уж как-то совсем неудобно мне показалось...
Как-то странно -- делать на C++ и вздыхать по поводу отсутствия GC
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Здравствуйте, Cyberax, Вы писали: C>Тогда другая проблема — все вызовы между доменами придется маршаллить.
Нда, я пожалуй погорячился.
Вообще, должно быть другое решение.
Идея решения примерно такова: при нехватке любого ресурса поток встает на ожидании освобождения; как только встали все потоки — единственный, кому можно работать, это GC и finalyzer thread. Ну то есть необязательно доводить совсем уж до упора, чем больше потоков тормознулось, тем выше шансы у GC запуститься.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Ну то есть необязательно доводить совсем уж до упора, чем больше потоков тормознулось, тем выше шансы у GC запуститься.
Это не решает проблемы анализа — что можно трогать, а что нельзя. Столь сильное усложнение GC в итоге скорее всего приведет к суммарному замедлению, а не ускорению. Тут скорее надо думать в сторону аппаратной поддержки ссылок, по типу того же Эльбруса, и аппаратного же сканера деревьев ссылок. Тогда можно думать в сторону реально конкурентной сборки.
... << RSDN@Home 1.2.0 alpha rev. 725 on Windows Vista 6.0.6000.0>>
Здравствуйте, eao197, Вы писали:
С>>Ну и много ли имеется вариантов по данному вопросу? Когда произвольная схема многопоточности (каждый поток может взаимодействовать с любым другим), когда актеры могут произвольным образом между собой связываться и взаимодействовать... Вот как в такой системе управлять их временем жизни и при этом, по-возможности, не заставлять пользователя следить за этим самостоятельно?
E>Пользователю в любом случае придется как-то помечать уже не нужные ему актеры. Автор фреймворка должен будет только определиться с тем, как пользователь будет это делать: вызывать какой-нибудь deregister_actor или delete в C++, или занулять ссылку на актера в языке с GC. А остальное уже дело техники.
Здравствуйте, remark, Вы писали:
С>>>Ну и много ли имеется вариантов по данному вопросу? Когда произвольная схема многопоточности (каждый поток может взаимодействовать с любым другим), когда актеры могут произвольным образом между собой связываться и взаимодействовать... Вот как в такой системе управлять их временем жизни и при этом, по-возможности, не заставлять пользователя следить за этим самостоятельно?
E>>Пользователю в любом случае придется как-то помечать уже не нужные ему актеры. Автор фреймворка должен будет только определиться с тем, как пользователь будет это делать: вызывать какой-нибудь deregister_actor или delete в C++, или занулять ссылку на актера в языке с GC. А остальное уже дело техники.
R>смарт поинтер не рассматривается?
Дело не в смарт-пойнтере, это всего лишь частный случай указателя.
Я о другом говорю. Стэн ведет речь об агентной системе, в которой агенты/актеры хранят ссылки (указатели, смарт-пойтнеры) на себя. Т.е. каждый актер знает своих клиентов непосредственно, без использования каких-либо форм косвенной адресации (в виде имен или идентификаторов). Т.е., предположим у нас есть два агента: producer и consumer:
class producer : public actor
{
private :
consumer * m_consumer;
public :
void on_some_event()
{
// Что-то произошло, consumer-у нужно отослать данные.
m_consumer->send( new data( ... ) );
}
};
class consumer : public actor
{
private :
producer * m_producer;
public :
void on_data( const data * msg )
{
// Обработка данных...
// Заставляем producer-а выдать следующую порцию данных.
m_producer->send( new get_next_data( ... ) );
}
};
Теперь, предположим, что producer-у нужно изъять из системы своего consumer-а. Он должен дать фреймворку какое-то указание о том, что значение producer::m_consumer больше не актуально (хотя на этого consumer-а могу ссылаться другие агенты). Выбрать как это указание будет выполняться -- задача дизайнера фреймворка.
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Здравствуйте, eao197, Вы писали:
R>>смарт поинтер не рассматривается?
E>Дело не в смарт-пойнтере, это всего лишь частный случай указателя. E>Я о другом говорю. Стэн ведет речь об агентной системе, в которой агенты/актеры хранят ссылки (указатели, смарт-пойтнеры) на себя. Т.е. каждый актер знает своих клиентов непосредственно, без использования каких-либо форм косвенной адресации (в виде имен или идентификаторов). Т.е., предположим у нас есть два агента: producer и consumer: E>Теперь, предположим, что producer-у нужно изъять из системы своего consumer-а. Он должен дать фреймворку какое-то указание о том, что значение producer::m_consumer больше не актуально (хотя на этого consumer-а могу ссылаться другие агенты). Выбрать как это указание будет выполняться -- задача дизайнера фреймворка.
Почему же о другом?
class producer : public actor
{
private :
agent_handle<consumer> m_consumer;
public :
void on_some_event()
{
// Что-то произошло, consumer-у нужно отослать данные.
m_consumer->send( new data( ... ) );
}
void on_stop()
{
m_consumer.reset();
}
};
Здравствуйте, remark, Вы писали:
R>>>смарт поинтер не рассматривается?
E>>Дело не в смарт-пойнтере, это всего лишь частный случай указателя. E>>Я о другом говорю. Стэн ведет речь об агентной системе, в которой агенты/актеры хранят ссылки (указатели, смарт-пойтнеры) на себя. Т.е. каждый актер знает своих клиентов непосредственно, без использования каких-либо форм косвенной адресации (в виде имен или идентификаторов). Т.е., предположим у нас есть два агента: producer и consumer: E>>Теперь, предположим, что producer-у нужно изъять из системы своего consumer-а. Он должен дать фреймворку какое-то указание о том, что значение producer::m_consumer больше не актуально (хотя на этого consumer-а могу ссылаться другие агенты). Выбрать как это указание будет выполняться -- задача дизайнера фреймворка.
R>Почему же о другом?
А потому, что кроме подхода Стэна, где агенты хранят ссылки/указатели друг на друга, возможен и другой подход к организации связей между агентами. Через косвенную адресацию в виде имен/идентификаторов агентов. В случае подхода Стэна неизбежны какие-то формы указателей, хоть голые, хоть смарт-пойнтеры. Но при другом подходе -- это уже не важно.
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Здравствуйте, eao197, Вы писали:
E>Здравствуйте, remark, Вы писали:
R>>>>смарт поинтер не рассматривается?
E>>>Дело не в смарт-пойнтере, это всего лишь частный случай указателя. E>>>Я о другом говорю. Стэн ведет речь об агентной системе, в которой агенты/актеры хранят ссылки (указатели, смарт-пойтнеры) на себя. Т.е. каждый актер знает своих клиентов непосредственно, без использования каких-либо форм косвенной адресации (в виде имен или идентификаторов). Т.е., предположим у нас есть два агента: producer и consumer: E>>>Теперь, предположим, что producer-у нужно изъять из системы своего consumer-а. Он должен дать фреймворку какое-то указание о том, что значение producer::m_consumer больше не актуально (хотя на этого consumer-а могу ссылаться другие агенты). Выбрать как это указание будет выполняться -- задача дизайнера фреймворка.
R>>Почему же о другом?
E>А потому, что кроме подхода Стэна, где агенты хранят ссылки/указатели друг на друга, возможен и другой подход к организации связей между агентами. Через косвенную адресацию в виде имен/идентификаторов агентов. В случае подхода Стэна неизбежны какие-то формы указателей, хоть голые, хоть смарт-пойнтеры. Но при другом подходе -- это уже не важно.
Регистр отображает имя агента на указатель, при этом он атомарно инкрементирует счётчик ссылок, либо возвращает 0, если такого агента нет.
Я не вижу тут никаких принципиальных отличий. Так это может выглядеть для пользователя:
void on_msg()
{
handle<my_agent> h = register().get_agent("foo");
if (!h)
...;
// ... Здесь пользуемся агентом
// в конце функции деструктор handle освобождает ссылку
}
Или так внутри фреймворка, если мы не хотим показывать пользователю никакие указатели/хэндлы (случай SObjectizer):
bool so_send_msg(string name, msg m)
{
handle<my_agent> h = register().get_agent("foo");
if (!h)
return false;
so_send_msg_internal(h, m);
}
Я паталогически не вижу ничего, что как-то принципиально отличалось бы от однопоточного случая и "синхронной" системы...
Здравствуйте, remark, Вы писали:
R>Я паталогически не вижу ничего, что как-то принципиально отличалось бы от однопоточного случая и "синхронной" системы...
Похоже, мы вообще говорим о разных вещах
Если есть желание продолжить, то можно сделать это в частной переписке.
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Здравствуйте, eao197, Вы писали:
E>Про управление памятью говорил, есть такое дело. Хуже всего с этим у GDI библиотек, но там, вероятно, своя специфика. E>А вот высокоуровневых С++ библиотек, в которых бы утекали другие ресурсы (GDI хендлы, сокеты, мутексы и пр.) не видел. Хотя приходилось объединять, например, Qt и Crypto++, ACE с Qt, ACE с FOX Toolkit и пр.
Ты говорил (почти дословно), что испытывал немалые проблемы из-за того, что в одной программе был вынужден использовать разные библиотеки. Мол у них были разные прирципы контроля памяти трудно совместимые между собой.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
E>>Про управление памятью говорил, есть такое дело. Хуже всего с этим у GDI библиотек, но там, вероятно, своя специфика. E>>А вот высокоуровневых С++ библиотек, в которых бы утекали другие ресурсы (GDI хендлы, сокеты, мутексы и пр.) не видел. Хотя приходилось объединять, например, Qt и Crypto++, ACE с Qt, ACE с FOX Toolkit и пр.
VD>Ты говорил (почти дословно), что испытывал немалые проблемы из-за того, что в одной программе был вынужден использовать разные библиотеки. Мол у них были разные прирципы контроля памяти трудно совместимые между собой.
Еще раз повторю -- да такое было. Но не было чтобы библиотеки ресурсы теряли. А ведь именно о потери ресурсов (т.к. GDI объекты и пр.) шла речь здесь