diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index 768174854..2fd90bfd1 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -53,6 +53,7 @@ add_library(common
rectangle.h
progress_callback.cpp
progress_callback.h
+ scope_guard.h
state_wrapper.cpp
state_wrapper.h
string.cpp
diff --git a/src/common/common.vcxproj b/src/common/common.vcxproj
index 57f492b4c..a2c6c2653 100644
--- a/src/common/common.vcxproj
+++ b/src/common/common.vcxproj
@@ -70,6 +70,7 @@
+
diff --git a/src/common/common.vcxproj.filters b/src/common/common.vcxproj.filters
index ea31c228d..55d805ec3 100644
--- a/src/common/common.vcxproj.filters
+++ b/src/common/common.vcxproj.filters
@@ -67,6 +67,7 @@
+
diff --git a/src/common/scope_guard.h b/src/common/scope_guard.h
new file mode 100644
index 000000000..c1cad06dd
--- /dev/null
+++ b/src/common/scope_guard.h
@@ -0,0 +1,41 @@
+// Copyright 2015 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include
+
+namespace Common
+{
+template
+class ScopeGuard final
+{
+public:
+ ScopeGuard(Callable&& finalizer) : m_finalizer(std::forward(finalizer)) {}
+
+ ScopeGuard(ScopeGuard&& other) : m_finalizer(std::move(other.m_finalizer))
+ {
+ other.m_finalizer = nullptr;
+ }
+
+ ~ScopeGuard() { Exit(); }
+ void Dismiss() { m_finalizer.reset(); }
+ void Exit()
+ {
+ if (m_finalizer)
+ {
+ (*m_finalizer)(); // must not throw
+ m_finalizer.reset();
+ }
+ }
+
+ ScopeGuard(const ScopeGuard&) = delete;
+
+ void operator=(const ScopeGuard&) = delete;
+
+private:
+ std::optional m_finalizer;
+};
+
+} // Namespace Common