rc CopyOnWrite gc programming
Есть у меня одно соображение насчёт подсчёта ссылок вместо сборки мусора, которое заключается, помимо длинных пауз и больших изначальных выделений памяти, в том, что если клиент каким–то образом может точно знать, что он единственный владелец структуры данных, то он может изменить её, а при сборке мусора на структуру может ссылаться невесть сколько желающих, и, чтобы не было сюрпризов, может требоваться делать глубокое копирование, и за счёт отсутствия глубоких копирований подсчёт ссылок может и выруливать. Однако, чтобы это было так, нужно, чтобы вместо сумбурных представлений типа «вот, если мы убедились, что мы единственный владелец, мы можем внести изменения прямо на месте, а если не совсем единственный, то оптимальным образом скопировать узлы на пути от корня к потомку, а соседние узлы оставить общие» иметь некое более формализованное представление, которое можно закодировать или хотя бы представить. Потому что в моих CVariants для Делфей (
bitbucket.org ), например, счётчик ссылок, но глубокое копирование делать всё равно надо, потому что я в требуемые сроки логику разработать и воплотить в жизнь не смог. А зря. Дельты бы значительно ускорились (в контексте задачи приложение на терминале, который, как правило, на GPRS, описывает своё состояние в виде большой структуры и передаёт на сервер, а для экономии трафика шлются только дельты).
Так вот, попробуем набросать:
Итак, для начала надо отбросить двоичную логику константа/неконстанта, мутируемый/немутируемый. Эта путаница идёт, мне кажется, из языков программирования. То есть, если у нас есть X : constant Integer := 3; в синтаксисе Ada, или const X: Integer = 3; в синтаксисе Delphi или const int X = 3; в синтаксисе C, то это сравнительно настоящая константа. Её неизменность гарантируется языком программирования, если не пытаться обхитрить его cast'ом, а ещё может гарантироваться OS и CPU защитой от записи в соответствующие страницы памяти. А кроме таких настоящих констант есть так называемые указатели на константы (access constant в синтаксисе Ада), которые на самом деле могут быть не указатели на константы, а указатели в режиме только–чтение, что не то же самое, что указатель на константу. А такой вещи, как указатель на константу, на самом деле нет, и я сейчас критикую не языки программирования, а ту картину мира, которая непроизвольно складывается, если ими пользоваться. Пока не поймёшь, что нам может зачем–то понадобиться не 2 типа сущностей, а 3, сложно продвинуться. Итак, на мой взгляд, нам нужны:
1. Ссылки (умные указатели, итераторы) в режиме чтение–запись, которые знают, где корень той структуры, которую они представляют, и каков точный путь от этого корня к тому узлу, на который эта ссылка. Кроме корня, есть ещё один главный объект (переменная), который олицетворяет структуру таким образом, что изменения, производимые над структурой, должны быть видны только тем клиентам, которые используют ссылки с тем же главным объектом. Корень может быть общим у нескольких главных объектов до первого изменения.
2. Ссылки в режиме только–чтение на потенциально изменчивые структуры. Они нужны, чтобы соответствовать формальным требованиям алгоритмов, но было бы ошибкой выдавать налево и направо гарантии неизменности содержимого.
3. Константы, представляющие структуры, которые гарантированно не изменятся. Ссылки на константы не знают про корень структуры, которой они принадлежат, в противном случае это были бы ссылки второго типа. Константы–списки и константы–словари ссылаются на другие константы, у которых уже нельзя узнать родителя.