From 44b4c2db49f9d3283e04d4c34b5f4d22e66d0af4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Sat, 15 Feb 2020 21:13:29 +0100 Subject: Common: Avoid std::function overhead in ScopeGuard So far in all our uses of ScopeGuard, the type of the callable is usually just a lambda or a function pointer, so there is no need to rely on std::function's type erasure. While the cost of using std::function is probably negligible, it still causes some unnecessary overhead that can be avoided by making ScopeGuard a templated class. Thanks to class template argument deduction in C++17 most existing usages do not even need to be changed. See https://godbolt.org/z/KcoPni for a comparison between a ScopeGuard that uses std::function and one that doesn't --- Source/Core/Common/ScopeGuard.h | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'Source/Core/Common') diff --git a/Source/Core/Common/ScopeGuard.h b/Source/Core/Common/ScopeGuard.h index d95ef8e4ae..c1cad06dd7 100644 --- a/Source/Core/Common/ScopeGuard.h +++ b/Source/Core/Common/ScopeGuard.h @@ -4,17 +4,15 @@ #pragma once -#include +#include namespace Common { +template class ScopeGuard final { public: - template - ScopeGuard(Callable&& finalizer) : m_finalizer(std::forward(finalizer)) - { - } + ScopeGuard(Callable&& finalizer) : m_finalizer(std::forward(finalizer)) {} ScopeGuard(ScopeGuard&& other) : m_finalizer(std::move(other.m_finalizer)) { @@ -22,13 +20,13 @@ public: } ~ScopeGuard() { Exit(); } - void Dismiss() { m_finalizer = nullptr; } + void Dismiss() { m_finalizer.reset(); } void Exit() { if (m_finalizer) { - m_finalizer(); // must not throw - m_finalizer = nullptr; + (*m_finalizer)(); // must not throw + m_finalizer.reset(); } } @@ -37,7 +35,7 @@ public: void operator=(const ScopeGuard&) = delete; private: - std::function m_finalizer; + std::optional m_finalizer; }; } // Namespace Common -- cgit v1.2.3