5

这可能看起来很奇怪,但我会尝试使其合理化。我目前将boost.object_poolshared_ptr一起广泛使用,最近我遇到了一种情况,我需要对当前程序状态进行快照,以便实现像全面重放/回滚/快进这样的功能。

所以我不想克隆一个对象池以在其他地方使用,这显然不会起作用,因为即使我被 boost.pool 的接口(我不是)允许这样做,也不会有指向块的有效指针在那个新克隆的池中,这将毫无意义。但是我在这里的用例是如果有重播/回滚需求,我想将其“粘贴”回原始池中。

我当然可以手动复制和克隆所有状态、对象和子状态、子对象和子子...然后将它们打包到快照中,并希望一切顺利,但考虑到复杂性,这很容易出错项目已经搞定了,比直接复制内存要慢很多。使用命令模式(或类似模式)来实现撤消重做也是不可能的,因为撤消重做机制不是我的意图。

我只是想知道我是否使用顽固的传统 C 方式再次从头开始执行该项目,并且一个简单的 memcpy(snapshot, all_states, size) 调用几乎可以完成所有工作。

我还有其他选择吗?是否有任何类似 boost.object_pool 的实现允许您克隆底层内存区域?考虑到这种情况,侵入式破解 boost.object_pool 是一个合理的选择吗?

4

1 回答 1

2

从来没听说过。

正如您所指出的,这里的主要问题是对象之间可能存在相互依赖关系,这需要在复制时更新指针。当然不是微不足道的。

我可以想到两种可能的解决方案:

  • 持久性
  • 序列化

持久性是永不改变现有状态。因此,当您更改状态时,您会创建一个新快照,该快照引用旧状态,但新位除外。例如,它通常用于数据库的 MVCC 实现中,并且在函数式编程世界中无处不在。如果您尝试保留太多引用,这也是获得空间泄漏的好方法。最后,它需要进行深入的重新设计。

序列化是关于持久化状态,但格式不同。您以序列化格式(无论是文本还是二进制)转储当前状态,并且可以通过读取序列化缓冲区来重新创建它。您甚至可以在序列化缓冲区上应用压缩通道以节省一些内存。

既然您已经在使用 Boost,那么很高兴知道它会Boost.Serialization自动处理对象图(嗯!),我认为已经正确处理了boost::shared_ptr. 这里可能是你最好的选择。

于 2012-11-14T09:42:38.013 回答