多个场景对象可能引用同一个资源包,而不同资源包又共享同一张图片。释放一个对象时直接删除图片,可能破坏仍在使用它的其他对象。
本例有四个资源包,每包依赖若干图片。对象各引用一个包;包引用数由零变为一时才给其依赖图片各增加一次引用,包由一变为零时才各减一次。图片引用数为零才卸载。
这一例的完整输入
四个包依赖的图片编号分别是[[0, 1, 3, 4], [2, 4], [1, 3, 4], [0]]。对象编号只标识对象身份,不是图片编号。创建格式为对象、包;销毁格式为对象。
逐项计算记录
事件 | 包0至3引用数 | 图片0至4引用数 | 装入图片 | 卸载图片 | 对象数 ['create', 0, 2] | [0, 0, 1, 0] | [0, 1, 0, 1, 1] | [1, 3, 4] | [] | 1 ['create', 1, 2] | [0, 0, 2, 0] | [0, 1, 0, 1, 1] | [] | [] | 2 ['create', 2, 2] | [0, 0, 3, 0] | [0, 1, 0, 1, 1] | [] | [] | 3 ['create', 3, 3] | [0, 0, 3, 1] | [1, 1, 0, 1, 1] | [0] | [] | 4 ['destroy', 0] | [0, 0, 2, 1] | [1, 1, 0, 1, 1] | [] | [] | 3 ['create', 4, 2] | [0, 0, 3, 1] | [1, 1, 0, 1, 1] | [] | [] | 4 ['create', 5, 3] | [0, 0, 3, 2] | [1, 1, 0, 1, 1] | [] | [] | 5 ['destroy', 2] | [0, 0, 2, 2] | [1, 1, 0, 1, 1] | [] | [] | 4 ['destroy', 4] | [0, 0, 1, 2] | [1, 1, 0, 1, 1] | [] | [] | 3 ['create', 6, 2] | [0, 0, 2, 2] | [1, 1, 0, 1, 1] | [] | [] | 4 ['create', 7, 1] | [0, 1, 2, 2] | [1, 1, 1, 1, 2] | [2] | [] | 5 ['destroy', 5] | [0, 1, 2, 1] | [1, 1, 1, 1, 2] | [] | [] | 4 ['create', 8, 1] | [0, 2, 2, 1] | [1, 1, 1, 1, 2] | [] | [] | 5 ['destroy', 6] | [0, 2, 1, 1] | [1, 1, 1, 1, 2] | [] | [] | 4 ['destroy', 1] | [0, 2, 0, 1] | [1, 0, 1, 0, 1] | [] | [1, 3] | 3 ['destroy', 3] | [0, 2, 0, 0] | [0, 0, 1, 0, 1] | [] | [0] | 2 ['destroy', 8] | [0, 1, 0, 0] | [0, 0, 1, 0, 1] | [] | [] | 1 ['destroy', 7] | [0, 0, 0, 0] | [0, 0, 0, 0, 0] | [] | [2, 4] | 0 ['create', 9, 3] | [0, 0, 0, 1] | [1, 0, 0, 0, 0] | [0] | [] | 1 ['destroy', 9] | [0, 0, 0, 0] | [0, 0, 0, 0, 0] | [] | [0] | 0
读表时先把输入与计算后的结果分开。空值表示这一步没有适用对象或没有可用结果,不应自动换成零。编号只负责识别本例中的元素,同一个数字出现在不同字段时,要先确认它代表位置、对象还是数值。
怎样复核和使用
逐事件记录对象集合、包引用数和图片引用数。包有多个对象使用时,其依赖图片不按对象数重复计数;图片引用数等于当前处于使用状态并依赖它的不同包数量。
这是没有循环依赖的两层资源模型,依赖列表也没有重复项。实际系统的异步加载、失败回滚和跨线程释放需要额外约定;引用数只解释生命周期,不能单独保证并发正确。
可以先遮住记录表,只按上述规则重算前两步,再选择一个边界条件重新试算。若结果不一致,应逐项检查输入顺序、端点是否包含以及状态在哪一步更新;不要只看最终合计相同就认为中间处理也完全正确。
