我需要在C++中創建「事務流」。我的意思是「事務性流」是一個流,如果在處理過程中某個點出現錯誤,它將倒回。例如, 如果某個流的消費者無法處理該流的數據,我希望該流在生成該數據之前恢復到其狀態。如何在C++中創建事務流?
也許一個懶惰的流可以實現這一點?這是常見解決方案的常見情況,還是我必須爲我的特定問題編寫自己的自定義實現?
我需要在C++中創建「事務流」。我的意思是「事務性流」是一個流,如果在處理過程中某個點出現錯誤,它將倒回。例如, 如果某個流的消費者無法處理該流的數據,我希望該流在生成該數據之前恢復到其狀態。如何在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將範圍界面與交易界面分離可能也是有益的。不過,我現在想不出採用虛擬功能的好方法。
優秀的例子! – 2012-12-12 20:08:14
如果您在Windows上工作,那麼可以使用結構化存儲來提供一種交易形式。您可能不得不將問題分解成單獨的流。
下面是詳細信息: http://msdn.microsoft.com/en-us/library/windows/desktop/aa380369(v=vs.85).aspx
這將取決於流的底層實現(文件系統,網絡/協議等)。如果支持事務,並且支持所需的語義,則可以直接使用它。如果你想從中抽象出來,你必須自己推出。如果做得正確,這是不平凡的。例如,不要忘記,「事務」通常不僅需要可靠的ROLLBACK,而且還需要可靠的COMMIT(使用懶/內存支持的方法很難實現)。 – 2012-07-12 14:12:41
@ Christian.K,好點。我意識到這是不平凡的。爲了以抽象的方式完成,我猜想有必要使用像事務內存這樣的東西,但是如上所述爲其他底層實現提供接口。我希望有人已經完成了這項工作(可能是Boost?)! ;) – 2012-07-12 16:13:45
聽起來像設計模式的應用程序。看看紀念品... – steffen 2012-07-12 20:03:37