Спільна власність рідко викликає сенс
Ця відповідь може бути дещо дотичною, але я мушу запитати, скільки випадків має сенс з точки зору користувача, щоб поділити право власності ? Принаймні, в доменах, в яких я працював, їх практично не було, тому що в іншому випадку це означатиме, що користувачеві не потрібно просто одноразово видаляти щось з одного місця, а явно видаляти його від усіх відповідних власників, перш ніж ресурс насправді буде видалено з системи.
Це часто інженерна ідея нижчого рівня, щоб запобігти руйнуванню ресурсів, поки щось інше все ще доступ до неї, як інша нитка. Часто, коли користувач просить закрити / видалити / видалити щось із програмного забезпечення, його слід видалити якомога швидше (коли це безпечно видалити), і він, безумовно, не повинен затримуватися і спричиняти витік ресурсів настільки довго, програма працює.
Наприклад, ігровий актив у відеоігри може посилатися на матеріал із бібліотеки матеріалів. Ми, звичайно, не хочемо, скажімо, збиття звисаючого вказівника, якщо матеріал видаляється з бібліотеки матеріалів одним потоком, а інший потік все ще отримує доступ до матеріалу, на який посилається ігровий актив. Але це не означає, що для ігрових активів немає сенсу розділяти право власності на матеріали, на які вони посилаються, з бібліотекою матеріалів. Ми не хочемо примушувати користувача явно видаляти матеріал як з ресурсу, так і з бібліотеки матеріалів. Ми просто хочемо переконатися, що матеріали не видаляються з бібліотеки матеріалів, єдиного розумного власника матеріалів, поки інші теми не закінчать доступ до матеріалу.
Витоки ресурсів
Однак я працював з колишньою командою, яка охоплювала GC для всіх компонентів програмного забезпечення. І хоча це справді допомогло переконатися, що ми ніколи не знищували ресурси, а інші потоки все ще отримували доступ до них, ми натомість отримували свою частку витоків ресурсів .
І це були не тривіальні витоки ресурсів, які засмучують лише розробників, як кілобайт пам'яті, що просочився після багатогодинного сеансу. Це були епічні витоки, часто гігабайти пам'яті протягом активного сеансу, що призводило до звітів про помилки. Тому що зараз, коли на власність ресурсу посилається (і, отже, поділяється право власності) серед, скажімо, 8 різних частин системи, тоді потрібно лише одну, щоб не видалити ресурс у відповідь на те, що користувач просить його видалити бути просоченим і, можливо, на невизначений термін.
Тому я ніколи не був великим шанувальником GC або підрахунку довідок, застосовуваних в будь-яких широких масштабах через те, наскільки легко вони створили пропускне програмне забезпечення. Те, що раніше було б звисаючим крахом вказівника, який легко виявити, перетворюється на дуже важко виявити витік ресурсу, який легко може летіти під радари тестування.
Слабкі посилання можуть пом'якшити це питання, якщо мова / бібліотека надає це, але мені було важко отримати команду розробників змішаних наборів вмінь, щоб мати можливість постійно використовувати слабкі посилання, коли це доречно. І ця складність стосувалася не лише внутрішньої команди, але і кожного розробника плагінів для нашого програмного забезпечення. Вони також могли легко призвести до витоку системи через просто збереження постійної посилання на об'єкт таким чином, що важко було простежити за плагіном як винуватцем, тому ми також отримали нашу левову частку звітів про помилки в результаті наших програмних ресурсів витік просто тому, що плагін, вихідний код якого був поза нашим контролем, не зміг випустити посилання на ці дорогі ресурси.
Рішення: відкладено, періодичне видалення
Тому згодом моє рішення, в якому я звернувся до своїх особистих проектів, які дали мені найкраще, що я знайшов, з обох світів, полягало в тому, щоб усунути концепцію, яка, referencing=ownership
але все ще відклала руйнування ресурсів.
Як наслідок, тепер, коли користувач робить щось, що викликає необхідність видалення ресурсу, API виражається в простому видаленні ресурсу:
ecs->remove(component);
... який дуже просто відтворює логіку користувача. Однак ресурс (компонент) не може бути видалений відразу, якщо у фазі їх обробки є інші системні потоки, де вони можуть одночасно отримувати доступ до того ж компонента.
Тож ці нитки обробки потім дають час туди-сюди, що дозволяє потоці, що нагадує сміттєзбірник, прокидатися і " зупиняти світ " і знищувати всі ресурси, які вимагали видалити, блокуючи потоки від обробки цих компонентів, поки вона не буде закінчена . Я налаштував це настільки, що кількість робіт, які потрібно виконати тут, як правило, мінімальна і не помітно скорочується на частоту кадрів.
Зараз я не можу сказати, що це якийсь перевірений і добре задокументований метод, але це те, що я використовую вже кілька років, без головних болів і без витоків ресурсів. Я рекомендую досліджувати такі підходи, коли можливо, щоб ваша архітектура підходила до такої моделі паралельної валюти, оскільки це набагато менш важко, ніж GC або перерахунок переліку, і не ризикує ці види витоків ресурсів летіти під радари тестування.
Єдине місце, де я вважаю перерахунок посилань або GC корисним - це стійкі структури даних. У такому випадку це територія структури даних, далека від проблем, пов'язаних з користувачем, і там фактично має сенс для кожної непорушної копії потенційно ділитися правом власності на ті самі немодифіковані дані.