如何在C++中创建事务流

How do you create a transactional stream in C++?

本文关键字:创建 事务 C++      更新时间:2023-10-16

我需要在C++中创建"事务流"。我所说的"事务流"是指如果在处理过程中出现错误,就会倒带的流。例如如果流的使用者以某种方式无法处理流的数据,我希望在生成数据之前将流恢复到其状态。

也许一条懒惰的溪流就能做到这一点?这是一种常见的情况和常见的解决方案吗?还是我一定要为我的特定问题编写自己的自定义实现?

首先想到的是将范围接口(用于惰性和可组合性)与事务接口(用于回溯)相结合:

#include <iostream>
#include <stack>
#include <sstream>
struct transaction_failure {};
class transactional_istream_range {
  std::istream& stream;
  std::stack<std::streampos> states;
public:
  transactional_istream_range(std::istream& stream)
    : stream(stream) {}
  // Transaction interface.
  template<class R, class T>
  R transaction(R(*body)(T&)) {
    try {
      begin();
      R result = body(*this);
      commit();
      return result;
    } catch (const transaction_failure&) {
      rollback();
    }
    return R();
  }
  void begin() {
    states.push(stream.tellg());
  }
  void commit() {
    states.pop();
  }
  void rollback() {
    stream.seekg(states.top());
    states.pop();
  }
  // Range interface.
  bool empty() const {
    return stream.peek() == EOF && stream.eof();
  }
  char front() const {
    return stream.peek();
  }
  void pop_front() const {
    stream.ignore(1);
  }
};

然后,您可以轻松地编写在事务范围上操作的模板函数:

#include <cctype>
template<class R>
std::string parse_integer(R& input) {
  std::string result;
  while (!input.empty()) {
    if (std::isdigit(input.front())) {
      result += input.front();
      input.pop_front();
    } else {
      throw transaction_failure();
    }
  }
  return result;
}
int main() {
  std::istringstream stream("1234a");
  typedef transactional_istream_range tir;
  tir input(stream);
  std::string result = input.transaction(parse_integer<tir>);
  std::cout << "Result: " << result;
}

这只是第一个近似值;您可能不必指定事务函数的范围类型(即,仅指定parse_integer而不是parse_integer<...>)。以范围形式编写许多类型的惰性流和惰性算法是非常简单的

至于扩展它,您可以将事务处理参数化,以调用用户指定的提交或回滚函数,或者只单独实现每种类型的回滚。使用mixin将范围接口与事务接口解耦也可能是有益的。不过,如果不使用虚拟功能,我现在想不出一个好的方法。

如果你在Windows上工作,有一种叫做结构化存储的东西可以提供一种交易形式。你可能不得不把你的问题分解成不同的问题。

以下是更多信息:http://msdn.microsoft.com/en-us/library/windows/desktop/aa380369(v=vs.85).aspx

或者,您可以考虑使用类似SQLite或Firebird的东西来提供后端事务存储。