共享所有权几乎没有道理
这个答案可能有点不切实际,但是我不得不问,从用户端的角度来看,共享所有权有多少种情况有意义?至少在我工作过的领域中,几乎没有,因为这意味着用户不需要一次从一个地方删除某件事,而是在资源真正使用之前将其从所有相关所有者中删除。从系统中删除。
防止其他人仍在访问资源(例如另一个线程)时破坏资源通常是一个较低层的工程思想。通常,当用户要求关闭/删除/删除软件中的某些内容时,应尽快将其删除(只要可以安全删除),并且它肯定不会流连忘返并导致资源泄漏该应用程序正在运行。
例如,视频游戏中的游戏资产可能引用了素材库中的素材。例如,我们肯定不希望悬空的指针崩溃,如果在一个线程中从材料库中删除了该材料,而另一个线程仍在访问游戏资产所引用的材料时。但这并不意味着游戏资产与素材库共享它们引用的素材所有权。我们不想强迫用户从资产和物料库中显式删除物料。我们只想确保在其他线程完成对材料的访问之前,不要将材料从唯一的材料所有者材料库中删除。
资源泄漏
但是我曾与一个以前的团队合作过,该团队在软件中的所有组件都使用了GC。虽然这确实有助于确保在其他线程仍在访问它们时我们绝不会销毁资源,但最终却导致了资源泄漏。
而且这些也不是琐碎的资源泄漏,这种泄漏只会使开发人员感到不适,就像在一个小时的会话后泄漏了千字节的内存一样。这些都是史诗性的泄漏,通常在活动会话中存在数GB的内存,从而导致错误报告。因为现在,当在例如系统的8个不同部分之间引用资源所有权(并因此在所有权中共享)时,响应于用户请求将其删除,仅需一个失败即可删除资源被泄漏,并可能无限期地泄漏。
因此,我从来都不是GC或大规模应用引用计数的忠实拥护者,因为他们使创建泄漏软件变得如此容易。以前是悬而未决的指针崩溃,它很容易检测到,变成了很难检测的资源泄漏,很容易在测试的雷达下飞行。
如果语言/库提供了弱引用,则弱引用可以缓解此问题,但是我发现很难让一组混合技能组的开发人员能够在适当的情况下始终使用弱引用。这个困难不仅与内部团队有关,还与我们软件的每个插件开发人员有关。它们也很容易通过仅存储对对象的持久引用而以某种方式导致难以追溯到作为罪魁祸首的插件,从而很容易导致系统泄漏资源,因此我们也从我们的软件资源中获得了大部分错误报告。仅仅因为源代码不在我们控制范围之内的插件无法释放对那些昂贵资源的引用而被泄漏。
解决方案:延迟定期删除
因此,后来我将其应用于我的个人项目的解决方案使我从两个方面都得到了最好的帮助,那就是消除referencing=ownership
仍然延迟资源破坏的概念。
结果,现在,只要用户执行导致需要删除资源的操作,API就会以删除资源的方式表示:
ecs->remove(component);
...以非常直接的方式对用户端逻辑进行建模。但是,如果在处理阶段有其他系统线程可以同时访问同一组件,则可能不会立即删除资源(组件)。
因此,这些处理线程然后在这里到处产生时间,这使得类似于垃圾收集器的线程可以唤醒并“ 停止运行 ”并销毁所有需要删除的资源,同时将线程锁定在处理这些组件之前,直到完成。我已对此进行了调整,以使此处需要完成的工作量通常最少,并且不会明显降低帧速率。
现在,我不能说这是一种经过尝试和测试且有据可查的方法,但这是我已经使用了几年的东西,没有任何麻烦,也没有资源泄漏。我建议您在架构可能适合这种并发模型的情况下探索这种方法,因为它比GC或ref计数要费力得多,并且不会冒着在测试范围内泄漏这些类型的资源泄漏的风险。
我发现引用计数或GC有用的一个地方是持久数据结构。在那种情况下,它是数据结构的领域,与用户端的关注点相去甚远,对于每个不可变的副本来说,共享相同的未修改数据的所有权实际上是有意义的。