From ccc4eb8530727d5b9701f46ef4d79660b872a66e Mon Sep 17 00:00:00 2001 From: Eugene Kosov Date: Sun, 3 May 2020 01:05:15 +0300 Subject: [PATCH] MDEV-22438 add a function similar to std::make_scope_exit() The idea was borrowed from http://wg21.link/p0052 scope_exit class is a helper, its name is hidden from user in the namespace detail. Alternative implementation of scope_exit with std::function looks slower on goldbolt.org as it may require allocation, etc. scope_exit doesn't need to own a callable, so beeing a pointer is enough. And std::decay produces such a pointer from callable. --- include/scope.h | 66 +++++++++++++++++++++++++++ storage/innobase/handler/ha_innodb.cc | 6 +-- 2 files changed, 68 insertions(+), 4 deletions(-) create mode 100644 include/scope.h diff --git a/include/scope.h b/include/scope.h new file mode 100644 index 00000000000..b9e2e96ae5c --- /dev/null +++ b/include/scope.h @@ -0,0 +1,66 @@ +/* + Copyright (c) 2020, MariaDB + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include +#include + +namespace detail +{ + +template class scope_exit +{ +public: + template + explicit scope_exit(F &&f) : function_(std::forward(f)) + { + } + + scope_exit(scope_exit &&rhs) + : function_(std::move(rhs.function_)), engaged_(rhs.engaged_) + { + rhs.release(); + } + + scope_exit(const scope_exit &)= delete; + scope_exit &operator=(scope_exit &&)= delete; + scope_exit &operator=(const scope_exit &)= delete; + + void release() { engaged_= false; } + + ~scope_exit() + { + if (engaged_) + function_(); + } + +private: + Callable function_; + bool engaged_= true; +}; + +} // end namespace detail + +template +detail::scope_exit::type> +make_scope_exit(Callable &&f) +{ + return detail::scope_exit::type>( + std::forward(f)); +} diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 777e93997e0..06d63fbe84a 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -55,6 +55,7 @@ this program; if not, write to the Free Software Foundation, Inc., #include #include #include "field.h" +#include "scope.h" // MYSQL_PLUGIN_IMPORT extern my_bool lower_case_file_system; // MYSQL_PLUGIN_IMPORT extern char mysql_unpacked_real_data_home[]; @@ -10881,6 +10882,7 @@ create_table_info_t::create_table_def() } heap = mem_heap_create(1000); + auto _ = make_scope_exit([heap]() { mem_heap_free(heap); }); ut_d(bool have_vers_start = false); ut_d(bool have_vers_end = false); @@ -10941,7 +10943,6 @@ create_table_info_t::create_table_def() " must be below 256." " Unsupported code " ULINTPF ".", charset_no); - mem_heap_free(heap); dict_mem_table_free(table); DBUG_RETURN(ER_CANT_CREATE_TABLE); @@ -10972,7 +10973,6 @@ create_table_info_t::create_table_def() field->field_name.str); err_col: dict_mem_table_free(table); - mem_heap_free(heap); ut_ad(trx_state_eq(m_trx, TRX_STATE_NOT_STARTED)); DBUG_RETURN(HA_ERR_GENERIC); } @@ -11100,8 +11100,6 @@ err_col: DBUG_SUICIDE();); } - mem_heap_free(heap); - DBUG_EXECUTE_IF("ib_create_err_tablespace_exist", err = DB_TABLESPACE_EXISTS;);