Оберон-технология: особенности и перспективы |
Тематика обсуждения: Оберон-технология. Особенности, перспективы, практическое применение.
Всего в теме 6256 сообщений
Добавить свое сообщение
Отслеживать это обсуждение Обсуждение из раздела Школа ОБЕРОНА
№ 1556 10-01-2007 04:07 | |
Ответ на »сообщение 1552« (Max Belugin)
x = filesystem.byPath(r'c:\autoexec.bat')
y = filesystem.byPath(r'c:\autoexec.bat')
assert(x == y)
assert(x.parent == filesystem.byPath(r'c:\'))
В BlackBox модуль Files не держит ссылок на созданные им объекты соответствующие файлам, но всегда возвращает один и тот же объект для одного и того же файла:
MODULE TestFiles;
IMPORT Log, Files;
PROCEDURE Do* ;
VAR f1, f2: Files.File;
BEGIN
f1 := Files.dir.Old(Files.dir.This(""), "untitled.odc", TRUE);
f2 := Files.dir.Old(Files.dir.This(""), "untitled.odc", TRUE);
ASSERT(f1 # NIL, 20);
ASSERT(f2 # NIL, 21);
ASSERT(f1 = f2, 100);
Log.String("Что и требовалось доказать..."); Log.Ln
END Do;
END TestFiles.
Делает он это без слабых ссылок. Реализацию смотрите в HostFiles (используется возможность предоставляемая модулем Kernel отыскать в памяти созданный ранее, но ещё не уничтоженный объект).
№ 1555 10-01-2007 03:56 | |
Насколько я понимаю (на основе Си++), слабый указатель есть некий механизм получения сильного указателя. Через сам слабый указатель получить доступ к объекту нельзя.
В случае неудачи (объект был удален из кэша) вместо сильного указателя будет возвращен NULL (для Оберона соответственно NIL).
Типичный пример использования слабого указателя:
struct CBetterChild : public CSample
};
Вы уверены, что эта задача решается только включением слабых указателей в язык?
Вместе с тем, техника работы с "умными указателями" в Си++ приводит к довольно быстрому размножению сущностей.
Например, возьмем только первые попавшиеся разновидности умных указателей из boost:
- scoped_ptr
- scoped_array
- shared_ptr
- shared_array
- weak_ptr
- intrusive_ptr
№ 1554 10-01-2007 03:54 | |
Ответ на »сообщение 1547« (Max Belugin)
А что в обероне нету слабых и мягких ссылок?
В Active BlackBox слабые ссылки есть.
Ответ на »сообщение 1550« (pepper)
У тебя есть сервер, который умеет конструировать разные объекты по запросу клиентов. Допустим объекты такие, что конструируются долго и жрут много памяти. Вполне естественно завести кэш таких объектов. Все круто, но сервер работает 7/24 и встает задача чистить этот кэш, потому что свободной памяти на компе вполне определенное количество. Твое решение?
...
Слабые ссылки решают эту задачу без введения каких-либо "лишних сущностей" и усложнения логики. И вс это "нахаляву", если только язык позволяет ;)
А кто будет чистить кэш от самих слабых ссылок?
В BlackBox есть следующая штука...
Модуль Kernel позволяет найти любой созданный ранее динамический объект прямо в памяти:
DEFINITION Kernel;
TYPE
Identifier = ABSTRACT RECORD
typ: INTEGER;
obj-: ANYPTR;
(VAR id: Identifier) Identified (): BOOLEAN, NEW, ABSTRACT
END;
PROCEDURE ThisFinObj (VAR id: Identifier): ANYPTR;
...
Вы определяете функцию (предикат) Identifier.Identified (): BOOLEAN, а Kernel вызывает её для всех найденных в памяти объектов указанного Вами типа. Благодаря чему и становится возможным отыскать находящийся где-то в памяти ранее созданный, но ещё не удалённый объект.
Этой штукой пользуется модуль HostFiles. Когда его просят открыть файл, то он сначала ищёт в памяти объект соответсвующий этому файлу, и только если такого объекта в памяти не обнаружено, открывает файл заново, объект соответствующий этому файлу выдаёт пользователю и сам у себя ссылку на этот объект не держит. Оно и понятно, если ссылку никто не держит, то этот объект не нужен, а если этот объект кому-то нужен, то вот он пусть и держит ссылку, а мы здесь у себя специально слабую ссылку заводить на него уже не будем, ведь мы доступ к тому объекту и так можем получить благодаря Kernel.ThisFinObj.
№ 1553 10-01-2007 03:48 | |
Ответ на »сообщение 1550« (pepper)
___________________________
Самый очевидный способ - переложить чистку кэша на клиентов.
Для кого очевидный? Это полный бред – посвящать клиентов в работу сервера...
Другой способ - придумать какую-то эвристику (например, основанную на частоте запросов каждого из объектов) и на основании этого чистить кэш без участия клиентов.
Ну вот ты сам на свой вопрос и ответил. Эта самая эвристика – как раз часть твоей задачи.
Слежение (каким-либо способом) за "подключённостью" клиента к серверу у тебя есть? Через те же коннекты, например. На стоимость "подключения/отключения" (то есть фиксации факта подключения клиента к серверу) ты повлиять, как я понимаю, не в силах. Тебя больше организация неких данных для клиента волнует. Она дорогА. Ну так что опять мешает "эвристику" основать на том же пресловутом "колцевом" пуле буферов. Само положение "кешированного" буфера( объекта для клиента) уже говорит о давности его использования... При чём тут "слабые указатели"?
№ 1552 10-01-2007 03:47 | |
Ответ на »сообщение 1548« (Владимир Лось)
___________________________
Всё что выходит за границы branfuck избыточно ;)
Если вы не испольюзуете оберон с рождения, то без него вы тоже обходились :)
Вот в Питоне тоже есть:
http://www.python.org/doc/2.4.1/lib/module-weakref.html
Еще один вариант использования - mapping. Например, мы хотим видеть файловую систему в виде чистой ОО структуры, причем чтобы identity соотвествовало: например
x = filesystem.byPath(r'c:\autoexec.bat')
y = filesystem.byPath(r'c:\autoexec.bat')
assert(x == y)
assert(x.parent == filesystem.byPath(r'c:\'))
мы просто создаем глобальный Map (path -> FileObject) и когда кому-то понадобится объект-файл, мы просто либо забираем его из Map, если он там есть, либо создаем заново. При этом если он перестал нам быть нужен - мы его убиваем.
№ 1551 10-01-2007 03:47 | |
Ответ на »сообщение 1545« (Илья Ермаков)
___________________________
Причем тут шаблоны? Каким образом логика этапа компиляции может быть применена для выбора варианта действий в зависимости от динамического типа переменной?
Логика этапа компиляции может указать компилятору сгенерить необходимый код для использования в рантайме. В том числе и код по выбору варианта действий в зависимости от динамического типа. Компилятор C++ не просто так сложный, он может даже решать олимпиадные задачи в compile-time :) А уж switch сгенерить...
typeid типа-предка его не обработает, в отличие от WITH в Обероне.
Только dynamic_cast и годится.
На самом деле, я бы сначала проверил насколько "тормознутым" будет dynamic_cast для случая простого одиночного невиртуального наследования относительно обероновского WITH. Потому как о "тормознутости" dynamic_cast принято говорить в сравнении со static_cast, который вообще ничего не стоит. Если же окажется, что dynamic_cast все-таки тормозной, то на помощь опять придут шаблоны и можно сделать свой велосипедный "быстрый cast", специализированный для одиночного невиртуального наследования.
Приведите "более элегантный" пример эквивалентный по своей логике - двойная виртуализация по (TYP(object), TYP(message)) на этапе выполнения?
Ну я представляю себе что-то типа:
class my_handler : handle<msg1, msg2, msg3>
;
Вся логика по выбору варианта действия будет сидеть в шаблоне handle<>.
Если все типы уже существуют на этапе компиляции, то есть красивый способ, предложенный в книге Дж. Элджера "С++ for real programmers"
Эту книгу не читал...
Ничего другого, лучшего "дубового WITH", Вам не придумать.
Аналог приведенного мной кода реально используется (правда не мной написан). Хотя там все намного сложнее - используется это решение для обработки сообщений от сишной либы, поэтому там не просто декларация типов msg1, msg2, msg3, а декларация целочисленных констант (аналог WM_PAINT и т.п.) и декларация о соотношениях между целочисленными константами и конкретным типами (структурами), но сами обработчики handle(msg1)/handle(msg2)/handle(msg3) уже типизированные с соответствующими типами сообщений. Если изначально работать с типами, то все только упростится.
Про LPARAM/WPARAM молчу.
Это чисто сишное (без плюсов) решение. Со всеми своими сишными недостатками.
И навязать эти ограничения начинающим самоуверенным самоучкам крайне сложно, потому что "язык позволяет, свободу программисту, никаких ограничений"...
С этим я никогда не спорил. Научить правильно использовать C++ очень сложно.
№ 1550 10-01-2007 02:56 | |
Ответ на »сообщение 1548« (Владимир Лось)
___________________________
И до сих пор как-то обходились (век мак не родыв и голоду не було :о) )
Попробую еще более конкретизировать задачу. У тебя есть сервер, который умеет конструировать разные объекты по запросу клиентов. Допустим объекты такие, что конструируются долго и жрут много памяти. Вполне естественно завести кэш таких объектов. Все круто, но сервер работает 7/24 и встает задача чистить этот кэш, потому что свободной памяти на компе вполне определенное количество. Твое решение?
Самый очевидный способ - переложить чистку кэша на клиентов. Но:
1) Ты ослабляешь инкапсуляцию и надежность системы, так-как все клиенты должны знать про кэш и обязаны чистить его.
2) Клиентов может быть много и это надо учитывать при принятии решения о вычищении кэша
Другой способ - придумать какую-то эвристику (например, основанную на частоте запросов каждого из объектов) и на основании этого чистить кэш без участия клиентов. Но это будет заведомо не самый эффективный способ, так как объекты все равно могут использоваться клиентами (и занимать память), а в кэше для новых клиентов их уже не будет.
Слабые ссылки решают эту задачу без введения каких-либо "лишних сущностей" и усложнения логики. И вс это "нахаляву", если только язык позволяет ;)
№ 1549 10-01-2007 01:28 | |
добавление к »сообщение 1548« (Владимир Лось)
___________________________
>>> А что в обероне нету слабых и мягких ссылок?
Какая-то избыточность...
В чём избыточность...
Мне пытаются всучить функциональность, которую я не заказывал, да и которая и на фиг не нужна.
В той задаче, которую здесь обсуждают, ПО САМОЙ задаче (например через кольцевой буфер буферов, пул буферов) я определяю, какой участок пула у меня содержит заполнение буферы, а какой – дожидающихся заполнения.
Что значит "объект живёт"? Вы со словами осторожней, теперь, когда у нас активные объекты появились на вооружении... :о)
Если это не активный объект, а постое расширение понятия записи, то ничего кроме как расширенным хранилищем (пассивным!) он не является. Если мне что-то понадобилось зафиксировать - создаю объект, нет – уничтожаю. Я понимаю, что операции выделения/возвращения памяти затратна по времени, если самому за этим следить – приходится идти на ухищрения (типа перекрытия new в Си++ для размещения в уже выделенном участке памяти), но какая система просчитает оптимально сколько объектов каких типов мне понадобится? :о)
№ 1548 10-01-2007 01:02 | |
Ответ на »сообщение 1547« (Max Belugin)
___________________________
А что в обероне нету слабых и мягких ссылок?
Насколько я помню - нет. И до сих пор как-то обходились (век мак не родыв и голоду не було :о) )
Если есть какая-то ссылка кроме как из кеша объект живет.
Если объект никому не нужен но есть в кеще - он собирается сборщиком мусора.
Какая-то избыточность...
А что в этом случае означает "объект живёт". И что, получается сборщику надо ещё учитывать, что добрался до объекта по ссылкам, стартовав из некоего "кэша", а не просто из "корневых ссылок" самого внешнего скоупа? То есть нужно плодить сущности?
№ 1547 10-01-2007 00:46 | |
Ответ на »сообщение 1539« (Владимир Лось)
___________________________
>>>А, ну так, примерно так я и думал, когда говорил, чего примерно ожидаю услышать...
А что в обероне нету слабых и мягких ссылок?
Они нужны вот для чего: допустим у нас есть кеш объектов, которые храняться на диске - мы можем пересоздать объект по имени в любой момент времени, но не хотим делать это на каждый чих. С другой стороны, мы не хотим чтобы они были в памяти даже если их давно никто не использует.
Мы поступаем так: далем глобальный Map (Имя -> Слабая ссылка), куда мы помещаем объект.
Если есть какая-то ссылка кроме как из кеша объект живет.
Если объект никому не нужен но есть в кеще - он собирается сборщиком мусора.
Добавить свое сообщение
Отслеживать это обсуждение
Дополнительная навигация: |
|