Created
April 14, 2012 07:15
-
-
Save Mankarse/2382599 to your computer and use it in GitHub Desktop.
Fixed version of https://gist.github.com/dab4bec98a0baa2ebabe
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "scope.hpp" | |
#include <iostream> | |
class Action { | |
static unsigned _count; | |
unsigned _id; | |
public: | |
Action(bool valid): | |
_id(++_count) | |
{ | |
std::cout << "Action " << _id << "\n"; | |
if(!valid) { | |
std::cout << "Throwing exception from action " << _id << "!!!\n"; | |
throw std::exception(); | |
} | |
} | |
void Rollback() | |
{ | |
std::cout << "Rollback " << _id << "\n"; | |
} | |
void Cleanup() | |
{ | |
std::cout << "Cleanup " << _id << "\n"; | |
} | |
}; | |
unsigned Action::_count = 0; | |
void test2() | |
{ | |
Action a1(true); | |
scope s1( | |
at_exit([&]{ a1.Cleanup(); }), | |
at_failure([&]{ | |
Action a3(true); | |
scope s3( | |
at_exit([&]{ a3.Cleanup(); }), | |
at_failure([&]{ a3.Rollback(); })); | |
a1.Rollback(); })); | |
Action a2(false); | |
} | |
int main() | |
{ | |
try { | |
test2(); | |
} | |
catch(...) { | |
std::cout << "Exception caught\n"; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef SCOPE_HPP | |
#define SCOPE_HPP | |
#include <functional> | |
#include <exception> | |
namespace details { | |
struct rollback_cb_t { }; | |
struct cleanup_cb_t { }; | |
template<typename T> | |
class scope_cb { | |
std::function<void()> _cb; | |
public: | |
scope_cb() = default; | |
scope_cb(std::function<void()> &&cb): _cb(std::move(cb)) {} | |
scope_cb(const scope_cb &) = delete; | |
scope_cb(scope_cb && o) : | |
_cb() | |
{ | |
_cb.swap(o._cb); | |
} | |
scope_cb &operator=(const scope_cb &) = delete; | |
scope_cb &operator=(scope_cb && o) { | |
if (this != &o) { | |
_cb = std::function<void()>(); | |
_cb.swap(o._cb); | |
} | |
return *this; | |
} | |
~scope_cb() { if(_cb) _cb(); } | |
}; | |
} | |
typedef details::scope_cb<details::cleanup_cb_t> cleanup_t; | |
typedef details::scope_cb<details::rollback_cb_t> rollback_t; | |
class scope { | |
cleanup_t _cleanup; | |
rollback_t _rollback; | |
public: | |
scope(cleanup_t &&cleanup, rollback_t &&rollback = rollback_t()): | |
_cleanup(std::move(cleanup)), _rollback(std::move(rollback)) {} | |
scope(rollback_t &&rollback, cleanup_t &&cleanup = cleanup_t()): | |
_cleanup(std::move(cleanup)), _rollback(std::move(rollback)) {} | |
scope(const scope &) = delete; | |
scope(scope &&) = delete; | |
scope &operator=(const scope &) = delete; | |
scope &operator=(scope &&) = delete; | |
~scope() = default; | |
}; | |
inline cleanup_t at_exit(std::function<void()> &&cb) | |
{ | |
return cleanup_t(std::move(cb)); | |
} | |
inline rollback_t at_failure(std::function<void()> &&cb) | |
{ | |
return rollback_t([=]{ if(std::uncaught_exception()) cb(); }); | |
} | |
#endif SCOPE_HPP |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks, fixed ;-)