81 lines
1.5 KiB
C++
81 lines
1.5 KiB
C++
|
/*
|
||
|
* Based on Loki::ScopeGuard
|
||
|
*/
|
||
|
|
||
|
#pragma once
|
||
|
|
||
|
#include <utility>
|
||
|
|
||
|
namespace scope_guard_util {
|
||
|
|
||
|
template <typename FunctionType>
|
||
|
class ScopeGuard {
|
||
|
public:
|
||
|
void dismiss() noexcept
|
||
|
{
|
||
|
dismissed_ = true;
|
||
|
}
|
||
|
|
||
|
explicit ScopeGuard(const FunctionType &fn)
|
||
|
: function_(fn)
|
||
|
{}
|
||
|
|
||
|
explicit ScopeGuard(FunctionType &&fn)
|
||
|
: function_(std::move(fn))
|
||
|
{}
|
||
|
|
||
|
ScopeGuard(ScopeGuard &&other)
|
||
|
: dismissed_(other.dismissed_),
|
||
|
function_(std::move(other.function_))
|
||
|
{
|
||
|
other.dismissed_ = true;
|
||
|
}
|
||
|
|
||
|
~ScopeGuard() noexcept
|
||
|
{
|
||
|
if (!dismissed_)
|
||
|
execute();
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
void* operator new(size_t) = delete;
|
||
|
|
||
|
void execute() noexcept
|
||
|
{
|
||
|
function_();
|
||
|
}
|
||
|
|
||
|
bool dismissed_ = false;
|
||
|
FunctionType function_;
|
||
|
};
|
||
|
|
||
|
template <typename FunctionType>
|
||
|
ScopeGuard<typename std::decay<FunctionType>::type>
|
||
|
make_guard(FunctionType &&fn)
|
||
|
{
|
||
|
return ScopeGuard<typename std::decay<FunctionType>::type>{
|
||
|
std::forward<FunctionType>(fn)};
|
||
|
}
|
||
|
|
||
|
namespace detail {
|
||
|
|
||
|
enum class ScopeGuardOnExit {};
|
||
|
|
||
|
template <typename FunctionType>
|
||
|
ScopeGuard<typename std::decay<FunctionType>::type>
|
||
|
operator+(detail::ScopeGuardOnExit, FunctionType &&fn) {
|
||
|
return ScopeGuard<typename std::decay<FunctionType>::type>(
|
||
|
std::forward<FunctionType>(fn));
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
} // namespace scope_guard_util
|
||
|
|
||
|
#define SCOPE_EXIT_CONCAT2(x, y) x ## y
|
||
|
#define SCOPE_EXIT_CONCAT(x, y) SCOPE_EXIT_CONCAT2(x, y)
|
||
|
#define SCOPE_EXIT \
|
||
|
auto SCOPE_EXIT_CONCAT(SCOPE_EXIT_STATE, __LINE__) = \
|
||
|
::scope_guard_util::detail::ScopeGuardOnExit() + [&]() noexcept
|
||
|
|