Created
February 6, 2013 09:44
-
-
Save killwing/4721462 to your computer and use it in GitHub Desktop.
[ScopeGuard] encapsulates scoped control flow from @andrei
This file contains hidden or 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 SCOPEGUARD_H | |
#define SCOPEGUARD_H | |
template <typename Fun> | |
class ScopeGuard { | |
public: | |
ScopeGuard(Fun f) : f_(std::move(f)), active_(true) {} | |
~ScopeGuard() { | |
if (active_) { | |
f_(); | |
} | |
} | |
void dismiss() { active_ = false; } | |
ScopeGuard() = delete; | |
ScopeGuard(const ScopeGuard&) = delete; | |
ScopeGuard& operator=(const ScopeGuard&) = delete; | |
ScopeGuard(ScopeGuard&& rhs) : f_(std::move(rhs.f_)), active_(rhs.active_) { | |
rhs.dismiss(); | |
} | |
private: | |
Fun f_; | |
bool active_; | |
}; | |
template <typename Fun> | |
ScopeGuard<Fun> scopeGuard(Fun f) { | |
return ScopeGuard<Fun>(std::move(f)); | |
} | |
namespace detail { | |
enum class ScopeGuardOnExit {}; | |
template <typename Fun> | |
ScopeGuard<Fun> operator+(ScopeGuardOnExit, Fun&& fn) { | |
return ScopeGuard<Fun>(std::forward<Fun>(fn)); | |
} | |
} | |
#define SCOPE_EXIT \ | |
auto ANONYMOUS_VARIABLE(SCOPE_EXIT_STATE) = ::detail::ScopeGuardOnExit() + [&]() | |
#define CONCATENATE_IMPL(s1, s2) s1##s2 | |
#define CONCATENATE(s1, s2) CONCATENATE_IMPL(s1, s2) | |
#ifdef __COUNTER__ | |
#define ANONYMOUS_VARIABLE(str) CONCATENATE(str, __COUNTER__) | |
#else | |
#define ANONYMOUS_VARIABLE(str) CONCATENATE(str, __LINE__) | |
#endif | |
#endif // SCOPEGUARD_H |
This file contains hidden or 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 <iostream> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
#include "ScopeGuard.h" | |
using namespace std; | |
int main() { | |
char name[] = "/tmp/deleteme.XXXXXX"; | |
auto fd = mkstemp(name); | |
auto g1 = scopeGuard([&] { | |
close(fd); | |
unlink(name); | |
cout << "close & unlink" << endl; | |
}); | |
auto g2 = scopeGuard([] { | |
cout << "not called" << endl; | |
}); | |
auto buf = malloc(1024 * 1024); | |
SCOPE_EXIT { | |
free(buf); | |
cout << "free" << endl; | |
}; | |
// ... use fd and buf ... | |
g2.dismiss(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment