- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我的程序有一个操作,它由一系列更改全局状态的单个操作组成。每个基本操作都可能失败并使全局状态处于未定义状态。
是否有一种通用模式可以帮助我使组合操作成为“原子”操作,即如果其中一个子操作失败,则全局状态保持不变?
我使用 C++,因此如果答案包含代码,如果可以选择,请选择该语言。但我不介意其他语言的例子。
这类似于数据库的“原子性”,在提交时您可以添加所有内容或不添加任何内容。这是如何实现的?
就我而言,我的全局状态是文件系统的状态。我需要一次添加或删除多个文件,并希望确保它们全部添加或未添加任何内容。
我能想到的最好的办法是一个获取操作及其逆操作列表的类。如果任何操作失败,则执行已执行操作的相反操作。但是如果其中一个逆向操作失败怎么办?
该类的接口(interface)是什么样的?我会有一个类似于可逆操作的额外类吗?您知道我可以在哪里阅读有关此问题的更多信息吗?
最佳答案
基本的解决方案是提交或回滚。
通用的 C++ 实现是构建支持 3 种方法的对象列表:
run()
它将执行所有可能失败的步骤,而不会产生可见副作用。如果失败,它必须在不改变任何内容的情况下抛出commit()
它可能不会抛出,并且只能使 run()
期间执行的步骤可见rollback()
它可能不会抛出,并且只能撤消 run()
期间执行的步骤然后迭代该列表调用 run()
在一切事情上。如果有任何抛出,捕获它并 rollback()
成功运行的一切。如果没有抛出,commit()
他们全部。
适合您情况的大致工作流程是 - 对于每个文件创建对象:
调用 run()
在正确的目录中创建(并填充?)文件,但使用临时名称 - 最好隐藏
如果失败,请调用rollback()
成功 run()
文件创建对象。这必须删除临时文件并且可能不会失败。
然后,放弃,从头开始重试,提示用户什么的。
commit()
在每个对象上。这必须将临时文件重命名为其最终名称,并且可能不会失败这要求 commit
步骤不能失败。在这种情况下,假设重命名文件不会失败 - 在您到达 commit
之前,您必须确保这是真的(即不存在名称冲突)阶段。
请注意,这确实有中间的非原子更改 - 一般来说,避免这种情况的唯一方法是拥有全局状态的两个副本,以及一个原子交换来提交修改后的状态。一般来说,即使您正在编写驱动程序,您也不能对文件系统执行此操作。
关于design-patterns - "atomicity"一系列操作如何实现? (不一定与多线程相关),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33548463/
string zodis; sregex_token_iterator it(eil.begin(), eil.end(), std::regex("[A-Za-z]+")); sregex_toke
我是一名优秀的程序员,十分优秀!