Илья Ермаков писал(а):
Иногда уже не выкрутиться явным списком: можно нарваться на замкнутый круг: объект никому не нужен, но ещё висит в списке, и никогда не будет определено, что он уже не нужен (потому что в списке-то он есть!)
Тут уже приходим к нужности "мягких ссылок" (weak pointers): которая указывает на объект, но не является якорем. Т.е. становится невалидной, когда объект соберёт сборщик.
Такие ссылки сделать несложно, но нужна интеграция со сборщиком мусера. Это было сделано в Active BlackBox...
Илья, поправьте меня, если я не прав, но мне кажется, что без особого типа указателей вполне себе можно обойтись. Просто с нашим особым типом объектов нужно обращаться как с любым другим глобальным ресурсом. Например, файловые хэндлы Windows мы закрываем либо явно вызовом Close для файла, либо при сборке мусора. Так вот, наши "глобальные" объекты точно так же нужно явным вызовом удалять из глобального списка. Как правило, этим будет заниматься тот, кто изначально создал себе этот объект, при своей финализации.
Info21, вам это понравится: композиция объектов вместо языковой фичи.
Решение в общем виде такое: делаем объект-посредник, а ссылку на глобальный объект прячем внутри. Все клиенты используют только посредника. Когда посредник становится ненужным и собирается сборщиком мусора, его финализация удаляет соответствующий глобальный объект из глобального списка и, возможно, выполняет дополнительные действия по освобождению ресурсов.
Таким образом, замкнутый круг разрывается, и модули выгружаются без ошибок. При желании не сложно также сделать так, чтобы при выгрузке модуля и уничтожении глобальных объектов последние оповещали своих посредников. Таким образом, клиенты посредников в случае выгрузки модуля могут поиметь нечто более осмысленное, чем трап: возвращаемый статус ошибки, вывод в лог или просто игнорирование вызываемых методов.
Кстати, сам модуль, реализующий сервис изначально, и хранящий в себе глобальный список объектов, может просто-напросто всегда возвращать клиентам уже созданных посредников. Они даже могут и не подозревать, что им представляется посредник. То есть, с точки зрения клиента нет абсолютно
никакой добавочной сложности.
Если немного подумать, то посредник - это только название такое. На самом деле вместо посредника может наружу выставляться реальный объект, просто у него внутри будет скрытая ссылка на объект-якорь, который уже в свою очередь и вбит накрепко в глобальную очередь.