У UI-виджетов во многих фреймворках уже есть деструктор, который вызывается при смене раута и вынимании виджета из DOM. В React это componentWillUnmount, например.
Этот "деструктор" перекрывается в базовом классе так, что он вызывает деструктор состояния виджета.
Состояние - составной объект, где часть полей агрегируется, а часть включена "по ссылке". Он будет делать dispose() всем агрегированным элементам рекурсивно.
Коллекция типа Collection.Refs выглядит точто так же, как обычная коллекция, и ведет себя почти так же, но она не агрегирует свои элементы. То есть, ее деструктор не вызовет dispose() для элементов, просто отпишется от событий от них.
Обычная коллекция предполагает, что все, что внутри - ее. И она это убьет.
То есть, ссылки от юзеров на коллекцию Refs есть, и они будут аккуратно убраны при ее dispose.
> Т.е. суть композиции - один флажок, учитываемый деструктором?
Там все немного сложнее (это не флажок, и он учитывается не только деструктором), но в целом - очень похоже. Композиция влияет на то, как происходит создание, удаление, копирование, сериализация, и валидация. Для композиции все эти операции рекурсивны.
И да, вся суть в создании "дерева владения". При композиции owner может быть один и только один. За этим фреймворк следит. Ну и да, деструктор ясен пень не настоящий, это метод dispose() который вызывается при удалении из DOM.
Печально это всё на самом деле. По сути, поверх одной модели владения (ссылки и gc) пришлось накрутить ещё одну, но уже не допускающую циклов. В reference-counting модели (я за последние годы к ней привык - под macos gc не успел даже попробовать, как его задепрекейтили в пользу arc) всё несколько проще, но, конечно, даны другие способы выстрелить себе в ногу (любимый метод создания циклических ссылок - лямбды [blocks]).
Кстати, не в курсе - текущие реализации js используют чистый gc или reference-counting-based оптимизации применяются (т.е. порой объект может быть убит сразу, как кончились ссылки на него, не дожидаясь прохода gc)?
Это все печально неимоверно. Я думал и о счетчике ссылок поверх, который бы включал деструкторы, но решил что не стоит. От явной агрегации много другой пользы - объекты правильно копируются by default, например.
Текущие реализации GC в JS используют mark-and-sweep, V8 использует stop-and-copy. Счетчиков ссылок, насколько мне известно, не использует никто.
В функциональных языках применяется оптимизация известная с LISP машин - однобитные счетчики ссылок. Специально для элементов однонаправленных списков. В JS это не поможет.
Этот "деструктор" перекрывается в базовом классе так, что он вызывает деструктор состояния виджета.
Состояние - составной объект, где часть полей агрегируется, а часть включена "по ссылке". Он будет делать dispose() всем агрегированным элементам рекурсивно.
Коллекция типа Collection.Refs выглядит точто так же, как обычная коллекция, и ведет себя почти так же, но она не агрегирует свои элементы. То есть, ее деструктор не вызовет dispose() для элементов, просто отпишется от событий от них.
Обычная коллекция предполагает, что все, что внутри - ее. И она это убьет.
То есть, ссылки от юзеров на коллекцию Refs есть, и они будут аккуратно убраны при ее dispose.
> Т.е. суть композиции - один флажок, учитываемый деструктором?
Там все немного сложнее (это не флажок, и он учитывается не только деструктором), но в целом - очень похоже. Композиция влияет на то, как происходит создание, удаление, копирование, сериализация, и валидация. Для композиции все эти операции рекурсивны.
И да, вся суть в создании "дерева владения". При композиции owner может быть один и только один. За этим фреймворк следит. Ну и да, деструктор ясен пень не настоящий, это метод dispose() который вызывается при удалении из DOM.
Reply
В reference-counting модели (я за последние годы к ней привык - под macos gc не успел даже попробовать, как его задепрекейтили в пользу arc) всё несколько проще, но, конечно, даны другие способы выстрелить себе в ногу (любимый метод создания циклических ссылок - лямбды [blocks]).
Кстати, не в курсе - текущие реализации js используют чистый gc или reference-counting-based оптимизации применяются (т.е. порой объект может быть убит сразу, как кончились ссылки на него, не дожидаясь прохода gc)?
Reply
Текущие реализации GC в JS используют mark-and-sweep, V8 использует stop-and-copy. Счетчиков ссылок, насколько мне известно, не использует никто.
В функциональных языках применяется оптимизация известная с LISP машин - однобитные счетчики ссылок. Специально для элементов однонаправленных списков. В JS это не поможет.
Reply
Leave a comment