C++ 팁 - transaction 처리
글쓴이: pinetr2e / 작성시간: 목, 2005/07/21 - 11:58오후
CUJ 2004 년 1월호에 재밌는 글이 있어 소개합니다.
constructor 와 destructor를 이용한 scoped lock, trace등의 기술은 많이
익숙한데, 여기에 소개하는 것은 transaction 처리를 자동으로 하도록 하는
방법입니다.
macro, for 문의 절묘한 사용, temporary object, function template 등의
특성등을 잘 조합하여 직관적인 방법이 만들어 지는 군요.
scoped_transaction.h
// // from CUJ Jan. 2004 // class ScopedTransactionBase { public: ScopedTransactionBase() : aborted_( true ) {} operator bool() const { return aborted_; } void finish() const { aborted_ = false; } mutable bool aborted_; }; template<class TransactionT> class ScopedTransaction : public ScopedTransactionBase { public: ScopedTransaction( TransactionT& tran ) : tran_( tran ) {} ~ScopedTransaction() { if ( aborted_ ) { tran_.rollback(); } else { tran_.commit(); } } private: TransactionT& tran_; }; template< class TranT > ScopedTransaction< TranT> makeScopedTransaction( TranT& tran ) { return ScopedTransaction<TranT>(tran); } #define transaction(tran) for ( const ScopedTransactionBase& tran_##__LINE__ = \ makeScopedTransaction( tran ); \ tran_##__LINE__; \ tran_##__LINE__.finish() )
다음은 예제 입니다.
Session classs는 commit() 과 rollback()을 멤버 함수로 가지고 있는 임의의 class가 될 수 있으며,
transaction(sess)
{
//
// do something
//
}
위에서 transaction block 이 정상적으로 종료되면 sess의
commit() 이 호출되고 그렇지 않으면( break, return, exception등에 의해) rollback()이 호출 됩니다.
#include <iostream> #include "scoped_transaction.h" using namespace std; // // example // class AnySession { public: void commit() { cout << "commit()" << endl; } void rollback() { cout << "rollback()" << endl; } }; int main() { AnySession sess; cout << "1. normal success" << endl; transaction( sess ) { cout << "do something" << endl; } cout << "2. fail in processing" << endl; transaction( sess ) { cout << "do domething" << endl; cout << "do domething(which failed)" << endl; break; } }
결과
1. normal success do something commit() 2. fail in processing do domething do domething(which failed) rollback()
Forums:
저를 감동시켰던 코드 중 하나인 [url=http://www.cuj.co
저를 감동시켰던 코드 중 하나인 ScopeGuard과 같은 맥락이로군요.
for 문의 사용은 재밌습니다.
ScopeGuard를 쓰면 이런 식으로 되겠네요.
얼핏 보고tran_##_LINE때문에 한참 고민했네요. ##과 _
얼핏 보고
tran_##_LINE
때문에 한참 고민했네요. ##과 __LINE__ 말고 다른 _##_LINE 이라는 게 있나 싶어서요. ㅜ.ㅜ
마침 윈도라 한참 전처리기 찾아서 한번 돌려보고야 이해했음. --;
그런데 tran__LINE으로 그냥 바뀌던데, 그래도 아무 상관없던데 왜 굳이
이상한 변수명을 썼는지 정말 궁금하네요.
전체기사를 보고싶네요. 이거원 벼르던 cuj잡지 dvd를 사야하나...
[quote="asheap"]얼핏 보고tran_##_LINE때문에
제가 실수 했군요.. __LINE__ 이 맞구요( 수정했습니다.)
transaction block 이 여러번 nesting 되었을때, 문제가 없도록 하기위한 목적입니다.
우와 그러면 여러면 nesting 되어도 괜찮게 되는 거구나.속이 다
우와 그러면 여러면 nesting 되어도 괜찮게 되는 거구나.
속이 다 시원하네요. 좋은 정보 감사합니다. ^^
댓글 달기