aboutsummaryrefslogtreecommitdiff
path: root/app/source/Cplt/Utils/ScopeGuard.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'app/source/Cplt/Utils/ScopeGuard.hpp')
-rw-r--r--app/source/Cplt/Utils/ScopeGuard.hpp39
1 files changed, 39 insertions, 0 deletions
diff --git a/app/source/Cplt/Utils/ScopeGuard.hpp b/app/source/Cplt/Utils/ScopeGuard.hpp
new file mode 100644
index 0000000..f2b7f46
--- /dev/null
+++ b/app/source/Cplt/Utils/ScopeGuard.hpp
@@ -0,0 +1,39 @@
+#pragma once
+
+#include <Cplt/Utils/Macros.hpp>
+
+#include <utility>
+
+template <class TCleanupFunc>
+class ScopeGuard
+{
+private:
+ TCleanupFunc mFunc;
+ bool mDismissed = false;
+
+public:
+ /// Specifically left this implicit so that constructs like
+ /// \code
+ /// ScopeGuard sg = [&]() { res.Cleanup(); };
+ /// \endcode
+ /// would work. It is highly discourage and unlikely that one would want to use ScopeGuard as a function
+ /// parameter, so the normal argument that implicit conversion are harmful doesn't really apply here.
+ ScopeGuard(TCleanupFunc func)
+ : mFunc{ std::move(func) }
+ {
+ }
+
+ ~ScopeGuard()
+ {
+ if (!mDismissed) {
+ mFunc();
+ }
+ }
+
+ void Dismiss() noexcept
+ {
+ mDismissed = true;
+ }
+};
+
+#define DEFER ScopeGuard UNIQUE_NAME(scopeGuard) = [&]()