Skip to content

Commit

Permalink
MDEV-22438 add a function similar to std::make_scope_exit()
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
kevgs committed Jun 22, 2020
1 parent 4c3cbe2 commit ccc4eb8
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 4 deletions.
66 changes: 66 additions & 0 deletions include/scope.h
Original file line number Diff line number Diff line change
@@ -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 <type_traits>
#include <utility>

namespace detail
{

template <typename Callable> class scope_exit
{
public:
template <typename F>
explicit scope_exit(F &&f) : function_(std::forward<F>(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 <typename Callable>
detail::scope_exit<typename std::decay<Callable>::type>
make_scope_exit(Callable &&f)
{
return detail::scope_exit<typename std::decay<Callable>::type>(
std::forward<Callable>(f));
}
6 changes: 2 additions & 4 deletions storage/innobase/handler/ha_innodb.cc
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ this program; if not, write to the Free Software Foundation, Inc.,
#include <mysql/service_thd_alloc.h>
#include <mysql/service_thd_wait.h>
#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[];
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -11100,8 +11100,6 @@ create_table_info_t::create_table_def()
DBUG_SUICIDE(););
}

mem_heap_free(heap);

DBUG_EXECUTE_IF("ib_create_err_tablespace_exist",
err = DB_TABLESPACE_EXISTS;);

Expand Down

0 comments on commit ccc4eb8

Please sign in to comment.