Scope Guard idiom

Tags:

Transactional Programming
More C++ Idioms/Scope Guard

예외가 발생했을 때 자동 원상 복구가 가능할까… 아래는 ScopeGuard idiom.

#include
#include

using namespace std;

class ScopeGuard {
char *mem;
bool dismissed;
public:
ScopeGuard(char *m):mem(m), dismissed(false) {
}

~ScopeGuard() {
if (!dismissed) {
cout << "Deallocating by ScopeGuard." << endl; delete[] mem; } else { cout << "Already deallocated." << endl; } } void Dismiss() { dismissed = true; } }; void foo() { char *a = new char[10]; ScopeGuard sg(a); throw "error"; } void bar() { char *a = new char[10]; ScopeGuard sg(a); delete[] a; cout << "Dismissing" << endl; sg.Dismiss(); } int main() { try { foo(); } catch (char const *s) { } bar(); return EXIT_SUCCESS; } [/code] 결론을 말씀드리면 안됩니다. 이유는 ScopeGuard를 std::vector 등에 적용되었을 때 보면, insert한걸 다시 delete하거나 delete한걸 다시 insert하도록 ScopeGuard의 소멸자를 작성하여야 하기 때문. delete한걸 자동 insert하는 소멸자를 만든다고 할 때, 아쉽게도 vector의 insert는 fail이 가능함. 만약 ScopeGuard가 소멸자에서 자동 insert중 fail한다면 갈데가 없음. 해결책은 DBMS의 rollback처럼 implicit 하게 동작을 로깅하도록 하는 것. 그리고 delete시에 실제로 element를 삭제해버리지 말고 메모리상에 저장해두었다가 rollback시엔 메모리 링크만 새로 이어줌.

Comments

2 responses to “Scope Guard idiom”

  1. gimmesilver Avatar

    말씀하신 것처럼 ScopeGuard idiom은 만능이 아닙니다. 일종의 트랜잭션 작업이기 때문에 I/O같이 side effect가 있는 작업에는 사용할 수 없죠. 하지만 예로 드신 std::vector의 insert/delete의 경우는 적절한 반론예가 아닌 듯…(마지막에 친절하게 해결책까지 주셨으면서…^^;)

  2. mkseo Avatar
    mkseo

    글 감사합니다. 네.. 말씀하신대로 side effect 없는 작업에서만 쓸 수 있는 약한 의미의(?) idiom입니다. 글 내용은 ddj 의 초간단 요약이었습니다.

    저에게는 scope guard에 대한 대안이 DBMS의 롤백을 흉내낸다는 점, 메모리 해제를 지연 (또는 영구히 안함) 함으로써 STL 컨테이너의 한계를 해결한다는 점이 인상적이었습니다.

    2PC or not 2PC도 관련해서 볼만하리라 자추해봅니다 ^^

Leave a Reply

Your email address will not be published. Required fields are marked *