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: [PATCH] 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 +++++++--------- Source/Core/Core/Core.cpp | 6 +++--- 2 files changed, 10 insertions(+), 12 deletions(-) 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 diff --git a/Source/Core/Core/Core.cpp b/Source/Core/Core/Core.cpp index ea5954e90a..dfad2b100e 100644 --- a/Source/Core/Core/Core.cpp +++ b/Source/Core/Core/Core.cpp @@ -434,7 +434,7 @@ static void EmuThread(std::unique_ptr boot, WindowSystemInfo wsi s_frame_step = false; Movie::Init(*boot); - Common::ScopeGuard movie_guard{Movie::Shutdown}; + Common::ScopeGuard movie_guard{&Movie::Shutdown}; HW::Init(); @@ -539,7 +539,7 @@ static void EmuThread(std::unique_ptr boot, WindowSystemInfo wsi }}; AudioCommon::InitSoundStream(); - Common::ScopeGuard audio_guard{AudioCommon::ShutdownSoundStream}; + Common::ScopeGuard audio_guard{&AudioCommon::ShutdownSoundStream}; // The hardware is initialized. s_hardware_initialized = true; @@ -565,7 +565,7 @@ static void EmuThread(std::unique_ptr boot, WindowSystemInfo wsi // Initialise Wii filesystem contents. // This is done here after Boot and not in HW to ensure that we operate // with the correct title context since save copying requires title directories to exist. - Common::ScopeGuard wiifs_guard{Core::CleanUpWiiFileSystemContents}; + Common::ScopeGuard wiifs_guard{&Core::CleanUpWiiFileSystemContents}; if (SConfig::GetInstance().bWii) Core::InitializeWiiFileSystemContents(); else