Sep. 5th, 2009

Garbage collection is hard - я это только сейчас понял "на своей шкуре".

Переделываю управление памятью (исправляю баги и хочу сделать немного более прозрачным) в cl-gtk2-gobject и натыкаюсь на разного рода неприятности.

GObject использует подсчет ссылок для управления памятью. При этом, имеется 3 типа ссылок: обычные (strong references), слабые (weak references) и переключаемые (toggle references). С первыми двумя все более-менее понятно, toggle references - зверь более интересный. Основное, для чего он нужен - интеграция подсчета ссылок в gobject со сборщиками мусора других языков (биндингов). Переключаемые ссылки различают два состояния: на объект есть только toggle reference и на объект есть другие ссылки. В случае, когда на объект нет других ссылок, то это значит, что на объект есть только ссылка из биндинга, и значит, биндинг может быть уверен в том, что объект больше не "воскреснет". Если бы таких ссылок не было, биндинг не мог бы быть уверен в том, что он удаляет последнюю ссылку на объект - потом эта ссылка может "всплыть", и биндингу придется воссоздать объект, которого уже нет, и вместе с которым ушло его состояние (например, есть объект класса custom-window, отнаследованный от gtk-window; если биндинг удалит этот объект, и на него придет ссылка, то все, что сможет сделать биндинг - это вернуть ссылку как объект типа gtk-window, а это плохо; это называется денатурацией объектов). В итоге, такие ссылки позволяют биндингу держать "правильный" объект доступным на тот случай, если он понадобится. А когда "чужих" ссылок на объект нет, об объекте можно забыть (убрав сильную ссылку из хэш-таблицы указателей и оставив слабую ссылку).

С такими ссылками разобраться несложно: имеем две хэш-таблицы, одну для сильных ссылок, другую - для слабых. При поиске объекта по указателю ищем в обеих таблицах, при "переключении" переключаемой ссылки - перемещаем указатель из одной хэш-таблицы в другую.

Заодно нашел баг в конструировании объектов, иногда оставались лишние ссылки на объекты, а использование переключаемых ссылок окончательно решило проблему денатурации объектов (ранее эта проблема была решена только для классов, зарегистрированных в gobject).

Другая найденная неприятность более неприятна. Для хранения ссылок на функции-обработчики сигналов используются stable pointers - целочисленные индексы в массив объектов. Проблема в том, что ссылки в этом массиве всегда сильные. И если обработчик сигнала ссылается на объект, чей сигнал он обрабатывает, то объект никогда не будет собран, т.к. на него есть сильная ссылка со стороны обработчика сигнала, на который есть сильная ссылка со стороны массива stable pointer'ов. Выглядит это вот так:



Решение этой проблемы состоит в том, что при переключении переключаемой ссылки в "слабое" состояние делать ссылки на соответствующие объекту обработчики также слабыми. В этом случае на объект не будет сильных ссылок со стороны обработчиков сигналов, и он будет подобран сборщиком (как и обработчики его сигналов). Осталось только реализовать это. Либо же обработчики сигналов хранить в самом объекте:

Profile

dmitry_vk

April 2023

S M T W T F S
      1
234567 8
9101112131415
16171819202122
23242526272829
30      

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Apr. 5th, 2026 07:15 pm
Powered by Dreamwidth Studios