V>>Чего гадать? Возьми любые исходники на Схеме чего-нить (полно в сети) да посмотри. Локальные замыкания в Паскалевском стиле не так уж часто используются. Т>Берем slib и находим там эти самые локальные замыкания сотнями. А те исходники (которых полно в сети) скорее всего написаны бывшими сишниками.
По сравнению с десятком тысяч нелокальных их не видно и под микроскопом.
Здравствуйте, VladD2, Вы писали:
VD>Темболее, что если надо, то это в любом языке делается. VD>Вот только с замыканиями и локальными фунциями это можно делать удобнее и чаще:
Можно сравнить "синтаксический оверхед" и run-time эффективность на твоем любимом C# и С++:
Итак, делегаты сохранены во внутренние переменные, а не вызваны "анонимно", именно по той причине, зачем вообще делают локальные замыкания — для повторного использования в локальном контексте.
Итого — 1 лишняя строчка на объявление типа-предиката. В общем случае у нас будет одна лишняя строка на каждое замыкание, т.к. типы и кол-во аргументов в общем случае уникальны.
Тем более, что вместо typedef я могу по месту писать требуемый function<type1(type2, ... and so on)>, а в C# я должен явно декларировать делегат перед использованием.
Замыкание красиво и элегантно создается конструкцией var(x) (есть еще константная версия, для избежания копирования по значению больших объектов, если мы не собираемся их модифицировать). Созданное замыкание — суть функциональный объект, который затем используется в функциях высшего порядка. Примеры эти тривиальны, иначе можно было бы показать такое же элегантное порождение curring-функций через bind.
Но это все синтаксис. С точки зрения run-time, в C# динамически создаются экземпляры объектов/замыканий, так что подобный код я бы не рекомендовал применять при обработке значительных объемов данных. Оссобенно хотелось бы отметить эффективность замыкания GreaterOrEquals. Причем ситуация такова, что на данном этапе развития CLR нет никакой возможности оптимизировать это дело, ввиду самой механики эмуляции замыканий. Эти замыкания и код по их вызову "по-честному" создает компилятор. Только вот сам характер генерируемого кода таков, что платформа CLR не в состоянии предотвратить динамическое создание объектов-замыканий никакими оптимизациями, ибо классы, их реализующие, декларативно никак не связаны с целевым методом в конечном байт-коде, кроме как в момент вызова из оного. Т.е. пока что для замыканий существует слишком высокий "abstraction penalty", о котором необходимо помнить (динамическое создание объектов-замыканий!!!).
Напротив, в С++ не создаеются динамические объекты, не используется ни полиморфизм или коссвенная адресация, а значит все инлайнится в момент компиляции таким образом, что вообще никаких локальных объектов не создается (это хорошо видно в режиме релиз с галочкой "генерировать debug информацию", и в результате непосредственно генерируется в теле метода целевой код, как если бы мы написали: "if(x<y) ..."
--------
В принципе, "разглядывая" платформу .Net 2.0 хорошо видно, что подобные свойства нынешней реализации замыканий учтены разработчиками — во фреймворчной библиотеке провоцируется подача "готовых" замыканий как аргументы всяких "цикличных" процедур...
Здравствуйте, Дарней, Вы писали:
I>>Его можно использовать с Hashtable из .NET? Чтобы Hashtable оставалась в основном на диске и в память загружались только используемые ее части?
Д>ты удивишься — поведение по умолчанию именно таково.
А как использовать заполненную Hashtable при повторном старте программы не записывая ее? (Она ведь уже на диске.)
eao197 wrote: > А мы не поимеем трах с std::basic_string<char,shmem_allocator<char>> в > программе? Он ведь не совместим с std::string.
У меня все нормально работает. В крайнем случае, можно через c_str()
интеоперировать (а std::string — это вообще зло ).
> Может лучше было бы иметь: > std::vector< B, shmem_allocator<B> > ... > и специализацию shmem_allocator для типа B, который должным образом > сериализует b и c, имеющие обычный тип std::string.
Нет смысла. Вся фича как раз в том, что мы прозрачно работаем с графом
объектов, разделяемым между процессами или винчестером.
Здравствуйте, dshe, Вы писали:
D>Насколько я понимаю, указатели на персистентные объекты такие же как и указатели на обычные объекты (перегруженный оператор new возвращает (void *), который должен быть валидным указателем, поскольку далее к нему применяется конструктор). Далее, страницы с диска не просто загружаются, они загружаются вместо старых страниц, т.е. на их место. Следовательно, физические адреса персистентных объектов могут иногда совпадать и даже для одного и того же объекта меняться в процессе работы программы (т.е. нужно обновлять ссылки на персистентные объекты, если их физический адрес поменялся). Кроме того, нужно как-то отслеживать можно ли выгружать определенную страницу или нет. Все это, наверное, вполне решаемые задачи, но на мой взгляд их весьма трудно решить "прозрачно".
Имхо, такая штука нормально решается, если в программе работать не с голыми указателями, а с "умными", которые скрывают в себе всю работу с загрузкой/выгрузкой объектов. Подобный подход, если мне не отшибает память, использовался в ООБД Goods Константина Книжника.
В других ООБД (кажется в ObjectStore) использовался другой подход. Там были обычные голые указатели, но они были уникальными для персистентных объектов. ObjectStore работала с виртуальной памятью: когда происходило обращение к объекту, которого в памяти нет, возникало исключение, оно перехватывалось ObjectStore, в память загружалась нужная страница и указатель оказывался валидным. Соответственно, если в памяти оказывалось слишком много страниц, лишние выгружались.
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
dshe wrote: > Идея, использовать allocator'ы для прозрачного обращения в объектам на > диске, меня тоже когда-то прельщала. Однако я столкнулся с определенными > сложностями. Интересно было бы взглянуть на работющую реализацию этой идеи.
Вот тут для shared_memory: http://ice.prohosting.com/newfunk/boost/libs/shmem/doc/html/index.html
Для работы с диском нужно тривиальное изменение в классе сегмента.
Скоро shmem появится в Boost'е (он официально принят, идет доработка по
результатам обсуждения) — так что стоит подождать.
> Насколько я понимаю, указатели на персистентные объекты такие же как и > указатели на обычные объекты (перегруженный оператор new возвращает > (void *), который должен быть валидным указателем, поскольку далее к > нему применяется конструктор). Далее, страницы с диска не просто > загружаются, они загружаются вместо старых страниц, т.е. на их место.
Не совсем так. Когда я создаю mapping, то могу указать с какого
виртуального адреса его делать.
> Следовательно, физические адреса персистентных объектов могут иногда > совпадать и даже для одного и того же объекта меняться в процессе работы > программы (т.е. нужно обновлять ссылки на персистентные объекты, если их > физический адрес поменялся).
В Windows можно дать гарантию, что mapping будет на один и тот же
виртуальный адрес. Для общего случая — offset_pointer (умный указатель,
записывающий смещение относительно начала блока памяти).
> Кроме того, нужно как-то отслеживать можно > ли выгружать определенную страницу или нет.
Этим занимается OS совершенно прозрачно для прикладных программ.
Здравствуйте, Дарней, Вы писали:
Д>для таких случаев умные волосатые дядьки уже придумали базы данных Д>или тебе хочется во что бы то ни стало изобрести свой велосипед?
Здравствуйте, eao197, Вы писали:
E>Насколько мне известно, умные волосатые дядьки (с ними еще и тетька была) из SleepyCat Software используют разделяемую память для организации доступа к БД из нескольких процессов. И file mapping для увеличения скорости работы с БД.
они для этого используют аллокаторы и отображение стль-ных контейнеров на диск? не верю (С)
igna wrote: > Д>для таких случаев умные волосатые дядьки уже придумали базы данных > Д>или тебе хочется во что бы то ни стало изобрести свой велосипед? > Тут то мы и зациклились: > http://rsdn.ru/Forum/Message.aspx?mid=1772997&only=1
Здравствуйте, eao197, Вы писали:
E>А мы не поимеем трах с std::basic_string<char,shmem_allocator<char>> в программе? Он ведь не совместим с std::string.
Когда я писал свой file mapped аллокатор, написал заодно и свой string. Наверняка и в boost::ShMem проблема решена.
P.S. Думаю, это непродумано в стандарте, что std::string с разными аллокаторами нельзя присваивать друг другу.
igna wrote: > P.S. Думаю, это непродумано в стандарте, что std::string с разными > аллокаторами нельзя присваивать друг другу.
Ага, и то что allocator::pointer и allocator::const_pointer должны быть
простыми указателями.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, anonymous_user, Вы писали:
_>>а с++ был создан затем, чтобы максимально удобно отразить в коде всю сложность окружающего мира
VD>С++ даже дальше пошел. Нем без проблем можно отразить всю сложность казалось бы простых вещей.
На свете много идиотов — усложнить простые вещи можно на любом языке!
Дарней wrote: > E>Насколько мне известно, умные волосатые дядьки (с ними еще и тетька > была) из SleepyCat Software используют разделяемую память для > организации доступа к БД из нескольких процессов. И file mapping для > увеличения скорости работы с БД. > они для этого используют аллокаторы и отображение стль-ных контейнеров > на диск? не верю (С)
Горячие BDB-шные парни пишут на чистом С
Но отображение файлов в память они как раз именно так и используют.
VladD2 wrote: > C>.NET дает возможность писать кривые и уродские приложения. Причем не > C>менее неэффективно, чем VB3. > Понимаш ли в чем дело. Твое злопыхательство ни на грам не повредит > .NET-у, но вот тебя подобные слова выставляют в не очень хорошем свете.
Если ты не заметил, то я просто утрирую твои слова
> C>А для вызова методов у String надо _обязательно_ использовать SOAP через > C>прокси-сервер в Африке. В конце концов, вы ведь не можете знать заранее > C>откуда пришла строка? > Похоже ты перетрудился.
Ну так ты ведь утверждаешь, что всегда надо использовать GC.