Михаил писал(а):
Дельфовые строки, это супер. То же бы сделал. Пороху не хватило, или мозгов скорее всего (((.
да там несложно. по сути STRING — это указатель на динамически выделяемую структуру, в которой счётчик ссылок, длина строки, да указатель на её данные. в прологе процедуры всем локальным переменным типа STRING присваиваем NIL (я вообще все-все локалы на входе зануляю, потому что лень ловить ошибки типа «use before initialised»). потом аккуратно инкрементим/декрементим ссылки. перед каждым RETURN вставляем вызовы внутренней процедуры `StringDecRef()`, например. в общем-то всё. главное быть внимательным, и нигде не пропустить инкремент/декремент. и будут у нас динамические строки.
я ещё слайсы строк сделал: структура строки имеет флажок: «а я не настоящая строка, я кусочек вон той строки!» чтобы всякие операции взятия подстрок дешёвые были.
в общем, компилятор под капотом занимается шулерстом — ну и пусть: на то он и компилятор.
сами строки я выделяю вне обероновского хипа, тупо через либцшные `malloc()`/`free()`. можно было сделать для них отдельный менеджер памяти, конечно — но зачем, если я всё равно к libc обращаюсь уже.
Михаил писал(а):
Да, я и сам двумя руками за. Вы уже на столько интересных моментов, глаза открыли. Не знаю, за что хвататься. Хочется все и сразу. А голова кругом, умею одномоментно делать только, что-то одно.
знакомая беда, да. столько интересного, и всё хочется.
Михаил писал(а):
Dispose, да. И спорить не буду. Выбрал вариант по силам. GC мне нужен многопоточный и плюс, у меня стиль - без зазрения совести временным переменным присваиваю ссылки. Хорошо кроме меня, никто не видит ))).
в принципе, многопоточный GC можно сделать даже без жонглирования потоками. в смысле, без механики их заморозки.
кратко: вставляйте в начало (или конец) циклов, а также в пролог и эпилог gc sync points. это обычная глобальная переменная, которая работает как спинлок. `NEW()` поднимает спинлок и ожидает, пока все потоки дойдут до safe point и застынут в ожидании освобождения спинлока. на этом моменте можно совершенно безопасно делать обычный GC, потому что у нас гарантировано ровно один пользователь. как закончили — отпускаем лочку, все спокойно едут дальше.
в большинстве случаев накладные расходы — одна операция CAS. потеря производительности мизерная, зато нам больше не надо сочинять механику приостановки потоков для кучи осей. плюс в безопасных точках у нас известное состояние потока: если лочка поднята, можно скинуть в память все регистры, чтобы GC увидел актуальные данные.
метод не самый лучший, конечно — зато простой в реализации. ну, будут кратковременные пики, когда программа выжирает весь CPU — но вряд ли кто-то это особо заметит. это можно будет решить потом, если начнёт раздражать.